USB: fix cdc-acm problems with hard irq? (inconsistent lock state)
authorJarek Poplawski <jarkao2@o2.pl>
Fri, 6 Oct 2006 05:23:11 +0000 (07:23 +0200)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 17 Oct 2006 21:46:31 +0000 (14:46 -0700)
Signed-off-by: Jarek Poplawski <jarkao2@o2.pl>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/class/cdc-acm.c

index daecdf0bff04d43a081cd4e6f947b2d5d5ddb3cb..9a9012fd284b48668e7feb7d46b32bcfd97810f2 100644 (file)
@@ -325,7 +325,7 @@ static void acm_rx_tasklet(unsigned long _acm)
        struct acm_rb *buf;
        struct tty_struct *tty = acm->tty;
        struct acm_ru *rcv;
-       //unsigned long flags;
+       unsigned long flags;
        int i = 0;
        dbg("Entering acm_rx_tasklet");
 
@@ -333,15 +333,15 @@ static void acm_rx_tasklet(unsigned long _acm)
                return;
 
 next_buffer:
-       spin_lock(&acm->read_lock);
+       spin_lock_irqsave(&acm->read_lock, flags);
        if (list_empty(&acm->filled_read_bufs)) {
-               spin_unlock(&acm->read_lock);
+               spin_unlock_irqrestore(&acm->read_lock, flags);
                goto urbs;
        }
        buf = list_entry(acm->filled_read_bufs.next,
                         struct acm_rb, list);
        list_del(&buf->list);
-       spin_unlock(&acm->read_lock);
+       spin_unlock_irqrestore(&acm->read_lock, flags);
 
        dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d", buf, buf->size);
 
@@ -356,29 +356,29 @@ next_buffer:
                memmove(buf->base, buf->base + i, buf->size - i);
                buf->size -= i;
                spin_unlock(&acm->throttle_lock);
-               spin_lock(&acm->read_lock);
+               spin_lock_irqsave(&acm->read_lock, flags);
                list_add(&buf->list, &acm->filled_read_bufs);
-               spin_unlock(&acm->read_lock);
+               spin_unlock_irqrestore(&acm->read_lock, flags);
                return;
        }
        spin_unlock(&acm->throttle_lock);
 
-       spin_lock(&acm->read_lock);
+       spin_lock_irqsave(&acm->read_lock, flags);
        list_add(&buf->list, &acm->spare_read_bufs);
-       spin_unlock(&acm->read_lock);
+       spin_unlock_irqrestore(&acm->read_lock, flags);
        goto next_buffer;
 
 urbs:
        while (!list_empty(&acm->spare_read_bufs)) {
-               spin_lock(&acm->read_lock);
+               spin_lock_irqsave(&acm->read_lock, flags);
                if (list_empty(&acm->spare_read_urbs)) {
-                       spin_unlock(&acm->read_lock);
+                       spin_unlock_irqrestore(&acm->read_lock, flags);
                        return;
                }
                rcv = list_entry(acm->spare_read_urbs.next,
                                 struct acm_ru, list);
                list_del(&rcv->list);
-               spin_unlock(&acm->read_lock);
+               spin_unlock_irqrestore(&acm->read_lock, flags);
 
                buf = list_entry(acm->spare_read_bufs.next,
                                 struct acm_rb, list);
@@ -400,9 +400,9 @@ urbs:
                   free-urbs-pool and resubmited ASAP */
                if (usb_submit_urb(rcv->urb, GFP_ATOMIC) < 0) {
                        list_add(&buf->list, &acm->spare_read_bufs);
-                       spin_lock(&acm->read_lock);
+                       spin_lock_irqsave(&acm->read_lock, flags);
                        list_add(&rcv->list, &acm->spare_read_urbs);
-                       spin_unlock(&acm->read_lock);
+                       spin_unlock_irqrestore(&acm->read_lock, flags);
                        return;
                }
        }