From: Greg Kroah-Hartman Date: Sun, 28 Nov 2021 12:01:09 +0000 (+0100) Subject: 5.10-stable patches X-Git-Tag: v5.15.6~58 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=910c770fa11f03ece6d0215a0c0a2003a36ce905;p=thirdparty%2Fkernel%2Fstable-queue.git 5.10-stable patches 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 --- 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 index 00000000000..2f10090a811 --- /dev/null +++ b/queue-5.10/pci-aardvark-deduplicate-code-in-advk_pcie_rd_conf.patch @@ -0,0 +1,98 @@ +From 67cb2a4c93499c2c22704998fd1fd2bc35194d8e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +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 + +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 +Signed-off-by: Lorenzo Pieralisi +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..24b3f7dfcdd --- /dev/null +++ b/queue-5.10/pci-aardvark-fix-link-training.patch @@ -0,0 +1,320 @@ +From f76b36d40beee0a13aa8f6aa011df0d7cbbb8a7f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +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 + +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 +Signed-off-by: Marek Behún +Signed-off-by: Lorenzo Pieralisi +Reviewed-by: Marek Behún +Signed-off-by: Marek Behún +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..ba55e841fa3 --- /dev/null +++ b/queue-5.10/pci-aardvark-implement-re-issuing-config-requests-on-crs-response.patch @@ -0,0 +1,212 @@ +From 223dec14a05337a4155f1deed46d2becce4d00fd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +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 + +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 +Signed-off-by: Marek Behún +Signed-off-by: Lorenzo Pieralisi +Reviewed-by: Marek Behún +Signed-off-by: Marek Behún +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..aa435c46e5f --- /dev/null +++ b/queue-5.10/pci-aardvark-simplify-initialization-of-rootcap-on-virtual-bridge.patch @@ -0,0 +1,63 @@ +From 454c53271fc11f3aa5e44e41fd99ca181bd32c62 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +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 + +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 +Signed-off-by: Marek Behún +Signed-off-by: Lorenzo Pieralisi +Reviewed-by: Marek Behún +Signed-off-by: Marek Behún +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..8b7ae584490 --- /dev/null +++ b/queue-5.10/pci-aardvark-update-comment-about-disabling-link-training.patch @@ -0,0 +1,45 @@ +From 1d1cd163d0de22a4041a6f1aeabcf78f80076539 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +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 + +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 +Signed-off-by: Lorenzo Pieralisi +Signed-off-by: Marek Behún +Signed-off-by: Greg Kroah-Hartman +--- + 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); diff --git a/queue-5.10/series b/queue-5.10/series index 7009daf504a..d406ee68ab5 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -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