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

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

diff -u --recursive --new-file v2.3.24/linux/drivers/usb/hub.c linux/drivers/usb/hub.c
@@ -22,7 +22,6 @@
 
 /* Wakes up khubd */
 static spinlock_t hub_event_lock = SPIN_LOCK_UNLOCKED;
-static spinlock_t hub_list_lock = SPIN_LOCK_UNLOCKED;
 
 static LIST_HEAD(hub_event_list);	/* List of hubs needing servicing */
 static LIST_HEAD(hub_list);		/* List containing all of the hubs (for cleanup) */
@@ -105,9 +104,6 @@
 	struct usb_hub_status *hubsts;
 	int i;
 
-	/* Set it to the first configuration */
-	usb_set_configuration(dev, dev->config[0].bConfigurationValue);
-
 	/* Get the length first */
 	if (usb_get_hub_descriptor(dev, buffer, 4))
 		return -1;
@@ -188,7 +184,7 @@
 	return 0;
 }
 
-static int hub_probe(struct usb_device *dev)
+static void * hub_probe(struct usb_device *dev, unsigned int i)
 {
 	struct usb_interface_descriptor *interface;
 	struct usb_endpoint_descriptor *endpoint;
@@ -196,60 +192,50 @@
 	unsigned long flags;
 	int ret;
 
-	/* We don't handle multi-config hubs */
-	if (dev->descriptor.bNumConfigurations != 1)
-		return -1;
-
-	/* We don't handle multi-interface hubs */
-	if (dev->config[0].bNumInterfaces != 1)
-		return -1;
-
-	interface = &dev->config[0].interface[0].altsetting[0];
+	interface = &dev->actconfig->interface[i].altsetting[0];
 
 	/* Is it a hub? */
 	if (interface->bInterfaceClass != USB_CLASS_HUB)
-		return -1;
+		return NULL;
 
 	/* Some hubs have a subclass of 1, which AFAICT according to the */
 	/*  specs is not defined, but it works */
 	if ((interface->bInterfaceSubClass != 0) &&
 	    (interface->bInterfaceSubClass != 1))
-		return -1;
+		return NULL;
 
 	/* Multiple endpoints? What kind of mutant ninja-hub is this? */
 	if (interface->bNumEndpoints != 1)
-		return -1;
+		return NULL;
 
 	endpoint = &interface->endpoint[0];
 
 	/* Output endpoint? Curiousier and curiousier.. */
 	if (!(endpoint->bEndpointAddress & USB_DIR_IN))
-		return -1;
+		return NULL;
 
 	/* If it's not an interrupt endpoint, we'd better punt! */
 	if ((endpoint->bmAttributes & 3) != 3)
-		return -1;
+		return NULL;
 
 	/* We found a hub */
 	printk(KERN_INFO "USB hub found\n");
 
 	if ((hub = kmalloc(sizeof(*hub), GFP_KERNEL)) == NULL) {
 		printk(KERN_ERR "couldn't kmalloc hub struct\n");
-		return -1;
+		return NULL;
 	}
 
 	memset(hub, 0, sizeof(*hub));
 
-	dev->private = hub;
-
 	INIT_LIST_HEAD(&hub->event_list);
 	hub->dev = dev;
 
 	/* Record the new hub's existence */
-	spin_lock_irqsave(&hub_list_lock, flags);
+	spin_lock_irqsave(&hub_event_lock, flags);
 	INIT_LIST_HEAD(&hub->hub_list);
 	list_add(&hub->hub_list, &hub_list);
-	spin_unlock_irqrestore(&hub_list_lock, flags);
+	spin_unlock_irqrestore(&hub_event_lock, flags);
 
 	if (usb_hub_configure(hub) >= 0) {
 		hub->irqpipe = usb_rcvctrlpipe(dev, endpoint->bEndpointAddress);
@@ -258,20 +244,32 @@
 			hub, &hub->irq_handle);
 		if (ret) {
 			printk (KERN_WARNING "usb-hub: usb_request_irq failed (0x%x)\n", ret);
-			/* FIXME: need to free <hub> but first clean up its list. */
-			return -1;
+			/* free hub, but first clean up its list. */
+			spin_lock_irqsave(&hub_event_lock, flags);
+
+			/* Delete it and then reset it */
+			list_del(&hub->event_list);
+			INIT_LIST_HEAD(&hub->event_list);
+			list_del(&hub->hub_list);
+			INIT_LIST_HEAD(&hub->hub_list);
+
+			spin_unlock_irqrestore(&hub_event_lock, flags);
+
+			kfree(hub);
+
+			return NULL;
 		}
 
 		/* Wake up khubd */
 		wake_up(&khubd_wait);
 	}
 
-	return 0;
+	return hub;
 }
 
-static void hub_disconnect(struct usb_device *dev)
+static void hub_disconnect(struct usb_device *dev, void *ptr)
 {
-	struct usb_hub *hub = dev->private;
+	struct usb_hub *hub = ptr;
 	unsigned long flags;
 
 	spin_lock_irqsave(&hub_event_lock, flags);

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