Patch against 2.4.20-rc1.
When an urb has been submitted via usbdevfs, and is still pending
when the interface is released, force the urb to be completed. This
fixes an oops on system shutdown with the user space driver for
the speedtouch modem.
Remarks:
(1) I chose to add a new field to the async struct (it holds the interface
to which the urb was submitted). I could have looped over all endpoints
of the interface, and killed urbs submitted to the endpoint, but that seemed
a bit clumsy.
(2) In destroy_async_on_interface, urbs that are to be finalized are first
moved to a new list. This is to avoid problems due to urbs completing
spontaneously during list traversal.
(3) This does not force urbs submitted to endpoint zero to complete.
You are not required to claim an interface for these anyway.
Duncan.
--- linux/drivers/usb/devio.c.orig 2002-11-07 09:06:27.000000000 +0100
+++ linux/drivers/usb/devio.c 2002-11-15 18:49:12.000000000 +0100
@@ -50,6 +50,7 @@
struct dev_state *ps;
struct task_struct *task;
unsigned int signr;
+ unsigned int intf;
void *userbuffer;
void *userurb;
struct urb urb;
@@ -265,6 +266,38 @@
}
}
+static void destroy_async_on_interface (struct dev_state *ps, unsigned int intf)
+{
+ struct async *as;
+ struct list_head *p, hitlist;
+ unsigned long flags;
+
+ INIT_LIST_HEAD(&hitlist);
+ spin_lock_irqsave(&ps->lock, flags);
+ for (p = ps->async_pending.next; p != &ps->async_pending; ) {
+ as = list_entry(p, struct async, asynclist);
+ p = p->next;
+
+ if (as->intf == intf) {
+ list_del(&as->asynclist);
+ list_add_tail(&as->asynclist, &hitlist);
+ }
+ }
+
+ while (!list_empty(&hitlist)) {
+ as = list_entry(hitlist.next, struct async, asynclist);
+ list_del(&as->asynclist);
+ INIT_LIST_HEAD(&as->asynclist);
+ spin_unlock_irqrestore(&ps->lock, flags);
+ /* usb_unlink_urb calls the completion handler with status ==
+USB_ST_URB_KILLED */
+ usb_unlink_urb(&as->urb);
+ spin_lock_irqsave(&ps->lock, flags);
+ }
+ spin_unlock_irqrestore(&ps->lock, flags);
+ while ((as = async_getcompleted(ps)))
+ free_async(as);
+}
+
static void destroy_all_async(struct dev_state *ps)
{
struct async *as;
@@ -775,6 +810,7 @@
struct usb_ctrlrequest *dr = NULL;
unsigned int u, totlen, isofrmlen;
int ret;
+ int intf = -1;
if (copy_from_user(&uurb, arg, sizeof(uurb)))
return -EFAULT;
@@ -786,9 +822,9 @@
if (uurb.signr != 0 && (uurb.signr < SIGRTMIN || uurb.signr > SIGRTMAX))
return -EINVAL;
if (!(uurb.type == USBDEVFS_URB_TYPE_CONTROL && (uurb.endpoint &
~USB_ENDPOINT_DIR_MASK) == 0)) {
- if ((ret = findintfep(ps->dev, uurb.endpoint)) < 0)
- return ret;
- if ((ret = checkintf(ps, ret)))
+ if ((intf = findintfep(ps->dev, uurb.endpoint)) < 0)
+ return intf;
+ if ((ret = checkintf(ps, intf)))
return ret;
}
switch(uurb.type) {
@@ -909,6 +945,7 @@
else
as->userbuffer = NULL;
as->signr = uurb.signr;
+ as->intf = intf;
as->task = current;
if (!(uurb.endpoint & USB_DIR_IN)) {
if (copy_from_user(as->urb.transfer_buffer, uurb.buffer,
as->urb.transfer_buffer_length)) {
@@ -1054,7 +1091,10 @@
return -EFAULT;
if ((ret = findintfif(ps->dev, intf)) < 0)
return ret;
- return releaseintf(ps, intf);
+ if ((ret = releaseintf(ps, intf)) < 0)
+ return ret;
+ destroy_async_on_interface (ps, intf);
+ return 0;
}
static int proc_ioctl (struct dev_state *ps, void *arg)
-------------------------------------------------------
This sf.net email is sponsored by: To learn the basics of securing
your web site with SSL, click here to get a FREE TRIAL of a Thawte
Server Certificate: http://www.gothawte.com/rd524.html
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel