diff options
Diffstat (limited to 'drivers/usb/core/usb.c')
-rw-r--r-- | drivers/usb/core/usb.c | 114 |
1 files changed, 9 insertions, 105 deletions
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 294e9f127477..fcfda21be499 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c | |||
@@ -32,7 +32,6 @@ | |||
32 | #include <linux/spinlock.h> | 32 | #include <linux/spinlock.h> |
33 | #include <linux/errno.h> | 33 | #include <linux/errno.h> |
34 | #include <linux/smp_lock.h> | 34 | #include <linux/smp_lock.h> |
35 | #include <linux/rwsem.h> | ||
36 | #include <linux/usb.h> | 35 | #include <linux/usb.h> |
37 | 36 | ||
38 | #include <asm/io.h> | 37 | #include <asm/io.h> |
@@ -49,8 +48,6 @@ const char *usbcore_name = "usbcore"; | |||
49 | static int nousb; /* Disable USB when built into kernel image */ | 48 | static int nousb; /* Disable USB when built into kernel image */ |
50 | /* Not honored on modular build */ | 49 | /* Not honored on modular build */ |
51 | 50 | ||
52 | static DECLARE_RWSEM(usb_all_devices_rwsem); | ||
53 | |||
54 | 51 | ||
55 | /** | 52 | /** |
56 | * usb_ifnum_to_if - get the interface object with a given interface number | 53 | * usb_ifnum_to_if - get the interface object with a given interface number |
@@ -446,8 +443,6 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1) | |||
446 | dev->parent = parent; | 443 | dev->parent = parent; |
447 | INIT_LIST_HEAD(&dev->filelist); | 444 | INIT_LIST_HEAD(&dev->filelist); |
448 | 445 | ||
449 | init_MUTEX(&dev->serialize); | ||
450 | |||
451 | return dev; | 446 | return dev; |
452 | } | 447 | } |
453 | 448 | ||
@@ -520,76 +515,21 @@ void usb_put_intf(struct usb_interface *intf) | |||
520 | 515 | ||
521 | /* USB device locking | 516 | /* USB device locking |
522 | * | 517 | * |
523 | * Although locking USB devices should be straightforward, it is | 518 | * USB devices and interfaces are locked using the semaphore in their |
524 | * complicated by the way the driver-model core works. When a new USB | 519 | * embedded struct device. The hub driver guarantees that whenever a |
525 | * driver is registered or unregistered, the core will automatically | 520 | * device is connected or disconnected, drivers are called with the |
526 | * probe or disconnect all matching interfaces on all USB devices while | 521 | * USB device locked as well as their particular interface. |
527 | * holding the USB subsystem writelock. There's no good way for us to | ||
528 | * tell which devices will be used or to lock them beforehand; our only | ||
529 | * option is to effectively lock all the USB devices. | ||
530 | * | ||
531 | * We do that by using a private rw-semaphore, usb_all_devices_rwsem. | ||
532 | * When locking an individual device you must first acquire the rwsem's | ||
533 | * readlock. When a driver is registered or unregistered the writelock | ||
534 | * must be held. These actions are encapsulated in the subroutines | ||
535 | * below, so all a driver needs to do is call usb_lock_device() and | ||
536 | * usb_unlock_device(). | ||
537 | * | 522 | * |
538 | * Complications arise when several devices are to be locked at the same | 523 | * Complications arise when several devices are to be locked at the same |
539 | * time. Only hub-aware drivers that are part of usbcore ever have to | 524 | * time. Only hub-aware drivers that are part of usbcore ever have to |
540 | * do this; nobody else needs to worry about it. The problem is that | 525 | * do this; nobody else needs to worry about it. The rule for locking |
541 | * usb_lock_device() must not be called to lock a second device since it | 526 | * is simple: |
542 | * would acquire the rwsem's readlock reentrantly, leading to deadlock if | ||
543 | * another thread was waiting for the writelock. The solution is simple: | ||
544 | * | ||
545 | * When locking more than one device, call usb_lock_device() | ||
546 | * to lock the first one. Lock the others by calling | ||
547 | * down(&udev->serialize) directly. | ||
548 | * | ||
549 | * When unlocking multiple devices, use up(&udev->serialize) | ||
550 | * to unlock all but the last one. Unlock the last one by | ||
551 | * calling usb_unlock_device(). | ||
552 | * | 527 | * |
553 | * When locking both a device and its parent, always lock the | 528 | * When locking both a device and its parent, always lock the |
554 | * the parent first. | 529 | * the parent first. |
555 | */ | 530 | */ |
556 | 531 | ||
557 | /** | 532 | /** |
558 | * usb_lock_device - acquire the lock for a usb device structure | ||
559 | * @udev: device that's being locked | ||
560 | * | ||
561 | * Use this routine when you don't hold any other device locks; | ||
562 | * to acquire nested inner locks call down(&udev->serialize) directly. | ||
563 | * This is necessary for proper interaction with usb_lock_all_devices(). | ||
564 | */ | ||
565 | void usb_lock_device(struct usb_device *udev) | ||
566 | { | ||
567 | down_read(&usb_all_devices_rwsem); | ||
568 | down(&udev->serialize); | ||
569 | } | ||
570 | |||
571 | /** | ||
572 | * usb_trylock_device - attempt to acquire the lock for a usb device structure | ||
573 | * @udev: device that's being locked | ||
574 | * | ||
575 | * Don't use this routine if you already hold a device lock; | ||
576 | * use down_trylock(&udev->serialize) instead. | ||
577 | * This is necessary for proper interaction with usb_lock_all_devices(). | ||
578 | * | ||
579 | * Returns 1 if successful, 0 if contention. | ||
580 | */ | ||
581 | int usb_trylock_device(struct usb_device *udev) | ||
582 | { | ||
583 | if (!down_read_trylock(&usb_all_devices_rwsem)) | ||
584 | return 0; | ||
585 | if (down_trylock(&udev->serialize)) { | ||
586 | up_read(&usb_all_devices_rwsem); | ||
587 | return 0; | ||
588 | } | ||
589 | return 1; | ||
590 | } | ||
591 | |||
592 | /** | ||
593 | * usb_lock_device_for_reset - cautiously acquire the lock for a | 533 | * usb_lock_device_for_reset - cautiously acquire the lock for a |
594 | * usb device structure | 534 | * usb device structure |
595 | * @udev: device that's being locked | 535 | * @udev: device that's being locked |
@@ -627,7 +567,7 @@ int usb_lock_device_for_reset(struct usb_device *udev, | |||
627 | } | 567 | } |
628 | } | 568 | } |
629 | 569 | ||
630 | while (!usb_trylock_device(udev)) { | 570 | while (usb_trylock_device(udev) != 0) { |
631 | 571 | ||
632 | /* If we can't acquire the lock after waiting one second, | 572 | /* If we can't acquire the lock after waiting one second, |
633 | * we're probably deadlocked */ | 573 | * we're probably deadlocked */ |
@@ -645,39 +585,6 @@ int usb_lock_device_for_reset(struct usb_device *udev, | |||
645 | return 1; | 585 | return 1; |
646 | } | 586 | } |
647 | 587 | ||
648 | /** | ||
649 | * usb_unlock_device - release the lock for a usb device structure | ||
650 | * @udev: device that's being unlocked | ||
651 | * | ||
652 | * Use this routine when releasing the only device lock you hold; | ||
653 | * to release inner nested locks call up(&udev->serialize) directly. | ||
654 | * This is necessary for proper interaction with usb_lock_all_devices(). | ||
655 | */ | ||
656 | void usb_unlock_device(struct usb_device *udev) | ||
657 | { | ||
658 | up(&udev->serialize); | ||
659 | up_read(&usb_all_devices_rwsem); | ||
660 | } | ||
661 | |||
662 | /** | ||
663 | * usb_lock_all_devices - acquire the lock for all usb device structures | ||
664 | * | ||
665 | * This is necessary when registering a new driver or probing a bus, | ||
666 | * since the driver-model core may try to use any usb_device. | ||
667 | */ | ||
668 | void usb_lock_all_devices(void) | ||
669 | { | ||
670 | down_write(&usb_all_devices_rwsem); | ||
671 | } | ||
672 | |||
673 | /** | ||
674 | * usb_unlock_all_devices - release the lock for all usb device structures | ||
675 | */ | ||
676 | void usb_unlock_all_devices(void) | ||
677 | { | ||
678 | up_write(&usb_all_devices_rwsem); | ||
679 | } | ||
680 | |||
681 | 588 | ||
682 | static struct usb_device *match_device(struct usb_device *dev, | 589 | static struct usb_device *match_device(struct usb_device *dev, |
683 | u16 vendor_id, u16 product_id) | 590 | u16 vendor_id, u16 product_id) |
@@ -700,10 +607,10 @@ static struct usb_device *match_device(struct usb_device *dev, | |||
700 | /* look through all of the children of this device */ | 607 | /* look through all of the children of this device */ |
701 | for (child = 0; child < dev->maxchild; ++child) { | 608 | for (child = 0; child < dev->maxchild; ++child) { |
702 | if (dev->children[child]) { | 609 | if (dev->children[child]) { |
703 | down(&dev->children[child]->serialize); | 610 | usb_lock_device(dev->children[child]); |
704 | ret_dev = match_device(dev->children[child], | 611 | ret_dev = match_device(dev->children[child], |
705 | vendor_id, product_id); | 612 | vendor_id, product_id); |
706 | up(&dev->children[child]->serialize); | 613 | usb_unlock_device(dev->children[child]); |
707 | if (ret_dev) | 614 | if (ret_dev) |
708 | goto exit; | 615 | goto exit; |
709 | } | 616 | } |
@@ -1300,10 +1207,7 @@ EXPORT_SYMBOL(usb_put_dev); | |||
1300 | EXPORT_SYMBOL(usb_get_dev); | 1207 | EXPORT_SYMBOL(usb_get_dev); |
1301 | EXPORT_SYMBOL(usb_hub_tt_clear_buffer); | 1208 | EXPORT_SYMBOL(usb_hub_tt_clear_buffer); |
1302 | 1209 | ||
1303 | EXPORT_SYMBOL(usb_lock_device); | ||
1304 | EXPORT_SYMBOL(usb_trylock_device); | ||
1305 | EXPORT_SYMBOL(usb_lock_device_for_reset); | 1210 | EXPORT_SYMBOL(usb_lock_device_for_reset); |
1306 | EXPORT_SYMBOL(usb_unlock_device); | ||
1307 | 1211 | ||
1308 | EXPORT_SYMBOL(usb_driver_claim_interface); | 1212 | EXPORT_SYMBOL(usb_driver_claim_interface); |
1309 | EXPORT_SYMBOL(usb_driver_release_interface); | 1213 | EXPORT_SYMBOL(usb_driver_release_interface); |