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