| Alan Stern | 0458d5b | 2007-05-04 11:52:20 -0400 | [diff] [blame] | 1 | USB device persistence during system suspend | 
|  | 2 |  | 
|  | 3 | Alan Stern <stern@rowland.harvard.edu> | 
|  | 4 |  | 
| Alan Stern | b41a60e | 2007-05-30 15:39:33 -0400 | [diff] [blame] | 5 | September 2, 2006 (Updated May 29, 2007) | 
| Alan Stern | 0458d5b | 2007-05-04 11:52:20 -0400 | [diff] [blame] | 6 |  | 
|  | 7 |  | 
|  | 8 | What is the problem? | 
|  | 9 |  | 
|  | 10 | According to the USB specification, when a USB bus is suspended the | 
|  | 11 | bus must continue to supply suspend current (around 1-5 mA).  This | 
|  | 12 | is so that devices can maintain their internal state and hubs can | 
|  | 13 | detect connect-change events (devices being plugged in or unplugged). | 
|  | 14 | The technical term is "power session". | 
|  | 15 |  | 
|  | 16 | If a USB device's power session is interrupted then the system is | 
|  | 17 | required to behave as though the device has been unplugged.  It's a | 
|  | 18 | conservative approach; in the absence of suspend current the computer | 
|  | 19 | has no way to know what has actually happened.  Perhaps the same | 
|  | 20 | device is still attached or perhaps it was removed and a different | 
|  | 21 | device plugged into the port.  The system must assume the worst. | 
|  | 22 |  | 
|  | 23 | By default, Linux behaves according to the spec.  If a USB host | 
|  | 24 | controller loses power during a system suspend, then when the system | 
|  | 25 | wakes up all the devices attached to that controller are treated as | 
|  | 26 | though they had disconnected.  This is always safe and it is the | 
|  | 27 | "officially correct" thing to do. | 
|  | 28 |  | 
|  | 29 | For many sorts of devices this behavior doesn't matter in the least. | 
|  | 30 | If the kernel wants to believe that your USB keyboard was unplugged | 
|  | 31 | while the system was asleep and a new keyboard was plugged in when the | 
|  | 32 | system woke up, who cares?  It'll still work the same when you type on | 
|  | 33 | it. | 
|  | 34 |  | 
|  | 35 | Unfortunately problems _can_ arise, particularly with mass-storage | 
|  | 36 | devices.  The effect is exactly the same as if the device really had | 
|  | 37 | been unplugged while the system was suspended.  If you had a mounted | 
|  | 38 | filesystem on the device, you're out of luck -- everything in that | 
|  | 39 | filesystem is now inaccessible.  This is especially annoying if your | 
|  | 40 | root filesystem was located on the device, since your system will | 
|  | 41 | instantly crash. | 
|  | 42 |  | 
|  | 43 | Loss of power isn't the only mechanism to worry about.  Anything that | 
|  | 44 | interrupts a power session will have the same effect.  For example, | 
|  | 45 | even though suspend current may have been maintained while the system | 
|  | 46 | was asleep, on many systems during the initial stages of wakeup the | 
|  | 47 | firmware (i.e., the BIOS) resets the motherboard's USB host | 
|  | 48 | controllers.  Result: all the power sessions are destroyed and again | 
|  | 49 | it's as though you had unplugged all the USB devices.  Yes, it's | 
|  | 50 | entirely the BIOS's fault, but that doesn't do _you_ any good unless | 
|  | 51 | you can convince the BIOS supplier to fix the problem (lots of luck!). | 
|  | 52 |  | 
|  | 53 | On many systems the USB host controllers will get reset after a | 
|  | 54 | suspend-to-RAM.  On almost all systems, no suspend current is | 
| Alan Stern | b41a60e | 2007-05-30 15:39:33 -0400 | [diff] [blame] | 55 | available during hibernation (also known as swsusp or suspend-to-disk). | 
|  | 56 | You can check the kernel log after resuming to see if either of these | 
|  | 57 | has happened; look for lines saying "root hub lost power or was reset". | 
| Alan Stern | 0458d5b | 2007-05-04 11:52:20 -0400 | [diff] [blame] | 58 |  | 
|  | 59 | In practice, people are forced to unmount any filesystems on a USB | 
|  | 60 | device before suspending.  If the root filesystem is on a USB device, | 
|  | 61 | the system can't be suspended at all.  (All right, it _can_ be | 
|  | 62 | suspended -- but it will crash as soon as it wakes up, which isn't | 
|  | 63 | much better.) | 
|  | 64 |  | 
|  | 65 |  | 
|  | 66 | What is the solution? | 
|  | 67 |  | 
|  | 68 | Setting CONFIG_USB_PERSIST will cause the kernel to work around these | 
|  | 69 | issues.  It enables a mode in which the core USB device data | 
|  | 70 | structures are allowed to persist across a power-session disruption. | 
|  | 71 | It works like this.  If the kernel sees that a USB host controller is | 
|  | 72 | not in the expected state during resume (i.e., if the controller was | 
|  | 73 | reset or otherwise had lost power) then it applies a persistence check | 
| Alan Stern | b41a60e | 2007-05-30 15:39:33 -0400 | [diff] [blame] | 74 | to each of the USB devices below that controller for which the | 
|  | 75 | "persist" attribute is set.  It doesn't try to resume the device; that | 
|  | 76 | can't work once the power session is gone.  Instead it issues a USB | 
|  | 77 | port reset and then re-enumerates the device.  (This is exactly the | 
|  | 78 | same thing that happens whenever a USB device is reset.)  If the | 
|  | 79 | re-enumeration shows that the device now attached to that port has the | 
|  | 80 | same descriptors as before, including the Vendor and Product IDs, then | 
|  | 81 | the kernel continues to use the same device structure.  In effect, the | 
|  | 82 | kernel treats the device as though it had merely been reset instead of | 
|  | 83 | unplugged. | 
| Alan Stern | 0458d5b | 2007-05-04 11:52:20 -0400 | [diff] [blame] | 84 |  | 
|  | 85 | If no device is now attached to the port, or if the descriptors are | 
|  | 86 | different from what the kernel remembers, then the treatment is what | 
|  | 87 | you would expect.  The kernel destroys the old device structure and | 
|  | 88 | behaves as though the old device had been unplugged and a new device | 
|  | 89 | plugged in, just as it would without the CONFIG_USB_PERSIST option. | 
|  | 90 |  | 
|  | 91 | The end result is that the USB device remains available and usable. | 
|  | 92 | Filesystem mounts and memory mappings are unaffected, and the world is | 
|  | 93 | now a good and happy place. | 
|  | 94 |  | 
| Alan Stern | b41a60e | 2007-05-30 15:39:33 -0400 | [diff] [blame] | 95 | Note that even when CONFIG_USB_PERSIST is set, the "persist" feature | 
|  | 96 | will be applied only to those devices for which it is enabled.  You | 
|  | 97 | can enable the feature by doing (as root): | 
|  | 98 |  | 
|  | 99 | echo 1 >/sys/bus/usb/devices/.../power/persist | 
|  | 100 |  | 
|  | 101 | where the "..." should be filled in the with the device's ID.  Disable | 
|  | 102 | the feature by writing 0 instead of 1.  For hubs the feature is | 
|  | 103 | automatically and permanently enabled, so you only have to worry about | 
|  | 104 | setting it for devices where it really matters. | 
|  | 105 |  | 
| Alan Stern | 0458d5b | 2007-05-04 11:52:20 -0400 | [diff] [blame] | 106 |  | 
|  | 107 | Is this the best solution? | 
|  | 108 |  | 
|  | 109 | Perhaps not.  Arguably, keeping track of mounted filesystems and | 
|  | 110 | memory mappings across device disconnects should be handled by a | 
|  | 111 | centralized Logical Volume Manager.  Such a solution would allow you | 
|  | 112 | to plug in a USB flash device, create a persistent volume associated | 
|  | 113 | with it, unplug the flash device, plug it back in later, and still | 
|  | 114 | have the same persistent volume associated with the device.  As such | 
|  | 115 | it would be more far-reaching than CONFIG_USB_PERSIST. | 
|  | 116 |  | 
|  | 117 | On the other hand, writing a persistent volume manager would be a big | 
|  | 118 | job and using it would require significant input from the user.  This | 
|  | 119 | solution is much quicker and easier -- and it exists now, a giant | 
|  | 120 | point in its favor! | 
|  | 121 |  | 
|  | 122 | Furthermore, the USB_PERSIST option applies to _all_ USB devices, not | 
|  | 123 | just mass-storage devices.  It might turn out to be equally useful for | 
|  | 124 | other device types, such as network interfaces. | 
|  | 125 |  | 
|  | 126 |  | 
|  | 127 | WARNING: Using CONFIG_USB_PERSIST can be dangerous!! | 
|  | 128 |  | 
|  | 129 | When recovering an interrupted power session the kernel does its best | 
|  | 130 | to make sure the USB device hasn't been changed; that is, the same | 
|  | 131 | device is still plugged into the port as before.  But the checks | 
|  | 132 | aren't guaranteed to be 100% accurate. | 
|  | 133 |  | 
|  | 134 | If you replace one USB device with another of the same type (same | 
|  | 135 | manufacturer, same IDs, and so on) there's an excellent chance the | 
|  | 136 | kernel won't detect the change.  Serial numbers and other strings are | 
|  | 137 | not compared.  In many cases it wouldn't help if they were, because | 
|  | 138 | manufacturers frequently omit serial numbers entirely in their | 
|  | 139 | devices. | 
|  | 140 |  | 
|  | 141 | Furthermore it's quite possible to leave a USB device exactly the same | 
|  | 142 | while changing its media.  If you replace the flash memory card in a | 
|  | 143 | USB card reader while the system is asleep, the kernel will have no | 
|  | 144 | way to know you did it.  The kernel will assume that nothing has | 
|  | 145 | happened and will continue to use the partition tables, inodes, and | 
|  | 146 | memory mappings for the old card. | 
|  | 147 |  | 
|  | 148 | If the kernel gets fooled in this way, it's almost certain to cause | 
|  | 149 | data corruption and to crash your system.  You'll have no one to blame | 
|  | 150 | but yourself. | 
|  | 151 |  | 
|  | 152 | YOU HAVE BEEN WARNED!  USE AT YOUR OWN RISK! | 
|  | 153 |  | 
|  | 154 | That having been said, most of the time there shouldn't be any trouble | 
|  | 155 | at all.  The "persist" feature can be extremely useful.  Make the most | 
|  | 156 | of it. |