patch-2.3.99-pre2 linux/drivers/usb/hub.c

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

diff -u --recursive --new-file v2.3.99-pre1/linux/drivers/usb/hub.c linux/drivers/usb/hub.c
@@ -4,8 +4,6 @@
  * (C) Copyright 1999 Linus Torvalds
  * (C) Copyright 1999 Johannes Erdfelt
  * (C) Copyright 1999 Gregory P. Smith
- *
- * $Id: hub.c,v 1.21 2000/01/16 21:19:44 acher Exp $
  */
 
 #include <linux/kernel.h>
@@ -75,31 +73,29 @@
  * the low-level driver that it wants to be re-activated,
  * or zero to say "I'm done".
  */
-static int hub_irq(int status, void *__buffer, int len, void *dev_id)
+static void hub_irq(struct urb *urb)
 {
-	struct usb_hub *hub = dev_id;
+	struct usb_hub *hub = (struct usb_hub *)urb->context;
 	unsigned long flags;
 
-	switch (status) {
-	case -ENODEV:
-		/* Just ignore it */
-		break;
-	case 0:
-		/* Something happened, let khubd figure it out */
-		if (waitqueue_active(&khubd_wait)) {
-			/* Add the hub to the event queue */
-			spin_lock_irqsave(&hub_event_lock, flags);
-			if (hub->event_list.next == &hub->event_list) {
-				list_add(&hub->event_list, &hub_event_list);
-				/* Wake up khubd */
-				wake_up(&khubd_wait);
-			}
-			spin_unlock_irqrestore(&hub_event_lock, flags);
-		}
-		break;
+	if (urb->status) {
+		if (urb->status != -ENOENT)
+			dbg("nonzero status in irq %d", urb->status);
+
+		return;
 	}
 
-	return 1;
+	/* Something happened, let khubd figure it out */
+	if (waitqueue_active(&khubd_wait)) {
+		/* Add the hub to the event queue */
+		spin_lock_irqsave(&hub_event_lock, flags);
+		if (hub->event_list.next == &hub->event_list) {
+			list_add(&hub->event_list, &hub_event_list);
+			/* Wake up khubd */
+			wake_up(&khubd_wait);
+		}
+		spin_unlock_irqrestore(&hub_event_lock, flags);
+	}
 }
 
 static void usb_hub_power_on(struct usb_hub *hub)
@@ -196,13 +192,14 @@
 	return 0;
 }
 
-static void * hub_probe(struct usb_device *dev, unsigned int i)
+static void *hub_probe(struct usb_device *dev, unsigned int i)
 {
 	struct usb_interface_descriptor *interface;
 	struct usb_endpoint_descriptor *endpoint;
 	struct usb_hub *hub;
 	unsigned long flags;
-	int ret;
+	unsigned int pipe;
+	int maxp, ret;
 
 	interface = &dev->actconfig->interface[i].altsetting[0];
 
@@ -233,7 +230,8 @@
 	/* We found a hub */
 	info("USB hub found");
 
-	if ((hub = kmalloc(sizeof(*hub), GFP_KERNEL)) == NULL) {
+	hub = kmalloc(sizeof(*hub), GFP_KERNEL);
+	if (!hub) {
 		err("couldn't kmalloc hub struct");
 		return NULL;
 	}
@@ -250,26 +248,24 @@
 	spin_unlock_irqrestore(&hub_event_lock, flags);
 
 	if (usb_hub_configure(hub) >= 0) {
-		hub->irqpipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
-		ret = usb_request_irq(dev, hub->irqpipe,
-			hub_irq, endpoint->bInterval,
-			hub, &hub->irq_handle);
-		if (ret) {
-			err("usb_request_irq failed (%d)", ret);
-			/* free hub, but first clean up its list. */
-			spin_lock_irqsave(&hub_event_lock, flags);
+		pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
+		maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
 
-			/* 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);
+		if (maxp > sizeof(hub->buffer))
+			maxp = sizeof(hub->buffer);
 
-			spin_unlock_irqrestore(&hub_event_lock, flags);
-
-			kfree(hub);
+		hub->urb = usb_alloc_urb(0);
+		if (!hub->urb) {
+			err("couldn't allocate interrupt urb");
+			goto fail;
+		}
 
-			return NULL;
+		FILL_INT_URB(hub->urb, dev, pipe, hub->buffer, maxp, hub_irq,
+			hub, endpoint->bInterval);
+		ret = usb_submit_urb(hub->urb);
+		if (ret) {
+			err("usb_submit_urb failed (%d)", ret);
+			goto fail;
 		}
 
 		/* Wake up khubd */
@@ -277,11 +273,27 @@
 	}
 
 	return hub;
+
+fail:
+	/* 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;
 }
 
 static void hub_disconnect(struct usb_device *dev, void *ptr)
 {
-	struct usb_hub *hub = ptr;
+	struct usb_hub *hub = (struct usb_hub *)ptr;
 	unsigned long flags;
 
 	spin_lock_irqsave(&hub_event_lock, flags);
@@ -294,8 +306,10 @@
 
 	spin_unlock_irqrestore(&hub_event_lock, flags);
 
-	if (hub->irq_handle) {
-		usb_release_irq(hub->dev, hub->irq_handle, hub->irqpipe);
+	if (hub->urb) {
+		usb_unlink_urb(hub->urb);
+		usb_free_urb(hub->urb);
+		hub->urb = NULL;
 	}
 
 	/* Free the memory */

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