lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20230618224656.2476-2-retpolanne@posteo.net>
Date:   Sun, 18 Jun 2023 22:46:57 +0000
From:   Anne Macedo <retpolanne@...teo.net>
To:     Mathias Nyman <mathias.nyman@...el.com>,
        Greg Kroah-Hartman <gregkh@...uxfoundation.org>
Cc:     Yoshihiro Shimoda <yoshihiro.shimoda.uh@...esas.com>,
        Vinod Koul <vkoul@...nel.org>,
        Christian Lamparter <chunkeey@...glemail.com>,
        linux-usb@...r.kernel.org, linux-kernel@...r.kernel.org,
        retpolanne@...teo.net
Subject: [PATCH] usb: host: xhci: parameterize Renesas delay/retry

Cards based on Renesas uPD720202 have their firmware downloaded during
boot by xhci-pci. At this step, the status of the firmware is read and
it takes a while for this read to happen (up to a few seconds). The
macros RENESAS_RETRY and RENESAS_DELAY are used to retry reading this
status byte from PCI a few times. If it can't read the status byte in
RENESAS_RETRY tries, it times out.

However, since this may vary from card to card, these retry and delay
values need to be tweaked. In order to avoid having to patch the code to
change these values, CONFIG_USB_XHCI_PCI_RENESAS_RETRY and
CONFIG_USB_XHCI_PCI_RENESAS_DELAY are introduced.

If applied, this patch helps to fix errors such as:

ROM Download Step 34 failed at position 136 bytes
Firmware Download Step 2 failed at position 8 bytes with (-110)

while loading xhci-pci when using these cards.

This error in particular has been noticed by this e-mail [1].

[1] https://lore.kernel.org/lkml/20190626070658.GP2962@vkoul-mobl/

Signed-off-by: Anne Macedo <retpolanne@...teo.net>
---
 drivers/usb/host/Kconfig            | 10 +++++++
 drivers/usb/host/xhci-pci-renesas.c | 45 ++++++++++++++---------------
 2 files changed, 31 insertions(+), 24 deletions(-)

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index c170672f847e..8a255e3b0f03 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -51,6 +51,16 @@ config USB_XHCI_PCI_RENESAS
 	  installed on your system for this device to work.
 	  If unsure, say 'N'.
 
+config USB_XHCI_PCI_RENESAS_DELAY
+	int "Renesas firmware download delay for setting DATAX"
+	depends on USB_XHCI_PCI_RENESAS
+	default 10
+
+config USB_XHCI_PCI_RENESAS_RETRY
+	int "Renesas firmware download number of retries for setting DATAX"
+	depends on USB_XHCI_PCI_RENESAS
+	default 1000
+
 config USB_XHCI_PLATFORM
 	tristate "Generic xHCI driver for a platform device"
 	help
diff --git a/drivers/usb/host/xhci-pci-renesas.c b/drivers/usb/host/xhci-pci-renesas.c
index 93f8b355bc70..009f5878fe6f 100644
--- a/drivers/usb/host/xhci-pci-renesas.c
+++ b/drivers/usb/host/xhci-pci-renesas.c
@@ -47,9 +47,6 @@
 #define RENESAS_ROM_ERASE_MAGIC				0x5A65726F
 #define RENESAS_ROM_WRITE_MAGIC				0x53524F4D
 
