rt2x00
cover rt2x00
Hi John,
Here is a minor update for rt2x00, no version bump this time since the number of patches is so limited. If possible queue these for 2.6.24.
The first one fixes a bug in the chipset revision detection, where devices were being accepted by the rt2500usb driver while they should be dropped (in favour of rt73usb).
The second patch is code cleaning, but the third patch depends on this one. Finally the first patch fixes the dreadfull "non-free entry in the non-full queue" queue messages which effectively resulted in the TX shutting down comlpletely with rt61pci.
Ivo
PATCH 1/3 rt2x00: Fix chipset revision validation
The validation of the chipset revision was broken since for rt2500usb and rt73usb different registers should be read. When rt2500usb was loaded for a rt73 device it would false think the chipset was correct because the wrong register was read and validated.
This has been fixed by expanding the check to also see if the first 4 bits of the revision is not-0 (When reading the wrong register offset the returned value is usually 0 which can be interpreted as invalid)
--- drivers/net/wireless/rt2x00/rt2500pci.c | 4 ++-- drivers/net/wireless/rt2x00/rt2500usb.c | 4 ++-- drivers/net/wireless/rt2x00/rt2x00.h | 8 +++++--- drivers/net/wireless/rt2x00/rt73usb.c | 2 +- 4 files changed, 10 insertions(+), 8 deletions(-)
drivers/net/wireless/rt2x00/rt2500pci.c +2 -2
@@ -617,7 +617,7 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev)* up to version C the link tuning should halt after 20 * seconds. */ -if (rt2x00_get_rev (&rt2x00dev->chip) <RT2560_VERSION_D && +if (rt2x00_rev (&rt2x00dev->chip) <RT2560_VERSION_D && rt2x00dev->link.count >20 )return ;
@@ -627,7 +627,7 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev)* Chipset versions C and lower should directly continue * to the dynamic CCA tuning. */ -if (rt2x00_get_rev (&rt2x00dev->chip) <RT2560_VERSION_D ) +if (rt2x00_rev (&rt2x00dev->chip) <RT2560_VERSION_D ) goto dynamic_cca_tune;/*
drivers/net/wireless/rt2x00/rt2500usb.c +2 -2
@@ -791,7 +791,7 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev)rt2x00_set_field16 (®,MAC_CSR1_HOST_READY ,1 );rt2500usb_register_write (rt2x00dev,MAC_CSR1 , reg); -if (rt2x00_get_rev (&rt2x00dev->chip) >=RT2570_VERSION_C ) { +if (rt2x00_rev (&rt2x00dev->chip) >=RT2570_VERSION_C ) {rt2500usb_register_read (rt2x00dev,PHY_CSR2 , ®);rt2x00_set_field16 (®,PHY_CSR2_LNA ,0 ); }else {
@@ -1299,7 +1299,7 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)rt2500usb_register_read (rt2x00dev,MAC_CSR0 , ®);rt2x00_set_chip (rt2x00dev,RT2570 , value, reg); -if (rt2x00_rev (&rt2x00dev->chip,0xffff0 )) { +if (!rt2x00_check_rev (&rt2x00dev->chip,0 )) {ERROR (rt2x00dev,"Invalid RT chipset detected.\n" );return -ENODEV ; }
drivers/net/wireless/rt2x00/rt2x00.h +5 -3
@@ -849,14 +849,16 @@ static inline char rt2x00_rf(const struct rt2x00_chip *chipset, const u16 chip)return (chipset->rf == chip); } -static inline u16 rt2x00_get_rev (const struct rt2x00_chip *chipset) +static inline u16 rt2x00_rev (const struct rt2x00_chip *chipset) {return chipset->rev; } -static inline u16 rt2x00_rev (const struct rt2x00_chip *chipset,const u32 mask) +static inline u16 rt2x00_check_rev (const struct rt2x00_chip *chipset, +const u32 rev) { -return chipset->rev & mask; +return (((chipset->rev &0xffff0 ) == rev) && + !!(chipset->rev &0x0000f )); }/*
drivers/net/wireless/rt2x00/rt73usb.c +1 -1
@@ -1530,7 +1530,7 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)rt73usb_register_read (rt2x00dev,MAC_CSR0 , ®);rt2x00_set_chip (rt2x00dev,RT2571 , value, reg); -if (!rt2x00_rev (&rt2x00dev->chip,0x25730 )) { +if (!rt2x00_check_rev (&rt2x00dev->chip,0x25730 )) {ERROR (rt2x00dev,"Invalid RT chipset detected.\n" );return -ENODEV ; }
Signature · 1 line
1.5.3.4
PATCH 2/3 rt2x00: Move duplicate code into rt2x00pci_txdone()
In reply to Ivo van Doornrt2400pci, rt2500pci and rt61 require different txdone handling, but the code that pushes the frame upstream and cleans up the entry is identical to all of them.
This will create the function rt2x00pci_txdone() to remove the duplicate code.
--- drivers/net/wireless/rt2x00/rt2400pci.c | 20 +----------------- drivers/net/wireless/rt2x00/rt2500pci.c | 20 +----------------- drivers/net/wireless/rt2x00/rt2x00pci.c | 33 ++++++++++++++++++++++++++++++- drivers/net/wireless/rt2x00/rt2x00pci.h | 4 ++- drivers/net/wireless/rt2x00/rt61pci.c | 19 +---------------- 5 files changed, 38 insertions(+), 58 deletions(-)
drivers/net/wireless/rt2x00/rt2400pci.c +1 -19
@@ -1167,26 +1167,8 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue) tx_status =rt2x00_get_field32 (word,TXD_W0_RESULT ); retry =rt2x00_get_field32 (word,TXD_W0_RETRY_COUNT ); -rt2x00lib_txdone (entry, tx_status, retry); - -/* -* Make this entry available for reuse. -*/ - entry->flags =0 ; -rt2x00_set_field32 (&word,TXD_W0_VALID ,0 ); -rt2x00_desc_write (txd,0 , word); -rt2x00_ring_index_done_inc (ring); +rt2x00pci_txdone (rt2x00dev, entry, tx_status, retry); } - -/* -* If the data ring was full before the txdone handler -* we must make sure the packet queue in the mac80211 stack -* is reenabled when the txdone handler has finished. -*/ - entry = ring->entry; -if (!rt2x00_ring_full (ring)) -ieee80211_wake_queue (rt2x00dev->hw, - entry->tx_status.control.queue); }static irqreturn_t rt2400pci_interrupt (int irq,void *dev_instance)
drivers/net/wireless/rt2x00/rt2500pci.c +1 -19
@@ -1298,26 +1298,8 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue) tx_status =rt2x00_get_field32 (word,TXD_W0_RESULT ); retry =rt2x00_get_field32 (word,TXD_W0_RETRY_COUNT ); -rt2x00lib_txdone (entry, tx_status, retry); - -/* -* Make this entry available for reuse. -*/ - entry->flags =0 ; -rt2x00_set_field32 (&word,TXD_W0_VALID ,0 ); -rt2x00_desc_write (txd,0 , word); -rt2x00_ring_index_done_inc (ring); +rt2x00pci_txdone (rt2x00dev, entry, tx_status, retry); } - -/* -* If the data ring was full before the txdone handler -* we must make sure the packet queue in the mac80211 stack -* is reenabled when the txdone handler has finished. -*/ - entry = ring->entry; -if (!rt2x00_ring_full (ring)) -ieee80211_wake_queue (rt2x00dev->hw, - entry->tx_status.control.queue); }static irqreturn_t rt2500pci_interrupt (int irq,void *dev_instance)
drivers/net/wireless/rt2x00/rt2x00pci.c +32 -1
@@ -116,7 +116,7 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,EXPORT_SYMBOL_GPL (rt2x00pci_write_tx_data);/* -* RX data handlers. +* TX/RX data handlers. */ void rt2x00pci_rxdone (struct rt2x00_dev *rt2x00dev) {
@@ -165,6 +165,37 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) }EXPORT_SYMBOL_GPL (rt2x00pci_rxdone); +void rt2x00pci_txdone (struct rt2x00_dev *rt2x00dev,struct data_entry *entry, +const int tx_status,const int retry) +{ +u32 word; + +rt2x00lib_txdone (entry, tx_status, retry); + +/* +* Make this entry available for reuse. +*/ + entry->flags =0 ; + +rt2x00_desc_read (entry->priv,0 , &word); +rt2x00_set_field32 (&word,TXD_ENTRY_OWNER_NIC ,0 ); +rt2x00_set_field32 (&word,TXD_ENTRY_VALID ,0 ); +rt2x00_desc_write (entry->priv,0 , word); + +rt2x00_ring_index_done_inc (entry->ring); + +/* +* If the data ring was full before the txdone handler +* we must make sure the packet queue in the mac80211 stack +* is reenabled when the txdone handler has finished. +*/ +if (!rt2x00_ring_full (entry->ring)) +ieee80211_wake_queue (rt2x00dev->hw, + entry->tx_status.control.queue); + +} +EXPORT_SYMBOL_GPL (rt2x00pci_txdone); +/* * Device initialization handlers. */
drivers/net/wireless/rt2x00/rt2x00pci.h +3 -1
@@ -101,9 +101,11 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev, struct ieee80211_tx_control *control);/* -* RX data handlers. +* RX/TX data handlers. */ void rt2x00pci_rxdone (struct rt2x00_dev *rt2x00dev); +void rt2x00pci_txdone (struct rt2x00_dev *rt2x00dev,struct data_entry *entry, +const int tx_status,const int retry);/* * Device initialization handlers.
drivers/net/wireless/rt2x00/rt61pci.c +1 -18
@@ -1767,24 +1767,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) tx_status =rt2x00_get_field32 (reg,STA_CSR4_TX_RESULT ); retry =rt2x00_get_field32 (reg,STA_CSR4_RETRY_COUNT ); -rt2x00lib_txdone (entry, tx_status, retry); - -/* -* Make this entry available for reuse. -*/ - entry->flags =0 ; -rt2x00_set_field32 (&word,TXD_W0_VALID ,0 ); -rt2x00_desc_write (txd,0 , word); -rt2x00_ring_index_done_inc (entry->ring); - -/* -* If the data ring was full before the txdone handler -* we must make sure the packet queue in the mac80211 stack -* is reenabled when the txdone handler has finished. -*/ -if (!rt2x00_ring_full (ring)) -ieee80211_wake_queue (rt2x00dev->hw, - entry->tx_status.control.queue); +rt2x00pci_txdone (rt2x00dev, entry, tx_status, retry); } }
Signature · 1 line
1.5.3.4
PATCH 3/3 rt2x00: Allow rt61 to catch up after a missing tx report
In reply to Ivo van DoornFrom: Mattias Nissler <[email protected]>
Sometimes it happens in the tx path that an entry given to the hardware isn't reported in the txdone handler. This ultimately led to the dreaded "non-free entry in the non-full queue" message and the stopping of the tx queue. Work around this issue by allowing the driver to also clear out previos entries in the txdone handler.
--- drivers/net/wireless/rt2x00/rt61pci.c | 13 +++++++++++++ 1 files changed, 13 insertions(+), 0 deletions(-)
drivers/net/wireless/rt2x00/rt61pci.c +13 -0
@@ -1708,6 +1708,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) {struct data_ring *ring;struct data_entry *entry; +struct data_entry *entry_done;__le32 *txd;u32 word;u32 reg;
@@ -1761,6 +1762,18 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) !rt2x00_get_field32(word, TXD_W0_VALID))return ; + entry_done =rt2x00_get_data_entry_done (ring); +while (entry != entry_done) { +/* Catch up. Just report any entries we missed as +* failed. */ +WARNING (rt2x00dev, +"TX status report missed for entry %p\n" , + entry_done); +rt2x00pci_txdone (rt2x00dev, entry_done,TX_FAIL_OTHER , +0 ); + entry_done =rt2x00_get_data_entry_done (ring); + } +/* * Obtain the status about this packet. */
Signature · 1 line
1.5.3.4