Exemple #1
0
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;
    }
}
Exemple #2
0
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);
    }
}
Exemple #3
0
void rt2x00usb_kill_tx_queue(struct data_queue *queue)
{
	rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX,
				   rt2x00usb_kill_tx_entry);
}
Exemple #4
0
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;
}