From: Greg Kroah-Hartman Date: Wed, 22 Sep 2021 15:52:08 +0000 (+0200) Subject: 5.4-stable patches X-Git-Tag: v4.4.285~66 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=27dbb0d62befdcc3a657934436501dc3352db30e;p=thirdparty%2Fkernel%2Fstable-queue.git 5.4-stable patches added patches: pci-aardvark-fix-reporting-crs-value.patch pci-aardvark-indicate-error-in-val-when-config-read-fails.patch pci-pci-bridge-emul-add-pcie-root-capabilities-register.patch pci-pci-bridge-emul-fix-big-endian-support.patch --- diff --git a/queue-5.4/pci-aardvark-fix-reporting-crs-value.patch b/queue-5.4/pci-aardvark-fix-reporting-crs-value.patch new file mode 100644 index 00000000000..cd5bb496b3c --- /dev/null +++ b/queue-5.4/pci-aardvark-fix-reporting-crs-value.patch @@ -0,0 +1,177 @@ +From 43f5c77bcbd27cce70bf33c2b86d6726ce95dd66 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Thu, 22 Jul 2021 16:40:41 +0200 +Subject: PCI: aardvark: Fix reporting CRS value +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +commit 43f5c77bcbd27cce70bf33c2b86d6726ce95dd66 upstream. + +Set CRSVIS flag in emulated root PCI bridge to indicate support for +Completion Retry Status. + +Add check for CRSSVE flag from root PCI brige when issuing Configuration +Read Request via PIO to correctly returns fabricated CRS value as it is +required by PCIe spec. + +Link: https://lore.kernel.org/r/20210722144041.12661-5-pali@kernel.org +Fixes: 8a3ebd8de328 ("PCI: aardvark: Implement emulated root PCI bridge config space") +Signed-off-by: Pali Rohár +Signed-off-by: Lorenzo Pieralisi +Cc: stable@vger.kernel.org # e0d9d30b7354 ("PCI: pci-bridge-emul: Fix big-endian support") +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/controller/pci-aardvark.c | 67 +++++++++++++++++++++++++++++++--- + 1 file changed, 63 insertions(+), 4 deletions(-) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -188,6 +188,8 @@ + + #define MSI_IRQ_NUM 32 + ++#define CFG_RD_CRS_VAL 0xffff0001 ++ + struct advk_pcie { + struct platform_device *pdev; + void __iomem *base; +@@ -365,7 +367,7 @@ static void advk_pcie_setup_hw(struct ad + advk_writel(pcie, reg, PCIE_CORE_CMD_STATUS_REG); + } + +-static int advk_pcie_check_pio_status(struct advk_pcie *pcie, u32 *val) ++static int advk_pcie_check_pio_status(struct advk_pcie *pcie, bool allow_crs, u32 *val) + { + struct device *dev = &pcie->pdev->dev; + u32 reg; +@@ -407,9 +409,30 @@ static int advk_pcie_check_pio_status(st + strcomp_status = "UR"; + break; + case PIO_COMPLETION_STATUS_CRS: ++ if (allow_crs && val) { ++ /* PCIe r4.0, sec 2.3.2, says: ++ * If CRS Software Visibility is enabled: ++ * For a Configuration Read Request that includes both ++ * bytes of the Vendor ID field of a device Function's ++ * Configuration Space Header, the Root Complex must ++ * complete the Request to the host by returning a ++ * read-data value of 0001h for the Vendor ID field and ++ * all '1's for any additional bytes included in the ++ * request. ++ * ++ * So CRS in this case is not an error status. ++ */ ++ *val = CFG_RD_CRS_VAL; ++ strcomp_status = NULL; ++ break; ++ } + /* PCIe r4.0, sec 2.3.2, says: + * If CRS Software Visibility is not enabled, the Root Complex + * must re-issue the Configuration Request as a new Request. ++ * If CRS Software Visibility is enabled: For a Configuration ++ * Write Request or for any other Configuration Read Request, ++ * the Root Complex must re-issue the Configuration Request as ++ * a new Request. + * A Root Complex implementation may choose to limit the number + * of Configuration Request/CRS Completion Status loops before + * determining that something is wrong with the target of the +@@ -478,6 +501,7 @@ advk_pci_bridge_emul_pcie_conf_read(stru + case PCI_EXP_RTCTL: { + u32 val = advk_readl(pcie, PCIE_ISR0_MASK_REG); + *value = (val & PCIE_MSG_PM_PME_MASK) ? 0 : PCI_EXP_RTCTL_PMEIE; ++ *value |= PCI_EXP_RTCAP_CRSVIS << 16; + return PCI_BRIDGE_EMUL_HANDLED; + } + +@@ -559,6 +583,7 @@ static struct pci_bridge_emul_ops advk_p + static int advk_sw_pci_bridge_init(struct advk_pcie *pcie) + { + struct pci_bridge_emul *bridge = &pcie->bridge; ++ int ret; + + bridge->conf.vendor = advk_readl(pcie, PCIE_CORE_DEV_ID_REG) & 0xffff; + bridge->conf.device = advk_readl(pcie, PCIE_CORE_DEV_ID_REG) >> 16; +@@ -580,7 +605,15 @@ static int advk_sw_pci_bridge_init(struc + bridge->data = pcie; + bridge->ops = &advk_pci_bridge_emul_ops; + +- return pci_bridge_emul_init(bridge, 0); ++ /* PCIe config space can be initialized after pci_bridge_emul_init() */ ++ ret = pci_bridge_emul_init(bridge, 0); ++ if (ret < 0) ++ return ret; ++ ++ /* Indicates supports for Completion Retry Status */ ++ bridge->pcie_conf.rootcap = cpu_to_le16(PCI_EXP_RTCAP_CRSVIS); ++ ++ return 0; + } + + static bool advk_pcie_valid_device(struct advk_pcie *pcie, struct pci_bus *bus, +@@ -625,6 +658,7 @@ static int advk_pcie_rd_conf(struct pci_ + int where, int size, u32 *val) + { + struct advk_pcie *pcie = bus->sysdata; ++ bool allow_crs; + u32 reg; + int ret; + +@@ -637,7 +671,24 @@ static int advk_pcie_rd_conf(struct pci_ + return pci_bridge_emul_conf_read(&pcie->bridge, where, + size, val); + ++ /* ++ * Completion Retry Status is possible to return only when reading all ++ * 4 bytes from PCI_VENDOR_ID and PCI_DEVICE_ID registers at once and ++ * CRSSVE flag on Root Bridge is enabled. ++ */ ++ allow_crs = (where == PCI_VENDOR_ID) && (size == 4) && ++ (le16_to_cpu(pcie->bridge.pcie_conf.rootctl) & ++ PCI_EXP_RTCTL_CRSSVE); ++ + if (advk_pcie_pio_is_running(pcie)) { ++ /* ++ * If it is possible return Completion Retry Status so caller ++ * tries to issue the request again instead of failing. ++ */ ++ if (allow_crs) { ++ *val = CFG_RD_CRS_VAL; ++ return PCIBIOS_SUCCESSFUL; ++ } + *val = 0xffffffff; + return PCIBIOS_SET_FAILED; + } +@@ -665,12 +716,20 @@ static int advk_pcie_rd_conf(struct pci_ + + ret = advk_pcie_wait_pio(pcie); + if (ret < 0) { ++ /* ++ * If it is possible return Completion Retry Status so caller ++ * tries to issue the request again instead of failing. ++ */ ++ if (allow_crs) { ++ *val = CFG_RD_CRS_VAL; ++ return PCIBIOS_SUCCESSFUL; ++ } + *val = 0xffffffff; + return PCIBIOS_SET_FAILED; + } + + /* Check PIO status and get the read result */ +- ret = advk_pcie_check_pio_status(pcie, val); ++ ret = advk_pcie_check_pio_status(pcie, allow_crs, val); + if (ret < 0) { + *val = 0xffffffff; + return PCIBIOS_SET_FAILED; +@@ -739,7 +798,7 @@ static int advk_pcie_wr_conf(struct pci_ + if (ret < 0) + return PCIBIOS_SET_FAILED; + +- ret = advk_pcie_check_pio_status(pcie, NULL); ++ ret = advk_pcie_check_pio_status(pcie, false, NULL); + if (ret < 0) + return PCIBIOS_SET_FAILED; + diff --git a/queue-5.4/pci-aardvark-indicate-error-in-val-when-config-read-fails.patch b/queue-5.4/pci-aardvark-indicate-error-in-val-when-config-read-fails.patch new file mode 100644 index 00000000000..2fefd9a00b2 --- /dev/null +++ b/queue-5.4/pci-aardvark-indicate-error-in-val-when-config-read-fails.patch @@ -0,0 +1,43 @@ +From b1bd5714472cc72e14409f5659b154c765a76c65 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Mon, 1 Jun 2020 15:03:15 +0200 +Subject: PCI: aardvark: Indicate error in 'val' when config read fails +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +commit b1bd5714472cc72e14409f5659b154c765a76c65 upstream. + +Most callers of config read do not check for return value. But most of the +ones that do, checks for error indication in 'val' variable. + +This patch updates error handling in advk_pcie_rd_conf() function. If PIO +transfer fails then 'val' variable is set to 0xffffffff which indicates +failture. + +Link: https://lore.kernel.org/r/20200528162604.GA323482@bjorn-Precision-5520 +Link: https://lore.kernel.org/r/20200601130315.18895-1-pali@kernel.org +Reported-by: Bjorn Helgaas +Signed-off-by: Pali Rohár +Signed-off-by: Lorenzo Pieralisi +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/controller/pci-aardvark.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -664,8 +664,10 @@ static int advk_pcie_rd_conf(struct pci_ + advk_writel(pcie, 1, PIO_START); + + ret = advk_pcie_wait_pio(pcie); +- if (ret < 0) ++ if (ret < 0) { ++ *val = 0xffffffff; + return PCIBIOS_SET_FAILED; ++ } + + /* Check PIO status and get the read result */ + ret = advk_pcie_check_pio_status(pcie, val); diff --git a/queue-5.4/pci-pci-bridge-emul-add-pcie-root-capabilities-register.patch b/queue-5.4/pci-pci-bridge-emul-add-pcie-root-capabilities-register.patch new file mode 100644 index 00000000000..6960b87aba9 --- /dev/null +++ b/queue-5.4/pci-pci-bridge-emul-add-pcie-root-capabilities-register.patch @@ -0,0 +1,35 @@ +From e902bb7c24a7099d0eb0eb4cba06f2d91e9299f3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Thu, 22 Jul 2021 16:40:40 +0200 +Subject: PCI: pci-bridge-emul: Add PCIe Root Capabilities Register +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +commit e902bb7c24a7099d0eb0eb4cba06f2d91e9299f3 upstream. + +The 16-bit Root Capabilities register is at offset 0x1e in the PCIe +Capability. Rename current 'rsvd' struct member to 'rootcap'. + +Link: https://lore.kernel.org/r/20210722144041.12661-4-pali@kernel.org +Signed-off-by: Pali Rohár +Signed-off-by: Lorenzo Pieralisi +Reviewed-by: Marek Behún +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/pci-bridge-emul.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/pci/pci-bridge-emul.h ++++ b/drivers/pci/pci-bridge-emul.h +@@ -54,7 +54,7 @@ struct pci_bridge_emul_pcie_conf { + __le16 slotctl; + __le16 slotsta; + __le16 rootctl; +- __le16 rsvd; ++ __le16 rootcap; + __le32 rootsta; + __le32 devcap2; + __le16 devctl2; diff --git a/queue-5.4/pci-pci-bridge-emul-fix-big-endian-support.patch b/queue-5.4/pci-pci-bridge-emul-fix-big-endian-support.patch new file mode 100644 index 00000000000..cfb4490ba99 --- /dev/null +++ b/queue-5.4/pci-pci-bridge-emul-fix-big-endian-support.patch @@ -0,0 +1,222 @@ +From e0d9d30b73548fbfe5c024ed630169bdc9a08aee Mon Sep 17 00:00:00 2001 +From: Grzegorz Jaszczyk +Date: Tue, 16 Jul 2019 14:13:46 +0200 +Subject: PCI: pci-bridge-emul: Fix big-endian support + +From: Grzegorz Jaszczyk + +commit e0d9d30b73548fbfe5c024ed630169bdc9a08aee upstream. + +Perform conversion to little-endian before every write to configuration +space and convert it back to CPU endianness on reads. + +Additionally, initialise every multiple byte field of config space with +the cpu_to_le* macro, which is required since the structure describing +config space of emulated bridge assumes little-endian convention. + +Signed-off-by: Grzegorz Jaszczyk +Signed-off-by: Lorenzo Pieralisi +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/pci-bridge-emul.c | 25 +++++++------ + drivers/pci/pci-bridge-emul.h | 78 +++++++++++++++++++++--------------------- + 2 files changed, 52 insertions(+), 51 deletions(-) + +--- a/drivers/pci/pci-bridge-emul.c ++++ b/drivers/pci/pci-bridge-emul.c +@@ -270,10 +270,10 @@ static const struct pci_bridge_reg_behav + int pci_bridge_emul_init(struct pci_bridge_emul *bridge, + unsigned int flags) + { +- bridge->conf.class_revision |= PCI_CLASS_BRIDGE_PCI << 16; ++ bridge->conf.class_revision |= cpu_to_le32(PCI_CLASS_BRIDGE_PCI << 16); + bridge->conf.header_type = PCI_HEADER_TYPE_BRIDGE; + bridge->conf.cache_line_size = 0x10; +- bridge->conf.status = PCI_STATUS_CAP_LIST; ++ bridge->conf.status = cpu_to_le16(PCI_STATUS_CAP_LIST); + bridge->pci_regs_behavior = kmemdup(pci_regs_behavior, + sizeof(pci_regs_behavior), + GFP_KERNEL); +@@ -284,8 +284,9 @@ int pci_bridge_emul_init(struct pci_brid + bridge->conf.capabilities_pointer = PCI_CAP_PCIE_START; + bridge->pcie_conf.cap_id = PCI_CAP_ID_EXP; + /* Set PCIe v2, root port, slot support */ +- bridge->pcie_conf.cap = PCI_EXP_TYPE_ROOT_PORT << 4 | 2 | +- PCI_EXP_FLAGS_SLOT; ++ bridge->pcie_conf.cap = ++ cpu_to_le16(PCI_EXP_TYPE_ROOT_PORT << 4 | 2 | ++ PCI_EXP_FLAGS_SLOT); + bridge->pcie_cap_regs_behavior = + kmemdup(pcie_cap_regs_behavior, + sizeof(pcie_cap_regs_behavior), +@@ -327,7 +328,7 @@ int pci_bridge_emul_conf_read(struct pci + int reg = where & ~3; + pci_bridge_emul_read_status_t (*read_op)(struct pci_bridge_emul *bridge, + int reg, u32 *value); +- u32 *cfgspace; ++ __le32 *cfgspace; + const struct pci_bridge_reg_behavior *behavior; + + if (bridge->has_pcie && reg >= PCI_CAP_PCIE_END) { +@@ -343,11 +344,11 @@ int pci_bridge_emul_conf_read(struct pci + if (bridge->has_pcie && reg >= PCI_CAP_PCIE_START) { + reg -= PCI_CAP_PCIE_START; + read_op = bridge->ops->read_pcie; +- cfgspace = (u32 *) &bridge->pcie_conf; ++ cfgspace = (__le32 *) &bridge->pcie_conf; + behavior = bridge->pcie_cap_regs_behavior; + } else { + read_op = bridge->ops->read_base; +- cfgspace = (u32 *) &bridge->conf; ++ cfgspace = (__le32 *) &bridge->conf; + behavior = bridge->pci_regs_behavior; + } + +@@ -357,7 +358,7 @@ int pci_bridge_emul_conf_read(struct pci + ret = PCI_BRIDGE_EMUL_NOT_HANDLED; + + if (ret == PCI_BRIDGE_EMUL_NOT_HANDLED) +- *value = cfgspace[reg / 4]; ++ *value = le32_to_cpu(cfgspace[reg / 4]); + + /* + * Make sure we never return any reserved bit with a value +@@ -387,7 +388,7 @@ int pci_bridge_emul_conf_write(struct pc + int mask, ret, old, new, shift; + void (*write_op)(struct pci_bridge_emul *bridge, int reg, + u32 old, u32 new, u32 mask); +- u32 *cfgspace; ++ __le32 *cfgspace; + const struct pci_bridge_reg_behavior *behavior; + + if (bridge->has_pcie && reg >= PCI_CAP_PCIE_END) +@@ -414,11 +415,11 @@ int pci_bridge_emul_conf_write(struct pc + if (bridge->has_pcie && reg >= PCI_CAP_PCIE_START) { + reg -= PCI_CAP_PCIE_START; + write_op = bridge->ops->write_pcie; +- cfgspace = (u32 *) &bridge->pcie_conf; ++ cfgspace = (__le32 *) &bridge->pcie_conf; + behavior = bridge->pcie_cap_regs_behavior; + } else { + write_op = bridge->ops->write_base; +- cfgspace = (u32 *) &bridge->conf; ++ cfgspace = (__le32 *) &bridge->conf; + behavior = bridge->pci_regs_behavior; + } + +@@ -431,7 +432,7 @@ int pci_bridge_emul_conf_write(struct pc + /* Clear the W1C bits */ + new &= ~((value << shift) & (behavior[reg / 4].w1c & mask)); + +- cfgspace[reg / 4] = new; ++ cfgspace[reg / 4] = cpu_to_le32(new); + + if (write_op) + write_op(bridge, reg, old, new, mask); +--- a/drivers/pci/pci-bridge-emul.h ++++ b/drivers/pci/pci-bridge-emul.h +@@ -6,65 +6,65 @@ + + /* PCI configuration space of a PCI-to-PCI bridge. */ + struct pci_bridge_emul_conf { +- u16 vendor; +- u16 device; +- u16 command; +- u16 status; +- u32 class_revision; ++ __le16 vendor; ++ __le16 device; ++ __le16 command; ++ __le16 status; ++ __le32 class_revision; + u8 cache_line_size; + u8 latency_timer; + u8 header_type; + u8 bist; +- u32 bar[2]; ++ __le32 bar[2]; + u8 primary_bus; + u8 secondary_bus; + u8 subordinate_bus; + u8 secondary_latency_timer; + u8 iobase; + u8 iolimit; +- u16 secondary_status; +- u16 membase; +- u16 memlimit; +- u16 pref_mem_base; +- u16 pref_mem_limit; +- u32 prefbaseupper; +- u32 preflimitupper; +- u16 iobaseupper; +- u16 iolimitupper; ++ __le16 secondary_status; ++ __le16 membase; ++ __le16 memlimit; ++ __le16 pref_mem_base; ++ __le16 pref_mem_limit; ++ __le32 prefbaseupper; ++ __le32 preflimitupper; ++ __le16 iobaseupper; ++ __le16 iolimitupper; + u8 capabilities_pointer; + u8 reserve[3]; +- u32 romaddr; ++ __le32 romaddr; + u8 intline; + u8 intpin; +- u16 bridgectrl; ++ __le16 bridgectrl; + }; + + /* PCI configuration space of the PCIe capabilities */ + struct pci_bridge_emul_pcie_conf { + u8 cap_id; + u8 next; +- u16 cap; +- u32 devcap; +- u16 devctl; +- u16 devsta; +- u32 lnkcap; +- u16 lnkctl; +- u16 lnksta; +- u32 slotcap; +- u16 slotctl; +- u16 slotsta; +- u16 rootctl; +- u16 rsvd; +- u32 rootsta; +- u32 devcap2; +- u16 devctl2; +- u16 devsta2; +- u32 lnkcap2; +- u16 lnkctl2; +- u16 lnksta2; +- u32 slotcap2; +- u16 slotctl2; +- u16 slotsta2; ++ __le16 cap; ++ __le32 devcap; ++ __le16 devctl; ++ __le16 devsta; ++ __le32 lnkcap; ++ __le16 lnkctl; ++ __le16 lnksta; ++ __le32 slotcap; ++ __le16 slotctl; ++ __le16 slotsta; ++ __le16 rootctl; ++ __le16 rsvd; ++ __le32 rootsta; ++ __le32 devcap2; ++ __le16 devctl2; ++ __le16 devsta2; ++ __le32 lnkcap2; ++ __le16 lnkctl2; ++ __le16 lnksta2; ++ __le32 slotcap2; ++ __le16 slotctl2; ++ __le16 slotsta2; + }; + + struct pci_bridge_emul; diff --git a/queue-5.4/series b/queue-5.4/series index e69de29bb2d..eeea807c498 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -0,0 +1,4 @@ +pci-pci-bridge-emul-fix-big-endian-support.patch +pci-aardvark-indicate-error-in-val-when-config-read-fails.patch +pci-pci-bridge-emul-add-pcie-root-capabilities-register.patch +pci-aardvark-fix-reporting-crs-value.patch