]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 22 Sep 2021 15:52:08 +0000 (17:52 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 22 Sep 2021 15:52:08 +0000 (17:52 +0200)
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

queue-5.4/pci-aardvark-fix-reporting-crs-value.patch [new file with mode: 0644]
queue-5.4/pci-aardvark-indicate-error-in-val-when-config-read-fails.patch [new file with mode: 0644]
queue-5.4/pci-pci-bridge-emul-add-pcie-root-capabilities-register.patch [new file with mode: 0644]
queue-5.4/pci-pci-bridge-emul-fix-big-endian-support.patch [new file with mode: 0644]
queue-5.4/series

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 (file)
index 0000000..cd5bb49
--- /dev/null
@@ -0,0 +1,177 @@
+From 43f5c77bcbd27cce70bf33c2b86d6726ce95dd66 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
+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 <pali@kernel.org>
+
+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 <pali@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Cc: stable@vger.kernel.org # e0d9d30b7354 ("PCI: pci-bridge-emul: Fix big-endian support")
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..2fefd9a
--- /dev/null
@@ -0,0 +1,43 @@
+From b1bd5714472cc72e14409f5659b154c765a76c65 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
+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 <pali@kernel.org>
+
+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 <helgaas@kernel.org>
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..6960b87
--- /dev/null
@@ -0,0 +1,35 @@
+From e902bb7c24a7099d0eb0eb4cba06f2d91e9299f3 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
+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 <pali@kernel.org>
+
+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 <pali@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Reviewed-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..cfb4490
--- /dev/null
@@ -0,0 +1,222 @@
+From e0d9d30b73548fbfe5c024ed630169bdc9a08aee Mon Sep 17 00:00:00 2001
+From: Grzegorz Jaszczyk <jaz@semihalf.com>
+Date: Tue, 16 Jul 2019 14:13:46 +0200
+Subject: PCI: pci-bridge-emul: Fix big-endian support
+
+From: Grzegorz Jaszczyk <jaz@semihalf.com>
+
+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 <jaz@semihalf.com>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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;
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..eeea807c4986e7dc40581026e84212786d326c69 100644 (file)
@@ -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