]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/bluetooth/hci_usb.h
tcp: Restore ordering of TCP options for the sake of inter-operability
[linux-2.6-omap-h63xx.git] / drivers / bluetooth / hci_usb.h
index 414080a4e8ff6c157c820cf0adf840ba39c50930..8e659914523f76990e1e736201044771531b02eb 100644 (file)
@@ -70,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 smp_mb(). */
+       _urb->queue = q; smp_mb(); list_add(&_urb->list, &q->head);
        spin_unlock_irqrestore(&q->lock, flags);
 }
 
@@ -78,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 smp_mb(). */
+       _urb->queue = q; smp_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);
-       }
+
+       smp_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 {