Commit a00c74c1 authored by Bjorn Helgaas's avatar Bjorn Helgaas

Merge branches 'pci/aspm', 'pci/dpc', 'pci/hotplug', 'pci/misc', 'pci/msi',...

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
...@@ -3016,6 +3016,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted. ...@@ -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 hpmemsize=nn[KMG] The fixed amount of bus space which is
reserved for hotplug bridge's memory window. reserved for hotplug bridge's memory window.
Default size is 2 megabytes. 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 realloc= Enable/disable reallocating PCI bridge resources
if allocations done by BIOS are too small to if allocations done by BIOS are too small to
accommodate resources required by all child accommodate resources required by all child
...@@ -3047,6 +3050,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted. ...@@ -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 compat Treat PCIe ports as PCI-to-PCI bridges, disable the PCIe
ports driver. 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: pcie_pme= [PCIE,PM] Native PCIe PME signaling options:
nomsi Do not use MSI for native PCIe PME signaling (this makes nomsi Do not use MSI for native PCIe PME signaling (this makes
all PCIe root ports use INTx for all services). all PCIe root ports use INTx for all services).
......
...@@ -8678,6 +8678,7 @@ L: linux-pci@vger.kernel.org ...@@ -8678,6 +8678,7 @@ L: linux-pci@vger.kernel.org
Q: http://patchwork.ozlabs.org/project/linux-pci/list/ Q: http://patchwork.ozlabs.org/project/linux-pci/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git
S: Supported S: Supported
F: Documentation/devicetree/bindings/pci/
F: Documentation/PCI/ F: Documentation/PCI/
F: drivers/pci/ F: drivers/pci/
F: include/linux/pci* F: include/linux/pci*
......
...@@ -715,7 +715,7 @@ config ARCH_VIRT ...@@ -715,7 +715,7 @@ config ARCH_VIRT
depends on ARCH_MULTI_V7 depends on ARCH_MULTI_V7
select ARM_AMBA select ARM_AMBA
select ARM_GIC select ARM_GIC
select ARM_GIC_V2M if PCI_MSI select ARM_GIC_V2M if PCI
select ARM_GIC_V3 select ARM_GIC_V3
select ARM_PSCI select ARM_PSCI
select HAVE_ARM_ARCH_TIMER select HAVE_ARM_ARCH_TIMER
......
...@@ -21,9 +21,9 @@ config ARM64 ...@@ -21,9 +21,9 @@ config ARM64
select ARM_ARCH_TIMER select ARM_ARCH_TIMER
select ARM_GIC select ARM_GIC
select AUDIT_ARCH_COMPAT_GENERIC 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
select ARM_GIC_V3_ITS if PCI_MSI select ARM_GIC_V3_ITS if PCI
select ARM_PSCI_FW select ARM_PSCI_FW
select BUILDTIME_EXTABLE_SORT select BUILDTIME_EXTABLE_SORT
select CLONE_BACKWARDS select CLONE_BACKWARDS
......
...@@ -133,7 +133,7 @@ static void pcibios_fixup_device_resources(struct pci_dev *dev) ...@@ -133,7 +133,7 @@ static void pcibios_fixup_device_resources(struct pci_dev *dev)
if (pci_probe & PCI_NOASSIGN_BARS) { if (pci_probe & PCI_NOASSIGN_BARS) {
/* /*
* If the BIOS did not assign the BAR, zero out the * 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 * it later on in pci_assign_unassigned_resources
*/ */
for (bar = 0; bar <= PCI_STD_RESOURCE_END; bar++) { for (bar = 0; bar <= PCI_STD_RESOURCE_END; bar++) {
......
...@@ -15,9 +15,9 @@ config ARM_GIC_MAX_NR ...@@ -15,9 +15,9 @@ config ARM_GIC_MAX_NR
config ARM_GIC_V2M config ARM_GIC_V2M
bool bool
depends on ARM_GIC depends on PCI
depends on PCI && PCI_MSI select ARM_GIC
select PCI_MSI_IRQ_DOMAIN select PCI_MSI
config GIC_NON_BANKED config GIC_NON_BANKED
bool bool
...@@ -31,7 +31,8 @@ config ARM_GIC_V3 ...@@ -31,7 +31,8 @@ config ARM_GIC_V3
config ARM_GIC_V3_ITS config ARM_GIC_V3_ITS
bool bool
select PCI_MSI_IRQ_DOMAIN depends on PCI
depends on PCI_MSI
config ARM_NVIC config ARM_NVIC
bool bool
...@@ -56,13 +57,13 @@ config ARM_VIC_NR ...@@ -56,13 +57,13 @@ config ARM_VIC_NR
config ARMADA_370_XP_IRQ config ARMADA_370_XP_IRQ
bool bool
select GENERIC_IRQ_CHIP select GENERIC_IRQ_CHIP
select PCI_MSI_IRQ_DOMAIN if PCI_MSI select PCI_MSI if PCI
config ALPINE_MSI config ALPINE_MSI
bool bool
depends on PCI && PCI_MSI depends on PCI
select PCI_MSI
select GENERIC_IRQ_CHIP select GENERIC_IRQ_CHIP
select PCI_MSI_IRQ_DOMAIN
config ATMEL_AIC_IRQ config ATMEL_AIC_IRQ
bool bool
...@@ -111,7 +112,6 @@ config HISILICON_IRQ_MBIGEN ...@@ -111,7 +112,6 @@ config HISILICON_IRQ_MBIGEN
bool bool
select ARM_GIC_V3 select ARM_GIC_V3
select ARM_GIC_V3_ITS select ARM_GIC_V3_ITS
select GENERIC_MSI_IRQ_DOMAIN
config IMGPDC_IRQ config IMGPDC_IRQ
bool bool
...@@ -244,12 +244,10 @@ config IRQ_MXS ...@@ -244,12 +244,10 @@ config IRQ_MXS
config MVEBU_ODMI config MVEBU_ODMI
bool bool
select GENERIC_MSI_IRQ_DOMAIN
config LS_SCFG_MSI config LS_SCFG_MSI
def_bool y if SOC_LS1021A || ARCH_LAYERSCAPE def_bool y if SOC_LS1021A || ARCH_LAYERSCAPE
depends on PCI && PCI_MSI depends on PCI && PCI_MSI
select PCI_MSI_IRQ_DOMAIN
config PARTITION_PERCPU config PARTITION_PERCPU
bool bool
......
...@@ -25,7 +25,7 @@ config PCI_MSI ...@@ -25,7 +25,7 @@ config PCI_MSI
If you don't know what to do here, say Y. If you don't know what to do here, say Y.
config PCI_MSI_IRQ_DOMAIN config PCI_MSI_IRQ_DOMAIN
bool def_bool ARM || ARM64 || X86
depends on PCI_MSI depends on PCI_MSI
select GENERIC_MSI_IRQ_DOMAIN select GENERIC_MSI_IRQ_DOMAIN
......
...@@ -291,6 +291,7 @@ void pci_bus_add_device(struct pci_dev *dev) ...@@ -291,6 +291,7 @@ void pci_bus_add_device(struct pci_dev *dev)
pci_fixup_device(pci_fixup_final, dev); pci_fixup_device(pci_fixup_final, dev);
pci_create_sysfs_dev_files(dev); pci_create_sysfs_dev_files(dev);
pci_proc_attach_device(dev); pci_proc_attach_device(dev);
pci_bridge_d3_device_changed(dev);
dev->match_driver = true; dev->match_driver = true;
retval = device_attach(&dev->dev); retval = device_attach(&dev->dev);
......
...@@ -3,8 +3,9 @@ menu "PCI host controller drivers" ...@@ -3,8 +3,9 @@ menu "PCI host controller drivers"
config PCI_DRA7XX config PCI_DRA7XX
bool "TI DRA7xx PCIe controller" bool "TI DRA7xx PCIe controller"
select PCIE_DW
depends on OF && HAS_IOMEM && TI_PIPE3 depends on OF && HAS_IOMEM && TI_PIPE3
depends on PCI_MSI_IRQ_DOMAIN
select PCIE_DW
help help
Enables support for the PCIe controller in the DRA7xx SoC. There Enables support for the PCIe controller in the DRA7xx SoC. There
are two instances of PCIe controller in DRA7xx. This controller can are two instances of PCIe controller in DRA7xx. This controller can
...@@ -20,7 +21,7 @@ config PCI_MVEBU ...@@ -20,7 +21,7 @@ config PCI_MVEBU
config PCIE_XILINX_NWL config PCIE_XILINX_NWL
bool "NWL PCIe Core" bool "NWL PCIe Core"
depends on ARCH_ZYNQMP depends on ARCH_ZYNQMP
select PCI_MSI_IRQ_DOMAIN if PCI_MSI depends on PCI_MSI_IRQ_DOMAIN
help help
Say 'Y' here if you want kernel support for Xilinx Say 'Y' here if you want kernel support for Xilinx
NWL PCIe controller. The controller can act as Root Port NWL PCIe controller. The controller can act as Root Port
...@@ -29,6 +30,7 @@ config PCIE_XILINX_NWL ...@@ -29,6 +30,7 @@ config PCIE_XILINX_NWL
config PCIE_DW_PLAT config PCIE_DW_PLAT
bool "Platform bus based DesignWare PCIe Controller" bool "Platform bus based DesignWare PCIe Controller"
depends on PCI_MSI_IRQ_DOMAIN
select PCIE_DW select PCIE_DW
---help--- ---help---
This selects the DesignWare PCIe controller support. Select this if This selects the DesignWare PCIe controller support. Select this if
...@@ -40,16 +42,19 @@ config PCIE_DW_PLAT ...@@ -40,16 +42,19 @@ config PCIE_DW_PLAT
config PCIE_DW config PCIE_DW
bool bool
depends on PCI_MSI_IRQ_DOMAIN
config PCI_EXYNOS config PCI_EXYNOS
bool "Samsung Exynos PCIe controller" bool "Samsung Exynos PCIe controller"
depends on SOC_EXYNOS5440 depends on SOC_EXYNOS5440
depends on PCI_MSI_IRQ_DOMAIN
select PCIEPORTBUS select PCIEPORTBUS
select PCIE_DW select PCIE_DW
config PCI_IMX6 config PCI_IMX6
bool "Freescale i.MX6 PCIe controller" bool "Freescale i.MX6 PCIe controller"
depends on SOC_IMX6Q depends on SOC_IMX6Q
depends on PCI_MSI_IRQ_DOMAIN
select PCIEPORTBUS select PCIEPORTBUS
select PCIE_DW select PCIE_DW
...@@ -72,8 +77,7 @@ config PCI_RCAR_GEN2 ...@@ -72,8 +77,7 @@ config PCI_RCAR_GEN2
config PCIE_RCAR config PCIE_RCAR
bool "Renesas R-Car PCIe controller" bool "Renesas R-Car PCIe controller"
depends on ARCH_RENESAS || (ARM && COMPILE_TEST) depends on ARCH_RENESAS || (ARM && COMPILE_TEST)
select PCI_MSI depends on PCI_MSI_IRQ_DOMAIN
select PCI_MSI_IRQ_DOMAIN
help help
Say Y here if you want PCIe controller support on R-Car SoCs. Say Y here if you want PCIe controller support on R-Car SoCs.
...@@ -92,6 +96,7 @@ config PCI_HOST_GENERIC ...@@ -92,6 +96,7 @@ config PCI_HOST_GENERIC
config PCIE_SPEAR13XX config PCIE_SPEAR13XX
bool "STMicroelectronics SPEAr PCIe controller" bool "STMicroelectronics SPEAr PCIe controller"
depends on ARCH_SPEAR13XX depends on ARCH_SPEAR13XX
depends on PCI_MSI_IRQ_DOMAIN
select PCIEPORTBUS select PCIEPORTBUS
select PCIE_DW select PCIE_DW
help help
...@@ -100,6 +105,7 @@ config PCIE_SPEAR13XX ...@@ -100,6 +105,7 @@ config PCIE_SPEAR13XX
config PCI_KEYSTONE config PCI_KEYSTONE
bool "TI Keystone PCIe controller" bool "TI Keystone PCIe controller"
depends on ARCH_KEYSTONE depends on ARCH_KEYSTONE
depends on PCI_MSI_IRQ_DOMAIN
select PCIE_DW select PCIE_DW
select PCIEPORTBUS select PCIEPORTBUS
help help
...@@ -120,7 +126,6 @@ config PCI_XGENE ...@@ -120,7 +126,6 @@ config PCI_XGENE
depends on ARCH_XGENE depends on ARCH_XGENE
depends on OF depends on OF
select PCIEPORTBUS select PCIEPORTBUS
select PCI_MSI_IRQ_DOMAIN if PCI_MSI
help help
Say Y here if you want internal PCI support on APM X-Gene SoC. 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 There are 5 internal PCIe ports available. Each port is GEN3 capable
...@@ -128,7 +133,8 @@ config PCI_XGENE ...@@ -128,7 +133,8 @@ config PCI_XGENE
config PCI_XGENE_MSI config PCI_XGENE_MSI
bool "X-Gene v1 PCIe MSI feature" 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 default y
help help
Say Y here if you want PCIe MSI support for the APM X-Gene v1 SoC. Say Y here if you want PCIe MSI support for the APM X-Gene v1 SoC.
...@@ -137,6 +143,7 @@ config PCI_XGENE_MSI ...@@ -137,6 +143,7 @@ config PCI_XGENE_MSI
config PCI_LAYERSCAPE config PCI_LAYERSCAPE
bool "Freescale Layerscape PCIe controller" bool "Freescale Layerscape PCIe controller"
depends on OF && (ARM || ARCH_LAYERSCAPE) depends on OF && (ARM || ARCH_LAYERSCAPE)
depends on PCI_MSI_IRQ_DOMAIN
select PCIE_DW select PCIE_DW
select MFD_SYSCON select MFD_SYSCON
help help
...@@ -177,8 +184,7 @@ config PCIE_IPROC_BCMA ...@@ -177,8 +184,7 @@ config PCIE_IPROC_BCMA
config PCIE_IPROC_MSI config PCIE_IPROC_MSI
bool "Broadcom iProc PCIe MSI support" bool "Broadcom iProc PCIe MSI support"
depends on PCIE_IPROC_PLATFORM || PCIE_IPROC_BCMA depends on PCIE_IPROC_PLATFORM || PCIE_IPROC_BCMA
depends on PCI_MSI depends on PCI_MSI_IRQ_DOMAIN
select PCI_MSI_IRQ_DOMAIN
default ARCH_BCM_IPROC default ARCH_BCM_IPROC
help help
Say Y here if you want to enable MSI support for Broadcom's iProc Say Y here if you want to enable MSI support for Broadcom's iProc
...@@ -195,8 +201,8 @@ config PCIE_ALTERA ...@@ -195,8 +201,8 @@ config PCIE_ALTERA
config PCIE_ALTERA_MSI config PCIE_ALTERA_MSI
bool "Altera PCIe MSI feature" bool "Altera PCIe MSI feature"
depends on PCIE_ALTERA && PCI_MSI depends on PCIE_ALTERA
select PCI_MSI_IRQ_DOMAIN depends on PCI_MSI_IRQ_DOMAIN
help help
Say Y here if you want PCIe MSI support for the Altera FPGA. Say Y here if you want PCIe MSI support for the Altera FPGA.
This MSI driver supports Altera MSI to GIC controller IP. This MSI driver supports Altera MSI to GIC controller IP.
...@@ -204,6 +210,7 @@ config PCIE_ALTERA_MSI ...@@ -204,6 +210,7 @@ config PCIE_ALTERA_MSI
config PCI_HISI config PCI_HISI
depends on OF && ARM64 depends on OF && ARM64
bool "HiSilicon Hip05 and Hip06 SoCs PCIe controllers" bool "HiSilicon Hip05 and Hip06 SoCs PCIe controllers"
depends on PCI_MSI_IRQ_DOMAIN
select PCIEPORTBUS select PCIEPORTBUS
select PCIE_DW select PCIE_DW
help help
...@@ -213,6 +220,7 @@ config PCI_HISI ...@@ -213,6 +220,7 @@ config PCI_HISI
config PCIE_QCOM config PCIE_QCOM
bool "Qualcomm PCIe controller" bool "Qualcomm PCIe controller"
depends on ARCH_QCOM && OF depends on ARCH_QCOM && OF
depends on PCI_MSI_IRQ_DOMAIN
select PCIE_DW select PCIE_DW
select PCIEPORTBUS select PCIEPORTBUS
help help
...@@ -237,6 +245,7 @@ config PCI_HOST_THUNDER_ECAM ...@@ -237,6 +245,7 @@ config PCI_HOST_THUNDER_ECAM
config PCIE_ARMADA_8K config PCIE_ARMADA_8K
bool "Marvell Armada-8K PCIe controller" bool "Marvell Armada-8K PCIe controller"
depends on ARCH_MVEBU depends on ARCH_MVEBU
depends on PCI_MSI_IRQ_DOMAIN
select PCIE_DW select PCIE_DW
select PCIEPORTBUS select PCIEPORTBUS
help help
......
...@@ -675,6 +675,8 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge) ...@@ -675,6 +675,8 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge)
if (bridge->is_going_away) if (bridge->is_going_away)
return; return;
pm_runtime_get_sync(&bridge->pci_dev->dev);
list_for_each_entry(slot, &bridge->slots, node) { list_for_each_entry(slot, &bridge->slots, node) {
struct pci_bus *bus = slot->bus; struct pci_bus *bus = slot->bus;
struct pci_dev *dev, *tmp; struct pci_dev *dev, *tmp;
...@@ -694,6 +696,8 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge) ...@@ -694,6 +696,8 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge)
disable_slot(slot); disable_slot(slot);
} }
} }
pm_runtime_put(&bridge->pci_dev->dev);
} }
/* /*
......
...@@ -546,6 +546,10 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) ...@@ -546,6 +546,10 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
u8 present; u8 present;
bool link; 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 * In order to guarantee that all interrupt events are
* serviced, we need to re-inspect Slot Status register after * serviced, we need to re-inspect Slot Status register after
......
...@@ -777,7 +777,7 @@ static int pci_pm_suspend_noirq(struct device *dev) ...@@ -777,7 +777,7 @@ static int pci_pm_suspend_noirq(struct device *dev)
if (!pci_dev->state_saved) { if (!pci_dev->state_saved) {
pci_save_state(pci_dev); pci_save_state(pci_dev);
if (!pci_has_subordinate(pci_dev)) if (pci_power_manageable(pci_dev))
pci_prepare_to_sleep(pci_dev); pci_prepare_to_sleep(pci_dev);
} }
...@@ -1144,7 +1144,6 @@ static int pci_pm_runtime_suspend(struct device *dev) ...@@ -1144,7 +1144,6 @@ static int pci_pm_runtime_suspend(struct device *dev)
return -ENOSYS; return -ENOSYS;
pci_dev->state_saved = false; pci_dev->state_saved = false;
pci_dev->no_d3cold = false;
error = pm->runtime_suspend(dev); error = pm->runtime_suspend(dev);
if (error) { if (error) {
/* /*
...@@ -1161,8 +1160,6 @@ static int pci_pm_runtime_suspend(struct device *dev) ...@@ -1161,8 +1160,6 @@ static int pci_pm_runtime_suspend(struct device *dev)
return error; return error;
} }
if (!pci_dev->d3cold_allowed)
pci_dev->no_d3cold = true;
pci_fixup_device(pci_fixup_suspend, pci_dev); pci_fixup_device(pci_fixup_suspend, pci_dev);
......
...@@ -406,6 +406,11 @@ static ssize_t d3cold_allowed_store(struct device *dev, ...@@ -406,6 +406,11 @@ static ssize_t d3cold_allowed_store(struct device *dev,
return -EINVAL; return -EINVAL;
pdev->d3cold_allowed = !!val; pdev->d3cold_allowed = !!val;
if (pdev->d3cold_allowed)
pci_d3cold_enable(pdev);
else
pci_d3cold_disable(pdev);
pm_runtime_resume(dev); pm_runtime_resume(dev);
return count; return count;
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/dmi.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_pci.h> #include <linux/of_pci.h>
...@@ -28,6 +29,7 @@ ...@@ -28,6 +29,7 @@
#include <linux/pci_hotplug.h> #include <linux/pci_hotplug.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <asm/setup.h> #include <asm/setup.h>
#include <asm/dma.h>
#include <linux/aer.h> #include <linux/aer.h>
#include "pci.h" #include "pci.h"
...@@ -83,6 +85,9 @@ unsigned long pci_cardbus_mem_size = DEFAULT_CARDBUS_MEM_SIZE; ...@@ -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_io_size = DEFAULT_HOTPLUG_IO_SIZE;
unsigned long pci_hotplug_mem_size = DEFAULT_HOTPLUG_MEM_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; enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_DEFAULT;
/* /*
...@@ -103,6 +108,21 @@ unsigned int pcibios_max_latency = 255; ...@@ -103,6 +108,21 @@ unsigned int pcibios_max_latency = 255;
/* If set, the PCIe ARI capability will not be used. */ /* If set, the PCIe ARI capability will not be used. */
static bool pcie_ari_disabled; 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 * pci_bus_max_busnr - returns maximum PCI bus number of given bus' children
* @bus: pointer to PCI bus structure to search * @bus: pointer to PCI bus structure to search
...@@ -2157,6 +2177,164 @@ void pci_config_pm_runtime_put(struct pci_dev *pdev) ...@@ -2157,6 +2177,164 @@ void pci_config_pm_runtime_put(struct pci_dev *pdev)
pm_runtime_put_sync(parent); 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 * pci_pm_init - Initialize PM functions of given PCI device
* @dev: PCI device to handle. * @dev: PCI device to handle.
...@@ -2191,6 +2369,7 @@ void pci_pm_init(struct pci_dev *dev) ...@@ -2191,6 +2369,7 @@ void pci_pm_init(struct pci_dev *dev)
dev->pm_cap = pm; dev->pm_cap = pm;
dev->d3_delay = PCI_PM_D3_WAIT; dev->d3_delay = PCI_PM_D3_WAIT;
dev->d3cold_delay = PCI_PM_D3COLD_WAIT; dev->d3cold_delay = PCI_PM_D3COLD_WAIT;
dev->bridge_d3 = pci_bridge_d3_possible(dev);
dev->d3cold_allowed = true; dev->d3cold_allowed = true;
dev->d1_support = false; dev->d1_support = false;
...@@ -4916,7 +5095,7 @@ static ssize_t pci_resource_alignment_store(struct bus_type *bus, ...@@ -4916,7 +5095,7 @@ static ssize_t pci_resource_alignment_store(struct bus_type *bus,
return pci_set_resource_alignment_param(buf, count); 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); pci_resource_alignment_store);
static int __init pci_resource_alignment_sysfs_init(void) static int __init pci_resource_alignment_sysfs_init(void)
...@@ -5046,6 +5225,11 @@ static int __init pci_setup(char *str) ...@@ -5046,6 +5225,11 @@ static int __init pci_setup(char *str)
pci_hotplug_io_size = memparse(str + 9, &str); pci_hotplug_io_size = memparse(str + 9, &str);
} else if (!strncmp(str, "hpmemsize=", 10)) { } else if (!strncmp(str, "hpmemsize=", 10)) {
pci_hotplug_mem_size = memparse(str + 10, &str); 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)) { } else if (!strncmp(str, "pcie_bus_tune_off", 17)) {
pcie_bus_config = PCIE_BUS_TUNE_OFF; pcie_bus_config = PCIE_BUS_TUNE_OFF;
} else if (!strncmp(str, "pcie_bus_safe", 13)) { } else if (!strncmp(str, "pcie_bus_safe", 13)) {
......
...@@ -82,6 +82,8 @@ void pci_pm_init(struct pci_dev *dev); ...@@ -82,6 +82,8 @@ void pci_pm_init(struct pci_dev *dev);
void pci_ea_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_allocate_cap_save_buffers(struct pci_dev *dev);
void pci_free_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) 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) ...@@ -94,6 +96,15 @@ static inline bool pci_has_subordinate(struct pci_dev *pci_dev)
return !!(pci_dev->subordinate); 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 { struct pci_vpd_ops {
ssize_t (*read)(struct pci_dev *dev, loff_t pos, size_t count, void *buf); 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); ssize_t (*write)(struct pci_dev *dev, loff_t pos, size_t count, const void *buf);
......
...@@ -83,7 +83,7 @@ config PCIE_PME ...@@ -83,7 +83,7 @@ config PCIE_PME
depends on PCIEPORTBUS && PM depends on PCIEPORTBUS && PM
config PCIE_DPC config PCIE_DPC
tristate "PCIe Downstream Port Containment support" bool "PCIe Downstream Port Containment support"
depends on PCIEPORTBUS depends on PCIEPORTBUS
default n default n
help help
...@@ -92,6 +92,3 @@ config PCIE_DPC ...@@ -92,6 +92,3 @@ config PCIE_DPC
will be handled by the DPC driver. If your system doesn't will be handled by the DPC driver. If your system doesn't
have this capability or you do not want to use this feature, have this capability or you do not want to use this feature,
it is safe to answer N. 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) ...@@ -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) 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 */ /* Don't enable Clock PM if the link is not Clock PM capable */
if (!link->clkpm_capable && enable) if (!link->clkpm_capable)
enable = 0; enable = 0;
/* Need nothing if the specified equals to current state */ /* Need nothing if the specified equals to current state */
if (link->clkpm_enabled == enable) if (link->clkpm_enabled == enable)
......
...@@ -15,8 +15,8 @@ ...@@ -15,8 +15,8 @@
struct dpc_dev { struct dpc_dev {
struct pcie_device *dev; struct pcie_device *dev;
struct work_struct work; struct work_struct work;
int cap_pos; int cap_pos;
}; };
static void dpc_wait_link_inactive(struct pci_dev *pdev) static void dpc_wait_link_inactive(struct pci_dev *pdev)
...@@ -89,7 +89,7 @@ static int dpc_probe(struct pcie_device *dev) ...@@ -89,7 +89,7 @@ static int dpc_probe(struct pcie_device *dev)
int status; int status;
u16 ctl, cap; u16 ctl, cap;
dpc = kzalloc(sizeof(*dpc), GFP_KERNEL); dpc = devm_kzalloc(&dev->device, sizeof(*dpc), GFP_KERNEL);
if (!dpc) if (!dpc)
return -ENOMEM; return -ENOMEM;
...@@ -98,11 +98,12 @@ static int dpc_probe(struct pcie_device *dev) ...@@ -98,11 +98,12 @@ static int dpc_probe(struct pcie_device *dev)
INIT_WORK(&dpc->work, interrupt_event_handler); INIT_WORK(&dpc->work, interrupt_event_handler);
set_service_data(dev, dpc); 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) { if (status) {
dev_warn(&dev->device, "request IRQ%d failed: %d\n", dev->irq, dev_warn(&dev->device, "request IRQ%d failed: %d\n", dev->irq,
status); status);
goto out; return status;
} }
pci_read_config_word(pdev, dpc->cap_pos + PCI_EXP_DPC_CAP, &cap); 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) ...@@ -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_SW_TRIGGER), (cap >> 8) & 0xf,
FLAG(cap, PCI_EXP_DPC_CAP_DL_ACTIVE)); FLAG(cap, PCI_EXP_DPC_CAP_DL_ACTIVE));
return status; return status;
out:
kfree(dpc);
return status;
} }
static void dpc_remove(struct pcie_device *dev) static void dpc_remove(struct pcie_device *dev)
...@@ -131,14 +129,11 @@ 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); 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); 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); 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 = { static struct pcie_port_service_driver dpcdriver = {
.name = "dpc", .name = "dpc",
.port_type = PCI_EXP_TYPE_ROOT_PORT | PCI_EXP_TYPE_DOWNSTREAM, .port_type = PCIE_ANY_PORT,
.service = PCIE_PORT_SERVICE_DPC, .service = PCIE_PORT_SERVICE_DPC,
.probe = dpc_probe, .probe = dpc_probe,
.remove = dpc_remove, .remove = dpc_remove,
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/pcieport_if.h> #include <linux/pcieport_if.h>
...@@ -342,6 +343,8 @@ static int pcie_device_init(struct pci_dev *pdev, int service, int irq) ...@@ -342,6 +343,8 @@ static int pcie_device_init(struct pci_dev *pdev, int service, int irq)
return retval; return retval;
} }
pm_runtime_no_callbacks(device);
return 0; return 0;
} }
......
...@@ -93,6 +93,26 @@ static int pcie_port_resume_noirq(struct device *dev) ...@@ -93,6 +93,26 @@ static int pcie_port_resume_noirq(struct device *dev)
return 0; 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 = { static const struct dev_pm_ops pcie_portdrv_pm_ops = {
.suspend = pcie_port_device_suspend, .suspend = pcie_port_device_suspend,
.resume = pcie_port_device_resume, .resume = pcie_port_device_resume,
...@@ -101,6 +121,9 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = { ...@@ -101,6 +121,9 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = {
.poweroff = pcie_port_device_suspend, .poweroff = pcie_port_device_suspend,
.restore = pcie_port_device_resume, .restore = pcie_port_device_resume,
.resume_noirq = pcie_port_resume_noirq, .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) #define PCIE_PORTDRV_PM_OPS (&pcie_portdrv_pm_ops)
...@@ -134,16 +157,39 @@ static int pcie_portdrv_probe(struct pci_dev *dev, ...@@ -134,16 +157,39 @@ static int pcie_portdrv_probe(struct pci_dev *dev,
return status; return status;
pci_save_state(dev); pci_save_state(dev);
/* /*
* D3cold may not work properly on some PCIe port, so disable * Prevent runtime PM if the port is advertising support for PCIe
* it by default. * 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; return 0;
} }
static void pcie_portdrv_remove(struct pci_dev *dev) 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); pcie_port_device_remove(dev);
} }
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/aer.h> #include <linux/aer.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/irqdomain.h> #include <linux/irqdomain.h>
#include <linux/pm_runtime.h>
#include "pci.h" #include "pci.h"
#define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */ #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) ...@@ -832,6 +833,12 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
u8 primary, secondary, subordinate; u8 primary, secondary, subordinate;
int broken = 0; 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); pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses);
primary = buses & 0xFF; primary = buses & 0xFF;
secondary = (buses >> 8) & 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) ...@@ -1012,6 +1019,8 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
out: out:
pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bctl); pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bctl);
pm_runtime_put(&dev->dev);
return max; return max;
} }
EXPORT_SYMBOL(pci_scan_bridge); EXPORT_SYMBOL(pci_scan_bridge);
...@@ -2076,6 +2085,15 @@ unsigned int pci_scan_child_bus(struct pci_bus *bus) ...@@ -2076,6 +2085,15 @@ unsigned int pci_scan_child_bus(struct pci_bus *bus)
max = pci_scan_bridge(bus, dev, max, pass); 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 * 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 * 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) ...@@ -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 * Some Atheros AR9xxx and QCA988x chips do not behave after a bus reset.
* throw a Link Down error on AER-capable systems and regardless of AER, * The device will throw a Link Down error on AER-capable systems and
* config space of the device is never accessible again and typically * regardless of AER, config space of the device is never accessible again
* causes the system to hang or reset when access is attempted. * and typically causes the system to hang or reset when access is attempted.
* http://www.spinics.net/lists/linux-pci/msg34797.html * 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, 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) static void quirk_no_pm_reset(struct pci_dev *dev)
{ {
...@@ -3711,6 +3713,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9172, ...@@ -3711,6 +3713,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9172,
/* https://bugzilla.kernel.org/show_bug.cgi?id=42679#c59 */ /* https://bugzilla.kernel.org/show_bug.cgi?id=42679#c59 */
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x917a, DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x917a,
quirk_dma_func1_alias); 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 */ /* https://bugzilla.kernel.org/show_bug.cgi?id=42679#c46 */
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x91a0, DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x91a0,
quirk_dma_func1_alias); quirk_dma_func1_alias);
...@@ -3747,6 +3752,9 @@ static const struct pci_device_id fixed_dma_alias_tbl[] = { ...@@ -3747,6 +3752,9 @@ static const struct pci_device_id fixed_dma_alias_tbl[] = {
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x0285, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x0285,
PCI_VENDOR_ID_ADAPTEC2, 0x02bb), /* Adaptec 3405 */ PCI_VENDOR_ID_ADAPTEC2, 0x02bb), /* Adaptec 3405 */
.driver_data = PCI_DEVFN(1, 0) }, .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 } { 0 }
}; };
...@@ -4087,6 +4095,7 @@ static const struct pci_dev_acs_enabled { ...@@ -4087,6 +4095,7 @@ static const struct pci_dev_acs_enabled {
{ PCI_VENDOR_ID_AMD, 0x7809, pci_quirk_amd_sb_acs }, { PCI_VENDOR_ID_AMD, 0x7809, pci_quirk_amd_sb_acs },
{ PCI_VENDOR_ID_SOLARFLARE, 0x0903, pci_quirk_mf_endpoint_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, 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, 0x10C6, pci_quirk_mf_endpoint_acs },
{ PCI_VENDOR_ID_INTEL, 0x10DB, 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 }, { PCI_VENDOR_ID_INTEL, 0x10DD, pci_quirk_mf_endpoint_acs },
......
...@@ -96,6 +96,8 @@ static void pci_remove_bus_device(struct pci_dev *dev) ...@@ -96,6 +96,8 @@ static void pci_remove_bus_device(struct pci_dev *dev)
dev->subordinate = NULL; dev->subordinate = NULL;
} }
pci_bridge_d3_device_removed(dev);
pci_destroy_dev(dev); pci_destroy_dev(dev);
} }
......
...@@ -382,7 +382,7 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) ...@@ -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. * need to have the registers polled during D3, so avoid D3cold.
*/ */
if (xhci->quirks & XHCI_COMP_MODE_QUIRK) if (xhci->quirks & XHCI_COMP_MODE_QUIRK)
pdev->no_d3cold = true; pci_d3cold_disable(pdev);
if (xhci->quirks & XHCI_PME_STUCK_QUIRK) if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
xhci_pme_quirk(hcd); xhci_pme_quirk(hcd);
......
...@@ -101,6 +101,10 @@ enum { ...@@ -101,6 +101,10 @@ enum {
DEVICE_COUNT_RESOURCE = PCI_NUM_RESOURCES, 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; typedef int __bitwise pci_power_t;
#define PCI_D0 ((pci_power_t __force) 0) #define PCI_D0 ((pci_power_t __force) 0)
...@@ -116,7 +120,7 @@ extern const char *pci_power_names[]; ...@@ -116,7 +120,7 @@ extern const char *pci_power_names[];
static inline const char *pci_power_name(pci_power_t state) 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 #define PCI_PM_D2_DELAY 200
...@@ -294,6 +298,7 @@ struct pci_dev { ...@@ -294,6 +298,7 @@ struct pci_dev {
unsigned int d2_support:1; /* Low power state D2 is supported */ unsigned int d2_support:1; /* Low power state D2 is supported */
unsigned int no_d1d2:1; /* D1 and D2 are forbidden */ unsigned int no_d1d2:1; /* D1 and D2 are forbidden */
unsigned int no_d3cold:1; /* D3cold is 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 d3cold_allowed:1; /* D3cold is allowed by user */
unsigned int mmio_always_on:1; /* disallow turning off io/mem unsigned int mmio_always_on:1; /* disallow turning off io/mem
decoding during bar sizing */ decoding during bar sizing */
...@@ -1083,6 +1088,8 @@ int pci_back_from_sleep(struct pci_dev *dev); ...@@ -1083,6 +1088,8 @@ int pci_back_from_sleep(struct pci_dev *dev);
bool pci_dev_run_wake(struct pci_dev *dev); bool pci_dev_run_wake(struct pci_dev *dev);
bool pci_check_pme_status(struct pci_dev *dev); bool pci_check_pme_status(struct pci_dev *dev);
void pci_pme_wakeup_bus(struct pci_bus *bus); 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, static inline int pci_enable_wake(struct pci_dev *dev, pci_power_t state,
bool enable) bool enable)
...@@ -1708,6 +1715,7 @@ extern u8 pci_cache_line_size; ...@@ -1708,6 +1715,7 @@ extern u8 pci_cache_line_size;
extern unsigned long pci_hotplug_io_size; extern unsigned long pci_hotplug_io_size;
extern unsigned long pci_hotplug_mem_size; extern unsigned long pci_hotplug_mem_size;
extern unsigned long pci_hotplug_bus_size;
/* Architecture-specific versions may override these (weak) */ /* Architecture-specific versions may override these (weak) */
void pcibios_disable_device(struct pci_dev *dev); void pcibios_disable_device(struct pci_dev *dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment