提交 ed61e2b0 编写于 作者: S Stanislaw Gruszka 提交者: John W. Linville

rt2x00: rt2800usb: rework txdone code

Patch change txdone code to make it similar like txdone in rt2800pci,
process only one entry from queue matching tx status.

Before we processed all pending entries from queue until PACKEDID match,
that caused that we do not report tx statuses correctly.
Signed-off-by: NStanislaw Gruszka <sgruszka@redhat.com>
Acked-by: NGertjan van Wingerde <gwingerde@gmail.com>
Signed-off-by: NJohn W. Linville <linville@tuxdriver.com>
上级 627fdaf7
......@@ -438,35 +438,25 @@ static int rt2800usb_get_tx_data_len(struct queue_entry *entry)
/*
* TX control handlers
*/
static bool rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg)
static enum txdone_entry_desc_flags
rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg)
{
__le32 *txwi;
u32 word;
int wcid, ack, pid;
int tx_wcid, tx_ack, tx_pid;
if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
!test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) {
WARNING(entry->queue->rt2x00dev,
"Data pending for entry %u in queue %u\n",
entry->entry_idx, entry->queue->qid);
cond_resched();
return false;
}
wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED);
pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE);
/*
* This frames has returned with an IO error,
* so the status report is not intended for this
* frame.
*/
if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) {
rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
return false;
}
if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
return TXDONE_FAILURE;
wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED);
pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE);
/*
* Validate if this TX status report is intended for
......@@ -482,12 +472,11 @@ static bool rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg)
if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid)) {
WARNING(entry->queue->rt2x00dev,
"TX status report missed for queue %d entry %d\n",
entry->queue->qid, entry->entry_idx);
rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN);
return false;
entry->queue->qid, entry->entry_idx);
return TXDONE_UNKNOWN;
}
return true;
return TXDONE_SUCCESS;
}
static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev)
......@@ -496,35 +485,36 @@ static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev)
struct queue_entry *entry;
u32 reg;
u8 qid;
enum txdone_entry_desc_flags done_status;
while (kfifo_get(&rt2x00dev->txstatus_fifo, &reg)) {
/* TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus
* qid is guaranteed to be one of the TX QIDs
/*
* TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus qid is
* guaranteed to be one of the TX QIDs .
*/
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 "
if (unlikely(rt2x00queue_empty(queue))) {
WARNING(rt2x00dev, "Got TX status for an empty "
"queue %u, dropping\n", qid);
continue;
break;
}
/*
* Inside each queue, we process each entry in a chronological
* order. We first check that the queue is not empty.
*/
entry = NULL;
while (!rt2x00queue_empty(queue)) {
entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
if (rt2800usb_txdone_entry_check(entry, reg))
break;
entry = NULL;
entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
if (unlikely(test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
!test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))) {
WARNING(rt2x00dev, "Data pending for entry %u "
"in queue %u\n", entry->entry_idx, qid);
break;
}
if (entry)
rt2800_txdone_entry(entry, reg,
rt2800usb_get_txwi(entry));
done_status = rt2800usb_txdone_entry_check(entry, reg);
if (likely(done_status == TXDONE_SUCCESS))
rt2800_txdone_entry(entry, reg, rt2800usb_get_txwi(entry));
else
rt2x00lib_txdone_noinfo(entry, done_status);
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册