-#define RENESAS_RETRY	10000
-#define RENESAS_DELAY	10
-
 static int renesas_fw_download_image(struct pci_dev *dev,
 				     const u32 *fw, size_t step, bool rom)
 {
@@ -73,7 +70,7 @@ static int renesas_fw_download_image(struct pci_dev *dev,
 	data0_or_data1 = (step & 1) == 1;
 
 	/* step+1. Read "Set DATAX" and confirm it is cleared. */
-	for (i = 0; i < RENESAS_RETRY; i++) {
+	for (i = 0; i < CONFIG_USB_XHCI_PCI_RENESAS_RETRY; i++) {
 		err = pci_read_config_byte(dev, status_reg, &fw_status);
 		if (err) {
 			dev_err(&dev->dev, "Read Status failed: %d\n",
@@ -83,9 +80,9 @@ static int renesas_fw_download_image(struct pci_dev *dev,
 		if (!(fw_status & BIT(data0_or_data1)))
 			break;
 
-		udelay(RENESAS_DELAY);
+		udelay(CONFIG_USB_XHCI_PCI_RENESAS_DELAY);
 	}
-	if (i == RENESAS_RETRY) {
+	if (i == CONFIG_USB_XHCI_PCI_RENESAS_RETRY) {
 		dev_err(&dev->dev, "Timeout for Set DATAX step: %zd\n", step);
 		return -ETIMEDOUT;
 	}
@@ -321,7 +318,7 @@ static int renesas_fw_download(struct pci_dev *pdev,
 	 * "DATA0" or "DATA1". Naturally, we wait until "SET DATA0/1"
 	 * is cleared by the hardware beforehand.
 	 */
-	for (i = 0; i < RENESAS_RETRY; i++) {
+	for (i = 0; i < CONFIG_USB_XHCI_PCI_RENESAS_RETRY; i++) {
 		err = pci_read_config_byte(pdev, RENESAS_FW_STATUS_MSB,
 					   &fw_status);
 		if (err)
@@ -329,9 +326,9 @@ static int renesas_fw_download(struct pci_dev *pdev,
 		if (!(fw_status & (BIT(0) | BIT(1))))
 			break;
 
-		udelay(RENESAS_DELAY);
+		udelay(CONFIG_USB_XHCI_PCI_RENESAS_DELAY);
 	}
-	if (i == RENESAS_RETRY)
+	if (i == CONFIG_USB_XHCI_PCI_RENESAS_RETRY)
 		dev_warn(&pdev->dev, "Final Firmware Download step timed out.");
 
 	/*
@@ -343,16 +340,16 @@ static int renesas_fw_download(struct pci_dev *pdev,
 		return pcibios_err_to_errno(err);
 
 	/* 12. Read "Result Code" and confirm it is good. */
-	for (i = 0; i < RENESAS_RETRY; i++) {
+	for (i = 0; i < CONFIG_USB_XHCI_PCI_RENESAS_RETRY; i++) {
 		err = pci_read_config_byte(pdev, RENESAS_FW_STATUS, &fw_status);
 		if (err)
 			return pcibios_err_to_errno(err);
 		if (fw_status & RENESAS_FW_STATUS_SUCCESS)
 			break;
 
-		udelay(RENESAS_DELAY);
+		udelay(CONFIG_USB_XHCI_PCI_RENESAS_DELAY);
 	}
-	if (i == RENESAS_RETRY) {
+	if (i == CONFIG_USB_XHCI_PCI_RENESAS_RETRY) {
 		/* Timed out / Error - let's see if we can fix this */
 		err = renesas_fw_check_running(pdev);
 		switch (err) {
@@ -405,17 +402,17 @@ static void renesas_rom_erase(struct pci_dev *pdev)
 	/* sleep a bit while ROM is erased */
 	msleep(20);
 
-	for (i = 0; i < RENESAS_RETRY; i++) {
+	for (i = 0; i < CONFIG_USB_XHCI_PCI_RENESAS_RETRY; i++) {
 		retval = pci_read_config_byte(pdev, RENESAS_ROM_STATUS,
 					      &status);
 		status &= RENESAS_ROM_STATUS_ERASE;
 		if (!status)
 			break;
 
-		mdelay(RENESAS_DELAY);
+		mdelay(CONFIG_USB_XHCI_PCI_RENESAS_DELAY);
 	}
 
-	if (i == RENESAS_RETRY)
+	if (i == CONFIG_USB_XHCI_PCI_RENESAS_RETRY)
 		dev_dbg(&pdev->dev, "Chip erase timedout: %x\n", status);
 
 	dev_dbg(&pdev->dev, "ROM Erase... Done success\n");
@@ -464,7 +461,7 @@ static bool renesas_setup_rom(struct pci_dev *pdev, const struct firmware *fw)
 	/*
 	 * wait till DATA0/1 is cleared
 	 */
-	for (i = 0; i < RENESAS_RETRY; i++) {
+	for (i = 0; i < CONFIG_USB_XHCI_PCI_RENESAS_RETRY; i++) {
 		err = pci_read_config_byte(pdev, RENESAS_ROM_STATUS_MSB,
 					   &status);
 		if (err)
@@ -472,9 +469,9 @@ static bool renesas_setup_rom(struct pci_dev *pdev, const struct firmware *fw)
 		if (!(status & (BIT(0) | BIT(1))))
 			break;
 
-		udelay(RENESAS_DELAY);
+		udelay(CONFIG_USB_XHCI_PCI_RENESAS_DELAY);
 	}
-	if (i == RENESAS_RETRY) {
+	if (i == CONFIG_USB_XHCI_PCI_RENESAS_RETRY) {
 		dev_err(&pdev->dev, "Final Firmware ROM Download step timed out\n");
 		goto remove_bypass;
 	}
@@ -487,7 +484,7 @@ static bool renesas_setup_rom(struct pci_dev *pdev, const struct firmware *fw)
 	udelay(10);
 
 	/* 18. check result */
-	for (i = 0; i < RENESAS_RETRY; i++) {
+	for (i = 0; i < CONFIG_USB_XHCI_PCI_RENESAS_RETRY; i++) {
 		err = pci_read_config_byte(pdev, RENESAS_ROM_STATUS, &status);
 		if (err) {
 			dev_err(&pdev->dev, "Read ROM status failed:%d\n",
@@ -499,9 +496,9 @@ static bool renesas_setup_rom(struct pci_dev *pdev, const struct firmware *fw)
 			dev_dbg(&pdev->dev, "Download ROM success\n");
 			break;
 		}
-		udelay(RENESAS_DELAY);
+		udelay(CONFIG_USB_XHCI_PCI_RENESAS_DELAY);
 	}
-	if (i == RENESAS_RETRY) { /* Timed out */
+	if (i == CONFIG_USB_XHCI_PCI_RENESAS_RETRY) { /* Timed out */
 		dev_err(&pdev->dev,
 			"Download to external ROM TO: %x\n", status);
 		return false;
@@ -521,16 +518,16 @@ static bool renesas_setup_rom(struct pci_dev *pdev, const struct firmware *fw)
 	/*
 	 * wait till Reload is cleared
 	 */
-	for (i = 0; i < RENESAS_RETRY; i++) {
+	for (i = 0; i < CONFIG_USB_XHCI_PCI_RENESAS_RETRY; i++) {
 		err = pci_read_config_byte(pdev, RENESAS_ROM_STATUS, &status);
 		if (err)
 			return false;
 		if (!(status & RENESAS_ROM_STATUS_RELOAD))
 			break;
 
-		udelay(RENESAS_DELAY);
+		udelay(CONFIG_USB_XHCI_PCI_RENESAS_DELAY);
 	}
-	if (i == RENESAS_RETRY) {
+	if (i == CONFIG_USB_XHCI_PCI_RENESAS_RETRY) {
 		dev_err(&pdev->dev, "ROM Exec timed out: %x\n", status);
 		return false;
 	}
-- 
2.41.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