From: Felipe Balbi felipe.balbi@linux.intel.com
mainline inclusion from mainline-v4.20-rc1 commit d6112f8def514e019658bcc9b57d53acdb71ca3f category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I47H3V CVE: NA
--------------------------------
commit d6112f8def514e019658bcc9b57d53acdb71ca3f upstream.
PCIe r4.0, sec 7.5.1.1.4 defines a new bit in the Status Register:
Immediate Readiness – This optional bit, when Set, indicates the Function is guaranteed to be ready to successfully complete valid configuration accesses at any time following any reset that the host is capable of issuing Configuration Requests to this Function.
When this bit is Set, for accesses to this Function, software is exempt from all requirements to delay configuration accesses following any type of reset, including but not limited to the timing requirements defined in Section 6.6.
This means that all delays after a Conventional or Function Reset can be skipped.
This patch reads such bit and caches its value in a flag inside struct pci_dev to be checked later if we should delay or can skip delays after a reset. While at that, also move the explicit msleep(100) call from pcie_flr() and pci_af_flr() to pci_dev_wait().
Change-Id: I1c0f7772895b3ccf89092661f95e460f44ba4a2d Signed-off-by: Felipe Balbi felipe.balbi@linux.intel.com [bhelgaas: rename PCI_STATUS_IMMEDIATE to PCI_STATUS_IMM_READY] Signed-off-by: Bjorn Helgaas bhelgaas@google.com Signed-off-by: Lin Wang lin.x.wang@intel.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com Reviewed-by: Xiongfeng Wang wangxiongfeng2@huawei.com --- drivers/pci/pci.c | 13 ++++++++++++- include/linux/pci.h | 1 + include/uapi/linux/pci_regs.h | 1 + 3 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index f6e3a813caf1..09a19caa32eb 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1009,7 +1009,7 @@ static void __pci_start_power_transition(struct pci_dev *dev, pci_power_t state) * because have already delayed for the bridge. */ if (dev->runtime_d3cold) { - if (dev->d3cold_delay) + if (dev->d3cold_delay && !dev->imm_ready) msleep(dev->d3cold_delay); /* * When powering on a bridge from D3cold, the @@ -2708,6 +2708,7 @@ EXPORT_SYMBOL_GPL(pci_d3cold_disable); void pci_pm_init(struct pci_dev *dev) { int pm; + u16 status; u16 pmc;
pm_runtime_forbid(&dev->dev); @@ -2770,6 +2771,10 @@ void pci_pm_init(struct pci_dev *dev) /* Disable the PME# generation functionality */ pci_pme_active(dev, false); } + + pci_read_config_word(dev, PCI_STATUS, &status); + if (status & PCI_STATUS_IMM_READY) + dev->imm_ready = 1; }
static unsigned long pci_ea_flags(struct pci_dev *dev, u8 prop) @@ -4444,6 +4449,9 @@ int pcie_flr(struct pci_dev *dev)
pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR);
+ if (dev->imm_ready) + return 0; + /* * Per PCIe r4.0, sec 6.6.2, a device must complete an FLR within * 100ms, but may silently discard requests while the FLR is in @@ -4485,6 +4493,9 @@ static int pci_af_flr(struct pci_dev *dev, int probe)
pci_write_config_byte(dev, pos + PCI_AF_CTRL, PCI_AF_CTRL_FLR);
+ if (dev->imm_ready) + return 0; + /* * Per Advanced Capabilities for Conventional PCI ECN, 13 April 2006, * updated 27 July 2006; a device must complete an FLR within diff --git a/include/linux/pci.h b/include/linux/pci.h index c97de5c8bc35..4988b58628a2 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -326,6 +326,7 @@ struct pci_dev { pci_power_t current_state; /* Current operating state. In ACPI, this is D0-D3, D0 being fully functional, and D3 being off. */ + unsigned int imm_ready:1; /* Supports Immediate Readiness */ u8 pm_cap; /* PM capability offset */ unsigned int pme_support:5; /* Bitmask of states from which PME# can be generated */ diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h index 662bac7a677a..6050817163a6 100644 --- a/include/uapi/linux/pci_regs.h +++ b/include/uapi/linux/pci_regs.h @@ -52,6 +52,7 @@ #define PCI_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */
#define PCI_STATUS 0x06 /* 16 bits */ +#define PCI_STATUS_IMM_READY 0x01 /* Immediate Readiness */ #define PCI_STATUS_INTERRUPT 0x08 /* Interrupt status */ #define PCI_STATUS_CAP_LIST 0x10 /* Support Capability List */ #define PCI_STATUS_66MHZ 0x20 /* Support 66 MHz PCI 2.1 bus */