void rt2x00usb_kick_queue(struct data_queue *queue) { switch (queue->qid) { case QID_AC_VO: case QID_AC_VI: case QID_AC_BE: case QID_AC_BK: if (!rt2x00queue_empty(queue)) rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, NULL, rt2x00usb_kick_tx_entry); break; case QID_RX: if (!rt2x00queue_full(queue)) rt2x00queue_for_each_entry(queue, Q_INDEX, Q_INDEX_DONE, NULL, rt2x00usb_kick_rx_entry); break; default: break; } }
void rt2x00usb_flush_queue(struct data_queue *queue, bool drop) { struct work_struct *completion; unsigned int i; if (drop) rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, NULL, rt2x00usb_flush_entry); /* * Obtain the queue completion handler */ switch (queue->qid) { case QID_AC_VO: case QID_AC_VI: case QID_AC_BE: case QID_AC_BK: completion = &queue->rt2x00dev->txdone_work; break; case QID_RX: completion = &queue->rt2x00dev->rxdone_work; break; default: return; } for (i = 0; i < 10; i++) { /* * Check if the driver is already done, otherwise we * have to sleep a little while to give the driver/hw * the oppurtunity to complete interrupt process itself. */ if (rt2x00queue_empty(queue)) break; /* * Schedule the completion handler manually, when this * worker function runs, it should cleanup the queue. */ queue_work(queue->rt2x00dev->workqueue, completion); /* * Wait for a little while to give the driver * the oppurtunity to recover itself. */ msleep(10); } }
void rt2x00usb_kill_tx_queue(struct data_queue *queue) { rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, rt2x00usb_kill_tx_entry); }
static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) { struct data_queue *queue; u32 status; u8 qid; int max_tx_done = 16; while (kfifo_get(&rt2x00dev->txstatus_fifo, &status)) { qid = rt2x00_get_field32(status, TX_STA_FIFO_PID_QUEUE); if (unlikely(qid >= QID_RX)) { /* * Unknown queue, this shouldn't happen. Just drop * this tx status. */ rt2x00_warn(rt2x00dev, "Got TX status report with unexpected pid %u, dropping\n", qid); break; } queue = rt2x00queue_get_tx_queue(rt2x00dev, qid); if (unlikely(queue == NULL)) { /* * The queue is NULL, this shouldn't happen. Stop * processing here and drop the tx status */ rt2x00_warn(rt2x00dev, "Got TX status for an unavailable queue %u, dropping\n", qid); break; } if (unlikely(rt2x00queue_empty(queue))) { /* * The queue is empty. Stop processing here * and drop the tx status. */ rt2x00_warn(rt2x00dev, "Got TX status for an empty queue %u, dropping\n", qid); break; } /* * Let's associate this tx status with the first * matching frame. */ if (!rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, &status, rt2800pci_txdone_find_entry)) { /* * We cannot match the tx status to any frame, so just * use the first one. */ if (!rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, &status, rt2800pci_txdone_match_first)) { rt2x00_warn(rt2x00dev, "No frame found for TX status on queue %u, dropping\n", qid); break; } } /* * Release all frames with a valid tx status. */ rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, NULL, rt2800pci_txdone_release_entries); if (--max_tx_done == 0) break; } return !max_tx_done; }