Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 214279
b: refs/heads/master
c: cd35a39
h: refs/heads/master
i:
  214277: 52baa84
  214275: 69985e8
  214271: c037473
v: v3
  • Loading branch information
Ivo van Doorn authored and John W. Linville committed Aug 31, 2010
1 parent d8cc808 commit 4d734cb
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 27 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 652a9dd2a0c07251e328519cc23f1316ab13ed51
refs/heads/master: cd35a3912188d006f251fff1028d84e1d1649ca2
66 changes: 40 additions & 26 deletions trunk/drivers/net/wireless/rt2x00/rt2x00usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,7 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
struct queue_entry *entry = (struct queue_entry *)urb->context;
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;

if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) ||
!__test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
if (!__test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
return;

/*
Expand All @@ -227,7 +226,9 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
* Schedule the delayed work for reading the TX status
* from the device.
*/
ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->txdone_work);
if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->txdone_work);
}

static void rt2x00usb_kick_tx_entry(struct queue_entry *entry)
Expand Down Expand Up @@ -279,6 +280,14 @@ 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)
Expand All @@ -290,8 +299,7 @@ EXPORT_SYMBOL_GPL(rt2x00usb_kill_tx_queue);

static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue)
{
struct queue_entry *entry;
struct queue_entry_priv_usb *entry_priv;
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
unsigned short threshold = queue->threshold;

WARNING(queue->rt2x00dev, "TX queue %d DMA timed out,"
Expand All @@ -305,36 +313,41 @@ static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue)
* queue from being enabled during the txdone handler.
*/
queue->threshold = queue->limit;
ieee80211_stop_queue(queue->rt2x00dev->hw, queue->qid);
ieee80211_stop_queue(rt2x00dev->hw, queue->qid);

/*
* Reset all currently uploaded TX frames.
* Kill all entries in the queue, afterwards we need to
* wait a bit for all URBs to be cancelled.
*/
while (!rt2x00queue_empty(queue)) {
entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
entry_priv = entry->priv_data;
usb_kill_urb(entry_priv->urb);
rt2x00usb_kill_tx_queue(queue);

/*
* 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));
/*
* In case that a driver has overriden the txdone_work
* function, we invoke the TX done through there.
*/
rt2x00dev->txdone_work.func(&rt2x00dev->txdone_work);

/*
* Invoke the TX done handler
*/
rt2x00usb_work_txdone_entry(entry);
/*
* Security measure: if the driver did override the
* txdone_work function, and the hardware did arrive
* in a state which causes it to malfunction, it is
* possible that the driver couldn't handle the txdone
* event correctly. So after giving the driver the
* chance to cleanup, we now force a cleanup of any
* leftovers.
*/
if (!rt2x00queue_empty(queue)) {
WARNING(queue->rt2x00dev, "TX queue %d DMA timed out,"
" status handling failed, invoke hard reset", queue->qid);
rt2x00usb_work_txdone(&rt2x00dev->txdone_work);
}

/*
* The queue has been reset, and mac80211 is allowed to use the
* queue again.
*/
queue->threshold = threshold;
ieee80211_wake_queue(queue->rt2x00dev->hw, queue->qid);
ieee80211_wake_queue(rt2x00dev->hw, queue->qid);
}

static void rt2x00usb_watchdog_tx_status(struct data_queue *queue)
Expand Down Expand Up @@ -394,8 +407,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
struct queue_entry *entry = (struct queue_entry *)urb->context;
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;

if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) ||
!__test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
if (!__test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
return;

/*
Expand All @@ -415,7 +427,9 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
* Schedule the delayed work for reading the RX status
* from the device.
*/
ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->rxdone_work);
if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->rxdone_work);
}

/*
Expand Down

0 comments on commit 4d734cb

Please sign in to comment.