2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-12-25 21:54:06 +08:00

Merge branch 'for-linus'

* for-linus:
  PCI: Fix is_added/is_busmaster race condition
  PCI: mobiveil: Avoid integer overflow in IB_WIN_SIZE
  PCI/AER: Work around use-after-free in pcie_do_fatal_recovery()
  PCI: v3-semi: Fix I/O space page leak
  PCI: mediatek: Fix I/O space page leak
  PCI: faraday: Fix I/O space page leak
  PCI: aardvark: Fix I/O space page leak
  PCI: designware: Fix I/O space page leak
  PCI: versatile: Fix I/O space page leak
  PCI: xgene: Fix I/O space page leak
  PCI: OF: Fix I/O space page leak
  PCI: endpoint: Fix NULL pointer dereference error when CONFIGFS is disabled
  PCI: hv: Disable/enable IRQs rather than BH in hv_compose_msi_msg()
  nfp: stop limiting VFs to 0
  PCI/IOV: Reset total_VFs limit after detaching PF driver
  PCI: faraday: Add missing of_node_put()
  PCI: xilinx-nwl: Add missing of_node_put()
  PCI: xilinx: Add missing of_node_put()
  PCI: endpoint: Use after free in pci_epf_unregister_driver()
  PCI: controller: dwc: Do not let PCIE_DW_PLAT_HOST default to yes
  PCI: rcar: Clean up PHY init on failure
  PCI: rcar: Shut the PHY down in failpath
  PCI: controller: Move PCI_DOMAINS selection to arch Kconfig
  PCI: Initialize endpoint library before controllers
  PCI: shpchp: Manage SHPC unconditionally on non-ACPI systems
This commit is contained in:
Bjorn Helgaas 2018-08-15 14:58:43 -05:00
commit af863d18a1
35 changed files with 187 additions and 61 deletions

View File

@ -1245,8 +1245,14 @@ config PCI
VESA. If you have PCI, say Y, otherwise N. VESA. If you have PCI, say Y, otherwise N.
config PCI_DOMAINS config PCI_DOMAINS
bool bool "Support for multiple PCI domains"
depends on PCI depends on PCI
help
Enable PCI domains kernel management. Say Y if your machine
has a PCI bus hierarchy that requires more than one PCI
domain (aka segment) to be correctly managed. Say N otherwise.
If you don't know what to do here, say N.
config PCI_DOMAINS_GENERIC config PCI_DOMAINS_GENERIC
def_bool PCI_DOMAINS def_bool PCI_DOMAINS

View File

@ -20,6 +20,7 @@ config ARCH_BCM_IPROC
select GPIOLIB select GPIOLIB
select ARM_AMBA select ARM_AMBA
select PINCTRL select PINCTRL
select PCI_DOMAINS if PCI
help help
This enables support for systems based on Broadcom IPROC architected SoCs. This enables support for systems based on Broadcom IPROC architected SoCs.
The IPROC complex contains one or more ARM CPUs along with common The IPROC complex contains one or more ARM CPUs along with common

View File

@ -10,6 +10,7 @@ menuconfig ARCH_SOCFPGA
select HAVE_ARM_SCU select HAVE_ARM_SCU
select HAVE_ARM_TWD if SMP select HAVE_ARM_TWD if SMP
select MFD_SYSCON select MFD_SYSCON
select PCI_DOMAINS if PCI
if ARCH_SOCFPGA if ARCH_SOCFPGA
config SOCFPGA_SUSPEND config SOCFPGA_SUSPEND

View File

@ -42,6 +42,8 @@
#include <asm/ppc-pci.h> #include <asm/ppc-pci.h>
#include <asm/eeh.h> #include <asm/eeh.h>
#include "../../../drivers/pci/pci.h"
/* hose_spinlock protects accesses to the the phb_bitmap. */ /* hose_spinlock protects accesses to the the phb_bitmap. */
static DEFINE_SPINLOCK(hose_spinlock); static DEFINE_SPINLOCK(hose_spinlock);
LIST_HEAD(hose_list); LIST_HEAD(hose_list);
@ -1014,7 +1016,7 @@ void pcibios_setup_bus_devices(struct pci_bus *bus)
/* Cardbus can call us to add new devices to a bus, so ignore /* Cardbus can call us to add new devices to a bus, so ignore
* those who are already fully discovered * those who are already fully discovered
*/ */
if (dev->is_added) if (pci_dev_is_added(dev))
continue; continue;
pcibios_setup_device(dev); pcibios_setup_device(dev);

View File

