/* * TX control handlers */ static bool 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; } /* * Validate if this TX status report is intended for * this entry by comparing the WCID/ACK/PID fields. */ txwi = rt2800usb_get_txwi(entry); rt2x00_desc_read(txwi, 1, &word); tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID); tx_ack = rt2x00_get_field32(word, TXWI_W1_ACK); tx_pid = rt2x00_get_field32(word, TXWI_W1_PACKETID); 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; } return true; }
/* * TX data handlers. */ static void rt2x00usb_work_txdone_entry(struct queue_entry *entry) { /* * If the transfer to hardware succeeded, it does not mean the * frame was send out correctly. It only means the frame * was successfully pushed to the hardware, we have no * way to determine the transmission status right now. * (Only indirectly by looking at the failed TX counters * in the register). */ if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE); else rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN); }
/* * TX control handlers */ static void rt2800usb_work_txdone(struct work_struct *work) { struct rt2x00_dev *rt2x00dev = container_of(work, struct rt2x00_dev, txdone_work); struct data_queue *queue; struct queue_entry *entry; rt2800_txdone(rt2x00dev); /* * Process any trailing TX status reports for IO failures, * we loop until we find the first non-IO error entry. This * can either be a frame which is free, is being uploaded, * or has completed the upload but didn't have an entry * in the TX_STAT_FIFO register yet. */ tx_queue_for_each(rt2x00dev, queue) { while (!rt2x00queue_empty(queue)) { entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) || !test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) break; rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE); } } }
/* * TX control handlers */ static void rt2800usb_work_txdone(struct work_struct *work) { struct rt2x00_dev *rt2x00dev = container_of(work, struct rt2x00_dev, txdone_work); struct data_queue *queue; struct queue_entry *entry; rt2800_txdone(rt2x00dev); /* * Process any trailing TX status reports for IO failures, * we loop until we find the first non-IO error entry. This * can either be a frame which is free, is being uploaded, * or has completed the upload but didn't have an entry * in the TX_STAT_FIFO register yet. */ tx_queue_for_each(rt2x00dev, queue) { while (!rt2x00queue_empty(queue)) { entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) || !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) break; if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE); else if (rt2x00queue_status_timeout(entry)) rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN); else 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(2)); }