Commit 59afff14 authored by Mathias Nyman's avatar Mathias Nyman Committed by Greg Kroah-Hartman

usb: define USB_SPEED_SUPER_PLUS speed for SuperSpeedPlus USB3.1 devices

commit 8a1b2725 upstream.

Add a new USB_SPEED_SUPER_PLUS device speed, and make sure usb core can
handle the new speed.
In most cases the behaviour is the same as with USB_SPEED_SUPER SuperSpeed
devices. In a few places we add a "Plus" string to inform the user of the
new speed.
Signed-off-by: default avatarMathias Nyman <mathias.nyman@linux.intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent baa329fa
...@@ -192,6 +192,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum, ...@@ -192,6 +192,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
if (usb_endpoint_xfer_int(d)) { if (usb_endpoint_xfer_int(d)) {
i = 1; i = 1;
switch (to_usb_device(ddev)->speed) { switch (to_usb_device(ddev)->speed) {
case USB_SPEED_SUPER_PLUS:
case USB_SPEED_SUPER: case USB_SPEED_SUPER:
case USB_SPEED_HIGH: case USB_SPEED_HIGH:
/* Many device manufacturers are using full-speed /* Many device manufacturers are using full-speed
...@@ -264,7 +265,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum, ...@@ -264,7 +265,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
} }
/* Parse a possible SuperSpeed endpoint companion descriptor */ /* Parse a possible SuperSpeed endpoint companion descriptor */
if (to_usb_device(ddev)->speed == USB_SPEED_SUPER) if (to_usb_device(ddev)->speed >= USB_SPEED_SUPER)
usb_parse_ss_endpoint_companion(ddev, cfgno, usb_parse_ss_endpoint_companion(ddev, cfgno,
inum, asnum, endpoint, buffer, size); inum, asnum, endpoint, buffer, size);
......
...@@ -221,7 +221,7 @@ static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end, ...@@ -221,7 +221,7 @@ static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end,
break; break;
case USB_ENDPOINT_XFER_INT: case USB_ENDPOINT_XFER_INT:
type = "Int."; type = "Int.";
if (speed == USB_SPEED_HIGH || speed == USB_SPEED_SUPER) if (speed == USB_SPEED_HIGH || speed >= USB_SPEED_SUPER)
interval = 1 << (desc->bInterval - 1); interval = 1 << (desc->bInterval - 1);
else else
interval = desc->bInterval; interval = desc->bInterval;
...@@ -230,7 +230,7 @@ static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end, ...@@ -230,7 +230,7 @@ static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end,
return start; return start;
} }
interval *= (speed == USB_SPEED_HIGH || interval *= (speed == USB_SPEED_HIGH ||
speed == USB_SPEED_SUPER) ? 125 : 1000; speed >= USB_SPEED_SUPER) ? 125 : 1000;
if (interval % 1000) if (interval % 1000)
unit = 'u'; unit = 'u';
else { else {
...@@ -322,7 +322,7 @@ static char *usb_dump_config_descriptor(char *start, char *end, ...@@ -322,7 +322,7 @@ static char *usb_dump_config_descriptor(char *start, char *end,
if (start > end) if (start > end)
return start; return start;
if (speed == USB_SPEED_SUPER) if (speed >= USB_SPEED_SUPER)
mul = 8; mul = 8;
else else
mul = 2; mul = 2;
...@@ -534,6 +534,8 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, ...@@ -534,6 +534,8 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes,
speed = "480"; break; speed = "480"; break;
case USB_SPEED_SUPER: case USB_SPEED_SUPER:
speed = "5000"; break; speed = "5000"; break;
case USB_SPEED_SUPER_PLUS:
speed = "10000"; break;
default: default:
speed = "??"; speed = "??";
} }
...@@ -553,7 +555,7 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, ...@@ -553,7 +555,7 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes,
/* super/high speed reserves 80%, full/low reserves 90% */ /* super/high speed reserves 80%, full/low reserves 90% */
if (usbdev->speed == USB_SPEED_HIGH || if (usbdev->speed == USB_SPEED_HIGH ||
usbdev->speed == USB_SPEED_SUPER) usbdev->speed >= USB_SPEED_SUPER)
max = 800; max = 800;
else else
max = FRAME_TIME_MAX_USECS_ALLOC; max = FRAME_TIME_MAX_USECS_ALLOC;
......
...@@ -207,7 +207,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) ...@@ -207,7 +207,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
* The xHCI driver has its own irq management * The xHCI driver has its own irq management
* make sure irq setup is not touched for xhci in generic hcd code * make sure irq setup is not touched for xhci in generic hcd code
*/ */
if ((driver->flags & HCD_MASK) != HCD_USB3) { if ((driver->flags & HCD_MASK) < HCD_USB3) {
if (!dev->irq) { if (!dev->irq) {
dev_err(&dev->dev, dev_err(&dev->dev,
"Found HC with no IRQ. Check BIOS/PCI %s setup!\n", "Found HC with no IRQ. Check BIOS/PCI %s setup!\n",
......
...@@ -1024,7 +1024,7 @@ static int register_root_hub(struct usb_hcd *hcd) ...@@ -1024,7 +1024,7 @@ static int register_root_hub(struct usb_hcd *hcd)
dev_name(&usb_dev->dev), retval); dev_name(&usb_dev->dev), retval);
return (retval < 0) ? retval : -EMSGSIZE; return (retval < 0) ? retval : -EMSGSIZE;
} }
if (usb_dev->speed == USB_SPEED_SUPER) { if (usb_dev->speed >= USB_SPEED_SUPER) {
retval = usb_get_bos_descriptor(usb_dev); retval = usb_get_bos_descriptor(usb_dev);
if (retval < 0) { if (retval < 0) {
mutex_unlock(&usb_bus_list_lock); mutex_unlock(&usb_bus_list_lock);
...@@ -2055,7 +2055,7 @@ int usb_alloc_streams(struct usb_interface *interface, ...@@ -2055,7 +2055,7 @@ int usb_alloc_streams(struct usb_interface *interface,
hcd = bus_to_hcd(dev->bus); hcd = bus_to_hcd(dev->bus);
if (!hcd->driver->alloc_streams || !hcd->driver->free_streams) if (!hcd->driver->alloc_streams || !hcd->driver->free_streams)
return -EINVAL; return -EINVAL;
if (dev->speed != USB_SPEED_SUPER) if (dev->speed < USB_SPEED_SUPER)
return -EINVAL; return -EINVAL;
if (dev->state < USB_STATE_CONFIGURED) if (dev->state < USB_STATE_CONFIGURED)
return -ENODEV; return -ENODEV;
...@@ -2093,7 +2093,7 @@ int usb_free_streams(struct usb_interface *interface, ...@@ -2093,7 +2093,7 @@ int usb_free_streams(struct usb_interface *interface,
dev = interface_to_usbdev(interface); dev = interface_to_usbdev(interface);
hcd = bus_to_hcd(dev->bus); hcd = bus_to_hcd(dev->bus);
if (dev->speed != USB_SPEED_SUPER) if (dev->speed < USB_SPEED_SUPER)
return -EINVAL; return -EINVAL;
/* Streams only apply to bulk endpoints. */ /* Streams only apply to bulk endpoints. */
......
...@@ -297,7 +297,7 @@ static void usb_set_lpm_parameters(struct usb_device *udev) ...@@ -297,7 +297,7 @@ static void usb_set_lpm_parameters(struct usb_device *udev)
unsigned int hub_u1_del; unsigned int hub_u1_del;
unsigned int hub_u2_del; unsigned int hub_u2_del;
if (!udev->lpm_capable || udev->speed != USB_SPEED_SUPER) if (!udev->lpm_capable || udev->speed < USB_SPEED_SUPER)
return; return;
hub = usb_hub_to_struct_hub(udev->parent); hub = usb_hub_to_struct_hub(udev->parent);
...@@ -2559,7 +2559,7 @@ static unsigned hub_is_wusb(struct usb_hub *hub) ...@@ -2559,7 +2559,7 @@ static unsigned hub_is_wusb(struct usb_hub *hub)
*/ */
static bool use_new_scheme(struct usb_device *udev, int retry) static bool use_new_scheme(struct usb_device *udev, int retry)
{ {
if (udev->speed == USB_SPEED_SUPER) if (udev->speed >= USB_SPEED_SUPER)
return false; return false;
return USE_NEW_SCHEME(retry); return USE_NEW_SCHEME(retry);
...@@ -3812,7 +3812,7 @@ int usb_disable_lpm(struct usb_device *udev) ...@@ -3812,7 +3812,7 @@ int usb_disable_lpm(struct usb_device *udev)
struct usb_hcd *hcd; struct usb_hcd *hcd;
if (!udev || !udev->parent || if (!udev || !udev->parent ||
udev->speed != USB_SPEED_SUPER || udev->speed < USB_SPEED_SUPER ||
!udev->lpm_capable) !udev->lpm_capable)
return 0; return 0;
...@@ -3868,7 +3868,7 @@ void usb_enable_lpm(struct usb_device *udev) ...@@ -3868,7 +3868,7 @@ void usb_enable_lpm(struct usb_device *udev)
struct usb_hcd *hcd; struct usb_hcd *hcd;
if (!udev || !udev->parent || if (!udev || !udev->parent ||
udev->speed != USB_SPEED_SUPER || udev->speed < USB_SPEED_SUPER ||
!udev->lpm_capable) !udev->lpm_capable)
return; return;
...@@ -4127,7 +4127,9 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, ...@@ -4127,7 +4127,9 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
retval = -ENODEV; retval = -ENODEV;
if (oldspeed != USB_SPEED_UNKNOWN && oldspeed != udev->speed) { /* Don't allow speed changes at reset, except usb 3.0 to faster */
if (oldspeed != USB_SPEED_UNKNOWN && oldspeed != udev->speed &&
!(oldspeed == USB_SPEED_SUPER && udev->speed > oldspeed)) {
dev_dbg(&udev->dev, "device reset changed speed!\n"); dev_dbg(&udev->dev, "device reset changed speed!\n");
goto fail; goto fail;
} }
...@@ -4139,6 +4141,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, ...@@ -4139,6 +4141,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
* reported as 0xff in the device descriptor). WUSB1.0[4.8.1]. * reported as 0xff in the device descriptor). WUSB1.0[4.8.1].
*/ */
switch (udev->speed) { switch (udev->speed) {
case USB_SPEED_SUPER_PLUS:
case USB_SPEED_SUPER: case USB_SPEED_SUPER:
case USB_SPEED_WIRELESS: /* fixed at 512 */ case USB_SPEED_WIRELESS: /* fixed at 512 */
udev->ep0.desc.wMaxPacketSize = cpu_to_le16(512); udev->ep0.desc.wMaxPacketSize = cpu_to_le16(512);
...@@ -4165,7 +4168,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, ...@@ -4165,7 +4168,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
else else
speed = usb_speed_string(udev->speed); speed = usb_speed_string(udev->speed);
if (udev->speed != USB_SPEED_SUPER) if (udev->speed < USB_SPEED_SUPER)
dev_info(&udev->dev, dev_info(&udev->dev,
"%s %s USB device number %d using %s\n", "%s %s USB device number %d using %s\n",
(udev->config) ? "reset" : "new", speed, (udev->config) ? "reset" : "new", speed,
...@@ -4291,11 +4294,12 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, ...@@ -4291,11 +4294,12 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
devnum, retval); devnum, retval);
goto fail; goto fail;
} }
if (udev->speed == USB_SPEED_SUPER) { if (udev->speed >= USB_SPEED_SUPER) {
devnum = udev->devnum; devnum = udev->devnum;
dev_info(&udev->dev, dev_info(&udev->dev,
"%s SuperSpeed USB device number %d using %s\n", "%s SuperSpeed%s USB device number %d using %s\n",
(udev->config) ? "reset" : "new", (udev->config) ? "reset" : "new",
(udev->speed == USB_SPEED_SUPER_PLUS) ? "Plus" : "",
devnum, udev->bus->controller->driver->name); devnum, udev->bus->controller->driver->name);
} }
...@@ -4337,7 +4341,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, ...@@ -4337,7 +4341,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
* got from those devices show they aren't superspeed devices. Warm * got from those devices show they aren't superspeed devices. Warm
* reset the port attached by the devices can fix them. * reset the port attached by the devices can fix them.
*/ */
if ((udev->speed == USB_SPEED_SUPER) && if ((udev->speed >= USB_SPEED_SUPER) &&
(le16_to_cpu(udev->descriptor.bcdUSB) < 0x0300)) { (le16_to_cpu(udev->descriptor.bcdUSB) < 0x0300)) {
dev_err(&udev->dev, "got a wrong device descriptor, " dev_err(&udev->dev, "got a wrong device descriptor, "
"warm reset device\n"); "warm reset device\n");
...@@ -4348,7 +4352,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, ...@@ -4348,7 +4352,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
} }
if (udev->descriptor.bMaxPacketSize0 == 0xff || if (udev->descriptor.bMaxPacketSize0 == 0xff ||
udev->speed == USB_SPEED_SUPER) udev->speed >= USB_SPEED_SUPER)
i = 512; i = 512;
else else
i = udev->descriptor.bMaxPacketSize0; i = udev->descriptor.bMaxPacketSize0;
...@@ -4607,7 +4611,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, ...@@ -4607,7 +4611,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
udev->level = hdev->level + 1; udev->level = hdev->level + 1;
udev->wusb = hub_is_wusb(hub); udev->wusb = hub_is_wusb(hub);
/* Only USB 3.0 devices are connected to SuperSpeed hubs. */ /* Devices connected to SuperSpeed hubs are USB 3.0 or later */
if (hub_is_superspeed(hub->hdev)) if (hub_is_superspeed(hub->hdev))
udev->speed = USB_SPEED_SUPER; udev->speed = USB_SPEED_SUPER;
else else
......
...@@ -402,7 +402,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) ...@@ -402,7 +402,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
/* SuperSpeed isoc endpoints have up to 16 bursts of up to /* SuperSpeed isoc endpoints have up to 16 bursts of up to
* 3 packets each * 3 packets each
*/ */
if (dev->speed == USB_SPEED_SUPER) { if (dev->speed >= USB_SPEED_SUPER) {
int burst = 1 + ep->ss_ep_comp.bMaxBurst; int burst = 1 + ep->ss_ep_comp.bMaxBurst;
int mult = USB_SS_MULT(ep->ss_ep_comp.bmAttributes); int mult = USB_SS_MULT(ep->ss_ep_comp.bmAttributes);
max *= burst; max *= burst;
...@@ -499,6 +499,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) ...@@ -499,6 +499,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
} }
/* too big? */ /* too big? */
switch (dev->speed) { switch (dev->speed) {
case USB_SPEED_SUPER_PLUS:
case USB_SPEED_SUPER: /* units are 125us */ case USB_SPEED_SUPER: /* units are 125us */
/* Handle up to 2^(16-1) microframes */ /* Handle up to 2^(16-1) microframes */
if (urb->interval > (1 << 15)) if (urb->interval > (1 << 15))
......
...@@ -43,7 +43,7 @@ static inline unsigned usb_get_max_power(struct usb_device *udev, ...@@ -43,7 +43,7 @@ static inline unsigned usb_get_max_power(struct usb_device *udev,
struct usb_host_config *c) struct usb_host_config *c)
{ {
/* SuperSpeed power is in 8 mA units; others are in 2 mA units */ /* SuperSpeed power is in 8 mA units; others are in 2 mA units */
unsigned mul = (udev->speed == USB_SPEED_SUPER ? 8 : 2); unsigned mul = (udev->speed >= USB_SPEED_SUPER ? 8 : 2);
return c->desc.bMaxPower * mul; return c->desc.bMaxPower * mul;
} }
......
...@@ -913,6 +913,7 @@ enum usb_device_speed { ...@@ -913,6 +913,7 @@ enum usb_device_speed {
USB_SPEED_HIGH, /* usb 2.0 */ USB_SPEED_HIGH, /* usb 2.0 */
USB_SPEED_WIRELESS, /* wireless (usb 2.5) */ USB_SPEED_WIRELESS, /* wireless (usb 2.5) */
USB_SPEED_SUPER, /* usb 3.0 */ USB_SPEED_SUPER, /* usb 3.0 */
USB_SPEED_SUPER_PLUS, /* usb 3.1 */
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment