Re: debugging oops after disconnecting Nexio USB touchscreen

From: Alan Stern
Date: Thu Dec 10 2009 - 15:38:43 EST


On Thu, 10 Dec 2009, Ondrej Zary wrote:

> Narrowed down the code to this 170-line module which reproduces my
> "rmmod usbtouchscreen" problem. Loading this module causes EHCI to fail.
> Looks like it fails after calling usb_kill_urb(). Can a buggy device cause
> this?

I don't think so. But I am getting an idea of what the problem might
be. Try applying the patch below and see if it makes any difference
(make sure that CONFIG_USB_DEBUG is enabled).

If the module stops messing up EHCI, try changing the source code:

> static int crashnexio_probe(struct usb_interface *intf,
> const struct usb_device_id *id)
> {

...

> interface = intf->cur_altsetting;
> /* find first input endpoint */
> for (i = 0; i < interface->desc.bNumEndpoints; i++)
> if (usb_endpoint_dir_in(&interface->endpoint[i].desc)) {
> endpoint = &interface->endpoint[i].desc;
> break;
> }

Does the interface have more than one input endpoint? (What does
"lsusb -v" show for the Nexio?) If it does, how do you know the
endpoint you want is the first one?

...

> usb_fill_bulk_urb(crashnexio->irq, udev,
> usb_rcvintpipe(udev, endpoint->bEndpointAddress),

Either change this to usb_fill_int_urb() or else use usb_rcvbulkpipe().

...

> static int __init crashnexio_init(void)
> {
> return usb_register(&crashnexio_driver);
> }

You should also have an __exit routine.

Alan Stern




Index: 2.6.31/Documentation/usb/error-codes.txt
===================================================================
--- 2.6.31.orig/Documentation/usb/error-codes.txt
+++ 2.6.31/Documentation/usb/error-codes.txt
@@ -41,8 +41,8 @@ USB-specific:

-EFBIG Host controller driver can't schedule that many ISO frames.

--EPIPE Specified endpoint is stalled. For non-control endpoints,
- reset this status with usb_clear_halt().
+-EPIPE The pipe type specified in the URB doesn't match the
+ endpoint's actual type.

-EMSGSIZE (a) endpoint maxpacket size is zero; it is not usable
in the current interface altsetting.
@@ -60,6 +60,8 @@ USB-specific:

-EHOSTUNREACH URB was rejected because the device is suspended.

+-ENOEXEC A control URB doesn't contain a Setup packet.
+

**************************************************************************
* Error codes returned by in urb->status *
Index: 2.6.31/drivers/usb/core/devio.c
===================================================================
--- 2.6.31.orig/drivers/usb/core/devio.c
+++ 2.6.31/drivers/usb/core/devio.c
@@ -1065,7 +1065,10 @@ static int proc_do_submiturb(struct dev_
case USB_ENDPOINT_XFER_CONTROL:
case USB_ENDPOINT_XFER_ISOC:
return -EINVAL;
- /* allow single-shot interrupt transfers, at bogus rates */
+ case USB_ENDPOINT_XFER_INT:
+ /* allow single-shot interrupt transfers */
+ uurb->type = USBDEVFS_URB_TYPE_INTERRUPT;
+ goto interrupt_urb;
}
uurb->number_of_packets = 0;
if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
@@ -1073,6 +1076,16 @@ static int proc_do_submiturb(struct dev_
snoop(&ps->dev->dev, "bulk urb\n");
break;

+ case USBDEVFS_URB_TYPE_INTERRUPT:
+ if (!usb_endpoint_xfer_int(&ep->desc))
+ return -EINVAL;
+ interrupt_urb:
+ uurb->number_of_packets = 0;
+ if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
+ return -EINVAL;
+ snoop(&ps->dev->dev, "interrupt urb\n");
+ break;
+
case USBDEVFS_URB_TYPE_ISO:
/* arbitrary limit */
if (uurb->number_of_packets < 1 ||
@@ -1105,15 +1118,6 @@ static int proc_do_submiturb(struct dev_
snoop(&ps->dev->dev, "iso urb\n");
break;

- case USBDEVFS_URB_TYPE_INTERRUPT:
- uurb->number_of_packets = 0;
- if (!usb_endpoint_xfer_int(&ep->desc))
- return -EINVAL;
- if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
- return -EINVAL;
- snoop(&ps->dev->dev, "interrupt urb\n");
- break;
-
default:
return -EINVAL;
}
Index: 2.6.31/drivers/usb/core/urb.c
===================================================================
--- 2.6.31.orig/drivers/usb/core/urb.c
+++ 2.6.31/drivers/usb/core/urb.c
@@ -387,6 +387,13 @@ int usb_submit_urb(struct urb *urb, gfp_
{
unsigned int orig_flags = urb->transfer_flags;
unsigned int allowed;
+ static int pipetypes[4] = {
+ PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
+ };
+
+ /* Check that pipe's type matches the endpoint's type */
+ if (usb_pipetype(urb->pipe) != pipetypes[xfertype])
+ return -EPIPE;

/* enforce simple/standard policy */
allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP |

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/