diff options
author | Jeff Garzik <jeff@garzik.org> | 2006-09-30 23:45:41 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-09-30 23:45:41 -0400 |
commit | 1c7da74c4aab595a994beb5fe728ebf0d0b41f59 (patch) | |
tree | 64128abdf9550ebb51d8f3ee6732d7350b9c62f2 /drivers/usb | |
parent | aebb1153ac54ddbbd3d3f0481a193f4bf0ead53b (diff) | |
parent | 1bdfd554be94def718323659173517c5d4a69d25 (diff) |
Merge branch 'master' into upstream
Diffstat (limited to 'drivers/usb')
33 files changed, 440 insertions, 247 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index b10463244413..113e484c763e 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
@@ -24,6 +24,7 @@ | |||
24 | 24 | ||
25 | #include <linux/device.h> | 25 | #include <linux/device.h> |
26 | #include <linux/usb.h> | 26 | #include <linux/usb.h> |
27 | #include <linux/workqueue.h> | ||
27 | #include "hcd.h" | 28 | #include "hcd.h" |
28 | #include "usb.h" | 29 | #include "usb.h" |
29 | 30 | ||
@@ -302,11 +303,11 @@ int usb_driver_claim_interface(struct usb_driver *driver, | |||
302 | dev->driver = &driver->drvwrap.driver; | 303 | dev->driver = &driver->drvwrap.driver; |
303 | usb_set_intfdata(iface, priv); | 304 | usb_set_intfdata(iface, priv); |
304 | 305 | ||
305 | mutex_lock_nested(&udev->pm_mutex, udev->level); | 306 | usb_pm_lock(udev); |
306 | iface->condition = USB_INTERFACE_BOUND; | 307 | iface->condition = USB_INTERFACE_BOUND; |
307 | mark_active(iface); | 308 | mark_active(iface); |
308 | iface->pm_usage_cnt = !(driver->supports_autosuspend); | 309 | iface->pm_usage_cnt = !(driver->supports_autosuspend); |
309 | mutex_unlock(&udev->pm_mutex); | 310 | usb_pm_unlock(udev); |
310 | 311 | ||
311 | /* if interface was already added, bind now; else let | 312 | /* if interface was already added, bind now; else let |
312 | * the future device_add() bind it, bypassing probe() | 313 | * the future device_add() bind it, bypassing probe() |
@@ -355,11 +356,11 @@ void usb_driver_release_interface(struct usb_driver *driver, | |||
355 | dev->driver = NULL; | 356 | dev->driver = NULL; |
356 | usb_set_intfdata(iface, NULL); | 357 | usb_set_intfdata(iface, NULL); |
357 | 358 | ||
358 | mutex_lock_nested(&udev->pm_mutex, udev->level); | 359 | usb_pm_lock(udev); |
359 | iface->condition = USB_INTERFACE_UNBOUND; | 360 | iface->condition = USB_INTERFACE_UNBOUND; |
360 | mark_quiesced(iface); | 361 | mark_quiesced(iface); |
361 | iface->needs_remote_wakeup = 0; | 362 | iface->needs_remote_wakeup = 0; |
362 | mutex_unlock(&udev->pm_mutex); | 363 | usb_pm_unlock(udev); |
363 | } | 364 | } |
364 | EXPORT_SYMBOL(usb_driver_release_interface); | 365 | EXPORT_SYMBOL(usb_driver_release_interface); |
365 | 366 | ||
@@ -788,7 +789,7 @@ EXPORT_SYMBOL_GPL_FUTURE(usb_deregister); | |||
788 | 789 | ||
789 | #ifdef CONFIG_PM | 790 | #ifdef CONFIG_PM |
790 | 791 | ||
791 | /* Caller has locked udev->pm_mutex */ | 792 | /* Caller has locked udev's pm_mutex */ |
792 | static int suspend_device(struct usb_device *udev, pm_message_t msg) | 793 | static int suspend_device(struct usb_device *udev, pm_message_t msg) |
793 | { | 794 | { |
794 | struct usb_device_driver *udriver; | 795 | struct usb_device_driver *udriver; |
@@ -815,7 +816,7 @@ done: | |||
815 | return status; | 816 | return status; |
816 | } | 817 | } |
817 | 818 | ||
818 | /* Caller has locked udev->pm_mutex */ | 819 | /* Caller has locked udev's pm_mutex */ |
819 | static int resume_device(struct usb_device *udev) | 820 | static int resume_device(struct usb_device *udev) |
820 | { | 821 | { |
821 | struct usb_device_driver *udriver; | 822 | struct usb_device_driver *udriver; |
@@ -841,7 +842,7 @@ done: | |||
841 | return status; | 842 | return status; |
842 | } | 843 | } |
843 | 844 | ||
844 | /* Caller has locked intf's usb_device's pm_mutex */ | 845 | /* Caller has locked intf's usb_device's pm mutex */ |
845 | static int suspend_interface(struct usb_interface *intf, pm_message_t msg) | 846 | static int suspend_interface(struct usb_interface *intf, pm_message_t msg) |
846 | { | 847 | { |
847 | struct usb_driver *driver; | 848 | struct usb_driver *driver; |
@@ -1063,7 +1064,7 @@ int usb_resume_both(struct usb_device *udev) | |||
1063 | /* Propagate the resume up the tree, if necessary */ | 1064 | /* Propagate the resume up the tree, if necessary */ |
1064 | if (udev->state == USB_STATE_SUSPENDED) { | 1065 | if (udev->state == USB_STATE_SUSPENDED) { |
1065 | if (parent) { | 1066 | if (parent) { |
1066 | mutex_lock_nested(&parent->pm_mutex, parent->level); | 1067 | usb_pm_lock(parent); |
1067 | parent->auto_pm = 1; | 1068 | parent->auto_pm = 1; |
1068 | status = usb_resume_both(parent); | 1069 | status = usb_resume_both(parent); |
1069 | } else { | 1070 | } else { |
@@ -1078,7 +1079,7 @@ int usb_resume_both(struct usb_device *udev) | |||
1078 | if (status == 0) | 1079 | if (status == 0) |
1079 | status = resume_device(udev); | 1080 | status = resume_device(udev); |
1080 | if (parent) | 1081 | if (parent) |
1081 | mutex_unlock(&parent->pm_mutex); | 1082 | usb_pm_unlock(parent); |
1082 | } else { | 1083 | } else { |
1083 | 1084 | ||
1084 | /* Needed only for setting udev->dev.power.power_state.event | 1085 | /* Needed only for setting udev->dev.power.power_state.event |
@@ -1103,8 +1104,8 @@ int usb_resume_both(struct usb_device *udev) | |||
1103 | 1104 | ||
1104 | /** | 1105 | /** |
1105 | * usb_autosuspend_device - delayed autosuspend of a USB device and its interfaces | 1106 | * usb_autosuspend_device - delayed autosuspend of a USB device and its interfaces |
1106 | * @udev - the usb_device to autosuspend | 1107 | * @udev: the usb_device to autosuspend |
1107 | * @dec_usage_cnt - flag to decrement @udev's PM-usage counter | 1108 | * @dec_usage_cnt: flag to decrement @udev's PM-usage counter |
1108 | * | 1109 | * |
1109 | * This routine should be called when a core subsystem is finished using | 1110 | * This routine should be called when a core subsystem is finished using |
1110 | * @udev and wants to allow it to autosuspend. Examples would be when | 1111 | * @udev and wants to allow it to autosuspend. Examples would be when |
@@ -1128,20 +1129,20 @@ int usb_resume_both(struct usb_device *udev) | |||
1128 | */ | 1129 | */ |
1129 | void usb_autosuspend_device(struct usb_device *udev, int dec_usage_cnt) | 1130 | void usb_autosuspend_device(struct usb_device *udev, int dec_usage_cnt) |
1130 | { | 1131 | { |
1131 | mutex_lock_nested(&udev->pm_mutex, udev->level); | 1132 | usb_pm_lock(udev); |
1132 | udev->pm_usage_cnt -= dec_usage_cnt; | 1133 | udev->pm_usage_cnt -= dec_usage_cnt; |
1133 | if (udev->pm_usage_cnt <= 0) | 1134 | if (udev->pm_usage_cnt <= 0) |
1134 | schedule_delayed_work(&udev->autosuspend, | 1135 | queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend, |
1135 | USB_AUTOSUSPEND_DELAY); | 1136 | USB_AUTOSUSPEND_DELAY); |
1136 | mutex_unlock(&udev->pm_mutex); | 1137 | usb_pm_unlock(udev); |
1137 | // dev_dbg(&udev->dev, "%s: cnt %d\n", | 1138 | // dev_dbg(&udev->dev, "%s: cnt %d\n", |
1138 | // __FUNCTION__, udev->pm_usage_cnt); | 1139 | // __FUNCTION__, udev->pm_usage_cnt); |
1139 | } | 1140 | } |
1140 | 1141 | ||
1141 | /** | 1142 | /** |
1142 | * usb_autoresume_device - immediately autoresume a USB device and its interfaces | 1143 | * usb_autoresume_device - immediately autoresume a USB device and its interfaces |
1143 | * @udev - the usb_device to autoresume | 1144 | * @udev: the usb_device to autoresume |
1144 | * @inc_usage_cnt - flag to increment @udev's PM-usage counter | 1145 | * @inc_usage_cnt: flag to increment @udev's PM-usage counter |
1145 | * | 1146 | * |
1146 | * This routine should be called when a core subsystem wants to use @udev | 1147 | * This routine should be called when a core subsystem wants to use @udev |
1147 | * and needs to guarantee that it is not suspended. In addition, the | 1148 | * and needs to guarantee that it is not suspended. In addition, the |
@@ -1167,13 +1168,13 @@ int usb_autoresume_device(struct usb_device *udev, int inc_usage_cnt) | |||
1167 | { | 1168 | { |
1168 | int status; | 1169 | int status; |
1169 | 1170 | ||
1170 | mutex_lock_nested(&udev->pm_mutex, udev->level); | 1171 | usb_pm_lock(udev); |
1171 | udev->pm_usage_cnt += inc_usage_cnt; | 1172 | udev->pm_usage_cnt += inc_usage_cnt; |
1172 | udev->auto_pm = 1; | 1173 | udev->auto_pm = 1; |
1173 | status = usb_resume_both(udev); | 1174 | status = usb_resume_both(udev); |
1174 | if (status != 0) | 1175 | if (status != 0) |
1175 | udev->pm_usage_cnt -= inc_usage_cnt; | 1176 | udev->pm_usage_cnt -= inc_usage_cnt; |
1176 | mutex_unlock(&udev->pm_mutex); | 1177 | usb_pm_unlock(udev); |
1177 | // dev_dbg(&udev->dev, "%s: status %d cnt %d\n", | 1178 | // dev_dbg(&udev->dev, "%s: status %d cnt %d\n", |
1178 | // __FUNCTION__, status, udev->pm_usage_cnt); | 1179 | // __FUNCTION__, status, udev->pm_usage_cnt); |
1179 | return status; | 1180 | return status; |
@@ -1181,7 +1182,7 @@ int usb_autoresume_device(struct usb_device *udev, int inc_usage_cnt) | |||
1181 | 1182 | ||
1182 | /** | 1183 | /** |
1183 | * usb_autopm_put_interface - decrement a USB interface's PM-usage counter | 1184 | * usb_autopm_put_interface - decrement a USB interface's PM-usage counter |
1184 | * @intf - the usb_interface whose counter should be decremented | 1185 | * @intf: the usb_interface whose counter should be decremented |
1185 | * | 1186 | * |
1186 | * This routine should be called by an interface driver when it is | 1187 | * This routine should be called by an interface driver when it is |
1187 | * finished using @intf and wants to allow it to autosuspend. A typical | 1188 | * finished using @intf and wants to allow it to autosuspend. A typical |
@@ -1214,13 +1215,13 @@ void usb_autopm_put_interface(struct usb_interface *intf) | |||
1214 | { | 1215 | { |
1215 | struct usb_device *udev = interface_to_usbdev(intf); | 1216 | struct usb_device *udev = interface_to_usbdev(intf); |
1216 | 1217 | ||
1217 | mutex_lock_nested(&udev->pm_mutex, udev->level); | 1218 | usb_pm_lock(udev); |
1218 | if (intf->condition != USB_INTERFACE_UNBOUND) { | 1219 | if (intf->condition != USB_INTERFACE_UNBOUND && |
1219 | if (--intf->pm_usage_cnt <= 0) | 1220 | --intf->pm_usage_cnt <= 0) { |
1220 | schedule_delayed_work(&udev->autosuspend, | 1221 | queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend, |
1221 | USB_AUTOSUSPEND_DELAY); | 1222 | USB_AUTOSUSPEND_DELAY); |
1222 | } | 1223 | } |
1223 | mutex_unlock(&udev->pm_mutex); | 1224 | usb_pm_unlock(udev); |
1224 | // dev_dbg(&intf->dev, "%s: cnt %d\n", | 1225 | // dev_dbg(&intf->dev, "%s: cnt %d\n", |
1225 | // __FUNCTION__, intf->pm_usage_cnt); | 1226 | // __FUNCTION__, intf->pm_usage_cnt); |
1226 | } | 1227 | } |
@@ -1228,7 +1229,7 @@ EXPORT_SYMBOL_GPL(usb_autopm_put_interface); | |||
1228 | 1229 | ||
1229 | /** | 1230 | /** |
1230 | * usb_autopm_get_interface - increment a USB interface's PM-usage counter | 1231 | * usb_autopm_get_interface - increment a USB interface's PM-usage counter |
1231 | * @intf - the usb_interface whose counter should be incremented | 1232 | * @intf: the usb_interface whose counter should be incremented |
1232 | * | 1233 | * |
1233 | * This routine should be called by an interface driver when it wants to | 1234 | * This routine should be called by an interface driver when it wants to |
1234 | * use @intf and needs to guarantee that it is not suspended. In addition, | 1235 | * use @intf and needs to guarantee that it is not suspended. In addition, |
@@ -1262,7 +1263,7 @@ int usb_autopm_get_interface(struct usb_interface *intf) | |||
1262 | struct usb_device *udev = interface_to_usbdev(intf); | 1263 | struct usb_device *udev = interface_to_usbdev(intf); |
1263 | int status; | 1264 | int status; |
1264 | 1265 | ||
1265 | mutex_lock_nested(&udev->pm_mutex, udev->level); | 1266 | usb_pm_lock(udev); |
1266 | if (intf->condition == USB_INTERFACE_UNBOUND) | 1267 | if (intf->condition == USB_INTERFACE_UNBOUND) |
1267 | status = -ENODEV; | 1268 | status = -ENODEV; |
1268 | else { | 1269 | else { |
@@ -1272,7 +1273,7 @@ int usb_autopm_get_interface(struct usb_interface *intf) | |||
1272 | if (status != 0) | 1273 | if (status != 0) |
1273 | --intf->pm_usage_cnt; | 1274 | --intf->pm_usage_cnt; |
1274 | } | 1275 | } |
1275 | mutex_unlock(&udev->pm_mutex); | 1276 | usb_pm_unlock(udev); |
1276 | // dev_dbg(&intf->dev, "%s: status %d cnt %d\n", | 1277 | // dev_dbg(&intf->dev, "%s: status %d cnt %d\n", |
1277 | // __FUNCTION__, status, intf->pm_usage_cnt); | 1278 | // __FUNCTION__, status, intf->pm_usage_cnt); |
1278 | return status; | 1279 | return status; |
@@ -1288,10 +1289,10 @@ static int usb_suspend(struct device *dev, pm_message_t message) | |||
1288 | if (is_usb_device(dev)) { | 1289 | if (is_usb_device(dev)) { |
1289 | struct usb_device *udev = to_usb_device(dev); | 1290 | struct usb_device *udev = to_usb_device(dev); |
1290 | 1291 | ||
1291 | mutex_lock_nested(&udev->pm_mutex, udev->level); | 1292 | usb_pm_lock(udev); |
1292 | udev->auto_pm = 0; | 1293 | udev->auto_pm = 0; |
1293 | status = usb_suspend_both(udev, message); | 1294 | status = usb_suspend_both(udev, message); |
1294 | mutex_unlock(&udev->pm_mutex); | 1295 | usb_pm_unlock(udev); |
1295 | } else | 1296 | } else |
1296 | status = 0; | 1297 | status = 0; |
1297 | return status; | 1298 | return status; |
@@ -1304,10 +1305,10 @@ static int usb_resume(struct device *dev) | |||
1304 | if (is_usb_device(dev)) { | 1305 | if (is_usb_device(dev)) { |
1305 | struct usb_device *udev = to_usb_device(dev); | 1306 | struct usb_device *udev = to_usb_device(dev); |
1306 | 1307 | ||
1307 | mutex_lock_nested(&udev->pm_mutex, udev->level); | 1308 | usb_pm_lock(udev); |
1308 | udev->auto_pm = 0; | 1309 | udev->auto_pm = 0; |
1309 | status = usb_resume_both(udev); | 1310 | status = usb_resume_both(udev); |
1310 | mutex_unlock(&udev->pm_mutex); | 1311 | usb_pm_unlock(udev); |
1311 | 1312 | ||
1312 | /* Rebind drivers that had no suspend method? */ | 1313 | /* Rebind drivers that had no suspend method? */ |
1313 | } else | 1314 | } else |
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index e86f62957085..37f9f5e7425d 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c | |||
@@ -345,7 +345,8 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) | |||
345 | struct usb_ctrlrequest *cmd; | 345 | struct usb_ctrlrequest *cmd; |
346 | u16 typeReq, wValue, wIndex, wLength; | 346 | u16 typeReq, wValue, wIndex, wLength; |
347 | u8 *ubuf = urb->transfer_buffer; | 347 | u8 *ubuf = urb->transfer_buffer; |
348 | u8 tbuf [sizeof (struct usb_hub_descriptor)]; | 348 | u8 tbuf [sizeof (struct usb_hub_descriptor)] |
349 | __attribute__((aligned(4))); | ||
349 | const u8 *bufp = tbuf; | 350 | const u8 *bufp = tbuf; |
350 | int len = 0; | 351 | int len = 0; |
351 | int patch_wakeup = 0; | 352 | int patch_wakeup = 0; |
@@ -835,8 +836,7 @@ void usb_enable_root_hub_irq (struct usb_bus *bus) | |||
835 | struct usb_hcd *hcd; | 836 | struct usb_hcd *hcd; |
836 | 837 | ||
837 | hcd = container_of (bus, struct usb_hcd, self); | 838 | hcd = container_of (bus, struct usb_hcd, self); |
838 | if (hcd->driver->hub_irq_enable && !hcd->poll_rh && | 839 | if (hcd->driver->hub_irq_enable && hcd->state != HC_STATE_HALT) |
839 | hcd->state != HC_STATE_HALT) | ||
840 | hcd->driver->hub_irq_enable (hcd); | 840 | hcd->driver->hub_irq_enable (hcd); |
841 | } | 841 | } |
842 | 842 | ||
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 2a8cb3c2b19c..7676690a0386 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -1779,7 +1779,7 @@ static int remote_wakeup(struct usb_device *udev) | |||
1779 | * to the parent hub! */ | 1779 | * to the parent hub! */ |
1780 | 1780 | ||
1781 | usb_lock_device(udev); | 1781 | usb_lock_device(udev); |
1782 | mutex_lock_nested(&udev->pm_mutex, udev->level); | 1782 | usb_pm_lock(udev); |
1783 | if (udev->state == USB_STATE_SUSPENDED) { | 1783 | if (udev->state == USB_STATE_SUSPENDED) { |
1784 | dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-"); | 1784 | dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-"); |
1785 | /* TRSMRCY = 10 msec */ | 1785 | /* TRSMRCY = 10 msec */ |
@@ -1788,7 +1788,7 @@ static int remote_wakeup(struct usb_device *udev) | |||
1788 | if (status == 0) | 1788 | if (status == 0) |
1789 | udev->dev.power.power_state.event = PM_EVENT_ON; | 1789 | udev->dev.power.power_state.event = PM_EVENT_ON; |
1790 | } | 1790 | } |
1791 | mutex_unlock(&udev->pm_mutex); | 1791 | usb_pm_unlock(udev); |
1792 | 1792 | ||
1793 | if (status == 0) | 1793 | if (status == 0) |
1794 | usb_autoresume_device(udev, 0); | 1794 | usb_autoresume_device(udev, 0); |
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 60ef4ef0101a..e4df9edf1bc0 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/smp_lock.h> | 33 | #include <linux/smp_lock.h> |
34 | #include <linux/usb.h> | 34 | #include <linux/usb.h> |
35 | #include <linux/mutex.h> | 35 | #include <linux/mutex.h> |
36 | #include <linux/workqueue.h> | ||
36 | 37 | ||
37 | #include <asm/io.h> | 38 | #include <asm/io.h> |
38 | #include <asm/scatterlist.h> | 39 | #include <asm/scatterlist.h> |
@@ -47,6 +48,8 @@ const char *usbcore_name = "usbcore"; | |||
47 | 48 | ||
48 | static int nousb; /* Disable USB when built into kernel image */ | 49 | static int nousb; /* Disable USB when built into kernel image */ |
49 | 50 | ||
51 | struct workqueue_struct *ksuspend_usb_wq; /* For autosuspend */ | ||
52 | |||
50 | 53 | ||
51 | /** | 54 | /** |
52 | * usb_ifnum_to_if - get the interface object with a given interface number | 55 | * usb_ifnum_to_if - get the interface object with a given interface number |
@@ -170,9 +173,9 @@ static void usb_release_dev(struct device *dev) | |||
170 | 173 | ||
171 | udev = to_usb_device(dev); | 174 | udev = to_usb_device(dev); |
172 | 175 | ||
173 | #ifdef CONFIG_PM | 176 | #ifdef CONFIG_USB_SUSPEND |
174 | cancel_delayed_work(&udev->autosuspend); | 177 | cancel_delayed_work(&udev->autosuspend); |
175 | flush_scheduled_work(); | 178 | flush_workqueue(ksuspend_usb_wq); |
176 | #endif | 179 | #endif |
177 | usb_destroy_configuration(udev); | 180 | usb_destroy_configuration(udev); |
178 | usb_put_hcd(bus_to_hcd(udev->bus)); | 181 | usb_put_hcd(bus_to_hcd(udev->bus)); |
@@ -184,17 +187,44 @@ static void usb_release_dev(struct device *dev) | |||
184 | 187 | ||
185 | #ifdef CONFIG_PM | 188 | #ifdef CONFIG_PM |
186 | 189 | ||
190 | static int ksuspend_usb_init(void) | ||
191 | { | ||
192 | ksuspend_usb_wq = create_singlethread_workqueue("ksuspend_usbd"); | ||
193 | if (!ksuspend_usb_wq) | ||
194 | return -ENOMEM; | ||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | static void ksuspend_usb_cleanup(void) | ||
199 | { | ||
200 | destroy_workqueue(ksuspend_usb_wq); | ||
201 | } | ||
202 | |||
203 | #else | ||
204 | |||
205 | #define ksuspend_usb_init() 0 | ||
206 | #define ksuspend_usb_cleanup() do {} while (0) | ||
207 | |||
208 | #endif | ||
209 | |||
210 | #ifdef CONFIG_USB_SUSPEND | ||
211 | |||
187 | /* usb_autosuspend_work - callback routine to autosuspend a USB device */ | 212 | /* usb_autosuspend_work - callback routine to autosuspend a USB device */ |
188 | static void usb_autosuspend_work(void *_udev) | 213 | static void usb_autosuspend_work(void *_udev) |
189 | { | 214 | { |
190 | struct usb_device *udev = _udev; | 215 | struct usb_device *udev = _udev; |
191 | 216 | ||
192 | mutex_lock_nested(&udev->pm_mutex, udev->level); | 217 | usb_pm_lock(udev); |
193 | udev->auto_pm = 1; | 218 | udev->auto_pm = 1; |
194 | usb_suspend_both(udev, PMSG_SUSPEND); | 219 | usb_suspend_both(udev, PMSG_SUSPEND); |
195 | mutex_unlock(&udev->pm_mutex); | 220 | usb_pm_unlock(udev); |
196 | } | 221 | } |
197 | 222 | ||
223 | #else | ||
224 | |||
225 | static void usb_autosuspend_work(void *_udev) | ||
226 | {} | ||
227 | |||
198 | #endif | 228 | #endif |
199 | 229 | ||
200 | /** | 230 | /** |
@@ -976,9 +1006,12 @@ static int __init usb_init(void) | |||
976 | return 0; | 1006 | return 0; |
977 | } | 1007 | } |
978 | 1008 | ||
1009 | retval = ksuspend_usb_init(); | ||
1010 | if (retval) | ||
1011 | goto out; | ||
979 | retval = bus_register(&usb_bus_type); | 1012 | retval = bus_register(&usb_bus_type); |
980 | if (retval) | 1013 | if (retval) |
981 | goto out; | 1014 | goto bus_register_failed; |
982 | retval = usb_host_init(); | 1015 | retval = usb_host_init(); |
983 | if (retval) | 1016 | if (retval) |
984 | goto host_init_failed; | 1017 | goto host_init_failed; |
@@ -1014,6 +1047,8 @@ major_init_failed: | |||
1014 | usb_host_cleanup(); | 1047 | usb_host_cleanup(); |
1015 | host_init_failed: | 1048 | host_init_failed: |
1016 | bus_unregister(&usb_bus_type); | 1049 | bus_unregister(&usb_bus_type); |
1050 | bus_register_failed: | ||
1051 | ksuspend_usb_cleanup(); | ||
1017 | out: | 1052 | out: |
1018 | return retval; | 1053 | return retval; |
1019 | } | 1054 | } |
@@ -1035,6 +1070,7 @@ static void __exit usb_exit(void) | |||
1035 | usb_hub_cleanup(); | 1070 | usb_hub_cleanup(); |
1036 | usb_host_cleanup(); | 1071 | usb_host_cleanup(); |
1037 | bus_unregister(&usb_bus_type); | 1072 | bus_unregister(&usb_bus_type); |
1073 | ksuspend_usb_cleanup(); | ||
1038 | } | 1074 | } |
1039 | 1075 | ||
1040 | subsys_initcall(usb_init); | 1076 | subsys_initcall(usb_init); |
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 0c09ecced6e1..f69df137ec0e 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h | |||
@@ -36,6 +36,16 @@ extern int usb_resume_both(struct usb_device *udev); | |||
36 | extern int usb_port_suspend(struct usb_device *dev); | 36 | extern int usb_port_suspend(struct usb_device *dev); |
37 | extern int usb_port_resume(struct usb_device *dev); | 37 | extern int usb_port_resume(struct usb_device *dev); |
38 | 38 | ||
39 | static inline void usb_pm_lock(struct usb_device *udev) | ||
40 | { | ||
41 | mutex_lock_nested(&udev->pm_mutex, udev->level); | ||
42 | } | ||
43 | |||
44 | static inline void usb_pm_unlock(struct usb_device *udev) | ||
45 | { | ||
46 | mutex_unlock(&udev->pm_mutex); | ||
47 | } | ||
48 | |||
39 | #else | 49 | #else |
40 | 50 | ||
41 | #define usb_suspend_both(udev, msg) 0 | 51 | #define usb_suspend_both(udev, msg) 0 |
@@ -45,6 +55,8 @@ static inline int usb_resume_both(struct usb_device *udev) | |||
45 | } | 55 | } |
46 | #define usb_port_suspend(dev) 0 | 56 | #define usb_port_suspend(dev) 0 |
47 | #define usb_port_resume(dev) 0 | 57 | #define usb_port_resume(dev) 0 |
58 | static inline void usb_pm_lock(struct usb_device *udev) {} | ||
59 | static inline void usb_pm_unlock(struct usb_device *udev) {} | ||
48 | 60 | ||
49 | #endif | 61 | #endif |
50 | 62 | ||
@@ -58,10 +70,15 @@ extern int usb_autoresume_device(struct usb_device *udev, int inc_busy_cnt); | |||
58 | #else | 70 | #else |
59 | 71 | ||
60 | #define usb_autosuspend_device(udev, dec_busy_cnt) do {} while (0) | 72 | #define usb_autosuspend_device(udev, dec_busy_cnt) do {} while (0) |
61 | #define usb_autoresume_device(udev, inc_busy_cnt) 0 | 73 | static inline int usb_autoresume_device(struct usb_device *udev, |
74 | int inc_busy_cnt) | ||
75 | { | ||
76 | return 0; | ||
77 | } | ||
62 | 78 | ||
63 | #endif | 79 | #endif |
64 | 80 | ||
81 | extern struct workqueue_struct *ksuspend_usb_wq; | ||
65 | extern struct bus_type usb_bus_type; | 82 | extern struct bus_type usb_bus_type; |
66 | extern struct usb_device_driver usb_generic_driver; | 83 | extern struct usb_device_driver usb_generic_driver; |
67 | 84 | ||
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index d00958a01cfb..77beba485a84 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c | |||
@@ -1658,7 +1658,7 @@ static int __devinit at91udc_probe(struct platform_device *pdev) | |||
1658 | return -ENODEV; | 1658 | return -ENODEV; |
1659 | } | 1659 | } |
1660 | 1660 | ||
1661 | if (!request_mem_region(AT91_BASE_UDP, SZ_16K, driver_name)) { | 1661 | if (!request_mem_region(AT91RM9200_BASE_UDP, SZ_16K, driver_name)) { |
1662 | DBG("someone's using UDC memory\n"); | 1662 | DBG("someone's using UDC memory\n"); |
1663 | return -EBUSY; | 1663 | return -EBUSY; |
1664 | } | 1664 | } |
@@ -1720,7 +1720,7 @@ static int __devinit at91udc_probe(struct platform_device *pdev) | |||
1720 | fail1: | 1720 | fail1: |
1721 | device_unregister(&udc->gadget.dev); | 1721 | device_unregister(&udc->gadget.dev); |
1722 | fail0: | 1722 | fail0: |
1723 | release_mem_region(AT91_BASE_UDP, SZ_16K); | 1723 | release_mem_region(AT91RM9200_BASE_UDP, SZ_16K); |
1724 | DBG("%s probe failed, %d\n", driver_name, retval); | 1724 | DBG("%s probe failed, %d\n", driver_name, retval); |
1725 | return retval; | 1725 | return retval; |
1726 | } | 1726 | } |
@@ -1742,7 +1742,7 @@ static int __devexit at91udc_remove(struct platform_device *pdev) | |||
1742 | free_irq(udc->board.vbus_pin, udc); | 1742 | free_irq(udc->board.vbus_pin, udc); |
1743 | free_irq(udc->udp_irq, udc); | 1743 | free_irq(udc->udp_irq, udc); |
1744 | device_unregister(&udc->gadget.dev); | 1744 | device_unregister(&udc->gadget.dev); |
1745 | release_mem_region(AT91_BASE_UDP, SZ_16K); | 1745 | release_mem_region(AT91RM9200_BASE_UDP, SZ_16K); |
1746 | 1746 | ||
1747 | clk_put(udc->iclk); | 1747 | clk_put(udc->iclk); |
1748 | clk_put(udc->fclk); | 1748 | clk_put(udc->fclk); |
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index fdab97a27c08..4d2946e540cf 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c | |||
@@ -816,15 +816,14 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver) | |||
816 | dum->gadget.dev.driver = &driver->driver; | 816 | dum->gadget.dev.driver = &driver->driver; |
817 | dev_dbg (udc_dev(dum), "binding gadget driver '%s'\n", | 817 | dev_dbg (udc_dev(dum), "binding gadget driver '%s'\n", |
818 | driver->driver.name); | 818 | driver->driver.name); |
819 | if ((retval = driver->bind (&dum->gadget)) != 0) { | 819 | if ((retval = driver->bind (&dum->gadget)) != 0) |
820 | dum->driver = NULL; | 820 | goto err_bind_gadget; |
821 | dum->gadget.dev.driver = NULL; | ||
822 | return retval; | ||
823 | } | ||
824 | 821 | ||
825 | driver->driver.bus = dum->gadget.dev.parent->bus; | 822 | driver->driver.bus = dum->gadget.dev.parent->bus; |
826 | driver_register (&driver->driver); | 823 | if ((retval = driver_register (&driver->driver)) != 0) |
827 | device_bind_driver (&dum->gadget.dev); | 824 | goto err_register; |
825 | if ((retval = device_bind_driver (&dum->gadget.dev)) != 0) | ||
826 | goto err_bind_driver; | ||
828 | 827 | ||
829 | /* khubd will enumerate this in a while */ | 828 | /* khubd will enumerate this in a while */ |
830 | spin_lock_irq (&dum->lock); | 829 | spin_lock_irq (&dum->lock); |
@@ -834,6 +833,19 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver) | |||
834 | 833 | ||
835 | usb_hcd_poll_rh_status (dummy_to_hcd (dum)); | 834 | usb_hcd_poll_rh_status (dummy_to_hcd (dum)); |
836 | return 0; | 835 | return 0; |
836 | |||
837 | err_bind_driver: | ||
838 | driver_unregister (&driver->driver); | ||
839 | err_register: | ||
840 | driver->unbind (&dum->gadget); | ||
841 | spin_lock_irq (&dum->lock); | ||
842 | dum->pullup = 0; | ||
843 | set_link_state (dum); | ||
844 | spin_unlock_irq (&dum->lock); | ||
845 | err_bind_gadget: | ||
846 | dum->driver = NULL; | ||
847 | dum->gadget.dev.driver = NULL; | ||
848 | return retval; | ||
837 | } | 849 | } |
838 | EXPORT_SYMBOL (usb_gadget_register_driver); | 850 | EXPORT_SYMBOL (usb_gadget_register_driver); |
839 | 851 | ||
@@ -916,7 +928,9 @@ static int dummy_udc_probe (struct platform_device *pdev) | |||
916 | usb_get_hcd (dummy_to_hcd (dum)); | 928 | usb_get_hcd (dummy_to_hcd (dum)); |
917 | 929 | ||
918 | platform_set_drvdata (pdev, dum); | 930 | platform_set_drvdata (pdev, dum); |
919 | device_create_file (&dum->gadget.dev, &dev_attr_function); | 931 | rc = device_create_file (&dum->gadget.dev, &dev_attr_function); |
932 | if (rc < 0) | ||
933 | device_unregister (&dum->gadget.dev); | ||
920 | return rc; | 934 | return rc; |
921 | } | 935 | } |
922 | 936 | ||
@@ -1864,8 +1878,7 @@ static int dummy_start (struct usb_hcd *hcd) | |||
1864 | #endif | 1878 | #endif |
1865 | 1879 | ||
1866 | /* FIXME 'urbs' should be a per-device thing, maybe in usbcore */ | 1880 | /* FIXME 'urbs' should be a per-device thing, maybe in usbcore */ |
1867 | device_create_file (dummy_dev(dum), &dev_attr_urbs); | 1881 | return device_create_file (dummy_dev(dum), &dev_attr_urbs); |
1868 | return 0; | ||
1869 | } | 1882 | } |
1870 | 1883 | ||
1871 | static void dummy_stop (struct usb_hcd *hcd) | 1884 | static void dummy_stop (struct usb_hcd *hcd) |
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index 8d7f1e84cd7b..c83d3b6c68f2 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c | |||
@@ -567,6 +567,7 @@ struct lun { | |||
567 | unsigned int ro : 1; | 567 | unsigned int ro : 1; |
568 | unsigned int prevent_medium_removal : 1; | 568 | unsigned int prevent_medium_removal : 1; |
569 | unsigned int registered : 1; | 569 | unsigned int registered : 1; |
570 | unsigned int info_valid : 1; | ||
570 | 571 | ||
571 | u32 sense_data; | 572 | u32 sense_data; |
572 | u32 sense_data_info; | 573 | u32 sense_data_info; |
@@ -1656,6 +1657,7 @@ static int do_read(struct fsg_dev *fsg) | |||
1656 | curlun->sense_data = | 1657 | curlun->sense_data = |
1657 | SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; | 1658 | SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; |
1658 | curlun->sense_data_info = file_offset >> 9; | 1659 | curlun->sense_data_info = file_offset >> 9; |
1660 | curlun->info_valid = 1; | ||
1659 | bh->inreq->length = 0; | 1661 | bh->inreq->length = 0; |
1660 | bh->state = BUF_STATE_FULL; | 1662 | bh->state = BUF_STATE_FULL; |
1661 | break; | 1663 | break; |
@@ -1691,6 +1693,7 @@ static int do_read(struct fsg_dev *fsg) | |||
1691 | if (nread < amount) { | 1693 | if (nread < amount) { |
1692 | curlun->sense_data = SS_UNRECOVERED_READ_ERROR; | 1694 | curlun->sense_data = SS_UNRECOVERED_READ_ERROR; |
1693 | curlun->sense_data_info = file_offset >> 9; | 1695 | curlun->sense_data_info = file_offset >> 9; |
1696 | curlun->info_valid = 1; | ||
1694 | break; | 1697 | break; |
1695 | } | 1698 | } |
1696 | 1699 | ||
@@ -1785,6 +1788,7 @@ static int do_write(struct fsg_dev *fsg) | |||
1785 | curlun->sense_data = | 1788 | curlun->sense_data = |
1786 | SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; | 1789 | SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; |
1787 | curlun->sense_data_info = usb_offset >> 9; | 1790 | curlun->sense_data_info = usb_offset >> 9; |
1791 | curlun->info_valid = 1; | ||
1788 | continue; | 1792 | continue; |
1789 | } | 1793 | } |
1790 | amount -= (amount & 511); | 1794 | amount -= (amount & 511); |
@@ -1827,6 +1831,7 @@ static int do_write(struct fsg_dev *fsg) | |||
1827 | if (bh->outreq->status != 0) { | 1831 | if (bh->outreq->status != 0) { |
1828 | curlun->sense_data = SS_COMMUNICATION_FAILURE; | 1832 | curlun->sense_data = SS_COMMUNICATION_FAILURE; |
1829 | curlun->sense_data_info = file_offset >> 9; | 1833 | curlun->sense_data_info = file_offset >> 9; |
1834 | curlun->info_valid = 1; | ||
1830 | break; | 1835 | break; |
1831 | } | 1836 | } |
1832 | 1837 | ||
@@ -1868,6 +1873,7 @@ static int do_write(struct fsg_dev *fsg) | |||
1868 | if (nwritten < amount) { | 1873 | if (nwritten < amount) { |
1869 | curlun->sense_data = SS_WRITE_ERROR; | 1874 | curlun->sense_data = SS_WRITE_ERROR; |
1870 | curlun->sense_data_info = file_offset >> 9; | 1875 | curlun->sense_data_info = file_offset >> 9; |
1876 | curlun->info_valid = 1; | ||
1871 | break; | 1877 | break; |
1872 | } | 1878 | } |
1873 | 1879 | ||
@@ -2010,6 +2016,7 @@ static int do_verify(struct fsg_dev *fsg) | |||
2010 | curlun->sense_data = | 2016 | curlun->sense_data = |
2011 | SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; | 2017 | SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; |
2012 | curlun->sense_data_info = file_offset >> 9; | 2018 | curlun->sense_data_info = file_offset >> 9; |
2019 | curlun->info_valid = 1; | ||
2013 | break; | 2020 | break; |
2014 | } | 2021 | } |
2015 | 2022 | ||
@@ -2036,6 +2043,7 @@ static int do_verify(struct fsg_dev *fsg) | |||
2036 | if (nread == 0) { | 2043 | if (nread == 0) { |
2037 | curlun->sense_data = SS_UNRECOVERED_READ_ERROR; | 2044 | curlun->sense_data = SS_UNRECOVERED_READ_ERROR; |
2038 | curlun->sense_data_info = file_offset >> 9; | 2045 | curlun->sense_data_info = file_offset >> 9; |
2046 | curlun->info_valid = 1; | ||
2039 | break; | 2047 | break; |
2040 | } | 2048 | } |
2041 | file_offset += nread; | 2049 | file_offset += nread; |
@@ -2079,6 +2087,7 @@ static int do_request_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh) | |||
2079 | struct lun *curlun = fsg->curlun; | 2087 | struct lun *curlun = fsg->curlun; |
2080 | u8 *buf = (u8 *) bh->buf; | 2088 | u8 *buf = (u8 *) bh->buf; |
2081 | u32 sd, sdinfo; | 2089 | u32 sd, sdinfo; |
2090 | int valid; | ||
2082 | 2091 | ||
2083 | /* | 2092 | /* |
2084 | * From the SCSI-2 spec., section 7.9 (Unit attention condition): | 2093 | * From the SCSI-2 spec., section 7.9 (Unit attention condition): |
@@ -2106,15 +2115,18 @@ static int do_request_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh) | |||
2106 | fsg->bad_lun_okay = 1; | 2115 | fsg->bad_lun_okay = 1; |
2107 | sd = SS_LOGICAL_UNIT_NOT_SUPPORTED; | 2116 | sd = SS_LOGICAL_UNIT_NOT_SUPPORTED; |
2108 | sdinfo = 0; | 2117 | sdinfo = 0; |
2118 | valid = 0; | ||
2109 | } else { | 2119 | } else { |
2110 | sd = curlun->sense_data; | 2120 | sd = curlun->sense_data; |
2111 | sdinfo = curlun->sense_data_info; | 2121 | sdinfo = curlun->sense_data_info; |
2122 | valid = curlun->info_valid << 7; | ||
2112 | curlun->sense_data = SS_NO_SENSE; | 2123 | curlun->sense_data = SS_NO_SENSE; |
2113 | curlun->sense_data_info = 0; | 2124 | curlun->sense_data_info = 0; |
2125 | curlun->info_valid = 0; | ||
2114 | } | 2126 | } |
2115 | 2127 | ||
2116 | memset(buf, 0, 18); | 2128 | memset(buf, 0, 18); |
2117 | buf[0] = 0x80 | 0x70; // Valid, current error | 2129 | buf[0] = valid | 0x70; // Valid, current error |
2118 | buf[2] = SK(sd); | 2130 | buf[2] = SK(sd); |
2119 | put_be32(&buf[3], sdinfo); // Sense information | 2131 | put_be32(&buf[3], sdinfo); // Sense information |
2120 | buf[7] = 18 - 8; // Additional sense length | 2132 | buf[7] = 18 - 8; // Additional sense length |
@@ -2703,6 +2715,7 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size, | |||
2703 | if (fsg->cmnd[0] != SC_REQUEST_SENSE) { | 2715 | if (fsg->cmnd[0] != SC_REQUEST_SENSE) { |
2704 | curlun->sense_data = SS_NO_SENSE; | 2716 | curlun->sense_data = SS_NO_SENSE; |
2705 | curlun->sense_data_info = 0; | 2717 | curlun->sense_data_info = 0; |
2718 | curlun->info_valid = 0; | ||
2706 | } | 2719 | } |
2707 | } else { | 2720 | } else { |
2708 | fsg->curlun = curlun = NULL; | 2721 | fsg->curlun = curlun = NULL; |
@@ -3332,6 +3345,7 @@ static void handle_exception(struct fsg_dev *fsg) | |||
3332 | curlun->sense_data = curlun->unit_attention_data = | 3345 | curlun->sense_data = curlun->unit_attention_data = |
3333 | SS_NO_SENSE; | 3346 | SS_NO_SENSE; |
3334 | curlun->sense_data_info = 0; | 3347 | curlun->sense_data_info = 0; |
3348 | curlun->info_valid = 0; | ||
3335 | } | 3349 | } |
3336 | fsg->state = FSG_STATE_IDLE; | 3350 | fsg->state = FSG_STATE_IDLE; |
3337 | } | 3351 | } |
@@ -3873,21 +3887,26 @@ static int __init fsg_bind(struct usb_gadget *gadget) | |||
3873 | for (i = 0; i < fsg->nluns; ++i) { | 3887 | for (i = 0; i < fsg->nluns; ++i) { |
3874 | curlun = &fsg->luns[i]; | 3888 | curlun = &fsg->luns[i]; |
3875 | curlun->ro = mod_data.ro[i]; | 3889 | curlun->ro = mod_data.ro[i]; |
3890 | curlun->dev.release = lun_release; | ||
3876 | curlun->dev.parent = &gadget->dev; | 3891 | curlun->dev.parent = &gadget->dev; |
3877 | curlun->dev.driver = &fsg_driver.driver; | 3892 | curlun->dev.driver = &fsg_driver.driver; |
3878 | dev_set_drvdata(&curlun->dev, fsg); | 3893 | dev_set_drvdata(&curlun->dev, fsg); |
3879 | snprintf(curlun->dev.bus_id, BUS_ID_SIZE, | 3894 | snprintf(curlun->dev.bus_id, BUS_ID_SIZE, |
3880 | "%s-lun%d", gadget->dev.bus_id, i); | 3895 | "%s-lun%d", gadget->dev.bus_id, i); |
3881 | 3896 | ||
3882 | if ((rc = device_register(&curlun->dev)) != 0) | 3897 | if ((rc = device_register(&curlun->dev)) != 0) { |
3883 | INFO(fsg, "failed to register LUN%d: %d\n", i, rc); | 3898 | INFO(fsg, "failed to register LUN%d: %d\n", i, rc); |
3884 | else { | 3899 | goto out; |
3885 | curlun->registered = 1; | 3900 | } |
3886 | curlun->dev.release = lun_release; | 3901 | if ((rc = device_create_file(&curlun->dev, |
3887 | device_create_file(&curlun->dev, &dev_attr_ro); | 3902 | &dev_attr_ro)) != 0 || |
3888 | device_create_file(&curlun->dev, &dev_attr_file); | 3903 | (rc = device_create_file(&curlun->dev, |
3889 | kref_get(&fsg->ref); | 3904 | &dev_attr_file)) != 0) { |
3905 | device_unregister(&curlun->dev); | ||
3906 | goto out; | ||
3890 | } | 3907 | } |
3908 | curlun->registered = 1; | ||
3909 | kref_get(&fsg->ref); | ||
3891 | 3910 | ||
3892 | if (mod_data.file[i] && *mod_data.file[i]) { | 3911 | if (mod_data.file[i] && *mod_data.file[i]) { |
3893 | if ((rc = open_backing_file(curlun, | 3912 | if ((rc = open_backing_file(curlun, |
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 1027aa04583d..d1d68c402251 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c | |||
@@ -715,17 +715,8 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs) | |||
715 | return IRQ_NOTMINE; | 715 | return IRQ_NOTMINE; |
716 | } | 716 | } |
717 | 717 | ||
718 | /* NOTE: vendors didn't always make the same implementation | ||
719 | * choices for RHSC. Sometimes it triggers on an edge (like | ||
720 | * setting and maybe clearing a port status change bit); and | ||
721 | * it's level-triggered on other silicon, active until khubd | ||
722 | * clears all active port status change bits. Poll by timer | ||
723 | * til it's fully debounced and the difference won't matter. | ||
724 | */ | ||
725 | if (ints & OHCI_INTR_RHSC) { | 718 | if (ints & OHCI_INTR_RHSC) { |
726 | ohci_vdbg (ohci, "rhsc\n"); | 719 | ohci_vdbg (ohci, "rhsc\n"); |
727 | ohci_writel (ohci, OHCI_INTR_RHSC, ®s->intrdisable); | ||
728 | hcd->poll_rh = 1; | ||
729 | ohci->next_statechange = jiffies + STATECHANGE_DELAY; | 720 | ohci->next_statechange = jiffies + STATECHANGE_DELAY; |
730 | ohci_writel (ohci, OHCI_INTR_RHSC, ®s->intrstatus); | 721 | ohci_writel (ohci, OHCI_INTR_RHSC, ®s->intrstatus); |
731 | usb_hcd_poll_rh_status(hcd); | 722 | usb_hcd_poll_rh_status(hcd); |
@@ -743,13 +734,18 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs) | |||
743 | if (ints & OHCI_INTR_RD) { | 734 | if (ints & OHCI_INTR_RD) { |
744 | ohci_vdbg (ohci, "resume detect\n"); | 735 | ohci_vdbg (ohci, "resume detect\n"); |
745 | ohci_writel (ohci, OHCI_INTR_RD, ®s->intrstatus); | 736 | ohci_writel (ohci, OHCI_INTR_RD, ®s->intrstatus); |
746 | if (hcd->state != HC_STATE_QUIESCING) | 737 | hcd->poll_rh = 1; |
738 | if (ohci->autostop) { | ||
739 | spin_lock (&ohci->lock); | ||
740 | ohci_rh_resume (ohci); | ||
741 | spin_unlock (&ohci->lock); | ||
742 | } else | ||
747 | usb_hcd_resume_root_hub(hcd); | 743 | usb_hcd_resume_root_hub(hcd); |
748 | } | 744 | } |
749 | 745 | ||
750 | if (ints & OHCI_INTR_WDH) { | 746 | if (ints & OHCI_INTR_WDH) { |
751 | if (HC_IS_RUNNING(hcd->state)) | 747 | if (HC_IS_RUNNING(hcd->state)) |
752 | ohci_writel (ohci, OHCI_INTR_WDH, ®s->intrdisable); | 748 | ohci_writel (ohci, OHCI_INTR_WDH, ®s->intrdisable); |
753 | spin_lock (&ohci->lock); | 749 | spin_lock (&ohci->lock); |
754 | dl_done_list (ohci, ptregs); | 750 | dl_done_list (ohci, ptregs); |
755 | spin_unlock (&ohci->lock); | 751 | spin_unlock (&ohci->lock); |
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index 0b899339cac8..ec75774abeac 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c | |||
@@ -44,27 +44,17 @@ static void ohci_rhsc_enable (struct usb_hcd *hcd) | |||
44 | ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable); | 44 | ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable); |
45 | } | 45 | } |
46 | 46 | ||
47 | #ifdef CONFIG_PM | ||
48 | |||
49 | #define OHCI_SCHED_ENABLES \ | 47 | #define OHCI_SCHED_ENABLES \ |
50 | (OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE) | 48 | (OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE) |
51 | 49 | ||
52 | static void dl_done_list (struct ohci_hcd *, struct pt_regs *); | 50 | static void dl_done_list (struct ohci_hcd *, struct pt_regs *); |
53 | static void finish_unlinks (struct ohci_hcd *, u16 , struct pt_regs *); | 51 | static void finish_unlinks (struct ohci_hcd *, u16 , struct pt_regs *); |
54 | static int ohci_restart (struct ohci_hcd *ohci); | ||
55 | 52 | ||
56 | static int ohci_bus_suspend (struct usb_hcd *hcd) | 53 | static int ohci_rh_suspend (struct ohci_hcd *ohci, int autostop) |
54 | __releases(ohci->lock) | ||
55 | __acquires(ohci->lock) | ||
57 | { | 56 | { |
58 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | ||
59 | int status = 0; | 57 | int status = 0; |
60 | unsigned long flags; | ||
61 | |||
62 | spin_lock_irqsave (&ohci->lock, flags); | ||
63 | |||
64 | if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) { | ||
65 | spin_unlock_irqrestore (&ohci->lock, flags); | ||
66 | return -ESHUTDOWN; | ||
67 | } | ||
68 | 58 | ||
69 | ohci->hc_control = ohci_readl (ohci, &ohci->regs->control); | 59 | ohci->hc_control = ohci_readl (ohci, &ohci->regs->control); |
70 | switch (ohci->hc_control & OHCI_CTRL_HCFS) { | 60 | switch (ohci->hc_control & OHCI_CTRL_HCFS) { |
@@ -80,15 +70,16 @@ static int ohci_bus_suspend (struct usb_hcd *hcd) | |||
80 | ohci_dbg (ohci, "needs reinit!\n"); | 70 | ohci_dbg (ohci, "needs reinit!\n"); |
81 | goto done; | 71 | goto done; |
82 | case OHCI_USB_SUSPEND: | 72 | case OHCI_USB_SUSPEND: |
83 | ohci_dbg (ohci, "already suspended\n"); | 73 | if (!ohci->autostop) { |
84 | goto done; | 74 | ohci_dbg (ohci, "already suspended\n"); |
75 | goto done; | ||
76 | } | ||
85 | } | 77 | } |
86 | ohci_dbg (ohci, "suspend root hub\n"); | 78 | ohci_dbg (ohci, "%s root hub\n", |
79 | autostop ? "auto-stop" : "suspend"); | ||
87 | 80 | ||
88 | /* First stop any processing */ | 81 | /* First stop any processing */ |
89 | if (ohci->hc_control & OHCI_SCHED_ENABLES) { | 82 | if (!autostop && (ohci->hc_control & OHCI_SCHED_ENABLES)) { |
90 | int limit; | ||
91 | |||
92 | ohci->hc_control &= ~OHCI_SCHED_ENABLES; | 83 | ohci->hc_control &= ~OHCI_SCHED_ENABLES; |
93 | ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); | 84 | ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); |
94 | ohci->hc_control = ohci_readl (ohci, &ohci->regs->control); | 85 | ohci->hc_control = ohci_readl (ohci, &ohci->regs->control); |
@@ -98,27 +89,22 @@ static int ohci_bus_suspend (struct usb_hcd *hcd) | |||
98 | * then the last WDH could take 6+ msec | 89 | * then the last WDH could take 6+ msec |
99 | */ | 90 | */ |
100 | ohci_dbg (ohci, "stopping schedules ...\n"); | 91 | ohci_dbg (ohci, "stopping schedules ...\n"); |
101 | limit = 2000; | 92 | ohci->autostop = 0; |
102 | while (limit > 0) { | 93 | spin_unlock_irq (&ohci->lock); |
103 | udelay (250); | 94 | msleep (8); |
104 | limit =- 250; | 95 | spin_lock_irq (&ohci->lock); |
105 | if (ohci_readl (ohci, &ohci->regs->intrstatus) | ||
106 | & OHCI_INTR_SF) | ||
107 | break; | ||
108 | } | ||
109 | dl_done_list (ohci, NULL); | ||
110 | mdelay (7); | ||
111 | } | 96 | } |
112 | dl_done_list (ohci, NULL); | 97 | dl_done_list (ohci, NULL); |
113 | finish_unlinks (ohci, ohci_frame_no(ohci), NULL); | 98 | finish_unlinks (ohci, ohci_frame_no(ohci), NULL); |
114 | ohci_writel (ohci, ohci_readl (ohci, &ohci->regs->intrstatus), | ||
115 | &ohci->regs->intrstatus); | ||
116 | 99 | ||
117 | /* maybe resume can wake root hub */ | 100 | /* maybe resume can wake root hub */ |
118 | if (device_may_wakeup(&ohci_to_hcd(ohci)->self.root_hub->dev)) | 101 | if (device_may_wakeup(&ohci_to_hcd(ohci)->self.root_hub->dev) || |
102 | autostop) | ||
119 | ohci->hc_control |= OHCI_CTRL_RWE; | 103 | ohci->hc_control |= OHCI_CTRL_RWE; |
120 | else | 104 | else { |
105 | ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrdisable); | ||
121 | ohci->hc_control &= ~OHCI_CTRL_RWE; | 106 | ohci->hc_control &= ~OHCI_CTRL_RWE; |
107 | } | ||
122 | 108 | ||
123 | /* Suspend hub ... this is the "global (to this bus) suspend" mode, | 109 | /* Suspend hub ... this is the "global (to this bus) suspend" mode, |
124 | * which doesn't imply ports will first be individually suspended. | 110 | * which doesn't imply ports will first be individually suspended. |
@@ -129,13 +115,12 @@ static int ohci_bus_suspend (struct usb_hcd *hcd) | |||
129 | (void) ohci_readl (ohci, &ohci->regs->control); | 115 | (void) ohci_readl (ohci, &ohci->regs->control); |
130 | 116 | ||
131 | /* no resumes until devices finish suspending */ | 117 | /* no resumes until devices finish suspending */ |
132 | ohci->next_statechange = jiffies + msecs_to_jiffies (5); | 118 | if (!autostop) { |
133 | 119 | ohci->next_statechange = jiffies + msecs_to_jiffies (5); | |
134 | /* no timer polling */ | 120 | ohci->autostop = 0; |
135 | hcd->poll_rh = 0; | 121 | } |
136 | 122 | ||
137 | done: | 123 | done: |
138 | spin_unlock_irqrestore (&ohci->lock, flags); | ||
139 | return status; | 124 | return status; |
140 | } | 125 | } |
141 | 126 | ||
@@ -147,25 +132,19 @@ static inline struct ed *find_head (struct ed *ed) | |||
147 | return ed; | 132 | return ed; |
148 | } | 133 | } |
149 | 134 | ||
135 | static int ohci_restart (struct ohci_hcd *ohci); | ||
136 | |||
150 | /* caller has locked the root hub */ | 137 | /* caller has locked the root hub */ |
151 | static int ohci_bus_resume (struct usb_hcd *hcd) | 138 | static int ohci_rh_resume (struct ohci_hcd *ohci) |
139 | __releases(ohci->lock) | ||
140 | __acquires(ohci->lock) | ||
152 | { | 141 | { |
153 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | 142 | struct usb_hcd *hcd = ohci_to_hcd (ohci); |
154 | u32 temp, enables; | 143 | u32 temp, enables; |
155 | int status = -EINPROGRESS; | 144 | int status = -EINPROGRESS; |
156 | unsigned long flags; | 145 | int autostopped = ohci->autostop; |
157 | |||
158 | if (time_before (jiffies, ohci->next_statechange)) | ||
159 | msleep(5); | ||
160 | |||
161 | spin_lock_irqsave (&ohci->lock, flags); | ||
162 | |||
163 | if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) { | ||
164 | spin_unlock_irqrestore (&ohci->lock, flags); | ||
165 | return -ESHUTDOWN; | ||
166 | } | ||
167 | |||
168 | 146 | ||
147 | ohci->autostop = 0; | ||
169 | ohci->hc_control = ohci_readl (ohci, &ohci->regs->control); | 148 | ohci->hc_control = ohci_readl (ohci, &ohci->regs->control); |
170 | 149 | ||
171 | if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) { | 150 | if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) { |
@@ -185,7 +164,8 @@ static int ohci_bus_resume (struct usb_hcd *hcd) | |||
185 | ohci->hc_control |= OHCI_USB_RESUME; | 164 | ohci->hc_control |= OHCI_USB_RESUME; |
186 | ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); | 165 | ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); |
187 | (void) ohci_readl (ohci, &ohci->regs->control); | 166 | (void) ohci_readl (ohci, &ohci->regs->control); |
188 | ohci_dbg (ohci, "resume root hub\n"); | 167 | ohci_dbg (ohci, "%s root hub\n", |
168 | autostopped ? "auto-start" : "resume"); | ||
189 | break; | 169 | break; |
190 | case OHCI_USB_RESUME: | 170 | case OHCI_USB_RESUME: |
191 | /* HCFS changes sometime after INTR_RD */ | 171 | /* HCFS changes sometime after INTR_RD */ |
@@ -200,16 +180,24 @@ static int ohci_bus_resume (struct usb_hcd *hcd) | |||
200 | ohci_dbg (ohci, "lost power\n"); | 180 | ohci_dbg (ohci, "lost power\n"); |
201 | status = -EBUSY; | 181 | status = -EBUSY; |
202 | } | 182 | } |
203 | spin_unlock_irqrestore (&ohci->lock, flags); | 183 | #ifdef CONFIG_PM |
204 | if (status == -EBUSY) { | 184 | if (status == -EBUSY) { |
205 | (void) ohci_init (ohci); | 185 | if (!autostopped) { |
206 | return ohci_restart (ohci); | 186 | spin_unlock_irq (&ohci->lock); |
187 | (void) ohci_init (ohci); | ||
188 | status = ohci_restart (ohci); | ||
189 | spin_lock_irq (&ohci->lock); | ||
190 | } | ||
191 | return status; | ||
207 | } | 192 | } |
193 | #endif | ||
208 | if (status != -EINPROGRESS) | 194 | if (status != -EINPROGRESS) |
209 | return status; | 195 | return status; |
196 | if (autostopped) | ||
197 | goto skip_resume; | ||
198 | spin_unlock_irq (&ohci->lock); | ||
210 | 199 | ||
211 | temp = ohci->num_ports; | 200 | temp = ohci->num_ports; |
212 | enables = 0; | ||
213 | while (temp--) { | 201 | while (temp--) { |
214 | u32 stat = ohci_readl (ohci, | 202 | u32 stat = ohci_readl (ohci, |
215 | &ohci->regs->roothub.portstatus [temp]); | 203 | &ohci->regs->roothub.portstatus [temp]); |
@@ -242,17 +230,21 @@ static int ohci_bus_resume (struct usb_hcd *hcd) | |||
242 | /* Sometimes PCI D3 suspend trashes frame timings ... */ | 230 | /* Sometimes PCI D3 suspend trashes frame timings ... */ |
243 | periodic_reinit (ohci); | 231 | periodic_reinit (ohci); |
244 | 232 | ||
233 | /* the following code is executed with ohci->lock held and | ||
234 | * irqs disabled if and only if autostopped is true | ||
235 | */ | ||
236 | |||
237 | skip_resume: | ||
245 | /* interrupts might have been disabled */ | 238 | /* interrupts might have been disabled */ |
246 | ohci_writel (ohci, OHCI_INTR_INIT, &ohci->regs->intrenable); | 239 | ohci_writel (ohci, OHCI_INTR_INIT, &ohci->regs->intrenable); |
247 | if (ohci->ed_rm_list) | 240 | if (ohci->ed_rm_list) |
248 | ohci_writel (ohci, OHCI_INTR_SF, &ohci->regs->intrenable); | 241 | ohci_writel (ohci, OHCI_INTR_SF, &ohci->regs->intrenable); |
249 | ohci_writel (ohci, ohci_readl (ohci, &ohci->regs->intrstatus), | ||
250 | &ohci->regs->intrstatus); | ||
251 | 242 | ||
252 | /* Then re-enable operations */ | 243 | /* Then re-enable operations */ |
253 | ohci_writel (ohci, OHCI_USB_OPER, &ohci->regs->control); | 244 | ohci_writel (ohci, OHCI_USB_OPER, &ohci->regs->control); |
254 | (void) ohci_readl (ohci, &ohci->regs->control); | 245 | (void) ohci_readl (ohci, &ohci->regs->control); |
255 | msleep (3); | 246 | if (!autostopped) |
247 | msleep (3); | ||
256 | 248 | ||
257 | temp = ohci->hc_control; | 249 | temp = ohci->hc_control; |
258 | temp &= OHCI_CTRL_RWC; | 250 | temp &= OHCI_CTRL_RWC; |
@@ -262,7 +254,11 @@ static int ohci_bus_resume (struct usb_hcd *hcd) | |||
262 | (void) ohci_readl (ohci, &ohci->regs->control); | 254 | (void) ohci_readl (ohci, &ohci->regs->control); |
263 | 255 | ||
264 | /* TRSMRCY */ | 256 | /* TRSMRCY */ |
265 | msleep (10); | 257 | if (!autostopped) { |
258 | msleep (10); | ||
259 | spin_lock_irq (&ohci->lock); | ||
260 | } | ||
261 | /* now ohci->lock is always held and irqs are always disabled */ | ||
266 | 262 | ||
267 | /* keep it alive for more than ~5x suspend + resume costs */ | 263 | /* keep it alive for more than ~5x suspend + resume costs */ |
268 | ohci->next_statechange = jiffies + STATECHANGE_DELAY; | 264 | ohci->next_statechange = jiffies + STATECHANGE_DELAY; |
@@ -299,6 +295,45 @@ static int ohci_bus_resume (struct usb_hcd *hcd) | |||
299 | return 0; | 295 | return 0; |
300 | } | 296 | } |
301 | 297 | ||
298 | #ifdef CONFIG_PM | ||
299 | |||
300 | static int ohci_bus_suspend (struct usb_hcd *hcd) | ||
301 | { | ||
302 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | ||
303 | int rc; | ||
304 | |||
305 | spin_lock_irq (&ohci->lock); | ||
306 | |||
307 | if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) | ||
308 | rc = -ESHUTDOWN; | ||
309 | else | ||
310 | rc = ohci_rh_suspend (ohci, 0); | ||
311 | spin_unlock_irq (&ohci->lock); | ||
312 | return rc; | ||
313 | } | ||
314 | |||
315 | static int ohci_bus_resume (struct usb_hcd *hcd) | ||
316 | { | ||
317 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | ||
318 | int rc; | ||
319 | |||
320 | if (time_before (jiffies, ohci->next_statechange)) | ||
321 | msleep(5); | ||
322 | |||
323 | spin_lock_irq (&ohci->lock); | ||
324 | |||
325 | if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) | ||
326 | rc = -ESHUTDOWN; | ||
327 | else | ||
328 | rc = ohci_rh_resume (ohci); | ||
329 | spin_unlock_irq (&ohci->lock); | ||
330 | |||
331 | /* poll until we know a device is connected or we autostop */ | ||
332 | if (rc == 0) | ||
333 | usb_hcd_poll_rh_status(hcd); | ||
334 | return rc; | ||
335 | } | ||
336 | |||
302 | #endif /* CONFIG_PM */ | 337 | #endif /* CONFIG_PM */ |
303 | 338 | ||
304 | /*-------------------------------------------------------------------------*/ | 339 | /*-------------------------------------------------------------------------*/ |
@@ -310,21 +345,11 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) | |||
310 | { | 345 | { |
311 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | 346 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
312 | int i, changed = 0, length = 1; | 347 | int i, changed = 0, length = 1; |
313 | int can_suspend; | 348 | int any_connected = 0, rhsc_enabled = 1; |
314 | unsigned long flags; | 349 | unsigned long flags; |
315 | 350 | ||
316 | can_suspend = device_may_wakeup(&hcd->self.root_hub->dev); | ||
317 | spin_lock_irqsave (&ohci->lock, flags); | 351 | spin_lock_irqsave (&ohci->lock, flags); |
318 | 352 | ||
319 | /* handle autosuspended root: finish resuming before | ||
320 | * letting khubd or root hub timer see state changes. | ||
321 | */ | ||
322 | if (unlikely((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER | ||
323 | || !HC_IS_RUNNING(hcd->state))) { | ||
324 | can_suspend = 0; | ||
325 | goto done; | ||
326 | } | ||
327 | |||
328 | /* undocumented erratum seen on at least rev D */ | 353 | /* undocumented erratum seen on at least rev D */ |
329 | if ((ohci->flags & OHCI_QUIRK_AMD756) | 354 | if ((ohci->flags & OHCI_QUIRK_AMD756) |
330 | && (roothub_a (ohci) & RH_A_NDP) > MAX_ROOT_PORTS) { | 355 | && (roothub_a (ohci) & RH_A_NDP) > MAX_ROOT_PORTS) { |
@@ -348,9 +373,8 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) | |||
348 | for (i = 0; i < ohci->num_ports; i++) { | 373 | for (i = 0; i < ohci->num_ports; i++) { |
349 | u32 status = roothub_portstatus (ohci, i); | 374 | u32 status = roothub_portstatus (ohci, i); |
350 | 375 | ||
351 | /* can't autosuspend with active ports */ | 376 | /* can't autostop if ports are connected */ |
352 | if ((status & RH_PS_PES) && !(status & RH_PS_PSS)) | 377 | any_connected |= (status & RH_PS_CCS); |
353 | can_suspend = 0; | ||
354 | 378 | ||
355 | if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC | 379 | if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC |
356 | | RH_PS_OCIC | RH_PS_PRSC)) { | 380 | | RH_PS_OCIC | RH_PS_PRSC)) { |
@@ -359,49 +383,73 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) | |||
359 | buf [0] |= 1 << (i + 1); | 383 | buf [0] |= 1 << (i + 1); |
360 | else | 384 | else |
361 | buf [1] |= 1 << (i - 7); | 385 | buf [1] |= 1 << (i - 7); |
362 | continue; | ||
363 | } | 386 | } |
364 | } | 387 | } |
365 | 388 | ||
366 | /* after root hub changes, stop polling after debouncing | 389 | /* NOTE: vendors didn't always make the same implementation |
367 | * for a while and maybe kicking in autosuspend | 390 | * choices for RHSC. Sometimes it triggers on an edge (like |
391 | * setting and maybe clearing a port status change bit); and | ||
392 | * it's level-triggered on other silicon, active until khubd | ||
393 | * clears all active port status change bits. If it's still | ||
394 | * set (level-triggered) we must disable it and rely on | ||
395 | * polling until khubd re-enables it. | ||
368 | */ | 396 | */ |
369 | if (changed) { | 397 | if (ohci_readl (ohci, &ohci->regs->intrstatus) & OHCI_INTR_RHSC) { |
370 | ohci->next_statechange = jiffies + STATECHANGE_DELAY; | 398 | ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrdisable); |
371 | can_suspend = 0; | 399 | (void) ohci_readl (ohci, &ohci->regs->intrdisable); |
372 | } else if (time_before (jiffies, ohci->next_statechange)) { | 400 | rhsc_enabled = 0; |
373 | can_suspend = 0; | 401 | } |
374 | } else { | 402 | hcd->poll_rh = 1; |
375 | #ifdef CONFIG_PM | 403 | |
376 | can_suspend = can_suspend | 404 | /* carry out appropriate state changes */ |
377 | && !ohci->ed_rm_list | 405 | switch (ohci->hc_control & OHCI_CTRL_HCFS) { |
378 | && ((OHCI_CTRL_HCFS | OHCI_SCHED_ENABLES) | 406 | |
379 | & ohci->hc_control) | 407 | case OHCI_USB_OPER: |
380 | == OHCI_USB_OPER; | 408 | /* keep on polling until we know a device is connected |
381 | #endif | 409 | * and RHSC is enabled */ |
382 | if (hcd->uses_new_polling) { | 410 | if (!ohci->autostop) { |
411 | if (any_connected) { | ||
412 | if (rhsc_enabled) | ||
413 | hcd->poll_rh = 0; | ||
414 | } else { | ||
415 | ohci->autostop = 1; | ||
416 | ohci->next_statechange = jiffies + HZ; | ||
417 | } | ||
418 | |||
419 | /* if no devices have been attached for one second, autostop */ | ||
420 | } else { | ||
421 | if (changed || any_connected) { | ||
422 | ohci->autostop = 0; | ||
423 | ohci->next_statechange = jiffies + | ||
424 | STATECHANGE_DELAY; | ||
425 | } else if (time_after_eq (jiffies, | ||
426 | ohci->next_statechange) | ||
427 | && !ohci->ed_rm_list | ||
428 | && !(ohci->hc_control & | ||
429 | OHCI_SCHED_ENABLES)) { | ||
430 | ohci_rh_suspend (ohci, 1); | ||
431 | } | ||
432 | } | ||
433 | break; | ||
434 | |||
435 | /* if there is a port change, autostart or ask to be resumed */ | ||
436 | case OHCI_USB_SUSPEND: | ||
437 | case OHCI_USB_RESUME: | ||
438 | if (changed) { | ||
439 | if (ohci->autostop) | ||
440 | ohci_rh_resume (ohci); | ||
441 | else | ||
442 | usb_hcd_resume_root_hub (hcd); | ||
443 | } else { | ||
444 | /* everything is idle, no need for polling */ | ||
383 | hcd->poll_rh = 0; | 445 | hcd->poll_rh = 0; |
384 | /* use INTR_RHSC iff INTR_RD won't apply */ | ||
385 | if (!can_suspend) | ||
386 | ohci_writel (ohci, OHCI_INTR_RHSC, | ||
387 | &ohci->regs->intrenable); | ||
388 | } | 446 | } |
447 | break; | ||
389 | } | 448 | } |
390 | 449 | ||
391 | done: | 450 | done: |
392 | spin_unlock_irqrestore (&ohci->lock, flags); | 451 | spin_unlock_irqrestore (&ohci->lock, flags); |
393 | 452 | ||
394 | #ifdef CONFIG_PM | ||
395 | /* save power by autosuspending idle root hubs; | ||
396 | * INTR_RD wakes us when there's work | ||
397 | */ | ||
398 | if (can_suspend && usb_trylock_device (hcd->self.root_hub) == 0) { | ||
399 | ohci_vdbg (ohci, "autosuspend\n"); | ||
400 | (void) ohci_bus_suspend (hcd); | ||
401 | usb_unlock_device (hcd->self.root_hub); | ||
402 | } | ||
403 | #endif | ||
404 | |||
405 | return changed ? length : 0; | 453 | return changed ? length : 0; |
406 | } | 454 | } |
407 | 455 | ||
@@ -572,9 +620,6 @@ static int ohci_hub_control ( | |||
572 | break; | 620 | break; |
573 | case USB_PORT_FEAT_SUSPEND: | 621 | case USB_PORT_FEAT_SUSPEND: |
574 | temp = RH_PS_POCI; | 622 | temp = RH_PS_POCI; |
575 | if ((ohci->hc_control & OHCI_CTRL_HCFS) | ||
576 | != OHCI_USB_OPER) | ||
577 | usb_hcd_resume_root_hub(hcd); | ||
578 | break; | 623 | break; |
579 | case USB_PORT_FEAT_C_SUSPEND: | 624 | case USB_PORT_FEAT_C_SUSPEND: |
580 | temp = RH_PS_PSSC; | 625 | temp = RH_PS_PSSC; |
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 3732db7d68eb..874418552789 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c | |||
@@ -73,13 +73,14 @@ ohci_pci_start (struct usb_hcd *hcd) | |||
73 | else if (pdev->vendor == PCI_VENDOR_ID_NS) { | 73 | else if (pdev->vendor == PCI_VENDOR_ID_NS) { |
74 | struct pci_dev *b; | 74 | struct pci_dev *b; |
75 | 75 | ||
76 | b = pci_find_slot (pdev->bus->number, | 76 | b = pci_get_slot (pdev->bus, |
77 | PCI_DEVFN (PCI_SLOT (pdev->devfn), 1)); | 77 | PCI_DEVFN (PCI_SLOT (pdev->devfn), 1)); |
78 | if (b && b->device == PCI_DEVICE_ID_NS_87560_LIO | 78 | if (b && b->device == PCI_DEVICE_ID_NS_87560_LIO |
79 | && b->vendor == PCI_VENDOR_ID_NS) { | 79 | && b->vendor == PCI_VENDOR_ID_NS) { |
80 | ohci->flags |= OHCI_QUIRK_SUPERIO; | 80 | ohci->flags |= OHCI_QUIRK_SUPERIO; |
81 | ohci_dbg (ohci, "Using NSC SuperIO setup\n"); | 81 | ohci_dbg (ohci, "Using NSC SuperIO setup\n"); |
82 | } | 82 | } |
83 | pci_dev_put(b); | ||
83 | } | 84 | } |
84 | 85 | ||
85 | /* Check for Compaq's ZFMicro chipset, which needs short | 86 | /* Check for Compaq's ZFMicro chipset, which needs short |
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index 93fdc3c35341..a2f42a2f47c6 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h | |||
@@ -388,6 +388,7 @@ struct ohci_hcd { | |||
388 | u32 hc_control; /* copy of hc control reg */ | 388 | u32 hc_control; /* copy of hc control reg */ |
389 | unsigned long next_statechange; /* suspend/resume */ | 389 | unsigned long next_statechange; /* suspend/resume */ |
390 | u32 fminterval; /* saved register */ | 390 | u32 fminterval; /* saved register */ |
391 | unsigned autostop:1; /* rh auto stopping/stopped */ | ||
391 | 392 | ||
392 | unsigned long flags; /* for HC bugs */ | 393 | unsigned long flags; /* for HC bugs */ |
393 | #define OHCI_QUIRK_AMD756 0x01 /* erratum #4 */ | 394 | #define OHCI_QUIRK_AMD756 0x01 /* erratum #4 */ |
diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c index b2bafc37c414..5f861331932a 100644 --- a/drivers/usb/image/microtek.c +++ b/drivers/usb/image/microtek.c | |||
@@ -225,7 +225,7 @@ static inline void mts_debug_dump(struct mts_desc* desc) { | |||
225 | } | 225 | } |
226 | 226 | ||
227 | 227 | ||
228 | static inline void mts_show_command(Scsi_Cmnd *srb) | 228 | static inline void mts_show_command(struct scsi_cmnd *srb) |
229 | { | 229 | { |
230 | char *what = NULL; | 230 | char *what = NULL; |
231 | 231 | ||
@@ -309,7 +309,7 @@ static inline void mts_show_command(Scsi_Cmnd *srb) | |||
309 | 309 | ||
310 | #else | 310 | #else |
311 | 311 | ||
312 | static inline void mts_show_command(Scsi_Cmnd * dummy) | 312 | static inline void mts_show_command(struct scsi_cmnd * dummy) |
313 | { | 313 | { |
314 | } | 314 | } |
315 | 315 | ||
@@ -338,7 +338,7 @@ static int mts_slave_configure (struct scsi_device *s) | |||
338 | return 0; | 338 | return 0; |
339 | } | 339 | } |
340 | 340 | ||
341 | static int mts_scsi_abort (Scsi_Cmnd *srb) | 341 | static int mts_scsi_abort(struct scsi_cmnd *srb) |
342 | { | 342 | { |
343 | struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]); | 343 | struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]); |
344 | 344 | ||
@@ -349,7 +349,7 @@ static int mts_scsi_abort (Scsi_Cmnd *srb) | |||
349 | return FAILED; | 349 | return FAILED; |
350 | } | 350 | } |
351 | 351 | ||
352 | static int mts_scsi_host_reset (Scsi_Cmnd *srb) | 352 | static int mts_scsi_host_reset(struct scsi_cmnd *srb) |
353 | { | 353 | { |
354 | struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]); | 354 | struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]); |
355 | int result, rc; | 355 | int result, rc; |
@@ -366,8 +366,8 @@ static int mts_scsi_host_reset (Scsi_Cmnd *srb) | |||
366 | return result ? FAILED : SUCCESS; | 366 | return result ? FAILED : SUCCESS; |
367 | } | 367 | } |
368 | 368 | ||
369 | static | 369 | static int |
370 | int mts_scsi_queuecommand (Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback ); | 370 | mts_scsi_queuecommand(struct scsi_cmnd *srb, mts_scsi_cmnd_callback callback); |
371 | 371 | ||
372 | static void mts_transfer_cleanup( struct urb *transfer ); | 372 | static void mts_transfer_cleanup( struct urb *transfer ); |
373 | static void mts_do_sg(struct urb * transfer, struct pt_regs *regs); | 373 | static void mts_do_sg(struct urb * transfer, struct pt_regs *regs); |
@@ -537,7 +537,7 @@ static const unsigned char mts_direction[256/8] = { | |||
537 | #define MTS_DIRECTION_IS_IN(x) ((mts_direction[x>>3] >> (x & 7)) & 1) | 537 | #define MTS_DIRECTION_IS_IN(x) ((mts_direction[x>>3] >> (x & 7)) & 1) |
538 | 538 | ||
539 | static void | 539 | static void |
540 | mts_build_transfer_context( Scsi_Cmnd *srb, struct mts_desc* desc ) | 540 | mts_build_transfer_context(struct scsi_cmnd *srb, struct mts_desc* desc) |
541 | { | 541 | { |
542 | int pipe; | 542 | int pipe; |
543 | struct scatterlist * sg; | 543 | struct scatterlist * sg; |
@@ -588,8 +588,8 @@ mts_build_transfer_context( Scsi_Cmnd *srb, struct mts_desc* desc ) | |||
588 | } | 588 | } |
589 | 589 | ||
590 | 590 | ||
591 | static | 591 | static int |
592 | int mts_scsi_queuecommand( Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback ) | 592 | mts_scsi_queuecommand(struct scsi_cmnd *srb, mts_scsi_cmnd_callback callback) |
593 | { | 593 | { |
594 | struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]); | 594 | struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]); |
595 | int err = 0; | 595 | int err = 0; |
diff --git a/drivers/usb/image/microtek.h b/drivers/usb/image/microtek.h index 926d4bdc6746..d5d62a939058 100644 --- a/drivers/usb/image/microtek.h +++ b/drivers/usb/image/microtek.h | |||
@@ -8,14 +8,14 @@ | |||
8 | * | 8 | * |
9 | */ | 9 | */ |
10 | 10 | ||
11 | typedef void (*mts_scsi_cmnd_callback)(Scsi_Cmnd *); | 11 | typedef void (*mts_scsi_cmnd_callback)(struct scsi_cmnd *); |
12 | 12 | ||
13 | 13 | ||
14 | struct mts_transfer_context | 14 | struct mts_transfer_context |
15 | { | 15 | { |
16 | struct mts_desc* instance; | 16 | struct mts_desc* instance; |
17 | mts_scsi_cmnd_callback final_callback; | 17 | mts_scsi_cmnd_callback final_callback; |
18 | Scsi_Cmnd *srb; | 18 | struct scsi_cmnd *srb; |
19 | 19 | ||
20 | void* data; | 20 | void* data; |
21 | unsigned data_length; | 21 | unsigned data_length; |
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 2a3e9e9b4b3d..81b1ea01a172 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c | |||
@@ -1600,6 +1600,9 @@ void hid_init_reports(struct hid_device *hid) | |||
1600 | #define USB_VENDOR_ID_ALCOR 0x058f | 1600 | #define USB_VENDOR_ID_ALCOR 0x058f |
1601 | #define USB_DEVICE_ID_ALCOR_USBRS232 0x9720 | 1601 | #define USB_DEVICE_ID_ALCOR_USBRS232 0x9720 |
1602 | 1602 | ||
1603 | #define USB_VENDOR_ID_SUN 0x0430 | ||
1604 | #define USB_DEVICE_ID_RARITAN_KVM_DONGLE 0xcdab | ||
1605 | |||
1603 | /* | 1606 | /* |
1604 | * Alphabetically sorted blacklist by quirk type. | 1607 | * Alphabetically sorted blacklist by quirk type. |
1605 | */ | 1608 | */ |
@@ -1729,6 +1732,7 @@ static const struct hid_blacklist { | |||
1729 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET }, | 1732 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET }, |
1730 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET }, | 1733 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET }, |
1731 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET }, | 1734 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET }, |
1735 | { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, | ||
1732 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, | 1736 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, |
1733 | { USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, | 1737 | { USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, |
1734 | 1738 | ||
diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c index 9a8d137d39f9..78e419904abf 100644 --- a/drivers/usb/misc/phidgetkit.c +++ b/drivers/usb/misc/phidgetkit.c | |||
@@ -44,20 +44,25 @@ struct driver_interfacekit { | |||
44 | int inputs; | 44 | int inputs; |
45 | int outputs; | 45 | int outputs; |
46 | int has_lcd; | 46 | int has_lcd; |
47 | int amnesiac; | ||
47 | }; | 48 | }; |
48 | #define ifkit(_sensors, _inputs, _outputs, _lcd) \ | 49 | |
49 | static struct driver_interfacekit ph_##_sensors##_inputs##_outputs = { \ | 50 | #define ifkit(_sensors, _inputs, _outputs, _lcd, _amnesiac) \ |
51 | { \ | ||
50 | .sensors = _sensors, \ | 52 | .sensors = _sensors, \ |
51 | .inputs = _inputs, \ | 53 | .inputs = _inputs, \ |
52 | .outputs = _outputs, \ | 54 | .outputs = _outputs, \ |
53 | .has_lcd = _lcd, \ | 55 | .has_lcd = _lcd, \ |
56 | .amnesiac = _amnesiac \ | ||
54 | }; | 57 | }; |
55 | ifkit(0, 0, 4, 0); | 58 | |
56 | ifkit(8, 8, 8, 0); | 59 | static const struct driver_interfacekit ph_004 = ifkit(0, 0, 4, 0, 0); |
57 | ifkit(0, 4, 7, 1); | 60 | static const struct driver_interfacekit ph_888n = ifkit(8, 8, 8, 0, 1); |
58 | ifkit(8, 8, 4, 0); | 61 | static const struct driver_interfacekit ph_888o = ifkit(8, 8, 8, 0, 0); |
59 | ifkit(0, 8, 8, 1); | 62 | static const struct driver_interfacekit ph_047 = ifkit(0, 4, 7, 1, 0); |
60 | ifkit(0, 16, 16, 0); | 63 | static const struct driver_interfacekit ph_884 = ifkit(8, 8, 4, 0, 0); |
64 | static const struct driver_interfacekit ph_088 = ifkit(0, 8, 8, 1, 0); | ||
65 | static const struct driver_interfacekit ph_01616 = ifkit(0, 16, 16, 0, 0); | ||
61 | 66 | ||
62 | static unsigned long device_no; | 67 | static unsigned long device_no; |
63 | 68 | ||
@@ -77,6 +82,7 @@ struct interfacekit { | |||
77 | dma_addr_t data_dma; | 82 | dma_addr_t data_dma; |
78 | 83 | ||
79 | struct work_struct do_notify; | 84 | struct work_struct do_notify; |
85 | struct work_struct do_resubmit; | ||
80 | unsigned long input_events; | 86 | unsigned long input_events; |
81 | unsigned long sensor_events; | 87 | unsigned long sensor_events; |
82 | }; | 88 | }; |
@@ -84,8 +90,10 @@ struct interfacekit { | |||
84 | static struct usb_device_id id_table[] = { | 90 | static struct usb_device_id id_table[] = { |
85 | {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT004), | 91 | {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT004), |
86 | .driver_info = (kernel_ulong_t)&ph_004}, | 92 | .driver_info = (kernel_ulong_t)&ph_004}, |
87 | {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT888), | 93 | {USB_DEVICE_VER(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT888, 0, 0x814), |
88 | .driver_info = (kernel_ulong_t)&ph_888}, | 94 | .driver_info = (kernel_ulong_t)&ph_888o}, |
95 | {USB_DEVICE_VER(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT888, 0x0815, 0xffff), | ||
96 | .driver_info = (kernel_ulong_t)&ph_888n}, | ||
89 | {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT047), | 97 | {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT047), |
90 | .driver_info = (kernel_ulong_t)&ph_047}, | 98 | .driver_info = (kernel_ulong_t)&ph_047}, |
91 | {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT088), | 99 | {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT088), |
@@ -98,16 +106,11 @@ static struct usb_device_id id_table[] = { | |||
98 | }; | 106 | }; |
99 | MODULE_DEVICE_TABLE(usb, id_table); | 107 | MODULE_DEVICE_TABLE(usb, id_table); |
100 | 108 | ||
101 | static int change_outputs(struct interfacekit *kit, int output_num, int enable) | 109 | static int set_outputs(struct interfacekit *kit) |
102 | { | 110 | { |
103 | u8 *buffer; | 111 | u8 *buffer; |
104 | int retval; | 112 | int retval; |
105 | 113 | ||
106 | if (enable) | ||
107 | set_bit(output_num, &kit->outputs); | ||
108 | else | ||
109 | clear_bit(output_num, &kit->outputs); | ||
110 | |||
111 | buffer = kzalloc(4, GFP_KERNEL); | 114 | buffer = kzalloc(4, GFP_KERNEL); |
112 | if (!buffer) { | 115 | if (!buffer) { |
113 | dev_err(&kit->udev->dev, "%s - out of memory\n", __FUNCTION__); | 116 | dev_err(&kit->udev->dev, "%s - out of memory\n", __FUNCTION__); |
@@ -127,6 +130,9 @@ static int change_outputs(struct interfacekit *kit, int output_num, int enable) | |||
127 | retval); | 130 | retval); |
128 | kfree(buffer); | 131 | kfree(buffer); |
129 | 132 | ||
133 | if (kit->ifkit->amnesiac) | ||
134 | schedule_delayed_work(&kit->do_resubmit, HZ / 2); | ||
135 | |||
130 | return retval < 0 ? retval : 0; | 136 | return retval < 0 ? retval : 0; |
131 | } | 137 | } |
132 | 138 | ||
@@ -399,19 +405,29 @@ static void do_notify(void *data) | |||
399 | } | 405 | } |
400 | } | 406 | } |
401 | 407 | ||
408 | static void do_resubmit(void *data) | ||
409 | { | ||
410 | set_outputs(data); | ||
411 | } | ||
412 | |||
402 | #define show_set_output(value) \ | 413 | #define show_set_output(value) \ |
403 | static ssize_t set_output##value(struct device *dev, \ | 414 | static ssize_t set_output##value(struct device *dev, \ |
404 | struct device_attribute *attr, \ | 415 | struct device_attribute *attr, \ |
405 | const char *buf, size_t count) \ | 416 | const char *buf, size_t count) \ |
406 | { \ | 417 | { \ |
407 | struct interfacekit *kit = dev_get_drvdata(dev); \ | 418 | struct interfacekit *kit = dev_get_drvdata(dev); \ |
408 | int enabled; \ | 419 | int enable; \ |
409 | int retval; \ | 420 | int retval; \ |
410 | \ | 421 | \ |
411 | if (sscanf(buf, "%d", &enabled) < 1) \ | 422 | if (sscanf(buf, "%d", &enable) < 1) \ |
412 | return -EINVAL; \ | 423 | return -EINVAL; \ |
413 | \ | 424 | \ |
414 | retval = change_outputs(kit, value - 1, enabled); \ | 425 | if (enable) \ |
426 | set_bit(value - 1, &kit->outputs); \ | ||
427 | else \ | ||
428 | clear_bit(value - 1, &kit->outputs); \ | ||
429 | \ | ||
430 | retval = set_outputs(kit); \ | ||
415 | \ | 431 | \ |
416 | return retval ? retval : count; \ | 432 | return retval ? retval : count; \ |
417 | } \ | 433 | } \ |
@@ -560,6 +576,7 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic | |||
560 | kit->udev = usb_get_dev(dev); | 576 | kit->udev = usb_get_dev(dev); |
561 | kit->intf = intf; | 577 | kit->intf = intf; |
562 | INIT_WORK(&kit->do_notify, do_notify, kit); | 578 | INIT_WORK(&kit->do_notify, do_notify, kit); |
579 | INIT_WORK(&kit->do_resubmit, do_resubmit, kit); | ||
563 | usb_fill_int_urb(kit->irq, kit->udev, pipe, kit->data, | 580 | usb_fill_int_urb(kit->irq, kit->udev, pipe, kit->data, |
564 | maxp > URB_INT_SIZE ? URB_INT_SIZE : maxp, | 581 | maxp > URB_INT_SIZE ? URB_INT_SIZE : maxp, |
565 | interfacekit_irq, kit, endpoint->bInterval); | 582 | interfacekit_irq, kit, endpoint->bInterval); |
@@ -663,6 +680,7 @@ static void interfacekit_disconnect(struct usb_interface *interface) | |||
663 | usb_buffer_free(kit->udev, URB_INT_SIZE, kit->data, kit->data_dma); | 680 | usb_buffer_free(kit->udev, URB_INT_SIZE, kit->data, kit->data_dma); |
664 | 681 | ||
665 | cancel_delayed_work(&kit->do_notify); | 682 | cancel_delayed_work(&kit->do_notify); |
683 | cancel_delayed_work(&kit->do_resubmit); | ||
666 | 684 | ||
667 | for (i=0; i<kit->ifkit->outputs; i++) | 685 | for (i=0; i<kit->ifkit->outputs; i++) |
668 | device_remove_file(kit->dev, &dev_output_attrs[i]); | 686 | device_remove_file(kit->dev, &dev_output_attrs[i]); |
diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c index 9b97aa6384c7..9c0eacf7055c 100644 --- a/drivers/usb/net/asix.c +++ b/drivers/usb/net/asix.c | |||
@@ -1456,6 +1456,10 @@ static const struct usb_device_id products [] = { | |||
1456 | USB_DEVICE (0x07d1, 0x3c05), | 1456 | USB_DEVICE (0x07d1, 0x3c05), |
1457 | .driver_info = (unsigned long) &ax88772_info, | 1457 | .driver_info = (unsigned long) &ax88772_info, |
1458 | }, { | 1458 | }, { |
1459 | // DLink DUB-E100 H/W Ver B1 Alternate | ||
1460 | USB_DEVICE (0x2001, 0x3c05), | ||
1461 | .driver_info = (unsigned long) &ax88772_info, | ||
1462 | }, { | ||
1459 | // Linksys USB1000 | 1463 | // Linksys USB1000 |
1460 | USB_DEVICE (0x1737, 0x0039), | 1464 | USB_DEVICE (0x1737, 0x0039), |
1461 | .driver_info = (unsigned long) &ax88178_info, | 1465 | .driver_info = (unsigned long) &ax88178_info, |
diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c index def3bb8e2290..544d41fe9b92 100644 --- a/drivers/usb/net/kaweth.c +++ b/drivers/usb/net/kaweth.c | |||
@@ -165,6 +165,7 @@ static struct usb_device_id usb_klsi_table[] = { | |||
165 | { USB_DEVICE(0x1645, 0x0005) }, /* Entrega E45 */ | 165 | { USB_DEVICE(0x1645, 0x0005) }, /* Entrega E45 */ |
166 | { USB_DEVICE(0x1645, 0x0008) }, /* Entrega USB Ethernet Adapter */ | 166 | { USB_DEVICE(0x1645, 0x0008) }, /* Entrega USB Ethernet Adapter */ |
167 | { USB_DEVICE(0x1645, 0x8005) }, /* PortGear Ethernet Adapter */ | 167 | { USB_DEVICE(0x1645, 0x8005) }, /* PortGear Ethernet Adapter */ |
168 | { USB_DEVICE(0x1668, 0x0323) }, /* Actiontec USB Ethernet */ | ||
168 | { USB_DEVICE(0x2001, 0x4000) }, /* D-link DSB-650C */ | 169 | { USB_DEVICE(0x2001, 0x4000) }, /* D-link DSB-650C */ |
169 | {} /* Null terminator */ | 170 | {} /* Null terminator */ |
170 | }; | 171 | }; |
diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c index b8e25af13f02..918cf5a77c08 100644 --- a/drivers/usb/net/pegasus.c +++ b/drivers/usb/net/pegasus.c | |||
@@ -45,7 +45,7 @@ | |||
45 | /* | 45 | /* |
46 | * Version Information | 46 | * Version Information |
47 | */ | 47 | */ |
48 | #define DRIVER_VERSION "v0.6.13 (2005/11/13)" | 48 | #define DRIVER_VERSION "v0.6.14 (2006/09/27)" |
49 | #define DRIVER_AUTHOR "Petko Manolov <petkan@users.sourceforge.net>" | 49 | #define DRIVER_AUTHOR "Petko Manolov <petkan@users.sourceforge.net>" |
50 | #define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver" | 50 | #define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver" |
51 | 51 | ||
@@ -339,7 +339,7 @@ static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd) | |||
339 | } | 339 | } |
340 | fail: | 340 | fail: |
341 | if (netif_msg_drv(pegasus)) | 341 | if (netif_msg_drv(pegasus)) |
342 | dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__); | 342 | dev_warn(&pegasus->intf->dev, "%s failed\n", __FUNCTION__); |
343 | 343 | ||
344 | return ret; | 344 | return ret; |
345 | } | 345 | } |
@@ -376,7 +376,7 @@ static int write_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 regd) | |||
376 | 376 | ||
377 | fail: | 377 | fail: |
378 | if (netif_msg_drv(pegasus)) | 378 | if (netif_msg_drv(pegasus)) |
379 | dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__); | 379 | dev_warn(&pegasus->intf->dev, "%s failed\n", __FUNCTION__); |
380 | return -ETIMEDOUT; | 380 | return -ETIMEDOUT; |
381 | } | 381 | } |
382 | 382 | ||
@@ -413,7 +413,7 @@ static int read_eprom_word(pegasus_t * pegasus, __u8 index, __u16 * retdata) | |||
413 | 413 | ||
414 | fail: | 414 | fail: |
415 | if (netif_msg_drv(pegasus)) | 415 | if (netif_msg_drv(pegasus)) |
416 | dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__); | 416 | dev_warn(&pegasus->intf->dev, "%s failed\n", __FUNCTION__); |
417 | return -ETIMEDOUT; | 417 | return -ETIMEDOUT; |
418 | } | 418 | } |
419 | 419 | ||
@@ -461,7 +461,7 @@ static int write_eprom_word(pegasus_t * pegasus, __u8 index, __u16 data) | |||
461 | return ret; | 461 | return ret; |
462 | fail: | 462 | fail: |
463 | if (netif_msg_drv(pegasus)) | 463 | if (netif_msg_drv(pegasus)) |
464 | dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__); | 464 | dev_warn(&pegasus->intf->dev, "%s failed\n", __FUNCTION__); |
465 | return -ETIMEDOUT; | 465 | return -ETIMEDOUT; |
466 | } | 466 | } |
467 | #endif /* PEGASUS_WRITE_EEPROM */ | 467 | #endif /* PEGASUS_WRITE_EEPROM */ |
@@ -481,8 +481,12 @@ static void set_ethernet_addr(pegasus_t * pegasus) | |||
481 | { | 481 | { |
482 | __u8 node_id[6]; | 482 | __u8 node_id[6]; |
483 | 483 | ||
484 | get_node_id(pegasus, node_id); | 484 | if (pegasus->features & PEGASUS_II) { |
485 | set_registers(pegasus, EthID, sizeof (node_id), node_id); | 485 | get_registers(pegasus, 0x10, sizeof(node_id), node_id); |
486 | } else { | ||
487 | get_node_id(pegasus, node_id); | ||
488 | set_registers(pegasus, EthID, sizeof (node_id), node_id); | ||
489 | } | ||
486 | memcpy(pegasus->net->dev_addr, node_id, sizeof (node_id)); | 490 | memcpy(pegasus->net->dev_addr, node_id, sizeof (node_id)); |
487 | } | 491 | } |
488 | 492 | ||
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index 6286aba86fae..d954ec34b018 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c | |||
@@ -214,14 +214,14 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b | |||
214 | return (0); | 214 | return (0); |
215 | } | 215 | } |
216 | 216 | ||
217 | spin_lock(&port->lock); | 217 | spin_lock_bh(&port->lock); |
218 | if (port->write_urb_busy) { | 218 | if (port->write_urb_busy) { |
219 | spin_unlock(&port->lock); | 219 | spin_unlock_bh(&port->lock); |
220 | dbg("%s - already writing", __FUNCTION__); | 220 | dbg("%s - already writing", __FUNCTION__); |
221 | return 0; | 221 | return 0; |
222 | } | 222 | } |
223 | port->write_urb_busy = 1; | 223 | port->write_urb_busy = 1; |
224 | spin_unlock(&port->lock); | 224 | spin_unlock_bh(&port->lock); |
225 | 225 | ||
226 | spin_lock_irqsave(&priv->lock, flags); | 226 | spin_lock_irqsave(&priv->lock, flags); |
227 | 227 | ||
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 1f7b72553f37..e774a27c6c98 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
@@ -344,6 +344,7 @@ static struct usb_device_id id_table_combined [] = { | |||
344 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2102_PID) }, | 344 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2102_PID) }, |
345 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2103_PID) }, | 345 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2103_PID) }, |
346 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2104_PID) }, | 346 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2104_PID) }, |
347 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2106_PID) }, | ||
347 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2201_1_PID) }, | 348 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2201_1_PID) }, |
348 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2201_2_PID) }, | 349 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2201_2_PID) }, |
349 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2202_1_PID) }, | 350 | { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2202_1_PID) }, |
@@ -507,6 +508,9 @@ static struct usb_device_id id_table_combined [] = { | |||
507 | { USB_DEVICE(FTDI_VID, FTDI_THORLABS_PID) }, | 508 | { USB_DEVICE(FTDI_VID, FTDI_THORLABS_PID) }, |
508 | { USB_DEVICE(TESTO_VID, TESTO_USB_INTERFACE_PID) }, | 509 | { USB_DEVICE(TESTO_VID, TESTO_USB_INTERFACE_PID) }, |
509 | { USB_DEVICE(FTDI_VID, FTDI_GAMMA_SCOUT_PID) }, | 510 | { USB_DEVICE(FTDI_VID, FTDI_GAMMA_SCOUT_PID) }, |
511 | { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13M_PID) }, | ||
512 | { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13S_PID) }, | ||
513 | { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13U_PID) }, | ||
510 | { }, /* Optional parameter entry */ | 514 | { }, /* Optional parameter entry */ |
511 | { } /* Terminating entry */ | 515 | { } /* Terminating entry */ |
512 | }; | 516 | }; |
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index 77299996f7ee..f0edb87d2dd5 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h | |||
@@ -111,6 +111,7 @@ | |||
111 | #define SEALEVEL_2102_PID 0x2102 /* SeaLINK+485 (2102) */ | 111 | #define SEALEVEL_2102_PID 0x2102 /* SeaLINK+485 (2102) */ |
112 | #define SEALEVEL_2103_PID 0x2103 /* SeaLINK+232I (2103) */ | 112 | #define SEALEVEL_2103_PID 0x2103 /* SeaLINK+232I (2103) */ |
113 | #define SEALEVEL_2104_PID 0x2104 /* SeaLINK+485I (2104) */ | 113 | #define SEALEVEL_2104_PID 0x2104 /* SeaLINK+485I (2104) */ |
114 | #define SEALEVEL_2106_PID 0x9020 /* SeaLINK+422 (2106) */ | ||
114 | #define SEALEVEL_2201_1_PID 0x2211 /* SeaPORT+2/232 (2201) Port 1 */ | 115 | #define SEALEVEL_2201_1_PID 0x2211 /* SeaPORT+2/232 (2201) Port 1 */ |
115 | #define SEALEVEL_2201_2_PID 0x2221 /* SeaPORT+2/232 (2201) Port 2 */ | 116 | #define SEALEVEL_2201_2_PID 0x2221 /* SeaPORT+2/232 (2201) Port 2 */ |
116 | #define SEALEVEL_2202_1_PID 0x2212 /* SeaPORT+2/485 (2202) Port 1 */ | 117 | #define SEALEVEL_2202_1_PID 0x2212 /* SeaPORT+2/485 (2202) Port 1 */ |
@@ -472,6 +473,15 @@ | |||
472 | */ | 473 | */ |
473 | #define FTDI_GAMMA_SCOUT_PID 0xD678 /* Gamma Scout online */ | 474 | #define FTDI_GAMMA_SCOUT_PID 0xD678 /* Gamma Scout online */ |
474 | 475 | ||
476 | /* | ||
477 | * Tactrix OpenPort (ECU) devices. | ||
478 | * OpenPort 1.3M submitted by Donour Sizemore. | ||
479 | * OpenPort 1.3S and 1.3U submitted by Ian Abbott. | ||
480 | */ | ||
481 | #define FTDI_TACTRIX_OPENPORT_13M_PID 0xCC48 /* OpenPort 1.3 Mitsubishi */ | ||
482 | #define FTDI_TACTRIX_OPENPORT_13S_PID 0xCC49 /* OpenPort 1.3 Subaru */ | ||
483 | #define FTDI_TACTRIX_OPENPORT_13U_PID 0xCC4A /* OpenPort 1.3 Universal */ | ||
484 | |||
475 | /* Commands */ | 485 | /* Commands */ |
476 | #define FTDI_SIO_RESET 0 /* Reset the port */ | 486 | #define FTDI_SIO_RESET 0 /* Reset the port */ |
477 | #define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ | 487 | #define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ |
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 172713556393..21cbaa0fb96b 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c | |||
@@ -175,14 +175,14 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char * | |||
175 | 175 | ||
176 | /* only do something if we have a bulk out endpoint */ | 176 | /* only do something if we have a bulk out endpoint */ |
177 | if (serial->num_bulk_out) { | 177 | if (serial->num_bulk_out) { |
178 | spin_lock(&port->lock); | 178 | spin_lock_bh(&port->lock); |
179 | if (port->write_urb_busy) { | 179 | if (port->write_urb_busy) { |
180 | spin_unlock(&port->lock); | 180 | spin_unlock_bh(&port->lock); |
181 | dbg("%s - already writing", __FUNCTION__); | 181 | dbg("%s - already writing", __FUNCTION__); |
182 | return 0; | 182 | return 0; |
183 | } | 183 | } |
184 | port->write_urb_busy = 1; | 184 | port->write_urb_busy = 1; |
185 | spin_unlock(&port->lock); | 185 | spin_unlock_bh(&port->lock); |
186 | 186 | ||
187 | count = (count > port->bulk_out_size) ? port->bulk_out_size : count; | 187 | count = (count > port->bulk_out_size) ? port->bulk_out_size : count; |
188 | 188 | ||
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index bfc6998cd16f..cbc725a6c58e 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c | |||
@@ -479,6 +479,7 @@ static struct usb_device_id ipaq_id_table [] = { | |||
479 | { USB_DEVICE(0x0BB4, 0x0A9D) }, /* SmartPhone USB Sync */ | 479 | { USB_DEVICE(0x0BB4, 0x0A9D) }, /* SmartPhone USB Sync */ |
480 | { USB_DEVICE(0x0BB4, 0x0A9E) }, /* SmartPhone USB Sync */ | 480 | { USB_DEVICE(0x0BB4, 0x0A9E) }, /* SmartPhone USB Sync */ |
481 | { USB_DEVICE(0x0BB4, 0x0A9F) }, /* SmartPhone USB Sync */ | 481 | { USB_DEVICE(0x0BB4, 0x0A9F) }, /* SmartPhone USB Sync */ |
482 | { USB_DEVICE(0x0BB4, 0x0BCE) }, /* "High Tech Computer Corp" */ | ||
482 | { USB_DEVICE(0x0BF8, 0x1001) }, /* Fujitsu Siemens Computers USB Sync */ | 483 | { USB_DEVICE(0x0BF8, 0x1001) }, /* Fujitsu Siemens Computers USB Sync */ |
483 | { USB_DEVICE(0x0C44, 0x03A2) }, /* Motorola iDEN Smartphone */ | 484 | { USB_DEVICE(0x0C44, 0x03A2) }, /* Motorola iDEN Smartphone */ |
484 | { USB_DEVICE(0x0C8E, 0x6000) }, /* Cesscom Luxian Series */ | 485 | { USB_DEVICE(0x0C8E, 0x6000) }, /* Cesscom Luxian Series */ |
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c index 87306cb6f9f5..812bc213a963 100644 --- a/drivers/usb/serial/ipw.c +++ b/drivers/usb/serial/ipw.c | |||
@@ -394,14 +394,14 @@ static int ipw_write(struct usb_serial_port *port, const unsigned char *buf, int | |||
394 | return 0; | 394 | return 0; |
395 | } | 395 | } |
396 | 396 | ||
397 | spin_lock(&port->lock); | 397 | spin_lock_bh(&port->lock); |
398 | if (port->write_urb_busy) { | 398 | if (port->write_urb_busy) { |
399 | spin_unlock(&port->lock); | 399 | spin_unlock_bh(&port->lock); |
400 | dbg("%s - already writing", __FUNCTION__); | 400 | dbg("%s - already writing", __FUNCTION__); |
401 | return 0; | 401 | return 0; |
402 | } | 402 | } |
403 | port->write_urb_busy = 1; | 403 | port->write_urb_busy = 1; |
404 | spin_unlock(&port->lock); | 404 | spin_unlock_bh(&port->lock); |
405 | 405 | ||
406 | count = min(count, port->bulk_out_size); | 406 | count = min(count, port->bulk_out_size); |
407 | memcpy(port->bulk_out_buffer, buf, count); | 407 | memcpy(port->bulk_out_buffer, buf, count); |
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index 1738b0b6a376..1b348df388ed 100644 --- a/drivers/usb/serial/ir-usb.c +++ b/drivers/usb/serial/ir-usb.c | |||
@@ -342,14 +342,14 @@ static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int | |||
342 | if (count == 0) | 342 | if (count == 0) |
343 | return 0; | 343 | return 0; |
344 | 344 | ||
345 | spin_lock(&port->lock); | 345 | spin_lock_bh(&port->lock); |
346 | if (port->write_urb_busy) { | 346 | if (port->write_urb_busy) { |
347 | spin_unlock(&port->lock); | 347 | spin_unlock_bh(&port->lock); |
348 | dbg("%s - already writing", __FUNCTION__); | 348 | dbg("%s - already writing", __FUNCTION__); |
349 | return 0; | 349 | return 0; |
350 | } | 350 | } |
351 | port->write_urb_busy = 1; | 351 | port->write_urb_busy = 1; |
352 | spin_unlock(&port->lock); | 352 | spin_unlock_bh(&port->lock); |
353 | 353 | ||
354 | transfer_buffer = port->write_urb->transfer_buffer; | 354 | transfer_buffer = port->write_urb->transfer_buffer; |
355 | transfer_size = min(count, port->bulk_out_size - 1); | 355 | transfer_size = min(count, port->bulk_out_size - 1); |
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index 49b8dc039d1f..59e777f1e8fd 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c | |||
@@ -518,13 +518,13 @@ static int keyspan_pda_write(struct usb_serial_port *port, | |||
518 | the TX urb is in-flight (wait until it completes) | 518 | the TX urb is in-flight (wait until it completes) |
519 | the device is full (wait until it says there is room) | 519 | the device is full (wait until it says there is room) |
520 | */ | 520 | */ |
521 | spin_lock(&port->lock); | 521 | spin_lock_bh(&port->lock); |
522 | if (port->write_urb_busy || priv->tx_throttled) { | 522 | if (port->write_urb_busy || priv->tx_throttled) { |
523 | spin_unlock(&port->lock); | 523 | spin_unlock_bh(&port->lock); |
524 | return 0; | 524 | return 0; |
525 | } | 525 | } |
526 | port->write_urb_busy = 1; | 526 | port->write_urb_busy = 1; |
527 | spin_unlock(&port->lock); | 527 | spin_unlock_bh(&port->lock); |
528 | 528 | ||
529 | /* At this point the URB is in our control, nobody else can submit it | 529 | /* At this point the URB is in our control, nobody else can submit it |
530 | again (the only sudden transition was the one from EINPROGRESS to | 530 | again (the only sudden transition was the one from EINPROGRESS to |
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index e49f40913c27..a764ff4e326c 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c | |||
@@ -256,14 +256,14 @@ static int omninet_write (struct usb_serial_port *port, const unsigned char *buf | |||
256 | return (0); | 256 | return (0); |
257 | } | 257 | } |
258 | 258 | ||
259 | spin_lock(&wport->lock); | 259 | spin_lock_bh(&wport->lock); |
260 | if (wport->write_urb_busy) { | 260 | if (wport->write_urb_busy) { |
261 | spin_unlock(&wport->lock); | 261 | spin_unlock_bh(&wport->lock); |
262 | dbg("%s - already writing", __FUNCTION__); | 262 | dbg("%s - already writing", __FUNCTION__); |
263 | return 0; | 263 | return 0; |
264 | } | 264 | } |
265 | wport->write_urb_busy = 1; | 265 | wport->write_urb_busy = 1; |
266 | spin_unlock(&wport->lock); | 266 | spin_unlock_bh(&wport->lock); |
267 | 267 | ||
268 | count = (count > OMNINET_BULKOUTSIZE) ? OMNINET_BULKOUTSIZE : count; | 268 | count = (count > OMNINET_BULKOUTSIZE) ? OMNINET_BULKOUTSIZE : count; |
269 | 269 | ||
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 1036d436ed23..9c18173e33fb 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c | |||
@@ -82,6 +82,7 @@ static struct usb_device_id id_table [] = { | |||
82 | { USB_DEVICE(DATAPILOT_U2_VENDOR_ID, DATAPILOT_U2_PRODUCT_ID) }, | 82 | { USB_DEVICE(DATAPILOT_U2_VENDOR_ID, DATAPILOT_U2_PRODUCT_ID) }, |
83 | { USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) }, | 83 | { USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) }, |
84 | { USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID) }, | 84 | { USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID) }, |
85 | { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ID) }, | ||
85 | { } /* Terminating entry */ | 86 | { } /* Terminating entry */ |
86 | }; | 87 | }; |
87 | 88 | ||
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index 762cc290ef58..65a5039665e7 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h | |||
@@ -93,3 +93,7 @@ | |||
93 | /* Alcor Micro Corp. USB 2.0 TO RS-232 */ | 93 | /* Alcor Micro Corp. USB 2.0 TO RS-232 */ |
94 | #define ALCOR_VENDOR_ID 0x058F | 94 | #define ALCOR_VENDOR_ID 0x058F |
95 | #define ALCOR_PRODUCT_ID 0x9720 | 95 | #define ALCOR_PRODUCT_ID 0x9720 |
96 | |||
97 | /* Huawei E620 UMTS/HSDPA card (ID: 12d1:1001) */ | ||
98 | #define HUAWEI_VENDOR_ID 0x12d1 | ||
99 | #define HUAWEI_PRODUCT_ID 0x1001 | ||
diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c index 789771ecdb11..1e07dfad6853 100644 --- a/drivers/usb/serial/safe_serial.c +++ b/drivers/usb/serial/safe_serial.c | |||
@@ -298,14 +298,14 @@ static int safe_write (struct usb_serial_port *port, const unsigned char *buf, i | |||
298 | dbg ("%s - write request of 0 bytes", __FUNCTION__); | 298 | dbg ("%s - write request of 0 bytes", __FUNCTION__); |
299 | return (0); | 299 | return (0); |
300 | } | 300 | } |
301 | spin_lock(&port->lock); | 301 | spin_lock_bh(&port->lock); |
302 | if (port->write_urb_busy) { | 302 | if (port->write_urb_busy) { |
303 | spin_unlock(&port->lock); | 303 | spin_unlock_bh(&port->lock); |
304 | dbg("%s - already writing", __FUNCTION__); | 304 | dbg("%s - already writing", __FUNCTION__); |
305 | return 0; | 305 | return 0; |
306 | } | 306 | } |
307 | port->write_urb_busy = 1; | 307 | port->write_urb_busy = 1; |
308 | spin_unlock(&port->lock); | 308 | spin_unlock_bh(&port->lock); |
309 | 309 | ||
310 | packet_length = port->bulk_out_size; // get max packetsize | 310 | packet_length = port->bulk_out_size; // get max packetsize |
311 | 311 | ||
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 86e48c42d6af..422a4b288e34 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig | |||
@@ -8,8 +8,7 @@ comment "may also be needed; see USB_STORAGE Help for more information" | |||
8 | 8 | ||
9 | config USB_STORAGE | 9 | config USB_STORAGE |
10 | tristate "USB Mass Storage support" | 10 | tristate "USB Mass Storage support" |
11 | depends on USB | 11 | depends on USB && SCSI |
12 | select SCSI | ||
13 | ---help--- | 12 | ---help--- |
14 | Say Y here if you want to connect USB mass storage devices to your | 13 | Say Y here if you want to connect USB mass storage devices to your |
15 | computer's USB port. This is the driver you need for USB | 14 | computer's USB port. This is the driver you need for USB |
@@ -18,7 +17,7 @@ config USB_STORAGE | |||
18 | similar devices. This driver may also be used for some cameras | 17 | similar devices. This driver may also be used for some cameras |
19 | and card readers. | 18 | and card readers. |
20 | 19 | ||
21 | This option 'selects' (turns on, enables) 'SCSI', but you | 20 | This option depends on 'SCSI' support being enabled, but you |
22 | probably also need 'SCSI device support: SCSI disk support' | 21 | probably also need 'SCSI device support: SCSI disk support' |
23 | (BLK_DEV_SD) for most USB storage devices. | 22 | (BLK_DEV_SD) for most USB storage devices. |
24 | 23 | ||
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 40bf159f7d54..c9a8d50106d1 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h | |||
@@ -152,6 +152,13 @@ UNUSUAL_DEV( 0x0421, 0x042e, 0x0100, 0x0100, | |||
152 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 152 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
153 | US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ), | 153 | US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ), |
154 | 154 | ||
155 | /* Reported by Jon Hart <Jon.Hart@web.de> */ | ||
156 | UNUSUAL_DEV( 0x0421, 0x0434, 0x0100, 0x0100, | ||
157 | "Nokia", | ||
158 | "E60", | ||
159 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
160 | US_FL_FIX_CAPACITY | US_FL_IGNORE_RESIDUE ), | ||
161 | |||
155 | /* Reported by Sumedha Swamy <sumedhaswamy@gmail.com> and | 162 | /* Reported by Sumedha Swamy <sumedhaswamy@gmail.com> and |
156 | * Einar Th. Einarsson <einarthered@gmail.com> */ | 163 | * Einar Th. Einarsson <einarthered@gmail.com> */ |
157 | UNUSUAL_DEV( 0x0421, 0x0444, 0x0100, 0x0100, | 164 | UNUSUAL_DEV( 0x0421, 0x0444, 0x0100, 0x0100, |
@@ -1277,6 +1284,13 @@ UNUSUAL_DEV( 0x0fce, 0xe031, 0x0000, 0x0000, | |||
1277 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 1284 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
1278 | US_FL_FIX_CAPACITY ), | 1285 | US_FL_FIX_CAPACITY ), |
1279 | 1286 | ||
1287 | /* Reported by Jan Mate <mate@fiit.stuba.sk> */ | ||
1288 | UNUSUAL_DEV( 0x0fce, 0xe030, 0x0000, 0x0000, | ||
1289 | "Sony Ericsson", | ||
1290 | "P990i", | ||
1291 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
1292 | US_FL_FIX_CAPACITY ), | ||
1293 | |||
1280 | /* Reported by Kevin Cernekee <kpc-usbdev@gelato.uiuc.edu> | 1294 | /* Reported by Kevin Cernekee <kpc-usbdev@gelato.uiuc.edu> |
1281 | * Tested on hardware version 1.10. | 1295 | * Tested on hardware version 1.10. |
1282 | * Entry is needed only for the initializer function override. | 1296 | * Entry is needed only for the initializer function override. |