diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/core/Kconfig | 25 | ||||
-rw-r--r-- | drivers/usb/core/hub.c | 27 | ||||
-rw-r--r-- | drivers/usb/core/quirks.c | 12 | ||||
-rw-r--r-- | drivers/usb/core/sysfs.c | 22 | ||||
-rw-r--r-- | drivers/usb/host/ehci-hub.c | 11 |
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 | ||
105 | config 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 | |||
130 | config USB_OTG | 105 | config 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 | */ |
2121 | void usb_root_hub_lost_power(struct usb_device *rhdev) | 2114 | void 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) | |||
180 | static DEVICE_ATTR(urbnum, S_IRUGO, show_urbnum, NULL); | 180 | static 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 |
184 | static const char power_group[] = "power"; | ||
185 | #endif | ||
186 | 184 | ||
187 | #ifdef CONFIG_USB_PERSIST | 185 | static const char power_group[] = "power"; |
188 | 186 | ||
189 | static ssize_t | 187 | static ssize_t |
190 | show_persist(struct device *dev, struct device_attribute *attr, char *buf) | 188 | show_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 | ||
33 | static int ehci_hub_control( | 33 | static 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 | |||
109 | static inline void ehci_handover_companion_ports(struct ehci_hcd *ehci) | ||
110 | { } | ||
111 | |||
112 | #endif | ||
113 | |||
114 | #ifdef CONFIG_PM | ||
115 | |||
116 | static int ehci_bus_suspend (struct usb_hcd *hcd) | 107 | static 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); |