patch-2.4.21 linux-2.4.21/drivers/usb/devio.c
Next file: linux-2.4.21/drivers/usb/dsbr100.c
Previous file: linux-2.4.21/drivers/usb/auerswald.c
Back to the patch index
Back to the overall index
- Lines: 174
- Date:
2003-06-13 07:51:36.000000000 -0700
- Orig file:
linux-2.4.20/drivers/usb/devio.c
- Orig date:
2002-11-28 15:53:14.000000000 -0800
diff -urN linux-2.4.20/drivers/usb/devio.c linux-2.4.21/drivers/usb/devio.c
@@ -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;
@@ -204,8 +205,7 @@
unsigned long flags;
spin_lock_irqsave(&ps->lock, flags);
- list_del(&as->asynclist);
- INIT_LIST_HEAD(&as->asynclist);
+ list_del_init(&as->asynclist);
spin_unlock_irqrestore(&ps->lock, flags);
}
@@ -217,8 +217,7 @@
spin_lock_irqsave(&ps->lock, flags);
if (!list_empty(&ps->async_completed)) {
as = list_entry(ps->async_completed.next, struct async, asynclist);
- list_del(&as->asynclist);
- INIT_LIST_HEAD(&as->asynclist);
+ list_del_init(&as->asynclist);
}
spin_unlock_irqrestore(&ps->lock, flags);
return as;
@@ -228,19 +227,14 @@
{
unsigned long flags;
struct async *as;
- struct list_head *p;
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->userurb != userurb)
- continue;
- list_del(&as->asynclist);
- INIT_LIST_HEAD(&as->asynclist);
- spin_unlock_irqrestore(&ps->lock, flags);
- return as;
- }
+ list_for_each_entry(as, &ps->async_pending, asynclist)
+ if (as->userurb == userurb) {
+ list_del_init(&as->asynclist);
+ spin_unlock_irqrestore(&ps->lock, flags);
+ return as;
+ }
spin_unlock_irqrestore(&ps->lock, flags);
return NULL;
}
@@ -252,8 +246,7 @@
struct siginfo sinfo;
spin_lock(&ps->lock);
- list_del(&as->asynclist);
- list_add_tail(&as->asynclist, &ps->async_completed);
+ list_move_tail(&as->asynclist, &ps->async_completed);
spin_unlock(&ps->lock);
wake_up(&ps->wait);
if (as->signr) {
@@ -265,24 +258,42 @@
}
}
-static void destroy_all_async(struct dev_state *ps)
+static void destroy_async (struct dev_state *ps, struct list_head *list)
{
- struct async *as;
- unsigned long flags;
+ struct async *as;
+ unsigned long flags;
- spin_lock_irqsave(&ps->lock, flags);
- while (!list_empty(&ps->async_pending)) {
- as = list_entry(ps->async_pending.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);
+ spin_lock_irqsave(&ps->lock, flags);
+ while (!list_empty(list)) {
+ as = list_entry(list->next, struct async, asynclist);
+ list_del_init(&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_async_on_interface (struct dev_state *ps, unsigned int intf)
+{
+ struct list_head *p, *q, hitlist;
+ unsigned long flags;
+
+ INIT_LIST_HEAD(&hitlist);
+ spin_lock_irqsave(&ps->lock, flags);
+ list_for_each_safe(p, q, &ps->async_pending)
+ if (intf == list_entry(p, struct async, asynclist)->intf)
+ list_move_tail(p, &hitlist);
+ spin_unlock_irqrestore(&ps->lock, flags);
+ destroy_async(ps, &hitlist);
+}
+
+static inline void destroy_all_async(struct dev_state *ps)
+{
+ destroy_async(ps, &ps->async_pending);
}
/*
@@ -519,8 +530,7 @@
unsigned int i;
lock_kernel();
- list_del(&ps->list);
- INIT_LIST_HEAD(&ps->list);
+ list_del_init(&ps->list);
if (ps->dev) {
for (i = 0; ps->ifclaimed && i < 8*sizeof(ps->ifclaimed); i++)
if (test_bit(i, &ps->ifclaimed))
@@ -775,6 +785,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 +797,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 +920,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 +1066,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)
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)