Re: [PATCH v3] xhci: Bad Ethernet performance plugged in ASM1042A host

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Jun 15, 2017 at 02:58:21PM +0800, Jiahau Chang wrote:
> When USB Ethernet is plugged in ASMEDIA ASM1042A xHCI host, bad
> performance was manifesting in Web browser use (like download
> large file such as ISO image). It is known limitation of
> ASM1042A that is not compatible with driver scheduling,
> As a workaround we can modify flow control handling of ASM1042A.
> The register we modify is change the behavior
> 
> Signed-off-by: Jiahau Chang <Lars_chang@xxxxxxxxxxxxxx>
> ---
> v3: add define value of setting ASMT write Reg
>     modify dev_dbg message
>     use usleep
> v2: fix coding format
> 
>  drivers/usb/host/pci-quirks.c | 62 +++++++++++++++++++++++++++++++++++++++++++
>  drivers/usb/host/pci-quirks.h |  1 +
>  drivers/usb/host/xhci-pci.c   |  5 ++++
>  drivers/usb/host/xhci.c       |  3 +++
>  drivers/usb/host/xhci.h       |  1 +
>  5 files changed, 72 insertions(+)
> 
> diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
> index a9a1e4c..bdf50bf 100644
> --- a/drivers/usb/host/pci-quirks.c
> +++ b/drivers/usb/host/pci-quirks.c
> @@ -77,6 +77,16 @@
>  #define USB_INTEL_USB3_PSSEN   0xD8
>  #define USB_INTEL_USB3PRM      0xDC
>  
> +/*ASMEDIA quirk use*/

Please put ' ' characters in your comments around the text to make them
read better.  This line should read:
/* ASMEDIA quirk use */

You do that in other places in this patch, please fix up.

