--- /dev/null
+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,
--- /dev/null
+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");
+ }
+
+ /*
--- /dev/null
+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 = {
--- /dev/null
+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,
--- /dev/null
+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);
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