From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.7 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6B1C4C432BE for ; Fri, 27 Aug 2021 12:16:40 +0000 (UTC) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id C0AFD60551 for ; Fri, 27 Aug 2021 12:16:39 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org C0AFD60551 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=kernel.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=lists.denx.de Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 4B5D1832A2; Fri, 27 Aug 2021 14:16:33 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=kernel.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=kernel.org header.i=@kernel.org header.b="gCG1s6TM"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 4E67B83264; Fri, 27 Aug 2021 14:16:22 +0200 (CEST) Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 2B9B583276 for ; Fri, 27 Aug 2021 14:16:16 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=kernel.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=pali@kernel.org Received: by mail.kernel.org (Postfix) with ESMTPSA id 43AB960EE0; Fri, 27 Aug 2021 12:16:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1630066574; bh=YGpqyB73W5gRjb1u6MPiOGHn0If5sA7HDSihVaAH/2g=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=gCG1s6TMrTAEnOqBJzZPD1Mh0QS2BU6yBtwku3oGM7XZML+ae/hbUAwCod4FSOTZb z6fO+SNfT9pR3iGz+RByJKWKPrG4u0QhlwswdjEZktuFktQw4PnmACCym7+unHYM83 dxKS/6FwfzHaUYMW5evxhttnl9Pui3Yov58VoZ67u7T3ZyusIUqDbeIpCF8+PSmlpF B/7++udG+UUeFv8W7pMvwRUKjNK4yuFL4Qg0dEww+7+6ja3uwrbx3vpH3VkEU1nWo9 6mLAqarDLlqC6uN6+sCiqX/4QyC9xA1eAHzDxOWb9b7qhEDrZst2p7L8y0hLfTitBP 4AzY0tsz2Gl/Q== Received: by pali.im (Postfix) id 06A56617; Fri, 27 Aug 2021 14:16:14 +0200 (CEST) From: =?UTF-8?q?Pali=20Roh=C3=A1r?= To: Stefan Roese , Konstantin Porotchkin Cc: =?UTF-8?q?Marek=20Beh=C3=BAn?= , u-boot@lists.denx.de Subject: [PATCH 2/2] arm: a37xx: pci: Implement re-issuing config requests on CRS response Date: Fri, 27 Aug 2021 14:14:44 +0200 Message-Id: <20210827121444.7628-2-pali@kernel.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20210827121444.7628-1-pali@kernel.org> References: <20210827121444.7628-1-pali@kernel.org> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean According to PCIe base specification, if CRS Software Visibility is not enabled, the Root Complex must re-issue the Configuration Request as a new Request. Normally this part of Root Complex is implemented in hardware but aardvark is somehow special and does not implement it in hardware and expect that handling of config requests are fully implemented in software. This re-issuing functionality is required also because U-Boot does not support CRS Software Visibility feature and therefore expects that Root Complex re-issues requests as is specified in PCIe base specification. Retry / re-issue config request up to the PIO_MAX_RETRIES, to prevent infinite loop. After retry count exceed PIO_MAX_RETRIES, returns failure. Signed-off-by: Pali Rohár --- drivers/pci/pci-aardvark.c | 58 ++++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 15 deletions(-) diff --git a/drivers/pci/pci-aardvark.c b/drivers/pci/pci-aardvark.c index d3ef8f203d97..74797e984cb8 100644 --- a/drivers/pci/pci-aardvark.c +++ b/drivers/pci/pci-aardvark.c @@ -234,19 +234,19 @@ static int pcie_advk_addr_valid(pci_dev_t bdf, int first_busno) * * Wait up to 1.5 seconds for PIO access to be accomplished. * - * Return 1 (true) if PIO access is accomplished. - * Return 0 (false) if PIO access is timed out. + * Return positive - retry count if PIO access is accomplished. + * Return negative - error if PIO access is timed out. */ static int pcie_advk_wait_pio(struct pcie_advk *pcie) { uint start, isr; uint count; - for (count = 0; count < PIO_MAX_RETRIES; count++) { + for (count = 1; count <= PIO_MAX_RETRIES; count++) { start = advk_readl(pcie, PIO_START); isr = advk_readl(pcie, PIO_ISR); if (!start && isr) - return 1; + return count; /* * Do not check the PIO state too frequently, * 100us delay is appropriate. @@ -255,7 +255,7 @@ static int pcie_advk_wait_pio(struct pcie_advk *pcie) } dev_err(pcie->dev, "PIO read/write transfer time out\n"); - return 0; + return -ETIMEDOUT; } /** @@ -265,11 +265,13 @@ static int pcie_advk_wait_pio(struct pcie_advk *pcie) * @allow_crs: Only for read requests, if CRS response is allowed * @read_val: Pointer to the read result * + * Return: 0 on success */ static int pcie_advk_check_pio_status(struct pcie_advk *pcie, bool allow_crs, uint *read_val) { + int ret; uint reg; unsigned int status; char *strcomp_status, *str_posted; @@ -282,6 +284,7 @@ static int pcie_advk_check_pio_status(struct pcie_advk *pcie, case PIO_COMPLETION_STATUS_OK: if (reg & PIO_ERR_STATUS) { strcomp_status = "COMP_ERR"; + ret = -EFAULT; break; } /* Get the read result */ @@ -289,29 +292,35 @@ static int pcie_advk_check_pio_status(struct pcie_advk *pcie, *read_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 && read_val) { /* For reading, CRS is not an error status. */ *read_val = CFG_RD_CRS_VAL; strcomp_status = NULL; + ret = 0; } else { 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"; @@ -322,7 +331,7 @@ static int pcie_advk_check_pio_status(struct pcie_advk *pcie, str_posted, strcomp_status, reg, advk_readl(pcie, PIO_ADDR_LS)); - return -EFAULT; + return ret; } /** @@ -345,6 +354,7 @@ static int pcie_advk_read_config(const struct udevice *bus, pci_dev_t bdf, enum pci_size_t size) { struct pcie_advk *pcie = dev_get_priv(bus); + int retry_count; bool allow_crs; uint reg; int ret; @@ -379,7 +389,7 @@ static int pcie_advk_read_config(const struct udevice *bus, pci_dev_t bdf, return 0; } *valuep = pci_get_ff(size); - return -EINVAL; + return -EAGAIN; } /* Program the control register */ @@ -396,21 +406,29 @@ static int pcie_advk_read_config(const struct udevice *bus, pci_dev_t bdf, advk_writel(pcie, reg, PIO_ADDR_LS); advk_writel(pcie, 0, PIO_ADDR_MS); + retry_count = 0; + +retry: /* Start the transfer */ advk_writel(pcie, 1, PIO_ISR); advk_writel(pcie, 1, PIO_START); - if (!pcie_advk_wait_pio(pcie)) { + ret = pcie_advk_wait_pio(pcie); + if (ret < 0) { if (allow_crs) { *valuep = CFG_RD_CRS_VAL; return 0; } *valuep = pci_get_ff(size); - return -EINVAL; + return ret; } + retry_count += ret; + /* Check PIO status and get the read result */ ret = pcie_advk_check_pio_status(pcie, allow_crs, ®); + if (ret == -EAGAIN && retry_count < PIO_MAX_RETRIES) + goto retry; if (ret) { *valuep = pci_get_ff(size); return ret; @@ -472,7 +490,9 @@ static int pcie_advk_write_config(struct udevice *bus, pci_dev_t bdf, enum pci_size_t size) { struct pcie_advk *pcie = dev_get_priv(bus); + int retry_count; uint reg; + int ret; dev_dbg(pcie->dev, "PCIE CFG write: (b,d,f)=(%2d,%2d,%2d) ", PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf)); @@ -487,7 +507,7 @@ static int pcie_advk_write_config(struct udevice *bus, pci_dev_t bdf, if (advk_readl(pcie, PIO_START)) { dev_err(pcie->dev, "Previous PIO read/write transfer is still running\n"); - return -EINVAL; + return -EAGAIN; } /* Program the control register */ @@ -515,16 +535,24 @@ static int pcie_advk_write_config(struct udevice *bus, pci_dev_t bdf, advk_writel(pcie, reg, PIO_WR_DATA_STRB); dev_dbg(pcie->dev, "\tPIO req. - strb = 0x%02x\n", reg); + retry_count = 0; + +retry: /* Start the transfer */ advk_writel(pcie, 1, PIO_ISR); advk_writel(pcie, 1, PIO_START); - if (!pcie_advk_wait_pio(pcie)) { - return -EINVAL; - } + ret = pcie_advk_wait_pio(pcie); + if (ret < 0) + return ret; + + retry_count += ret; /* Check PIO status */ - return pcie_advk_check_pio_status(pcie, false, NULL); + ret = pcie_advk_check_pio_status(pcie, false, NULL); + if (ret == -EAGAIN && retry_count < PIO_MAX_RETRIES) + goto retry; + return ret; } /** -- 2.20.1