> +#define ASMT_DATA_WRITE0_REG	0xF8
> +#define ASMT_DATA_WRITE1_REG	0xFC
> +#define ASMT_CONTROL_REG	0xE0
> +#define ASMT_CONTROL_WRITE_BIT	0x02
> +#define ASMT_WRITEREG_CMD	0x10423
> +#define ASMT_FLOWCTL_ADDR	0xFA30
> +#define ASMT_FLOWCTL_DATA	0xBA
> +#define ASMT_PSEUDO_DATA	0
> +
>  /*
>   * amd_chipset_gen values represent AMD different chipset generations
>   */
> @@ -412,6 +422,58 @@ void usb_amd_quirk_pll_disable(void)
>  }
>  EXPORT_SYMBOL_GPL(usb_amd_quirk_pll_disable);
>  
> +void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev)
> +{
> +	unsigned char value;
> +	unsigned long wait_time_count;
> +
> +	/*check device can accept command*/

Like there ^

> +	wait_time_count = 1000;
> +	while (wait_time_count) {
> +		pci_read_config_byte(pdev, ASMT_CONTROL_REG, &value);
> +		if (value == 0xff) {
> +			dev_dbg(&pdev->dev, "%s: check_ready ERROR", __func__);
> +			goto err_exit;
> +		}
> +		if ((value & ASMT_CONTROL_WRITE_BIT) == 0)
> +			break;
> +		wait_time_count--;
> +		usleep(50);
> +	}
> +	if (wait_time_count == 0) {
> +		dev_dbg(&pdev->dev, "%s: check_write_ready timeout", __func__);

Shouldn't this be an error?  The hardware didn't respond correctly,
shouldn't users be able to report this?

> +		goto err_exit;
> +	}
> +	/* send command and address to device */
> +	pci_write_config_dword(pdev, ASMT_DATA_WRITE0_REG, ASMT_WRITEREG_CMD);
> +	pci_write_config_dword(pdev, ASMT_DATA_WRITE1_REG, ASMT_FLOWCTL_ADDR);
> +	pci_write_config_byte(pdev, ASMT_CONTROL_REG, ASMT_CONTROL_WRITE_BIT);
> +	wait_time_count = 1000;
> +	/* wait device receive the data */
> +	while (wait_time_count) {
> +		pci_read_config_byte(pdev, ASMT_CONTROL_REG, &value);
> +		if (value == 0xff) {
> +			dev_dbg(&pdev->dev, "%s: wait_ready ERROR", __func__);
> +			goto err_exit;
> +		}
> +		if ((value & ASMT_CONTROL_WRITE_BIT) == 0)
> +			break;
> +		wait_time_count--;
> +		usleep(50);
> +	}
> +	if (wait_time_count == 0) {
> +		dev_dbg(&pdev->dev, "%s: wait_write_ready timeout", __func__);

Same here.

> +		goto err_exit;
> +	}
> +	/* send data to device */
> +	pci_write_config_dword(pdev, ASMT_DATA_WRITE0_REG, ASMT_FLOWCTL_DATA);
> +	pci_write_config_dword(pdev, ASMT_DATA_WRITE1_REG, ASMT_PSEUDO_DATA);
> +	pci_write_config_byte(pdev, ASMT_CONTROL_REG, ASMT_CONTROL_WRITE_BIT);
> +err_exit:
> +	return;
> +}
> +EXPORT_SYMBOL_GPL(usb_asmedia_modifyflowcontrol);
> +
>  void usb_amd_quirk_pll_enable(void)
>  {
>  	usb_amd_quirk_pll(0);
> diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h
> index 0222195..6ce1df1 100644
> --- a/drivers/usb/host/pci-quirks.h
> +++ b/drivers/usb/host/pci-quirks.h
> @@ -11,6 +11,7 @@ bool usb_amd_prefetch_quirk(void);
>  void usb_amd_dev_put(void);
>  void usb_amd_quirk_pll_disable(void);
>  void usb_amd_quirk_pll_enable(void);
> +void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev);
>  void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev);
>  void usb_disable_xhci_ports(struct pci_dev *xhci_pdev);
>  void sb800_prefetch(struct device *dev, int on);
> diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
> index fcf1f3f..fba52f0 100644
> --- a/drivers/usb/host/xhci-pci.c
> +++ b/drivers/usb/host/xhci-pci.c
> @@ -53,6 +53,7 @@
>  #define PCI_DEVICE_ID_INTEL_BROXTON_B_XHCI		0x1aa8
>  #define PCI_DEVICE_ID_INTEL_APL_XHCI			0x5aa8
>  #define PCI_DEVICE_ID_INTEL_DNV_XHCI			0x19d0
> +#define PCI_DEVICE_ID_ASMEDIA_1042A_XHCI		0x1142
>  
>  static const char hcd_name[] = "xhci_hcd";
>  
> @@ -202,6 +203,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
>  			pdev->device == 0x1042)
>  		xhci->quirks |= XHCI_BROKEN_STREAMS;
>  
> +	if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
> +		pdev->device == PCI_DEVICE_ID_ASMEDIA_1042A_XHCI)
> +		xhci->quirks |= XHCI_ASMEDIA_MODIFY_FLOWCONTROL;
> +
>  	if (pdev->vendor == PCI_VENDOR_ID_TI && pdev->device == 0x8241)
>  		xhci->quirks |= XHCI_LIMIT_ENDPOINT_INTERVAL_7;
>  
> diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
> index 30f47d9..dcc310d 100644
> --- a/drivers/usb/host/xhci.c
> +++ b/drivers/usb/host/xhci.c
> @@ -625,6 +625,9 @@ int xhci_run(struct usb_hcd *hcd)
>  		xhci_queue_vendor_command(xhci, command, 0, 0, 0,
>  				TRB_TYPE(TRB_NEC_GET_FW));
>  	}
> +	if (xhci->quirks & XHCI_ASMEDIA_MODIFY_FLOWCONTROL)
> +		usb_asmedia_modifyflowcontrol(to_pci_dev(hcd->self.controller));
> +
>  	xhci_dbg_trace(xhci, trace_xhci_dbg_init,
>  			"Finished xhci_run for USB2 roothub");
>  	return 0;
> diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
> index 73a28a9..ed58f87 100644
> --- a/drivers/usb/host/xhci.h
> +++ b/drivers/usb/host/xhci.h
> @@ -1819,6 +1819,7 @@ struct xhci_hcd {
>  /* For controller with a broken Port Disable implementation */
>  #define XHCI_BROKEN_PORT_PED	(1 << 25)
>  #define XHCI_LIMIT_ENDPOINT_INTERVAL_7	(1 << 26)
> +#define XHCI_ASMEDIA_MODIFY_FLOWCONTROL	(1<<27)

BIT(27)?

At the least, follow the ' ' rules of the above #defines please.

thanks,

greg k-h
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux