aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/core')
-rw-r--r--drivers/usb/core/devices.c10
-rw-r--r--drivers/usb/core/devio.c2
-rw-r--r--drivers/usb/core/driver.c15
-rw-r--r--drivers/usb/core/hcd.c4
-rw-r--r--drivers/usb/core/hub.c14
-rw-r--r--drivers/usb/core/usb.c5
-rw-r--r--drivers/usb/core/usb.h3
7 files changed, 32 insertions, 21 deletions
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index a3d2e2399655..96fdfb815f89 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -221,7 +221,7 @@ static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end,
break;
case USB_ENDPOINT_XFER_INT:
type = "Int.";
- if (speed == USB_SPEED_HIGH)
+ if (speed == USB_SPEED_HIGH || speed == USB_SPEED_SUPER)
interval = 1 << (desc->bInterval - 1);
else
interval = desc->bInterval;
@@ -229,7 +229,8 @@ static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end,
default: /* "can't happen" */
return start;
}
- interval *= (speed == USB_SPEED_HIGH) ? 125 : 1000;
+ interval *= (speed == USB_SPEED_HIGH ||
+ speed == USB_SPEED_SUPER) ? 125 : 1000;
if (interval % 1000)
unit = 'u';
else {
@@ -542,8 +543,9 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes,
if (level == 0) {
int max;
- /* high speed reserves 80%, full/low reserves 90% */
- if (usbdev->speed == USB_SPEED_HIGH)
+ /* super/high speed reserves 80%, full/low reserves 90% */
+ if (usbdev->speed == USB_SPEED_HIGH ||
+ usbdev->speed == USB_SPEED_SUPER)
max = 800;
else
max = FRAME_TIME_MAX_USECS_ALLOC;
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index a7131ad630f9..37518dfdeb98 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -802,7 +802,7 @@ static int proc_control(struct dev_state *ps, void __user *arg)
tbuf, ctrl.wLength, tmo);
usb_lock_device(dev);
snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE,
- tbuf, i);
+ tbuf, max(i, 0));
if ((i > 0) && ctrl.wLength) {
if (copy_to_user(ctrl.data, tbuf, i)) {
free_page((unsigned long)tbuf);
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 38072e4e74bd..e35a17687c05 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1646,7 +1646,7 @@ static int autosuspend_check(struct usb_device *udev)
return 0;
}
-static int usb_runtime_suspend(struct device *dev)
+int usb_runtime_suspend(struct device *dev)
{
struct usb_device *udev = to_usb_device(dev);
int status;
@@ -1667,7 +1667,7 @@ static int usb_runtime_suspend(struct device *dev)
return status;
}
-static int usb_runtime_resume(struct device *dev)
+int usb_runtime_resume(struct device *dev)
{
struct usb_device *udev = to_usb_device(dev);
int status;
@@ -1679,7 +1679,7 @@ static int usb_runtime_resume(struct device *dev)
return status;
}
-static int usb_runtime_idle(struct device *dev)
+int usb_runtime_idle(struct device *dev)
{
struct usb_device *udev = to_usb_device(dev);
@@ -1691,19 +1691,10 @@ static int usb_runtime_idle(struct device *dev)
return 0;
}
-static const struct dev_pm_ops usb_bus_pm_ops = {
- .runtime_suspend = usb_runtime_suspend,
- .runtime_resume = usb_runtime_resume,
- .runtime_idle = usb_runtime_idle,
-};
-
#endif /* CONFIG_USB_SUSPEND */
struct bus_type usb_bus_type = {
.name = "usb",
.match = usb_device_match,
.uevent = usb_uevent,
-#ifdef CONFIG_USB_SUSPEND
- .pm = &usb_bus_pm_ops,
-#endif
};
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 02b4dbfa488a..77a7faec8d78 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -700,7 +700,7 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd)
/* The USB 2.0 spec says 256 ms. This is close enough and won't
* exceed that limit if HZ is 100. The math is more clunky than
* maybe expected, this is to make sure that all timers for USB devices
- * fire at the same time to give the CPU a break inbetween */
+ * fire at the same time to give the CPU a break in between */
if (hcd->uses_new_polling ? HCD_POLL_RH(hcd) :
(length == 0 && hcd->status_urb != NULL))
mod_timer (&hcd->rh_timer, (jiffies/(HZ/4) + 1) * (HZ/4));
@@ -1908,7 +1908,7 @@ void usb_free_streams(struct usb_interface *interface,
/* Streams only apply to bulk endpoints. */
for (i = 0; i < num_eps; i++)
- if (!usb_endpoint_xfer_bulk(&eps[i]->desc))
+ if (!eps[i] || !usb_endpoint_xfer_bulk(&eps[i]->desc))
return;
hcd->driver->free_streams(hcd, dev, eps, num_eps, mem_flags);
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 564eaa5525d7..93720bdc9efd 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1649,7 +1649,7 @@ void usb_disconnect(struct usb_device **pdev)
/* mark the device as inactive, so any further urb submissions for
* this device (and any of its children) will fail immediately.
- * this quiesces everyting except pending urbs.
+ * this quiesces everything except pending urbs.
*/
usb_set_device_state(udev, USB_STATE_NOTATTACHED);
dev_info(&udev->dev, "USB disconnect, device number %d\n",
@@ -2285,7 +2285,17 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
}
/* see 7.1.7.6 */
- status = set_port_feature(hub->hdev, port1, USB_PORT_FEAT_SUSPEND);
+ /* Clear PORT_POWER if it's a USB3.0 device connected to USB 3.0
+ * external hub.
+ * FIXME: this is a temporary workaround to make the system able
+ * to suspend/resume.
+ */
+ if ((hub->hdev->parent != NULL) && hub_is_superspeed(hub->hdev))
+ status = clear_port_feature(hub->hdev, port1,
+ USB_PORT_FEAT_POWER);
+ else
+ status = set_port_feature(hub->hdev, port1,
+ USB_PORT_FEAT_SUSPEND);
if (status) {
dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n",
port1, status);
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 079cb57bab4f..d9d4b169404f 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -315,6 +315,11 @@ static const struct dev_pm_ops usb_device_pm_ops = {
.thaw = usb_dev_thaw,
.poweroff = usb_dev_poweroff,
.restore = usb_dev_restore,
+#ifdef CONFIG_USB_SUSPEND
+ .runtime_suspend = usb_runtime_suspend,
+ .runtime_resume = usb_runtime_resume,
+ .runtime_idle = usb_runtime_idle,
+#endif
};
#endif /* CONFIG_PM */
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index a9cf484ecae4..d450b742137e 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -77,6 +77,9 @@ static inline int usb_port_resume(struct usb_device *udev, pm_message_t msg)
extern void usb_autosuspend_device(struct usb_device *udev);
extern int usb_autoresume_device(struct usb_device *udev);
extern int usb_remote_wakeup(struct usb_device *dev);
+extern int usb_runtime_suspend(struct device *dev);
+extern int usb_runtime_resume(struct device *dev);
+extern int usb_runtime_idle(struct device *dev);
#else