summaryrefslogtreecommitdiff
path: root/drivers/usb/core/hub.c
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2007-05-30 15:39:33 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2007-07-12 16:34:30 -0700
commitb41a60eca833d76593d4dac8a59f5c38714194ee (patch)
treea7c5cf721d9978503c3c8c88183747cf954b8733 /drivers/usb/core/hub.c
parent54515fe528d8c6f9bfaf7d0b9fffb908deecad78 (diff)
USB: add power/persist device attribute
This patch (as920) adds an extra level of protection to the USB-Persist facility. Now it will apply by default only to hubs; for all other devices the user must enable it explicitly by setting the power/persist device attribute. The disconnect_all_children() routine in hub.c has been removed and its code placed inline. This is the way it was originally as part of hub_pre_reset(); the revised usage in hub_reset_resume() is sufficiently different that the code can no longer be shared. Likewise, mark_children_for_reset() is now inline as part of hub_reset_resume(). The end result looks much cleaner than before. The sysfs interface is updated to add the new attribute file, and there are corresponding documentation updates. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/core/hub.c')
-rw-r--r--drivers/usb/core/hub.c78
1 files changed, 29 insertions, 49 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index c4cdb69a6e9e..50e79010401c 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -596,27 +596,18 @@ static void hub_port_logical_disconnect(struct usb_hub *hub, int port1)
kick_khubd(hub);
}
-static void disconnect_all_children(struct usb_hub *hub, int logical)
-{
- struct usb_device *hdev = hub->hdev;
- int port1;
-
- for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
- if (hdev->children[port1-1]) {
- if (logical)
- hub_port_logical_disconnect(hub, port1);
- else
- usb_disconnect(&hdev->children[port1-1]);
- }
- }
-}
-
/* caller has locked the hub device */
static int hub_pre_reset(struct usb_interface *intf)
{
struct usb_hub *hub = usb_get_intfdata(intf);
+ struct usb_device *hdev = hub->hdev;
+ int i;
- disconnect_all_children(hub, 0);
+ /* Disconnect all the children */
+ for (i = 0; i < hdev->maxchild; ++i) {
+ if (hdev->children[i])
+ usb_disconnect(&hdev->children[i]);
+ }
hub_quiesce(hub);
return 0;
}
@@ -1872,50 +1863,39 @@ static int hub_resume(struct usb_interface *intf)
return 0;
}
-#ifdef CONFIG_USB_PERSIST
-
-/* For "persistent-device" resets we must mark the child devices for reset
- * and turn off a possible connect-change status (so khubd won't disconnect
- * them later).
- */
-static void mark_children_for_reset_resume(struct usb_hub *hub)
+static int hub_reset_resume(struct usb_interface *intf)
{
+ struct usb_hub *hub = usb_get_intfdata(intf);
struct usb_device *hdev = hub->hdev;
int port1;
+ hub_power_on(hub);
+
for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
struct usb_device *child = hdev->children[port1-1];
if (child) {
- child->reset_resume = 1;
- clear_port_feature(hdev, port1,
- USB_PORT_FEAT_C_CONNECTION);
+
+ /* For "USB_PERSIST"-enabled children we must
+ * mark the child device for reset-resume and
+ * turn off the connect-change status to prevent
+ * khubd from disconnecting it later.
+ */
+ if (USB_PERSIST && child->persist_enabled) {
+ child->reset_resume = 1;
+ clear_port_feature(hdev, port1,
+ USB_PORT_FEAT_C_CONNECTION);
+
+ /* Otherwise we must disconnect the child,
+ * but as we may not lock the child device here
+ * we have to do a "logical" disconnect.
+ */
+ } else {
+ hub_port_logical_disconnect(hub, port1);
+ }
}
}
-}
-
-#else
-
-static inline void mark_children_for_reset_resume(struct usb_hub *hub)
-{ }
-
-#endif /* CONFIG_USB_PERSIST */
-
-static int hub_reset_resume(struct usb_interface *intf)
-{
- struct usb_hub *hub = usb_get_intfdata(intf);
- hub_power_on(hub);
- if (USB_PERSIST)
- mark_children_for_reset_resume(hub);
- else {
- /* Reset-resume doesn't call pre_reset, so we have to
- * disconnect the children here. But we may not lock
- * the child devices, so we have to do a "logical"
- * disconnect.
- */
- disconnect_all_children(hub, 1);
- }
hub_activate(hub);
return 0;
}