Re: [PATCH 4/5 v2] xHCI: report USB3.0 portstatus comply with USB3.0 specification

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

 



On Tue, 29 Mar 2011, Andiry Xu wrote:

> USB3.0 specification has different wPortStatus and wPortChange definitions
> from USB2.0 specification. Since USB3 root hub and USB2 root hub are split
> now and USB3 hub only has USB3 protocol ports, we should modify the
> portstatus and portchange report of USB3 ports to comply with USB3.0
> specification.
> 
> Signed-off-by: Andiry Xu <andiry.xu@xxxxxxx>
> ---
>  drivers/usb/core/hub.c      |   52 ++++++++++++++++++++++++++++++------------
>  drivers/usb/host/xhci-hub.c |   23 +++++++++++++++----
>  2 files changed, 55 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
> index 0968157..bc6f39c 100644
> --- a/drivers/usb/core/hub.c
> +++ b/drivers/usb/core/hub.c
> @@ -379,15 +379,6 @@ static int hub_port_status(struct usb_hub *hub, int port1,
>  		*status = le16_to_cpu(hub->status->port.wPortStatus);
>  		*change = le16_to_cpu(hub->status->port.wPortChange);
>  
> -		if ((hub->hdev->parent != NULL) &&
> -				hub_is_superspeed(hub->hdev)) {
> -			/* Translate the USB 3 port status */
> -			u16 tmp = *status & USB_SS_PORT_STAT_MASK;
> -			if (*status & USB_SS_PORT_STAT_POWER)
> -				tmp |= USB_PORT_STAT_POWER;
> -			*status = tmp;
> -		}
> -
>  		ret = 0;
>  	}
>  	mutex_unlock(&hub->status_mutex);
> @@ -2158,11 +2149,40 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
>  	return status;
>  }
>  
> +/* Check if a port is power on */
> +static int port_is_power_on(struct usb_hub *hub, unsigned portstatus)
> +{
> +	int ret = 0;
> +
> +	if (hub_is_superspeed(hub->hdev)) {
> +		if (portstatus & USB_SS_PORT_STAT_POWER)
> +			ret = 1;
> +	} else {
> +		if (portstatus & USB_PORT_STAT_POWER)
> +			ret = 1;
> +	}
> +
> +	return ret;
> +}
> +
>  #ifdef	CONFIG_PM
>  
> -#define MASK_BITS	(USB_PORT_STAT_POWER | USB_PORT_STAT_CONNECTION | \
> -				USB_PORT_STAT_SUSPEND)
> -#define WANT_BITS	(USB_PORT_STAT_POWER | USB_PORT_STAT_CONNECTION)
> +/* Check if a port is suspended(USB2.0 port) or in U3 state(USB3.0 port) */
> +static int port_is_suspended(struct usb_hub *hub, unsigned portstatus)
> +{
> +	int ret = 0;
> +
> +	if (hub_is_superspeed(hub->hdev)) {
> +		if ((portstatus & USB_PORT_STAT_LINK_STATE)
> +				== USB_SS_PORT_LS_U3)
> +			ret = 1;
> +	} else {
> +		if (portstatus & USB_PORT_STAT_SUSPEND)
> +			ret = 1;
> +	}
> +
> +	return ret;
> +}
>  
>  /* Determine whether the device on a port is ready for a normal resume,
>   * is ready for a reset-resume, or should be disconnected.
> @@ -2172,7 +2192,9 @@ static int check_port_resume_type(struct usb_device *udev,
>  		int status, unsigned portchange, unsigned portstatus)
>  {
>  	/* Is the device still present? */
> -	if (status || (portstatus & MASK_BITS) != WANT_BITS) {
> +	if (status || port_is_suspended(hub, portstatus) ||
> +			!port_is_power_on(hub, portstatus) ||
> +			!(portstatus & USB_PORT_STAT_CONNECTION)) {
>  		if (status >= 0)
>  			status = -ENODEV;
>  	}
> @@ -2427,7 +2449,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
>  
>  	/* Skip the initial Clear-Suspend step for a remote wakeup */
>  	status = hub_port_status(hub, port1, &portstatus, &portchange);
> -	if (status == 0 && !(portstatus & USB_PORT_STAT_SUSPEND))
> +	if (status == 0 && !port_is_suspended(hub, portstatus))
>  		goto SuspendCleared;
>  
>  	// dev_dbg(hub->intfdev, "resume port %d\n", port1);
> @@ -3139,7 +3161,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
>  
>  		/* maybe switch power back on (e.g. root hub was reset) */
>  		if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2
> -				&& !(portstatus & USB_PORT_STAT_POWER))
> +				&& !port_is_power_on(hub, portstatus))
>  			set_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
>  
>  		if (portstatus & USB_PORT_STAT_ENABLE)

This part is now indeed a lot cleaner.  Thanks.

Acked-by: Alan Stern <stern@xxxxxxxxxxxxxxxxxxx>

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