rt2x00: Fix URB error handling
authorIvo van Doorn <ivdoorn@gmail.com>
Mon, 11 Oct 2010 13:39:48 +0000 (15:39 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 11 Oct 2010 19:04:26 +0000 (15:04 -0400)
kill_urb guarentees that when the function returns, the URB has
been fully killed. This means we don't need the extra sleeping
after the call to kill_urb.

kill_urb can however also guarentee the submit_urb to fail, as
a result, we must catch the return value from submit_urb an
correctly mark the entry as owned by the driver, and the
status as broken.

Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/rt2x00/rt2x00dev.c
drivers/net/wireless/rt2x00/rt2x00usb.c

index e5e8ba3bf228f06e980025c844a250e411000c7f..5ba79b935f09f5bed56f999653338501584cf141 100644 (file)
@@ -253,6 +253,7 @@ EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt);
 
 void rt2x00lib_dmadone(struct queue_entry *entry)
 {
+       clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
        rt2x00queue_index_inc(entry->queue, Q_INDEX_DMA_DONE);
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_dmadone);
index 89d77f55d76c4f29dc3d98ea17d70fd12b606132..b3317df7a7d4afdd88169c8ad16f2ad99984bc9e 100644 (file)
@@ -253,7 +253,10 @@ static void rt2x00usb_kick_tx_entry(struct queue_entry *entry)
                          entry->skb->data, length,
                          rt2x00usb_interrupt_txdone, entry);
 
-       usb_submit_urb(entry_priv->urb, GFP_ATOMIC);
+       if (usb_submit_urb(entry_priv->urb, GFP_ATOMIC)) {
+               set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
+               rt2x00lib_dmadone(entry);
+       }
 }
 
 void rt2x00usb_kick_tx_queue(struct data_queue *queue)
@@ -280,14 +283,6 @@ static void rt2x00usb_kill_tx_entry(struct queue_entry *entry)
        if ((entry->queue->qid == QID_BEACON) &&
            (test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags)))
                usb_kill_urb(bcn_priv->guardian_urb);
-
-       /*
-        * We need a short delay here to wait for
-        * the URB to be canceled
-        */
-       do {
-               udelay(100);
-       } while (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags));
 }
 
 void rt2x00usb_kill_tx_queue(struct data_queue *queue)
@@ -469,7 +464,10 @@ void rt2x00usb_clear_entry(struct queue_entry *entry)
                                rt2x00usb_interrupt_rxdone, entry);
 
                set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
-               usb_submit_urb(entry_priv->urb, GFP_ATOMIC);
+               if (usb_submit_urb(entry_priv->urb, GFP_ATOMIC)) {
+                       set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
+                       rt2x00lib_dmadone(entry);
+               }
        }
 }
 EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry);