diff options
author | Petr Mladek <pmladek@suse.cz> | 2014-09-19 11:32:20 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-09-24 01:31:12 -0400 |
commit | eb6e29248714d767d5338b8b82d286293e8a041a (patch) | |
tree | 338b633a4ff70da536a56b42fbf63e7164e4d257 /drivers/usb | |
parent | 5d14f323834eeb0cd428bcec4a9cd8d8839467fb (diff) |
usb: hub: rename hub_events() to hub_event() and handle only one event there
We would like to convert khubd kthread to a workqueue. As a result hub_events()
will handle only one event per call.
In fact, we could do this already now because there is another cycle in
hub_thread(). It calls hub_events() until hub_event_list is empty.
This patch renames the function to hub_event(), removes the while cycle, and
renames the goto targets from loop* to out*.
When touching the code, it fixes also formatting of dev_err() and dev_dbg()
calls to make checkpatch.pl happy :-)
Signed-off-by: Petr Mladek <pmladek@suse.cz>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/core/hub.c | 236 |
1 files changed, 111 insertions, 125 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 6a9f11fbc2eb..b75749c3029a 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -4996,8 +4996,7 @@ static void port_event(struct usb_hub *hub, int port1) | |||
4996 | hub_port_connect_change(hub, port1, portstatus, portchange); | 4996 | hub_port_connect_change(hub, port1, portstatus, portchange); |
4997 | } | 4997 | } |
4998 | 4998 | ||
4999 | 4999 | static void hub_event(void) | |
5000 | static void hub_events(void) | ||
5001 | { | 5000 | { |
5002 | struct list_head *tmp; | 5001 | struct list_head *tmp; |
5003 | struct usb_device *hdev; | 5002 | struct usb_device *hdev; |
@@ -5008,144 +5007,131 @@ static void hub_events(void) | |||
5008 | u16 hubchange; | 5007 | u16 hubchange; |
5009 | int i, ret; | 5008 | int i, ret; |
5010 | 5009 | ||
5011 | /* | 5010 | /* Grab the first entry at the beginning of the list */ |
5012 | * We restart the list every time to avoid a deadlock with | 5011 | spin_lock_irq(&hub_event_lock); |
5013 | * deleting hubs downstream from this one. This should be | 5012 | if (list_empty(&hub_event_list)) { |
5014 | * safe since we delete the hub from the event list. | 5013 | spin_unlock_irq(&hub_event_lock); |
5015 | * Not the most efficient, but avoids deadlocks. | 5014 | return; |
5016 | */ | 5015 | } |
5017 | while (1) { | ||
5018 | 5016 | ||
5019 | /* Grab the first entry at the beginning of the list */ | 5017 | tmp = hub_event_list.next; |
5020 | spin_lock_irq(&hub_event_lock); | 5018 | list_del_init(tmp); |
5021 | if (list_empty(&hub_event_list)) { | ||
5022 | spin_unlock_irq(&hub_event_lock); | ||
5023 | break; | ||
5024 | } | ||
5025 | 5019 | ||
5026 | tmp = hub_event_list.next; | 5020 | hub = list_entry(tmp, struct usb_hub, event_list); |
5027 | list_del_init(tmp); | 5021 | kref_get(&hub->kref); |
5022 | spin_unlock_irq(&hub_event_lock); | ||
5028 | 5023 | ||
5029 | hub = list_entry(tmp, struct usb_hub, event_list); | 5024 | hdev = hub->hdev; |
5030 | kref_get(&hub->kref); | 5025 | hub_dev = hub->intfdev; |
5031 | spin_unlock_irq(&hub_event_lock); | 5026 | intf = to_usb_interface(hub_dev); |
5027 | dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x\n", | ||
5028 | hdev->state, hdev->maxchild, | ||
5029 | /* NOTE: expects max 15 ports... */ | ||
5030 | (u16) hub->change_bits[0], | ||
5031 | (u16) hub->event_bits[0]); | ||
5032 | |||
5033 | /* Lock the device, then check to see if we were | ||
5034 | * disconnected while waiting for the lock to succeed. */ | ||
5035 | usb_lock_device(hdev); | ||
5036 | if (unlikely(hub->disconnected)) | ||
5037 | goto out_disconnected; | ||
5038 | |||
5039 | /* If the hub has died, clean up after it */ | ||
5040 | if (hdev->state == USB_STATE_NOTATTACHED) { | ||
5041 | hub->error = -ENODEV; | ||
5042 | hub_quiesce(hub, HUB_DISCONNECT); | ||
5043 | goto out; | ||
5044 | } | ||
5045 | |||
5046 | /* Autoresume */ | ||
5047 | ret = usb_autopm_get_interface(intf); | ||
5048 | if (ret) { | ||
5049 | dev_dbg(hub_dev, "Can't autoresume: %d\n", ret); | ||
5050 | goto out; | ||
5051 | } | ||
5032 | 5052 | ||
5033 | hdev = hub->hdev; | 5053 | /* If this is an inactive hub, do nothing */ |
5034 | hub_dev = hub->intfdev; | 5054 | if (hub->quiescing) |
5035 | intf = to_usb_interface(hub_dev); | 5055 | goto out_autopm; |
5036 | dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x\n", | 5056 | |
5037 | hdev->state, hdev->maxchild, | 5057 | if (hub->error) { |
5038 | /* NOTE: expects max 15 ports... */ | 5058 | dev_dbg(hub_dev, "resetting for error %d\n", hub->error); |
5039 | (u16) hub->change_bits[0], | ||
5040 | (u16) hub->event_bits[0]); | ||
5041 | |||
5042 | /* Lock the device, then check to see if we were | ||
5043 | * disconnected while waiting for the lock to succeed. */ | ||
5044 | usb_lock_device(hdev); | ||
5045 | if (unlikely(hub->disconnected)) | ||
5046 | goto loop_disconnected; | ||
5047 | |||
5048 | /* If the hub has died, clean up after it */ | ||
5049 | if (hdev->state == USB_STATE_NOTATTACHED) { | ||
5050 | hub->error = -ENODEV; | ||
5051 | hub_quiesce(hub, HUB_DISCONNECT); | ||
5052 | goto loop; | ||
5053 | } | ||
5054 | 5059 | ||
5055 | /* Autoresume */ | 5060 | ret = usb_reset_device(hdev); |
5056 | ret = usb_autopm_get_interface(intf); | ||
5057 | if (ret) { | 5061 | if (ret) { |
5058 | dev_dbg(hub_dev, "Can't autoresume: %d\n", ret); | 5062 | dev_dbg(hub_dev, "error resetting hub: %d\n", ret); |
5059 | goto loop; | 5063 | goto out_autopm; |
5060 | } | 5064 | } |
5061 | 5065 | ||
5062 | /* If this is an inactive hub, do nothing */ | 5066 | hub->nerrors = 0; |
5063 | if (hub->quiescing) | 5067 | hub->error = 0; |
5064 | goto loop_autopm; | 5068 | } |
5065 | 5069 | ||
5066 | if (hub->error) { | 5070 | /* deal with port status changes */ |
5067 | dev_dbg (hub_dev, "resetting for error %d\n", | 5071 | for (i = 1; i <= hdev->maxchild; i++) { |
5068 | hub->error); | 5072 | struct usb_port *port_dev = hub->ports[i - 1]; |
5069 | 5073 | ||
5070 | ret = usb_reset_device(hdev); | 5074 | if (test_bit(i, hub->event_bits) |
5071 | if (ret) { | 5075 | || test_bit(i, hub->change_bits) |
5072 | dev_dbg (hub_dev, | 5076 | || test_bit(i, hub->wakeup_bits)) { |
5073 | "error resetting hub: %d\n", ret); | 5077 | /* |
5074 | goto loop_autopm; | 5078 | * The get_noresume and barrier ensure that if |
5075 | } | 5079 | * the port was in the process of resuming, we |
5076 | 5080 | * flush that work and keep the port active for | |
5077 | hub->nerrors = 0; | 5081 | * the duration of the port_event(). However, |
5078 | hub->error = 0; | 5082 | * if the port is runtime pm suspended |
5083 | * (powered-off), we leave it in that state, run | ||
5084 | * an abbreviated port_event(), and move on. | ||
5085 | */ | ||
5086 | pm_runtime_get_noresume(&port_dev->dev); | ||
5087 | pm_runtime_barrier(&port_dev->dev); | ||
5088 | usb_lock_port(port_dev); | ||
5089 | port_event(hub, i); | ||
5090 | usb_unlock_port(port_dev); | ||
5091 | pm_runtime_put_sync(&port_dev->dev); | ||
5079 | } | 5092 | } |
5093 | } | ||
5080 | 5094 | ||
5081 | /* deal with port status changes */ | 5095 | /* deal with hub status changes */ |
5082 | for (i = 1; i <= hdev->maxchild; i++) { | 5096 | if (test_and_clear_bit(0, hub->event_bits) == 0) |
5083 | struct usb_port *port_dev = hub->ports[i - 1]; | 5097 | ; /* do nothing */ |
5084 | 5098 | else if (hub_hub_status(hub, &hubstatus, &hubchange) < 0) | |
5085 | if (test_bit(i, hub->event_bits) | 5099 | dev_err(hub_dev, "get_hub_status failed\n"); |
5086 | || test_bit(i, hub->change_bits) | 5100 | else { |
5087 | || test_bit(i, hub->wakeup_bits)) { | 5101 | if (hubchange & HUB_CHANGE_LOCAL_POWER) { |
5088 | /* | 5102 | dev_dbg(hub_dev, "power change\n"); |
5089 | * The get_noresume and barrier ensure that if | 5103 | clear_hub_feature(hdev, C_HUB_LOCAL_POWER); |
5090 | * the port was in the process of resuming, we | 5104 | if (hubstatus & HUB_STATUS_LOCAL_POWER) |
5091 | * flush that work and keep the port active for | 5105 | /* FIXME: Is this always true? */ |
5092 | * the duration of the port_event(). However, | 5106 | hub->limited_power = 1; |
5093 | * if the port is runtime pm suspended | 5107 | else |
5094 | * (powered-off), we leave it in that state, run | 5108 | hub->limited_power = 0; |
5095 | * an abbreviated port_event(), and move on. | ||
5096 | */ | ||
5097 | pm_runtime_get_noresume(&port_dev->dev); | ||
5098 | pm_runtime_barrier(&port_dev->dev); | ||
5099 | usb_lock_port(port_dev); | ||
5100 | port_event(hub, i); | ||
5101 | usb_unlock_port(port_dev); | ||
5102 | pm_runtime_put_sync(&port_dev->dev); | ||
5103 | } | ||
5104 | } | 5109 | } |
5110 | if (hubchange & HUB_CHANGE_OVERCURRENT) { | ||
5111 | u16 status = 0; | ||
5112 | u16 unused; | ||
5105 | 5113 | ||
5106 | /* deal with hub status changes */ | 5114 | dev_dbg(hub_dev, "over-current change\n"); |
5107 | if (test_and_clear_bit(0, hub->event_bits) == 0) | 5115 | clear_hub_feature(hdev, C_HUB_OVER_CURRENT); |
5108 | ; /* do nothing */ | 5116 | msleep(500); /* Cool down */ |
5109 | else if (hub_hub_status(hub, &hubstatus, &hubchange) < 0) | 5117 | hub_power_on(hub, true); |
5110 | dev_err (hub_dev, "get_hub_status failed\n"); | 5118 | hub_hub_status(hub, &status, &unused); |
5111 | else { | 5119 | if (status & HUB_STATUS_OVERCURRENT) |
5112 | if (hubchange & HUB_CHANGE_LOCAL_POWER) { | 5120 | dev_err(hub_dev, "over-current condition\n"); |
5113 | dev_dbg (hub_dev, "power change\n"); | ||
5114 | clear_hub_feature(hdev, C_HUB_LOCAL_POWER); | ||
5115 | if (hubstatus & HUB_STATUS_LOCAL_POWER) | ||
5116 | /* FIXME: Is this always true? */ | ||
5117 | hub->limited_power = 1; | ||
5118 | else | ||
5119 | hub->limited_power = 0; | ||
5120 | } | ||
5121 | if (hubchange & HUB_CHANGE_OVERCURRENT) { | ||
5122 | u16 status = 0; | ||
5123 | u16 unused; | ||
5124 | |||
5125 | dev_dbg(hub_dev, "over-current change\n"); | ||
5126 | clear_hub_feature(hdev, C_HUB_OVER_CURRENT); | ||
5127 | msleep(500); /* Cool down */ | ||
5128 | hub_power_on(hub, true); | ||
5129 | hub_hub_status(hub, &status, &unused); | ||
5130 | if (status & HUB_STATUS_OVERCURRENT) | ||
5131 | dev_err(hub_dev, "over-current " | ||
5132 | "condition\n"); | ||
5133 | } | ||
5134 | } | 5121 | } |
5122 | } | ||
5135 | 5123 | ||
5136 | loop_autopm: | 5124 | out_autopm: |
5137 | /* Balance the usb_autopm_get_interface() above */ | 5125 | /* Balance the usb_autopm_get_interface() above */ |
5138 | usb_autopm_put_interface_no_suspend(intf); | 5126 | usb_autopm_put_interface_no_suspend(intf); |
5139 | loop: | 5127 | out: |
5140 | /* Balance the usb_autopm_get_interface_no_resume() in | 5128 | /* Balance the usb_autopm_get_interface_no_resume() in |
5141 | * kick_khubd() and allow autosuspend. | 5129 | * kick_khubd() and allow autosuspend. |
5142 | */ | 5130 | */ |
5143 | usb_autopm_put_interface(intf); | 5131 | usb_autopm_put_interface(intf); |
5144 | loop_disconnected: | 5132 | out_disconnected: |
5145 | usb_unlock_device(hdev); | 5133 | usb_unlock_device(hdev); |
5146 | kref_put(&hub->kref, hub_release); | 5134 | kref_put(&hub->kref, hub_release); |
5147 | |||
5148 | } /* end while (1) */ | ||
5149 | } | 5135 | } |
5150 | 5136 | ||
5151 | static int hub_thread(void *__unused) | 5137 | static int hub_thread(void *__unused) |
@@ -5158,7 +5144,7 @@ static int hub_thread(void *__unused) | |||
5158 | set_freezable(); | 5144 | set_freezable(); |
5159 | 5145 | ||
5160 | do { | 5146 | do { |
5161 | hub_events(); | 5147 | hub_event(); |
5162 | wait_event_freezable(khubd_wait, | 5148 | wait_event_freezable(khubd_wait, |
5163 | !list_empty(&hub_event_list) || | 5149 | !list_empty(&hub_event_list) || |
5164 | kthread_should_stop()); | 5150 | kthread_should_stop()); |