aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/power/swsusp.txt3
-rw-r--r--Documentation/usb/persist.txt144
-rw-r--r--drivers/hid/usbhid/hid-core.c2
-rw-r--r--drivers/usb/core/Kconfig22
-rw-r--r--drivers/usb/core/driver.c39
-rw-r--r--drivers/usb/core/generic.c5
-rw-r--r--drivers/usb/core/hub.c196
-rw-r--r--drivers/usb/core/usb.h1
-rw-r--r--drivers/usb/storage/usb.c8
-rw-r--r--include/linux/usb.h8
10 files changed, 351 insertions, 77 deletions
diff --git a/Documentation/power/swsusp.txt b/Documentation/power/swsusp.txt
index 5b8d6953f05e..152b510d1bbb 100644
--- a/Documentation/power/swsusp.txt
+++ b/Documentation/power/swsusp.txt
@@ -393,6 +393,9 @@ safest thing is to unmount all filesystems on removable media (such USB,
393Firewire, CompactFlash, MMC, external SATA, or even IDE hotplug bays) 393Firewire, CompactFlash, MMC, external SATA, or even IDE hotplug bays)
394before suspending; then remount them after resuming. 394before suspending; then remount them after resuming.
395 395
396There is a work-around for this problem. For more information, see
397Documentation/usb/persist.txt.
398
396Q: I upgraded the kernel from 2.6.15 to 2.6.16. Both kernels were 399Q: I upgraded the kernel from 2.6.15 to 2.6.16. Both kernels were
397compiled with the similar configuration files. Anyway I found that 400compiled with the similar configuration files. Anyway I found that
398suspend to disk (and resume) is much slower on 2.6.16 compared to 401suspend to disk (and resume) is much slower on 2.6.16 compared to
diff --git a/Documentation/usb/persist.txt b/Documentation/usb/persist.txt
new file mode 100644
index 000000000000..6dcd5f884795
--- /dev/null
+++ b/Documentation/usb/persist.txt
@@ -0,0 +1,144 @@
1 USB device persistence during system suspend
2
3 Alan Stern <stern@rowland.harvard.edu>
4
5 September 2, 2006 (Updated March 27, 2007)
6
7
8 What is the problem?
9
10According to the USB specification, when a USB bus is suspended the
11bus must continue to supply suspend current (around 1-5 mA). This
12is so that devices can maintain their internal state and hubs can
13detect connect-change events (devices being plugged in or unplugged).
14The technical term is "power session".
15
16If a USB device's power session is interrupted then the system is
17required to behave as though the device has been unplugged. It's a
18conservative approach; in the absence of suspend current the computer
19has no way to know what has actually happened. Perhaps the same
20device is still attached or perhaps it was removed and a different
21device plugged into the port. The system must assume the worst.
22
23By default, Linux behaves according to the spec. If a USB host
24controller loses power during a system suspend, then when the system
25wakes up all the devices attached to that controller are treated as
26though they had disconnected. This is always safe and it is the
27"officially correct" thing to do.
28
29For many sorts of devices this behavior doesn't matter in the least.
30If the kernel wants to believe that your USB keyboard was unplugged
31while the system was asleep and a new keyboard was plugged in when the
32system woke up, who cares? It'll still work the same when you type on
33it.
34
35Unfortunately problems _can_ arise, particularly with mass-storage
36devices. The effect is exactly the same as if the device really had
37been unplugged while the system was suspended. If you had a mounted
38filesystem on the device, you're out of luck -- everything in that
39filesystem is now inaccessible. This is especially annoying if your
40root filesystem was located on the device, since your system will
41instantly crash.
42
43Loss of power isn't the only mechanism to worry about. Anything that
44interrupts a power session will have the same effect. For example,
45even though suspend current may have been maintained while the system
46was asleep, on many systems during the initial stages of wakeup the
47firmware (i.e., the BIOS) resets the motherboard's USB host
48controllers. Result: all the power sessions are destroyed and again
49it's as though you had unplugged all the USB devices. Yes, it's
50entirely the BIOS's fault, but that doesn't do _you_ any good unless
51you can convince the BIOS supplier to fix the problem (lots of luck!).
52
53On many systems the USB host controllers will get reset after a
54suspend-to-RAM. On almost all systems, no suspend current is
55available during suspend-to-disk (also known as swsusp). You can
56check the kernel log after resuming to see if either of these has
57happened; look for lines saying "root hub lost power or was reset".
58
59In practice, people are forced to unmount any filesystems on a USB
60device before suspending. If the root filesystem is on a USB device,
61the system can't be suspended at all. (All right, it _can_ be
62suspended -- but it will crash as soon as it wakes up, which isn't
63much better.)
64
65
66 What is the solution?
67
68Setting CONFIG_USB_PERSIST will cause the kernel to work around these
69issues. It enables a mode in which the core USB device data
70structures are allowed to persist across a power-session disruption.
71It works like this. If the kernel sees that a USB host controller is
72not in the expected state during resume (i.e., if the controller was
73reset or otherwise had lost power) then it applies a persistence check
74to each of the USB devices below that controller. It doesn't try to
75resume the device; that can't work once the power session is gone.
76Instead it issues a USB port reset and then re-enumerates the device.
77(This is exactly the same thing that happens whenever a USB device is
78reset.) If the re-enumeration shows that the device now attached to
79that port has the same descriptors as before, including the Vendor and
80Product IDs, then the kernel continues to use the same device
81structure. In effect, the kernel treats the device as though it had
82merely been reset instead of unplugged.
83
84If no device is now attached to the port, or if the descriptors are
85different from what the kernel remembers, then the treatment is what
86you would expect. The kernel destroys the old device structure and
87behaves as though the old device had been unplugged and a new device
88plugged in, just as it would without the CONFIG_USB_PERSIST option.
89
90The end result is that the USB device remains available and usable.
91Filesystem mounts and memory mappings are unaffected, and the world is
92now a good and happy place.
93
94
95 Is this the best solution?
96
97Perhaps not. Arguably, keeping track of mounted filesystems and
98memory mappings across device disconnects should be handled by a
99centralized Logical Volume Manager. Such a solution would allow you
100to plug in a USB flash device, create a persistent volume associated
101with it, unplug the flash device, plug it back in later, and still
102have the same persistent volume associated with the device. As such
103it would be more far-reaching than CONFIG_USB_PERSIST.
104
105On the other hand, writing a persistent volume manager would be a big
106job and using it would require significant input from the user. This
107solution is much quicker and easier -- and it exists now, a giant
108point in its favor!
109
110Furthermore, the USB_PERSIST option applies to _all_ USB devices, not
111just mass-storage devices. It might turn out to be equally useful for
112other device types, such as network interfaces.
113
114
115 WARNING: Using CONFIG_USB_PERSIST can be dangerous!!
116
117When recovering an interrupted power session the kernel does its best
118to make sure the USB device hasn't been changed; that is, the same
119device is still plugged into the port as before. But the checks
120aren't guaranteed to be 100% accurate.
121
122If you replace one USB device with another of the same type (same
123manufacturer, same IDs, and so on) there's an excellent chance the
124kernel won't detect the change. Serial numbers and other strings are
125not compared. In many cases it wouldn't help if they were, because
126manufacturers frequently omit serial numbers entirely in their
127devices.
128
129Furthermore it's quite possible to leave a USB device exactly the same
130while changing its media. If you replace the flash memory card in a
131USB card reader while the system is asleep, the kernel will have no
132way to know you did it. The kernel will assume that nothing has
133happened and will continue to use the partition tables, inodes, and
134memory mappings for the old card.
135
136If the kernel gets fooled in this way, it's almost certain to cause
137data corruption and to crash your system. You'll have no one to blame
138but yourself.
139
140YOU HAVE BEEN WARNED! USE AT YOUR OWN RISK!
141
142That having been said, most of the time there shouldn't be any trouble
143at all. The "persist" feature can be extremely useful. Make the most
144of it.
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 3afa4a5035b7..e221b0d1f667 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -1015,7 +1015,7 @@ static void hid_pre_reset(struct usb_interface *intf)
1015 hid_suspend(intf, PMSG_ON); 1015 hid_suspend(intf, PMSG_ON);
1016} 1016}
1017 1017
1018static void hid_post_reset(struct usb_interface *intf) 1018static void hid_post_reset(struct usb_interface *intf, int reset_resume)
1019{ 1019{
1020 struct usb_device *dev = interface_to_usbdev (intf); 1020 struct usb_device *dev = interface_to_usbdev (intf);
1021 1021
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index 346fc030c929..5113ef4cb7f6 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -86,6 +86,28 @@ config USB_SUSPEND
86 86
87 If you are unsure about this, say N here. 87 If you are unsure about this, say N here.
88 88
89config USB_PERSIST
90 bool "USB device persistence during system suspend (DANGEROUS)"
91 depends on USB && PM && EXPERIMENTAL
92 default n
93 help
94 If you say Y here, USB device data structures will remain
95 persistent across system suspend, even if the USB bus loses
96 power. (This includes software-suspend, also known as swsusp,
97 or suspend-to-disk.) The devices will reappear as if by magic
98 when the system wakes up, with no need to unmount USB filesystems,
99 rmmod host-controller drivers, or do anything else.
100
101 WARNING: This option can be dangerous!
102
103 If a USB device is replaced by another of the same type while
104 the system is asleep, there's a good chance the kernel won't
105 detect the change. Likewise if the media in a USB storage
106 device is replaced. When this happens it's almost certain to
107 cause data corruption and maybe even crash your system.
108
109 If you are unsure, say N here.
110
89config USB_OTG 111config USB_OTG
90 bool 112 bool
91 depends on USB && EXPERIMENTAL 113 depends on USB && EXPERIMENTAL
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index e8b447e06c54..12dd986bdffd 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -824,8 +824,9 @@ static int usb_resume_device(struct usb_device *udev)
824 struct usb_device_driver *udriver; 824 struct usb_device_driver *udriver;
825 int status = 0; 825 int status = 0;
826 826
827 if (udev->state == USB_STATE_NOTATTACHED || 827 if (udev->state == USB_STATE_NOTATTACHED)
828 udev->state != USB_STATE_SUSPENDED) 828 goto done;
829 if (udev->state != USB_STATE_SUSPENDED && !udev->reset_resume)
829 goto done; 830 goto done;
830 831
831 /* Can't resume it if it doesn't have a driver. */ 832 /* Can't resume it if it doesn't have a driver. */
@@ -882,7 +883,7 @@ done:
882} 883}
883 884
884/* Caller has locked intf's usb_device's pm_mutex */ 885/* Caller has locked intf's usb_device's pm_mutex */
885static int usb_resume_interface(struct usb_interface *intf) 886static int usb_resume_interface(struct usb_interface *intf, int reset_resume)
886{ 887{
887 struct usb_driver *driver; 888 struct usb_driver *driver;
888 int status = 0; 889 int status = 0;
@@ -902,21 +903,21 @@ static int usb_resume_interface(struct usb_interface *intf)
902 } 903 }
903 driver = to_usb_driver(intf->dev.driver); 904 driver = to_usb_driver(intf->dev.driver);
904 905
905 if (driver->resume) { 906 if (reset_resume && driver->post_reset)
907 driver->post_reset(intf, reset_resume);
908 else if (driver->resume) {
906 status = driver->resume(intf); 909 status = driver->resume(intf);
907 if (status) 910 if (status)
908 dev_err(&intf->dev, "%s error %d\n", 911 dev_err(&intf->dev, "%s error %d\n",
909 "resume", status); 912 "resume", status);
910 else 913 } else
911 mark_active(intf);
912 } else {
913 dev_warn(&intf->dev, "no resume for driver %s?\n", 914 dev_warn(&intf->dev, "no resume for driver %s?\n",
914 driver->name); 915 driver->name);
915 mark_active(intf);
916 }
917 916
918done: 917done:
919 // dev_dbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status); 918 // dev_dbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
919 if (status == 0)
920 mark_active(intf);
920 return status; 921 return status;
921} 922}
922 923
@@ -1063,7 +1064,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
1063 if (status != 0) { 1064 if (status != 0) {
1064 while (--i >= 0) { 1065 while (--i >= 0) {
1065 intf = udev->actconfig->interface[i]; 1066 intf = udev->actconfig->interface[i];
1066 usb_resume_interface(intf); 1067 usb_resume_interface(intf, 0);
1067 } 1068 }
1068 1069
1069 /* Try another autosuspend when the interfaces aren't busy */ 1070 /* Try another autosuspend when the interfaces aren't busy */
@@ -1162,20 +1163,21 @@ static int usb_resume_both(struct usb_device *udev)
1162 } 1163 }
1163 } else { 1164 } else {
1164 1165
1165 /* Needed only for setting udev->dev.power.power_state.event 1166 /* Needed for setting udev->dev.power.power_state.event,
1166 * and for possible debugging message. */ 1167 * for possible debugging message, and for reset_resume. */
1167 status = usb_resume_device(udev); 1168 status = usb_resume_device(udev);
1168 } 1169 }
1169 1170
1170 if (status == 0 && udev->actconfig) { 1171 if (status == 0 && udev->actconfig) {
1171 for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { 1172 for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
1172 intf = udev->actconfig->interface[i]; 1173 intf = udev->actconfig->interface[i];
1173 usb_resume_interface(intf); 1174 usb_resume_interface(intf, udev->reset_resume);
1174 } 1175 }
1175 } 1176 }
1176 1177
1177 done: 1178 done:
1178 // dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status); 1179 // dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
1180 udev->reset_resume = 0;
1179 return status; 1181 return status;
1180} 1182}
1181 1183
@@ -1510,8 +1512,15 @@ static int usb_resume(struct device *dev)
1510 if (!is_usb_device(dev)) /* Ignore PM for interfaces */ 1512 if (!is_usb_device(dev)) /* Ignore PM for interfaces */
1511 return 0; 1513 return 0;
1512 udev = to_usb_device(dev); 1514 udev = to_usb_device(dev);
1513 if (udev->autoresume_disabled) 1515
1514 return -EPERM; 1516 /* If autoresume is disabled then we also want to prevent resume
1517 * during system wakeup. However, a "persistent-device" reset-resume
1518 * after power loss counts as a wakeup event. So allow a
1519 * reset-resume to occur if remote wakeup is enabled. */
1520 if (udev->autoresume_disabled) {
1521 if (!(udev->reset_resume && udev->do_remote_wakeup))
1522 return -EPERM;
1523 }
1515 return usb_external_resume_device(udev); 1524 return usb_external_resume_device(udev);
1516} 1525}
1517 1526
diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
index 7cbf992adccd..d363b0ea7345 100644
--- a/drivers/usb/core/generic.c
+++ b/drivers/usb/core/generic.c
@@ -217,7 +217,10 @@ static int generic_resume(struct usb_device *udev)
217{ 217{
218 int rc; 218 int rc;
219 219
220 rc = usb_port_resume(udev); 220 if (udev->reset_resume)
221 rc = usb_reset_suspended_device(udev);
222 else
223 rc = usb_port_resume(udev);
221 224
222 /* Root hubs don't have upstream ports to resume or reset, 225 /* Root hubs don't have upstream ports to resume or reset,
223 * so the line above won't do much for them. We have to 226 * so the line above won't do much for them. We have to
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 77a6627b18d2..51d2d304568b 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -553,45 +553,121 @@ static int hub_hub_status(struct usb_hub *hub,
553static int hub_port_disable(struct usb_hub *hub, int port1, int set_state) 553static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
554{ 554{
555 struct usb_device *hdev = hub->hdev; 555 struct usb_device *hdev = hub->hdev;
556 int ret; 556 int ret = 0;
557 557
558 if (hdev->children[port1-1] && set_state) { 558 if (hdev->children[port1-1] && set_state)
559 usb_set_device_state(hdev->children[port1-1], 559 usb_set_device_state(hdev->children[port1-1],
560 USB_STATE_NOTATTACHED); 560 USB_STATE_NOTATTACHED);
561 } 561 if (!hub->error)
562 ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE); 562 ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE);
563 if (ret) 563 if (ret)
564 dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n", 564 dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n",
565 port1, ret); 565 port1, ret);
566
567 return ret; 566 return ret;
568} 567}
569 568
569/*
570 * Disable a port and mark a logical connnect-change event, so that some
571 * time later khubd will disconnect() any existing usb_device on the port
572 * and will re-enumerate if there actually is a device attached.
573 */
574static void hub_port_logical_disconnect(struct usb_hub *hub, int port1)
575{
576 dev_dbg(hub->intfdev, "logical disconnect on port %d\n", port1);
577 hub_port_disable(hub, port1, 1);
570 578
571/* caller has locked the hub device */ 579 /* FIXME let caller ask to power down the port:
572static void hub_pre_reset(struct usb_interface *intf) 580 * - some devices won't enumerate without a VBUS power cycle
581 * - SRP saves power that way
582 * - ... new call, TBD ...
583 * That's easy if this hub can switch power per-port, and
584 * khubd reactivates the port later (timer, SRP, etc).
585 * Powerdown must be optional, because of reset/DFU.
586 */
587
588 set_bit(port1, hub->change_bits);
589 kick_khubd(hub);
590}
591
592static void disconnect_all_children(struct usb_hub *hub, int logical)
573{ 593{
574 struct usb_hub *hub = usb_get_intfdata(intf);
575 struct usb_device *hdev = hub->hdev; 594 struct usb_device *hdev = hub->hdev;
576 int port1; 595 int port1;
577 596
578 for (port1 = 1; port1 <= hdev->maxchild; ++port1) { 597 for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
579 if (hdev->children[port1 - 1]) { 598 if (hdev->children[port1-1]) {
580 usb_disconnect(&hdev->children[port1 - 1]); 599 if (logical)
581 if (hub->error == 0) 600 hub_port_logical_disconnect(hub, port1);
582 hub_port_disable(hub, port1, 0); 601 else
602 usb_disconnect(&hdev->children[port1-1]);
603 }
604 }
605}
606
607#ifdef CONFIG_USB_PERSIST
608
609#define USB_PERSIST 1
610
611/* For "persistent-device" resets we must mark the child devices for reset
612 * and turn off a possible connect-change status (so khubd won't disconnect
613 * them later).
614 */
615static void mark_children_for_reset_resume(struct usb_hub *hub)
616{
617 struct usb_device *hdev = hub->hdev;
618 int port1;
619
620 for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
621 struct usb_device *child = hdev->children[port1-1];
622
623 if (child) {
624 child->reset_resume = 1;
625 clear_port_feature(hdev, port1,
626 USB_PORT_FEAT_C_CONNECTION);
583 } 627 }
584 } 628 }
629}
630
631#else
632
633#define USB_PERSIST 0
634
635static inline void mark_children_for_reset_resume(struct usb_hub *hub)
636{ }
637
638#endif /* CONFIG_USB_PERSIST */
639
640/* caller has locked the hub device */
641static void hub_pre_reset(struct usb_interface *intf)
642{
643 struct usb_hub *hub = usb_get_intfdata(intf);
644
645 /* This routine doesn't run as part of a reset-resume, so it's safe
646 * to disconnect all the drivers below the hub.
647 */
648 disconnect_all_children(hub, 0);
585 hub_quiesce(hub); 649 hub_quiesce(hub);
586} 650}
587 651
588/* caller has locked the hub device */ 652/* caller has locked the hub device */
589static void hub_post_reset(struct usb_interface *intf) 653static void hub_post_reset(struct usb_interface *intf, int reset_resume)
590{ 654{
591 struct usb_hub *hub = usb_get_intfdata(intf); 655 struct usb_hub *hub = usb_get_intfdata(intf);
592 656
593 hub_activate(hub);
594 hub_power_on(hub); 657 hub_power_on(hub);
658 if (reset_resume) {
659 if (USB_PERSIST)
660 mark_children_for_reset_resume(hub);
661 else {
662 /* Reset-resume doesn't call pre_reset, so we have to
663 * disconnect the children here. But we may not lock
664 * the child devices, so we have to do a "logical"
665 * disconnect.
666 */
667 disconnect_all_children(hub, 1);
668 }
669 }
670 hub_activate(hub);
595} 671}
596 672
597 673
@@ -1054,32 +1130,63 @@ void usb_set_device_state(struct usb_device *udev,
1054#ifdef CONFIG_PM 1130#ifdef CONFIG_PM
1055 1131
1056/** 1132/**
1133 * usb_reset_suspended_device - reset a suspended device instead of resuming it
1134 * @udev: device to be reset instead of resumed
1135 *
1136 * If a host controller doesn't maintain VBUS suspend current during a
1137 * system sleep or is reset when the system wakes up, all the USB
1138 * power sessions below it will be broken. This is especially troublesome
1139 * for mass-storage devices containing mounted filesystems, since the
1140 * device will appear to have disconnected and all the memory mappings
1141 * to it will be lost.
1142 *
1143 * As an alternative, this routine attempts to recover power sessions for
1144 * devices that are still present by resetting them instead of resuming
1145 * them. If all goes well, the devices will appear to persist across the
1146 * the interruption of the power sessions.
1147 *
1148 * This facility is inherently dangerous. Although usb_reset_device()
1149 * makes every effort to insure that the same device is present after the
1150 * reset as before, it cannot provide a 100% guarantee. Furthermore it's
1151 * quite possible for a device to remain unaltered but its media to be
1152 * changed. If the user replaces a flash memory card while the system is
1153 * asleep, he will have only himself to blame when the filesystem on the
1154 * new card is corrupted and the system crashes.
1155 */
1156int usb_reset_suspended_device(struct usb_device *udev)
1157{
1158 int rc = 0;
1159
1160 dev_dbg(&udev->dev, "usb %sresume\n", "reset-");
1161
1162 /* After we're done the device won't be suspended any more.
1163 * In addition, the reset won't work if udev->state is SUSPENDED.
1164 */
1165 usb_set_device_state(udev, udev->actconfig
1166 ? USB_STATE_CONFIGURED
1167 : USB_STATE_ADDRESS);
1168
1169 /* Root hubs don't need to be (and can't be) reset */
1170 if (udev->parent)
1171 rc = usb_reset_device(udev);
1172 return rc;
1173}
1174
1175/**
1057 * usb_root_hub_lost_power - called by HCD if the root hub lost Vbus power 1176 * usb_root_hub_lost_power - called by HCD if the root hub lost Vbus power
1058 * @rhdev: struct usb_device for the root hub 1177 * @rhdev: struct usb_device for the root hub
1059 * 1178 *
1060 * The USB host controller driver calls this function when its root hub 1179 * The USB host controller driver calls this function when its root hub
1061 * is resumed and Vbus power has been interrupted or the controller 1180 * is resumed and Vbus power has been interrupted or the controller
1062 * has been reset. The routine marks all the children of the root hub 1181 * has been reset. The routine marks @rhdev as having lost power. When
1063 * as NOTATTACHED and marks logical connect-change events on their ports. 1182 * the hub driver is resumed it will take notice; if CONFIG_USB_PERSIST
1183 * is enabled then it will carry out power-session recovery, otherwise
1184 * it will disconnect all the child devices.
1064 */ 1185 */
1065void usb_root_hub_lost_power(struct usb_device *rhdev) 1186void usb_root_hub_lost_power(struct usb_device *rhdev)
1066{ 1187{
1067 struct usb_hub *hub;
1068 int port1;
1069 unsigned long flags;
1070
1071 dev_warn(&rhdev->dev, "root hub lost power or was reset\n"); 1188 dev_warn(&rhdev->dev, "root hub lost power or was reset\n");
1072 1189 rhdev->reset_resume = 1;
1073 spin_lock_irqsave(&device_state_lock, flags);
1074 hub = hdev_to_hub(rhdev);
1075 for (port1 = 1; port1 <= rhdev->maxchild; ++port1) {
1076 if (rhdev->children[port1 - 1]) {
1077 recursively_mark_NOTATTACHED(
1078 rhdev->children[port1 - 1]);
1079 set_bit(port1, hub->change_bits);
1080 }
1081 }
1082 spin_unlock_irqrestore(&device_state_lock, flags);
1083} 1190}
1084EXPORT_SYMBOL_GPL(usb_root_hub_lost_power); 1191EXPORT_SYMBOL_GPL(usb_root_hub_lost_power);
1085 1192
@@ -1513,29 +1620,6 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
1513 return status; 1620 return status;
1514} 1621}
1515 1622
1516/*
1517 * Disable a port and mark a logical connnect-change event, so that some
1518 * time later khubd will disconnect() any existing usb_device on the port
1519 * and will re-enumerate if there actually is a device attached.
1520 */
1521static void hub_port_logical_disconnect(struct usb_hub *hub, int port1)
1522{
1523 dev_dbg(hub->intfdev, "logical disconnect on port %d\n", port1);
1524 hub_port_disable(hub, port1, 1);
1525
1526 /* FIXME let caller ask to power down the port:
1527 * - some devices won't enumerate without a VBUS power cycle
1528 * - SRP saves power that way
1529 * - ... new call, TBD ...
1530 * That's easy if this hub can switch power per-port, and
1531 * khubd reactivates the port later (timer, SRP, etc).
1532 * Powerdown must be optional, because of reset/DFU.
1533 */
1534
1535 set_bit(port1, hub->change_bits);
1536 kick_khubd(hub);
1537}
1538
1539#ifdef CONFIG_PM 1623#ifdef CONFIG_PM
1540 1624
1541#ifdef CONFIG_USB_SUSPEND 1625#ifdef CONFIG_USB_SUSPEND
@@ -3018,7 +3102,7 @@ int usb_reset_composite_device(struct usb_device *udev,
3018 cintf->dev.driver) { 3102 cintf->dev.driver) {
3019 drv = to_usb_driver(cintf->dev.driver); 3103 drv = to_usb_driver(cintf->dev.driver);
3020 if (drv->post_reset) 3104 if (drv->post_reset)
3021 (drv->post_reset)(cintf); 3105 (drv->post_reset)(cintf, 0);
3022 } 3106 }
3023 if (cintf != iface) 3107 if (cintf != iface)
3024 up(&cintf->dev.sem); 3108 up(&cintf->dev.sem);
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 6f361df374fc..1a4862886733 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -36,6 +36,7 @@ extern void usb_host_cleanup(void);
36extern void usb_autosuspend_work(struct work_struct *work); 36extern void usb_autosuspend_work(struct work_struct *work);
37extern int usb_port_suspend(struct usb_device *dev); 37extern int usb_port_suspend(struct usb_device *dev);
38extern int usb_port_resume(struct usb_device *dev); 38extern int usb_port_resume(struct usb_device *dev);
39extern int usb_reset_suspended_device(struct usb_device *udev);
39extern int usb_external_suspend_device(struct usb_device *udev, 40extern int usb_external_suspend_device(struct usb_device *udev,
40 pm_message_t msg); 41 pm_message_t msg);
41extern int usb_external_resume_device(struct usb_device *udev); 42extern int usb_external_resume_device(struct usb_device *udev);
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index df5dc186aef5..be4cd8fe4ce6 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -236,7 +236,7 @@ static void storage_pre_reset(struct usb_interface *iface)
236 mutex_lock(&us->dev_mutex); 236 mutex_lock(&us->dev_mutex);
237} 237}
238 238
239static void storage_post_reset(struct usb_interface *iface) 239static void storage_post_reset(struct usb_interface *iface, int reset_resume)
240{ 240{
241 struct us_data *us = usb_get_intfdata(iface); 241 struct us_data *us = usb_get_intfdata(iface);
242 242
@@ -249,7 +249,11 @@ static void storage_post_reset(struct usb_interface *iface)
249 249
250 /* FIXME: Notify the subdrivers that they need to reinitialize 250 /* FIXME: Notify the subdrivers that they need to reinitialize
251 * the device */ 251 * the device */
252 mutex_unlock(&us->dev_mutex); 252
253 /* If this is a reset-resume then the pre_reset routine wasn't
254 * called, so we don't need to unlock the mutex. */
255 if (!reset_resume)
256 mutex_unlock(&us->dev_mutex);
253} 257}
254 258
255/* 259/*
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 56aa2ee21f1b..3d63e0c2dd70 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -403,6 +403,7 @@ struct usb_device {
403 403
404 unsigned auto_pm:1; /* autosuspend/resume in progress */ 404 unsigned auto_pm:1; /* autosuspend/resume in progress */
405 unsigned do_remote_wakeup:1; /* remote wakeup should be enabled */ 405 unsigned do_remote_wakeup:1; /* remote wakeup should be enabled */
406 unsigned reset_resume:1; /* needs reset instead of resume */
406 unsigned autosuspend_disabled:1; /* autosuspend and autoresume */ 407 unsigned autosuspend_disabled:1; /* autosuspend and autoresume */
407 unsigned autoresume_disabled:1; /* disabled by the user */ 408 unsigned autoresume_disabled:1; /* disabled by the user */
408#endif 409#endif
@@ -819,7 +820,10 @@ struct usbdrv_wrap {
819 * @pre_reset: Called by usb_reset_composite_device() when the device 820 * @pre_reset: Called by usb_reset_composite_device() when the device
820 * is about to be reset. 821 * is about to be reset.
821 * @post_reset: Called by usb_reset_composite_device() after the device 822 * @post_reset: Called by usb_reset_composite_device() after the device
822 * has been reset. 823 * has been reset, or in lieu of @resume following a reset-resume
824 * (i.e., the device is reset instead of being resumed, as might
825 * happen if power was lost). The second argument tells which is
826 * the reason.
823 * @id_table: USB drivers use ID table to support hotplugging. 827 * @id_table: USB drivers use ID table to support hotplugging.
824 * Export this with MODULE_DEVICE_TABLE(usb,...). This must be set 828 * Export this with MODULE_DEVICE_TABLE(usb,...). This must be set
825 * or your driver's probe function will never get called. 829 * or your driver's probe function will never get called.
@@ -861,7 +865,7 @@ struct usb_driver {
861 int (*resume) (struct usb_interface *intf); 865 int (*resume) (struct usb_interface *intf);
862 866
863 void (*pre_reset) (struct usb_interface *intf); 867 void (*pre_reset) (struct usb_interface *intf);
864 void (*post_reset) (struct usb_interface *intf); 868 void (*post_reset) (struct usb_interface *intf, int reset_resume);
865 869
866 const struct usb_device_id *id_table; 870 const struct usb_device_id *id_table;
867 871