Commit feccc30d authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman

USB: remove CONFIG_USB_PERSIST setting

This patch (as1047) removes the USB_PERSIST Kconfig option, enabling
it permanently.  It also prevents the power/persist attribute from
being created for hub devices; there's no point in having it since
USB-PERSIST is always turned on for hubs.
Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 5e6effae
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
Alan Stern <stern@rowland.harvard.edu> Alan Stern <stern@rowland.harvard.edu>
September 2, 2006 (Updated May 29, 2007) September 2, 2006 (Updated February 25, 2008)
What is the problem? What is the problem?
...@@ -65,9 +65,10 @@ much better.) ...@@ -65,9 +65,10 @@ much better.)
What is the solution? What is the solution?
Setting CONFIG_USB_PERSIST will cause the kernel to work around these The kernel includes a feature called USB-persist. It tries to work
issues. It enables a mode in which the core USB device data around these issues by allowing the core USB device data structures to
structures are allowed to persist across a power-session disruption. persist across a power-session disruption.
It works like this. If the kernel sees that a USB host controller is It works like this. If the kernel sees that a USB host controller is
not in the expected state during resume (i.e., if the controller was not in the expected state during resume (i.e., if the controller was
reset or otherwise had lost power) then it applies a persistence check reset or otherwise had lost power) then it applies a persistence check
...@@ -80,28 +81,30 @@ re-enumeration shows that the device now attached to that port has the ...@@ -80,28 +81,30 @@ re-enumeration shows that the device now attached to that port has the
same descriptors as before, including the Vendor and Product IDs, then same descriptors as before, including the Vendor and Product IDs, then
the kernel continues to use the same device structure. In effect, the the kernel continues to use the same device structure. In effect, the
kernel treats the device as though it had merely been reset instead of kernel treats the device as though it had merely been reset instead of
unplugged. unplugged. The same thing happens if the host controller is in the
expected state but a USB device was unplugged and then replugged.
If no device is now attached to the port, or if the descriptors are If no device is now attached to the port, or if the descriptors are
different from what the kernel remembers, then the treatment is what different from what the kernel remembers, then the treatment is what
you would expect. The kernel destroys the old device structure and you would expect. The kernel destroys the old device structure and
behaves as though the old device had been unplugged and a new device behaves as though the old device had been unplugged and a new device
plugged in, just as it would without the CONFIG_USB_PERSIST option. plugged in.
The end result is that the USB device remains available and usable. The end result is that the USB device remains available and usable.
Filesystem mounts and memory mappings are unaffected, and the world is Filesystem mounts and memory mappings are unaffected, and the world is
now a good and happy place. now a good and happy place.
Note that even when CONFIG_USB_PERSIST is set, the "persist" feature Note that the "USB-persist" feature will be applied only to those
will be applied only to those devices for which it is enabled. You devices for which it is enabled. You can enable the feature by doing
can enable the feature by doing (as root): (as root):
echo 1 >/sys/bus/usb/devices/.../power/persist echo 1 >/sys/bus/usb/devices/.../power/persist
where the "..." should be filled in the with the device's ID. Disable where the "..." should be filled in the with the device's ID. Disable
the feature by writing 0 instead of 1. For hubs the feature is the feature by writing 0 instead of 1. For hubs the feature is
automatically and permanently enabled, so you only have to worry about automatically and permanently enabled and the power/persist file
setting it for devices where it really matters. doesn't even exist, so you only have to worry about setting it for
devices where it really matters.
Is this the best solution? Is this the best solution?
...@@ -112,19 +115,19 @@ centralized Logical Volume Manager. Such a solution would allow you ...@@ -112,19 +115,19 @@ centralized Logical Volume Manager. Such a solution would allow you
to plug in a USB flash device, create a persistent volume associated to plug in a USB flash device, create a persistent volume associated
with it, unplug the flash device, plug it back in later, and still with it, unplug the flash device, plug it back in later, and still
have the same persistent volume associated with the device. As such have the same persistent volume associated with the device. As such
it would be more far-reaching than CONFIG_USB_PERSIST. it would be more far-reaching than USB-persist.
On the other hand, writing a persistent volume manager would be a big On the other hand, writing a persistent volume manager would be a big
job and using it would require significant input from the user. This job and using it would require significant input from the user. This
solution is much quicker and easier -- and it exists now, a giant solution is much quicker and easier -- and it exists now, a giant
point in its favor! point in its favor!
Furthermore, the USB_PERSIST option applies to _all_ USB devices, not Furthermore, the USB-persist feature applies to _all_ USB devices, not
just mass-storage devices. It might turn out to be equally useful for just mass-storage devices. It might turn out to be equally useful for
other device types, such as network interfaces. other device types, such as network interfaces.
WARNING: Using CONFIG_USB_PERSIST can be dangerous!! WARNING: USB-persist can be dangerous!!
When recovering an interrupted power session the kernel does its best When recovering an interrupted power session the kernel does its best
to make sure the USB device hasn't been changed; that is, the same to make sure the USB device hasn't been changed; that is, the same
...@@ -152,5 +155,5 @@ but yourself. ...@@ -152,5 +155,5 @@ but yourself.
YOU HAVE BEEN WARNED! USE AT YOUR OWN RISK! YOU HAVE BEEN WARNED! USE AT YOUR OWN RISK!
That having been said, most of the time there shouldn't be any trouble That having been said, most of the time there shouldn't be any trouble
at all. The "persist" feature can be extremely useful. Make the most at all. The USB-persist feature can be extremely useful. Make the
of it. most of it.
...@@ -102,31 +102,6 @@ config USB_SUSPEND ...@@ -102,31 +102,6 @@ config USB_SUSPEND
If you are unsure about this, say N here. If you are unsure about this, say N here.
config USB_PERSIST
bool "USB device persistence during system suspend (DANGEROUS)"
depends on USB && PM && EXPERIMENTAL
default n
help
If you say Y here and enable the "power/persist" attribute
for a USB device, the device's data structures will remain
persistent across system suspend, even if the USB bus loses
power. (This includes hibernation, also known as swsusp or
suspend-to-disk.) The devices will reappear as if by magic
when the system wakes up, with no need to unmount USB
filesystems, rmmod host-controller drivers, or do anything
else.
WARNING: This option can be dangerous!
If a USB device is replaced by another of the same type while
the system is asleep, there's a good chance the kernel won't
detect the change. Likewise if the media in a USB storage
device is replaced. When this happens it's almost certain to
cause data corruption and maybe even crash your system.
If you are unsure, say N here.
config USB_OTG config USB_OTG
bool bool
depends on USB && EXPERIMENTAL depends on USB && EXPERIMENTAL
......
...@@ -30,12 +30,6 @@ ...@@ -30,12 +30,6 @@
#include "hcd.h" #include "hcd.h"
#include "hub.h" #include "hub.h"
#ifdef CONFIG_USB_PERSIST
#define USB_PERSIST 1
#else
#define USB_PERSIST 0
#endif
/* if we are in debug mode, always announce new devices */ /* if we are in debug mode, always announce new devices */
#ifdef DEBUG #ifdef DEBUG
#ifndef CONFIG_USB_ANNOUNCE_NEW_DEVICES #ifndef CONFIG_USB_ANNOUNCE_NEW_DEVICES
...@@ -695,7 +689,7 @@ static void hub_restart(struct usb_hub *hub, int type) ...@@ -695,7 +689,7 @@ static void hub_restart(struct usb_hub *hub, int type)
* turn off the various status changes to prevent * turn off the various status changes to prevent
* khubd from disconnecting it later. * khubd from disconnecting it later.
*/ */
if (USB_PERSIST && udev->persist_enabled && status == 0 && if (udev->persist_enabled && status == 0 &&
!(portstatus & USB_PORT_STAT_ENABLE)) { !(portstatus & USB_PORT_STAT_ENABLE)) {
if (portchange & USB_PORT_STAT_C_ENABLE) if (portchange & USB_PORT_STAT_C_ENABLE)
clear_port_feature(hub->hdev, port1, clear_port_feature(hub->hdev, port1,
...@@ -1923,9 +1917,8 @@ static int finish_port_resume(struct usb_device *udev) ...@@ -1923,9 +1917,8 @@ static int finish_port_resume(struct usb_device *udev)
* the host and the device is the same as it was when the device * the host and the device is the same as it was when the device
* suspended. * suspended.
* *
* If CONFIG_USB_PERSIST and @udev->reset_resume are both set then this * If @udev->reset_resume is set then this routine won't check that the
* routine won't check that the port is still enabled. Furthermore, * port is still enabled. Furthermore, finish_port_resume() above will
* if @udev->reset_resume is set then finish_port_resume() above will
* reset @udev. The end result is that a broken power session can be * reset @udev. The end result is that a broken power session can be
* recovered and @udev will appear to persist across a loss of VBUS power. * recovered and @udev will appear to persist across a loss of VBUS power.
* *
...@@ -1937,8 +1930,8 @@ static int finish_port_resume(struct usb_device *udev) ...@@ -1937,8 +1930,8 @@ static int finish_port_resume(struct usb_device *udev)
* to it will be lost. Using the USB_PERSIST facility, the device can be * to it will be lost. Using the USB_PERSIST facility, the device can be
* made to appear as if it had not disconnected. * made to appear as if it had not disconnected.
* *
* This facility is inherently dangerous. Although usb_reset_device() * This facility can be dangerous. Although usb_reset_device() makes
* makes every effort to insure that the same device is present after the * every effort to insure that the same device is present after the
* reset as before, it cannot provide a 100% guarantee. Furthermore it's * reset as before, it cannot provide a 100% guarantee. Furthermore it's
* quite possible for a device to remain unaltered but its media to be * quite possible for a device to remain unaltered but its media to be
* changed. If the user replaces a flash memory card while the system is * 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,7 +1976,7 @@ int usb_port_resume(struct usb_device *udev)
status = hub_port_status(hub, port1, &portstatus, &portchange); status = hub_port_status(hub, port1, &portstatus, &portchange);
SuspendCleared: SuspendCleared:
if (USB_PERSIST && udev->reset_resume) if (udev->reset_resume)
want_flags = USB_PORT_STAT_POWER want_flags = USB_PORT_STAT_POWER
| USB_PORT_STAT_CONNECTION; | USB_PORT_STAT_CONNECTION;
else else
...@@ -2113,10 +2106,10 @@ static int hub_reset_resume(struct usb_interface *intf) ...@@ -2113,10 +2106,10 @@ static int hub_reset_resume(struct usb_interface *intf)
* *
* The USB host controller driver calls this function when its root hub * The USB host controller driver calls this function when its root hub
* is resumed and Vbus power has been interrupted or the controller * is resumed and Vbus power has been interrupted or the controller
* has been reset. The routine marks @rhdev as having lost power. When * has been reset. The routine marks @rhdev as having lost power.
* the hub driver is resumed it will take notice; if CONFIG_USB_PERSIST * When the hub driver is resumed it will take notice and carry out
* is enabled then it will carry out power-session recovery, otherwise * power-session recovery for all the "USB-PERSIST"-enabled child devices;
* it will disconnect all the child devices. * the others will be disconnected.
*/ */
void usb_root_hub_lost_power(struct usb_device *rhdev) void usb_root_hub_lost_power(struct usb_device *rhdev)
{ {
......
...@@ -97,4 +97,16 @@ void usb_detect_quirks(struct usb_device *udev) ...@@ -97,4 +97,16 @@ void usb_detect_quirks(struct usb_device *udev)
if (udev->descriptor.bDeviceClass != USB_CLASS_HUB) if (udev->descriptor.bDeviceClass != USB_CLASS_HUB)
udev->autosuspend_disabled = 1; udev->autosuspend_disabled = 1;
#endif #endif
#ifdef CONFIG_PM
/* Hubs are automatically enabled for USB-PERSIST */
if (udev->descriptor.bDeviceClass == USB_CLASS_HUB)
udev->persist_enabled = 1;
#else
/* In the absense of PM, we can safely enable USB-PERSIST
* for all devices. It will affect things like hub resets
* and EMF-related port disables.
*/
udev->persist_enabled = 1;
#endif /* CONFIG_PM */
} }
...@@ -180,11 +180,9 @@ show_urbnum(struct device *dev, struct device_attribute *attr, char *buf) ...@@ -180,11 +180,9 @@ show_urbnum(struct device *dev, struct device_attribute *attr, char *buf)
static DEVICE_ATTR(urbnum, S_IRUGO, show_urbnum, NULL); static DEVICE_ATTR(urbnum, S_IRUGO, show_urbnum, NULL);
#if defined(CONFIG_USB_PERSIST) || defined(CONFIG_USB_SUSPEND) #ifdef CONFIG_PM
static const char power_group[] = "power";
#endif
#ifdef CONFIG_USB_PERSIST static const char power_group[] = "power";
static ssize_t static ssize_t
show_persist(struct device *dev, struct device_attribute *attr, char *buf) show_persist(struct device *dev, struct device_attribute *attr, char *buf)
...@@ -222,12 +220,13 @@ static int add_persist_attributes(struct device *dev) ...@@ -222,12 +220,13 @@ static int add_persist_attributes(struct device *dev)
if (is_usb_device(dev)) { if (is_usb_device(dev)) {
struct usb_device *udev = to_usb_device(dev); struct usb_device *udev = to_usb_device(dev);
/* Hubs are automatically enabled for USB_PERSIST */ /* Hubs are automatically enabled for USB_PERSIST,
if (udev->descriptor.bDeviceClass == USB_CLASS_HUB) * no point in creating the attribute file.
udev->persist_enabled = 1; */
rc = sysfs_add_file_to_group(&dev->kobj, if (udev->descriptor.bDeviceClass != USB_CLASS_HUB)
&dev_attr_persist.attr, rc = sysfs_add_file_to_group(&dev->kobj,
power_group); &dev_attr_persist.attr,
power_group);
} }
return rc; return rc;
} }
...@@ -238,13 +237,12 @@ static void remove_persist_attributes(struct device *dev) ...@@ -238,13 +237,12 @@ static void remove_persist_attributes(struct device *dev)
&dev_attr_persist.attr, &dev_attr_persist.attr,
power_group); power_group);
} }
#else #else
#define add_persist_attributes(dev) 0 #define add_persist_attributes(dev) 0
#define remove_persist_attributes(dev) do {} while (0) #define remove_persist_attributes(dev) do {} while (0)
#endif /* CONFIG_USB_PERSIST */ #endif /* CONFIG_PM */
#ifdef CONFIG_USB_SUSPEND #ifdef CONFIG_USB_SUSPEND
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
#ifdef CONFIG_USB_PERSIST #ifdef CONFIG_PM
static int ehci_hub_control( static int ehci_hub_control(
struct usb_hcd *hcd, struct usb_hcd *hcd,
...@@ -104,15 +104,6 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci) ...@@ -104,15 +104,6 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci)
ehci->owned_ports = 0; ehci->owned_ports = 0;
} }
#else /* CONFIG_USB_PERSIST */
static inline void ehci_handover_companion_ports(struct ehci_hcd *ehci)
{ }
#endif
#ifdef CONFIG_PM
static int ehci_bus_suspend (struct usb_hcd *hcd) static int ehci_bus_suspend (struct usb_hcd *hcd)
{ {
struct ehci_hcd *ehci = hcd_to_ehci (hcd); struct ehci_hcd *ehci = hcd_to_ehci (hcd);
......
...@@ -387,6 +387,7 @@ struct usb_device { ...@@ -387,6 +387,7 @@ struct usb_device {
unsigned can_submit:1; /* URBs may be submitted */ unsigned can_submit:1; /* URBs may be submitted */
unsigned discon_suspended:1; /* Disconnected while suspended */ unsigned discon_suspended:1; /* Disconnected while suspended */
unsigned persist_enabled:1; /* USB_PERSIST enabled for this dev */
unsigned have_langid:1; /* whether string_langid is valid */ unsigned have_langid:1; /* whether string_langid is valid */
unsigned authorized:1; /* Policy has said we can use it */ unsigned authorized:1; /* Policy has said we can use it */
unsigned wusb:1; /* Device is Wireless USB */ unsigned wusb:1; /* Device is Wireless USB */
...@@ -433,7 +434,6 @@ struct usb_device { ...@@ -433,7 +434,6 @@ struct usb_device {
unsigned auto_pm:1; /* autosuspend/resume in progress */ unsigned auto_pm:1; /* autosuspend/resume in progress */
unsigned do_remote_wakeup:1; /* remote wakeup should be enabled */ unsigned do_remote_wakeup:1; /* remote wakeup should be enabled */
unsigned reset_resume:1; /* needs reset instead of resume */ unsigned reset_resume:1; /* needs reset instead of resume */
unsigned persist_enabled:1; /* USB_PERSIST enabled for this dev */
unsigned autosuspend_disabled:1; /* autosuspend and autoresume */ unsigned autosuspend_disabled:1; /* autosuspend and autoresume */
unsigned autoresume_disabled:1; /* disabled by the user */ unsigned autoresume_disabled:1; /* disabled by the user */
unsigned skip_sys_resume:1; /* skip the next system resume */ unsigned skip_sys_resume:1; /* skip the next system resume */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment