patch-2.4.3 linux/drivers/usb/hub.c

Next file: linux/drivers/usb/hub.h
Previous file: linux/drivers/usb/devio.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.2/linux/drivers/usb/hub.c linux/drivers/usb/hub.c
@@ -146,6 +146,8 @@
 		return -1;
 	}
 
+	le16_to_cpus(&hub->descriptor->wHubCharacteristics);
+
 	hub->nports = dev->maxchild = hub->descriptor->bNbrPorts;
 	info("%d port%s detected", hub->nports, (hub->nports == 1) ? "" : "s");
 
@@ -291,6 +293,7 @@
 
 	INIT_LIST_HEAD(&hub->event_list);
 	hub->dev = dev;
+	init_MUTEX(&hub->khubd_sem);
 
 	/* Record the new hub's existence */
 	spin_lock_irqsave(&hub_event_lock, flags);
@@ -334,6 +337,9 @@
 
 	spin_unlock_irqrestore(&hub_event_lock, flags);
 
+	down(&hub->khubd_sem); /* Wait for khubd to leave this hub alone. */
+	up(&hub->khubd_sem);
+
 	if (hub->urb) {
 		usb_unlink_urb(hub->urb);
 		usb_free_urb(hub->urb);
@@ -545,6 +551,13 @@
 		return;
 	}
 
+	/* Some low speed devices have problems with the quick delay, so */
+	/*  be a bit pessimistic with those devices. RHbug #23670 */
+	if (portstatus & USB_PORT_STAT_LOW_SPEED) {
+		wait_ms(400);
+		delay = HUB_LONG_RESET_TIME;
+	}
+
 	down(&usb_address0_sem);
 
 	tempstr = kmalloc(1024, GFP_KERNEL);
@@ -639,7 +652,7 @@
 		spin_lock_irqsave(&hub_event_lock, flags);
 
 		if (list_empty(&hub_event_list))
-			goto he_unlock;
+			break;
 
 		/* Grab the next entry from the beginning of the list */
 		tmp = hub_event_list.next;
@@ -650,6 +663,7 @@
 		list_del(tmp);
 		INIT_LIST_HEAD(tmp);
 
+		down(&hub->khubd_sem); /* never blocks, we were on list */
 		spin_unlock_irqrestore(&hub_event_lock, flags);
 
 		if (hub->error) {
@@ -658,6 +672,7 @@
 			if (usb_hub_reset(hub)) {
 				err("error resetting hub %d - disconnecting", dev->devnum);
 				usb_hub_disconnect(dev);
+				up(&hub->khubd_sem);
 				continue;
 			}
 
@@ -733,9 +748,9 @@
                         	usb_hub_power_on(hub);
 			}
 		}
+		up(&hub->khubd_sem);
         } /* end while (1) */
 
-he_unlock:
 	spin_unlock_irqrestore(&hub_event_lock, flags);
 }
 
@@ -905,7 +920,7 @@
 			if (ret < 0)
 				err("unable to get device descriptor (error=%d)", ret);
 			else
-				err("USB device descriptor short read (expected %i, got %i)", sizeof(dev->descriptor), ret);
+				err("USB device descriptor short read (expected %Zi, got %i)", sizeof(dev->descriptor), ret);
         
 			clear_bit(dev->devnum, &dev->bus->devmap.devicemap);
 			dev->devnum = -1;

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)