I recently ran up against a scenario in which khubd was awakened and
started interfering during a port reset. (Don't ask me why this has never
turned up before.) Although this was a possibility I had considered some
time ago, no protections were ever added to the kernel to deal with it.
Anyway, here's a patch. I don't want to submit it yet because I've got
other patches which ought to be accepted first. But people's comments are
welcome. The patch simply makes khubd ignore events for ports which are
undergoing a reset. The idea is that if anything serious has happened,
usb_reset_device will realize it and will force a logical disconnect (or
else khubd will catch it later on). However this reasoning may not be
entirely correct, and I would appreciate external feedback.
Alan Stern
===== drivers/usb/core/hub.c 1.215 vs edited =====
--- 1.215/drivers/usb/core/hub.c 2004-11-27 18:14:57 -05:00
+++ edited/drivers/usb/core/hub.c 2004-12-17 11:56:29 -05:00
@@ -2599,6 +2599,8 @@
/* deal with port status changes */
for (i = 0; i < hub->descriptor->bNbrPorts; i++) {
+ if (test_bit(i, hub->busy_bits))
+ continue;
connect_change = test_bit(i, hub->change_bits);
if (!test_and_clear_bit(i+1, hub->event_bits) &&
!connect_change)
@@ -2859,6 +2861,7 @@
{
struct usb_device *parent = udev->parent;
struct usb_device_descriptor descriptor = udev->descriptor;
+ struct usb_hub *hub;
int i, ret = 0, port = -1;
int udev_is_a_hub = 0;
@@ -2895,6 +2898,8 @@
hub_pre_reset(udev);
}
+ hub = usb_get_intfdata(parent->actconfig->interface[0]);
+ set_bit(port, hub->busy_bits);
for (i = 0; i < SET_CONFIG_TRIES; ++i) {
/* ep0 maxpacket size may change; let the HCD know about it.
@@ -2904,6 +2909,7 @@
if (ret >= 0)
break;
}
+ clear_bit(port, hub->busy_bits);
if (ret < 0)
goto re_enumerate;
===== drivers/usb/core/hub.h 1.41 vs edited =====
--- 1.41/drivers/usb/core/hub.h 2004-10-11 13:51:58 -04:00
+++ edited/drivers/usb/core/hub.h 2004-12-17 11:50:52 -05:00
@@ -205,6 +205,7 @@
unsigned long event_bits[1]; /* status change bitmask */
unsigned long change_bits[1]; /* ports with logical connect
status change */
+ unsigned long busy_bits[1]; /* ports being reset */
#if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */
#error event_bits[] is too short!
#endif
-------------------------------------------------------
SF email is sponsored by - The IT Product Guide
Read honest & candid reviews on hundreds of IT Products from real users.
Discover which products truly live up to the hype. Start reading now.
http://productguide.itmanagersjournal.com/
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel