rt2800usb: read TX_STA_FIFO asynchronously
Trying to fix the "TX status report missed" warnings by reading the TX_STA_FIFO entries as quickly as possible. The TX_STA_FIFO is too small in hardware, thus reading it only from the workqueue is too slow and entries get lost. Start an asynchronous read of the TX_STA_FIFO directly from the TX URB completion callback (atomic context, thus it cannot use the blocking rt2800_register_read()). If the async read returns a valid FIFO entry, it is pushed into a larger FIFO inside struct rt2x00_dev, until rt2800_txdone() picks it up. A .tx_dma_done callback is added to struct rt2x00lib_ops to trigger the async read from the URB completion callback. Signed-off-by: Johannes Stezenbach <js@sig21.net> Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
committed by
John W. Linville
parent
8da3efbb4a
commit
0e0d39e5f3
@@ -730,34 +730,20 @@ void rt2800_txdone(struct rt2x00_dev *rt2x00dev)
|
||||
struct data_queue *queue;
|
||||
struct queue_entry *entry;
|
||||
u32 reg;
|
||||
u8 pid;
|
||||
int i;
|
||||
u8 qid;
|
||||
|
||||
/*
|
||||
* TX_STA_FIFO is a stack of X entries, hence read TX_STA_FIFO
|
||||
* at most X times and also stop processing once the TX_STA_FIFO_VALID
|
||||
* flag is not set anymore.
|
||||
*
|
||||
* The legacy drivers use X=TX_RING_SIZE but state in a comment
|
||||
* that the TX_STA_FIFO stack has a size of 16. We stick to our
|
||||
* tx ring size for now.
|
||||
*/
|
||||
for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) {
|
||||
rt2800_register_read(rt2x00dev, TX_STA_FIFO, ®);
|
||||
if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID))
|
||||
break;
|
||||
while (kfifo_get(&rt2x00dev->txstatus_fifo, ®)) {
|
||||
|
||||
/*
|
||||
* Skip this entry when it contains an invalid
|
||||
* queue identication number.
|
||||
/* TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus
|
||||
* qid is guaranteed to be one of the TX QIDs
|
||||
*/
|
||||
pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE);
|
||||
if (pid >= QID_RX)
|
||||
continue;
|
||||
|
||||
queue = rt2x00queue_get_tx_queue(rt2x00dev, pid);
|
||||
if (unlikely(!queue))
|
||||
qid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE);
|
||||
queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
|
||||
if (unlikely(!queue)) {
|
||||
WARNING(rt2x00dev, "Got TX status for an unavailable "
|
||||
"queue %u, dropping\n", qid);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Inside each queue, we process each entry in a chronological
|
||||
|
Reference in New Issue
Block a user