Re: [PATCH v2] USB: Add support for SuperSpeed hubs

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

 



Nak on this patch, see the previous email.

Sarah Sharp

On Fri, Feb 25, 2011 at 03:01:07PM -0800, Paul Zimmerman wrote:
> From: John Youn <johnyoun@xxxxxxxxxxxx>
> 
> Make the following changes to work with SuperSpeed hubs:
> - Add new constants in header
> - Add check for superspeed hubs
> - Skip some things not needed for superspeed hub
> - Set the hub depth after enumeration to address downstream ports
> - Modify the port status and port changed bits from the hub
> 
> Signed-off-by: John Youn <johnyoun@xxxxxxxxxxxx>
> Signed-off-by: Paul Zimmerman <paulz@xxxxxxxxxxxx>
> ---
> 
> v2 - Rediffed against Greg's usb-next branch
> 
> Hi Sarah,
> 
> Can we finally get John's hub patches queued for .39? There are SuperSpeed
> hubs in the market now (e.g.
> http://www.amazon.com/SuperSpeed-USB-3-0-7-Port-Hub/dp/B003NE5I9I) so I
> think we should have the support in the kernel. It also makes it easier
> for us not needing to patch the kernel every time a new version is
> released.
> 
> I seem to recall some objections to a couple of things in the patch, but I
> don't remember what those were now.
> 
> The diffs are against Greg's usb-next branch.
> 
> -Paul
> 
> 
>  drivers/usb/core/hub.c   |   60 ++++++++++++++++++++++++++++++++++++++++++--
>  include/linux/usb/ch11.h |   62 ++++++++++++++++++++++++++++++++++------------
>  2 files changed, 103 insertions(+), 19 deletions(-)
> 
> diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
> index c168121..5dd9dd1 100644
> --- a/drivers/usb/core/hub.c
> +++ b/drivers/usb/core/hub.c
> @@ -82,6 +82,10 @@ struct usb_hub {
>  	void			**port_owners;
>  };
>  
> +static inline int hub_is_superspeed(struct usb_device *hdev)
> +{
> +	return (hdev->descriptor.bDeviceProtocol == 3);
> +}
>  
>  /* Protect struct usb_device->state and ->children members
>   * Note: Both are also protected by ->dev.sem, except that ->state can
> @@ -176,10 +180,17 @@ static int get_hub_descriptor(struct usb_device *hdev, void *data, int size)
>  {
>  	int i, ret;
>  
> +	unsigned dtype = USB_DT_HUB;
> +
> +	if (hub_is_superspeed(hdev)) {
> +		dtype = USB_DT_SS_HUB;
> +		size = 12;
> +	}
> +
>  	for (i = 0; i < 3; i++) {
>  		ret = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
>  			USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB,
> -			USB_DT_HUB << 8, 0, data, size,
> +			dtype << 8, 0, data, size,
>  			USB_CTRL_GET_TIMEOUT);
>  		if (ret >= (USB_DT_HUB_NONVAR_SIZE + 2))
>  			return ret;
> @@ -365,6 +376,17 @@ static int hub_port_status(struct usb_hub *hub, int port1,
>  	} else {
>  		*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 & USB3_PORT_STAT_MASK;
> +			if (*status & USB3_PORT_STAT_POWER)
> +				tmp |= USB_PORT_STAT_POWER;
> +			if ((*status & USB3_PORT_STAT_SPEED) == USB3_PORT_STAT_SPEED_SUPER)
> +				tmp |= USB_PORT_STAT_SUPER_SPEED;
> +			*status = tmp;
> +		}
> +
>  		ret = 0;
>  	}
>  	mutex_unlock(&hub->status_mutex);
> @@ -607,7 +629,7 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
>  	if (hdev->children[port1-1] && set_state)
>  		usb_set_device_state(hdev->children[port1-1],
>  				USB_STATE_NOTATTACHED);
> -	if (!hub->error)
> +	if (!hub->error && !hub_is_superspeed(hdev))
>  		ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE);
>  	if (ret)
>  		dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n",
> @@ -795,6 +817,11 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
>  			clear_port_feature(hub->hdev, port1,
>  					USB_PORT_FEAT_C_ENABLE);
>  		}
> +		if (portchange & USB_PORT_STAT_C_LINK_STATE) {
> +			need_debounce_delay = true;
> +			clear_port_feature(hub->hdev, port1,
> +					USB_PORT_FEAT_C_PORT_LINK_STATE);
> +		}
>  
>  		/* We can forget about a "removed" device when there's a
>  		 * physical disconnect or the connect status changes.
> @@ -964,6 +991,18 @@ static int hub_configure(struct usb_hub *hub,
>  		goto fail;
>  	}
>  
> +	if (hub_is_superspeed(hdev) && (hdev->parent != NULL)) {
> +		ret = usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
> +				HUB_SET_DEPTH, USB_RT_HUB,
> +				hdev->level - 1, 0, NULL, 0,
> +				USB_CTRL_SET_TIMEOUT);
> +
> +		if (ret < 0) {
> +			message = "can't set hub depth";
> +			goto fail;
> +		}
> +	}
> +
>  	/* Request the entire hub descriptor.
>  	 * hub->descriptor can handle USB_MAXCHILDREN ports,
>  	 * but the hub can/will return fewer bytes here.
> @@ -991,7 +1030,8 @@ static int hub_configure(struct usb_hub *hub,
>  
>  	wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics);
>  
> -	if (wHubCharacteristics & HUB_CHAR_COMPOUND) {
> +	/* FIXME for USB 3.0, skip for now */
> +	if ((wHubCharacteristics & HUB_CHAR_COMPOUND) && !(hub_is_superspeed(hdev))) {
>  		int	i;
>  		char	portstr [USB_MAXCHILDREN + 1];
>  
> @@ -3423,6 +3463,20 @@ static void hub_events(void)
>  				clear_port_feature(hdev, i,
>  					USB_PORT_FEAT_C_RESET);
>  			}
> +			if (portchange & USB_PORT_STAT_C_LINK_STATE) {
> +				dev_dbg (hub_dev,
> +					"link state change on port %d\n",
> +					i);
> +				clear_port_feature(hub->hdev, i,
> +						USB_PORT_FEAT_C_PORT_LINK_STATE);
> +			}
> +			if (portchange & USB_PORT_STAT_C_CONFIG_ERROR) {
> +				dev_dbg (hub_dev,
> +					"config error on port %d\n",
> +					i);
> +				clear_port_feature(hub->hdev, i,
> +						USB_PORT_FEAT_C_PORT_CONFIG_ERROR);
> +			}
>  
>  			if (connect_change)
>  				hub_port_connect_change(hub, i,
> diff --git a/include/linux/usb/ch11.h b/include/linux/usb/ch11.h
> index 38c42b0..a87153e 100644
> --- a/include/linux/usb/ch11.h
> +++ b/include/linux/usb/ch11.h
> @@ -26,6 +26,7 @@
>  #define HUB_RESET_TT		9
>  #define HUB_GET_TT_STATE	10
>  #define HUB_STOP_TT		11
> +#define HUB_SET_DEPTH		12
>  
>  /*
>   * Hub class additional requests defined by USB 3.0 spec
> @@ -45,22 +46,28 @@
>   * Port feature numbers
>   * See USB 2.0 spec Table 11-17
>   */
> -#define USB_PORT_FEAT_CONNECTION	0
> -#define USB_PORT_FEAT_ENABLE		1
> -#define USB_PORT_FEAT_SUSPEND		2	/* L2 suspend */
> -#define USB_PORT_FEAT_OVER_CURRENT	3
> -#define USB_PORT_FEAT_RESET		4
> -#define USB_PORT_FEAT_L1		5	/* L1 suspend */
> -#define USB_PORT_FEAT_POWER		8
> -#define USB_PORT_FEAT_LOWSPEED		9	/* Should never be used */
> -#define USB_PORT_FEAT_C_CONNECTION	16
> -#define USB_PORT_FEAT_C_ENABLE		17
> -#define USB_PORT_FEAT_C_SUSPEND		18
> -#define USB_PORT_FEAT_C_OVER_CURRENT	19
> -#define USB_PORT_FEAT_C_RESET		20
> -#define USB_PORT_FEAT_TEST              21
> -#define USB_PORT_FEAT_INDICATOR         22
> -#define USB_PORT_FEAT_C_PORT_L1         23
> +#define USB_PORT_FEAT_CONNECTION		0
> +#define USB_PORT_FEAT_ENABLE			1
> +#define USB_PORT_FEAT_SUSPEND			2     /* L2 suspend */
> +#define USB_PORT_FEAT_OVER_CURRENT		3
> +#define USB_PORT_FEAT_RESET			4
> +#define USB_PORT_FEAT_L1			5     /* L1 suspend */
> +#define USB_PORT_FEAT_POWER			8
> +#define USB_PORT_FEAT_LOWSPEED			9     /* Should never be used */
> +#define USB_PORT_FEAT_C_CONNECTION		16
> +#define USB_PORT_FEAT_C_ENABLE			17
> +#define USB_PORT_FEAT_C_SUSPEND			18
> +#define USB_PORT_FEAT_C_OVER_CURRENT		19
> +#define USB_PORT_FEAT_C_RESET			20
> +#define USB_PORT_FEAT_TEST			21
> +#define USB_PORT_FEAT_INDICATOR			22
> +#define USB_PORT_FEAT_C_PORT_L1			23
> +#define USB_PORT_FEAT_C_PORT_LINK_STATE		25
> +#define USB_PORT_FEAT_C_PORT_CONFIG_ERROR	26
> +#define USB_PORT_FEAT_PORT_REMOTE_WAKE_MASK	27
> +#define USB_PORT_FEAT_BH_PORT_RESET		28
> +#define USB_PORT_FEAT_C_BH_PORT_RESET		29
> +#define USB_PORT_FEAT_FORCE_LINKPM_ACCEPT	30
>  
>  /*
>   * Port feature selectors added by USB 3.0 spec.
> @@ -131,6 +138,21 @@ struct usb_port_status {
>  #define USB_SS_PORT_LS_LOOPBACK		0x0160
>  
>  /*
> + * USB 3.0 wPortStatus bit fields
> + * See USB 3.0 spec Table 10-10
> + */
> +/* Bits that are the same from USB 2.0 */
> +#define USB3_PORT_STAT_MASK (USB_PORT_STAT_CONNECTION |		\
> +				USB_PORT_STAT_ENABLE |		\
> +				USB_PORT_STAT_OVERCURRENT |	\
> +				USB_PORT_STAT_RESET)
> +/* 3.0 specific bits */
> +#define USB3_PORT_STAT_LINK_STATE	0x01e0
> +#define USB3_PORT_STAT_POWER		0x0200
> +#define USB3_PORT_STAT_SPEED		0x1c00
> +#define USB3_PORT_STAT_SPEED_SUPER	0x0
> +
> +/*
>   * wPortChange bit field
>   * See USB 2.0 spec Table 11-22 and USB 2.0 LPM ECN Table-4.10
>   * Bits 0 to 5 shown, bits 6 to 15 are reserved
> @@ -141,6 +163,13 @@ struct usb_port_status {
>  #define USB_PORT_STAT_C_OVERCURRENT	0x0008
>  #define USB_PORT_STAT_C_RESET		0x0010
>  #define USB_PORT_STAT_C_L1		0x0020
> +/*
> + * USB 3.0 wPortChange bit fields
> + * See USB 3.0 spec Table 10-11
> + */
> +#define USB_PORT_STAT_C_BH_RESET	0x0020
> +#define USB_PORT_STAT_C_LINK_STATE	0x0040
> +#define USB_PORT_STAT_C_CONFIG_ERROR	0x0080
>  
>  /*
>   * wHubCharacteristics (masks)
> @@ -175,6 +204,7 @@ struct usb_hub_status {
>   */
>  
>  #define USB_DT_HUB			(USB_TYPE_CLASS | 0x09)
> +#define USB_DT_SS_HUB			(USB_TYPE_CLASS | 0x0a)
>  #define USB_DT_HUB_NONVAR_SIZE		7
>  
>  struct usb_hub_descriptor {
> -- 
> 1.6.5.1.69.g36942
> 
> 
--
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