| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 | 
							- From 0b0d556e0ebb6c966bc993e21a22a156812d8fdf Mon Sep 17 00:00:00 2001
 
- From: Stanislaw Gruszka <[email protected]>
 
- Date: Wed, 26 Sep 2018 12:24:54 +0200
 
- Subject: [PATCH 03/28] rt2800mmio: use txdone/txstatus routines from lib
 
- Use usb txdone/txstatus routines (now in rt2800libc) for mmio devices.
 
- Note this also change how we handle INT_SOURCE_CSR_TX_FIFO_STATUS
 
- interrupt. Now it is disabled since IRQ routine till end of the txstatus
 
- tasklet (the same behaviour like others interrupts). Reason to do not
 
- disable this interrupt was not to miss any tx status from 16 entries
 
- FIFO register. Now, since we check for tx status timeout, we can
 
- allow to miss some tx statuses. However this will be improved in further
 
- patch where I also implement read status FIFO register in the tasklet.
 
- Signed-off-by: Stanislaw Gruszka <[email protected]>
 
- Signed-off-by: Kalle Valo <[email protected]>
 
- ---
 
-  .../net/wireless/ralink/rt2x00/rt2800mmio.c   | 180 +-----------------
 
-  .../net/wireless/ralink/rt2x00/rt2x00queue.c  |   1 +
 
-  2 files changed, 9 insertions(+), 172 deletions(-)
 
- --- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
 
- +++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
 
- @@ -175,161 +175,6 @@ static void rt2800mmio_wakeup(struct rt2
 
-  	rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS);
 
-  }
 
-  
 
- -static bool rt2800mmio_txdone_entry_check(struct queue_entry *entry, u32 status)
 
- -{
 
- -	__le32 *txwi;
 
- -	u32 word;
 
- -	int wcid, tx_wcid;
 
- -
 
- -	wcid = rt2x00_get_field32(status, TX_STA_FIFO_WCID);
 
- -
 
- -	txwi = rt2800_drv_get_txwi(entry);
 
- -	word = rt2x00_desc_read(txwi, 1);
 
- -	tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID);
 
- -
 
- -	return (tx_wcid == wcid);
 
- -}
 
- -
 
- -static bool rt2800mmio_txdone_find_entry(struct queue_entry *entry, void *data)
 
- -{
 
- -	u32 status = *(u32 *)data;
 
- -
 
- -	/*
 
- -	 * rt2800pci hardware might reorder frames when exchanging traffic
 
- -	 * with multiple BA enabled STAs.
 
- -	 *
 
- -	 * For example, a tx queue
 
- -	 *    [ STA1 | STA2 | STA1 | STA2 ]
 
- -	 * can result in tx status reports
 
- -	 *    [ STA1 | STA1 | STA2 | STA2 ]
 
- -	 * when the hw decides to aggregate the frames for STA1 into one AMPDU.
 
- -	 *
 
- -	 * To mitigate this effect, associate the tx status to the first frame
 
- -	 * in the tx queue with a matching wcid.
 
- -	 */
 
- -	if (rt2800mmio_txdone_entry_check(entry, status) &&
 
- -	    !test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) {
 
- -		/*
 
- -		 * Got a matching frame, associate the tx status with
 
- -		 * the frame
 
- -		 */
 
- -		entry->status = status;
 
- -		set_bit(ENTRY_DATA_STATUS_SET, &entry->flags);
 
- -		return true;
 
- -	}
 
- -
 
- -	/* Check the next frame */
 
- -	return false;
 
- -}
 
- -
 
- -static bool rt2800mmio_txdone_match_first(struct queue_entry *entry, void *data)
 
- -{
 
- -	u32 status = *(u32 *)data;
 
- -
 
- -	/*
 
- -	 * Find the first frame without tx status and assign this status to it
 
- -	 * regardless if it matches or not.
 
- -	 */
 
- -	if (!test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) {
 
- -		/*
 
- -		 * Got a matching frame, associate the tx status with
 
- -		 * the frame
 
- -		 */
 
- -		entry->status = status;
 
- -		set_bit(ENTRY_DATA_STATUS_SET, &entry->flags);
 
- -		return true;
 
- -	}
 
- -
 
- -	/* Check the next frame */
 
- -	return false;
 
- -}
 