@ -46,6 +46,7 @@
#include "powernv.h" #include "powernv.h"
#include "pci.h" #include "pci.h"
#include "../../../../drivers/pci/pci.h"
#define PNV_IODA1_M64_NUM 16 /* Number of M64 BARs */ #define PNV_IODA1_M64_NUM 16 /* Number of M64 BARs */
#define PNV_IODA1_M64_SEGS 8 /* Segments per M64 BAR */ #define PNV_IODA1_M64_SEGS 8 /* Segments per M64 BAR */
@ -3138,7 +3139,7 @@ static void pnv_pci_ioda_fixup_iov_resources(struct pci_dev *pdev)
struct pci_dn *pdn; struct pci_dn *pdn;
int mul, total_vfs; int mul, total_vfs;
if (!pdev->is_physfn || pdev->is_added) if (!pdev->is_physfn || pci_dev_is_added(pdev))
return; return;
pdn = pci_get_pdn(pdev); pdn = pci_get_pdn(pdev);

View File

@ -71,6 +71,7 @@
#include <asm/security_features.h> #include <asm/security_features.h>
#include "pseries.h" #include "pseries.h"
#include "../../../../drivers/pci/pci.h"
int CMO_PrPSP = -1; int CMO_PrPSP = -1;
int CMO_SecPSP = -1; int CMO_SecPSP = -1;
@ -664,7 +665,7 @@ static void pseries_pci_fixup_iov_resources(struct pci_dev *pdev)
const int *indexes; const int *indexes;
struct device_node *dn = pci_device_to_OF_node(pdev); struct device_node *dn = pci_device_to_OF_node(pdev);
if (!pdev->is_physfn || pdev->is_added) if (!pdev->is_physfn || pci_dev_is_added(pdev))
return; return;
/*Firmware must support open sriov otherwise dont configure*/ /*Firmware must support open sriov otherwise dont configure*/
indexes = of_get_property(dn, "ibm,open-sriov-vf-bar-info", NULL); indexes = of_get_property(dn, "ibm,open-sriov-vf-bar-info", NULL);

View File

