ChangeSet 1.865.28.14, 2002/12/19 15:14:03-08:00, david-b@pacbell.net

[PATCH] usbcore: rm hub oops, message cleanups, unlink

These changes are unrelated except I ran into them all at once:

- Fixes an oops from a partial hub_configure() clean; let
   hub_disconnect() do the whole thing, simpler.

- Since I was there, modify that routine's err() messages
   to use dev_err().  Then eliminate a redundant diagnostic
   in hub_probe(), and merge the "bad descriptor" cases into
   one diagnostic.  Saves a few hundred rodata bytes, and
   the messages now say what hub's involved.

- Unlink fixes:  if lower level code reports a submit error,
   make sure the urb gets unlinked from the device's urb_list;
   and report "it's already being unlinked" as -EBUSY so callers
   can do something smarter than wonder "what did I do wrong".


diff -Nru a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
--- a/drivers/usb/core/hcd.c	Sun Dec 22 00:38:58 2002
+++ b/drivers/usb/core/hcd.c	Sun Dec 22 00:38:58 2002
@@ -1022,7 +1022,10 @@
 		 * they could clobber root hub response data.
 		 */
 		urb->transfer_flags |= URB_NO_DMA_MAP;
-		return rh_urb_enqueue (hcd, urb);
+		status = rh_urb_enqueue (hcd, urb);
+		if (status)
+			urb_unlink (urb);
+		return status;
 	}
 
 	/* lower level hcd code should use *_dma exclusively */
@@ -1043,7 +1046,10 @@
 					    : PCI_DMA_TODEVICE);
 	}
 
-	return hcd->driver->urb_enqueue (hcd, urb, mem_flags);
+	status = hcd->driver->urb_enqueue (hcd, urb, mem_flags);
+	if (status)
+		urb_unlink (urb);
+	return status;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -1137,7 +1143,7 @@
 	 * FIXME use better explicit urb state
 	 */
 	if (urb->status != -EINPROGRESS) {
-		retval = -EINVAL;
+		retval = -EBUSY;
 		goto done;
 	}
 
diff -Nru a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
--- a/drivers/usb/core/hub.c	Sun Dec 22 00:38:58 2002
+++ b/drivers/usb/core/hub.c	Sun Dec 22 00:38:58 2002
@@ -279,12 +279,13 @@
 	struct usb_hub_status hubstatus;
 	unsigned int pipe;
 	int maxp, ret;
+	char *message;
 
 	hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL);
 	if (!hub->descriptor) {
-		err("Unable to kmalloc %Zd bytes for hub descriptor",
-			sizeof(*hub->descriptor));
-		return -1;
+		message = "can't kmalloc hub descriptor";
+		ret = -ENOMEM;
+		goto fail;
 	}
 
 	/* Request the entire hub descriptor.
@@ -294,13 +295,12 @@
 	ret = usb_get_hub_descriptor(dev, hub->descriptor,
 			sizeof(*hub->descriptor));
 	if (ret < 0) {
-		err("Unable to get hub descriptor (err = %d)", ret);
-		kfree(hub->descriptor);
-		return -1;
+		message = "can't read hub descriptor";
+		goto fail;
 	} else if (hub->descriptor->bNbrPorts > USB_MAXCHILDREN) {
-		err("Hub is too big! %d children", hub->descriptor->bNbrPorts);
-		kfree(hub->descriptor);
-		return -1;
+		message = "hub has too many ports!";
+		ret = -ENODEV;
+		goto fail;
 	}
 
 	dev->maxchild = hub->descriptor->bNbrPorts;
@@ -396,9 +396,8 @@
 
 	ret = usb_get_hub_status(dev, &hubstatus);
 	if (ret < 0) {
-		err("Unable to get hub status (err = %d)", ret);
-		kfree(hub->descriptor);
-		return -1;
+		message = "can't get hub status";
+		goto fail;
 	}
 
 	le16_to_cpus(&hubstatus.wHubStatus);
@@ -419,18 +418,17 @@
 
 	hub->urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!hub->urb) {
-		err("couldn't allocate interrupt urb");
-		kfree(hub->descriptor);
-		return -1;
+		message = "couldn't allocate interrupt urb";
+		ret = -ENOMEM;
+		goto fail;
 	}
 
 	usb_fill_int_urb(hub->urb, dev, pipe, hub->buffer, maxp, hub_irq,
 		hub, endpoint->bInterval);
 	ret = usb_submit_urb(hub->urb, GFP_KERNEL);
 	if (ret) {
-		err("usb_submit_urb failed (%d)", ret);
-		kfree(hub->descriptor);
-		return -1;
+		message = "couldn't submit status urb";
+		goto fail;
 	}
 		
 	/* Wake up khubd */
@@ -439,6 +437,12 @@
 	usb_hub_power_on(hub);
 
 	return 0;
+
+fail:
+	dev_err (hub->intf->dev, "config failed, %s (err %d)\n",
+			message, ret);
+	/* hub_disconnect() frees urb and descriptor */
+	return ret;
 }
 
 static void hub_disconnect(struct usb_interface *intf)
@@ -497,32 +501,27 @@
 	/*  specs is not defined, but it works */
 	if ((desc->desc.bInterfaceSubClass != 0) &&
 	    (desc->desc.bInterfaceSubClass != 1)) {
-		err("invalid subclass (%d) for USB hub device #%d",
-			desc->desc.bInterfaceSubClass, dev->devnum);
+descriptor_error:
+		dev_err (intf->dev, "bad descriptor, ignoring hub\n");
 		return -EIO;
 	}
 
 	/* Multiple endpoints? What kind of mutant ninja-hub is this? */
 	if (desc->desc.bNumEndpoints != 1) {
-		err("invalid bNumEndpoints (%d) for USB hub device #%d",
-			desc->desc.bNumEndpoints, dev->devnum);
-		return -EIO;
+		goto descriptor_error;
 	}
 
 	endpoint = &desc->endpoint[0].desc;
 
 	/* Output endpoint? Curiousier and curiousier.. */
 	if (!(endpoint->bEndpointAddress & USB_DIR_IN)) {
-		err("Device #%d is hub class, but has output endpoint?",
-			dev->devnum);
-		return -EIO;
+		goto descriptor_error;
 	}
 
 	/* If it's not an interrupt endpoint, we'd better punt! */
 	if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
 			!= USB_ENDPOINT_XFER_INT) {
-		err("Device #%d is hub class, but endpoint is not interrupt?",
-			dev->devnum);
+		goto descriptor_error;
 		return -EIO;
 	}
 
@@ -553,8 +552,6 @@
 		strcpy (intf->dev.name, "Hub");
 		return 0;
 	}
-
-	err("hub configuration failed for device at %s", dev->devpath);
 
 	hub_disconnect (intf);
 	return -ENODEV;