- -static bool rt2800mmio_txdone_release_entries(struct queue_entry *entry,
 
- -					      void *data)
 
- -{
 
- -	if (test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) {
 
- -		rt2800_txdone_entry(entry, entry->status,
 
- -				    rt2800mmio_get_txwi(entry), true);
 
- -		return false;
 
- -	}
 
- -
 
- -	/* No more frames to release */
 
- -	return true;
 
- -}
 
- -
 
- -static bool rt2800mmio_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,
 
- -						rt2800mmio_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,
 
- -							rt2800mmio_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,
 
- -					   rt2800mmio_txdone_release_entries);
 
- -
 
- -		if (--max_tx_done == 0)
 
- -			break;
 
- -	}
 
- -
 
- -	return !max_tx_done;
 
- -}
 
- -
 
-  static inline void rt2800mmio_enable_interrupt(struct rt2x00_dev *rt2x00dev,
 
-  					       struct rt2x00_field32 irq_field)
 
-  {
 
- @@ -349,14 +194,14 @@ static inline void rt2800mmio_enable_int
 
-  void rt2800mmio_txstatus_tasklet(unsigned long data)
 
-  {
 
-  	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
 
- -	if (rt2800mmio_txdone(rt2x00dev))
 
- -		tasklet_schedule(&rt2x00dev->txstatus_tasklet);
 
-  
 
- -	/*
 
- -	 * No need to enable the tx status interrupt here as we always
 
- -	 * leave it enabled to minimize the possibility of a tx status
 
- -	 * register overflow. See comment in interrupt handler.
 
- -	 */
 
- +	rt2800_txdone(rt2x00dev);
 
- +
 
- +	rt2800_txdone_nostatus(rt2x00dev);
 
- +
 
- +	if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
 
- +		rt2800mmio_enable_interrupt(rt2x00dev,
 
- +					    INT_SOURCE_CSR_TX_FIFO_STATUS);
 
-  }
 
-  EXPORT_SYMBOL_GPL(rt2800mmio_txstatus_tasklet);
 
-  
 
- @@ -440,10 +285,6 @@ static void rt2800mmio_txstatus_interrup
 
-  	 * because we can schedule the tasklet multiple times (when the
 
-  	 * interrupt fires again during tx status processing).
 
-  	 *
 
- -	 * Furthermore we don't disable the TX_FIFO_STATUS
 
- -	 * interrupt here but leave it enabled so that the TX_STA_FIFO
 
- -	 * can also be read while the tx status tasklet gets executed.
 
- -	 *
 
-  	 * Since we have only one producer and one consumer we don't
 
-  	 * need to lock the kfifo.
 
-  	 */
 
- @@ -485,13 +326,8 @@ irqreturn_t rt2800mmio_interrupt(int irq
 
-  	 */
 
-  	mask = ~reg;
 
-  
 
- -	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) {
 
- +	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS))
 
-  		rt2800mmio_txstatus_interrupt(rt2x00dev);
 
- -		/*
 
- -		 * Never disable the TX_FIFO_STATUS interrupt.
 
- -		 */
 
- -		rt2x00_set_field32(&mask, INT_MASK_CSR_TX_FIFO_STATUS, 1);
 
- -	}
 
-  
 
-  	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT))
 
-  		tasklet_hi_schedule(&rt2x00dev->pretbtt_tasklet);
 
- --- a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
 
- +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
 
- @@ -113,6 +113,7 @@ int rt2x00queue_map_txskb(struct queue_e
 
-  		return -ENOMEM;
 
-  
 
-  	skbdesc->flags |= SKBDESC_DMA_MAPPED_TX;
 
- +	rt2x00lib_dmadone(entry);
 
-  	return 0;
 
-  }
 
-  EXPORT_SYMBOL_GPL(rt2x00queue_map_txskb);
 
 
  |