diff options
Diffstat (limited to 'drivers/usb/core')
-rw-r--r-- | drivers/usb/core/hcd.c | 2 | ||||
-rw-r--r-- | drivers/usb/core/hub.c | 97 | ||||
-rw-r--r-- | drivers/usb/core/hub.h | 4 | ||||
-rw-r--r-- | drivers/usb/core/port.c | 6 |
4 files changed, 72 insertions, 37 deletions
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index b81407518fdf..bec31e2efb88 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c | |||
@@ -2267,9 +2267,7 @@ static void hcd_resume_work(struct work_struct *work) | |||
2267 | 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); |
2268 | struct usb_device *udev = hcd->self.root_hub; | 2268 | struct usb_device *udev = hcd->self.root_hub; |
2269 | 2269 | ||
2270 | usb_lock_device(udev); | ||
2271 | usb_remote_wakeup(udev); | 2270 | usb_remote_wakeup(udev); |
2272 | usb_unlock_device(udev); | ||
2273 | } | 2271 | } |
2274 | 2272 | ||
2275 | /** | 2273 | /** |
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 988f227e796f..d43054e8e257 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -2781,6 +2781,20 @@ static int port_is_power_on(struct usb_hub *hub, unsigned portstatus) | |||
2781 | return ret; | 2781 | return ret; |
2782 | } | 2782 | } |
2783 | 2783 | ||
2784 | static void usb_lock_port(struct usb_port *port_dev) | ||
2785 | __acquires(&port_dev->status_lock) | ||
2786 | { | ||
2787 | mutex_lock(&port_dev->status_lock); | ||
2788 | __acquire(&port_dev->status_lock); | ||
2789 | } | ||
2790 | |||
2791 | static void usb_unlock_port(struct usb_port *port_dev) | ||
2792 | __releases(&port_dev->status_lock) | ||
2793 | { | ||
2794 | mutex_unlock(&port_dev->status_lock); | ||
2795 | __release(&port_dev->status_lock); | ||
2796 | } | ||
2797 | |||
2784 | #ifdef CONFIG_PM | 2798 | #ifdef CONFIG_PM |
2785 | 2799 | ||
2786 | /* Check if a port is suspended(USB2.0 port) or in U3 state(USB3.0 port) */ | 2800 | /* Check if a port is suspended(USB2.0 port) or in U3 state(USB3.0 port) */ |
@@ -3003,6 +3017,8 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) | |||
3003 | int status; | 3017 | int status; |
3004 | bool really_suspend = true; | 3018 | bool really_suspend = true; |
3005 | 3019 | ||
3020 | usb_lock_port(port_dev); | ||
3021 | |||
3006 | /* enable remote wakeup when appropriate; this lets the device | 3022 | /* enable remote wakeup when appropriate; this lets the device |
3007 | * wake up the upstream hub (including maybe the root hub). | 3023 | * wake up the upstream hub (including maybe the root hub). |
3008 | * | 3024 | * |
@@ -3096,6 +3112,8 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) | |||
3096 | pm_runtime_put_sync(&port_dev->dev); | 3112 | pm_runtime_put_sync(&port_dev->dev); |
3097 | 3113 | ||
3098 | usb_mark_last_busy(hub->hdev); | 3114 | usb_mark_last_busy(hub->hdev); |
3115 | |||
3116 | usb_unlock_port(port_dev); | ||
3099 | return status; | 3117 | return status; |
3100 | } | 3118 | } |
3101 | 3119 | ||
@@ -3244,13 +3262,13 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) | |||
3244 | } | 3262 | } |
3245 | } | 3263 | } |
3246 | 3264 | ||
3265 | usb_lock_port(port_dev); | ||
3266 | |||
3247 | /* Skip the initial Clear-Suspend step for a remote wakeup */ | 3267 | /* Skip the initial Clear-Suspend step for a remote wakeup */ |
3248 | status = hub_port_status(hub, port1, &portstatus, &portchange); | 3268 | status = hub_port_status(hub, port1, &portstatus, &portchange); |
3249 | if (status == 0 && !port_is_suspended(hub, portstatus)) | 3269 | if (status == 0 && !port_is_suspended(hub, portstatus)) |
3250 | goto SuspendCleared; | 3270 | goto SuspendCleared; |
3251 | 3271 | ||
3252 | set_bit(port1, hub->busy_bits); | ||
3253 | |||
3254 | /* see 7.1.7.7; affects power usage, but not budgeting */ | 3272 | /* see 7.1.7.7; affects power usage, but not budgeting */ |
3255 | if (hub_is_superspeed(hub->hdev)) | 3273 | if (hub_is_superspeed(hub->hdev)) |
3256 | status = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_U0); | 3274 | status = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_U0); |
@@ -3289,8 +3307,6 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) | |||
3289 | } | 3307 | } |
3290 | } | 3308 | } |
3291 | 3309 | ||
3292 | clear_bit(port1, hub->busy_bits); | ||
3293 | |||
3294 | status = check_port_resume_type(udev, | 3310 | status = check_port_resume_type(udev, |
3295 | hub, port1, status, portchange, portstatus); | 3311 | hub, port1, status, portchange, portstatus); |
3296 | if (status == 0) | 3312 | if (status == 0) |
@@ -3308,16 +3324,18 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) | |||
3308 | usb_unlocked_enable_lpm(udev); | 3324 | usb_unlocked_enable_lpm(udev); |
3309 | } | 3325 | } |
3310 | 3326 | ||
3327 | usb_unlock_port(port_dev); | ||
3328 | |||
3311 | return status; | 3329 | return status; |
3312 | } | 3330 | } |
3313 | 3331 | ||
3314 | #ifdef CONFIG_PM_RUNTIME | 3332 | #ifdef CONFIG_PM_RUNTIME |
3315 | 3333 | ||
3316 | /* caller has locked udev */ | ||
3317 | int usb_remote_wakeup(struct usb_device *udev) | 3334 | int usb_remote_wakeup(struct usb_device *udev) |
3318 | { | 3335 | { |
3319 | int status = 0; | 3336 | int status = 0; |
3320 | 3337 | ||
3338 | usb_lock_device(udev); | ||
3321 | if (udev->state == USB_STATE_SUSPENDED) { | 3339 | if (udev->state == USB_STATE_SUSPENDED) { |
3322 | dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-"); | 3340 | dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-"); |
3323 | status = usb_autoresume_device(udev); | 3341 | status = usb_autoresume_device(udev); |
@@ -3326,6 +3344,7 @@ int usb_remote_wakeup(struct usb_device *udev) | |||
3326 | usb_autosuspend_device(udev); | 3344 | usb_autosuspend_device(udev); |
3327 | } | 3345 | } |
3328 | } | 3346 | } |
3347 | usb_unlock_device(udev); | ||
3329 | return status; | 3348 | return status; |
3330 | } | 3349 | } |
3331 | 3350 | ||
@@ -4030,9 +4049,10 @@ static int hub_enable_device(struct usb_device *udev) | |||
4030 | * Returns device in USB_STATE_ADDRESS, except on error. | 4049 | * Returns device in USB_STATE_ADDRESS, except on error. |
4031 | * | 4050 | * |
4032 | * If this is called for an already-existing device (as part of | 4051 | * If this is called for an already-existing device (as part of |
4033 | * usb_reset_and_verify_device), the caller must own the device lock. For a | 4052 | * usb_reset_and_verify_device), the caller must own the device lock and |
4034 | * newly detected device that is not accessible through any global | 4053 | * the port lock. For a newly detected device that is not accessible |
4035 | * pointers, it's not necessary to lock the device. | 4054 | * through any global pointers, it's not necessary to lock the device, |
4055 | * but it is still necessary to lock the port. | ||
4036 | */ | 4056 | */ |
4037 | static int | 4057 | static int |
4038 | hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, | 4058 | hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, |
@@ -4502,7 +4522,9 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus, | |||
4502 | } | 4522 | } |
4503 | 4523 | ||
4504 | /* reset (non-USB 3.0 devices) and get descriptor */ | 4524 | /* reset (non-USB 3.0 devices) and get descriptor */ |
4525 | usb_lock_port(port_dev); | ||
4505 | status = hub_port_init(hub, udev, port1, i); | 4526 | status = hub_port_init(hub, udev, port1, i); |
4527 | usb_unlock_port(port_dev); | ||
4506 | if (status < 0) | 4528 | if (status < 0) |
4507 | goto loop; | 4529 | goto loop; |
4508 | 4530 | ||
@@ -4624,6 +4646,7 @@ done: | |||
4624 | */ | 4646 | */ |
4625 | static void hub_port_connect_change(struct usb_hub *hub, int port1, | 4647 | static void hub_port_connect_change(struct usb_hub *hub, int port1, |
4626 | u16 portstatus, u16 portchange) | 4648 | u16 portstatus, u16 portchange) |
4649 | __must_hold(&port_dev->status_lock) | ||
4627 | { | 4650 | { |
4628 | struct usb_port *port_dev = hub->ports[port1 - 1]; | 4651 | struct usb_port *port_dev = hub->ports[port1 - 1]; |
4629 | struct usb_device *udev = port_dev->child; | 4652 | struct usb_device *udev = port_dev->child; |
@@ -4655,26 +4678,29 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, | |||
4655 | /* For a suspended device, treat this as a | 4678 | /* For a suspended device, treat this as a |
4656 | * remote wakeup event. | 4679 | * remote wakeup event. |
4657 | */ | 4680 | */ |
4658 | usb_lock_device(udev); | 4681 | usb_unlock_port(port_dev); |
4659 | status = usb_remote_wakeup(udev); | 4682 | status = usb_remote_wakeup(udev); |
4660 | usb_unlock_device(udev); | 4683 | usb_lock_port(port_dev); |
4661 | #endif | 4684 | #endif |
4662 | } else { | 4685 | } else { |
4663 | /* Don't resuscitate */; | 4686 | /* Don't resuscitate */; |
4664 | } | 4687 | } |
4665 | |||
4666 | } | 4688 | } |
4667 | clear_bit(port1, hub->change_bits); | 4689 | clear_bit(port1, hub->change_bits); |
4668 | 4690 | ||
4691 | /* successfully revalidated the connection */ | ||
4669 | if (status == 0) | 4692 | if (status == 0) |
4670 | return; | 4693 | return; |
4671 | 4694 | ||
4695 | usb_unlock_port(port_dev); | ||
4672 | hub_port_connect(hub, port1, portstatus, portchange); | 4696 | hub_port_connect(hub, port1, portstatus, portchange); |
4697 | usb_lock_port(port_dev); | ||
4673 | } | 4698 | } |
4674 | 4699 | ||
4675 | /* Returns 1 if there was a remote wakeup and a connect status change. */ | 4700 | /* Returns 1 if there was a remote wakeup and a connect status change. */ |
4676 | static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port, | 4701 | static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port, |
4677 | u16 portstatus, u16 portchange) | 4702 | u16 portstatus, u16 portchange) |
4703 | __must_hold(&port_dev->status_lock) | ||
4678 | { | 4704 | { |
4679 | struct usb_port *port_dev = hub->ports[port - 1]; | 4705 | struct usb_port *port_dev = hub->ports[port - 1]; |
4680 | struct usb_device *hdev; | 4706 | struct usb_device *hdev; |
@@ -4699,9 +4725,9 @@ static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port, | |||
4699 | /* TRSMRCY = 10 msec */ | 4725 | /* TRSMRCY = 10 msec */ |
4700 | msleep(10); | 4726 | msleep(10); |
4701 | 4727 | ||
4702 | usb_lock_device(udev); | 4728 | usb_unlock_port(port_dev); |
4703 | ret = usb_remote_wakeup(udev); | 4729 | ret = usb_remote_wakeup(udev); |
4704 | usb_unlock_device(udev); | 4730 | usb_lock_port(port_dev); |
4705 | if (ret < 0) | 4731 | if (ret < 0) |
4706 | connect_change = 1; | 4732 | connect_change = 1; |
4707 | } else { | 4733 | } else { |
@@ -4713,6 +4739,7 @@ static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port, | |||
4713 | } | 4739 | } |
4714 | 4740 | ||
4715 | static void port_event(struct usb_hub *hub, int port1) | 4741 | static void port_event(struct usb_hub *hub, int port1) |
4742 | __must_hold(&port_dev->status_lock) | ||
4716 | { | 4743 | { |
4717 | int connect_change, reset_device = 0; | 4744 | int connect_change, reset_device = 0; |
4718 | struct usb_port *port_dev = hub->ports[port1 - 1]; | 4745 | struct usb_port *port_dev = hub->ports[port1 - 1]; |
@@ -4820,9 +4847,11 @@ static void port_event(struct usb_hub *hub, int port1) | |||
4820 | if (reset_device || (udev && hub_is_superspeed(hub->hdev) | 4847 | if (reset_device || (udev && hub_is_superspeed(hub->hdev) |
4821 | && (portchange & USB_PORT_STAT_C_LINK_STATE) | 4848 | && (portchange & USB_PORT_STAT_C_LINK_STATE) |
4822 | && (portstatus & USB_PORT_STAT_CONNECTION))) { | 4849 | && (portstatus & USB_PORT_STAT_CONNECTION))) { |
4850 | usb_unlock_port(port_dev); | ||
4823 | usb_lock_device(udev); | 4851 | usb_lock_device(udev); |
4824 | usb_reset_device(udev); | 4852 | usb_reset_device(udev); |
4825 | usb_unlock_device(udev); | 4853 | usb_unlock_device(udev); |
4854 | usb_lock_port(port_dev); | ||
4826 | connect_change = 0; | 4855 | connect_change = 0; |
4827 | } | 4856 | } |
4828 | 4857 | ||
@@ -4916,10 +4945,9 @@ static void hub_events(void) | |||
4916 | for (i = 1; i <= hdev->maxchild; i++) { | 4945 | for (i = 1; i <= hdev->maxchild; i++) { |
4917 | struct usb_port *port_dev = hub->ports[i - 1]; | 4946 | struct usb_port *port_dev = hub->ports[i - 1]; |
4918 | 4947 | ||
4919 | if (!test_bit(i, hub->busy_bits) | 4948 | if (test_bit(i, hub->event_bits) |
4920 | && (test_bit(i, hub->event_bits) | 4949 | || test_bit(i, hub->change_bits) |
4921 | || test_bit(i, hub->change_bits) | 4950 | || test_bit(i, hub->wakeup_bits)) { |
4922 | || test_bit(i, hub->wakeup_bits))) { | ||
4923 | /* | 4951 | /* |
4924 | * The get_noresume and barrier ensure that if | 4952 | * The get_noresume and barrier ensure that if |
4925 | * the port was in the process of resuming, we | 4953 | * the port was in the process of resuming, we |
@@ -4931,7 +4959,9 @@ static void hub_events(void) | |||
4931 | */ | 4959 | */ |
4932 | pm_runtime_get_noresume(&port_dev->dev); | 4960 | pm_runtime_get_noresume(&port_dev->dev); |
4933 | pm_runtime_barrier(&port_dev->dev); | 4961 | pm_runtime_barrier(&port_dev->dev); |
4962 | usb_lock_port(port_dev); | ||
4934 | port_event(hub, i); | 4963 | port_event(hub, i); |
4964 | usb_unlock_port(port_dev); | ||
4935 | pm_runtime_put_sync(&port_dev->dev); | 4965 | pm_runtime_put_sync(&port_dev->dev); |
4936 | } | 4966 | } |
4937 | } | 4967 | } |
@@ -5169,15 +5199,18 @@ static int descriptors_changed(struct usb_device *udev, | |||
5169 | * if the reset wasn't even attempted. | 5199 | * if the reset wasn't even attempted. |
5170 | * | 5200 | * |
5171 | * Note: | 5201 | * Note: |
5172 | * The caller must own the device lock. For example, it's safe to use | 5202 | * The caller must own the device lock and the port lock, the latter is |
5173 | * this from a driver probe() routine after downloading new firmware. | 5203 | * taken by usb_reset_device(). For example, it's safe to use |
5174 | * For calls that might not occur during probe(), drivers should lock | 5204 | * usb_reset_device() from a driver probe() routine after downloading |
5175 | * the device using usb_lock_device_for_reset(). | 5205 | * new firmware. For calls that might not occur during probe(), drivers |
5206 | * should lock the device using usb_lock_device_for_reset(). | ||
5176 | * | 5207 | * |
5177 | * Locking exception: This routine may also be called from within an | 5208 | * Locking exception: This routine may also be called from within an |
5178 | * autoresume handler. Such usage won't conflict with other tasks | 5209 | * autoresume handler. Such usage won't conflict with other tasks |
5179 | * holding the device lock because these tasks should always call | 5210 | * holding the device lock because these tasks should always call |
5180 | * usb_autopm_resume_device(), thereby preventing any unwanted autoresume. | 5211 | * usb_autopm_resume_device(), thereby preventing any unwanted |
5212 | * autoresume. The autoresume handler is expected to have already | ||
5213 | * acquired the port lock before calling this routine. | ||
5181 | */ | 5214 | */ |
5182 | static int usb_reset_and_verify_device(struct usb_device *udev) | 5215 | static int usb_reset_and_verify_device(struct usb_device *udev) |
5183 | { | 5216 | { |
@@ -5196,11 +5229,9 @@ static int usb_reset_and_verify_device(struct usb_device *udev) | |||
5196 | return -EINVAL; | 5229 | return -EINVAL; |
5197 | } | 5230 | } |
5198 | 5231 | ||
5199 | if (!parent_hdev) { | 5232 | if (!parent_hdev) |
5200 | /* this requires hcd-specific logic; see ohci_restart() */ | ||
5201 | dev_dbg(&udev->dev, "%s for root hub!\n", __func__); | ||
5202 | return -EISDIR; | 5233 | return -EISDIR; |
5203 | } | 5234 | |
5204 | parent_hub = usb_hub_to_struct_hub(parent_hdev); | 5235 | parent_hub = usb_hub_to_struct_hub(parent_hdev); |
5205 | 5236 | ||
5206 | /* Disable USB2 hardware LPM. | 5237 | /* Disable USB2 hardware LPM. |
@@ -5229,7 +5260,6 @@ static int usb_reset_and_verify_device(struct usb_device *udev) | |||
5229 | goto re_enumerate; | 5260 | goto re_enumerate; |
5230 | } | 5261 | } |
5231 | 5262 | ||
5232 | set_bit(port1, parent_hub->busy_bits); | ||
5233 | for (i = 0; i < SET_CONFIG_TRIES; ++i) { | 5263 | for (i = 0; i < SET_CONFIG_TRIES; ++i) { |
5234 | 5264 | ||
5235 | /* ep0 maxpacket size may change; let the HCD know about it. | 5265 | /* ep0 maxpacket size may change; let the HCD know about it. |
@@ -5239,7 +5269,6 @@ static int usb_reset_and_verify_device(struct usb_device *udev) | |||
5239 | if (ret >= 0 || ret == -ENOTCONN || ret == -ENODEV) | 5269 | if (ret >= 0 || ret == -ENOTCONN || ret == -ENODEV) |
5240 | break; | 5270 | break; |
5241 | } | 5271 | } |
5242 | clear_bit(port1, parent_hub->busy_bits); | ||
5243 | 5272 | ||
5244 | if (ret < 0) | 5273 | if (ret < 0) |
5245 | goto re_enumerate; | 5274 | goto re_enumerate; |
@@ -5360,7 +5389,9 @@ int usb_reset_device(struct usb_device *udev) | |||
5360 | int ret; | 5389 | int ret; |
5361 | int i; | 5390 | int i; |
5362 | unsigned int noio_flag; | 5391 | unsigned int noio_flag; |
5392 | struct usb_port *port_dev; | ||
5363 | struct usb_host_config *config = udev->actconfig; | 5393 | struct usb_host_config *config = udev->actconfig; |
5394 | struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent); | ||
5364 | 5395 | ||
5365 | if (udev->state == USB_STATE_NOTATTACHED || | 5396 | if (udev->state == USB_STATE_NOTATTACHED || |
5366 | udev->state == USB_STATE_SUSPENDED) { | 5397 | udev->state == USB_STATE_SUSPENDED) { |
@@ -5369,6 +5400,14 @@ int usb_reset_device(struct usb_device *udev) | |||
5369 | return -EINVAL; | 5400 | return -EINVAL; |
5370 | } | 5401 | } |
5371 | 5402 | ||
5403 | if (!udev->parent) { | ||
5404 | /* this requires hcd-specific logic; see ohci_restart() */ | ||
5405 | dev_dbg(&udev->dev, "%s for root hub!\n", __func__); | ||
5406 | return -EISDIR; | ||
5407 | } | ||
5408 | |||
5409 | port_dev = hub->ports[udev->portnum - 1]; | ||
5410 | |||
5372 | /* | 5411 | /* |
5373 | * Don't allocate memory with GFP_KERNEL in current | 5412 | * Don't allocate memory with GFP_KERNEL in current |
5374 | * context to avoid possible deadlock if usb mass | 5413 | * context to avoid possible deadlock if usb mass |
@@ -5402,7 +5441,9 @@ int usb_reset_device(struct usb_device *udev) | |||
5402 | } | 5441 | } |
5403 | } | 5442 | } |
5404 | 5443 | ||
5444 | usb_lock_port(port_dev); | ||
5405 | ret = usb_reset_and_verify_device(udev); | 5445 | ret = usb_reset_and_verify_device(udev); |
5446 | usb_unlock_port(port_dev); | ||
5406 | 5447 | ||
5407 | if (config) { | 5448 | if (config) { |
5408 | for (i = config->desc.bNumInterfaces - 1; i >= 0; --i) { | 5449 | for (i = config->desc.bNumInterfaces - 1; i >= 0; --i) { |
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h index 906c355e0631..0a7cdc0ef0a9 100644 --- a/drivers/usb/core/hub.h +++ b/drivers/usb/core/hub.h | |||
@@ -45,8 +45,6 @@ struct usb_hub { | |||
45 | unsigned long event_bits[1]; /* status change bitmask */ | 45 | unsigned long event_bits[1]; /* status change bitmask */ |
46 | unsigned long change_bits[1]; /* ports with logical connect | 46 | unsigned long change_bits[1]; /* ports with logical connect |
47 | status change */ | 47 | status change */ |
48 | unsigned long busy_bits[1]; /* ports being reset or | ||
49 | resumed */ | ||
50 | unsigned long removed_bits[1]; /* ports with a "removed" | 48 | unsigned long removed_bits[1]; /* ports with a "removed" |
51 | device present */ | 49 | device present */ |
52 | unsigned long wakeup_bits[1]; /* ports that have signaled | 50 | unsigned long wakeup_bits[1]; /* ports that have signaled |
@@ -88,6 +86,7 @@ struct usb_hub { | |||
88 | * @peer: related usb2 and usb3 ports (share the same connector) | 86 | * @peer: related usb2 and usb3 ports (share the same connector) |
89 | * @connect_type: port's connect type | 87 | * @connect_type: port's connect type |
90 | * @location: opaque representation of platform connector location | 88 | * @location: opaque representation of platform connector location |
89 | * @status_lock: synchronize port_event() vs usb_port_{suspend|resume} | ||
91 | * @portnum: port index num based one | 90 | * @portnum: port index num based one |
92 | * @is_superspeed cache super-speed status | 91 | * @is_superspeed cache super-speed status |
93 | */ | 92 | */ |
@@ -98,6 +97,7 @@ struct usb_port { | |||
98 | struct usb_port *peer; | 97 | struct usb_port *peer; |
99 | enum usb_port_connect_type connect_type; | 98 | enum usb_port_connect_type connect_type; |
100 | usb_port_location_t location; | 99 | usb_port_location_t location; |
100 | struct mutex status_lock; | ||
101 | u8 portnum; | 101 | u8 portnum; |
102 | unsigned int is_superspeed:1; | 102 | unsigned int is_superspeed:1; |
103 | }; | 103 | }; |
diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index fb83c2c13920..8b1655700104 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c | |||
@@ -95,8 +95,6 @@ static int usb_port_runtime_resume(struct device *dev) | |||
95 | pm_runtime_get_sync(&peer->dev); | 95 | pm_runtime_get_sync(&peer->dev); |
96 | 96 | ||
97 | usb_autopm_get_interface(intf); | 97 | usb_autopm_get_interface(intf); |
98 | set_bit(port1, hub->busy_bits); | ||
99 | |||
100 | retval = usb_hub_set_port_power(hdev, hub, port1, true); | 98 | retval = usb_hub_set_port_power(hdev, hub, port1, true); |
101 | msleep(hub_power_on_good_delay(hub)); | 99 | msleep(hub_power_on_good_delay(hub)); |
102 | if (port_dev->child && !retval) { | 100 | if (port_dev->child && !retval) { |
@@ -113,7 +111,6 @@ static int usb_port_runtime_resume(struct device *dev) | |||
113 | retval = 0; | 111 | retval = 0; |
114 | } | 112 | } |
115 | 113 | ||
116 | clear_bit(port1, hub->busy_bits); | ||
117 | usb_autopm_put_interface(intf); | 114 | usb_autopm_put_interface(intf); |
118 | 115 | ||
119 | return retval; | 116 | return retval; |
@@ -139,12 +136,10 @@ static int usb_port_runtime_suspend(struct device *dev) | |||
139 | return -EAGAIN; | 136 | return -EAGAIN; |
140 | 137 | ||
141 | usb_autopm_get_interface(intf); | 138 | usb_autopm_get_interface(intf); |
142 | set_bit(port1, hub->busy_bits); | ||
143 | retval = usb_hub_set_port_power(hdev, hub, port1, false); | 139 | retval = usb_hub_set_port_power(hdev, hub, port1, false); |
144 | usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_CONNECTION); | 140 | usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_CONNECTION); |
145 | if (!port_dev->is_superspeed) | 141 | if (!port_dev->is_superspeed) |
146 | usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_ENABLE); | 142 | usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_ENABLE); |
147 | clear_bit(port1, hub->busy_bits); | ||
148 | usb_autopm_put_interface(intf); | 143 | usb_autopm_put_interface(intf); |
149 | 144 | ||
150 | /* | 145 | /* |
@@ -400,6 +395,7 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1) | |||
400 | port_dev->is_superspeed = 1; | 395 | port_dev->is_superspeed = 1; |
401 | dev_set_name(&port_dev->dev, "%s-port%d", dev_name(&hub->hdev->dev), | 396 | dev_set_name(&port_dev->dev, "%s-port%d", dev_name(&hub->hdev->dev), |
402 | port1); | 397 | port1); |
398 | mutex_init(&port_dev->status_lock); | ||
403 | retval = device_register(&port_dev->dev); | 399 | retval = device_register(&port_dev->dev); |
404 | if (retval) | 400 | if (retval) |
405 | goto error_register; | 401 | goto error_register; |