]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 28 Nov 2021 12:01:09 +0000 (13:01 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 28 Nov 2021 12:01:09 +0000 (13:01 +0100)
added patches:
pci-aardvark-deduplicate-code-in-advk_pcie_rd_conf.patch
pci-aardvark-fix-link-training.patch
pci-aardvark-implement-re-issuing-config-requests-on-crs-response.patch
pci-aardvark-simplify-initialization-of-rootcap-on-virtual-bridge.patch
pci-aardvark-update-comment-about-disabling-link-training.patch

queue-5.10/pci-aardvark-deduplicate-code-in-advk_pcie_rd_conf.patch [new file with mode: 0644]
queue-5.10/pci-aardvark-fix-link-training.patch [new file with mode: 0644]
queue-5.10/pci-aardvark-implement-re-issuing-config-requests-on-crs-response.patch [new file with mode: 0644]
queue-5.10/pci-aardvark-simplify-initialization-of-rootcap-on-virtual-bridge.patch [new file with mode: 0644]
queue-5.10/pci-aardvark-update-comment-about-disabling-link-training.patch [new file with mode: 0644]
queue-5.10/series

diff --git a/queue-5.10/pci-aardvark-deduplicate-code-in-advk_pcie_rd_conf.patch b/queue-5.10/pci-aardvark-deduplicate-code-in-advk_pcie_rd_conf.patch
new file mode 100644 (file)
index 0000000..2f10090
--- /dev/null
@@ -0,0 +1,98 @@
+From 67cb2a4c93499c2c22704998fd1fd2bc35194d8e Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marek=20Beh=C3=BAn?= <kabel@kernel.org>
+Date: Tue, 5 Oct 2021 20:09:47 +0200
+Subject: PCI: aardvark: Deduplicate code in advk_pcie_rd_conf()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Marek Behún <kabel@kernel.org>
+
+commit 67cb2a4c93499c2c22704998fd1fd2bc35194d8e upstream.
+
+Avoid code repetition in advk_pcie_rd_conf() by handling errors with
+goto jump, as is customary in kernel.
+
+Link: https://lore.kernel.org/r/20211005180952.6812-9-kabel@kernel.org
+Fixes: 43f5c77bcbd2 ("PCI: aardvark: Fix reporting CRS value")
+Signed-off-by: Marek Behún <kabel@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 |   48 ++++++++++++++--------------------
+ 1 file changed, 20 insertions(+), 28 deletions(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -1090,18 +1090,8 @@ static int advk_pcie_rd_conf(struct pci_
+                   (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;
+-      }
++      if (advk_pcie_pio_is_running(pcie))
++              goto try_crs;
+       /* Program the control register */
+       reg = advk_readl(pcie, PIO_CTRL);
+@@ -1125,25 +1115,13 @@ static int advk_pcie_rd_conf(struct pci_
+       advk_writel(pcie, 1, PIO_START);
+       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;
+-      }
++      if (ret < 0)
++              goto try_crs;
+       /* Check PIO status and get the read result */
+       ret = advk_pcie_check_pio_status(pcie, allow_crs, val);
+-      if (ret < 0) {
+-              *val = 0xffffffff;
+-              return PCIBIOS_SET_FAILED;
+-      }
++      if (ret < 0)
++              goto fail;
+       if (size == 1)
+               *val = (*val >> (8 * (where & 3))) & 0xff;
+@@ -1151,6 +1129,20 @@ static int advk_pcie_rd_conf(struct pci_
+               *val = (*val >> (8 * (where & 3))) & 0xffff;
+       return PCIBIOS_SUCCESSFUL;
++
++try_crs:
++      /*
++       * If it is possible, return Completion Retry Status so that caller
++       * tries to issue the request again instead of failing.
++       */
++      if (allow_crs) {
++              *val = CFG_RD_CRS_VAL;
++              return PCIBIOS_SUCCESSFUL;
++      }
++
++fail:
++      *val = 0xffffffff;
++      return PCIBIOS_SET_FAILED;
+ }
+ static int advk_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
diff --git a/queue-5.10/pci-aardvark-fix-link-training.patch b/queue-5.10/pci-aardvark-fix-link-training.patch
new file mode 100644 (file)
index 0000000..24b3f7d
--- /dev/null
@@ -0,0 +1,320 @@
+From f76b36d40beee0a13aa8f6aa011df0d7cbbb8a7f Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
+Date: Tue, 5 Oct 2021 20:09:50 +0200
+Subject: PCI: aardvark: Fix link training
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pali Rohár <pali@kernel.org>
+
+commit f76b36d40beee0a13aa8f6aa011df0d7cbbb8a7f upstream.
+
+Fix multiple link training issues in aardvark driver. The main reason of
+these issues was misunderstanding of what certain registers do, since their
+names and comments were misleading: before commit 96be36dbffac ("PCI:
+aardvark: Replace custom macros by standard linux/pci_regs.h macros"), the
+pci-aardvark.c driver used custom macros for accessing standard PCIe Root
+Bridge registers, and misleading comments did not help to understand what
+the code was really doing.
+
+After doing more tests and experiments I've come to the conclusion that the
+SPEED_GEN register in aardvark sets the PCIe revision / generation
+compliance and forces maximal link speed. Both GEN3 and GEN2 values set the
+read-only PCI_EXP_FLAGS_VERS bits (PCIe capabilities version of Root
+Bridge) to value 2, while GEN1 value sets PCI_EXP_FLAGS_VERS to 1, which
+matches with PCI Express specifications revisions 3, 2 and 1 respectively.
+Changing SPEED_GEN also sets the read-only bits PCI_EXP_LNKCAP_SLS and
+PCI_EXP_LNKCAP2_SLS to corresponding speed.
+
+(Note that PCI Express rev 1 specification does not define PCI_EXP_LNKCAP2
+ and PCI_EXP_LNKCTL2 registers and when SPEED_GEN is set to GEN1 (which
+ also sets PCI_EXP_FLAGS_VERS set to 1), lspci cannot access
+ PCI_EXP_LNKCAP2 and PCI_EXP_LNKCTL2 registers.)
+
+Changing PCIe link speed can be done via PCI_EXP_LNKCTL2_TLS bits of
+PCI_EXP_LNKCTL2 register. Armada 3700 Functional Specifications says that
+the default value of PCI_EXP_LNKCTL2_TLS is based on SPEED_GEN value, but
+tests showed that the default value is always 8.0 GT/s, independently of
+speed set by SPEED_GEN. So after setting SPEED_GEN, we must also set value
+in PCI_EXP_LNKCTL2 register via PCI_EXP_LNKCTL2_TLS bits.
+
+Triggering PCI_EXP_LNKCTL_RL bit immediately after setting LINK_TRAINING_EN
+bit actually doesn't do anything. Tests have shown that a delay is needed
+after enabling LINK_TRAINING_EN bit. As triggering PCI_EXP_LNKCTL_RL
+currently does nothing, remove it.
+
+Commit 43fc679ced18 ("PCI: aardvark: Improve link training") introduced
+code which sets SPEED_GEN register based on negotiated link speed from
+PCI_EXP_LNKSTA_CLS bits of PCI_EXP_LNKSTA register. This code was added to
+fix detection of Compex WLE900VX (Atheros QCA9880) WiFi GEN1 PCIe cards, as
+otherwise these cards were "invisible" on PCIe bus (probably because they
+crashed). But apparently more people reported the same issues with these
+cards also with other PCIe controllers [1] and I was able to reproduce this
+issue also with other "noname" WiFi cards based on Atheros QCA9890 chip
+(with the same PCI vendor/device ids as Atheros QCA9880). So this is not an
+issue in aardvark but rather an issue in Atheros QCA98xx chips. Also, this
+issue only exists if the kernel is compiled with PCIe ASPM support, and a
+generic workaround for this is to change PCIe Bridge to 2.5 GT/s link speed
+via PCI_EXP_LNKCTL2_TLS_2_5GT bits in PCI_EXP_LNKCTL2 register [2], before
+triggering PCI_EXP_LNKCTL_RL bit. This workaround also works when SPEED_GEN
+is set to value GEN2 (5 GT/s). So remove this hack completely in the
+aardvark driver and always set SPEED_GEN to value from 'max-link-speed' DT
+property. Fix for Atheros QCA98xx chips is handled separately by patch [2].
+
+These two things (code for triggering PCI_EXP_LNKCTL_RL bit and changing
+SPEED_GEN value) also explain why commit 6964494582f5 ("PCI: aardvark:
+Train link immediately after enabling training") somehow fixed detection of
+those problematic Compex cards with Atheros chips: if triggering link
+retraining (via PCI_EXP_LNKCTL_RL bit) was done immediately after enabling
+link training (via LINK_TRAINING_EN), it did nothing. If there was a
+specific delay, aardvark HW already initialized PCIe link and therefore
+triggering link retraining caused the above issue. Compex cards triggered
+link down event and disappeared from the PCIe bus.
+
+Commit f4c7d053d7f7 ("PCI: aardvark: Wait for endpoint to be ready before
+training link") added 100ms sleep before calling 'Start link training'
+command and explained that it is a requirement of PCI Express
+specification. But the code after this 100ms sleep was not doing 'Start
+link training', rather it triggered PCI_EXP_LNKCTL_RL bit via PCIe Root
+Bridge to put link into Recovery state.
+
+The required delay after fundamental reset is already done in function
+advk_pcie_wait_for_link() which also checks whether PCIe link is up.
+So after removing the code which triggers PCI_EXP_LNKCTL_RL bit on PCIe
+Root Bridge, there is no need to wait 100ms again. Remove the extra
+msleep() call and update comment about the delay required by the PCI
+Express specification.
+
+According to Marvell Armada 3700 Functional Specifications, Link training
+should be enabled via aardvark register LINK_TRAINING_EN after selecting
+PCIe generation and x1 lane. There is no need to disable it prior resetting
+card via PERST# signal. This disabling code was introduced in commit
+5169a9851daa ("PCI: aardvark: Issue PERST via GPIO") as a workaround for
+some Atheros cards. It turns out that this also is Atheros specific issue
+and affects any PCIe controller, not only aardvark. Moreover this Atheros
+issue was triggered by juggling with PCI_EXP_LNKCTL_RL, LINK_TRAINING_EN
+and SPEED_GEN bits interleaved with sleeps. Now, after removing triggering
+PCI_EXP_LNKCTL_RL, there is no need to explicitly disable LINK_TRAINING_EN
+bit. So remove this code too. The problematic Compex cards described in
+previous git commits are correctly detected in advk_pcie_train_link()
+function even after applying all these changes.
+
+Note that with this patch, and also prior this patch, some NVMe disks which
+support PCIe GEN3 with 8 GT/s speed are negotiated only at the lowest link
+speed 2.5 GT/s, independently of SPEED_GEN value. After manually triggering
+PCI_EXP_LNKCTL_RL bit (e.g. from userspace via setpci), these NVMe disks
+change link speed to 5 GT/s when SPEED_GEN was configured to GEN2. This
+issue first needs to be properly investigated. I will send a fix in the
+future.
+
+On the other hand, some other GEN2 PCIe cards with 5 GT/s speed are
+autonomously by HW autonegotiated at full 5 GT/s speed without need of any
+software interaction.
+
+Armada 3700 Functional Specifications describes the following steps for
+link training: set SPEED_GEN to GEN2, enable LINK_TRAINING_EN, poll until
+link training is complete, trigger PCI_EXP_LNKCTL_RL, poll until signal
+rate is 5 GT/s, poll until link training is complete, enable ASPM L0s.
+
+The requirement for triggering PCI_EXP_LNKCTL_RL can be explained by the
+need to achieve 5 GT/s speed (as changing link speed is done by throw to
+recovery state entered by PCI_EXP_LNKCTL_RL) or maybe as a part of enabling
+ASPM L0s (but in this case ASPM L0s should have been enabled prior
+PCI_EXP_LNKCTL_RL).
+
+It is unknown why the original pci-aardvark.c driver was triggering
+PCI_EXP_LNKCTL_RL bit before waiting for the link to be up. This does not
+align with neither PCIe base specifications nor with Armada 3700 Functional
+Specification. (Note that in older versions of aardvark, this bit was
+called incorrectly PCIE_CORE_LINK_TRAINING, so this may be the reason.)
+
+It is also unknown why Armada 3700 Functional Specification says that it is
+needed to trigger PCI_EXP_LNKCTL_RL for GEN2 mode, as according to PCIe
+base specification 5 GT/s speed negotiation is supposed to be entirely
+autonomous, even if initial speed is 2.5 GT/s.
+
+[1] - https://lore.kernel.org/linux-pci/87h7l8axqp.fsf@toke.dk/
+[2] - https://lore.kernel.org/linux-pci/20210326124326.21163-1-pali@kernel.org/
+
+Link: https://lore.kernel.org/r/20211005180952.6812-12-kabel@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Reviewed-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c |  119 ++++++++++------------------------
+ 1 file changed, 35 insertions(+), 84 deletions(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -306,11 +306,6 @@ static inline u32 advk_readl(struct advk
+       return readl(pcie->base + reg);
+ }
+-static inline u16 advk_read16(struct advk_pcie *pcie, u64 reg)
+-{
+-      return advk_readl(pcie, (reg & ~0x3)) >> ((reg & 0x3) * 8);
+-}
+-
+ static u8 advk_pcie_ltssm_state(struct advk_pcie *pcie)
+ {
+       u32 val;
+@@ -384,23 +379,9 @@ static void advk_pcie_wait_for_retrain(s
+ static void advk_pcie_issue_perst(struct advk_pcie *pcie)
+ {
+-      u32 reg;
+-
+       if (!pcie->reset_gpio)
+               return;
+-      /*
+-       * As required by PCI Express spec (PCI Express Base Specification, REV.
+-       * 4.0 PCI Express, February 19 2014, 6.6.1 Conventional Reset) a delay
+-       * for at least 100ms after de-asserting PERST# signal is needed before
+-       * link training is enabled. So ensure that link training is disabled
+-       * prior de-asserting PERST# signal to fulfill that PCI Express spec
+-       * requirement.
+-       */
+-      reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
+-      reg &= ~LINK_TRAINING_EN;
+-      advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);
+-
+       /* 10ms delay is needed for some cards */
+       dev_info(&pcie->pdev->dev, "issuing PERST via reset GPIO for 10ms\n");
+       gpiod_set_value_cansleep(pcie->reset_gpio, 1);
+@@ -408,54 +389,47 @@ static void advk_pcie_issue_perst(struct
+       gpiod_set_value_cansleep(pcie->reset_gpio, 0);
+ }
+-static int advk_pcie_train_at_gen(struct advk_pcie *pcie, int gen)
++static void advk_pcie_train_link(struct advk_pcie *pcie)
+ {
+-      int ret, neg_gen;
++      struct device *dev = &pcie->pdev->dev;
+       u32 reg;
++      int ret;
+-      /* Setup link speed */
++      /*
++       * Setup PCIe rev / gen compliance based on device tree property
++       * 'max-link-speed' which also forces maximal link speed.
++       */
+       reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
+       reg &= ~PCIE_GEN_SEL_MSK;
+-      if (gen == 3)
++      if (pcie->link_gen == 3)
+               reg |= SPEED_GEN_3;
+-      else if (gen == 2)
++      else if (pcie->link_gen == 2)
+               reg |= SPEED_GEN_2;
+       else
+               reg |= SPEED_GEN_1;
+       advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);
+       /*
+-       * Enable link training. This is not needed in every call to this
+-       * function, just once suffices, but it does not break anything either.
+-       */
++       * Set maximal link speed value also into PCIe Link Control 2 register.
++       * Armada 3700 Functional Specification says that default value is based
++       * on SPEED_GEN but tests showed that default value is always 8.0 GT/s.
++       */
++      reg = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKCTL2);
++      reg &= ~PCI_EXP_LNKCTL2_TLS;
++      if (pcie->link_gen == 3)
++              reg |= PCI_EXP_LNKCTL2_TLS_8_0GT;
++      else if (pcie->link_gen == 2)
++              reg |= PCI_EXP_LNKCTL2_TLS_5_0GT;
++      else
++              reg |= PCI_EXP_LNKCTL2_TLS_2_5GT;
++      advk_writel(pcie, reg, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKCTL2);
++
++      /* Enable link training after selecting PCIe generation */
+       reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
+       reg |= LINK_TRAINING_EN;
+       advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);
+       /*
+-       * Start link training immediately after enabling it.
+-       * This solves problems for some buggy cards.
+-       */
+-      reg = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKCTL);
+-      reg |= PCI_EXP_LNKCTL_RL;
+-      advk_writel(pcie, reg, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKCTL);
+-
+-      ret = advk_pcie_wait_for_link(pcie);
+-      if (ret)
+-              return ret;
+-
+-      reg = advk_read16(pcie, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKSTA);
+-      neg_gen = reg & PCI_EXP_LNKSTA_CLS;
+-
+-      return neg_gen;
+-}
+-
+-static void advk_pcie_train_link(struct advk_pcie *pcie)
+-{
+-      struct device *dev = &pcie->pdev->dev;
+-      int neg_gen = -1, gen;
+-
+-      /*
+        * Reset PCIe card via PERST# signal. Some cards are not detected
+        * during link training when they are in some non-initial state.
+        */
+@@ -465,41 +439,18 @@ static void advk_pcie_train_link(struct
+        * PERST# signal could have been asserted by pinctrl subsystem before
+        * probe() callback has been called or issued explicitly by reset gpio
+        * function advk_pcie_issue_perst(), making the endpoint going into
+-       * fundamental reset. As required by PCI Express spec a delay for at
+-       * least 100ms after such a reset before link training is needed.
+-       */
+-      msleep(PCI_PM_D3COLD_WAIT);
+-
+-      /*
+-       * Try link training at link gen specified by device tree property
+-       * 'max-link-speed'. If this fails, iteratively train at lower gen.
+-       */
+-      for (gen = pcie->link_gen; gen > 0; --gen) {
+-              neg_gen = advk_pcie_train_at_gen(pcie, gen);
+-              if (neg_gen > 0)
+-                      break;
+-      }
+-
+-      if (neg_gen < 0)
+-              goto err;
+-
+-      /*
+-       * After successful training if negotiated gen is lower than requested,
+-       * train again on negotiated gen. This solves some stability issues for
+-       * some buggy gen1 cards.
++       * fundamental reset. As required by PCI Express spec (PCI Express
++       * Base Specification, REV. 4.0 PCI Express, February 19 2014, 6.6.1
++       * Conventional Reset) a delay for at least 100ms after such a reset
++       * before sending a Configuration Request to the device is needed.
++       * So wait until PCIe link is up. Function advk_pcie_wait_for_link()
++       * waits for link at least 900ms.
+        */
+-      if (neg_gen < gen) {
+-              gen = neg_gen;
+-              neg_gen = advk_pcie_train_at_gen(pcie, gen);
+-      }
+-
+-      if (neg_gen == gen) {
+-              dev_info(dev, "link up at gen %i\n", gen);
+-              return;
+-      }
+-
+-err:
+-      dev_err(dev, "link never came up\n");
++      ret = advk_pcie_wait_for_link(pcie);
++      if (ret < 0)
++              dev_err(dev, "link never came up\n");
++      else
++              dev_info(dev, "link up\n");
+ }
+ /*
diff --git a/queue-5.10/pci-aardvark-implement-re-issuing-config-requests-on-crs-response.patch b/queue-5.10/pci-aardvark-implement-re-issuing-config-requests-on-crs-response.patch
new file mode 100644 (file)
index 0000000..ba55e84
--- /dev/null
@@ -0,0 +1,212 @@
+From 223dec14a05337a4155f1deed46d2becce4d00fd Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
+Date: Tue, 5 Oct 2021 20:09:48 +0200
+Subject: PCI: aardvark: Implement re-issuing config requests on CRS response
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pali Rohár <pali@kernel.org>
+
+commit 223dec14a05337a4155f1deed46d2becce4d00fd upstream.
+
+Commit 43f5c77bcbd2 ("PCI: aardvark: Fix reporting CRS value") fixed
+handling of CRS response and when CRSSVE flag was not enabled it marked CRS
+response as failed transaction (due to simplicity).
+
+But pci-aardvark.c driver is already waiting up to the PIO_RETRY_CNT count
+for PIO config response and so we can with a small change implement
+re-issuing of config requests as described in PCIe base specification.
+
+This change implements re-issuing of config requests when response is CRS.
+Set upper bound of wait cycles to around PIO_RETRY_CNT, afterwards the
+transaction is marked as failed and an all-ones value is returned as
+before.
+
+We do this by returning appropriate error codes from function
+advk_pcie_check_pio_status(). On CRS we return -EAGAIN and caller then
+reissues transaction.
+
+Link: https://lore.kernel.org/r/20211005180952.6812-10-kabel@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Reviewed-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c |   69 +++++++++++++++++++++-------------
+ 1 file changed, 44 insertions(+), 25 deletions(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -699,6 +699,7 @@ static int advk_pcie_check_pio_status(st
+       u32 reg;
+       unsigned int status;
+       char *strcomp_status, *str_posted;
++      int ret;
+       reg = advk_readl(pcie, PIO_STAT);
+       status = (reg & PIO_COMPLETION_STATUS_MASK) >>
+@@ -723,6 +724,7 @@ static int advk_pcie_check_pio_status(st
+       case PIO_COMPLETION_STATUS_OK:
+               if (reg & PIO_ERR_STATUS) {
+                       strcomp_status = "COMP_ERR";
++                      ret = -EFAULT;
+                       break;
+               }
+               /* Get the read result */
+@@ -730,9 +732,11 @@ static int advk_pcie_check_pio_status(st
+                       *val = advk_readl(pcie, PIO_RD_DATA);
+               /* No error */
+               strcomp_status = NULL;
++              ret = 0;
+               break;
+       case PIO_COMPLETION_STATUS_UR:
+               strcomp_status = "UR";
++              ret = -EOPNOTSUPP;
+               break;
+       case PIO_COMPLETION_STATUS_CRS:
+               if (allow_crs && val) {
+@@ -750,6 +754,7 @@ static int advk_pcie_check_pio_status(st
+                        */
+                       *val = CFG_RD_CRS_VAL;
+                       strcomp_status = NULL;
++                      ret = 0;
+                       break;
+               }
+               /* PCIe r4.0, sec 2.3.2, says:
+@@ -765,21 +770,24 @@ static int advk_pcie_check_pio_status(st
+                * Request and taking appropriate action, e.g., complete the
+                * Request to the host as a failed transaction.
+                *
+-               * To simplify implementation do not re-issue the Configuration
+-               * Request and complete the Request as a failed transaction.
++               * So return -EAGAIN and caller (pci-aardvark.c driver) will
++               * re-issue request again up to the PIO_RETRY_CNT retries.
+                */
+               strcomp_status = "CRS";
++              ret = -EAGAIN;
+               break;
+       case PIO_COMPLETION_STATUS_CA:
+               strcomp_status = "CA";
++              ret = -ECANCELED;
+               break;
+       default:
+               strcomp_status = "Unknown";
++              ret = -EINVAL;
+               break;
+       }
+       if (!strcomp_status)
+-              return 0;
++              return ret;
+       if (reg & PIO_NON_POSTED_REQ)
+               str_posted = "Non-posted";
+@@ -789,7 +797,7 @@ static int advk_pcie_check_pio_status(st
+       dev_dbg(dev, "%s PIO Response Status: %s, %#x @ %#x\n",
+               str_posted, strcomp_status, reg, advk_readl(pcie, PIO_ADDR_LS));
+-      return -EFAULT;
++      return ret;
+ }
+ static int advk_pcie_wait_pio(struct advk_pcie *pcie)
+@@ -797,13 +805,13 @@ static int advk_pcie_wait_pio(struct adv
+       struct device *dev = &pcie->pdev->dev;
+       int i;
+-      for (i = 0; i < PIO_RETRY_CNT; i++) {
++      for (i = 1; i <= PIO_RETRY_CNT; i++) {
+               u32 start, isr;
+               start = advk_readl(pcie, PIO_START);
+               isr = advk_readl(pcie, PIO_ISR);
+               if (!start && isr)
+-                      return 0;
++                      return i;
+               udelay(PIO_RETRY_DELAY);
+       }
+@@ -1075,6 +1083,7 @@ static int advk_pcie_rd_conf(struct pci_
+                            int where, int size, u32 *val)
+ {
+       struct advk_pcie *pcie = bus->sysdata;
++      int retry_count;
+       bool allow_crs;
+       u32 reg;
+       int ret;
+@@ -1117,16 +1126,22 @@ static int advk_pcie_rd_conf(struct pci_
+       /* Program the data strobe */
+       advk_writel(pcie, 0xf, PIO_WR_DATA_STRB);
+-      /* Clear PIO DONE ISR and start the transfer */
+-      advk_writel(pcie, 1, PIO_ISR);
+-      advk_writel(pcie, 1, PIO_START);
+-
+-      ret = advk_pcie_wait_pio(pcie);
+-      if (ret < 0)
+-              goto try_crs;
++      retry_count = 0;
++      do {
++              /* Clear PIO DONE ISR and start the transfer */
++              advk_writel(pcie, 1, PIO_ISR);
++              advk_writel(pcie, 1, PIO_START);
++
++              ret = advk_pcie_wait_pio(pcie);
++              if (ret < 0)
++                      goto try_crs;
++
++              retry_count += ret;
++
++              /* Check PIO status and get the read result */
++              ret = advk_pcie_check_pio_status(pcie, allow_crs, val);
++      } while (ret == -EAGAIN && retry_count < PIO_RETRY_CNT);
+-      /* Check PIO status and get the read result */
+-      ret = advk_pcie_check_pio_status(pcie, allow_crs, val);
+       if (ret < 0)
+               goto fail;
+@@ -1158,6 +1173,7 @@ static int advk_pcie_wr_conf(struct pci_
+       struct advk_pcie *pcie = bus->sysdata;
+       u32 reg;
+       u32 data_strobe = 0x0;
++      int retry_count;
+       int offset;
+       int ret;
+@@ -1199,19 +1215,22 @@ static int advk_pcie_wr_conf(struct pci_
+       /* Program the data strobe */
+       advk_writel(pcie, data_strobe, PIO_WR_DATA_STRB);
+-      /* Clear PIO DONE ISR and start the transfer */
+-      advk_writel(pcie, 1, PIO_ISR);
+-      advk_writel(pcie, 1, PIO_START);
++      retry_count = 0;
++      do {
++              /* Clear PIO DONE ISR and start the transfer */
++              advk_writel(pcie, 1, PIO_ISR);
++              advk_writel(pcie, 1, PIO_START);
++
++              ret = advk_pcie_wait_pio(pcie);
++              if (ret < 0)
++                      return PCIBIOS_SET_FAILED;
+-      ret = advk_pcie_wait_pio(pcie);
+-      if (ret < 0)
+-              return PCIBIOS_SET_FAILED;
++              retry_count += ret;
+-      ret = advk_pcie_check_pio_status(pcie, false, NULL);
+-      if (ret < 0)
+-              return PCIBIOS_SET_FAILED;
++              ret = advk_pcie_check_pio_status(pcie, false, NULL);
++      } while (ret == -EAGAIN && retry_count < PIO_RETRY_CNT);
+-      return PCIBIOS_SUCCESSFUL;
++      return ret < 0 ? PCIBIOS_SET_FAILED : PCIBIOS_SUCCESSFUL;
+ }
+ static struct pci_ops advk_pcie_ops = {
diff --git a/queue-5.10/pci-aardvark-simplify-initialization-of-rootcap-on-virtual-bridge.patch b/queue-5.10/pci-aardvark-simplify-initialization-of-rootcap-on-virtual-bridge.patch
new file mode 100644 (file)
index 0000000..aa435c4
--- /dev/null
@@ -0,0 +1,63 @@
+From 454c53271fc11f3aa5e44e41fd99ca181bd32c62 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
+Date: Tue, 5 Oct 2021 20:09:49 +0200
+Subject: PCI: aardvark: Simplify initialization of rootcap on virtual bridge
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pali Rohár <pali@kernel.org>
+
+commit 454c53271fc11f3aa5e44e41fd99ca181bd32c62 upstream.
+
+PCIe config space can be initialized also before pci_bridge_emul_init()
+call, so move rootcap initialization after PCI config space initialization.
+
+This simplifies the function a little since it removes one if (ret < 0)
+check.
+
+Link: https://lore.kernel.org/r/20211005180952.6812-11-kabel@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Reviewed-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c |   14 ++++----------
+ 1 file changed, 4 insertions(+), 10 deletions(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -999,7 +999,6 @@ 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 =
+               cpu_to_le16(advk_readl(pcie, PCIE_CORE_DEV_ID_REG) & 0xffff);
+@@ -1019,19 +1018,14 @@ static int advk_sw_pci_bridge_init(struc
+       /* Support interrupt A for MSI feature */
+       bridge->conf.intpin = PCIE_CORE_INT_A_ASSERT_ENABLE;
++      /* Indicates supports for Completion Retry Status */
++      bridge->pcie_conf.rootcap = cpu_to_le16(PCI_EXP_RTCAP_CRSVIS);
++
+       bridge->has_pcie = true;
+       bridge->data = pcie;
+       bridge->ops = &advk_pci_bridge_emul_ops;
+-      /* 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;
++      return pci_bridge_emul_init(bridge, 0);
+ }
+ static bool advk_pcie_valid_device(struct advk_pcie *pcie, struct pci_bus *bus,
diff --git a/queue-5.10/pci-aardvark-update-comment-about-disabling-link-training.patch b/queue-5.10/pci-aardvark-update-comment-about-disabling-link-training.patch
new file mode 100644 (file)
index 0000000..8b7ae58
--- /dev/null
@@ -0,0 +1,45 @@
+From 1d1cd163d0de22a4041a6f1aeabcf78f80076539 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
+Date: Wed, 2 Dec 2020 19:46:59 +0100
+Subject: PCI: aardvark: Update comment about disabling link training
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pali Rohár <pali@kernel.org>
+
+commit 1d1cd163d0de22a4041a6f1aeabcf78f80076539 upstream.
+
+According to PCI Express Base Specifications (rev 4.0, 6.6.1
+"Conventional reset"), after fundamental reset a 100ms delay is needed
+prior to enabling link training.
+
+Update comment in code to reflect this requirement.
+
+Link: https://lore.kernel.org/r/20201202184659.3795-1-pali@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c |    9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -389,7 +389,14 @@ static void advk_pcie_issue_perst(struct
+       if (!pcie->reset_gpio)
+               return;
+-      /* PERST does not work for some cards when link training is enabled */
++      /*
++       * As required by PCI Express spec (PCI Express Base Specification, REV.
++       * 4.0 PCI Express, February 19 2014, 6.6.1 Conventional Reset) a delay
++       * for at least 100ms after de-asserting PERST# signal is needed before
++       * link training is enabled. So ensure that link training is disabled
++       * prior de-asserting PERST# signal to fulfill that PCI Express spec
++       * requirement.
++       */
+       reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
+       reg &= ~LINK_TRAINING_EN;
+       advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);
index 7009daf504adfb75b54b73d84b2507ebdff0b633..d406ee68ab53effc0374d36ca4050ff0f77e491c 100644 (file)
@@ -32,3 +32,8 @@ mmc-sdhci-esdhc-imx-disable-cmdq-support.patch
 mmc-sdhci-fix-adma-for-page_size-64kib.patch
 mdio-aspeed-fix-link-is-down-issue.patch
 powerpc-32-fix-hardlockup-on-vmap-stack-overflow.patch
+pci-aardvark-deduplicate-code-in-advk_pcie_rd_conf.patch
+pci-aardvark-update-comment-about-disabling-link-training.patch
+pci-aardvark-implement-re-issuing-config-requests-on-crs-response.patch
+pci-aardvark-simplify-initialization-of-rootcap-on-virtual-bridge.patch
+pci-aardvark-fix-link-training.patch