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

[PATCH] USB: Remove USB private semaphore

This patch (as605) removes the private udev->serialize semaphore,
relying instead on the locking provided by the embedded struct device's
semaphore. The changes are confined to the core, except that the
usb_trylock_device routine now uses the return convention of
down_trylock rather than down_read_trylock (they return opposite values
for no good reason).

A couple of other associated changes are included as well:

Now that we aren't concerned about HCDs that avoid using the
hcd glue layer, usb_disconnect no longer needs to acquire the
usb_bus_lock -- that can be done by usb_remove_hcd where it
belongs.

Devices aren't locked over the same scope of code in
usb_new_device and hub_port_connect_change as they used to be.
This shouldn't cause any trouble.

Along with the preceding driver core patch, this needs a lot of testing.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

Alan Stern and committed by
Greg Kroah-Hartman
9ad3d6cc 75318d2d

+37 -154
+2 -2
drivers/usb/core/devices.c
··· 545 545 struct usb_device *childdev = usbdev->children[chix]; 546 546 547 547 if (childdev) { 548 - down(&childdev->serialize); 548 + usb_lock_device(childdev); 549 549 ret = usb_device_dump(buffer, nbytes, skip_bytes, file_offset, childdev, 550 550 bus, level + 1, chix, ++cnt); 551 - up(&childdev->serialize); 551 + usb_unlock_device(childdev); 552 552 if (ret == -EFAULT) 553 553 return total_written; 554 554 total_written += ret;
-2
drivers/usb/core/devio.c
··· 1349 1349 /* let kernel drivers try to (re)bind to the interface */ 1350 1350 case USBDEVFS_CONNECT: 1351 1351 usb_unlock_device(ps->dev); 1352 - usb_lock_all_devices(); 1353 1352 bus_rescan_devices(intf->dev.bus); 1354 - usb_unlock_all_devices(); 1355 1353 usb_lock_device(ps->dev); 1356 1354 break; 1357 1355
-4
drivers/usb/core/driver.c
··· 432 432 spin_lock_init(&new_driver->dynids.lock); 433 433 INIT_LIST_HEAD(&new_driver->dynids.list); 434 434 435 - usb_lock_all_devices(); 436 435 retval = driver_register(&new_driver->driver); 437 - usb_unlock_all_devices(); 438 436 439 437 if (!retval) { 440 438 pr_info("%s: registered new driver %s\n", ··· 463 465 { 464 466 pr_info("%s: deregistering driver %s\n", usbcore_name, driver->name); 465 467 466 - usb_lock_all_devices(); 467 468 usb_remove_newid_file(driver); 468 469 usb_free_dynids(driver); 469 470 driver_unregister(&driver->driver); 470 - usb_unlock_all_devices(); 471 471 472 472 usbfs_update_special(); 473 473 }
+3 -2
drivers/usb/core/hcd.c
··· 857 857 return (retval < 0) ? retval : -EMSGSIZE; 858 858 } 859 859 860 - usb_lock_device (usb_dev); 861 860 retval = usb_new_device (usb_dev); 862 - usb_unlock_device (usb_dev); 863 861 if (retval) { 864 862 usb_dev->bus->root_hub = NULL; 865 863 dev_err (parent_dev, "can't register root hub for %s, %d\n", ··· 1889 1891 spin_lock_irq (&hcd_root_hub_lock); 1890 1892 hcd->rh_registered = 0; 1891 1893 spin_unlock_irq (&hcd_root_hub_lock); 1894 + 1895 + down(&usb_bus_list_lock); 1892 1896 usb_disconnect(&hcd->self.root_hub); 1897 + up(&usb_bus_list_lock); 1893 1898 1894 1899 hcd->poll_rh = 0; 1895 1900 del_timer_sync(&hcd->rh_timer);
+18 -30
drivers/usb/core/hub.c
··· 32 32 #include "hub.h" 33 33 34 34 /* Protect struct usb_device->state and ->children members 35 - * Note: Both are also protected by ->serialize, except that ->state can 35 + * Note: Both are also protected by ->dev.sem, except that ->state can 36 36 * change to USB_STATE_NOTATTACHED even when the semaphore isn't held. */ 37 37 static DEFINE_SPINLOCK(device_state_lock); 38 38 ··· 975 975 /* when everyone grabs locks top->bottom, 976 976 * non-overlapping work may be concurrent 977 977 */ 978 - down(&udev->serialize); 979 - up(&hdev->serialize); 978 + usb_lock_device(udev); 979 + usb_unlock_device(hdev); 980 980 return t + 1; 981 981 } 982 982 } ··· 1132 1132 * this quiesces everyting except pending urbs. 1133 1133 */ 1134 1134 usb_set_device_state(udev, USB_STATE_NOTATTACHED); 1135 - 1136 - /* lock the bus list on behalf of HCDs unregistering their root hubs */ 1137 - if (!udev->parent) { 1138 - down(&usb_bus_list_lock); 1139 - usb_lock_device(udev); 1140 - } else 1141 - down(&udev->serialize); 1142 - 1143 1135 dev_info (&udev->dev, "USB disconnect, address %d\n", udev->devnum); 1136 + 1137 + usb_lock_device(udev); 1144 1138 1145 1139 /* Free up all the children before we remove this device */ 1146 1140 for (i = 0; i < USB_MAXCHILDREN; i++) { ··· 1163 1169 *pdev = NULL; 1164 1170 spin_unlock_irq(&device_state_lock); 1165 1171 1166 - if (!udev->parent) { 1167 - usb_unlock_device(udev); 1168 - up(&usb_bus_list_lock); 1169 - } else 1170 - up(&udev->serialize); 1172 + usb_unlock_device(udev); 1171 1173 1172 1174 device_unregister(&udev->dev); 1173 1175 } ··· 1233 1243 * 1234 1244 * This is called with devices which have been enumerated, but not yet 1235 1245 * configured. The device descriptor is available, but not descriptors 1236 - * for any device configuration. The caller must have locked udev and 1237 - * either the parent hub (if udev is a normal device) or else the 1246 + * for any device configuration. The caller must have locked either 1247 + * the parent hub (if udev is a normal device) or else the 1238 1248 * usb_bus_list_lock (if udev is a root hub). The parent's pointer to 1239 1249 * udev has already been installed, but udev is not yet visible through 1240 1250 * sysfs or other filesystem code. ··· 1244 1254 * 1245 1255 * This call is synchronous, and may not be used in an interrupt context. 1246 1256 * 1247 - * Only the hub driver should ever call this; root hub registration 1248 - * uses it indirectly. 1257 + * Only the hub driver or root-hub registrar should ever call this. 1249 1258 */ 1250 1259 int usb_new_device(struct usb_device *udev) 1251 1260 { ··· 1353 1364 } 1354 1365 usb_create_sysfs_dev_files (udev); 1355 1366 1367 + usb_lock_device(udev); 1368 + 1356 1369 /* choose and set the configuration. that registers the interfaces 1357 1370 * with the driver core, and lets usb device drivers bind to them. 1358 1371 */ ··· 1375 1384 1376 1385 /* USB device state == configured ... usable */ 1377 1386 usb_notify_add_device(udev); 1387 + 1388 + usb_unlock_device(udev); 1378 1389 1379 1390 return 0; 1380 1391 ··· 1865 1872 usb_unlock_device(udev); 1866 1873 1867 1874 /* rebind drivers that had no suspend() */ 1868 - if (status == 0) { 1869 - usb_lock_all_devices(); 1875 + if (status == 0) 1870 1876 bus_rescan_devices(&usb_bus_type); 1871 - usb_unlock_all_devices(); 1872 - } 1873 1877 return status; 1874 1878 } 1875 1879 ··· 1879 1889 /* don't repeat RESUME sequence if this device 1880 1890 * was already woken up by some other task 1881 1891 */ 1882 - down(&udev->serialize); 1892 + usb_lock_device(udev); 1883 1893 if (udev->state == USB_STATE_SUSPENDED) { 1884 1894 dev_dbg(&udev->dev, "RESUME (wakeup)\n"); 1885 1895 /* TRSMRCY = 10 msec */ 1886 1896 msleep(10); 1887 1897 status = finish_device_resume(udev); 1888 1898 } 1889 - up(&udev->serialize); 1899 + usb_unlock_device(udev); 1890 1900 #endif 1891 1901 return status; 1892 1902 } ··· 1987 1997 1988 1998 if (!udev || status < 0) 1989 1999 continue; 1990 - down (&udev->serialize); 2000 + usb_lock_device(udev); 1991 2001 if (portstat & USB_PORT_STAT_SUSPEND) 1992 2002 status = hub_port_resume(hub, port1, udev); 1993 2003 else { ··· 1998 2008 hub_port_logical_disconnect(hub, port1); 1999 2009 } 2000 2010 } 2001 - up(&udev->serialize); 2011 + usb_unlock_device(udev); 2002 2012 } 2003 2013 } 2004 2014 #endif ··· 2563 2573 * udev becomes globally accessible, although presumably 2564 2574 * no one will look at it until hdev is unlocked. 2565 2575 */ 2566 - down (&udev->serialize); 2567 2576 status = 0; 2568 2577 2569 2578 /* We mustn't add new devices if the parent hub has ··· 2586 2597 } 2587 2598 } 2588 2599 2589 - up (&udev->serialize); 2590 2600 if (status) 2591 2601 goto loop_disable; 2592 2602
+9 -105
drivers/usb/core/usb.c
··· 32 32 #include <linux/spinlock.h> 33 33 #include <linux/errno.h> 34 34 #include <linux/smp_lock.h> 35 - #include <linux/rwsem.h> 36 35 #include <linux/usb.h> 37 36 38 37 #include <asm/io.h> ··· 47 48 48 49 static int nousb; /* Disable USB when built into kernel image */ 49 50 /* Not honored on modular build */ 50 - 51 - static DECLARE_RWSEM(usb_all_devices_rwsem); 52 51 53 52 54 53 /** ··· 443 446 dev->parent = parent; 444 447 INIT_LIST_HEAD(&dev->filelist); 445 448 446 - init_MUTEX(&dev->serialize); 447 - 448 449 return dev; 449 450 } 450 451 ··· 515 520 516 521 /* USB device locking 517 522 * 518 - * Although locking USB devices should be straightforward, it is 519 - * complicated by the way the driver-model core works. When a new USB 520 - * driver is registered or unregistered, the core will automatically 521 - * probe or disconnect all matching interfaces on all USB devices while 522 - * holding the USB subsystem writelock. There's no good way for us to 523 - * tell which devices will be used or to lock them beforehand; our only 524 - * option is to effectively lock all the USB devices. 525 - * 526 - * We do that by using a private rw-semaphore, usb_all_devices_rwsem. 527 - * When locking an individual device you must first acquire the rwsem's 528 - * readlock. When a driver is registered or unregistered the writelock 529 - * must be held. These actions are encapsulated in the subroutines 530 - * below, so all a driver needs to do is call usb_lock_device() and 531 - * usb_unlock_device(). 523 + * USB devices and interfaces are locked using the semaphore in their 524 + * embedded struct device. The hub driver guarantees that whenever a 525 + * device is connected or disconnected, drivers are called with the 526 + * USB device locked as well as their particular interface. 532 527 * 533 528 * Complications arise when several devices are to be locked at the same 534 529 * time. Only hub-aware drivers that are part of usbcore ever have to 535 - * do this; nobody else needs to worry about it. The problem is that 536 - * usb_lock_device() must not be called to lock a second device since it 537 - * would acquire the rwsem's readlock reentrantly, leading to deadlock if 538 - * another thread was waiting for the writelock. The solution is simple: 539 - * 540 - * When locking more than one device, call usb_lock_device() 541 - * to lock the first one. Lock the others by calling 542 - * down(&udev->serialize) directly. 543 - * 544 - * When unlocking multiple devices, use up(&udev->serialize) 545 - * to unlock all but the last one. Unlock the last one by 546 - * calling usb_unlock_device(). 530 + * do this; nobody else needs to worry about it. The rule for locking 531 + * is simple: 547 532 * 548 533 * When locking both a device and its parent, always lock the 549 534 * the parent first. 550 535 */ 551 - 552 - /** 553 - * usb_lock_device - acquire the lock for a usb device structure 554 - * @udev: device that's being locked 555 - * 556 - * Use this routine when you don't hold any other device locks; 557 - * to acquire nested inner locks call down(&udev->serialize) directly. 558 - * This is necessary for proper interaction with usb_lock_all_devices(). 559 - */ 560 - void usb_lock_device(struct usb_device *udev) 561 - { 562 - down_read(&usb_all_devices_rwsem); 563 - down(&udev->serialize); 564 - } 565 - 566 - /** 567 - * usb_trylock_device - attempt to acquire the lock for a usb device structure 568 - * @udev: device that's being locked 569 - * 570 - * Don't use this routine if you already hold a device lock; 571 - * use down_trylock(&udev->serialize) instead. 572 - * This is necessary for proper interaction with usb_lock_all_devices(). 573 - * 574 - * Returns 1 if successful, 0 if contention. 575 - */ 576 - int usb_trylock_device(struct usb_device *udev) 577 - { 578 - if (!down_read_trylock(&usb_all_devices_rwsem)) 579 - return 0; 580 - if (down_trylock(&udev->serialize)) { 581 - up_read(&usb_all_devices_rwsem); 582 - return 0; 583 - } 584 - return 1; 585 - } 586 536 587 537 /** 588 538 * usb_lock_device_for_reset - cautiously acquire the lock for a ··· 567 627 } 568 628 } 569 629 570 - while (!usb_trylock_device(udev)) { 630 + while (usb_trylock_device(udev) != 0) { 571 631 572 632 /* If we can't acquire the lock after waiting one second, 573 633 * we're probably deadlocked */ ··· 583 643 return -EINTR; 584 644 } 585 645 return 1; 586 - } 587 - 588 - /** 589 - * usb_unlock_device - release the lock for a usb device structure 590 - * @udev: device that's being unlocked 591 - * 592 - * Use this routine when releasing the only device lock you hold; 593 - * to release inner nested locks call up(&udev->serialize) directly. 594 - * This is necessary for proper interaction with usb_lock_all_devices(). 595 - */ 596 - void usb_unlock_device(struct usb_device *udev) 597 - { 598 - up(&udev->serialize); 599 - up_read(&usb_all_devices_rwsem); 600 - } 601 - 602 - /** 603 - * usb_lock_all_devices - acquire the lock for all usb device structures 604 - * 605 - * This is necessary when registering a new driver or probing a bus, 606 - * since the driver-model core may try to use any usb_device. 607 - */ 608 - void usb_lock_all_devices(void) 609 - { 610 - down_write(&usb_all_devices_rwsem); 611 - } 612 - 613 - /** 614 - * usb_unlock_all_devices - release the lock for all usb device structures 615 - */ 616 - void usb_unlock_all_devices(void) 617 - { 618 - up_write(&usb_all_devices_rwsem); 619 646 } 620 647 621 648 ··· 607 700 /* look through all of the children of this device */ 608 701 for (child = 0; child < dev->maxchild; ++child) { 609 702 if (dev->children[child]) { 610 - down(&dev->children[child]->serialize); 703 + usb_lock_device(dev->children[child]); 611 704 ret_dev = match_device(dev->children[child], 612 705 vendor_id, product_id); 613 - up(&dev->children[child]->serialize); 706 + usb_unlock_device(dev->children[child]); 614 707 if (ret_dev) 615 708 goto exit; 616 709 } ··· 1207 1300 EXPORT_SYMBOL(usb_get_dev); 1208 1301 EXPORT_SYMBOL(usb_hub_tt_clear_buffer); 1209 1302 1210 - EXPORT_SYMBOL(usb_lock_device); 1211 - EXPORT_SYMBOL(usb_trylock_device); 1212 1303 EXPORT_SYMBOL(usb_lock_device_for_reset); 1213 - EXPORT_SYMBOL(usb_unlock_device); 1214 1304 1215 1305 EXPORT_SYMBOL(usb_driver_claim_interface); 1216 1306 EXPORT_SYMBOL(usb_driver_release_interface);
-3
drivers/usb/core/usb.h
··· 16 16 extern char *usb_cache_string(struct usb_device *udev, int index); 17 17 extern int usb_set_configuration(struct usb_device *dev, int configuration); 18 18 19 - extern void usb_lock_all_devices(void); 20 - extern void usb_unlock_all_devices(void); 21 - 22 19 extern void usb_kick_khubd(struct usb_device *dev); 23 20 extern void usb_suspend_root_hub(struct usb_device *hdev); 24 21 extern void usb_resume_root_hub(struct usb_device *dev);
+1 -1
drivers/usb/host/ohci-hub.c
··· 372 372 & ohci->hc_control) 373 373 == OHCI_USB_OPER 374 374 && time_after (jiffies, ohci->next_statechange) 375 - && usb_trylock_device (hcd->self.root_hub) 375 + && usb_trylock_device (hcd->self.root_hub) == 0 376 376 ) { 377 377 ohci_vdbg (ohci, "autosuspend\n"); 378 378 (void) ohci_bus_suspend (hcd);
+4 -5
include/linux/usb.h
··· 329 329 struct usb_tt *tt; /* low/full speed dev, highspeed hub */ 330 330 int ttport; /* device port on that tt hub */ 331 331 332 - struct semaphore serialize; 333 - 334 332 unsigned int toggle[2]; /* one bit for each endpoint 335 333 * ([0] = IN, [1] = OUT) */ 336 334 ··· 375 377 extern struct usb_device *usb_get_dev(struct usb_device *dev); 376 378 extern void usb_put_dev(struct usb_device *dev); 377 379 378 - extern void usb_lock_device(struct usb_device *udev); 379 - extern int usb_trylock_device(struct usb_device *udev); 380 + /* USB device locking */ 381 + #define usb_lock_device(udev) down(&(udev)->dev.sem) 382 + #define usb_unlock_device(udev) up(&(udev)->dev.sem) 383 + #define usb_trylock_device(udev) down_trylock(&(udev)->dev.sem) 380 384 extern int usb_lock_device_for_reset(struct usb_device *udev, 381 385 struct usb_interface *iface); 382 - extern void usb_unlock_device(struct usb_device *udev); 383 386 384 387 /* USB port reset for device reinitialization */ 385 388 extern int usb_reset_device(struct usb_device *dev);