aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core/hcd.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-06-08 14:31:16 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-06-08 14:31:16 -0400
commit3f17ea6dea8ba5668873afa54628a91aaa3fb1c0 (patch)
treeafbeb2accd4c2199ddd705ae943995b143a0af02 /drivers/usb/core/hcd.c
parent1860e379875dfe7271c649058aeddffe5afd9d0d (diff)
parent1a5700bc2d10cd379a795fd2bb377a190af5acd4 (diff)
Merge branch 'next' (accumulated 3.16 merge window patches) into master
Now that 3.15 is released, this merges the 'next' branch into 'master', bringing us to the normal situation where my 'master' branch is the merge window. * accumulated work in next: (6809 commits) ufs: sb mutex merge + mutex_destroy powerpc: update comments for generic idle conversion cris: update comments for generic idle conversion idle: remove cpu_idle() forward declarations nbd: zero from and len fields in NBD_CMD_DISCONNECT. mm: convert some level-less printks to pr_* MAINTAINERS: adi-buildroot-devel is moderated MAINTAINERS: add linux-api for review of API/ABI changes mm/kmemleak-test.c: use pr_fmt for logging fs/dlm/debug_fs.c: replace seq_printf by seq_puts fs/dlm/lockspace.c: convert simple_str to kstr fs/dlm/config.c: convert simple_str to kstr mm: mark remap_file_pages() syscall as deprecated mm: memcontrol: remove unnecessary memcg argument from soft limit functions mm: memcontrol: clean up memcg zoneinfo lookup mm/memblock.c: call kmemleak directly from memblock_(alloc|free) mm/mempool.c: update the kmemleak stack trace for mempool allocations lib/radix-tree.c: update the kmemleak stack trace for radix tree allocations mm: introduce kmemleak_update_trace() mm/kmemleak.c: use %u to print ->checksum ...
Diffstat (limited to 'drivers/usb/core/hcd.c')
-rw-r--r--drivers/usb/core/hcd.c49
1 files changed, 39 insertions, 10 deletions
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 9c4e2922b04d..bec31e2efb88 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -918,6 +918,7 @@ static void usb_bus_init (struct usb_bus *bus)
918 bus->bandwidth_allocated = 0; 918 bus->bandwidth_allocated = 0;
919 bus->bandwidth_int_reqs = 0; 919 bus->bandwidth_int_reqs = 0;
920 bus->bandwidth_isoc_reqs = 0; 920 bus->bandwidth_isoc_reqs = 0;
921 mutex_init(&bus->usb_address0_mutex);
921 922
922 INIT_LIST_HEAD (&bus->bus_list); 923 INIT_LIST_HEAD (&bus->bus_list);
923} 924}
@@ -1502,6 +1503,9 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
1502 ret = -EAGAIN; 1503 ret = -EAGAIN;
1503 else 1504 else
1504 urb->transfer_flags |= URB_DMA_MAP_PAGE; 1505 urb->transfer_flags |= URB_DMA_MAP_PAGE;
1506 } else if (is_vmalloc_addr(urb->transfer_buffer)) {
1507 WARN_ONCE(1, "transfer buffer not dma capable\n");
1508 ret = -EAGAIN;
1505 } else { 1509 } else {
1506 urb->transfer_dma = dma_map_single( 1510 urb->transfer_dma = dma_map_single(
1507 hcd->self.controller, 1511 hcd->self.controller,
@@ -2263,9 +2267,7 @@ static void hcd_resume_work(struct work_struct *work)
2263 struct usb_hcd *hcd = container_of(work, struct usb_hcd, wakeup_work); 2267 struct usb_hcd *hcd = container_of(work, struct usb_hcd, wakeup_work);
2264 struct usb_device *udev = hcd->self.root_hub; 2268 struct usb_device *udev = hcd->self.root_hub;
2265 2269
2266 usb_lock_device(udev);
2267 usb_remote_wakeup(udev); 2270 usb_remote_wakeup(udev);
2268 usb_unlock_device(udev);
2269} 2271}
2270 2272
2271/** 2273/**
@@ -2454,11 +2456,13 @@ struct usb_hcd *usb_create_shared_hcd(const struct hc_driver *driver,
2454 mutex_init(hcd->bandwidth_mutex); 2456 mutex_init(hcd->bandwidth_mutex);
2455 dev_set_drvdata(dev, hcd); 2457 dev_set_drvdata(dev, hcd);
2456 } else { 2458 } else {
2459 mutex_lock(&usb_port_peer_mutex);
2457 hcd->bandwidth_mutex = primary_hcd->bandwidth_mutex; 2460 hcd->bandwidth_mutex = primary_hcd->bandwidth_mutex;
2458 hcd->primary_hcd = primary_hcd; 2461 hcd->primary_hcd = primary_hcd;
2459 primary_hcd->primary_hcd = primary_hcd; 2462 primary_hcd->primary_hcd = primary_hcd;
2460 hcd->shared_hcd = primary_hcd; 2463 hcd->shared_hcd = primary_hcd;
2461 primary_hcd->shared_hcd = hcd; 2464 primary_hcd->shared_hcd = hcd;
2465 mutex_unlock(&usb_port_peer_mutex);
2462 } 2466 }
2463 2467
2464 kref_init(&hcd->kref); 2468 kref_init(&hcd->kref);
@@ -2510,18 +2514,25 @@ EXPORT_SYMBOL_GPL(usb_create_hcd);
2510 * deallocated. 2514 * deallocated.
2511 * 2515 *
2512 * Make sure to only deallocate the bandwidth_mutex when the primary HCD is 2516 * Make sure to only deallocate the bandwidth_mutex when the primary HCD is
2513 * freed. When hcd_release() is called for the non-primary HCD, set the 2517 * freed. When hcd_release() is called for either hcd in a peer set
2514 * primary_hcd's shared_hcd pointer to null (since the non-primary HCD will be 2518 * invalidate the peer's ->shared_hcd and ->primary_hcd pointers to
2515 * freed shortly). 2519 * block new peering attempts
2516 */ 2520 */
2517static void hcd_release (struct kref *kref) 2521static void hcd_release(struct kref *kref)
2518{ 2522{
2519 struct usb_hcd *hcd = container_of (kref, struct usb_hcd, kref); 2523 struct usb_hcd *hcd = container_of (kref, struct usb_hcd, kref);
2520 2524
2525 mutex_lock(&usb_port_peer_mutex);
2521 if (usb_hcd_is_primary_hcd(hcd)) 2526 if (usb_hcd_is_primary_hcd(hcd))
2522 kfree(hcd->bandwidth_mutex); 2527 kfree(hcd->bandwidth_mutex);
2523 else 2528 if (hcd->shared_hcd) {
2524 hcd->shared_hcd->shared_hcd = NULL; 2529 struct usb_hcd *peer = hcd->shared_hcd;
2530
2531 peer->shared_hcd = NULL;
2532 if (peer->primary_hcd == hcd)
2533 peer->primary_hcd = NULL;
2534 }
2535 mutex_unlock(&usb_port_peer_mutex);
2525 kfree(hcd); 2536 kfree(hcd);
2526} 2537}
2527 2538
@@ -2589,6 +2600,21 @@ static int usb_hcd_request_irqs(struct usb_hcd *hcd,
2589 return 0; 2600 return 0;
2590} 2601}
2591 2602
2603/*
2604 * Before we free this root hub, flush in-flight peering attempts
2605 * and disable peer lookups
2606 */
2607static void usb_put_invalidate_rhdev(struct usb_hcd *hcd)
2608{
2609 struct usb_device *rhdev;
2610
2611 mutex_lock(&usb_port_peer_mutex);
2612 rhdev = hcd->self.root_hub;
2613 hcd->self.root_hub = NULL;
2614 mutex_unlock(&usb_port_peer_mutex);
2615 usb_put_dev(rhdev);
2616}
2617
2592/** 2618/**
2593 * usb_add_hcd - finish generic HCD structure initialization and register 2619 * usb_add_hcd - finish generic HCD structure initialization and register
2594 * @hcd: the usb_hcd structure to initialize 2620 * @hcd: the usb_hcd structure to initialize
@@ -2649,7 +2675,9 @@ int usb_add_hcd(struct usb_hcd *hcd,
2649 retval = -ENOMEM; 2675 retval = -ENOMEM;
2650 goto err_allocate_root_hub; 2676 goto err_allocate_root_hub;
2651 } 2677 }
2678 mutex_lock(&usb_port_peer_mutex);
2652 hcd->self.root_hub = rhdev; 2679 hcd->self.root_hub = rhdev;
2680 mutex_unlock(&usb_port_peer_mutex);
2653 2681
2654 switch (hcd->speed) { 2682 switch (hcd->speed) {
2655 case HCD_USB11: 2683 case HCD_USB11:
@@ -2758,7 +2786,7 @@ err_hcd_driver_start:
2758err_request_irq: 2786err_request_irq:
2759err_hcd_driver_setup: 2787err_hcd_driver_setup:
2760err_set_rh_speed: 2788err_set_rh_speed:
2761 usb_put_dev(hcd->self.root_hub); 2789 usb_put_invalidate_rhdev(hcd);
2762err_allocate_root_hub: 2790err_allocate_root_hub:
2763 usb_deregister_bus(&hcd->self); 2791 usb_deregister_bus(&hcd->self);
2764err_register_bus: 2792err_register_bus:
@@ -2838,7 +2866,6 @@ void usb_remove_hcd(struct usb_hcd *hcd)
2838 free_irq(hcd->irq, hcd); 2866 free_irq(hcd->irq, hcd);
2839 } 2867 }
2840 2868
2841 usb_put_dev(hcd->self.root_hub);
2842 usb_deregister_bus(&hcd->self); 2869 usb_deregister_bus(&hcd->self);
2843 hcd_buffer_destroy(hcd); 2870 hcd_buffer_destroy(hcd);
2844 if (hcd->remove_phy && hcd->phy) { 2871 if (hcd->remove_phy && hcd->phy) {
@@ -2846,6 +2873,8 @@ void usb_remove_hcd(struct usb_hcd *hcd)
2846 usb_put_phy(hcd->phy); 2873 usb_put_phy(hcd->phy);
2847 hcd->phy = NULL; 2874 hcd->phy = NULL;
2848 } 2875 }
2876
2877 usb_put_invalidate_rhdev(hcd);
2849} 2878}
2850EXPORT_SYMBOL_GPL(usb_remove_hcd); 2879EXPORT_SYMBOL_GPL(usb_remove_hcd);
2851 2880