diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 8e1855a478be..4eaa6280f367 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -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, ®)) { - - /* 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); } }