diff options
| -rw-r--r-- | drivers/usb/core/driver.c | 131 | ||||
| -rw-r--r-- | drivers/usb/core/hub.c | 27 | ||||
| -rw-r--r-- | drivers/usb/core/usb.h | 2 | ||||
| -rw-r--r-- | include/linux/usb.h | 1 |
4 files changed, 140 insertions, 21 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 8da1a56659be..ddb54e14a5c5 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
| @@ -201,6 +201,7 @@ static int usb_probe_interface(struct device *dev) | |||
| 201 | 201 | ||
| 202 | intf = to_usb_interface(dev); | 202 | intf = to_usb_interface(dev); |
| 203 | udev = interface_to_usbdev(intf); | 203 | udev = interface_to_usbdev(intf); |
| 204 | intf->needs_binding = 0; | ||
| 204 | 205 | ||
| 205 | if (udev->authorized == 0) { | 206 | if (udev->authorized == 0) { |
| 206 | dev_err(&intf->dev, "Device is not authorized for usage\n"); | 207 | dev_err(&intf->dev, "Device is not authorized for usage\n"); |
| @@ -311,6 +312,7 @@ int usb_driver_claim_interface(struct usb_driver *driver, | |||
| 311 | 312 | ||
| 312 | dev->driver = &driver->drvwrap.driver; | 313 | dev->driver = &driver->drvwrap.driver; |
| 313 | usb_set_intfdata(iface, priv); | 314 | usb_set_intfdata(iface, priv); |
| 315 | iface->needs_binding = 0; | ||
| 314 | 316 | ||
| 315 | usb_pm_lock(udev); | 317 | usb_pm_lock(udev); |
| 316 | iface->condition = USB_INTERFACE_BOUND; | 318 | iface->condition = USB_INTERFACE_BOUND; |
| @@ -772,6 +774,104 @@ void usb_deregister(struct usb_driver *driver) | |||
| 772 | } | 774 | } |
| 773 | EXPORT_SYMBOL_GPL(usb_deregister); | 775 | EXPORT_SYMBOL_GPL(usb_deregister); |
| 774 | 776 | ||
| 777 | |||
| 778 | /* Forced unbinding of a USB interface driver, either because | ||
| 779 | * it doesn't support pre_reset/post_reset/reset_resume or | ||
| 780 | * because it doesn't support suspend/resume. | ||
| 781 | * | ||
| 782 | * The caller must hold @intf's device's lock, but not its pm_mutex | ||
| 783 | * and not @intf->dev.sem. | ||
| 784 | */ | ||
| 785 | void usb_forced_unbind_intf(struct usb_interface *intf) | ||
| 786 | { | ||
| 787 | struct usb_driver *driver = to_usb_driver(intf->dev.driver); | ||
| 788 | |||
| 789 | dev_dbg(&intf->dev, "forced unbind\n"); | ||
| 790 | usb_driver_release_interface(driver, intf); | ||
| 791 | |||
| 792 | /* Mark the interface for later rebinding */ | ||
| 793 | intf->needs_binding = 1; | ||
| 794 | } | ||
| 795 | |||
| 796 | /* Delayed forced unbinding of a USB interface driver and scan | ||
| 797 | * for rebinding. | ||
| 798 | * | ||
| 799 | * The caller must hold @intf's device's lock, but not its pm_mutex | ||
| 800 | * and not @intf->dev.sem. | ||
| 801 | * | ||
| 802 | * FIXME: The caller must block system sleep transitions. | ||
| 803 | */ | ||
| 804 | void usb_rebind_intf(struct usb_interface *intf) | ||
| 805 | { | ||
| 806 | int rc; | ||
| 807 | |||
| 808 | /* Delayed unbind of an existing driver */ | ||
| 809 | if (intf->dev.driver) { | ||
| 810 | struct usb_driver *driver = | ||
| 811 | to_usb_driver(intf->dev.driver); | ||
| 812 | |||
| 813 | dev_dbg(&intf->dev, "forced unbind\n"); | ||
| 814 | usb_driver_release_interface(driver, intf); | ||
| 815 | } | ||
| 816 | |||
| 817 | /* Try to rebind the interface */ | ||
| 818 | intf->needs_binding = 0; | ||
| 819 | rc = device_attach(&intf->dev); | ||
| 820 | if (rc < 0) | ||
| 821 | dev_warn(&intf->dev, "rebind failed: %d\n", rc); | ||
| 822 | } | ||
| 823 | |||
| 824 | #define DO_UNBIND 0 | ||
| 825 | #define DO_REBIND 1 | ||
| 826 | |||
| 827 | /* Unbind drivers for @udev's interfaces that don't support suspend/resume, | ||
| 828 | * or rebind interfaces that have been unbound, according to @action. | ||
| 829 | * | ||
| 830 | * The caller must hold @udev's device lock. | ||
| 831 | * FIXME: For rebinds, the caller must block system sleep transitions. | ||
| 832 | */ | ||
| 833 | static void do_unbind_rebind(struct usb_device *udev, int action) | ||
| 834 | { | ||
| 835 | struct usb_host_config *config; | ||
| 836 | int i; | ||
| 837 | struct usb_interface *intf; | ||
| 838 | struct usb_driver *drv; | ||
| 839 | |||
| 840 | config = udev->actconfig; | ||
| 841 | if (config) { | ||
| 842 | for (i = 0; i < config->desc.bNumInterfaces; ++i) { | ||
| 843 | intf = config->interface[i]; | ||
| 844 | switch (action) { | ||
| 845 | case DO_UNBIND: | ||
| 846 | if (intf->dev.driver) { | ||
| 847 | drv = to_usb_driver(intf->dev.driver); | ||
| 848 | if (!drv->suspend || !drv->resume) | ||
| 849 | usb_forced_unbind_intf(intf); | ||
| 850 | } | ||
| 851 | break; | ||
| 852 | case DO_REBIND: | ||
| 853 | if (intf->needs_binding) { | ||
| 854 | |||
| 855 | /* FIXME: The next line is needed because we are going to probe | ||
| 856 | * the interface, but as far as the PM core is concerned the | ||
| 857 | * interface is still suspended. The problem wouldn't exist | ||
| 858 | * if we could rebind the interface during the interface's own | ||
| 859 | * resume() call, but at the time the usb_device isn't locked! | ||
| 860 | * | ||
| 861 | * The real solution will be to carry this out during the device's | ||
| 862 | * complete() callback. Until that is implemented, we have to | ||
| 863 | * use this hack. | ||
| 864 | */ | ||
| 865 | // intf->dev.power.sleeping = 0; | ||
| 866 | |||
| 867 | usb_rebind_intf(intf); | ||
| 868 | } | ||
| 869 | break; | ||
| 870 | } | ||
| 871 | } | ||
| 872 | } | ||
| 873 | } | ||
| 874 | |||
| 775 | #ifdef CONFIG_PM | 875 | #ifdef CONFIG_PM |
| 776 | 876 | ||
| 777 | /* Caller has locked udev's pm_mutex */ | 877 | /* Caller has locked udev's pm_mutex */ |
| @@ -841,7 +941,7 @@ static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg) | |||
| 841 | goto done; | 941 | goto done; |
| 842 | driver = to_usb_driver(intf->dev.driver); | 942 | driver = to_usb_driver(intf->dev.driver); |
| 843 | 943 | ||
| 844 | if (driver->suspend && driver->resume) { | 944 | if (driver->suspend) { |
| 845 | status = driver->suspend(intf, msg); | 945 | status = driver->suspend(intf, msg); |
| 846 | if (status == 0) | 946 | if (status == 0) |
| 847 | mark_quiesced(intf); | 947 | mark_quiesced(intf); |
| @@ -849,12 +949,10 @@ static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg) | |||
| 849 | dev_err(&intf->dev, "%s error %d\n", | 949 | dev_err(&intf->dev, "%s error %d\n", |
| 850 | "suspend", status); | 950 | "suspend", status); |
| 851 | } else { | 951 | } else { |
| 852 | /* | 952 | /* Later we will unbind the driver and reprobe */ |
| 853 | * FIXME else if there's no suspend method, disconnect... | 953 | intf->needs_binding = 1; |
| 854 | * Not possible if auto_pm is set... | 954 | dev_warn(&intf->dev, "no %s for driver %s?\n", |
| 855 | */ | 955 | "suspend", driver->name); |
| 856 | dev_warn(&intf->dev, "no suspend for driver %s?\n", | ||
| 857 | driver->name); | ||
| 858 | mark_quiesced(intf); | 956 | mark_quiesced(intf); |
| 859 | } | 957 | } |
| 860 | 958 | ||
| @@ -878,10 +976,12 @@ static int usb_resume_interface(struct usb_interface *intf, int reset_resume) | |||
| 878 | goto done; | 976 | goto done; |
| 879 | 977 | ||
| 880 | /* Can't resume it if it doesn't have a driver. */ | 978 | /* Can't resume it if it doesn't have a driver. */ |
| 881 | if (intf->condition == USB_INTERFACE_UNBOUND) { | 979 | if (intf->condition == USB_INTERFACE_UNBOUND) |
| 882 | status = -ENOTCONN; | 980 | goto done; |
| 981 | |||
| 982 | /* Don't resume if the interface is marked for rebinding */ | ||
| 983 | if (intf->needs_binding) | ||
| 883 | goto done; | 984 | goto done; |
| 884 | } | ||
| 885 | driver = to_usb_driver(intf->dev.driver); | 985 | driver = to_usb_driver(intf->dev.driver); |
| 886 | 986 | ||
| 887 | if (reset_resume) { | 987 | if (reset_resume) { |
| @@ -891,7 +991,7 @@ static int usb_resume_interface(struct usb_interface *intf, int reset_resume) | |||
| 891 | dev_err(&intf->dev, "%s error %d\n", | 991 | dev_err(&intf->dev, "%s error %d\n", |
| 892 | "reset_resume", status); | 992 | "reset_resume", status); |
| 893 | } else { | 993 | } else { |
| 894 | /* status = -EOPNOTSUPP; */ | 994 | intf->needs_binding = 1; |
| 895 | dev_warn(&intf->dev, "no %s for driver %s?\n", | 995 | dev_warn(&intf->dev, "no %s for driver %s?\n", |
| 896 | "reset_resume", driver->name); | 996 | "reset_resume", driver->name); |
| 897 | } | 997 | } |
| @@ -902,7 +1002,7 @@ static int usb_resume_interface(struct usb_interface *intf, int reset_resume) | |||
| 902 | dev_err(&intf->dev, "%s error %d\n", | 1002 | dev_err(&intf->dev, "%s error %d\n", |
| 903 | "resume", status); | 1003 | "resume", status); |
| 904 | } else { | 1004 | } else { |
| 905 | /* status = -EOPNOTSUPP; */ | 1005 | intf->needs_binding = 1; |
| 906 | dev_warn(&intf->dev, "no %s for driver %s?\n", | 1006 | dev_warn(&intf->dev, "no %s for driver %s?\n", |
| 907 | "resume", driver->name); | 1007 | "resume", driver->name); |
| 908 | } | 1008 | } |
| @@ -910,11 +1010,10 @@ static int usb_resume_interface(struct usb_interface *intf, int reset_resume) | |||
| 910 | 1010 | ||
| 911 | done: | 1011 | done: |
| 912 | dev_vdbg(&intf->dev, "%s: status %d\n", __func__, status); | 1012 | dev_vdbg(&intf->dev, "%s: status %d\n", __func__, status); |
| 913 | if (status == 0) | 1013 | if (status == 0 && intf->condition == USB_INTERFACE_BOUND) |
| 914 | mark_active(intf); | 1014 | mark_active(intf); |
| 915 | 1015 | ||
| 916 | /* FIXME: Unbind the driver and reprobe if the resume failed | 1016 | /* Later we will unbind the driver and/or reprobe, if necessary */ |
| 917 | * (not possible if auto_pm is set) */ | ||
| 918 | return status; | 1017 | return status; |
| 919 | } | 1018 | } |
| 920 | 1019 | ||
| @@ -1470,6 +1569,7 @@ int usb_external_suspend_device(struct usb_device *udev, pm_message_t msg) | |||
| 1470 | { | 1569 | { |
| 1471 | int status; | 1570 | int status; |
| 1472 | 1571 | ||
| 1572 | do_unbind_rebind(udev, DO_UNBIND); | ||
| 1473 | usb_pm_lock(udev); | 1573 | usb_pm_lock(udev); |
| 1474 | udev->auto_pm = 0; | 1574 | udev->auto_pm = 0; |
| 1475 | status = usb_suspend_both(udev, msg); | 1575 | status = usb_suspend_both(udev, msg); |
| @@ -1497,6 +1597,7 @@ int usb_external_resume_device(struct usb_device *udev) | |||
| 1497 | status = usb_resume_both(udev); | 1597 | status = usb_resume_both(udev); |
| 1498 | udev->last_busy = jiffies; | 1598 | udev->last_busy = jiffies; |
| 1499 | usb_pm_unlock(udev); | 1599 | usb_pm_unlock(udev); |
| 1600 | do_unbind_rebind(udev, DO_REBIND); | ||
| 1500 | 1601 | ||
| 1501 | /* Now that the device is awake, we can start trying to autosuspend | 1602 | /* Now that the device is awake, we can start trying to autosuspend |
| 1502 | * it again. */ | 1603 | * it again. */ |
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index bb3ecc4c08f2..f1efabbc1ca2 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
| @@ -3367,6 +3367,11 @@ re_enumerate: | |||
| 3367 | * this from a driver probe() routine after downloading new firmware. | 3367 | * this from a driver probe() routine after downloading new firmware. |
| 3368 | * For calls that might not occur during probe(), drivers should lock | 3368 | * For calls that might not occur during probe(), drivers should lock |
| 3369 | * the device using usb_lock_device_for_reset(). | 3369 | * the device using usb_lock_device_for_reset(). |
| 3370 | * | ||
| 3371 | * If an interface is currently being probed or disconnected, we assume | ||
| 3372 | * its driver knows how to handle resets. For all other interfaces, | ||
| 3373 | * if the driver doesn't have pre_reset and post_reset methods then | ||
| 3374 | * we attempt to unbind it and rebind afterward. | ||
| 3370 | */ | 3375 | */ |
| 3371 | int usb_reset_device(struct usb_device *udev) | 3376 | int usb_reset_device(struct usb_device *udev) |
| 3372 | { | 3377 | { |
| @@ -3388,12 +3393,17 @@ int usb_reset_device(struct usb_device *udev) | |||
| 3388 | for (i = 0; i < config->desc.bNumInterfaces; ++i) { | 3393 | for (i = 0; i < config->desc.bNumInterfaces; ++i) { |
| 3389 | struct usb_interface *cintf = config->interface[i]; | 3394 | struct usb_interface *cintf = config->interface[i]; |
| 3390 | struct usb_driver *drv; | 3395 | struct usb_driver *drv; |
| 3396 | int unbind = 0; | ||
| 3391 | 3397 | ||
| 3392 | if (cintf->dev.driver) { | 3398 | if (cintf->dev.driver) { |
| 3393 | drv = to_usb_driver(cintf->dev.driver); | 3399 | drv = to_usb_driver(cintf->dev.driver); |
| 3394 | if (drv->pre_reset) | 3400 | if (drv->pre_reset && drv->post_reset) |
| 3395 | (drv->pre_reset)(cintf); | 3401 | unbind = (drv->pre_reset)(cintf); |
| 3396 | /* FIXME: Unbind if pre_reset returns an error or isn't defined */ | 3402 | else if (cintf->condition == |
| 3403 | USB_INTERFACE_BOUND) | ||
| 3404 | unbind = 1; | ||
| 3405 | if (unbind) | ||
| 3406 | usb_forced_unbind_intf(cintf); | ||
| 3397 | } | 3407 | } |
| 3398 | } | 3408 | } |
| 3399 | } | 3409 | } |
| @@ -3404,13 +3414,18 @@ int usb_reset_device(struct usb_device *udev) | |||
| 3404 | for (i = config->desc.bNumInterfaces - 1; i >= 0; --i) { | 3414 | for (i = config->desc.bNumInterfaces - 1; i >= 0; --i) { |
| 3405 | struct usb_interface *cintf = config->interface[i]; | 3415 | struct usb_interface *cintf = config->interface[i]; |
| 3406 | struct usb_driver *drv; | 3416 | struct usb_driver *drv; |
| 3417 | int rebind = cintf->needs_binding; | ||
| 3407 | 3418 | ||
| 3408 | if (cintf->dev.driver) { | 3419 | if (!rebind && cintf->dev.driver) { |
| 3409 | drv = to_usb_driver(cintf->dev.driver); | 3420 | drv = to_usb_driver(cintf->dev.driver); |
| 3410 | if (drv->post_reset) | 3421 | if (drv->post_reset) |
| 3411 | (drv->post_reset)(cintf); | 3422 | rebind = (drv->post_reset)(cintf); |
| 3412 | /* FIXME: Unbind if post_reset returns an error or isn't defined */ | 3423 | else if (cintf->condition == |
| 3424 | USB_INTERFACE_BOUND) | ||
| 3425 | rebind = 1; | ||
| 3413 | } | 3426 | } |
| 3427 | if (rebind) | ||
| 3428 | usb_rebind_intf(cintf); | ||
| 3414 | } | 3429 | } |
| 3415 | } | 3430 | } |
| 3416 | 3431 | ||
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 1a8bc21c335e..d3eb0a29bca1 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h | |||
| @@ -29,6 +29,8 @@ extern int usb_choose_configuration(struct usb_device *udev); | |||
| 29 | extern void usb_kick_khubd(struct usb_device *dev); | 29 | extern void usb_kick_khubd(struct usb_device *dev); |
| 30 | extern int usb_match_device(struct usb_device *dev, | 30 | extern int usb_match_device(struct usb_device *dev, |
| 31 | const struct usb_device_id *id); | 31 | const struct usb_device_id *id); |
| 32 | extern void usb_forced_unbind_intf(struct usb_interface *intf); | ||
| 33 | extern void usb_rebind_intf(struct usb_interface *intf); | ||
| 32 | 34 | ||
| 33 | extern int usb_hub_init(void); | 35 | extern int usb_hub_init(void); |
| 34 | extern void usb_hub_cleanup(void); | 36 | extern void usb_hub_cleanup(void); |
diff --git a/include/linux/usb.h b/include/linux/usb.h index 3cc8db5254d1..5811c5da69f9 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h | |||
| @@ -160,6 +160,7 @@ struct usb_interface { | |||
| 160 | unsigned is_active:1; /* the interface is not suspended */ | 160 | unsigned is_active:1; /* the interface is not suspended */ |
| 161 | unsigned sysfs_files_created:1; /* the sysfs attributes exist */ | 161 | unsigned sysfs_files_created:1; /* the sysfs attributes exist */ |
| 162 | unsigned needs_remote_wakeup:1; /* driver requires remote wakeup */ | 162 | unsigned needs_remote_wakeup:1; /* driver requires remote wakeup */ |
| 163 | unsigned needs_binding:1; /* needs delayed unbind/rebind */ | ||
| 163 | 164 | ||
| 164 | struct device dev; /* interface specific device info */ | 165 | struct device dev; /* interface specific device info */ |
| 165 | struct device *usb_dev; | 166 | struct device *usb_dev; |
