aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2006-11-09 14:44:33 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2006-12-01 17:25:52 -0500
commit40f122f343797d02390c5a157372cac0c5b50bb7 (patch)
tree87f7b3f5b6fc347466668a4b9d8b67d32f5bb014 /drivers/usb
parent8c03356a559ced6fa78931f498193f776d67e445 (diff)
USB: Add autosuspend support to the hub driver
This patch (as742b) adds autosuspend/autoresume support to the USB hub driver. The largest aspect of the change is that we no longer need a special flag for root hubs that want to be resumed. Now every hub is autoresumed whenever khubd needs to access it. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/core/hub.c45
1 files changed, 26 insertions, 19 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index f6e692180587..55812a5ac661 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -65,7 +65,6 @@ struct usb_hub {
65 unsigned limited_power:1; 65 unsigned limited_power:1;
66 unsigned quiescing:1; 66 unsigned quiescing:1;
67 unsigned activating:1; 67 unsigned activating:1;
68 unsigned resume_root_hub:1;
69 68
70 unsigned has_indicators:1; 69 unsigned has_indicators:1;
71 u8 indicator[USB_MAXCHILDREN]; 70 u8 indicator[USB_MAXCHILDREN];
@@ -328,6 +327,9 @@ static void kick_khubd(struct usb_hub *hub)
328{ 327{
329 unsigned long flags; 328 unsigned long flags;
330 329
330 /* Suppress autosuspend until khubd runs */
331 to_usb_interface(hub->intfdev)->pm_usage_cnt = 1;
332
331 spin_lock_irqsave(&hub_event_lock, flags); 333 spin_lock_irqsave(&hub_event_lock, flags);
332 if (list_empty(&hub->event_list)) { 334 if (list_empty(&hub->event_list)) {
333 list_add_tail(&hub->event_list, &hub_event_list); 335 list_add_tail(&hub->event_list, &hub_event_list);
@@ -509,7 +511,6 @@ static void hub_quiesce(struct usb_hub *hub)
509 /* (nonblocking) khubd and related activity won't re-trigger */ 511 /* (nonblocking) khubd and related activity won't re-trigger */
510 hub->quiescing = 1; 512 hub->quiescing = 1;
511 hub->activating = 0; 513 hub->activating = 0;
512 hub->resume_root_hub = 0;
513 514
514 /* (blocking) stop khubd and related activity */ 515 /* (blocking) stop khubd and related activity */
515 usb_kill_urb(hub->urb); 516 usb_kill_urb(hub->urb);
@@ -525,7 +526,7 @@ static void hub_activate(struct usb_hub *hub)
525 526
526 hub->quiescing = 0; 527 hub->quiescing = 0;
527 hub->activating = 1; 528 hub->activating = 1;
528 hub->resume_root_hub = 0; 529
529 status = usb_submit_urb(hub->urb, GFP_NOIO); 530 status = usb_submit_urb(hub->urb, GFP_NOIO);
530 if (status < 0) 531 if (status < 0)
531 dev_err(hub->intfdev, "activate --> %d\n", status); 532 dev_err(hub->intfdev, "activate --> %d\n", status);
@@ -940,6 +941,7 @@ descriptor_error:
940 INIT_WORK(&hub->leds, led_work, hub); 941 INIT_WORK(&hub->leds, led_work, hub);
941 942
942 usb_set_intfdata (intf, hub); 943 usb_set_intfdata (intf, hub);
944 intf->needs_remote_wakeup = 1;
943 945
944 if (hdev->speed == USB_SPEED_HIGH) 946 if (hdev->speed == USB_SPEED_HIGH)
945 highspeed_hubs++; 947 highspeed_hubs++;
@@ -1938,6 +1940,8 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
1938 } 1940 }
1939 } 1941 }
1940 1942
1943 dev_dbg(&intf->dev, "%s\n", __FUNCTION__);
1944
1941 /* "global suspend" of the downstream HC-to-USB interface */ 1945 /* "global suspend" of the downstream HC-to-USB interface */
1942 if (!hdev->parent) { 1946 if (!hdev->parent) {
1943 struct usb_bus *bus = hdev->bus; 1947 struct usb_bus *bus = hdev->bus;
@@ -1960,10 +1964,12 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
1960 1964
1961static int hub_resume(struct usb_interface *intf) 1965static int hub_resume(struct usb_interface *intf)
1962{ 1966{
1963 struct usb_device *hdev = interface_to_usbdev(intf);
1964 struct usb_hub *hub = usb_get_intfdata (intf); 1967 struct usb_hub *hub = usb_get_intfdata (intf);
1968 struct usb_device *hdev = hub->hdev;
1965 int status; 1969 int status;
1966 1970
1971 dev_dbg(&intf->dev, "%s\n", __FUNCTION__);
1972
1967 /* "global resume" of the downstream HC-to-USB interface */ 1973 /* "global resume" of the downstream HC-to-USB interface */
1968 if (!hdev->parent) { 1974 if (!hdev->parent) {
1969 struct usb_bus *bus = hdev->bus; 1975 struct usb_bus *bus = hdev->bus;
@@ -2002,7 +2008,6 @@ void usb_resume_root_hub(struct usb_device *hdev)
2002{ 2008{
2003 struct usb_hub *hub = hdev_to_hub(hdev); 2009 struct usb_hub *hub = hdev_to_hub(hdev);
2004 2010
2005 hub->resume_root_hub = 1;
2006 kick_khubd(hub); 2011 kick_khubd(hub);
2007} 2012}
2008 2013
@@ -2639,16 +2644,13 @@ static void hub_events(void)
2639 intf = to_usb_interface(hub->intfdev); 2644 intf = to_usb_interface(hub->intfdev);
2640 hub_dev = &intf->dev; 2645 hub_dev = &intf->dev;
2641 2646
2642 i = hub->resume_root_hub; 2647 dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x\n",
2643
2644 dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x%s\n",
2645 hdev->state, hub->descriptor 2648 hdev->state, hub->descriptor
2646 ? hub->descriptor->bNbrPorts 2649 ? hub->descriptor->bNbrPorts
2647 : 0, 2650 : 0,
2648 /* NOTE: expects max 15 ports... */ 2651 /* NOTE: expects max 15 ports... */
2649 (u16) hub->change_bits[0], 2652 (u16) hub->change_bits[0],
2650 (u16) hub->event_bits[0], 2653 (u16) hub->event_bits[0]);
2651 i ? ", resume root" : "");
2652 2654
2653 usb_get_intf(intf); 2655 usb_get_intf(intf);
2654 spin_unlock_irq(&hub_event_lock); 2656 spin_unlock_irq(&hub_event_lock);
@@ -2669,16 +2671,16 @@ static void hub_events(void)
2669 goto loop; 2671 goto loop;
2670 } 2672 }
2671 2673
2672 /* Is this is a root hub wanting to reactivate the downstream 2674 /* Autoresume */
2673 * ports? If so, be sure the interface resumes even if its 2675 ret = usb_autopm_get_interface(intf);
2674 * stub "device" node was never suspended. 2676 if (ret) {
2675 */ 2677 dev_dbg(hub_dev, "Can't autoresume: %d\n", ret);
2676 if (i) 2678 goto loop;
2677 usb_autoresume_device(hdev, 0); 2679 }
2678 2680
2679 /* If this is an inactive or suspended hub, do nothing */ 2681 /* If this is an inactive hub, do nothing */
2680 if (hub->quiescing) 2682 if (hub->quiescing)
2681 goto loop; 2683 goto loop_autopm;
2682 2684
2683 if (hub->error) { 2685 if (hub->error) {
2684 dev_dbg (hub_dev, "resetting for error %d\n", 2686 dev_dbg (hub_dev, "resetting for error %d\n",
@@ -2688,7 +2690,7 @@ static void hub_events(void)
2688 if (ret) { 2690 if (ret) {
2689 dev_dbg (hub_dev, 2691 dev_dbg (hub_dev,
2690 "error resetting hub: %d\n", ret); 2692 "error resetting hub: %d\n", ret);
2691 goto loop; 2693 goto loop_autopm;
2692 } 2694 }
2693 2695
2694 hub->nerrors = 0; 2696 hub->nerrors = 0;
@@ -2816,6 +2818,10 @@ static void hub_events(void)
2816 if (!hdev->parent && !hub->busy_bits[0]) 2818 if (!hdev->parent && !hub->busy_bits[0])
2817 usb_enable_root_hub_irq(hdev->bus); 2819 usb_enable_root_hub_irq(hdev->bus);
2818 2820
2821loop_autopm:
2822 /* Allow autosuspend if we're not going to run again */
2823 if (list_empty(&hub->event_list))
2824 usb_autopm_enable(intf);
2819loop: 2825loop:
2820 usb_unlock_device(hdev); 2826 usb_unlock_device(hdev);
2821 usb_put_intf(intf); 2827 usb_put_intf(intf);
@@ -2857,6 +2863,7 @@ static struct usb_driver hub_driver = {
2857 .post_reset = hub_post_reset, 2863 .post_reset = hub_post_reset,
2858 .ioctl = hub_ioctl, 2864 .ioctl = hub_ioctl,
2859 .id_table = hub_id_table, 2865 .id_table = hub_id_table,
2866 .supports_autosuspend = 1,
2860}; 2867};
2861 2868
2862int usb_hub_init(void) 2869int usb_hub_init(void)