mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 22:51:42 +00:00
Merge branches 'pci/aspm', 'pci/dpc', 'pci/hotplug', 'pci/misc', 'pci/msi', 'pci/pm' and 'pci/virtualization' into next
* pci/aspm: PCI/ASPM: Remove redundant check of pcie_set_clkpm * pci/dpc: PCI: Remove DPC tristate module option PCI: Bind DPC to Root Ports as well as Downstream Ports PCI: Fix whitespace in struct dpc_dev PCI: Convert Downstream Port Containment driver to use devm_* functions * pci/hotplug: PCI: Allow additional bus numbers for hotplug bridges * pci/misc: PCI: Include <asm/dma.h> for isa_dma_bridge_buggy PCI: Make bus_attr_resource_alignment static MAINTAINERS: Add file patterns for PCI device tree bindings PCI: Fix comment typo * pci/msi: PCI/MSI: irqchip: Fix PCI_MSI dependencies * pci/pm: PCI: pciehp: Ignore interrupts during D3cold PCI: Document connection between pci_power_t and hardware PM capability PCI: Add runtime PM support for PCIe ports ACPI / hotplug / PCI: Runtime resume bridge before rescan PCI: Power on bridges before scanning new devices PCI: Put PCIe ports into D3 during suspend PCI: Don't clear d3cold_allowed for PCIe ports PCI / PM: Enforce type casting for pci_power_t * pci/virtualization: PCI: Add ACS quirk for Solarflare SFC9220 PCI: Add DMA alias quirk for Adaptec 3805 PCI: Mark Atheros AR9485 and QCA9882 to avoid bus reset PCI: Add function 1 DMA alias quirk for Marvell 88SE9182
This commit is contained in:
commit
a00c74c166
@ -3016,6 +3016,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
||||
hpmemsize=nn[KMG] The fixed amount of bus space which is
|
||||
reserved for hotplug bridge's memory window.
|
||||
Default size is 2 megabytes.
|
||||
hpbussize=nn The minimum amount of additional bus numbers
|
||||
reserved for buses below a hotplug bridge.
|
||||
Default is 1.
|
||||
realloc= Enable/disable reallocating PCI bridge resources
|
||||
if allocations done by BIOS are too small to
|
||||
accommodate resources required by all child
|
||||
@ -3047,6 +3050,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
||||
compat Treat PCIe ports as PCI-to-PCI bridges, disable the PCIe
|
||||
ports driver.
|
||||
|
||||
pcie_port_pm= [PCIE] PCIe port power management handling:
|
||||
off Disable power management of all PCIe ports
|
||||
force Forcibly enable power management of all PCIe ports
|
||||
|
||||
pcie_pme= [PCIE,PM] Native PCIe PME signaling options:
|
||||
nomsi Do not use MSI for native PCIe PME signaling (this makes
|
||||
all PCIe root ports use INTx for all services).
|
||||
|
@ -8678,6 +8678,7 @@ L: linux-pci@vger.kernel.org
|
||||
Q: http://patchwork.ozlabs.org/project/linux-pci/list/
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git
|
||||
S: Supported
|
||||
F: Documentation/devicetree/bindings/pci/
|
||||
F: Documentation/PCI/
|
||||
F: drivers/pci/
|
||||
F: include/linux/pci*
|
||||
|
@ -715,7 +715,7 @@ config ARCH_VIRT
|
||||
depends on ARCH_MULTI_V7
|
||||
select ARM_AMBA
|
||||
select ARM_GIC
|
||||
select ARM_GIC_V2M if PCI_MSI
|
||||
select ARM_GIC_V2M if PCI
|
||||
select ARM_GIC_V3
|
||||
select ARM_PSCI
|
||||
select HAVE_ARM_ARCH_TIMER
|
||||
|
@ -21,9 +21,9 @@ config ARM64
|
||||
select ARM_ARCH_TIMER
|
||||
select ARM_GIC
|
||||
select AUDIT_ARCH_COMPAT_GENERIC
|
||||
select ARM_GIC_V2M if PCI_MSI
|
||||
select ARM_GIC_V2M if PCI
|
||||
select ARM_GIC_V3
|
||||
select ARM_GIC_V3_ITS if PCI_MSI
|
||||
select ARM_GIC_V3_ITS if PCI
|
||||
select ARM_PSCI_FW
|
||||
select BUILDTIME_EXTABLE_SORT
|
||||
select CLONE_BACKWARDS
|
||||
|
@ -133,7 +133,7 @@ static void pcibios_fixup_device_resources(struct pci_dev *dev)
|
||||
if (pci_probe & PCI_NOASSIGN_BARS) {
|
||||
/*
|
||||
* If the BIOS did not assign the BAR, zero out the
|
||||
* resource so the kernel doesn't attmept to assign
|
||||
* resource so the kernel doesn't attempt to assign
|
||||
* it later on in pci_assign_unassigned_resources
|
||||
*/
|
||||
for (bar = 0; bar <= PCI_STD_RESOURCE_END; bar++) {
|
||||
|
@ -15,9 +15,9 @@ config ARM_GIC_MAX_NR
|
||||
|
||||
config ARM_GIC_V2M
|
||||
bool
|
||||
depends on ARM_GIC
|
||||
depends on PCI && PCI_MSI
|
||||
select PCI_MSI_IRQ_DOMAIN
|
||||
depends on PCI
|
||||
select ARM_GIC
|
||||
select PCI_MSI
|
||||
|
||||
config GIC_NON_BANKED
|
||||
bool
|
||||
@ -31,7 +31,8 @@ config ARM_GIC_V3
|
||||
|
||||
config ARM_GIC_V3_ITS
|
||||
bool
|
||||
select PCI_MSI_IRQ_DOMAIN
|
||||
depends on PCI
|
||||
depends on PCI_MSI
|
||||
|
||||
config ARM_NVIC
|
||||
bool
|
||||
@ -56,13 +57,13 @@ config ARM_VIC_NR
|
||||
config ARMADA_370_XP_IRQ
|
||||
bool
|
||||
select GENERIC_IRQ_CHIP
|
||||
select PCI_MSI_IRQ_DOMAIN if PCI_MSI
|
||||
select PCI_MSI if PCI
|
||||
|
||||
config ALPINE_MSI
|
||||
bool
|
||||
depends on PCI && PCI_MSI
|
||||
depends on PCI
|
||||
select PCI_MSI
|
||||
select GENERIC_IRQ_CHIP
|
||||
select PCI_MSI_IRQ_DOMAIN
|
||||
|
||||
config ATMEL_AIC_IRQ
|
||||
bool
|
||||
@ -111,7 +112,6 @@ config HISILICON_IRQ_MBIGEN
|
||||
bool
|
||||
select ARM_GIC_V3
|
||||
select ARM_GIC_V3_ITS
|
||||
select GENERIC_MSI_IRQ_DOMAIN
|
||||
|
||||
config IMGPDC_IRQ
|
||||
bool
|
||||
@ -244,12 +244,10 @@ config IRQ_MXS
|
||||
|
||||
config MVEBU_ODMI
|
||||
bool
|
||||
select GENERIC_MSI_IRQ_DOMAIN
|
||||
|
||||
config LS_SCFG_MSI
|
||||
def_bool y if SOC_LS1021A || ARCH_LAYERSCAPE
|
||||
depends on PCI && PCI_MSI
|
||||
select PCI_MSI_IRQ_DOMAIN
|
||||
|
||||
config PARTITION_PERCPU
|
||||
bool
|
||||
|
@ -25,7 +25,7 @@ config PCI_MSI
|
||||
If you don't know what to do here, say Y.
|
||||
|
||||
config PCI_MSI_IRQ_DOMAIN
|
||||
bool
|
||||
def_bool ARM || ARM64 || X86
|
||||
depends on PCI_MSI
|
||||
select GENERIC_MSI_IRQ_DOMAIN
|
||||
|
||||
|
@ -291,6 +291,7 @@ void pci_bus_add_device(struct pci_dev *dev)
|
||||
pci_fixup_device(pci_fixup_final, dev);
|
||||
pci_create_sysfs_dev_files(dev);
|
||||
pci_proc_attach_device(dev);
|
||||
pci_bridge_d3_device_changed(dev);
|
||||
|
||||
dev->match_driver = true;
|
||||
retval = device_attach(&dev->dev);
|
||||
|
@ -3,8 +3,9 @@ menu "PCI host controller drivers"
|
||||
|
||||
config PCI_DRA7XX
|
||||
bool "TI DRA7xx PCIe controller"
|
||||
select PCIE_DW
|
||||
depends on OF && HAS_IOMEM && TI_PIPE3
|
||||
depends on PCI_MSI_IRQ_DOMAIN
|
||||
select PCIE_DW
|
||||
help
|
||||
Enables support for the PCIe controller in the DRA7xx SoC. There
|
||||
are two instances of PCIe controller in DRA7xx. This controller can
|
||||
@ -20,7 +21,7 @@ config PCI_MVEBU
|
||||
config PCIE_XILINX_NWL
|
||||
bool "NWL PCIe Core"
|
||||
depends on ARCH_ZYNQMP
|
||||
select PCI_MSI_IRQ_DOMAIN if PCI_MSI
|
||||
depends on PCI_MSI_IRQ_DOMAIN
|
||||
help
|
||||
Say 'Y' here if you want kernel support for Xilinx
|
||||
NWL PCIe controller. The controller can act as Root Port
|
||||
@ -29,6 +30,7 @@ config PCIE_XILINX_NWL
|
||||
|
||||
config PCIE_DW_PLAT
|
||||
bool "Platform bus based DesignWare PCIe Controller"
|
||||
depends on PCI_MSI_IRQ_DOMAIN
|
||||
select PCIE_DW
|
||||
---help---
|
||||
This selects the DesignWare PCIe controller support. Select this if
|
||||
@ -40,16 +42,19 @@ config PCIE_DW_PLAT
|
||||
|
||||
config PCIE_DW
|
||||
bool
|
||||
depends on PCI_MSI_IRQ_DOMAIN
|
||||
|
||||
config PCI_EXYNOS
|
||||
bool "Samsung Exynos PCIe controller"
|
||||
depends on SOC_EXYNOS5440
|
||||
depends on PCI_MSI_IRQ_DOMAIN
|
||||
select PCIEPORTBUS
|
||||
select PCIE_DW
|
||||
|
||||
config PCI_IMX6
|
||||
bool "Freescale i.MX6 PCIe controller"
|
||||
depends on SOC_IMX6Q
|
||||
depends on PCI_MSI_IRQ_DOMAIN
|
||||
select PCIEPORTBUS
|
||||
select PCIE_DW
|
||||
|
||||
@ -72,8 +77,7 @@ config PCI_RCAR_GEN2
|
||||
config PCIE_RCAR
|
||||
bool "Renesas R-Car PCIe controller"
|
||||
depends on ARCH_RENESAS || (ARM && COMPILE_TEST)
|
||||
select PCI_MSI
|
||||
select PCI_MSI_IRQ_DOMAIN
|
||||
depends on PCI_MSI_IRQ_DOMAIN
|
||||
help
|
||||
Say Y here if you want PCIe controller support on R-Car SoCs.
|
||||
|
||||
@ -92,6 +96,7 @@ config PCI_HOST_GENERIC
|
||||
config PCIE_SPEAR13XX
|
||||
bool "STMicroelectronics SPEAr PCIe controller"
|
||||
depends on ARCH_SPEAR13XX
|
||||
depends on PCI_MSI_IRQ_DOMAIN
|
||||
select PCIEPORTBUS
|
||||
select PCIE_DW
|
||||
help
|
||||
@ -100,6 +105,7 @@ config PCIE_SPEAR13XX
|
||||
config PCI_KEYSTONE
|
||||
bool "TI Keystone PCIe controller"
|
||||
depends on ARCH_KEYSTONE
|
||||
depends on PCI_MSI_IRQ_DOMAIN
|
||||
select PCIE_DW
|
||||
select PCIEPORTBUS
|
||||
help
|
||||
@ -120,7 +126,6 @@ config PCI_XGENE
|
||||
depends on ARCH_XGENE
|
||||
depends on OF
|
||||
select PCIEPORTBUS
|
||||
select PCI_MSI_IRQ_DOMAIN if PCI_MSI
|
||||
help
|
||||
Say Y here if you want internal PCI support on APM X-Gene SoC.
|
||||
There are 5 internal PCIe ports available. Each port is GEN3 capable
|
||||
@ -128,7 +133,8 @@ config PCI_XGENE
|
||||
|
||||
config PCI_XGENE_MSI
|
||||
bool "X-Gene v1 PCIe MSI feature"
|
||||
depends on PCI_XGENE && PCI_MSI
|
||||
depends on PCI_XGENE
|
||||
depends on PCI_MSI_IRQ_DOMAIN
|
||||
default y
|
||||
help
|
||||
Say Y here if you want PCIe MSI support for the APM X-Gene v1 SoC.
|
||||
@ -137,6 +143,7 @@ config PCI_XGENE_MSI
|
||||
config PCI_LAYERSCAPE
|
||||
bool "Freescale Layerscape PCIe controller"
|
||||
depends on OF && (ARM || ARCH_LAYERSCAPE)
|
||||
depends on PCI_MSI_IRQ_DOMAIN
|
||||
select PCIE_DW
|
||||
select MFD_SYSCON
|
||||
help
|
||||
@ -177,8 +184,7 @@ config PCIE_IPROC_BCMA
|
||||
config PCIE_IPROC_MSI
|
||||
bool "Broadcom iProc PCIe MSI support"
|
||||
depends on PCIE_IPROC_PLATFORM || PCIE_IPROC_BCMA
|
||||
depends on PCI_MSI
|
||||
select PCI_MSI_IRQ_DOMAIN
|
||||
depends on PCI_MSI_IRQ_DOMAIN
|
||||
default ARCH_BCM_IPROC
|
||||
help
|
||||
Say Y here if you want to enable MSI support for Broadcom's iProc
|
||||
@ -195,8 +201,8 @@ config PCIE_ALTERA
|
||||
|
||||
config PCIE_ALTERA_MSI
|
||||
bool "Altera PCIe MSI feature"
|
||||
depends on PCIE_ALTERA && PCI_MSI
|
||||
select PCI_MSI_IRQ_DOMAIN
|
||||
depends on PCIE_ALTERA
|
||||
depends on PCI_MSI_IRQ_DOMAIN
|
||||
help
|
||||
Say Y here if you want PCIe MSI support for the Altera FPGA.
|
||||
This MSI driver supports Altera MSI to GIC controller IP.
|
||||
@ -204,6 +210,7 @@ config PCIE_ALTERA_MSI
|
||||
config PCI_HISI
|
||||
depends on OF && ARM64
|
||||
bool "HiSilicon Hip05 and Hip06 SoCs PCIe controllers"
|
||||
depends on PCI_MSI_IRQ_DOMAIN
|
||||
select PCIEPORTBUS
|
||||
select PCIE_DW
|
||||
help
|
||||
@ -213,6 +220,7 @@ config PCI_HISI
|
||||
config PCIE_QCOM
|
||||
bool "Qualcomm PCIe controller"
|
||||
depends on ARCH_QCOM && OF
|
||||
depends on PCI_MSI_IRQ_DOMAIN
|
||||
select PCIE_DW
|
||||
select PCIEPORTBUS
|
||||
help
|
||||
@ -237,6 +245,7 @@ config PCI_HOST_THUNDER_ECAM
|
||||
config PCIE_ARMADA_8K
|
||||
bool "Marvell Armada-8K PCIe controller"
|
||||
depends on ARCH_MVEBU
|
||||
depends on PCI_MSI_IRQ_DOMAIN
|
||||
select PCIE_DW
|
||||
select PCIEPORTBUS
|
||||
help
|
||||
|
@ -675,6 +675,8 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge)
|
||||
if (bridge->is_going_away)
|
||||
return;
|
||||
|
||||
pm_runtime_get_sync(&bridge->pci_dev->dev);
|
||||
|
||||
list_for_each_entry(slot, &bridge->slots, node) {
|
||||
struct pci_bus *bus = slot->bus;
|
||||
struct pci_dev *dev, *tmp;
|
||||
@ -694,6 +696,8 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge)
|
||||
disable_slot(slot);
|
||||
}
|
||||
}
|
||||
|
||||
pm_runtime_put(&bridge->pci_dev->dev);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -546,6 +546,10 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
|
||||
u8 present;
|
||||
bool link;
|
||||
|
||||
/* Interrupts cannot originate from a controller that's asleep */
|
||||
if (pdev->current_state == PCI_D3cold)
|
||||
return IRQ_NONE;
|
||||
|
||||
/*
|
||||
* In order to guarantee that all interrupt events are
|
||||
* serviced, we need to re-inspect Slot Status register after
|
||||
|
@ -777,7 +777,7 @@ static int pci_pm_suspend_noirq(struct device *dev)
|
||||
|
||||
if (!pci_dev->state_saved) {
|
||||
pci_save_state(pci_dev);
|
||||
if (!pci_has_subordinate(pci_dev))
|
||||
if (pci_power_manageable(pci_dev))
|
||||
pci_prepare_to_sleep(pci_dev);
|
||||
}
|
||||
|
||||
@ -1144,7 +1144,6 @@ static int pci_pm_runtime_suspend(struct device *dev)
|
||||
return -ENOSYS;
|
||||
|
||||
pci_dev->state_saved = false;
|
||||
pci_dev->no_d3cold = false;
|
||||
error = pm->runtime_suspend(dev);
|
||||
if (error) {
|
||||
/*
|
||||
@ -1161,8 +1160,6 @@ static int pci_pm_runtime_suspend(struct device *dev)
|
||||
|
||||
return error;
|
||||
}
|
||||
if (!pci_dev->d3cold_allowed)
|
||||
pci_dev->no_d3cold = true;
|
||||
|
||||
pci_fixup_device(pci_fixup_suspend, pci_dev);
|
||||
|
||||
|
@ -406,6 +406,11 @@ static ssize_t d3cold_allowed_store(struct device *dev,
|
||||
return -EINVAL;
|
||||
|
||||
pdev->d3cold_allowed = !!val;
|
||||
if (pdev->d3cold_allowed)
|
||||
pci_d3cold_enable(pdev);
|
||||
else
|
||||
pci_d3cold_disable(pdev);
|
||||
|
||||
pm_runtime_resume(dev);
|
||||
|
||||
return count;
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_pci.h>
|
||||
@ -28,6 +29,7 @@
|
||||
#include <linux/pci_hotplug.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/dma.h>
|
||||
#include <linux/aer.h>
|
||||
#include "pci.h"
|
||||
|
||||
@ -83,6 +85,9 @@ unsigned long pci_cardbus_mem_size = DEFAULT_CARDBUS_MEM_SIZE;
|
||||
unsigned long pci_hotplug_io_size = DEFAULT_HOTPLUG_IO_SIZE;
|
||||
unsigned long pci_hotplug_mem_size = DEFAULT_HOTPLUG_MEM_SIZE;
|
||||
|
||||
#define DEFAULT_HOTPLUG_BUS_SIZE 1
|
||||
unsigned long pci_hotplug_bus_size = DEFAULT_HOTPLUG_BUS_SIZE;
|
||||
|
||||
enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_DEFAULT;
|
||||
|
||||
/*
|
||||
@ -103,6 +108,21 @@ unsigned int pcibios_max_latency = 255;
|
||||
/* If set, the PCIe ARI capability will not be used. */
|
||||
static bool pcie_ari_disabled;
|
||||
|
||||
/* Disable bridge_d3 for all PCIe ports */
|
||||
static bool pci_bridge_d3_disable;
|
||||
/* Force bridge_d3 for all PCIe ports */
|
||||
static bool pci_bridge_d3_force;
|
||||
|
||||
static int __init pcie_port_pm_setup(char *str)
|
||||
{
|
||||
if (!strcmp(str, "off"))
|
||||
pci_bridge_d3_disable = true;
|
||||
else if (!strcmp(str, "force"))
|
||||
pci_bridge_d3_force = true;
|
||||
return 1;
|
||||
}
|
||||
__setup("pcie_port_pm=", pcie_port_pm_setup);
|
||||
|
||||
/**
|
||||
* pci_bus_max_busnr - returns maximum PCI bus number of given bus' children
|
||||
* @bus: pointer to PCI bus structure to search
|
||||
@ -2157,6 +2177,164 @@ void pci_config_pm_runtime_put(struct pci_dev *pdev)
|
||||
pm_runtime_put_sync(parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_bridge_d3_possible - Is it possible to put the bridge into D3
|
||||
* @bridge: Bridge to check
|
||||
*
|
||||
* This function checks if it is possible to move the bridge to D3.
|
||||
* Currently we only allow D3 for recent enough PCIe ports.
|
||||
*/
|
||||
static bool pci_bridge_d3_possible(struct pci_dev *bridge)
|
||||
{
|
||||
unsigned int year;
|
||||
|
||||
if (!pci_is_pcie(bridge))
|
||||
return false;
|
||||
|
||||
switch (pci_pcie_type(bridge)) {
|
||||
case PCI_EXP_TYPE_ROOT_PORT:
|
||||
case PCI_EXP_TYPE_UPSTREAM:
|
||||
case PCI_EXP_TYPE_DOWNSTREAM:
|
||||
if (pci_bridge_d3_disable)
|
||||
return false;
|
||||
if (pci_bridge_d3_force)
|
||||
return true;
|
||||
|
||||
/*
|
||||
* It should be safe to put PCIe ports from 2015 or newer
|
||||
* to D3.
|
||||
*/
|
||||
if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) &&
|
||||
year >= 2015) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int pci_dev_check_d3cold(struct pci_dev *dev, void *data)
|
||||
{
|
||||
bool *d3cold_ok = data;
|
||||
bool no_d3cold;
|
||||
|
||||
/*
|
||||
* The device needs to be allowed to go D3cold and if it is wake
|
||||
* capable to do so from D3cold.
|
||||
*/
|
||||
no_d3cold = dev->no_d3cold || !dev->d3cold_allowed ||
|
||||
(device_may_wakeup(&dev->dev) && !pci_pme_capable(dev, PCI_D3cold)) ||
|
||||
!pci_power_manageable(dev);
|
||||
|
||||
*d3cold_ok = !no_d3cold;
|
||||
|
||||
return no_d3cold;
|
||||
}
|
||||
|
||||
/*
|
||||
* pci_bridge_d3_update - Update bridge D3 capabilities
|
||||
* @dev: PCI device which is changed
|
||||
* @remove: Is the device being removed
|
||||
*
|
||||
* Update upstream bridge PM capabilities accordingly depending on if the
|
||||
* device PM configuration was changed or the device is being removed. The
|
||||
* change is also propagated upstream.
|
||||
*/
|
||||
static void pci_bridge_d3_update(struct pci_dev *dev, bool remove)
|
||||
{
|
||||
struct pci_dev *bridge;
|
||||
bool d3cold_ok = true;
|
||||
|
||||
bridge = pci_upstream_bridge(dev);
|
||||
if (!bridge || !pci_bridge_d3_possible(bridge))
|
||||
return;
|
||||
|
||||
pci_dev_get(bridge);
|
||||
/*
|
||||
* If the device is removed we do not care about its D3cold
|
||||
* capabilities.
|
||||
*/
|
||||
if (!remove)
|
||||
pci_dev_check_d3cold(dev, &d3cold_ok);
|
||||
|
||||
if (d3cold_ok) {
|
||||
/*
|
||||
* We need to go through all children to find out if all of
|
||||
* them can still go to D3cold.
|
||||
*/
|
||||
pci_walk_bus(bridge->subordinate, pci_dev_check_d3cold,
|
||||
&d3cold_ok);
|
||||
}
|
||||
|
||||
if (bridge->bridge_d3 != d3cold_ok) {
|
||||
bridge->bridge_d3 = d3cold_ok;
|
||||
/* Propagate change to upstream bridges */
|
||||
pci_bridge_d3_update(bridge, false);
|
||||
}
|
||||
|
||||
pci_dev_put(bridge);
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_bridge_d3_device_changed - Update bridge D3 capabilities on change
|
||||
* @dev: PCI device that was changed
|
||||
*
|
||||
* If a device is added or its PM configuration, such as is it allowed to
|
||||
* enter D3cold, is changed this function updates upstream bridge PM
|
||||
* capabilities accordingly.
|
||||
*/
|
||||
void pci_bridge_d3_device_changed(struct pci_dev *dev)
|
||||
{
|
||||
pci_bridge_d3_update(dev, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_bridge_d3_device_removed - Update bridge D3 capabilities on remove
|
||||
* @dev: PCI device being removed
|
||||
*
|
||||
* Function updates upstream bridge PM capabilities based on other devices
|
||||
* still left on the bus.
|
||||
*/
|
||||
void pci_bridge_d3_device_removed(struct pci_dev *dev)
|
||||
{
|
||||
pci_bridge_d3_update(dev, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_d3cold_enable - Enable D3cold for device
|
||||
* @dev: PCI device to handle
|
||||
*
|
||||
* This function can be used in drivers to enable D3cold from the device
|
||||
* they handle. It also updates upstream PCI bridge PM capabilities
|
||||
* accordingly.
|
||||
*/
|
||||
void pci_d3cold_enable(struct pci_dev *dev)
|
||||
{
|
||||
if (dev->no_d3cold) {
|
||||
dev->no_d3cold = false;
|
||||
pci_bridge_d3_device_changed(dev);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pci_d3cold_enable);
|
||||
|
||||
/**
|
||||
* pci_d3cold_disable - Disable D3cold for device
|
||||
* @dev: PCI device to handle
|
||||
*
|
||||
* This function can be used in drivers to disable D3cold from the device
|
||||
* they handle. It also updates upstream PCI bridge PM capabilities
|
||||
* accordingly.
|
||||
*/
|
||||
void pci_d3cold_disable(struct pci_dev *dev)
|
||||
{
|
||||
if (!dev->no_d3cold) {
|
||||
dev->no_d3cold = true;
|
||||
pci_bridge_d3_device_changed(dev);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pci_d3cold_disable);
|
||||
|
||||
/**
|
||||
* pci_pm_init - Initialize PM functions of given PCI device
|
||||
* @dev: PCI device to handle.
|
||||
@ -2191,6 +2369,7 @@ void pci_pm_init(struct pci_dev *dev)
|
||||
dev->pm_cap = pm;
|
||||
dev->d3_delay = PCI_PM_D3_WAIT;
|
||||
dev->d3cold_delay = PCI_PM_D3COLD_WAIT;
|
||||
dev->bridge_d3 = pci_bridge_d3_possible(dev);
|
||||
dev->d3cold_allowed = true;
|
||||
|
||||
dev->d1_support = false;
|
||||
@ -4916,7 +5095,7 @@ static ssize_t pci_resource_alignment_store(struct bus_type *bus,
|
||||
return pci_set_resource_alignment_param(buf, count);
|
||||
}
|
||||
|
||||
BUS_ATTR(resource_alignment, 0644, pci_resource_alignment_show,
|
||||
static BUS_ATTR(resource_alignment, 0644, pci_resource_alignment_show,
|
||||
pci_resource_alignment_store);
|
||||
|
||||
static int __init pci_resource_alignment_sysfs_init(void)
|
||||
@ -5046,6 +5225,11 @@ static int __init pci_setup(char *str)
|
||||
pci_hotplug_io_size = memparse(str + 9, &str);
|
||||
} else if (!strncmp(str, "hpmemsize=", 10)) {
|
||||
pci_hotplug_mem_size = memparse(str + 10, &str);
|
||||
} else if (!strncmp(str, "hpbussize=", 10)) {
|
||||
pci_hotplug_bus_size =
|
||||
simple_strtoul(str + 10, &str, 0);
|
||||
if (pci_hotplug_bus_size > 0xff)
|
||||
pci_hotplug_bus_size = DEFAULT_HOTPLUG_BUS_SIZE;
|
||||
} else if (!strncmp(str, "pcie_bus_tune_off", 17)) {
|
||||
pcie_bus_config = PCIE_BUS_TUNE_OFF;
|
||||
} else if (!strncmp(str, "pcie_bus_safe", 13)) {
|
||||
|
@ -82,6 +82,8 @@ void pci_pm_init(struct pci_dev *dev);
|
||||
void pci_ea_init(struct pci_dev *dev);
|
||||
void pci_allocate_cap_save_buffers(struct pci_dev *dev);
|
||||
void pci_free_cap_save_buffers(struct pci_dev *dev);
|
||||
void pci_bridge_d3_device_changed(struct pci_dev *dev);
|
||||
void pci_bridge_d3_device_removed(struct pci_dev *dev);
|
||||
|
||||
static inline void pci_wakeup_event(struct pci_dev *dev)
|
||||
{
|
||||
@ -94,6 +96,15 @@ static inline bool pci_has_subordinate(struct pci_dev *pci_dev)
|
||||
return !!(pci_dev->subordinate);
|
||||
}
|
||||
|
||||
static inline bool pci_power_manageable(struct pci_dev *pci_dev)
|
||||
{
|
||||
/*
|
||||
* Currently we allow normal PCI devices and PCI bridges transition
|
||||
* into D3 if their bridge_d3 is set.
|
||||
*/
|
||||
return !pci_has_subordinate(pci_dev) || pci_dev->bridge_d3;
|
||||
}
|
||||
|
||||
struct pci_vpd_ops {
|
||||
ssize_t (*read)(struct pci_dev *dev, loff_t pos, size_t count, void *buf);
|
||||
ssize_t (*write)(struct pci_dev *dev, loff_t pos, size_t count, const void *buf);
|
||||
|
@ -83,7 +83,7 @@ config PCIE_PME
|
||||
depends on PCIEPORTBUS && PM
|
||||
|
||||
config PCIE_DPC
|
||||
tristate "PCIe Downstream Port Containment support"
|
||||
bool "PCIe Downstream Port Containment support"
|
||||
depends on PCIEPORTBUS
|
||||
default n
|
||||
help
|
||||
@ -92,6 +92,3 @@ config PCIE_DPC
|
||||
will be handled by the DPC driver. If your system doesn't
|
||||
have this capability or you do not want to use this feature,
|
||||
it is safe to answer N.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called pcie-dpc.
|
||||
|
@ -139,7 +139,7 @@ static void pcie_set_clkpm_nocheck(struct pcie_link_state *link, int enable)
|
||||
static void pcie_set_clkpm(struct pcie_link_state *link, int enable)
|
||||
{
|
||||
/* Don't enable Clock PM if the link is not Clock PM capable */
|
||||
if (!link->clkpm_capable && enable)
|
||||
if (!link->clkpm_capable)
|
||||
enable = 0;
|
||||
/* Need nothing if the specified equals to current state */
|
||||
if (link->clkpm_enabled == enable)
|
||||
|
@ -15,8 +15,8 @@
|
||||
|
||||
struct dpc_dev {
|
||||
struct pcie_device *dev;
|
||||
struct work_struct work;
|
||||
int cap_pos;
|
||||
struct work_struct work;
|
||||
int cap_pos;
|
||||
};
|
||||
|
||||
static void dpc_wait_link_inactive(struct pci_dev *pdev)
|
||||
@ -89,7 +89,7 @@ static int dpc_probe(struct pcie_device *dev)
|
||||
int status;
|
||||
u16 ctl, cap;
|
||||
|
||||
dpc = kzalloc(sizeof(*dpc), GFP_KERNEL);
|
||||
dpc = devm_kzalloc(&dev->device, sizeof(*dpc), GFP_KERNEL);
|
||||
if (!dpc)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -98,11 +98,12 @@ static int dpc_probe(struct pcie_device *dev)
|
||||
INIT_WORK(&dpc->work, interrupt_event_handler);
|
||||
set_service_data(dev, dpc);
|
||||
|
||||
status = request_irq(dev->irq, dpc_irq, IRQF_SHARED, "pcie-dpc", dpc);
|
||||
status = devm_request_irq(&dev->device, dev->irq, dpc_irq, IRQF_SHARED,
|
||||
"pcie-dpc", dpc);
|
||||
if (status) {
|
||||
dev_warn(&dev->device, "request IRQ%d failed: %d\n", dev->irq,
|
||||
status);
|
||||
goto out;
|
||||
return status;
|
||||
}
|
||||
|
||||
pci_read_config_word(pdev, dpc->cap_pos + PCI_EXP_DPC_CAP, &cap);
|
||||
@ -117,9 +118,6 @@ static int dpc_probe(struct pcie_device *dev)
|
||||
FLAG(cap, PCI_EXP_DPC_CAP_SW_TRIGGER), (cap >> 8) & 0xf,
|
||||
FLAG(cap, PCI_EXP_DPC_CAP_DL_ACTIVE));
|
||||
return status;
|
||||
out:
|
||||
kfree(dpc);
|
||||
return status;
|
||||
}
|
||||
|
||||
static void dpc_remove(struct pcie_device *dev)
|
||||
@ -131,14 +129,11 @@ static void dpc_remove(struct pcie_device *dev)
|
||||
pci_read_config_word(pdev, dpc->cap_pos + PCI_EXP_DPC_CTL, &ctl);
|
||||
ctl &= ~(PCI_EXP_DPC_CTL_EN_NONFATAL | PCI_EXP_DPC_CTL_INT_EN);
|
||||
pci_write_config_word(pdev, dpc->cap_pos + PCI_EXP_DPC_CTL, ctl);
|
||||
|
||||
free_irq(dev->irq, dpc);
|
||||
kfree(dpc);
|
||||
}
|
||||
|
||||
static struct pcie_port_service_driver dpcdriver = {
|
||||
.name = "dpc",
|
||||
.port_type = PCI_EXP_TYPE_ROOT_PORT | PCI_EXP_TYPE_DOWNSTREAM,
|
||||
.port_type = PCIE_ANY_PORT,
|
||||
.service = PCIE_PORT_SERVICE_DPC,
|
||||
.probe = dpc_probe,
|
||||
.remove = dpc_remove,
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/pcieport_if.h>
|
||||
@ -342,6 +343,8 @@ static int pcie_device_init(struct pci_dev *pdev, int service, int irq)
|
||||
return retval;
|
||||
}
|
||||
|
||||
pm_runtime_no_callbacks(device);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -93,6 +93,26 @@ static int pcie_port_resume_noirq(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcie_port_runtime_suspend(struct device *dev)
|
||||
{
|
||||
return to_pci_dev(dev)->bridge_d3 ? 0 : -EBUSY;
|
||||
}
|
||||
|
||||
static int pcie_port_runtime_resume(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcie_port_runtime_idle(struct device *dev)
|
||||
{
|
||||
/*
|
||||
* Assume the PCI core has set bridge_d3 whenever it thinks the port
|
||||
* should be good to go to D3. Everything else, including moving
|
||||
* the port to D3, is handled by the PCI core.
|
||||
*/
|
||||
return to_pci_dev(dev)->bridge_d3 ? 0 : -EBUSY;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops pcie_portdrv_pm_ops = {
|
||||
.suspend = pcie_port_device_suspend,
|
||||
.resume = pcie_port_device_resume,
|
||||
@ -101,6 +121,9 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = {
|
||||
.poweroff = pcie_port_device_suspend,
|
||||
.restore = pcie_port_device_resume,
|
||||
.resume_noirq = pcie_port_resume_noirq,
|
||||
.runtime_suspend = pcie_port_runtime_suspend,
|
||||
.runtime_resume = pcie_port_runtime_resume,
|
||||
.runtime_idle = pcie_port_runtime_idle,
|
||||
};
|
||||
|
||||
#define PCIE_PORTDRV_PM_OPS (&pcie_portdrv_pm_ops)
|
||||
@ -134,16 +157,39 @@ static int pcie_portdrv_probe(struct pci_dev *dev,
|
||||
return status;
|
||||
|
||||
pci_save_state(dev);
|
||||
|
||||
/*
|
||||
* D3cold may not work properly on some PCIe port, so disable
|
||||
* it by default.
|
||||
* Prevent runtime PM if the port is advertising support for PCIe
|
||||
* hotplug. Otherwise the BIOS hotplug SMI code might not be able
|
||||
* to enumerate devices behind this port properly (the port is
|
||||
* powered down preventing all config space accesses to the
|
||||
* subordinate devices). We can't be sure for native PCIe hotplug
|
||||
* either so prevent that as well.
|
||||
*/
|
||||
dev->d3cold_allowed = false;
|
||||
if (!dev->is_hotplug_bridge) {
|
||||
/*
|
||||
* Keep the port resumed 100ms to make sure things like
|
||||
* config space accesses from userspace (lspci) will not
|
||||
* cause the port to repeatedly suspend and resume.
|
||||
*/
|
||||
pm_runtime_set_autosuspend_delay(&dev->dev, 100);
|
||||
pm_runtime_use_autosuspend(&dev->dev);
|
||||
pm_runtime_mark_last_busy(&dev->dev);
|
||||
pm_runtime_put_autosuspend(&dev->dev);
|
||||
pm_runtime_allow(&dev->dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pcie_portdrv_remove(struct pci_dev *dev)
|
||||
{
|
||||
if (!dev->is_hotplug_bridge) {
|
||||
pm_runtime_forbid(&dev->dev);
|
||||
pm_runtime_get_noresume(&dev->dev);
|
||||
pm_runtime_dont_use_autosuspend(&dev->dev);
|
||||
}
|
||||
|
||||
pcie_port_device_remove(dev);
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <linux/aer.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include "pci.h"
|
||||
|
||||
#define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */
|
||||
@ -832,6 +833,12 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
|
||||
u8 primary, secondary, subordinate;
|
||||
int broken = 0;
|
||||
|
||||
/*
|
||||
* Make sure the bridge is powered on to be able to access config
|
||||
* space of devices below it.
|
||||
*/
|
||||
pm_runtime_get_sync(&dev->dev);
|
||||
|
||||
pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses);
|
||||
primary = buses & 0xFF;
|
||||
secondary = (buses >> 8) & 0xFF;
|
||||
@ -1012,6 +1019,8 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
|
||||
out:
|
||||
pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bctl);
|
||||
|
||||
pm_runtime_put(&dev->dev);
|
||||
|
||||
return max;
|
||||
}
|
||||
EXPORT_SYMBOL(pci_scan_bridge);
|
||||
@ -2076,6 +2085,15 @@ unsigned int pci_scan_child_bus(struct pci_bus *bus)
|
||||
max = pci_scan_bridge(bus, dev, max, pass);
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure a hotplug bridge has at least the minimum requested
|
||||
* number of buses.
|
||||
*/
|
||||
if (bus->self && bus->self->is_hotplug_bridge && pci_hotplug_bus_size) {
|
||||
if (max - bus->busn_res.start < pci_hotplug_bus_size - 1)
|
||||
max = bus->busn_res.start + pci_hotplug_bus_size - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* We've scanned the bus and so we know all about what's on
|
||||
* the other side of any bridges that may be on this bus plus
|
||||
|
@ -3189,13 +3189,15 @@ static void quirk_no_bus_reset(struct pci_dev *dev)
|
||||
}
|
||||
|
||||
/*
|
||||
* Atheros AR93xx chips do not behave after a bus reset. The device will
|
||||
* throw a Link Down error on AER-capable systems and regardless of AER,
|
||||
* config space of the device is never accessible again and typically
|
||||
* causes the system to hang or reset when access is attempted.
|
||||
* Some Atheros AR9xxx and QCA988x chips do not behave after a bus reset.
|
||||
* The device will throw a Link Down error on AER-capable systems and
|
||||
* regardless of AER, config space of the device is never accessible again
|
||||
* and typically causes the system to hang or reset when access is attempted.
|
||||
* http://www.spinics.net/lists/linux-pci/msg34797.html
|
||||
*/
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0030, quirk_no_bus_reset);
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0032, quirk_no_bus_reset);
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x003c, quirk_no_bus_reset);
|
||||
|
||||
static void quirk_no_pm_reset(struct pci_dev *dev)
|
||||
{
|
||||
@ -3711,6 +3713,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9172,
|
||||
/* https://bugzilla.kernel.org/show_bug.cgi?id=42679#c59 */
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x917a,
|
||||
quirk_dma_func1_alias);
|
||||
/* https://bugzilla.kernel.org/show_bug.cgi?id=42679#c78 */
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9182,
|
||||
quirk_dma_func1_alias);
|
||||
/* https://bugzilla.kernel.org/show_bug.cgi?id=42679#c46 */
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x91a0,
|
||||
quirk_dma_func1_alias);
|
||||
@ -3747,6 +3752,9 @@ static const struct pci_device_id fixed_dma_alias_tbl[] = {
|
||||
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x0285,
|
||||
PCI_VENDOR_ID_ADAPTEC2, 0x02bb), /* Adaptec 3405 */
|
||||
.driver_data = PCI_DEVFN(1, 0) },
|
||||
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x0285,
|
||||
PCI_VENDOR_ID_ADAPTEC2, 0x02bc), /* Adaptec 3805 */
|
||||
.driver_data = PCI_DEVFN(1, 0) },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
@ -4087,6 +4095,7 @@ static const struct pci_dev_acs_enabled {
|
||||
{ PCI_VENDOR_ID_AMD, 0x7809, pci_quirk_amd_sb_acs },
|
||||
{ PCI_VENDOR_ID_SOLARFLARE, 0x0903, pci_quirk_mf_endpoint_acs },
|
||||
{ PCI_VENDOR_ID_SOLARFLARE, 0x0923, pci_quirk_mf_endpoint_acs },
|
||||
{ PCI_VENDOR_ID_SOLARFLARE, 0x0A03, pci_quirk_mf_endpoint_acs },
|
||||
{ PCI_VENDOR_ID_INTEL, 0x10C6, pci_quirk_mf_endpoint_acs },
|
||||
{ PCI_VENDOR_ID_INTEL, 0x10DB, pci_quirk_mf_endpoint_acs },
|
||||
{ PCI_VENDOR_ID_INTEL, 0x10DD, pci_quirk_mf_endpoint_acs },
|
||||
|
@ -96,6 +96,8 @@ static void pci_remove_bus_device(struct pci_dev *dev)
|
||||
dev->subordinate = NULL;
|
||||
}
|
||||
|
||||
pci_bridge_d3_device_removed(dev);
|
||||
|
||||
pci_destroy_dev(dev);
|
||||
}
|
||||
|
||||
|
@ -382,7 +382,7 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
|
||||
* need to have the registers polled during D3, so avoid D3cold.
|
||||
*/
|
||||
if (xhci->quirks & XHCI_COMP_MODE_QUIRK)
|
||||
pdev->no_d3cold = true;
|
||||
pci_d3cold_disable(pdev);
|
||||
|
||||
if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
|
||||
xhci_pme_quirk(hcd);
|
||||
|
@ -101,6 +101,10 @@ enum {
|
||||
DEVICE_COUNT_RESOURCE = PCI_NUM_RESOURCES,
|
||||
};
|
||||
|
||||
/*
|
||||
* pci_power_t values must match the bits in the Capabilities PME_Support
|
||||
* and Control/Status PowerState fields in the Power Management capability.
|
||||
*/
|
||||
typedef int __bitwise pci_power_t;
|
||||
|
||||
#define PCI_D0 ((pci_power_t __force) 0)
|
||||
@ -116,7 +120,7 @@ extern const char *pci_power_names[];
|
||||
|
||||
static inline const char *pci_power_name(pci_power_t state)
|
||||
{
|
||||
return pci_power_names[1 + (int) state];
|
||||
return pci_power_names[1 + (__force int) state];
|
||||
}
|
||||
|
||||
#define PCI_PM_D2_DELAY 200
|
||||
@ -294,6 +298,7 @@ struct pci_dev {
|
||||
unsigned int d2_support:1; /* Low power state D2 is supported */
|
||||
unsigned int no_d1d2:1; /* D1 and D2 are forbidden */
|
||||
unsigned int no_d3cold:1; /* D3cold is forbidden */
|
||||
unsigned int bridge_d3:1; /* Allow D3 for bridge */
|
||||
unsigned int d3cold_allowed:1; /* D3cold is allowed by user */
|
||||
unsigned int mmio_always_on:1; /* disallow turning off io/mem
|
||||
decoding during bar sizing */
|
||||
@ -1083,6 +1088,8 @@ int pci_back_from_sleep(struct pci_dev *dev);
|
||||
bool pci_dev_run_wake(struct pci_dev *dev);
|
||||
bool pci_check_pme_status(struct pci_dev *dev);
|
||||
void pci_pme_wakeup_bus(struct pci_bus *bus);
|
||||
void pci_d3cold_enable(struct pci_dev *dev);
|
||||
void pci_d3cold_disable(struct pci_dev *dev);
|
||||
|
||||
static inline int pci_enable_wake(struct pci_dev *dev, pci_power_t state,
|
||||
bool enable)
|
||||
@ -1708,6 +1715,7 @@ extern u8 pci_cache_line_size;
|
||||
|
||||
extern unsigned long pci_hotplug_io_size;
|
||||
extern unsigned long pci_hotplug_mem_size;
|
||||
extern unsigned long pci_hotplug_bus_size;
|
||||
|
||||
/* Architecture-specific versions may override these (weak) */
|
||||
void pcibios_disable_device(struct pci_dev *dev);
|
||||
|
Loading…
Reference in New Issue
Block a user