Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: introduce port status lock

In general we do not want khubd to act on port status changes that are
the result of in progress resets or USB runtime PM operations.
Specifically port power control testing has been able to trigger an
unintended disconnect in hub_port_connect_change(), paraphrasing:

if ((portstatus & USB_PORT_STAT_CONNECTION) && udev &&
udev->state != USB_STATE_NOTATTACHED) {
if (portstatus & USB_PORT_STAT_ENABLE) {
/* Nothing to do */
} else if (udev->state == USB_STATE_SUSPENDED &&
udev->persist_enabled) {
...
} else {
/* Don't resuscitate */;
}
}

...by falling to the "Don't resuscitate" path or missing
USB_PORT_STAT_CONNECTION because usb_port_resume() was in the middle of
modifying the port status.

So, we want a new lock to hold off khubd for a given port while the
child device is being suspended, resumed, or reset. The lock ordering
rules are now usb_lock_device() => usb_lock_port(). This is mandated by
the device core which may hold the device_lock on the usb_device before
invoking usb_port_{suspend|resume} which in turn take the status_lock on
the usb_port. We attempt to hold the status_lock for the duration of a
port_event() run, and drop/re-acquire it when needing to take the
device_lock. The lock is also dropped/re-acquired during
hub_port_reconnect().

This patch also deletes hub->busy_bits as all use cases are now covered
by port PM runtime synchronization or the port->status_lock and it
pushes down usb_device_lock() into usb_remote_wakeup().

Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Dan Williams and committed by
Greg Kroah-Hartman
5c79a1e3 097a155f

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