Commit 399b19dc authored by David Brownell's avatar David Brownell Committed by Greg Kroah-Hartman

[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".
parent 30a03849
...@@ -1022,7 +1022,10 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags) ...@@ -1022,7 +1022,10 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags)
* they could clobber root hub response data. * they could clobber root hub response data.
*/ */
urb->transfer_flags |= URB_NO_DMA_MAP; 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 */ /* lower level hcd code should use *_dma exclusively */
...@@ -1043,7 +1046,10 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags) ...@@ -1043,7 +1046,10 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags)
: PCI_DMA_TODEVICE); : 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 @@ static int hcd_unlink_urb (struct urb *urb) ...@@ -1137,7 +1143,7 @@ static int hcd_unlink_urb (struct urb *urb)
* FIXME use better explicit urb state * FIXME use better explicit urb state
*/ */
if (urb->status != -EINPROGRESS) { if (urb->status != -EINPROGRESS) {
retval = -EINVAL; retval = -EBUSY;
goto done; goto done;
} }
......
...@@ -279,12 +279,13 @@ static int usb_hub_configure(struct usb_hub *hub, ...@@ -279,12 +279,13 @@ static int usb_hub_configure(struct usb_hub *hub,
struct usb_hub_status hubstatus; struct usb_hub_status hubstatus;
unsigned int pipe; unsigned int pipe;
int maxp, ret; int maxp, ret;
char *message;
hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL); hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL);
if (!hub->descriptor) { if (!hub->descriptor) {
err("Unable to kmalloc %Zd bytes for hub descriptor", message = "can't kmalloc hub descriptor";
sizeof(*hub->descriptor)); ret = -ENOMEM;
return -1; goto fail;
} }
/* Request the entire hub descriptor. /* Request the entire hub descriptor.
...@@ -294,13 +295,12 @@ static int usb_hub_configure(struct usb_hub *hub, ...@@ -294,13 +295,12 @@ static int usb_hub_configure(struct usb_hub *hub,
ret = usb_get_hub_descriptor(dev, hub->descriptor, ret = usb_get_hub_descriptor(dev, hub->descriptor,
sizeof(*hub->descriptor)); sizeof(*hub->descriptor));
if (ret < 0) { if (ret < 0) {
err("Unable to get hub descriptor (err = %d)", ret); message = "can't read hub descriptor";
kfree(hub->descriptor); goto fail;
return -1;
} else if (hub->descriptor->bNbrPorts > USB_MAXCHILDREN) { } else if (hub->descriptor->bNbrPorts > USB_MAXCHILDREN) {
err("Hub is too big! %d children", hub->descriptor->bNbrPorts); message = "hub has too many ports!";
kfree(hub->descriptor); ret = -ENODEV;
return -1; goto fail;
} }
dev->maxchild = hub->descriptor->bNbrPorts; dev->maxchild = hub->descriptor->bNbrPorts;
...@@ -396,9 +396,8 @@ static int usb_hub_configure(struct usb_hub *hub, ...@@ -396,9 +396,8 @@ static int usb_hub_configure(struct usb_hub *hub,
ret = usb_get_hub_status(dev, &hubstatus); ret = usb_get_hub_status(dev, &hubstatus);
if (ret < 0) { if (ret < 0) {
err("Unable to get hub status (err = %d)", ret); message = "can't get hub status";
kfree(hub->descriptor); goto fail;
return -1;
} }
le16_to_cpus(&hubstatus.wHubStatus); le16_to_cpus(&hubstatus.wHubStatus);
...@@ -419,18 +418,17 @@ static int usb_hub_configure(struct usb_hub *hub, ...@@ -419,18 +418,17 @@ static int usb_hub_configure(struct usb_hub *hub,
hub->urb = usb_alloc_urb(0, GFP_KERNEL); hub->urb = usb_alloc_urb(0, GFP_KERNEL);
if (!hub->urb) { if (!hub->urb) {
err("couldn't allocate interrupt urb"); message = "couldn't allocate interrupt urb";
kfree(hub->descriptor); ret = -ENOMEM;
return -1; goto fail;
} }
usb_fill_int_urb(hub->urb, dev, pipe, hub->buffer, maxp, hub_irq, usb_fill_int_urb(hub->urb, dev, pipe, hub->buffer, maxp, hub_irq,
hub, endpoint->bInterval); hub, endpoint->bInterval);
ret = usb_submit_urb(hub->urb, GFP_KERNEL); ret = usb_submit_urb(hub->urb, GFP_KERNEL);
if (ret) { if (ret) {
err("usb_submit_urb failed (%d)", ret); message = "couldn't submit status urb";
kfree(hub->descriptor); goto fail;
return -1;
} }
/* Wake up khubd */ /* Wake up khubd */
...@@ -439,6 +437,12 @@ static int usb_hub_configure(struct usb_hub *hub, ...@@ -439,6 +437,12 @@ static int usb_hub_configure(struct usb_hub *hub,
usb_hub_power_on(hub); usb_hub_power_on(hub);
return 0; 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) static void hub_disconnect(struct usb_interface *intf)
...@@ -497,32 +501,27 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) ...@@ -497,32 +501,27 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
/* specs is not defined, but it works */ /* specs is not defined, but it works */
if ((desc->desc.bInterfaceSubClass != 0) && if ((desc->desc.bInterfaceSubClass != 0) &&
(desc->desc.bInterfaceSubClass != 1)) { (desc->desc.bInterfaceSubClass != 1)) {
err("invalid subclass (%d) for USB hub device #%d", descriptor_error:
desc->desc.bInterfaceSubClass, dev->devnum); dev_err (intf->dev, "bad descriptor, ignoring hub\n");
return -EIO; return -EIO;
} }
/* Multiple endpoints? What kind of mutant ninja-hub is this? */ /* Multiple endpoints? What kind of mutant ninja-hub is this? */
if (desc->desc.bNumEndpoints != 1) { if (desc->desc.bNumEndpoints != 1) {
err("invalid bNumEndpoints (%d) for USB hub device #%d", goto descriptor_error;
desc->desc.bNumEndpoints, dev->devnum);
return -EIO;
} }
endpoint = &desc->endpoint[0].desc; endpoint = &desc->endpoint[0].desc;
/* Output endpoint? Curiousier and curiousier.. */ /* Output endpoint? Curiousier and curiousier.. */
if (!(endpoint->bEndpointAddress & USB_DIR_IN)) { if (!(endpoint->bEndpointAddress & USB_DIR_IN)) {
err("Device #%d is hub class, but has output endpoint?", goto descriptor_error;
dev->devnum);
return -EIO;
} }
/* If it's not an interrupt endpoint, we'd better punt! */ /* If it's not an interrupt endpoint, we'd better punt! */
if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
!= USB_ENDPOINT_XFER_INT) { != USB_ENDPOINT_XFER_INT) {
err("Device #%d is hub class, but endpoint is not interrupt?", goto descriptor_error;
dev->devnum);
return -EIO; return -EIO;
} }
...@@ -554,8 +553,6 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) ...@@ -554,8 +553,6 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
return 0; return 0;
} }
err("hub configuration failed for device at %s", dev->devpath);
hub_disconnect (intf); hub_disconnect (intf);
return -ENODEV; return -ENODEV;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment