diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/pci/endpoint/functions/pci-epf-test.c | 1 | ||||
-rw-r--r-- | drivers/pci/pci.c | 6 | ||||
-rw-r--r-- | drivers/pci/pci.h | 2 | ||||
-rw-r--r-- | drivers/pci/pcie/aspm.c | 20 | ||||
-rw-r--r-- | drivers/pci/probe.c | 87 |
5 files changed, 41 insertions, 75 deletions
diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c index 5b833f00e980..a5ed779b0a51 100644 --- a/drivers/pci/endpoint/functions/pci-epf-test.c +++ b/drivers/pci/endpoint/functions/pci-epf-test.c @@ -627,7 +627,6 @@ static void pci_epf_test_unbind(struct pci_epf *epf) cancel_delayed_work(&epf_test->cmd_handler); pci_epf_test_clean_dma_chan(epf_test); - pci_epc_stop(epc); for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) { epf_bar = &epf->bar[bar]; diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index cfaf40a540a8..093303c27ea8 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1293,9 +1293,6 @@ static int pci_set_full_power_state(struct pci_dev *dev) pci_restore_bars(dev); } - if (dev->bus->self) - pcie_aspm_pm_state_change(dev->bus->self); - return 0; } @@ -1390,9 +1387,6 @@ static int pci_set_low_power_state(struct pci_dev *dev, pci_power_t state) pci_power_name(dev->current_state), pci_power_name(state)); - if (dev->bus->self) - pcie_aspm_pm_state_change(dev->bus->self); - return 0; } diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index e10cdec6c56e..785f31086313 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -560,12 +560,10 @@ bool pcie_wait_for_link(struct pci_dev *pdev, bool active); #ifdef CONFIG_PCIEASPM void pcie_aspm_init_link_state(struct pci_dev *pdev); void pcie_aspm_exit_link_state(struct pci_dev *pdev); -void pcie_aspm_pm_state_change(struct pci_dev *pdev); void pcie_aspm_powersave_config_link(struct pci_dev *pdev); #else static inline void pcie_aspm_init_link_state(struct pci_dev *pdev) { } static inline void pcie_aspm_exit_link_state(struct pci_dev *pdev) { } -static inline void pcie_aspm_pm_state_change(struct pci_dev *pdev) { } static inline void pcie_aspm_powersave_config_link(struct pci_dev *pdev) { } #endif diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index a96b7424c9bc..a8aec190986c 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -1012,25 +1012,6 @@ out: up_read(&pci_bus_sem); } -/* @pdev: the root port or switch downstream port */ -void pcie_aspm_pm_state_change(struct pci_dev *pdev) -{ - struct pcie_link_state *link = pdev->link_state; - - if (aspm_disabled || !link) - return; - /* - * Devices changed PM state, we should recheck if latency - * meets all functions' requirement - */ - down_read(&pci_bus_sem); - mutex_lock(&aspm_lock); - pcie_update_aspm_capable(link->root); - pcie_config_aspm_path(link); - mutex_unlock(&aspm_lock); - up_read(&pci_bus_sem); -} - void pcie_aspm_powersave_config_link(struct pci_dev *pdev) { struct pcie_link_state *link = pdev->link_state; @@ -1366,4 +1347,3 @@ bool pcie_aspm_support_enabled(void) { return aspm_support_enabled; } -EXPORT_SYMBOL(pcie_aspm_support_enabled); diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 414f659dc873..9884d8b29d3b 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -2582,33 +2582,39 @@ struct pci_dev *pci_scan_single_device(struct pci_bus *bus, int devfn) } EXPORT_SYMBOL(pci_scan_single_device); -static unsigned int next_fn(struct pci_bus *bus, struct pci_dev *dev, - unsigned int fn) +static int next_ari_fn(struct pci_bus *bus, struct pci_dev *dev, int fn) { int pos; u16 cap = 0; unsigned int next_fn; - if (pci_ari_enabled(bus)) { - if (!dev) - return 0; - pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI); - if (!pos) - return 0; + if (!dev) + return -ENODEV; - pci_read_config_word(dev, pos + PCI_ARI_CAP, &cap); - next_fn = PCI_ARI_CAP_NFN(cap); - if (next_fn <= fn) - return 0; /* protect against malformed list */ + pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI); + if (!pos) + return -ENODEV; - return next_fn; - } + pci_read_config_word(dev, pos + PCI_ARI_CAP, &cap); + next_fn = PCI_ARI_CAP_NFN(cap); + if (next_fn <= fn) + return -ENODEV; /* protect against malformed list */ - /* dev may be NULL for non-contiguous multifunction devices */ - if (!dev || dev->multifunction) - return (fn + 1) % 8; + return next_fn; +} - return 0; +static int next_fn(struct pci_bus *bus, struct pci_dev *dev, int fn) +{ + if (pci_ari_enabled(bus)) + return next_ari_fn(bus, dev, fn); + + if (fn >= 7) + return -ENODEV; + /* only multifunction devices may have more functions */ + if (dev && !dev->multifunction) + return -ENODEV; + + return fn + 1; } static int only_one_child(struct pci_bus *bus) @@ -2646,26 +2652,30 @@ static int only_one_child(struct pci_bus *bus) */ int pci_scan_slot(struct pci_bus *bus, int devfn) { - unsigned int fn, nr = 0; struct pci_dev *dev; + int fn = 0, nr = 0; if (only_one_child(bus) && (devfn > 0)) return 0; /* Already scanned the entire slot */ - dev = pci_scan_single_device(bus, devfn); - if (!dev) - return 0; - if (!pci_dev_is_added(dev)) - nr++; - - for (fn = next_fn(bus, dev, 0); fn > 0; fn = next_fn(bus, dev, fn)) { + do { dev = pci_scan_single_device(bus, devfn + fn); if (dev) { if (!pci_dev_is_added(dev)) nr++; - dev->multifunction = 1; + if (fn > 0) + dev->multifunction = 1; + } else if (fn == 0) { + /* + * Function 0 is required unless we are running on + * a hypervisor that passes through individual PCI + * functions. + */ + if (!hypervisor_isolated_pci_functions()) + break; } - } + fn = next_fn(bus, dev, fn); + } while (fn >= 0); /* Only one slot has PCIe device */ if (bus->self && nr) @@ -2861,29 +2871,14 @@ static unsigned int pci_scan_child_bus_extend(struct pci_bus *bus, { unsigned int used_buses, normal_bridges = 0, hotplug_bridges = 0; unsigned int start = bus->busn_res.start; - unsigned int devfn, fn, cmax, max = start; + unsigned int devfn, cmax, max = start; struct pci_dev *dev; - int nr_devs; dev_dbg(&bus->dev, "scanning bus\n"); /* Go find them, Rover! */ - for (devfn = 0; devfn < 256; devfn += 8) { - nr_devs = pci_scan_slot(bus, devfn); - - /* - * The Jailhouse hypervisor may pass individual functions of a - * multi-function device to a guest without passing function 0. - * Look for them as well. - */ - if (jailhouse_paravirt() && nr_devs == 0) { - for (fn = 1; fn < 8; fn++) { - dev = pci_scan_single_device(bus, devfn + fn); - if (dev) - dev->multifunction = 1; - } - } - } + for (devfn = 0; devfn < 256; devfn += 8) + pci_scan_slot(bus, devfn); /* Reserve buses for SR-IOV capability */ used_buses = pci_iov_bus_range(bus); |