diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-08-21 09:39:55 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-09-21 10:29:40 +0200 |
commit | 2df56dbd60bb5d925d2ce0ddbdefdbe6107ea783 (patch) | |
tree | bd7bad558534db4a1f400bc38a2c9aa7ea4f411e /freebsd/sys/dev/pci | |
parent | Update to FreeBSD head 2018-02-01 (diff) | |
download | rtems-libbsd-2df56dbd60bb5d925d2ce0ddbdefdbe6107ea783.tar.bz2 |
Update to FreeBSD head 2018-04-01
Git mirror commit 8dfb1ccc26d1cea7e2529303003ff61f9f1784c4.
Update #3472.
Diffstat (limited to 'freebsd/sys/dev/pci')
-rw-r--r-- | freebsd/sys/dev/pci/pci.c | 119 | ||||
-rw-r--r-- | freebsd/sys/dev/pci/pci_private.h | 6 | ||||
-rw-r--r-- | freebsd/sys/dev/pci/pci_user.c | 7 | ||||
-rw-r--r-- | freebsd/sys/dev/pci/pcivar.h | 21 |
4 files changed, 144 insertions, 9 deletions
diff --git a/freebsd/sys/dev/pci/pci.c b/freebsd/sys/dev/pci/pci.c index 7fbdc693..55a21320 100644 --- a/freebsd/sys/dev/pci/pci.c +++ b/freebsd/sys/dev/pci/pci.c @@ -185,8 +185,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), @@ -1381,7 +1384,7 @@ pci_find_htcap_method(device_t dev, device_t child, int capability, int *capreg) * 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) @@ -1395,13 +1398,51 @@ pci_find_htcap_method(device_t dev, device_t child, int capability, int *capreg) } /* 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); } @@ -1416,8 +1457,8 @@ pci_find_cap_method(device_t dev, device_t child, int capability, { 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. @@ -1459,6 +1500,33 @@ pci_find_cap_method(device_t dev, device_t child, int capability, } /* + * 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. @@ -1496,6 +1564,41 @@ pci_find_extcap_method(device_t dev, device_t child, int capability, } /* + * 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); +} + +/* * Support for MSI-X message interrupts. */ static void diff --git a/freebsd/sys/dev/pci/pci_private.h b/freebsd/sys/dev/pci/pci_private.h index dd254e66..f468152b 100644 --- a/freebsd/sys/dev/pci/pci_private.h +++ b/freebsd/sys/dev/pci/pci_private.h @@ -90,10 +90,16 @@ int pci_enable_io_method(device_t dev, device_t child, int space); 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, diff --git a/freebsd/sys/dev/pci/pci_user.c b/freebsd/sys/dev/pci/pci_user.c index 6e1cc3ef..e6297bd7 100644 --- a/freebsd/sys/dev/pci/pci_user.c +++ b/freebsd/sys/dev/pci/pci_user.c @@ -764,12 +764,16 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t * tell the user that there are more matches * left. */ - if (cio->num_matches >= ionum) + if (cio->num_matches >= ionum) { + error = 0; break; + } #ifdef PRE7_COMPAT #ifdef COMPAT_FREEBSD32 if (cmd == PCIOCGETCONF_OLD32) { + memset(&conf_old32, 0, + sizeof(conf_old32)); conf_old32.pc_sel.pc_bus = dinfo->conf.pc_sel.pc_bus; conf_old32.pc_sel.pc_dev = @@ -803,6 +807,7 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t } else #endif /* COMPAT_FREEBSD32 */ if (cmd == PCIOCGETCONF_OLD) { + memset(&conf_old, 0, sizeof(conf_old)); conf_old.pc_sel.pc_bus = dinfo->conf.pc_sel.pc_bus; conf_old.pc_sel.pc_dev = diff --git a/freebsd/sys/dev/pci/pcivar.h b/freebsd/sys/dev/pci/pcivar.h index 430e29db..492b7117 100644 --- a/freebsd/sys/dev/pci/pcivar.h +++ b/freebsd/sys/dev/pci/pcivar.h @@ -468,18 +468,39 @@ 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 pci_alloc_msi(device_t dev, int *count) { return (PCI_ALLOC_MSI(device_get_parent(dev), dev, count)); |