Re: [PATCH] xHCI: BESL calculation based on USB2.0 LPM errata

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

 



On 12/12/2011 04:45 PM, Andiry Xu wrote:
> The latest released errata for USB2.0 ECN LPM adds new fields to USB2.0
> extension descriptor, defines two BESL values for device: baseline BESL
> and deep BESL. Baseline BESL value communicates a nominal power savings
> design point and the deep BESL value communicates a significant power
> savings design point.
> 
> If device indicates BESL value, driver will use a value count in both
> host BESL and device BESL. Use baseline BESL value as default.
> 
> Signed-off-by: Andiry Xu <andiry.xu@xxxxxxx>
> Tested-by: Jason Fan <jcfan@xxxxxxxxxxxxxxxx>

Ping. I'm curious about the fate of this patch... Is it lost in the sea
of mails?

Thanks,
Andiry

> ---
>  drivers/usb/host/xhci.c |   51
> ++++++++++++++++++++++++----------------------
>  include/linux/usb/ch9.h |    5 ++++
>  2 files changed, 32 insertions(+), 24 deletions(-)
> 
> diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
> index a1afb7c..79943ee 100644
> --- a/drivers/usb/host/xhci.c
> +++ b/drivers/usb/host/xhci.c
> @@ -3606,26 +3606,38 @@ static int xhci_besl_encoding[16] = {125, 150,
> 200, 300, 400, 500, 1000, 2000,
>  	3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000};
>  
>  /* Calculate HIRD/BESL for USB2 PORTPMSC*/
> -static int xhci_calculate_hird_besl(int u2del, bool use_besl)
> +static int xhci_calculate_hird_besl(struct xhci_hcd *xhci,
> +					struct usb_device *udev)
>  {
> -	int hird;
> +	int u2del, besl, besl_host;
> +	int besl_device = 0;
> +	u32 field;
> +
> +	u2del = HCS_U2_LATENCY(xhci->hcs_params3);
> +	field = le32_to_cpu(udev->bos->ext_cap->bmAttributes);
>  
> -	if (use_besl) {
> -		for (hird = 0; hird < 16; hird++) {
> -			if (xhci_besl_encoding[hird] >= u2del)
> +	if (field & USB_BESL_SUPPORT) {
> +		for (besl_host = 0; besl_host < 16; besl_host++) {
> +			if (xhci_besl_encoding[besl_host] >= u2del)
>  				break;
>  		}
> +		/* Use baseline BESL value as default */
> +		if (field & USB_BESL_BASELINE_VALID)
> +			besl_device = USB_GET_BESL_BASELINE(field);
> +		else if (field & USB_BESL_DEEP_VALID)
> +			besl_device = USB_GET_BESL_DEEP(field);
>  	} else {
>  		if (u2del <= 50)
> -			hird = 0;
> +			besl_host = 0;
>  		else
> -			hird = (u2del - 51) / 75 + 1;
> -
> -		if (hird > 15)
> -			hird = 15;
> +			besl_host = (u2del - 51) / 75 + 1;
>  	}
>  
> -	return hird;
> +	besl = besl_host + besl_device;
> +	if (besl > 15)
> +		besl = 15;
> +
> +	return besl;
>  }
>  
>  static int xhci_usb2_software_lpm_test(struct usb_hcd *hcd,
> @@ -3638,7 +3650,7 @@ static int xhci_usb2_software_lpm_test(struct
> usb_hcd *hcd,
>  	u32		temp, dev_id;
>  	unsigned int	port_num;
>  	unsigned long	flags;
> -	int		u2del, hird;
> +	int		hird;
>  	int		ret;
>  
>  	if (hcd->speed == HCD_USB3 || !xhci->sw_lpm_support ||
> @@ -3684,12 +3696,7 @@ static int xhci_usb2_software_lpm_test(struct
> usb_hcd *hcd,
>  	 * HIRD or BESL shoule be used. See USB2.0 LPM errata.
>  	 */
>  	pm_addr = port_array[port_num] + 1;
> -	u2del = HCS_U2_LATENCY(xhci->hcs_params3);
> -	if (le32_to_cpu(udev->bos->ext_cap->bmAttributes) & (1 << 2))
> -		hird = xhci_calculate_hird_besl(u2del, 1);
> -	else
> -		hird = xhci_calculate_hird_besl(u2del, 0);
> -
> +	hird = xhci_calculate_hird_besl(xhci, udev);
>  	temp = PORT_L1DS(udev->slot_id) | PORT_HIRD(hird);
>  	xhci_writel(xhci, temp, pm_addr);
>  
> @@ -3768,7 +3775,7 @@ int xhci_set_usb2_hardware_lpm(struct usb_hcd
> *hcd,
>  	u32		temp;
>  	unsigned int	port_num;
>  	unsigned long	flags;
> -	int		u2del, hird;
> +	int		hird;
>  
>  	if (hcd->speed == HCD_USB3 || !xhci->hw_lpm_support ||
>  			!udev->lpm_capable)
> @@ -3791,11 +3798,7 @@ int xhci_set_usb2_hardware_lpm(struct usb_hcd
> *hcd,
>  	xhci_dbg(xhci, "%s port %d USB2 hardware LPM\n",
>  			enable ? "enable" : "disable", port_num);
>  
> -	u2del = HCS_U2_LATENCY(xhci->hcs_params3);
> -	if (le32_to_cpu(udev->bos->ext_cap->bmAttributes) & (1 << 2))
> -		hird = xhci_calculate_hird_besl(u2del, 1);
> -	else
> -		hird = xhci_calculate_hird_besl(u2del, 0);
> +	hird = xhci_calculate_hird_besl(xhci, udev);
>  
>  	if (enable) {
>  		temp &= ~PORT_HIRD_MASK;
> diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h
> index d5da6c6..b94f5ba 100644
> --- a/include/linux/usb/ch9.h
> +++ b/include/linux/usb/ch9.h
> @@ -771,6 +771,11 @@ struct usb_ext_cap_descriptor {		/* Link
> Power Management */
>  	__u8  bDevCapabilityType;
>  	__le32 bmAttributes;
>  #define USB_LPM_SUPPORT			(1 << 1)	/*
> supports LPM */
> +#define USB_BESL_SUPPORT		(1 << 2)	/* supports BESL
> */
> +#define USB_BESL_BASELINE_VALID		(1 << 3)	/*
> Baseline BESL valid*/
> +#define USB_BESL_DEEP_VALID		(1 << 4)	/* Deep BESL
> valid */
> +#define USB_GET_BESL_BASELINE(p)	(((p) & (0xf << 8)) >> 8)
> +#define USB_GET_BESL_DEEP(p)		(((p) & (0xf << 12)) >> 12)
>  } __attribute__((packed));
>  
>  #define USB_DT_USB_EXT_CAP_SIZE	7


--
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