aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/core/Kconfig25
-rw-r--r--drivers/usb/core/hub.c27
-rw-r--r--drivers/usb/core/quirks.c12
-rw-r--r--drivers/usb/core/sysfs.c22
-rw-r--r--drivers/usb/host/ehci-hub.c11
5 files changed, 33 insertions, 64 deletions
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index a2b0aa48b8ea..c15621d64579 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -102,31 +102,6 @@ config USB_SUSPEND
102 102
103 If you are unsure about this, say N here. 103 If you are unsure about this, say N here.
104 104
105config USB_PERSIST
106 bool "USB device persistence during system suspend (DANGEROUS)"
107 depends on USB && PM && EXPERIMENTAL
108 default n
109 help
110
111 If you say Y here and enable the "power/persist" attribute
112 for a USB device, the device's data structures will remain
113 persistent across system suspend, even if the USB bus loses
114 power. (This includes hibernation, also known as swsusp or
115 suspend-to-disk.) The devices will reappear as if by magic
116 when the system wakes up, with no need to unmount USB
117 filesystems, rmmod host-controller drivers, or do anything
118 else.
119
120 WARNING: This option can be dangerous!
121
122 If a USB device is replaced by another of the same type while
123 the system is asleep, there's a good chance the kernel won't
124 detect the change. Likewise if the media in a USB storage
125 device is replaced. When this happens it's almost certain to
126 cause data corruption and maybe even crash your system.
127
128 If you are unsure, say N here.
129
130config USB_OTG 105config USB_OTG
131 bool 106 bool
132 depends on USB && EXPERIMENTAL 107 depends on USB && EXPERIMENTAL
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index df68e2562582..6dc589955d75 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -30,12 +30,6 @@
30#include "hcd.h" 30#include "hcd.h"
31#include "hub.h" 31#include "hub.h"
32 32
33#ifdef CONFIG_USB_PERSIST
34#define USB_PERSIST 1
35#else
36#define USB_PERSIST 0
37#endif
38
39/* if we are in debug mode, always announce new devices */ 33/* if we are in debug mode, always announce new devices */
40#ifdef DEBUG 34#ifdef DEBUG
41#ifndef CONFIG_USB_ANNOUNCE_NEW_DEVICES 35#ifndef CONFIG_USB_ANNOUNCE_NEW_DEVICES
@@ -695,7 +689,7 @@ static void hub_restart(struct usb_hub *hub, int type)
695 * turn off the various status changes to prevent 689 * turn off the various status changes to prevent
696 * khubd from disconnecting it later. 690 * khubd from disconnecting it later.
697 */ 691 */
698 if (USB_PERSIST && udev->persist_enabled && status == 0 && 692 if (udev->persist_enabled && status == 0 &&
699 !(portstatus & USB_PORT_STAT_ENABLE)) { 693 !(portstatus & USB_PORT_STAT_ENABLE)) {
700 if (portchange & USB_PORT_STAT_C_ENABLE) 694 if (portchange & USB_PORT_STAT_C_ENABLE)
701 clear_port_feature(hub->hdev, port1, 695 clear_port_feature(hub->hdev, port1,
@@ -1923,9 +1917,8 @@ static int finish_port_resume(struct usb_device *udev)
1923 * the host and the device is the same as it was when the device 1917 * the host and the device is the same as it was when the device
1924 * suspended. 1918 * suspended.
1925 * 1919 *
1926 * If CONFIG_USB_PERSIST and @udev->reset_resume are both set then this 1920 * If @udev->reset_resume is set then this routine won't check that the
1927 * routine won't check that the port is still enabled. Furthermore, 1921 * port is still enabled. Furthermore, finish_port_resume() above will
1928 * if @udev->reset_resume is set then finish_port_resume() above will
1929 * reset @udev. The end result is that a broken power session can be 1922 * reset @udev. The end result is that a broken power session can be
1930 * recovered and @udev will appear to persist across a loss of VBUS power. 1923 * recovered and @udev will appear to persist across a loss of VBUS power.
1931 * 1924 *
@@ -1937,8 +1930,8 @@ static int finish_port_resume(struct usb_device *udev)
1937 * to it will be lost. Using the USB_PERSIST facility, the device can be 1930 * to it will be lost. Using the USB_PERSIST facility, the device can be
1938 * made to appear as if it had not disconnected. 1931 * made to appear as if it had not disconnected.
1939 * 1932 *
1940 * This facility is inherently dangerous. Although usb_reset_device() 1933 * This facility can be dangerous. Although usb_reset_device() makes
1941 * makes every effort to insure that the same device is present after the 1934 * every effort to insure that the same device is present after the
1942 * reset as before, it cannot provide a 100% guarantee. Furthermore it's 1935 * reset as before, it cannot provide a 100% guarantee. Furthermore it's
1943 * quite possible for a device to remain unaltered but its media to be 1936 * quite possible for a device to remain unaltered but its media to be
1944 * changed. If the user replaces a flash memory card while the system is 1937 * changed. If the user replaces a flash memory card while the system is
@@ -1983,7 +1976,7 @@ int usb_port_resume(struct usb_device *udev)
1983 status = hub_port_status(hub, port1, &portstatus, &portchange); 1976 status = hub_port_status(hub, port1, &portstatus, &portchange);
1984 1977
1985 SuspendCleared: 1978 SuspendCleared:
1986 if (USB_PERSIST && udev->reset_resume) 1979 if (udev->reset_resume)
1987 want_flags = USB_PORT_STAT_POWER 1980 want_flags = USB_PORT_STAT_POWER
1988 | USB_PORT_STAT_CONNECTION; 1981 | USB_PORT_STAT_CONNECTION;
1989 else 1982 else
@@ -2113,10 +2106,10 @@ static int hub_reset_resume(struct usb_interface *intf)
2113 * 2106 *
2114 * The USB host controller driver calls this function when its root hub 2107 * The USB host controller driver calls this function when its root hub
2115 * is resumed and Vbus power has been interrupted or the controller 2108 * is resumed and Vbus power has been interrupted or the controller
2116 * has been reset. The routine marks @rhdev as having lost power. When 2109 * has been reset. The routine marks @rhdev as having lost power.
2117 * the hub driver is resumed it will take notice; if CONFIG_USB_PERSIST 2110 * When the hub driver is resumed it will take notice and carry out
2118 * is enabled then it will carry out power-session recovery, otherwise 2111 * power-session recovery for all the "USB-PERSIST"-enabled child devices;
2119 * it will disconnect all the child devices. 2112 * the others will be disconnected.
2120 */ 2113 */
2121void usb_root_hub_lost_power(struct usb_device *rhdev) 2114void usb_root_hub_lost_power(struct usb_device *rhdev)
2122{ 2115{
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index dfc5418ea10c..f384edf35b44 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -97,4 +97,16 @@ void usb_detect_quirks(struct usb_device *udev)
97 if (udev->descriptor.bDeviceClass != USB_CLASS_HUB) 97 if (udev->descriptor.bDeviceClass != USB_CLASS_HUB)
98 udev->autosuspend_disabled = 1; 98 udev->autosuspend_disabled = 1;
99#endif 99#endif
100
101#ifdef CONFIG_PM
102 /* Hubs are automatically enabled for USB-PERSIST */
103 if (udev->descriptor.bDeviceClass == USB_CLASS_HUB)
104 udev->persist_enabled = 1;
105#else
106 /* In the absense of PM, we can safely enable USB-PERSIST
107 * for all devices. It will affect things like hub resets
108 * and EMF-related port disables.
109 */
110 udev->persist_enabled = 1;
111#endif /* CONFIG_PM */
100} 112}
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index a37ccbd1e007..5b20a60de8ba 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -180,11 +180,9 @@ show_urbnum(struct device *dev, struct device_attribute *attr, char *buf)
180static DEVICE_ATTR(urbnum, S_IRUGO, show_urbnum, NULL); 180static DEVICE_ATTR(urbnum, S_IRUGO, show_urbnum, NULL);
181 181
182 182
183#if defined(CONFIG_USB_PERSIST) || defined(CONFIG_USB_SUSPEND) 183#ifdef CONFIG_PM
184static const char power_group[] = "power";
185#endif
186 184
187#ifdef CONFIG_USB_PERSIST 185static const char power_group[] = "power";
188 186
189static ssize_t 187static ssize_t
190show_persist(struct device *dev, struct device_attribute *attr, char *buf) 188show_persist(struct device *dev, struct device_attribute *attr, char *buf)
@@ -222,12 +220,13 @@ static int add_persist_attributes(struct device *dev)
222 if (is_usb_device(dev)) { 220 if (is_usb_device(dev)) {
223 struct usb_device *udev = to_usb_device(dev); 221 struct usb_device *udev = to_usb_device(dev);
224 222
225 /* Hubs are automatically enabled for USB_PERSIST */ 223 /* Hubs are automatically enabled for USB_PERSIST,
226 if (udev->descriptor.bDeviceClass == USB_CLASS_HUB) 224 * no point in creating the attribute file.
227 udev->persist_enabled = 1; 225 */
228 rc = sysfs_add_file_to_group(&dev->kobj, 226 if (udev->descriptor.bDeviceClass != USB_CLASS_HUB)
229 &dev_attr_persist.attr, 227 rc = sysfs_add_file_to_group(&dev->kobj,
230 power_group); 228 &dev_attr_persist.attr,
229 power_group);
231 } 230 }
232 return rc; 231 return rc;
233} 232}
@@ -238,13 +237,12 @@ static void remove_persist_attributes(struct device *dev)
238 &dev_attr_persist.attr, 237 &dev_attr_persist.attr,
239 power_group); 238 power_group);
240} 239}
241
242#else 240#else
243 241
244#define add_persist_attributes(dev) 0 242#define add_persist_attributes(dev) 0
245#define remove_persist_attributes(dev) do {} while (0) 243#define remove_persist_attributes(dev) do {} while (0)
246 244
247#endif /* CONFIG_USB_PERSIST */ 245#endif /* CONFIG_PM */
248 246
249#ifdef CONFIG_USB_SUSPEND 247#ifdef CONFIG_USB_SUSPEND
250 248
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 8d513a15d0cd..fea9e47192db 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -28,7 +28,7 @@
28 28
29/*-------------------------------------------------------------------------*/ 29/*-------------------------------------------------------------------------*/
30 30
31#ifdef CONFIG_USB_PERSIST 31#ifdef CONFIG_PM
32 32
33static int ehci_hub_control( 33static int ehci_hub_control(
34 struct usb_hcd *hcd, 34 struct usb_hcd *hcd,
@@ -104,15 +104,6 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci)
104 ehci->owned_ports = 0; 104 ehci->owned_ports = 0;
105} 105}
106 106
107#else /* CONFIG_USB_PERSIST */
108
109static inline void ehci_handover_companion_ports(struct ehci_hcd *ehci)
110{ }
111
112#endif
113
114#ifdef CONFIG_PM
115
116static int ehci_bus_suspend (struct usb_hcd *hcd) 107static int ehci_bus_suspend (struct usb_hcd *hcd)
117{ 108{
118 struct ehci_hcd *ehci = hcd_to_ehci (hcd); 109 struct ehci_hcd *ehci = hcd_to_ehci (hcd);