rt2x00: Fix URB error handling
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>
This commit is contained in:
parent
1a39769653
commit
a13c8f3133
@ -253,6 +253,7 @@ EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt);
|
|||||||
|
|
||||||
void rt2x00lib_dmadone(struct queue_entry *entry)
|
void rt2x00lib_dmadone(struct queue_entry *entry)
|
||||||
{
|
{
|
||||||
|
clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
|
||||||
rt2x00queue_index_inc(entry->queue, Q_INDEX_DMA_DONE);
|
rt2x00queue_index_inc(entry->queue, Q_INDEX_DMA_DONE);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(rt2x00lib_dmadone);
|
EXPORT_SYMBOL_GPL(rt2x00lib_dmadone);
|
||||||
|
@ -253,7 +253,10 @@ static void rt2x00usb_kick_tx_entry(struct queue_entry *entry)
|
|||||||
entry->skb->data, length,
|
entry->skb->data, length,
|
||||||
rt2x00usb_interrupt_txdone, entry);
|
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)
|
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) &&
|
if ((entry->queue->qid == QID_BEACON) &&
|
||||||
(test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags)))
|
(test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags)))
|
||||||
usb_kill_urb(bcn_priv->guardian_urb);
|
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)
|
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);
|
rt2x00usb_interrupt_rxdone, entry);
|
||||||
|
|
||||||
set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
|
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);
|
EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry);
|
||||||
|
Loading…
Reference in New Issue
Block a user