Date: Sat, 17 Mar 2018 20:20:30 +0000 (UTC) From: Bryan Venteicher <bryanv@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r331111 - in stable/11: share/man/man9 sys/dev/pci Message-ID: <201803172020.w2HKKU8Q050401@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: bryanv Date: Sat Mar 17 20:20:29 2018 New Revision: 331111 URL: https://svnweb.freebsd.org/changeset/base/331111 Log: MFC r329598: Add PCI methods to iterate over the PCI capabilities VirtIO V1 provides configuration in multiple VENDOR capabilities so this allows all of the configuration to be discovered. Reviewed by: jhb Differential Revision: https://reviews.freebsd.org/D14325 Modified: stable/11/share/man/man9/pci.9 stable/11/sys/dev/pci/hostb_pci.c stable/11/sys/dev/pci/pci.c stable/11/sys/dev/pci/pci_if.m stable/11/sys/dev/pci/pci_private.h stable/11/sys/dev/pci/pcivar.h stable/11/sys/dev/pci/vga_pci.c Directory Properties: stable/11/ (props changed) Modified: stable/11/share/man/man9/pci.9 ============================================================================== --- stable/11/share/man/man9/pci.9 Sat Mar 17 20:17:35 2018 (r331110) +++ stable/11/share/man/man9/pci.9 Sat Mar 17 20:20:29 2018 (r331111) @@ -42,6 +42,9 @@ .Nm pci_find_device , .Nm pci_find_extcap , .Nm pci_find_htcap , +.Nm pci_find_next_cap , +.Nm pci_find_next_extcap , +.Nm pci_find_next_htcap , .Nm pci_find_pcie_root_port , .Nm pci_get_id , .Nm pci_get_max_payload , @@ -100,6 +103,12 @@ .Fn pci_find_extcap "device_t dev" "int capability" "int *capreg" .Ft int .Fn pci_find_htcap "device_t dev" "int capability" "int *capreg" +.Ft int +.Fn pci_find_next_cap "device_t dev" "int capability" "int start" "int *capreg" +.Ft int +.Fn pci_find_next_extcap "device_t dev" "int capability" "int start" "int *capreg" +.Ft int +.Fn pci_find_next_htcap "device_t dev" "int capability" "int start" "int *capreg" .Ft device_t .Fn pci_find_pcie_root_port "device_t dev" .Ft int @@ -330,6 +339,22 @@ returns zero. If the capability is not found or the device does not support capabilities, .Fn pci_find_cap returns an error. +The +.Fn pci_find_next_cap +function is used to locate the next instance of a PCI capability +register set for the device +.Fa dev . +The +.Fa start +should be the +.Fa *capreg +returned by a prior +.Fn pci_find_cap +or +.Fn pci_find_next_cap . +When no more instances are located +.Fn pci_find_next_cap +returns an error. .Pp The .Fn pci_find_extcap @@ -352,6 +377,22 @@ If the extended capability is not found or the device PCI-express device, .Fn pci_find_extcap returns an error. +The +.Fn pci_find_next_extcap +function is used to locate the next instance of a PCI-express +extended capability register set for the device +.Fa dev . +The +.Fa start +should be the +.Fa *capreg +returned by a prior +.Fn pci_find_extcap +or +.Fn pci_find_next_extcap . +When no more instances are located +.Fn pci_find_next_extcap +returns an error. .Pp The .Fn pci_find_htcap @@ -372,6 +413,22 @@ and returns zero. If the capability is not found or the device is not a HyperTransport device, .Fn pci_find_htcap +returns an error. +The +.Fn pci_find_next_htcap +function is used to locate the next instance of a HyperTransport capability +register set for the device +.Fa dev . +The +.Fa start +should be the +.Fa *capreg +returned by a prior +.Fn pci_find_htcap +or +.Fn pci_find_next_htcap . +When no more instances are located +.Fn pci_find_next_htcap returns an error. .Pp The Modified: stable/11/sys/dev/pci/hostb_pci.c ============================================================================== --- stable/11/sys/dev/pci/hostb_pci.c Sat Mar 17 20:17:35 2018 (r331110) +++ stable/11/sys/dev/pci/hostb_pci.c Sat Mar 17 20:20:29 2018 (r331111) @@ -207,6 +207,14 @@ pci_hostb_find_cap(device_t dev, device_t child, int c } static int +pci_hostb_find_next_cap(device_t dev, device_t child, int capability, + int start, int *capreg) +{ + + return (pci_find_next_cap(dev, capability, start, capreg)); +} + +static int pci_hostb_find_extcap(device_t dev, device_t child, int capability, int *capreg) { @@ -215,6 +223,14 @@ pci_hostb_find_extcap(device_t dev, device_t child, in } static int +pci_hostb_find_next_extcap(device_t dev, device_t child, int capability, + int start, int *capreg) +{ + + return (pci_find_next_extcap(dev, capability, start, capreg)); +} + +static int pci_hostb_find_htcap(device_t dev, device_t child, int capability, int *capreg) { @@ -222,6 +238,14 @@ pci_hostb_find_htcap(device_t dev, device_t child, int return (pci_find_htcap(dev, capability, capreg)); } +static int +pci_hostb_find_next_htcap(device_t dev, device_t child, int capability, + int start, int *capreg) +{ + + return (pci_find_next_htcap(dev, capability, start, capreg)); +} + static device_method_t pci_hostb_methods[] = { /* Device interface */ DEVMETHOD(device_probe, pci_hostb_probe), @@ -252,8 +276,11 @@ static device_method_t pci_hostb_methods[] = { DEVMETHOD(pci_set_powerstate, pci_hostb_set_powerstate), DEVMETHOD(pci_assign_interrupt, pci_hostb_assign_interrupt), DEVMETHOD(pci_find_cap, pci_hostb_find_cap), + DEVMETHOD(pci_find_next_cap, pci_hostb_find_next_cap), DEVMETHOD(pci_find_extcap, pci_hostb_find_extcap), + DEVMETHOD(pci_find_next_extcap, pci_hostb_find_next_extcap), DEVMETHOD(pci_find_htcap, pci_hostb_find_htcap), + DEVMETHOD(pci_find_next_htcap, pci_hostb_find_next_htcap), { 0, 0 } }; Modified: stable/11/sys/dev/pci/pci.c ============================================================================== --- stable/11/sys/dev/pci/pci.c Sat Mar 17 20:17:35 2018 (r331110) +++ stable/11/sys/dev/pci/pci.c Sat Mar 17 20:20:29 2018 (r331111) @@ -180,8 +180,11 @@ static device_method_t pci_methods[] = { DEVMETHOD(pci_set_powerstate, pci_set_powerstate_method), DEVMETHOD(pci_assign_interrupt, pci_assign_interrupt_method), DEVMETHOD(pci_find_cap, pci_find_cap_method), + DEVMETHOD(pci_find_next_cap, pci_find_next_cap_method), DEVMETHOD(pci_find_extcap, pci_find_extcap_method), + DEVMETHOD(pci_find_next_extcap, pci_find_next_extcap_method), DEVMETHOD(pci_find_htcap, pci_find_htcap_method), + DEVMETHOD(pci_find_next_htcap, pci_find_next_htcap_method), DEVMETHOD(pci_alloc_msi, pci_alloc_msi_method), DEVMETHOD(pci_alloc_msix, pci_alloc_msix_method), DEVMETHOD(pci_enable_msi, pci_enable_msi_method), @@ -1374,7 +1377,7 @@ pci_find_htcap_method(device_t dev, device_t child, in * Traverse the capabilities list checking each HT capability * to see if it matches the requested HT capability. */ - while (ptr != 0) { + for (;;) { val = pci_read_config(child, ptr + PCIR_HT_COMMAND, 2); if (capability == PCIM_HTCAP_SLAVE || capability == PCIM_HTCAP_HOST) @@ -1388,13 +1391,51 @@ pci_find_htcap_method(device_t dev, device_t child, in } /* Skip to the next HT capability. */ - while (ptr != 0) { - ptr = pci_read_config(child, ptr + PCICAP_NEXTPTR, 1); - if (pci_read_config(child, ptr + PCICAP_ID, 1) == - PCIY_HT) - break; + if (pci_find_next_cap(child, PCIY_HT, ptr, &ptr) != 0) + break; + } + + return (ENOENT); +} + +/* + * Find the next requested HyperTransport capability after start and return + * the offset in configuration space via the pointer provided. The function + * returns 0 on success and an error code otherwise. + */ +int +pci_find_next_htcap_method(device_t dev, device_t child, int capability, + int start, int *capreg) +{ + int ptr; + uint16_t val; + + KASSERT(pci_read_config(child, start + PCICAP_ID, 1) == PCIY_HT, + ("start capability is not HyperTransport capability")); + ptr = start; + + /* + * Traverse the capabilities list checking each HT capability + * to see if it matches the requested HT capability. + */ + for (;;) { + /* Skip to the next HT capability. */ + if (pci_find_next_cap(child, PCIY_HT, ptr, &ptr) != 0) + break; + + val = pci_read_config(child, ptr + PCIR_HT_COMMAND, 2); + if (capability == PCIM_HTCAP_SLAVE || + capability == PCIM_HTCAP_HOST) + val &= 0xe000; + else + val &= PCIM_HTCMD_CAP_MASK; + if (val == capability) { + if (capreg != NULL) + *capreg = ptr; + return (0); } } + return (ENOENT); } @@ -1409,8 +1450,8 @@ pci_find_cap_method(device_t dev, device_t child, int { struct pci_devinfo *dinfo = device_get_ivars(child); pcicfgregs *cfg = &dinfo->cfg; - u_int32_t status; - u_int8_t ptr; + uint32_t status; + uint8_t ptr; /* * Check the CAP_LIST bit of the PCI status register first. @@ -1452,6 +1493,33 @@ pci_find_cap_method(device_t dev, device_t child, int } /* + * Find the next requested capability after start and return the offset in + * configuration space via the pointer provided. The function returns + * 0 on success and an error code otherwise. + */ +int +pci_find_next_cap_method(device_t dev, device_t child, int capability, + int start, int *capreg) +{ + uint8_t ptr; + + KASSERT(pci_read_config(child, start + PCICAP_ID, 1) == capability, + ("start capability is not expected capability")); + + ptr = pci_read_config(child, start + PCICAP_NEXTPTR, 1); + while (ptr != 0) { + if (pci_read_config(child, ptr + PCICAP_ID, 1) == capability) { + if (capreg != NULL) + *capreg = ptr; + return (0); + } + ptr = pci_read_config(child, ptr + PCICAP_NEXTPTR, 1); + } + + return (ENOENT); +} + +/* * Find the requested extended capability and return the offset in * configuration space via the pointer provided. The function returns * 0 on success and an error code otherwise. @@ -1483,6 +1551,41 @@ pci_find_extcap_method(device_t dev, device_t child, i if (ptr == 0) break; ecap = pci_read_config(child, ptr, 4); + } + + return (ENOENT); +} + +/* + * Find the next requested extended capability after start and return the + * offset in configuration space via the pointer provided. The function + * returns 0 on success and an error code otherwise. + */ +int +pci_find_next_extcap_method(device_t dev, device_t child, int capability, + int start, int *capreg) +{ + struct pci_devinfo *dinfo = device_get_ivars(child); + pcicfgregs *cfg = &dinfo->cfg; + uint32_t ecap; + uint16_t ptr; + + /* Only supported for PCI-express devices. */ + if (cfg->pcie.pcie_location == 0) + return (ENXIO); + + ecap = pci_read_config(child, start, 4); + KASSERT(PCI_EXTCAP_ID(ecap) == capability, + ("start extended capability is not expected capability")); + ptr = PCI_EXTCAP_NEXTPTR(ecap); + while (ptr != 0) { + ecap = pci_read_config(child, ptr, 4); + if (PCI_EXTCAP_ID(ecap) == capability) { + if (capreg != NULL) + *capreg = ptr; + return (0); + } + ptr = PCI_EXTCAP_NEXTPTR(ecap); } return (ENOENT); Modified: stable/11/sys/dev/pci/pci_if.m ============================================================================== --- stable/11/sys/dev/pci/pci_if.m Sat Mar 17 20:17:35 2018 (r331110) +++ stable/11/sys/dev/pci/pci_if.m Sat Mar 17 20:20:29 2018 (r331111) @@ -144,6 +144,14 @@ METHOD int find_cap { int *capreg; }; +METHOD int find_next_cap { + device_t dev; + device_t child; + int capability; + int start; + int *capreg; +}; + METHOD int find_extcap { device_t dev; device_t child; @@ -151,10 +159,26 @@ METHOD int find_extcap { int *capreg; }; +METHOD int find_next_extcap { + device_t dev; + device_t child; + int capability; + int start; + int *capreg; +}; + METHOD int find_htcap { device_t dev; device_t child; int capability; + int *capreg; +}; + +METHOD int find_next_htcap { + device_t dev; + device_t child; + int capability; + int start; int *capreg; }; Modified: stable/11/sys/dev/pci/pci_private.h ============================================================================== --- stable/11/sys/dev/pci/pci_private.h Sat Mar 17 20:17:35 2018 (r331110) +++ stable/11/sys/dev/pci/pci_private.h Sat Mar 17 20:20:29 2018 (r331111) @@ -90,10 +90,16 @@ int pci_enable_io_method(device_t dev, device_t child int pci_disable_io_method(device_t dev, device_t child, int space); int pci_find_cap_method(device_t dev, device_t child, int capability, int *capreg); +int pci_find_next_cap_method(device_t dev, device_t child, + int capability, int start, int *capreg); int pci_find_extcap_method(device_t dev, device_t child, int capability, int *capreg); +int pci_find_next_extcap_method(device_t dev, device_t child, + int capability, int start, int *capreg); int pci_find_htcap_method(device_t dev, device_t child, int capability, int *capreg); +int pci_find_next_htcap_method(device_t dev, device_t child, + int capability, int start, int *capreg); int pci_alloc_msi_method(device_t dev, device_t child, int *count); int pci_alloc_msix_method(device_t dev, device_t child, int *count); void pci_enable_msi_method(device_t dev, device_t child, Modified: stable/11/sys/dev/pci/pcivar.h ============================================================================== --- stable/11/sys/dev/pci/pcivar.h Sat Mar 17 20:17:35 2018 (r331110) +++ stable/11/sys/dev/pci/pcivar.h Sat Mar 17 20:20:29 2018 (r331111) @@ -468,15 +468,36 @@ pci_find_cap(device_t dev, int capability, int *capreg } static __inline int +pci_find_next_cap(device_t dev, int capability, int start, int *capreg) +{ + return (PCI_FIND_NEXT_CAP(device_get_parent(dev), dev, capability, start, + capreg)); +} + +static __inline int pci_find_extcap(device_t dev, int capability, int *capreg) { return (PCI_FIND_EXTCAP(device_get_parent(dev), dev, capability, capreg)); } static __inline int +pci_find_next_extcap(device_t dev, int capability, int start, int *capreg) +{ + return (PCI_FIND_NEXT_EXTCAP(device_get_parent(dev), dev, capability, + start, capreg)); +} + +static __inline int pci_find_htcap(device_t dev, int capability, int *capreg) { return (PCI_FIND_HTCAP(device_get_parent(dev), dev, capability, capreg)); +} + +static __inline int +pci_find_next_htcap(device_t dev, int capability, int start, int *capreg) +{ + return (PCI_FIND_NEXT_HTCAP(device_get_parent(dev), dev, capability, + start, capreg)); } static __inline int Modified: stable/11/sys/dev/pci/vga_pci.c ============================================================================== --- stable/11/sys/dev/pci/vga_pci.c Sat Mar 17 20:17:35 2018 (r331110) +++ stable/11/sys/dev/pci/vga_pci.c Sat Mar 17 20:20:29 2018 (r331111) @@ -497,6 +497,14 @@ vga_pci_find_cap(device_t dev, device_t child, int cap } static int +vga_pci_find_next_cap(device_t dev, device_t child, int capability, + int start, int *capreg) +{ + + return (pci_find_next_cap(dev, capability, start, capreg)); +} + +static int vga_pci_find_extcap(device_t dev, device_t child, int capability, int *capreg) { @@ -505,6 +513,14 @@ vga_pci_find_extcap(device_t dev, device_t child, int } static int +vga_pci_find_next_extcap(device_t dev, device_t child, int capability, + int start, int *capreg) +{ + + return (pci_find_next_extcap(dev, capability, start, capreg)); +} + +static int vga_pci_find_htcap(device_t dev, device_t child, int capability, int *capreg) { @@ -513,6 +529,14 @@ vga_pci_find_htcap(device_t dev, device_t child, int c } static int +vga_pci_find_next_htcap(device_t dev, device_t child, int capability, + int start, int *capreg) +{ + + return (pci_find_next_htcap(dev, capability, start, capreg)); +} + +static int vga_pci_alloc_msi(device_t dev, device_t child, int *count) { struct vga_pci_softc *sc; @@ -622,8 +646,11 @@ static device_method_t vga_pci_methods[] = { DEVMETHOD(pci_set_powerstate, vga_pci_set_powerstate), DEVMETHOD(pci_assign_interrupt, vga_pci_assign_interrupt), DEVMETHOD(pci_find_cap, vga_pci_find_cap), + DEVMETHOD(pci_find_next_cap, vga_pci_find_next_cap), DEVMETHOD(pci_find_extcap, vga_pci_find_extcap), + DEVMETHOD(pci_find_next_extcap, vga_pci_find_next_extcap), DEVMETHOD(pci_find_htcap, vga_pci_find_htcap), + DEVMETHOD(pci_find_next_htcap, vga_pci_find_next_htcap), DEVMETHOD(pci_alloc_msi, vga_pci_alloc_msi), DEVMETHOD(pci_alloc_msix, vga_pci_alloc_msix), DEVMETHOD(pci_remap_msix, vga_pci_remap_msix),
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201803172020.w2HKKU8Q050401>