diff options
Diffstat (limited to 'sys/dev/pci/pci.c')
-rw-r--r-- | sys/dev/pci/pci.c | 59 |
1 files changed, 52 insertions, 7 deletions
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index fc18f70..db2a6cc 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -121,6 +121,8 @@ static void pci_resume_msix(device_t dev); static int pci_remap_intr_method(device_t bus, device_t dev, u_int irq); +static uint16_t pci_get_rid_method(device_t dev, device_t child); + static device_method_t pci_methods[] = { /* Device interface */ DEVMETHOD(device_probe, pci_probe), @@ -175,6 +177,7 @@ static device_method_t pci_methods[] = { DEVMETHOD(pci_release_msi, pci_release_msi_method), DEVMETHOD(pci_msi_count, pci_msi_count_method), DEVMETHOD(pci_msix_count, pci_msix_count_method), + DEVMETHOD(pci_get_rid, pci_get_rid_method), DEVMETHOD_END }; @@ -358,6 +361,11 @@ TUNABLE_INT("hw.pci.clear_bars", &pci_clear_bars); SYSCTL_INT(_hw_pci, OID_AUTO, clear_bars, CTLFLAG_RDTUN, &pci_clear_bars, 0, "Ignore firmware-assigned resources for BARs."); +static int pci_enable_ari = 1; +TUNABLE_INT("hw.pci.enable_ari", &pci_enable_ari); +SYSCTL_INT(_hw_pci, OID_AUTO, enable_ari, CTLFLAG_RDTUN, &pci_enable_ari, + 0, "Enable support for PCIe Alternative RID Interpretation"); + static int pci_has_quirk(uint32_t devid, int quirk) { @@ -3292,6 +3300,19 @@ pci_add_resources(device_t bus, device_t dev, int force, uint32_t prefetchmask) } } +static struct pci_devinfo * +pci_identify_function(device_t pcib, device_t dev, int domain, int busno, + int slot, int func, size_t dinfo_size) +{ + struct pci_devinfo *dinfo; + + dinfo = pci_read_device(pcib, domain, busno, slot, func, dinfo_size); + if (dinfo != NULL) + pci_add_child(dev, dinfo); + + return (dinfo); +} + void pci_add_children(device_t dev, int domain, int busno, size_t dinfo_size) { @@ -3301,6 +3322,24 @@ pci_add_children(device_t dev, int domain, int busno, size_t dinfo_size) int maxslots; int s, f, pcifunchigh; uint8_t hdrtype; + int first_func; + + /* + * Try to detect a device at slot 0, function 0. If it exists, try to + * enable ARI. We must enable ARI before detecting the rest of the + * functions on this bus as ARI changes the set of slots and functions + * that are legal on this bus. + */ + dinfo = pci_identify_function(pcib, dev, domain, busno, 0, 0, + dinfo_size); + if (dinfo != NULL && pci_enable_ari) + PCIB_TRY_ENABLE_ARI(pcib, dinfo->cfg.dev); + + /* + * Start looking for new devices on slot 0 at function 1 because we + * just identified the device at slot 0, function 0. + */ + first_func = 1; KASSERT(dinfo_size >= sizeof(struct pci_devinfo), ("dinfo_size too small")); @@ -3313,14 +3352,13 @@ pci_add_children(device_t dev, int domain, int busno, size_t dinfo_size) if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE) continue; if (hdrtype & PCIM_MFDEV) - pcifunchigh = PCI_FUNCMAX; - for (f = 0; f <= pcifunchigh; f++) { - dinfo = pci_read_device(pcib, domain, busno, s, f, + pcifunchigh = PCIB_MAXFUNCS(pcib); + for (f = first_func; f <= pcifunchigh; f++) + pci_identify_function(pcib, dev, domain, busno, s, f, dinfo_size); - if (dinfo != NULL) { - pci_add_child(dev, dinfo); - } - } + + /* For slots after slot 0 we need to check for function 0. */ + first_func = 0; } #undef REG } @@ -4877,3 +4915,10 @@ pci_restore_state(device_t dev) dinfo = device_get_ivars(dev); pci_cfg_restore(dev, dinfo); } + +static uint16_t +pci_get_rid_method(device_t dev, device_t child) +{ + + return (PCIB_GET_RID(device_get_parent(dev), child)); +} |