@ -240,7 +240,6 @@ static int nfp_pcie_sriov_read_nfd_limit(struct nfp_pf *pf)
return pci_sriov_set_totalvfs(pf->pdev, pf->limit_vfs); return pci_sriov_set_totalvfs(pf->pdev, pf->limit_vfs);
pf->limit_vfs = ~0; pf->limit_vfs = ~0;
pci_sriov_set_totalvfs(pf->pdev, 0); /* 0 is unset */
/* Allow any setting for backwards compatibility if symbol not found */ /* Allow any setting for backwards compatibility if symbol not found */
if (err == -ENOENT) if (err == -ENOENT)
return 0; return 0;
@ -668,7 +667,7 @@ static int nfp_pci_probe(struct pci_dev *pdev,
err = nfp_net_pci_probe(pf); err = nfp_net_pci_probe(pf);
if (err) if (err)
goto err_sriov_unlimit; goto err_fw_unload;
err = nfp_hwmon_register(pf); err = nfp_hwmon_register(pf);
if (err) { if (err) {
@ -680,8 +679,6 @@ static int nfp_pci_probe(struct pci_dev *pdev,
err_net_remove: err_net_remove:
nfp_net_pci_remove(pf); nfp_net_pci_remove(pf);
err_sriov_unlimit:
pci_sriov_set_totalvfs(pf->pdev, 0);
err_fw_unload: err_fw_unload:
kfree(pf->rtbl); kfree(pf->rtbl);
nfp_mip_close(pf->mip); nfp_mip_close(pf->mip);
@ -715,7 +712,6 @@ static void nfp_pci_remove(struct pci_dev *pdev)
nfp_hwmon_unregister(pf); nfp_hwmon_unregister(pf);
nfp_pcie_sriov_disable(pdev); nfp_pcie_sriov_disable(pdev);
pci_sriov_set_totalvfs(pf->pdev, 0);
nfp_net_pci_remove(pf); nfp_net_pci_remove(pf);

View File

@ -28,10 +28,10 @@ obj-$(CONFIG_PCI_PF_STUB) += pci-pf-stub.o
obj-$(CONFIG_PCI_ECAM) += ecam.o obj-$(CONFIG_PCI_ECAM) += ecam.o
obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += xen-pcifront.o obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += xen-pcifront.o
obj-y += controller/
obj-y += switch/
# Endpoint library must be initialized before its users # Endpoint library must be initialized before its users
obj-$(CONFIG_PCI_ENDPOINT) += endpoint/ obj-$(CONFIG_PCI_ENDPOINT) += endpoint/
obj-y += controller/
obj-y += switch/
ccflags-$(CONFIG_PCI_DEBUG) := -DDEBUG ccflags-$(CONFIG_PCI_DEBUG) := -DDEBUG

View File

@ -330,7 +330,7 @@ void pci_bus_add_device(struct pci_dev *dev)
return; return;
} }
dev->is_added = 1; pci_dev_assign_added(dev, true);
} }
EXPORT_SYMBOL_GPL(pci_bus_add_device); EXPORT_SYMBOL_GPL(pci_bus_add_device);
@ -347,14 +347,14 @@ void pci_bus_add_devices(const struct pci_bus *bus)
list_for_each_entry(dev, &bus->devices, bus_list) { list_for_each_entry(dev, &bus->devices, bus_list) {
/* Skip already-added devices */ /* Skip already-added devices */
if (dev->is_added) if (pci_dev_is_added(dev))
continue; continue;
pci_bus_add_device(dev); pci_bus_add_device(dev);
} }
list_for_each_entry(dev, &bus->devices, bus_list) { list_for_each_entry(dev, &bus->devices, bus_list) {
/* Skip if device attach failed */ /* Skip if device attach failed */
if (!dev->is_added) if (!pci_dev_is_added(dev))
continue; continue;
child = dev->subordinate; child = dev->subordinate;
if (child) if (child)

View File

@ -96,7 +96,6 @@ config PCI_HOST_GENERIC
depends on OF depends on OF
select PCI_HOST_COMMON select PCI_HOST_COMMON
select IRQ_DOMAIN select IRQ_DOMAIN
select PCI_DOMAINS
help help
Say Y here if you want to support a simple generic PCI host Say Y here if you want to support a simple generic PCI host
controller, such as the one emulated by kvmtool. controller, such as the one emulated by kvmtool.
@ -138,7 +137,6 @@ config PCI_VERSATILE
config PCIE_IPROC config PCIE_IPROC
tristate tristate
select PCI_DOMAINS
help help
This enables the iProc PCIe core controller support for Broadcom's This enables the iProc PCIe core controller support for Broadcom's
iProc family of SoCs. An appropriate bus interface driver needs iProc family of SoCs. An appropriate bus interface driver needs
@ -176,7 +174,6 @@ config PCIE_IPROC_MSI
config PCIE_ALTERA config PCIE_ALTERA
bool "Altera PCIe controller" bool "Altera PCIe controller"
depends on ARM || NIOS2 || COMPILE_TEST depends on ARM || NIOS2 || COMPILE_TEST
select PCI_DOMAINS
help help
Say Y here if you want to enable PCIe controller support on Altera Say Y here if you want to enable PCIe controller support on Altera
FPGA. FPGA.

View File

@ -58,7 +58,6 @@ config PCIE_DW_PLAT_HOST
depends on PCI && PCI_MSI_IRQ_DOMAIN depends on PCI && PCI_MSI_IRQ_DOMAIN
select PCIE_DW_HOST select PCIE_DW_HOST
select PCIE_DW_PLAT select PCIE_DW_PLAT
default y
help help
Enables support for the PCIe controller in the Designware IP to Enables support for the PCIe controller in the Designware IP to
work in host mode. There are two instances of PCIe controller in work in host mode. There are two instances of PCIe controller in

View File

@ -363,7 +363,8 @@ int dw_pcie_host_init(struct pcie_port *pp)
resource_list_for_each_entry_safe(win, tmp, &bridge->windows) { resource_list_for_each_entry_safe(win, tmp, &bridge->windows) {
switch (resource_type(win->res)) { switch (resource_type(win->res)) {
case IORESOURCE_IO: case IORESOURCE_IO:
ret = pci_remap_iospace(win->res, pp->io_base); ret = devm_pci_remap_iospace(dev, win->res,
pp->io_base);
if (ret) { if (ret) {
dev_warn(dev, "Error %d: failed to map resource %pR\n", dev_warn(dev, "Error %d: failed to map resource %pR\n",
ret, win->res); ret, win->res);

View File

@ -849,7 +849,7 @@ static int advk_pcie_parse_request_of_pci_ranges(struct advk_pcie *pcie)
0, 0xF8000000, 0, 0, 0xF8000000, 0,
lower_32_bits(res->start), lower_32_bits(res->start),
OB_PCIE_IO); OB_PCIE_IO);
err = pci_remap_iospace(res, iobase); err = devm_pci_remap_iospace(dev, res, iobase);
if (err) { if (err) {
dev_warn(dev, "error %d: failed to map resource %pR\n", dev_warn(dev, "error %d: failed to map resource %pR\n",
err, res); err, res);

View File

@ -355,11 +355,13 @@ static int faraday_pci_setup_cascaded_irq(struct faraday_pci *p)
irq = of_irq_get(intc, 0); irq = of_irq_get(intc, 0);
if (irq <= 0) { if (irq <= 0) {
dev_err(p->dev, "failed to get parent IRQ\n"); dev_err(p->dev, "failed to get parent IRQ\n");
of_node_put(intc);
return irq ?: -EINVAL; return irq ?: -EINVAL;
} }
p->irqdomain = irq_domain_add_linear(intc, PCI_NUM_INTX, p->irqdomain = irq_domain_add_linear(intc, PCI_NUM_INTX,
&faraday_pci_irqdomain_ops, p); &faraday_pci_irqdomain_ops, p);
of_node_put(intc);
if (!p->irqdomain) { if (!p->irqdomain) {
dev_err(p->dev, "failed to create Gemini PCI IRQ domain\n"); dev_err(p->dev, "failed to create Gemini PCI IRQ domain\n");
return -EINVAL; return -EINVAL;
@ -501,7 +503,7 @@ static int faraday_pci_probe(struct platform_device *pdev)
dev_err(dev, "illegal IO mem size\n"); dev_err(dev, "illegal IO mem size\n");
return -EINVAL; return -EINVAL;
} }
ret = pci_remap_iospace(io, io_base); ret = devm_pci_remap_iospace(dev, io, io_base);
if (ret) { if (ret) {
dev_warn(dev, "error %d: failed to map resource %pR\n", dev_warn(dev, "error %d: failed to map resource %pR\n",
ret, io); ret, io);

View File

@ -1073,6 +1073,7 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
struct pci_bus *pbus; struct pci_bus *pbus;
struct pci_dev *pdev; struct pci_dev *pdev;
struct cpumask *dest; struct cpumask *dest;
unsigned long flags;
struct compose_comp_ctxt comp; struct compose_comp_ctxt comp;
struct tran_int_desc *int_desc; struct tran_int_desc *int_desc;
struct { struct {
@ -1164,14 +1165,15 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
* the channel callback directly when channel->target_cpu is * the channel callback directly when channel->target_cpu is
* the current CPU. When the higher level interrupt code * the current CPU. When the higher level interrupt code
* calls us with interrupt enabled, let's add the * calls us with interrupt enabled, let's add the
* local_bh_disable()/enable() to avoid race. * local_irq_save()/restore() to avoid race:
* hv_pci_onchannelcallback() can also run in tasklet.
*/ */
local_bh_disable(); local_irq_save(flags);
if (hbus->hdev->channel->target_cpu == smp_processor_id()) if (hbus->hdev->channel->target_cpu == smp_processor_id())
hv_pci_onchannelcallback(hbus); hv_pci_onchannelcallback(hbus);
local_bh_enable(); local_irq_restore(flags);
if (hpdev->state == hv_pcichild_ejecting) { if (hpdev->state == hv_pcichild_ejecting) {
dev_err_once(&hbus->hdev->device, dev_err_once(&hbus->hdev->device,

View File

@ -537,7 +537,7 @@ static int v3_pci_setup_resource(struct v3_pci *v3,
v3->io_bus_addr = io->start - win->offset; v3->io_bus_addr = io->start - win->offset;
dev_dbg(dev, "I/O window %pR, bus addr %pap\n", dev_dbg(dev, "I/O window %pR, bus addr %pap\n",
io, &v3->io_bus_addr); io, &v3->io_bus_addr);
ret = pci_remap_iospace(io, io_base); ret = devm_pci_remap_iospace(dev, io, io_base);
if (ret) { if (ret) {
dev_warn(dev, dev_warn(dev,
"error %d: failed to map resource %pR\n", "error %d: failed to map resource %pR\n",

View File

@ -82,7 +82,7 @@ static int versatile_pci_parse_request_of_pci_ranges(struct device *dev,
switch (resource_type(res)) { switch (resource_type(res)) {
case IORESOURCE_IO: case IORESOURCE_IO:
err = pci_remap_iospace(res, iobase); err = devm_pci_remap_iospace(dev, res, iobase);
if (err) { if (err) {
dev_warn(dev, "error %d: failed to map resource %pR\n", dev_warn(dev, "error %d: failed to map resource %pR\n",
err, res); err, res);

View File

@ -423,7 +423,7 @@ static int xgene_pcie_map_ranges(struct xgene_pcie_port *port,
case IORESOURCE_IO: case IORESOURCE_IO:
xgene_pcie_setup_ob_reg(port, res, OMR3BARL, io_base, xgene_pcie_setup_ob_reg(port, res, OMR3BARL, io_base,
res->start - window->offset); res->start - window->offset);
ret = pci_remap_iospace(res, io_base); ret = devm_pci_remap_iospace(dev, res, io_base);
if (ret < 0) if (ret < 0)
return ret; return ret;
break; break;

View File

@ -1109,7 +1109,7 @@ static int mtk_pcie_request_resources(struct mtk_pcie *pcie)
if (err < 0) if (err < 0)
return err; return err;
pci_remap_iospace(&pcie->pio, pcie->io.start); devm_pci_remap_iospace(dev, &pcie->pio, pcie->io.start);
return 0; return 0;
} }

View File

@ -107,7 +107,7 @@
#define CFG_WINDOW_TYPE 0 #define CFG_WINDOW_TYPE 0
#define IO_WINDOW_TYPE 1 #define IO_WINDOW_TYPE 1
#define MEM_WINDOW_TYPE 2 #define MEM_WINDOW_TYPE 2
#define IB_WIN_SIZE (256 * 1024 * 1024 * 1024) #define IB_WIN_SIZE ((u64)256 * 1024 * 1024 * 1024)
#define MAX_PIO_WINDOWS 8 #define MAX_PIO_WINDOWS 8
/* Parameters for the waiting for link up routine */ /* Parameters for the waiting for link up routine */

View File

@ -680,7 +680,11 @@ static int rcar_pcie_phy_init_gen3(struct rcar_pcie *pcie)
if (err) if (err)
return err; return err;
return phy_power_on(pcie->phy); err = phy_power_on(pcie->phy);
if (err)
phy_exit(pcie->phy);
return err;
} }
static int rcar_msi_alloc(struct rcar_msi *chip) static int rcar_msi_alloc(struct rcar_msi *chip)
@ -1165,7 +1169,7 @@ static int rcar_pcie_probe(struct platform_device *pdev)
if (rcar_pcie_hw_init(pcie)) { if (rcar_pcie_hw_init(pcie)) {
dev_info(dev, "PCIe link down\n"); dev_info(dev, "PCIe link down\n");
err = -ENODEV; err = -ENODEV;
goto err_clk_disable; goto err_phy_shutdown;
} }
data = rcar_pci_read_reg(pcie, MACSR); data = rcar_pci_read_reg(pcie, MACSR);
@ -1177,7 +1181,7 @@ static int rcar_pcie_probe(struct platform_device *pdev)
dev_err(dev, dev_err(dev,
"failed to enable MSI support: %d\n", "failed to enable MSI support: %d\n",
err); err);
goto err_clk_disable; goto err_phy_shutdown;
} }
} }
@ -1191,6 +1195,12 @@ err_msi_teardown:
if (IS_ENABLED(CONFIG_PCI_MSI)) if (IS_ENABLED(CONFIG_PCI_MSI))
rcar_pcie_teardown_msi(pcie); rcar_pcie_teardown_msi(pcie);
err_phy_shutdown:
if (pcie->phy) {
phy_power_off(pcie->phy);
phy_exit(pcie->phy);
}
err_clk_disable: err_clk_disable:
clk_disable_unprepare(pcie->bus_clk); clk_disable_unprepare(pcie->bus_clk);

View File

@ -559,7 +559,7 @@ static int nwl_pcie_init_irq_domain(struct nwl_pcie *pcie)
PCI_NUM_INTX, PCI_NUM_INTX,
&legacy_domain_ops, &legacy_domain_ops,
pcie); pcie);
of_node_put(legacy_intc_node);
if (!pcie->legacy_irq_domain) { if (!pcie->legacy_irq_domain) {
dev_err(dev, "failed to create IRQ domain\n"); dev_err(dev, "failed to create IRQ domain\n");
return -ENOMEM; return -ENOMEM;

View File

@ -509,6 +509,7 @@ static int xilinx_pcie_init_irq_domain(struct xilinx_pcie_port *port)
port->leg_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX, port->leg_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,
&intx_domain_ops, &intx_domain_ops,
port); port);
of_node_put(pcie_intc_node);
if (!port->leg_domain) { if (!port->leg_domain) {
dev_err(dev, "Failed to get a INTx IRQ domain\n"); dev_err(dev, "Failed to get a INTx IRQ domain\n");
return -ENODEV; return -ENODEV;

View File

@ -137,6 +137,20 @@ void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar)
} }
EXPORT_SYMBOL_GPL(pci_epf_alloc_space); EXPORT_SYMBOL_GPL(pci_epf_alloc_space);
static void pci_epf_remove_cfs(struct pci_epf_driver *driver)
{
struct config_group *group, *tmp;
if (!IS_ENABLED(CONFIG_PCI_ENDPOINT_CONFIGFS))
return;
mutex_lock(&pci_epf_mutex);
list_for_each_entry_safe(group, tmp, &driver->epf_group, group_entry)
pci_ep_cfs_remove_epf_group(group);
list_del(&driver->epf_group);
mutex_unlock(&pci_epf_mutex);
}
/** /**
* pci_epf_unregister_driver() - unregister the PCI EPF driver * pci_epf_unregister_driver() - unregister the PCI EPF driver
* @driver: the PCI EPF driver that has to be unregistered * @driver: the PCI EPF driver that has to be unregistered
@ -145,17 +159,38 @@ EXPORT_SYMBOL_GPL(pci_epf_alloc_space);
*/ */
void pci_epf_unregister_driver(struct pci_epf_driver *driver) void pci_epf_unregister_driver(struct pci_epf_driver *driver)
{ {
struct config_group *group; pci_epf_remove_cfs(driver);
mutex_lock(&pci_epf_mutex);
list_for_each_entry(group, &driver->epf_group, group_entry)
pci_ep_cfs_remove_epf_group(group);
list_del(&driver->epf_group);
mutex_unlock(&pci_epf_mutex);
driver_unregister(&driver->driver); driver_unregister(&driver->driver);
} }
EXPORT_SYMBOL_GPL(pci_epf_unregister_driver); EXPORT_SYMBOL_GPL(pci_epf_unregister_driver);
static int pci_epf_add_cfs(struct pci_epf_driver *driver)
{
struct config_group *group;
const struct pci_epf_device_id *id;
if (!IS_ENABLED(CONFIG_PCI_ENDPOINT_CONFIGFS))
return 0;
INIT_LIST_HEAD(&driver->epf_group);
id = driver->id_table;
while (id->name[0]) {
group = pci_ep_cfs_add_epf_group(id->name);
if (IS_ERR(group)) {
pci_epf_remove_cfs(driver);
return PTR_ERR(group);
}
mutex_lock(&pci_epf_mutex);
list_add_tail(&group->group_entry, &driver->epf_group);
mutex_unlock(&pci_epf_mutex);
id++;
}
return 0;
}
/** /**
* __pci_epf_register_driver() - register a new PCI EPF driver * __pci_epf_register_driver() - register a new PCI EPF driver
* @driver: structure representing PCI EPF driver * @driver: structure representing PCI EPF driver
@ -167,8 +202,6 @@ int __pci_epf_register_driver(struct pci_epf_driver *driver,
struct module *owner) struct module *owner)
{ {
int ret; int ret;
struct config_group *group;
const struct pci_epf_device_id *id;
if (!driver->ops) if (!driver->ops)
return -EINVAL; return -EINVAL;
@ -183,16 +216,7 @@ int __pci_epf_register_driver(struct pci_epf_driver *driver,
if (ret) if (ret)
return ret; return ret;
INIT_LIST_HEAD(&driver->epf_group); pci_epf_add_cfs(driver);
id = driver->id_table;
while (id->name[0]) {
group = pci_ep_cfs_add_epf_group(id->name);
mutex_lock(&pci_epf_mutex);
list_add_tail(&group->group_entry, &driver->epf_group);
mutex_unlock(&pci_epf_mutex);
id++;
}
return 0; return 0;
} }

View File

@ -7,7 +7,6 @@
* All rights reserved. * All rights reserved.
* *
* Send feedback to <kristen.c.accardi@intel.com> * Send feedback to <kristen.c.accardi@intel.com>
*
*/ */
#include <linux/module.h> #include <linux/module.h>
@ -87,8 +86,17 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev)
return 0; return 0;
/* If _OSC exists, we should not evaluate OSHP */ /* If _OSC exists, we should not evaluate OSHP */
/*
* If there's no ACPI host bridge (i.e., ACPI support is compiled
* into the kernel but the hardware platform doesn't support ACPI),
* there's nothing to do here.
*/
host = pci_find_host_bridge(pdev->bus); host = pci_find_host_bridge(pdev->bus);
root = acpi_pci_find_root(ACPI_HANDLE(&host->dev)); root = acpi_pci_find_root(ACPI_HANDLE(&host->dev));
if (!root)
return 0;
if (root->osc_support_set) if (root->osc_support_set)
goto no_control; goto no_control;

View File

@ -509,7 +509,7 @@ static void enable_slot(struct acpiphp_slot *slot)
list_for_each_entry(dev, &bus->devices, bus_list) { list_for_each_entry(dev, &bus->devices, bus_list) {
/* Assume that newly added devices are powered on already. */ /* Assume that newly added devices are powered on already. */
if (!dev->is_added) if (!pci_dev_is_added(dev))
dev->current_state = PCI_D0; dev->current_state = PCI_D0;
} }

View File

@ -574,6 +574,22 @@ void pci_iov_release(struct pci_dev *dev)
sriov_release(dev); sriov_release(dev);
} }
/**
* pci_iov_remove - clean up SR-IOV state after PF driver is detached
* @dev: the PCI device
*/
void pci_iov_remove(struct pci_dev *dev)
{
struct pci_sriov *iov = dev->sriov;
if (!dev->is_physfn)
return;
iov->driver_max_VFs = iov->total_VFs;
if (iov->num_VFs)
pci_warn(dev, "driver left SR-IOV enabled after remove\n");
}
/** /**
* pci_iov_update_resource - update a VF BAR * pci_iov_update_resource - update a VF BAR
* @dev: the PCI device * @dev: the PCI device

View File

@ -612,7 +612,7 @@ int pci_parse_request_of_pci_ranges(struct device *dev,
switch (resource_type(res)) { switch (resource_type(res)) {
case IORESOURCE_IO: case IORESOURCE_IO:
err = pci_remap_iospace(res, iobase); err = devm_pci_remap_iospace(dev, res, iobase);
if (err) { if (err) {
dev_warn(dev, "error %d: failed to map resource %pR\n", dev_warn(dev, "error %d: failed to map resource %pR\n",
err, res); err, res);

View File

@ -445,6 +445,7 @@ static int pci_device_remove(struct device *dev)
} }
pcibios_free_irq(pci_dev); pcibios_free_irq(pci_dev);
pci_dev->driver = NULL; pci_dev->driver = NULL;
pci_iov_remove(pci_dev);
} }
/* Undo the runtime PM settings in local_pci_probe() */ /* Undo the runtime PM settings in local_pci_probe() */

View File

@ -3579,6 +3579,44 @@ void pci_unmap_iospace(struct resource *res)
} }
EXPORT_SYMBOL(pci_unmap_iospace); EXPORT_SYMBOL(pci_unmap_iospace);
static void devm_pci_unmap_iospace(struct device *dev, void *ptr)
{
struct resource **res = ptr;
pci_unmap_iospace(*res);
}
/**
* devm_pci_remap_iospace - Managed pci_remap_iospace()
* @dev: Generic device to remap IO address for
* @res: Resource describing the I/O space
* @phys_addr: physical address of range to be mapped
*
* Managed pci_remap_iospace(). Map is automatically unmapped on driver
* detach.
*/
int devm_pci_remap_iospace(struct device *dev, const struct resource *res,
phys_addr_t phys_addr)
{
const struct resource **ptr;
int error;
ptr = devres_alloc(devm_pci_unmap_iospace, sizeof(*ptr), GFP_KERNEL);
if (!ptr)
return -ENOMEM;
error = pci_remap_iospace(res, phys_addr);
if (error) {
devres_free(ptr);
} else {
*ptr = res;
devres_add(dev, ptr);
}
return error;
}
EXPORT_SYMBOL(devm_pci_remap_iospace);
/** /**
* devm_pci_remap_cfgspace - Managed pci_remap_cfgspace() * devm_pci_remap_cfgspace - Managed pci_remap_cfgspace()
* @dev: Generic device to remap IO address for * @dev: Generic device to remap IO address for

View File

@ -288,6 +288,7 @@ struct pci_sriov {
/* pci_dev priv_flags */ /* pci_dev priv_flags */
#define PCI_DEV_DISCONNECTED 0 #define PCI_DEV_DISCONNECTED 0
#define PCI_DEV_ADDED 1
static inline int pci_dev_set_disconnected(struct pci_dev *dev, void *unused) static inline int pci_dev_set_disconnected(struct pci_dev *dev, void *unused)
{ {
@ -300,6 +301,16 @@ static inline bool pci_dev_is_disconnected(const struct pci_dev *dev)
return test_bit(PCI_DEV_DISCONNECTED, &dev->priv_flags); return test_bit(PCI_DEV_DISCONNECTED, &dev->priv_flags);
} }
static inline void pci_dev_assign_added(struct pci_dev *dev, bool added)
{
assign_bit(PCI_DEV_ADDED, &dev->priv_flags, added);
}
static inline bool pci_dev_is_added(const struct pci_dev *dev)
{
return test_bit(PCI_DEV_ADDED, &dev->priv_flags);
}
#ifdef CONFIG_PCI_ATS #ifdef CONFIG_PCI_ATS
void pci_restore_ats_state(struct pci_dev *dev); void pci_restore_ats_state(struct pci_dev *dev);
#else #else
@ -311,6 +322,7 @@ static inline void pci_restore_ats_state(struct pci_dev *dev)
#ifdef CONFIG_PCI_IOV #ifdef CONFIG_PCI_IOV
int pci_iov_init(struct pci_dev *dev); int pci_iov_init(struct pci_dev *dev);
void pci_iov_release(struct pci_dev *dev); void pci_iov_release(struct pci_dev *dev);
void pci_iov_remove(struct pci_dev *dev);
void pci_iov_update_resource(struct pci_dev *dev, int resno); void pci_iov_update_resource(struct pci_dev *dev, int resno);
resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno); resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno);
void pci_restore_iov_state(struct pci_dev *dev); void pci_restore_iov_state(struct pci_dev *dev);
@ -323,6 +335,9 @@ static inline int pci_iov_init(struct pci_dev *dev)
} }
static inline void pci_iov_release(struct pci_dev *dev) static inline void pci_iov_release(struct pci_dev *dev)
{
}
static inline void pci_iov_remove(struct pci_dev *dev)
{ {
} }
static inline void pci_restore_iov_state(struct pci_dev *dev) static inline void pci_restore_iov_state(struct pci_dev *dev)

View File

@ -295,6 +295,7 @@ void pcie_do_fatal_recovery(struct pci_dev *dev, u32 service)
parent = udev->subordinate; parent = udev->subordinate;
pci_lock_rescan_remove(); pci_lock_rescan_remove();
pci_dev_get(dev);
list_for_each_entry_safe_reverse(pdev, temp, &parent->devices, list_for_each_entry_safe_reverse(pdev, temp, &parent->devices,
bus_list) { bus_list) {
pci_dev_get(pdev); pci_dev_get(pdev);
@ -328,6 +329,7 @@ void pcie_do_fatal_recovery(struct pci_dev *dev, u32 service)
pci_info(dev, "Device recovery from fatal error failed\n"); pci_info(dev, "Device recovery from fatal error failed\n");
} }
pci_dev_put(dev);
pci_unlock_rescan_remove(); pci_unlock_rescan_remove();
} }

View File

@ -2433,13 +2433,13 @@ int pci_scan_slot(struct pci_bus *bus, int devfn)
dev = pci_scan_single_device(bus, devfn); dev = pci_scan_single_device(bus, devfn);
if (!dev) if (!dev)
return 0; return 0;
if (!dev->is_added) if (!pci_dev_is_added(dev))
nr++; nr++;
for (fn = next_fn(bus, dev, 0); fn > 0; fn = next_fn(bus, dev, fn)) { for (fn = next_fn(bus, dev, 0); fn > 0; fn = next_fn(bus, dev, fn)) {
dev = pci_scan_single_device(bus, devfn + fn); dev = pci_scan_single_device(bus, devfn + fn);
if (dev) { if (dev) {
if (!dev->is_added) if (!pci_dev_is_added(dev))
nr++; nr++;
dev->multifunction = 1; dev->multifunction = 1;
} }

View File

@ -19,11 +19,12 @@ static void pci_stop_dev(struct pci_dev *dev)
{ {
pci_pme_active(dev, false); pci_pme_active(dev, false);
if (dev->is_added) { if (pci_dev_is_added(dev)) {
device_release_driver(&dev->dev); device_release_driver(&dev->dev);
pci_proc_detach_device(dev); pci_proc_detach_device(dev);
pci_remove_sysfs_dev_files(dev); pci_remove_sysfs_dev_files(dev);
dev->is_added = 0;
pci_dev_assign_added(dev, false);
} }
if (dev->bus->self) if (dev->bus->self)

View File

@ -368,7 +368,6 @@ struct pci_dev {
unsigned int transparent:1; /* Subtractive decode bridge */ unsigned int transparent:1; /* Subtractive decode bridge */
unsigned int multifunction:1; /* Multi-function device */ unsigned int multifunction:1; /* Multi-function device */
unsigned int is_added:1;
unsigned int is_busmaster:1; /* Is busmaster */ unsigned int is_busmaster:1; /* Is busmaster */
unsigned int no_msi:1; /* May not use MSI */ unsigned int no_msi:1; /* May not use MSI */
unsigned int no_64bit_msi:1; /* May only use 32-bit MSIs */ unsigned int no_64bit_msi:1; /* May only use 32-bit MSIs */
@ -1240,6 +1239,8 @@ int pci_register_io_range(struct fwnode_handle *fwnode, phys_addr_t addr,
unsigned long pci_address_to_pio(phys_addr_t addr); unsigned long pci_address_to_pio(phys_addr_t addr);
phys_addr_t pci_pio_to_address(unsigned long pio); phys_addr_t pci_pio_to_address(unsigned long pio);
int pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr); int pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr);
int devm_pci_remap_iospace(struct device *dev, const struct resource *res,
phys_addr_t phys_addr);
void pci_unmap_iospace(struct resource *res); void pci_unmap_iospace(struct resource *res);
void __iomem *devm_pci_remap_cfgspace(struct device *dev, void __iomem *devm_pci_remap_cfgspace(struct device *dev,
resource_size_t offset, resource_size_t offset,