Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 246963
b: refs/heads/master
c: f0187a1
h: refs/heads/master
i:
  246961: 841f644
  246959: e27a164
v: v3
  • Loading branch information
Johannes Stezenbach authored and John W. Linville committed Apr 19, 2011
1 parent 205c585 commit 943c33a
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 3 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: 6e6d6932a3f525d734f6c2f5845e9cadfaeddce9
refs/heads/master: f0187a1987ed6524518ff2a533eaf8394ac1a500
41 changes: 40 additions & 1 deletion trunk/drivers/net/wireless/rt2x00/rt2800usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,22 @@ static void rt2800usb_stop_queue(struct data_queue *queue)
}
}

/*
* test if there is an entry in any TX queue for which DMA is done
* but the TX status has not been returned yet
*/
static bool rt2800usb_txstatus_pending(struct rt2x00_dev *rt2x00dev)
{
struct data_queue *queue;

tx_queue_for_each(rt2x00dev, queue) {
if (rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE) !=
rt2x00queue_get_entry(queue, Q_INDEX_DONE))
return true;
}
return false;
}

static void rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev,
int urb_status, u32 tx_status)
{
Expand All @@ -115,8 +131,11 @@ static void rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev,
} else
rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO,
rt2800usb_tx_sta_fifo_read_completed);
} else if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo))
} else if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo)) {
queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
} else if (rt2800usb_txstatus_pending(rt2x00dev)) {
mod_timer(&rt2x00dev->txstatus_timer, jiffies + msecs_to_jiffies(20));
}
}

static void rt2800usb_tx_dma_done(struct queue_entry *entry)
Expand All @@ -127,6 +146,14 @@ static void rt2800usb_tx_dma_done(struct queue_entry *entry)
rt2800usb_tx_sta_fifo_read_completed);
}

static void rt2800usb_tx_sta_fifo_timeout(unsigned long data)
{
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;

rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO,
rt2800usb_tx_sta_fifo_read_completed);
}

/*
* Firmware functions
*/
Expand Down Expand Up @@ -459,6 +486,14 @@ static void rt2800usb_work_txdone(struct work_struct *work)
break;
}
}

/*
* The hw may delay sending the packet after DMA complete
* if the medium is busy, thus the TX_STA_FIFO entry is
* also delayed -> use a timer to retrieve it.
*/
if (rt2800usb_txstatus_pending(rt2x00dev))
mod_timer(&rt2x00dev->txstatus_timer, jiffies + msecs_to_jiffies(20));
}

/*
Expand Down Expand Up @@ -599,6 +634,10 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
__set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags);
__set_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags);

setup_timer(&rt2x00dev->txstatus_timer,
rt2800usb_tx_sta_fifo_timeout,
(unsigned long) rt2x00dev);

/*
* Set the rssi offset.
*/
Expand Down
6 changes: 6 additions & 0 deletions trunk/drivers/net/wireless/rt2x00/rt2x00.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include <linux/etherdevice.h>
#include <linux/input-polldev.h>
#include <linux/kfifo.h>
#include <linux/timer.h>

#include <net/mac80211.h>

Expand Down Expand Up @@ -923,6 +924,11 @@ struct rt2x00_dev {
*/
DECLARE_KFIFO_PTR(txstatus_fifo, u32);

/*
* Timer to ensure tx status reports are read (rt2800usb).
*/
struct timer_list txstatus_timer;

/*
* Tasklet for processing tx status reports (rt2800pci).
*/
Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/net/wireless/rt2x00/rt2x00dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -1071,6 +1071,7 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
/*
* Stop all work.
*/
del_timer_sync(&rt2x00dev->txstatus_timer);
cancel_work_sync(&rt2x00dev->intf_work);
if (rt2x00_is_usb(rt2x00dev)) {
cancel_work_sync(&rt2x00dev->rxdone_work);
Expand Down
5 changes: 4 additions & 1 deletion trunk/drivers/net/wireless/rt2x00/rt2x00usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,9 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
* Schedule the delayed work for reading the TX status
* from the device.
*/
queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
if (!test_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags) ||
!kfifo_is_empty(&rt2x00dev->txstatus_fifo))
queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
}

static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry, void* data)
Expand Down Expand Up @@ -816,6 +818,7 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,

INIT_WORK(&rt2x00dev->rxdone_work, rt2x00usb_work_rxdone);
INIT_WORK(&rt2x00dev->txdone_work, rt2x00usb_work_txdone);
init_timer(&rt2x00dev->txstatus_timer);

retval = rt2x00usb_alloc_reg(rt2x00dev);
if (retval)
Expand Down

0 comments on commit 943c33a

Please sign in to comment.