rt2x00 : hw support tdone implementation.
PATCH 1/2 rt2x00 : hw support tdone implementation.
This is an implementation that support WCID being the key_index coming from benoit and a change in the meaning of the tx fallback flag.
Signed-off-by Alban Browaeys <[email protected]>
--- drivers/net/wireless/rt2x00/rt2800pci.c | 116 ++++++++++++++--------------- drivers/net/wireless/rt2x00/rt2x00dev.c | 51 +++++++++++-- drivers/net/wireless/rt2x00/rt2x00queue.h | 6 +- 3 files changed, 103 insertions(+), 70 deletions(-)
drivers/net/wireless/rt2x00/rt2800pci.c +56 -60
@@ -920,100 +920,96 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) {struct data_queue *queue;struct queue_entry *entry; -struct queue_entry *entry_done; -struct queue_entry_priv_pci *entry_priv; +__le32 *txwi;struct txdone_entry_desc txdesc;u32 word;u32 reg; -u32 old_reg; -unsigned int type; -unsigned int index; -u16 mcs, real_mcs; - +int i; +int wcid, ack, pid, tx_wcid, tx_ack, tx_pid; +u16 mcs, tx_mcs; +/* -* During each loop we will compare the freshly read -* TX_STA_FIFO register value with the value read from -* the previous loop. If the 2 values are equal then -* we should stop processing because the chance it -* quite big that the device has been unplugged and -* we risk going into an endless loop. +* To avoid an endlees loop, we only read the TX_STA_FIFO register up +* to 256 times (this is enought to get all values from the FIFO). In +* normal situation, the loop is terminated when we reach a value with +* TX_STA_FIFO_VALID bit is 0. */ - old_reg =0 ; - -while (1 ) { + +for (i=0 ; i<256 ; i++) {rt2800_register_read (rt2x00dev,TX_STA_FIFO , ®);if (!rt2x00_get_field32 (reg,TX_STA_FIFO_VALID ))break ; -if (old_reg == reg) -break ; - old_reg = reg; + 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 );/* * Skip this entry when it contains an invalid * queue identication number. */ - type =rt2x00_get_field32 (reg,TX_STA_FIFO_PID_TYPE ) -1 ; -if (type >=QID_RX ) +if (pid <1 )continue ; - queue =rt2x00queue_get_queue (rt2x00dev, type); + queue =rt2x00queue_get_queue (rt2x00dev, pid -1 );if (unlikely (!queue))continue ;/* -* Skip this entry when it contains an invalid -* index number. +* Inside each queue, we process each entry in a chronological +* order. We first check that the queue is not empty. */ - index =rt2x00_get_field32 (reg,TX_STA_FIFO_WCID ) -1 ; -if (unlikely (index >= queue->limit)) +if (queue->length ==0 )continue ; + entry =rt2x00queue_get_entry (queue,Q_INDEX_DONE ); - entry = &queue->entries[index]; - entry_priv = entry->priv_data; -rt2x00_desc_read ((__le32 *)entry->skb->data,0 , &word); +/* Check if we got a match by looking at WCID/ACK/PID +* fields */ + txwi = (__le32 *)(entry->skb->data - + rt2x00dev->hw->extra_tx_headroom); - entry_done =rt2x00queue_get_entry (queue,Q_INDEX_DONE ); -while (entry != entry_done) { -/* -* Catch up. -* Just report any entries we missed as failed. -*/ -WARNING (rt2x00dev, -"TX status report missed for entry %d\n" , - entry_done->entry_idx); - - txdesc.flags =0 ; -__set_bit (TXDONE_UNKNOWN , &txdesc.flags); - txdesc.retry =0 ; +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 ); -rt2x00lib_txdone (entry_done, &txdesc); - entry_done =rt2x00queue_get_entry (queue,Q_INDEX_DONE ); - } +if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid)) +WARNING (rt2x00dev,"invalid TX_STA_FIFO content\n" );/* * Obtain the status about this packet. */ - txdesc.flags =0 ; -if (rt2x00_get_field32 (reg,TX_STA_FIFO_TX_SUCCESS )) -__set_bit (TXDONE_SUCCESS , &txdesc.flags); -else -__set_bit (TXDONE_FAILURE , &txdesc.flags); + mcs =rt2x00_get_field32 (reg,TX_STA_FIFO_MCS ); +rt2x00_desc_read (txwi,0 , &word); + tx_mcs =rt2x00_get_field32 (word,TXWI_W0_MCS );/* * Ralink has a retry mechanism using a global fallback -* table. We setup this fallback table to try immediate -* lower rate for all rates. In the TX_STA_FIFO, -* the MCS field contains the MCS used for the successfull -* transmission. If the first transmission succeed, -* we have mcs == tx_mcs. On the second transmission, -* we have mcs = tx_mcs - 1. So the number of -* retry is (tx_mcs - mcs). +* table. We setup this fallback table to try the immediate +* lower rate for all rates. In the TX_STA_FIFO, the MCS field +* always contains the MCS used for the last transmission, be +* it successful or not. */ - mcs =rt2x00_get_field32 (word,TXWI_W0_MCS ); - real_mcs =rt2x00_get_field32 (reg,TX_STA_FIFO_MCS ); + + txdesc.flags =0 ; +if (rt2x00_get_field32 (reg,TX_STA_FIFO_TX_SUCCESS )) { +/* +* Transmission succeeded. The number of retries is +* tx_mcs - mcs +*/ +__set_bit (TXDONE_SUCCESS , &txdesc.flags); + txdesc.retry = ((tx_mcs > mcs) ? tx_mcs - mcs :0 ); + }else { +/* +* Transmission failed. The number of retries is +* always 7 in this case (for a total number of 8 +* frames sent). +*/ +__set_bit (TXDONE_FAILURE , &txdesc.flags); + txdesc.retry =7 ; + } +__set_bit (TXDONE_FALLBACK , &txdesc.flags); - txdesc.retry = mcs -min (mcs, real_mcs);rt2x00lib_txdone (entry, &txdesc); }
drivers/net/wireless/rt2x00/rt2x00dev.c +43 -8
64 lines not on this page · raw message
drivers/net/wireless/rt2x00/rt2x00queue.h +4 -2
@@ -214,7 +214,7 @@ struct rxdone_entry_desc {* * @TXDONE_UNKNOWN: Hardware could not determine success of transmission. * @TXDONE_SUCCESS: Frame was successfully send -* @TXDONE_FALLBACK: Frame was successfully send using a fallback rate. +* @TXDONE_FALLBACK: Frame was sent using a fallback rate table. * @TXDONE_FAILURE: Frame was not successfully send * @TXDONE_EXCESSIVE_RETRY: In addition to &TXDONE_FAILURE, the * frame transmission failed due to excessive retries.
@@ -234,7 +234,9 @@ enum txdone_entry_desc_flags {* after the device is done with transmission. * * @flags: TX done flags (See &enum txdone_entry_desc_flags). -* @retry: Retry count. +* @retry: Retry count. If TXDONE_FALLBACK is not set, the frame was sent +* (retry+1) times at the same rate. If TXDONE_FALLBACK is set, the frame was +* sent once for each lower rates, up to (retry+1) times in total. */ struct txdone_entry_desc {unsigned long flags;
Signature · 1 line
1.7.0