diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-21 12:41:07 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-21 12:41:07 -0400 |
commit | 564fbee928594279409d825b31ee9751ddf11965 (patch) | |
tree | 257fdd870c09b5316340023d80f8ea9e01291a5d | |
parent | 3c8fb50445833b93f69b6b703a29aae3523cad0c (diff) | |
parent | 32b36eeae6a859670d2939a7d6136cb5e9ed64f8 (diff) |
Merge tag 'usb-3.16-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB fixes from Greg KH:
"Here are some USB fixes for 3.16-rc2 that resolve some reported
issues. All of these have been in linux-next for a while with no
problems"
* tag 'usb-3.16-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
USB: usbtest: add a timeout for scatter-gather tests
USB: EHCI: avoid BIOS handover on the HASEE E200
usb: fix hub-port pm_runtime_enable() vs runtime pm transitions
usb: quiet peer failure warning, disable poweroff
usb: improve "not suspended yet" message in hub_suspend()
xhci: Fix sleeping with IRQs disabled in xhci_stop_device()
usb: fix ->update_hub_device() vs hdev->maxchild
-rw-r--r-- | drivers/usb/core/hub.c | 33 | ||||
-rw-r--r-- | drivers/usb/core/hub.h | 2 | ||||
-rw-r--r-- | drivers/usb/core/port.c | 89 | ||||
-rw-r--r-- | drivers/usb/host/pci-quirks.c | 19 | ||||
-rw-r--r-- | drivers/usb/host/xhci-hub.c | 2 | ||||
-rw-r--r-- | drivers/usb/misc/usbtest.c | 16 |
6 files changed, 119 insertions, 42 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 879b66e13370..21b99b4b4082 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -1526,18 +1526,6 @@ static int hub_configure(struct usb_hub *hub, | |||
1526 | dev_dbg(hub_dev, "%umA bus power budget for each child\n", | 1526 | dev_dbg(hub_dev, "%umA bus power budget for each child\n", |
1527 | hub->mA_per_port); | 1527 | hub->mA_per_port); |
1528 | 1528 | ||
1529 | /* Update the HCD's internal representation of this hub before khubd | ||
1530 | * starts getting port status changes for devices under the hub. | ||
1531 | */ | ||
1532 | if (hcd->driver->update_hub_device) { | ||
1533 | ret = hcd->driver->update_hub_device(hcd, hdev, | ||
1534 | &hub->tt, GFP_KERNEL); | ||
1535 | if (ret < 0) { | ||
1536 | message = "can't update HCD hub info"; | ||
1537 | goto fail; | ||
1538 | } | ||
1539 | } | ||
1540 | |||
1541 | ret = hub_hub_status(hub, &hubstatus, &hubchange); | 1529 | ret = hub_hub_status(hub, &hubstatus, &hubchange); |
1542 | if (ret < 0) { | 1530 | if (ret < 0) { |
1543 | message = "can't get hub status"; | 1531 | message = "can't get hub status"; |
@@ -1589,10 +1577,28 @@ static int hub_configure(struct usb_hub *hub, | |||
1589 | } | 1577 | } |
1590 | } | 1578 | } |
1591 | hdev->maxchild = i; | 1579 | hdev->maxchild = i; |
1580 | for (i = 0; i < hdev->maxchild; i++) { | ||
1581 | struct usb_port *port_dev = hub->ports[i]; | ||
1582 | |||
1583 | pm_runtime_put(&port_dev->dev); | ||
1584 | } | ||
1585 | |||
1592 | mutex_unlock(&usb_port_peer_mutex); | 1586 | mutex_unlock(&usb_port_peer_mutex); |
1593 | if (ret < 0) | 1587 | if (ret < 0) |
1594 | goto fail; | 1588 | goto fail; |
1595 | 1589 | ||
1590 | /* Update the HCD's internal representation of this hub before khubd | ||
1591 | * starts getting port status changes for devices under the hub. | ||
1592 | */ | ||
1593 | if (hcd->driver->update_hub_device) { | ||
1594 | ret = hcd->driver->update_hub_device(hcd, hdev, | ||
1595 | &hub->tt, GFP_KERNEL); | ||
1596 | if (ret < 0) { | ||
1597 | message = "can't update HCD hub info"; | ||
1598 | goto fail; | ||
1599 | } | ||
1600 | } | ||
1601 | |||
1596 | usb_hub_adjust_deviceremovable(hdev, hub->descriptor); | 1602 | usb_hub_adjust_deviceremovable(hdev, hub->descriptor); |
1597 | 1603 | ||
1598 | hub_activate(hub, HUB_INIT); | 1604 | hub_activate(hub, HUB_INIT); |
@@ -3458,7 +3464,8 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) | |||
3458 | struct usb_device *udev = port_dev->child; | 3464 | struct usb_device *udev = port_dev->child; |
3459 | 3465 | ||
3460 | if (udev && udev->can_submit) { | 3466 | if (udev && udev->can_submit) { |
3461 | dev_warn(&port_dev->dev, "not suspended yet\n"); | 3467 | dev_warn(&port_dev->dev, "device %s not suspended yet\n", |
3468 | dev_name(&udev->dev)); | ||
3462 | if (PMSG_IS_AUTO(msg)) | 3469 | if (PMSG_IS_AUTO(msg)) |
3463 | return -EBUSY; | 3470 | return -EBUSY; |
3464 | } | 3471 | } |
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h index 0a7cdc0ef0a9..326308e53961 100644 --- a/drivers/usb/core/hub.h +++ b/drivers/usb/core/hub.h | |||
@@ -84,6 +84,7 @@ struct usb_hub { | |||
84 | * @dev: generic device interface | 84 | * @dev: generic device interface |
85 | * @port_owner: port's owner | 85 | * @port_owner: port's owner |
86 | * @peer: related usb2 and usb3 ports (share the same connector) | 86 | * @peer: related usb2 and usb3 ports (share the same connector) |
87 | * @req: default pm qos request for hubs without port power control | ||
87 | * @connect_type: port's connect type | 88 | * @connect_type: port's connect type |
88 | * @location: opaque representation of platform connector location | 89 | * @location: opaque representation of platform connector location |
89 | * @status_lock: synchronize port_event() vs usb_port_{suspend|resume} | 90 | * @status_lock: synchronize port_event() vs usb_port_{suspend|resume} |
@@ -95,6 +96,7 @@ struct usb_port { | |||
95 | struct device dev; | 96 | struct device dev; |
96 | struct usb_dev_state *port_owner; | 97 | struct usb_dev_state *port_owner; |
97 | struct usb_port *peer; | 98 | struct usb_port *peer; |
99 | struct dev_pm_qos_request *req; | ||
98 | enum usb_port_connect_type connect_type; | 100 | enum usb_port_connect_type connect_type; |
99 | usb_port_location_t location; | 101 | usb_port_location_t location; |
100 | struct mutex status_lock; | 102 | struct mutex status_lock; |
diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index 62036faf56c0..fe1b6d0967e3 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c | |||
@@ -21,6 +21,8 @@ | |||
21 | 21 | ||
22 | #include "hub.h" | 22 | #include "hub.h" |
23 | 23 | ||
24 | static int usb_port_block_power_off; | ||
25 | |||
24 | static const struct attribute_group *port_dev_group[]; | 26 | static const struct attribute_group *port_dev_group[]; |
25 | 27 | ||
26 | static ssize_t connect_type_show(struct device *dev, | 28 | static ssize_t connect_type_show(struct device *dev, |
@@ -66,6 +68,7 @@ static void usb_port_device_release(struct device *dev) | |||
66 | { | 68 | { |
67 | struct usb_port *port_dev = to_usb_port(dev); | 69 | struct usb_port *port_dev = to_usb_port(dev); |
68 | 70 | ||
71 | kfree(port_dev->req); | ||
69 | kfree(port_dev); | 72 | kfree(port_dev); |
70 | } | 73 | } |
71 | 74 | ||
@@ -142,6 +145,9 @@ static int usb_port_runtime_suspend(struct device *dev) | |||
142 | == PM_QOS_FLAGS_ALL) | 145 | == PM_QOS_FLAGS_ALL) |
143 | return -EAGAIN; | 146 | return -EAGAIN; |
144 | 147 | ||
148 | if (usb_port_block_power_off) | ||
149 | return -EBUSY; | ||
150 | |||
145 | usb_autopm_get_interface(intf); | 151 | usb_autopm_get_interface(intf); |
146 | retval = usb_hub_set_port_power(hdev, hub, port1, false); | 152 | retval = usb_hub_set_port_power(hdev, hub, port1, false); |
147 | usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_CONNECTION); | 153 | usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_CONNECTION); |
@@ -190,11 +196,19 @@ static int link_peers(struct usb_port *left, struct usb_port *right) | |||
190 | if (left->peer || right->peer) { | 196 | if (left->peer || right->peer) { |
191 | struct usb_port *lpeer = left->peer; | 197 | struct usb_port *lpeer = left->peer; |
192 | struct usb_port *rpeer = right->peer; | 198 | struct usb_port *rpeer = right->peer; |
193 | 199 | char *method; | |
194 | WARN(1, "failed to peer %s and %s (%s -> %p) (%s -> %p)\n", | 200 | |
195 | dev_name(&left->dev), dev_name(&right->dev), | 201 | if (left->location && left->location == right->location) |
196 | dev_name(&left->dev), lpeer, | 202 | method = "location"; |
197 | dev_name(&right->dev), rpeer); | 203 | else |
204 | method = "default"; | ||
205 | |||
206 | pr_warn("usb: failed to peer %s and %s by %s (%s:%s) (%s:%s)\n", | ||
207 | dev_name(&left->dev), dev_name(&right->dev), method, | ||
208 | dev_name(&left->dev), | ||
209 | lpeer ? dev_name(&lpeer->dev) : "none", | ||
210 | dev_name(&right->dev), | ||
211 | rpeer ? dev_name(&rpeer->dev) : "none"); | ||
198 | return -EBUSY; | 212 | return -EBUSY; |
199 | } | 213 | } |
200 | 214 | ||
@@ -251,6 +265,7 @@ static void link_peers_report(struct usb_port *left, struct usb_port *right) | |||
251 | dev_warn(&left->dev, "failed to peer to %s (%d)\n", | 265 | dev_warn(&left->dev, "failed to peer to %s (%d)\n", |
252 | dev_name(&right->dev), rc); | 266 | dev_name(&right->dev), rc); |
253 | pr_warn_once("usb: port power management may be unreliable\n"); | 267 | pr_warn_once("usb: port power management may be unreliable\n"); |
268 | usb_port_block_power_off = 1; | ||
254 | } | 269 | } |
255 | } | 270 | } |
256 | 271 | ||
@@ -386,9 +401,13 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1) | |||
386 | int retval; | 401 | int retval; |
387 | 402 | ||
388 | port_dev = kzalloc(sizeof(*port_dev), GFP_KERNEL); | 403 | port_dev = kzalloc(sizeof(*port_dev), GFP_KERNEL); |
389 | if (!port_dev) { | 404 | if (!port_dev) |
390 | retval = -ENOMEM; | 405 | return -ENOMEM; |
391 | goto exit; | 406 | |
407 | port_dev->req = kzalloc(sizeof(*(port_dev->req)), GFP_KERNEL); | ||
408 | if (!port_dev->req) { | ||
409 | kfree(port_dev); | ||
410 | return -ENOMEM; | ||
392 | } | 411 | } |
393 | 412 | ||
394 | hub->ports[port1 - 1] = port_dev; | 413 | hub->ports[port1 - 1] = port_dev; |
@@ -404,31 +423,53 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1) | |||
404 | port1); | 423 | port1); |
405 | mutex_init(&port_dev->status_lock); | 424 | mutex_init(&port_dev->status_lock); |
406 | retval = device_register(&port_dev->dev); | 425 | retval = device_register(&port_dev->dev); |
407 | if (retval) | 426 | if (retval) { |
408 | goto error_register; | 427 | put_device(&port_dev->dev); |
428 | return retval; | ||
429 | } | ||
430 | |||
431 | /* Set default policy of port-poweroff disabled. */ | ||
432 | retval = dev_pm_qos_add_request(&port_dev->dev, port_dev->req, | ||
433 | DEV_PM_QOS_FLAGS, PM_QOS_FLAG_NO_POWER_OFF); | ||
434 | if (retval < 0) { | ||
435 | device_unregister(&port_dev->dev); | ||
436 | return retval; | ||
437 | } | ||
409 | 438 | ||
410 | find_and_link_peer(hub, port1); | 439 | find_and_link_peer(hub, port1); |
411 | 440 | ||
441 | /* | ||
442 | * Enable runtime pm and hold a refernce that hub_configure() | ||
443 | * will drop once the PM_QOS_NO_POWER_OFF flag state has been set | ||
444 | * and the hub has been fully registered (hdev->maxchild set). | ||
445 | */ | ||
412 | pm_runtime_set_active(&port_dev->dev); | 446 | pm_runtime_set_active(&port_dev->dev); |
447 | pm_runtime_get_noresume(&port_dev->dev); | ||
448 | pm_runtime_enable(&port_dev->dev); | ||
449 | device_enable_async_suspend(&port_dev->dev); | ||
413 | 450 | ||
414 | /* | 451 | /* |
415 | * Do not enable port runtime pm if the hub does not support | 452 | * Keep hidden the ability to enable port-poweroff if the hub |
416 | * power switching. Also, userspace must have final say of | 453 | * does not support power switching. |
417 | * whether a port is permitted to power-off. Do not enable | ||
418 | * runtime pm if we fail to expose pm_qos_no_power_off. | ||
419 | */ | 454 | */ |
420 | if (hub_is_port_power_switchable(hub) | 455 | if (!hub_is_port_power_switchable(hub)) |
421 | && dev_pm_qos_expose_flags(&port_dev->dev, | 456 | return 0; |
422 | PM_QOS_FLAG_NO_POWER_OFF) == 0) | ||
423 | pm_runtime_enable(&port_dev->dev); | ||
424 | 457 | ||
425 | device_enable_async_suspend(&port_dev->dev); | 458 | /* Attempt to let userspace take over the policy. */ |
426 | return 0; | 459 | retval = dev_pm_qos_expose_flags(&port_dev->dev, |
460 | PM_QOS_FLAG_NO_POWER_OFF); | ||
461 | if (retval < 0) { | ||
462 | dev_warn(&port_dev->dev, "failed to expose pm_qos_no_poweroff\n"); | ||
463 | return 0; | ||
464 | } | ||
427 | 465 | ||
428 | error_register: | 466 | /* Userspace owns the policy, drop the kernel 'no_poweroff' request. */ |
429 | put_device(&port_dev->dev); | 467 | retval = dev_pm_qos_remove_request(port_dev->req); |
430 | exit: | 468 | if (retval >= 0) { |
431 | return retval; | 469 | kfree(port_dev->req); |
470 | port_dev->req = NULL; | ||
471 | } | ||
472 | return 0; | ||
432 | } | 473 | } |
433 | 474 | ||
434 | void usb_hub_remove_port_device(struct usb_hub *hub, int port1) | 475 | void usb_hub_remove_port_device(struct usb_hub *hub, int port1) |
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 4a6d3dd68572..2f3acebb577a 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c | |||
@@ -656,6 +656,14 @@ static const struct dmi_system_id ehci_dmi_nohandoff_table[] = { | |||
656 | DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"), | 656 | DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"), |
657 | }, | 657 | }, |
658 | }, | 658 | }, |
659 | { | ||
660 | /* HASEE E200 */ | ||
661 | .matches = { | ||
662 | DMI_MATCH(DMI_BOARD_VENDOR, "HASEE"), | ||
663 | DMI_MATCH(DMI_BOARD_NAME, "E210"), | ||
664 | DMI_MATCH(DMI_BIOS_VERSION, "6.00"), | ||
665 | }, | ||
666 | }, | ||
659 | { } | 667 | { } |
660 | }; | 668 | }; |
661 | 669 | ||
@@ -665,9 +673,14 @@ static void ehci_bios_handoff(struct pci_dev *pdev, | |||
665 | { | 673 | { |
666 | int try_handoff = 1, tried_handoff = 0; | 674 | int try_handoff = 1, tried_handoff = 0; |
667 | 675 | ||
668 | /* The Pegatron Lucid tablet sporadically waits for 98 seconds trying | 676 | /* |
669 | * the handoff on its unused controller. Skip it. */ | 677 | * The Pegatron Lucid tablet sporadically waits for 98 seconds trying |
670 | if (pdev->vendor == 0x8086 && pdev->device == 0x283a) { | 678 | * the handoff on its unused controller. Skip it. |
679 | * | ||
680 | * The HASEE E200 hangs when the semaphore is set (bugzilla #77021). | ||
681 | */ | ||
682 | if (pdev->vendor == 0x8086 && (pdev->device == 0x283a || | ||
683 | pdev->device == 0x27cc)) { | ||
671 | if (dmi_check_system(ehci_dmi_nohandoff_table)) | 684 | if (dmi_check_system(ehci_dmi_nohandoff_table)) |
672 | try_handoff = 0; | 685 | try_handoff = 0; |
673 | } | 686 | } |
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 6231ce6aa0c3..2b998c60faf2 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c | |||
@@ -287,7 +287,7 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend) | |||
287 | if (virt_dev->eps[i].ring && virt_dev->eps[i].ring->dequeue) { | 287 | if (virt_dev->eps[i].ring && virt_dev->eps[i].ring->dequeue) { |
288 | struct xhci_command *command; | 288 | struct xhci_command *command; |
289 | command = xhci_alloc_command(xhci, false, false, | 289 | command = xhci_alloc_command(xhci, false, false, |
290 | GFP_NOIO); | 290 | GFP_NOWAIT); |
291 | if (!command) { | 291 | if (!command) { |
292 | spin_unlock_irqrestore(&xhci->lock, flags); | 292 | spin_unlock_irqrestore(&xhci->lock, flags); |
293 | xhci_free_command(xhci, cmd); | 293 | xhci_free_command(xhci, cmd); |
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 51a6da256772..829f446064ea 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c | |||
@@ -7,7 +7,7 @@ | |||
7 | #include <linux/moduleparam.h> | 7 | #include <linux/moduleparam.h> |
8 | #include <linux/scatterlist.h> | 8 | #include <linux/scatterlist.h> |
9 | #include <linux/mutex.h> | 9 | #include <linux/mutex.h> |
10 | 10 | #include <linux/timer.h> | |
11 | #include <linux/usb.h> | 11 | #include <linux/usb.h> |
12 | 12 | ||
13 | #define SIMPLE_IO_TIMEOUT 10000 /* in milliseconds */ | 13 | #define SIMPLE_IO_TIMEOUT 10000 /* in milliseconds */ |
@@ -484,6 +484,14 @@ alloc_sglist(int nents, int max, int vary) | |||
484 | return sg; | 484 | return sg; |
485 | } | 485 | } |
486 | 486 | ||
487 | static void sg_timeout(unsigned long _req) | ||
488 | { | ||
489 | struct usb_sg_request *req = (struct usb_sg_request *) _req; | ||
490 | |||
491 | req->status = -ETIMEDOUT; | ||
492 | usb_sg_cancel(req); | ||
493 | } | ||
494 | |||
487 | static int perform_sglist( | 495 | static int perform_sglist( |
488 | struct usbtest_dev *tdev, | 496 | struct usbtest_dev *tdev, |
489 | unsigned iterations, | 497 | unsigned iterations, |
@@ -495,6 +503,9 @@ static int perform_sglist( | |||
495 | { | 503 | { |
496 | struct usb_device *udev = testdev_to_usbdev(tdev); | 504 | struct usb_device *udev = testdev_to_usbdev(tdev); |
497 | int retval = 0; | 505 | int retval = 0; |
506 | struct timer_list sg_timer; | ||
507 | |||
508 | setup_timer_on_stack(&sg_timer, sg_timeout, (unsigned long) req); | ||
498 | 509 | ||
499 | while (retval == 0 && iterations-- > 0) { | 510 | while (retval == 0 && iterations-- > 0) { |
500 | retval = usb_sg_init(req, udev, pipe, | 511 | retval = usb_sg_init(req, udev, pipe, |
@@ -505,7 +516,10 @@ static int perform_sglist( | |||
505 | 516 | ||
506 | if (retval) | 517 | if (retval) |
507 | break; | 518 | break; |
519 | mod_timer(&sg_timer, jiffies + | ||
520 | msecs_to_jiffies(SIMPLE_IO_TIMEOUT)); | ||
508 | usb_sg_wait(req); | 521 | usb_sg_wait(req); |
522 | del_timer_sync(&sg_timer); | ||
509 | retval = req->status; | 523 | retval = req->status; |
510 | 524 | ||
511 | /* FIXME check resulting data pattern */ | 525 | /* FIXME check resulting data pattern */ |