diff options
Diffstat (limited to 'drivers/usb/core/hcd.c')
-rw-r--r-- | drivers/usb/core/hcd.c | 49 |
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 | */ |
2517 | static void hcd_release (struct kref *kref) | 2521 | static 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 | */ | ||
2607 | static 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: | |||
2758 | err_request_irq: | 2786 | err_request_irq: |
2759 | err_hcd_driver_setup: | 2787 | err_hcd_driver_setup: |
2760 | err_set_rh_speed: | 2788 | err_set_rh_speed: |
2761 | usb_put_dev(hcd->self.root_hub); | 2789 | usb_put_invalidate_rhdev(hcd); |
2762 | err_allocate_root_hub: | 2790 | err_allocate_root_hub: |
2763 | usb_deregister_bus(&hcd->self); | 2791 | usb_deregister_bus(&hcd->self); |
2764 | err_register_bus: | 2792 | err_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 | } |
2850 | EXPORT_SYMBOL_GPL(usb_remove_hcd); | 2879 | EXPORT_SYMBOL_GPL(usb_remove_hcd); |
2851 | 2880 | ||