[Bluetooth] Fix double frees on error paths of btusb and bpa10x drivers
[pandora-kernel.git] / drivers / bluetooth / hci_usb.h
index 963fc55..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,28 +79,32 @@ 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 {
        struct hci_dev          *hdev;
 
        unsigned long           state;
-       
+
        struct usb_device       *udev;
-       
+
        struct usb_host_endpoint        *bulk_in_ep;
        struct usb_host_endpoint        *bulk_out_ep;
        struct usb_host_endpoint        *intr_in_ep;
@@ -116,7 +116,6 @@ struct hci_usb {
        __u8                    ctrl_req;
 
        struct sk_buff_head     transmit_q[4];
-       struct sk_buff          *reassembly[4];         /* Reassembly buffers */
 
        rwlock_t                completion_lock;