summaryrefslogtreecommitdiffstats
path: root/sys/dev/pci/pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/pci/pci.c')
-rw-r--r--sys/dev/pci/pci.c49
1 files changed, 42 insertions, 7 deletions
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index ac29705..172ce81 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -354,6 +354,11 @@ SYSCTL_INT(_hw_pci, OID_AUTO, clear_buses, CTLFLAG_RDTUN, &pci_clear_buses, 0,
"Ignore firmware-assigned bus numbers.");
#endif
+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)
{
@@ -3454,6 +3459,19 @@ pci_add_resources(device_t bus, device_t dev, int force, uint32_t prefetchmask)
#endif
}
+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)
{
@@ -3463,6 +3481,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"));
@@ -3475,14 +3511,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
}
OpenPOWER on IntegriCloud