[Bluetooth] Fix double frees on error paths of btusb and bpa10x drivers
[pandora-kernel.git] / drivers / bluetooth / hci_usb.h
index 56cd3a9..1790cc8 100644 (file)
@@ -60,11 +60,6 @@ struct _urb {
        struct urb        urb;
 };
 
-static inline void _urb_free(struct _urb *_urb)
-{
-       kfree(_urb);
-}
-
 static inline void _urb_queue_init(struct _urb_queue *q)
 {
        INIT_LIST_HEAD(&q->head);
@@ -75,7 +70,8 @@ static inline void _urb_queue_head(struct _urb_queue *q, struct _urb *_urb)
 {
        unsigned long flags;
        spin_lock_irqsave(&q->lock, flags);
-       list_add(&_urb->list, &q->head); _urb->queue = q;
+       /* _urb_unlink needs to know which spinlock to use, thus mb(). */
+       _urb->queue = q; mb(); list_add(&_urb->list, &q->head);
        spin_unlock_irqrestore(&q->lock, flags);
 }
 
@@ -83,19 +79,23 @@ static inline void _urb_queue_tail(struct _urb_queue *q, struct _urb *_urb)
 {
        unsigned long flags;
        spin_lock_irqsave(&q->lock, flags);
-       list_add_tail(&_urb->list, &q->head); _urb->queue = q;
+       /* _urb_unlink needs to know which spinlock to use, thus mb(). */
+       _urb->queue = q; mb(); list_add_tail(&_urb->list, &q->head);
        spin_unlock_irqrestore(&q->lock, flags);
 }
 
 static inline void _urb_unlink(struct _urb *_urb)
 {
-       struct _urb_queue *q = _urb->queue;
+       struct _urb_queue *q;
        unsigned long flags;
-       if (q) {
-               spin_lock_irqsave(&q->lock, flags);
-               list_del(&_urb->list); _urb->queue = NULL;
-               spin_unlock_irqrestore(&q->lock, flags);
-       }
+
+       mb();
+       q = _urb->queue;
+       /* If q is NULL, it will die at easy-to-debug NULL pointer dereference.
+          No need to BUG(). */
+       spin_lock_irqsave(&q->lock, flags);
+       list_del(&_urb->list); _urb->queue = NULL;
+       spin_unlock_irqrestore(&q->lock, flags);
 }
 
 struct hci_usb {