Please pull 'upstream' branch of rt2x00
Hi John,
Here is a quick followup release labeled 2.1.1. The previous release contained many bugs as it was mostly untested. Result was there were critical issues with it, of which some have now been fixed.
The most critical issues are random panics due to corrupt memory access, at the moment none of the drivers are displaying any activity yet where rt73usb is still crashing at random times.
Ivo
---
The following changes since commit d86916b7d36c4f0db8634fcc17fe2d747b317f17:
John W. Linville (1):
Merge branch 'at76' into everything
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/ivd/rt2x00.git/ upstream
Adam Baker (1):
rt2x00: correct address calc for queue private data
Ivo van Doorn (13):
rt2x00: Fix invalid DMA free
rt2x00: Make rt2x00 less verbose
rt2x00: Remove MGMT ring initialization
rt2x00: Select CONFIG_NEW_LEDS
rt2x00: make csr_cache and csr_addr an union
rt2x00: Fix scheduling while atomic errors in usb drivers
rt2x00: Add queue statistics to debugfs
rt2x00: Fix typo in debug statement
rt2x00: Fix skbdesc->data_len initialization
rt2x00: Fix queue->qid initialization
rt2x00: Cleanup Makefile
rt2x00: Kill guardian urb during disable_radio
rt2x00: Release rt2x00 2.1.1
drivers/net/wireless/rt2x00/Kconfig | 1 + drivers/net/wireless/rt2x00/Makefile | 41 +++++------- drivers/net/wireless/rt2x00/rt2400pci.c | 4 - drivers/net/wireless/rt2x00/rt2500pci.c | 4 - drivers/net/wireless/rt2x00/rt2500usb.c | 6 +-- drivers/net/wireless/rt2x00/rt2x00.h | 12 ++-- drivers/net/wireless/rt2x00/rt2x00debug.c | 90 ++++++++++++++++++++++---- drivers/net/wireless/rt2x00/rt2x00mac.c | 9 +++- drivers/net/wireless/rt2x00/rt2x00pci.c | 99 +++++++++++++++++++--------- drivers/net/wireless/rt2x00/rt2x00pci.h | 8 +- drivers/net/wireless/rt2x00/rt2x00queue.c | 36 ++++++----- drivers/net/wireless/rt2x00/rt2x00usb.c | 37 ++++++++--- drivers/net/wireless/rt2x00/rt61pci.c | 8 +-- drivers/net/wireless/rt2x00/rt61pci.h | 2 +- drivers/net/wireless/rt2x00/rt73usb.c | 8 +-- 15 files changed, 231 insertions(+), 134 deletions(-)
PATCH 1/14 rt2x00: Fix invalid DMA free
Be more strict when using the queue_entry_priv_pci_rx and queue_entry_priv_pci_tx structures. Only use a particular type that matches the queue type.
When freeing the DMA the priv_tx->data and priv_tx->dma was used. This is incorrect since the start of the DMA was in fact the priv_tx->desc pointer. Instead of recalculating the dma_addr_t for the DMA start this patch will swap the data and descriptor part of the allocated memory.
--- drivers/net/wireless/rt2x00/rt2x00pci.c | 85 ++++++++++++++++++++++--------- 1 files changed, 60 insertions(+), 25 deletions(-)
drivers/net/wireless/rt2x00/rt2x00pci.c +60 -25
@@ -186,38 +186,44 @@ EXPORT_SYMBOL_GPL(rt2x00pci_txdone);/* * Device initialization handlers. */ -#define dma_size (__queue) \ -({ \ - (__queue)->limit * \ - ((__queue)->desc_size + (__queue)->data_size);\ +#define desc_size (__queue) \ +({ \ + ((__queue)->limit * (__queue)->desc_size);\ }) -#define priv_offset (__queue, __base, __i) \ -({ \ - (__base) + ((__i) * (__queue)->desc_size); \ +#define data_size (__queue) \ +({ \ + ((__queue)->limit * (__queue)->data_size);\ }) -#define data_addr_offset (__queue, __base, __i) \ -({ \ - (__base) + \ - ((__queue)->limit * (__queue)->desc_size) + \ - ((__i) * (__queue)->data_size); \ +#define dma_size (__queue) \ +({ \ + data_size(__queue) + desc_size(__queue);\ }) -#define data_dma_offset (__queue, __base, __i) \ -({ \ - (__base) + \ - ((__queue)->limit * (__queue)->desc_size) + \ - ((__i) * (__queue)->data_size); \ +#define desc_offset (__queue, __base, __i) \ +({ \ + (__base) + data_size(__queue) + \ + ((__i) * (__queue)->desc_size); \ +}) + +#define data_offset (__queue, __base, __i) \ +({ \ + (__base) + \ + ((__i) * (__queue)->data_size); \ })static int rt2x00pci_alloc_queue_dma (struct rt2x00_dev *rt2x00dev,struct data_queue *queue) {struct pci_dev *pci_dev =rt2x00dev_pci (rt2x00dev); +struct queue_entry_priv_pci_rx *priv_rx;struct queue_entry_priv_pci_tx *priv_tx; +void *desc;void *data_addr; +void *data;dma_addr_t data_dma; +dma_addr_t dma;unsigned int i;/*
@@ -227,14 +233,27 @@ static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev,if (!data_addr)return -ENOMEM ; +memset (data_addr,0 ,dma_size (queue)); +/* * Initialize all queue entries to contain valid addresses. */ for (i =0 ; i < queue->limit; i++) { - priv_tx = queue->entries[i].priv_data; - priv_tx->desc =priv_offset (queue, data_addr, i); - priv_tx->data =data_addr_offset (queue, data_addr, i); - priv_tx->dma =data_dma_offset (queue, data_dma, i); + desc =desc_offset (queue, data_addr, i); + data =data_offset (queue, data_addr, i); + dma =data_offset (queue, data_dma, i); + +if (queue->qid ==QID_RX ) { + priv_rx = queue->entries[i].priv_data; + priv_rx->desc = desc; + priv_rx->data = data; + priv_rx->dma = dma; + }else { + priv_tx = queue->entries[i].priv_data; + priv_tx->desc = desc; + priv_tx->data = data; + priv_tx->dma = dma; + } }return 0 ;
@@ -244,12 +263,28 @@ static void rt2x00pci_free_queue_dma(struct rt2x00_dev *rt2x00dev, struct data_queue *queue) {struct pci_dev *pci_dev =rt2x00dev_pci (rt2x00dev); -struct queue_entry_priv_pci_tx *priv_tx = queue->entries[0 ].priv_data; +struct queue_entry_priv_pci_rx *priv_rx; +struct queue_entry_priv_pci_tx *priv_tx; +void *data_addr; +dma_addr_t data_dma; + +if (queue->qid ==QID_RX ) { + priv_rx = queue->entries[0 ].priv_data; + data_addr = priv_rx->data; + data_dma = priv_rx->dma; + + priv_rx->data =NULL ; + }else { + priv_tx = queue->entries[0 ].priv_data; + data_addr = priv_tx->data; + data_dma = priv_tx->dma; + + priv_tx->data =NULL ; + } -if (priv_tx->data) +if (data_addr)pci_free_consistent (pci_dev,dma_size (queue), - priv_tx->data, priv_tx->dma); - priv_tx->data =NULL ; + data_addr, data_dma); }int rt2x00pci_initialize (struct rt2x00_dev *rt2x00dev)
Signature · 1 line
1.5.4
PATCH 2/14 rt2x00: Make rt2x00 less verbose
In reply to Ivo van DoornRemove the debug messages regarding initialization from EEPROM. The values are vendor specific, and are not really needed for debug purposes. If they ever become usefull we still have access to them through debugfs which also prints the exact same values...
--- drivers/net/wireless/rt2x00/rt2400pci.c | 4 ---- drivers/net/wireless/rt2x00/rt2500pci.c | 4 ---- drivers/net/wireless/rt2x00/rt2500usb.c | 4 ---- drivers/net/wireless/rt2x00/rt61pci.c | 4 ---- drivers/net/wireless/rt2x00/rt73usb.c | 4 ---- 5 files changed, 0 insertions(+), 20 deletions(-)
drivers/net/wireless/rt2x00/rt2400pci.c +0 -4
@@ -797,19 +797,15 @@ continue_csr_init:rt2400pci_bbp_write (rt2x00dev,30 ,0x21 );rt2400pci_bbp_write (rt2x00dev,31 ,0x00 ); -DEBUG (rt2x00dev,"Start initialization from EEPROM...\n" );for (i =0 ; i <EEPROM_BBP_SIZE ; i++) {rt2x00_eeprom_read (rt2x00dev,EEPROM_BBP_START + i, &eeprom);if (eeprom !=0xffff && eeprom !=0x0000 ) { reg_id =rt2x00_get_field16 (eeprom,EEPROM_BBP_REG_ID ); value =rt2x00_get_field16 (eeprom,EEPROM_BBP_VALUE ); -DEBUG (rt2x00dev,"BBP: 0x%02x, value: 0x%02x.\n" , - reg_id, value);rt2400pci_bbp_write (rt2x00dev, reg_id, value); } } -DEBUG (rt2x00dev,"...End initialization from EEPROM.\n" );return 0 ; }
drivers/net/wireless/rt2x00/rt2500pci.c +0 -4
@@ -951,19 +951,15 @@ continue_csr_init:rt2500pci_bbp_write (rt2x00dev,61 ,0x6d );rt2500pci_bbp_write (rt2x00dev,62 ,0x10 ); -DEBUG (rt2x00dev,"Start initialization from EEPROM...\n" );for (i =0 ; i <EEPROM_BBP_SIZE ; i++) {rt2x00_eeprom_read (rt2x00dev,EEPROM_BBP_START + i, &eeprom);if (eeprom !=0xffff && eeprom !=0x0000 ) { reg_id =rt2x00_get_field16 (eeprom,EEPROM_BBP_REG_ID ); value =rt2x00_get_field16 (eeprom,EEPROM_BBP_VALUE ); -DEBUG (rt2x00dev,"BBP: 0x%02x, value: 0x%02x.\n" , - reg_id, value);rt2500pci_bbp_write (rt2x00dev, reg_id, value); } } -DEBUG (rt2x00dev,"...End initialization from EEPROM.\n" );return 0 ; }
drivers/net/wireless/rt2x00/rt2500usb.c +0 -4
@@ -881,19 +881,15 @@ continue_csr_init:rt2500usb_bbp_write (rt2x00dev,62 ,0x10 );rt2500usb_bbp_write (rt2x00dev,75 ,0xff ); -DEBUG (rt2x00dev,"Start initialization from EEPROM...\n" );for (i =0 ; i <EEPROM_BBP_SIZE ; i++) {rt2x00_eeprom_read (rt2x00dev,EEPROM_BBP_START + i, &eeprom);if (eeprom !=0xffff && eeprom !=0x0000 ) { reg_id =rt2x00_get_field16 (eeprom,EEPROM_BBP_REG_ID ); value =rt2x00_get_field16 (eeprom,EEPROM_BBP_VALUE ); -DEBUG (rt2x00dev,"BBP: 0x%02x, value: 0x%02x.\n" , - reg_id, value);rt2500usb_bbp_write (rt2x00dev, reg_id, value); } } -DEBUG (rt2x00dev,"...End initialization from EEPROM.\n" );return 0 ; }
drivers/net/wireless/rt2x00/rt61pci.c +0 -4
@@ -1282,19 +1282,15 @@ continue_csr_init:rt61pci_bbp_write (rt2x00dev,102 ,0x16 );rt61pci_bbp_write (rt2x00dev,107 ,0x04 ); -DEBUG (rt2x00dev,"Start initialization from EEPROM...\n" );for (i =0 ; i <EEPROM_BBP_SIZE ; i++) {rt2x00_eeprom_read (rt2x00dev,EEPROM_BBP_START + i, &eeprom);if (eeprom !=0xffff && eeprom !=0x0000 ) { reg_id =rt2x00_get_field16 (eeprom,EEPROM_BBP_REG_ID ); value =rt2x00_get_field16 (eeprom,EEPROM_BBP_VALUE ); -DEBUG (rt2x00dev,"BBP: 0x%02x, value: 0x%02x.\n" , - reg_id, value);rt61pci_bbp_write (rt2x00dev, reg_id, value); } } -DEBUG (rt2x00dev,"...End initialization from EEPROM.\n" );return 0 ; }
drivers/net/wireless/rt2x00/rt73usb.c +0 -4
@@ -1087,19 +1087,15 @@ continue_csr_init:rt73usb_bbp_write (rt2x00dev,102 ,0x16 );rt73usb_bbp_write (rt2x00dev,107 ,0x04 ); -DEBUG (rt2x00dev,"Start initialization from EEPROM...\n" );for (i =0 ; i <EEPROM_BBP_SIZE ; i++) {rt2x00_eeprom_read (rt2x00dev,EEPROM_BBP_START + i, &eeprom);if (eeprom !=0xffff && eeprom !=0x0000 ) { reg_id =rt2x00_get_field16 (eeprom,EEPROM_BBP_REG_ID ); value =rt2x00_get_field16 (eeprom,EEPROM_BBP_VALUE ); -DEBUG (rt2x00dev,"BBP: 0x%02x, value: 0x%02x.\n" , - reg_id, value);rt73usb_bbp_write (rt2x00dev, reg_id, value); } } -DEBUG (rt2x00dev,"...End initialization from EEPROM.\n" );return 0 ; }
Signature · 1 line
1.5.4
PATCH 3/14 rt2x00: Remove MGMT ring initialization
In reply to Ivo van DoornRemove the last remnants of the MGMT ring initialization from rt61pci.ko
--- drivers/net/wireless/rt2x00/rt61pci.c | 2 -- drivers/net/wireless/rt2x00/rt61pci.h | 2 +- 2 files changed, 1 insertions(+), 3 deletions(-)
drivers/net/wireless/rt2x00/rt61pci.c +0 -2
@@ -1070,7 +1070,6 @@ static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev)rt2x00_set_field32 (®,TX_DMA_DST_CSR_DEST_AC1 ,2 );rt2x00_set_field32 (®,TX_DMA_DST_CSR_DEST_AC2 ,2 );rt2x00_set_field32 (®,TX_DMA_DST_CSR_DEST_AC3 ,2 ); -rt2x00_set_field32 (®,TX_DMA_DST_CSR_DEST_MGMT ,0 );rt2x00pci_register_write (rt2x00dev,TX_DMA_DST_CSR , reg);rt2x00pci_register_read (rt2x00dev,LOAD_TX_RING_CSR , ®);
@@ -1078,7 +1077,6 @@ static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev)rt2x00_set_field32 (®,LOAD_TX_RING_CSR_LOAD_TXD_AC1 ,1 );rt2x00_set_field32 (®,LOAD_TX_RING_CSR_LOAD_TXD_AC2 ,1 );rt2x00_set_field32 (®,LOAD_TX_RING_CSR_LOAD_TXD_AC3 ,1 ); -rt2x00_set_field32 (®,LOAD_TX_RING_CSR_LOAD_TXD_MGMT ,0 );rt2x00pci_register_write (rt2x00dev,LOAD_TX_RING_CSR , reg);rt2x00pci_register_read (rt2x00dev,RX_CNTL_CSR , ®);
drivers/net/wireless/rt2x00/rt61pci.h +1 -1
@@ -880,7 +880,7 @@ struct hw_pairwise_ta_entry {#define TX_CNTL_CSR_ABORT_TX_MGMT FIELD32(0x00100000)/* -* LOAD_TX_RING_CSR: Load RX de +* LOAD_TX_RING_CSR: Load RX desriptor */ #define LOAD_TX_RING_CSR 0x3434#define LOAD_TX_RING_CSR_LOAD_TXD_AC0 FIELD32(0x00000001)
Signature · 1 line
1.5.4
PATCH 4/14 rt2x00: correct address calc for queue private data
In reply to Ivo van DoornFrom: Adam Baker <[email protected]>
When calculating the offset to add to the queue entry base to get the individual entry's private data area the base address must be treated as a char * not a struct queue_entry so we can do byte oriented pointer arithmetic with it.
--- drivers/net/wireless/rt2x00/rt2x00queue.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
drivers/net/wireless/rt2x00/rt2x00queue.c +2 -1
@@ -160,7 +160,8 @@ static int rt2x00queue_alloc_entries(struct data_queue *queue,return -ENOMEM ;#define QUEUE_ENTRY_PRIV_OFFSET (__base, __index, __limit, __esize, __psize) \ - ( (__base) + ((__limit) * (__esize)) + ((__index) * (__psize)) ) + ( ((char *)(__base)) + ((__limit) * (__esize)) + \ + ((__index) * (__psize)) )for (i =0 ; i < queue->limit; i++) { entries[i].flags =0 ;
Signature · 1 line
1.5.4
PATCH 5/14 rt2x00: Select CONFIG_NEW_LEDS
In reply to Ivo van DoornSelect CONFIG_NEW_LEDS before selecting the other LED config options. This fixes a link error when NEW_LEDS was disabled.
--- drivers/net/wireless/rt2x00/Kconfig | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
drivers/net/wireless/rt2x00/Kconfig +1 -0
@@ -41,6 +41,7 @@ config RT2X00_LIB_RFKILL config RT2X00_LIB_LEDS boolean depends on RT2X00_LIB + select NEW_LEDS select LEDS_CLASS select LEDS_TRIGGERS select MAC80211_LEDS
Signature · 1 line
1.5.4
PATCH 6/14 rt2x00: make csr_cache and csr_addr an union
In reply to Ivo van DoornThe csr_cache and csr_addr pointers are both the same size and they are never used both by the same driver. This makes them a nice candidate for an union.
We could merge into 1 pointer, but that would either upset sparse, or require a lot of __force casts.
--- drivers/net/wireless/rt2x00/rt2x00.h | 10 ++++++---- drivers/net/wireless/rt2x00/rt2x00pci.c | 10 +++++----- drivers/net/wireless/rt2x00/rt2x00pci.h | 8 ++++---- drivers/net/wireless/rt2x00/rt2x00usb.c | 16 ++++++++-------- 4 files changed, 23 insertions(+), 21 deletions(-)
drivers/net/wireless/rt2x00/rt2x00.h +6 -4
@@ -707,11 +707,13 @@ struct rt2x00_dev {/* * Register pointers -* csr_addr: Base register address. (PCI) -* csr_cache: CSR cache for usb_control_msg. (USB) +* csr.base: CSR base register address. (PCI) +* csr.cache: CSR cache for usb_control_msg. (USB) */ -void __iomem *csr_addr; -void *csr_cache; +union csr { +void __iomem *base; +void *cache; + } csr;/* * Mutex to protect register accesses on USB devices.
drivers/net/wireless/rt2x00/rt2x00pci.c +5 -5
@@ -350,9 +350,9 @@ static void rt2x00pci_free_reg(struct rt2x00_dev *rt2x00dev)kfree (rt2x00dev->eeprom); rt2x00dev->eeprom =NULL ; -if (rt2x00dev->csr_addr) { -iounmap (rt2x00dev->csr_addr); - rt2x00dev->csr_addr =NULL ; +if (rt2x00dev->csr.base) { +iounmap (rt2x00dev->csr.base); + rt2x00dev->csr.base =NULL ; } }
@@ -360,9 +360,9 @@ static int rt2x00pci_alloc_reg(struct rt2x00_dev *rt2x00dev) {struct pci_dev *pci_dev =rt2x00dev_pci (rt2x00dev); - rt2x00dev->csr_addr =ioremap (pci_resource_start (pci_dev,0 ), + rt2x00dev->csr.base =ioremap (pci_resource_start (pci_dev,0 ),pci_resource_len (pci_dev,0 )); -if (!rt2x00dev->csr_addr) +if (!rt2x00dev->csr.base) goto exit; rt2x00dev->eeprom =kzalloc (rt2x00dev->ops->eeprom_size,GFP_KERNEL );
drivers/net/wireless/rt2x00/rt2x00pci.h +4 -4
@@ -61,7 +61,7 @@ static inline void rt2x00pci_register_read(struct rt2x00_dev *rt2x00dev,const unsigned long offset, u32 *value) { - *value =readl (rt2x00dev->csr_addr + offset); + *value =readl (rt2x00dev->csr.base + offset); } static inline void
@@ -69,14 +69,14 @@ rt2x00pci_register_multiread(struct rt2x00_dev *rt2x00dev,const unsigned long offset, void *value, const u16 length) { - memcpy_fromio(value, rt2x00dev->csr_addr + offset, length); + memcpy_fromio(value, rt2x00dev->csr.base + offset, length); }static inline void rt2x00pci_register_write (struct rt2x00_dev *rt2x00dev,const unsigned long offset,u32 value) { -writel (value, rt2x00dev->csr_addr + offset); +writel (value, rt2x00dev->csr.base + offset); } static inline void
@@ -84,7 +84,7 @@ rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev,const unsigned long offset, void *value, const u16 length) { - memcpy_toio(rt2x00dev->csr_addr + offset, value, length); + memcpy_toio(rt2x00dev->csr.base + offset, value, length); }/*
drivers/net/wireless/rt2x00/rt2x00usb.c +8 -8
@@ -84,20 +84,20 @@ int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev,/* * Check for Cache availability. */ -if (unlikely (!rt2x00dev->csr_cache || buffer_length >CSR_CACHE_SIZE )) { +if (unlikely (!rt2x00dev->csr.cache || buffer_length >CSR_CACHE_SIZE )) {ERROR (rt2x00dev,"CSR cache not available.\n" );return -ENOMEM ; }if (requesttype ==USB_VENDOR_REQUEST_OUT ) -memcpy (rt2x00dev->csr_cache, buffer, buffer_length); +memcpy (rt2x00dev->csr.cache, buffer, buffer_length); status =rt2x00usb_vendor_request (rt2x00dev, request, requesttype, - offset,0 , rt2x00dev->csr_cache, + offset,0 , rt2x00dev->csr.cache, buffer_length, timeout);if (!status && requesttype ==USB_VENDOR_REQUEST_IN ) -memcpy (buffer, rt2x00dev->csr_cache, buffer_length); +memcpy (buffer, rt2x00dev->csr.cache, buffer_length);return status; }
@@ -562,14 +562,14 @@ static void rt2x00usb_free_reg(struct rt2x00_dev *rt2x00dev)kfree (rt2x00dev->eeprom); rt2x00dev->eeprom =NULL ; -kfree (rt2x00dev->csr_cache); - rt2x00dev->csr_cache =NULL ; +kfree (rt2x00dev->csr.cache); + rt2x00dev->csr.cache =NULL ; }static int rt2x00usb_alloc_reg (struct rt2x00_dev *rt2x00dev) { - rt2x00dev->csr_cache =kzalloc (CSR_CACHE_SIZE ,GFP_KERNEL ); -if (!rt2x00dev->csr_cache) + rt2x00dev->csr.cache =kzalloc (CSR_CACHE_SIZE ,GFP_KERNEL ); +if (!rt2x00dev->csr.cache) goto exit; rt2x00dev->eeprom =kzalloc (rt2x00dev->ops->eeprom_size,GFP_KERNEL );
Signature · 1 line
1.5.4
PATCH 7/14 rt2x00: Fix scheduling while atomic errors in usb drivers
In reply to Ivo van DoornCall rt2x00_config_intf() outside of the spinlock context since the call will sleep for USB drivers. By using the ieee80211_if_conf values as arguments we make keep access tp rt2x00_intf thread safe even without the lock.
--- drivers/net/wireless/rt2x00/rt2x00mac.c | 9 ++++++++- 1 files changed, 8 insertions(+), 1 deletions(-)
drivers/net/wireless/rt2x00/rt2x00mac.c +8 -1
@@ -334,11 +334,18 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw,*/ if (conf->type !=IEEE80211_IF_TYPE_AP )memcpy (&intf->bssid, conf->bssid,ETH_ALEN ); -rt2x00lib_config_intf (rt2x00dev, intf, conf->type,NULL , intf->bssid);spin_unlock (&intf->lock);/* +* Call rt2x00_config_intf() outside of the spinlock context since +* the call will sleep for USB drivers. By using the ieee80211_if_conf +* values as arguments we make keep access to rt2x00_intf thread safe +* even without the lock. +*/ +rt2x00lib_config_intf (rt2x00dev, intf, conf->type,NULL , conf->bssid); + +/* * We only need to initialize the beacon when master mode is enabled. */ if (conf->type !=IEEE80211_IF_TYPE_AP || !conf->beacon)
Signature · 1 line
1.5.4
PATCH 8/14 rt2x00: Add queue statistics to debugfs
In reply to Ivo van DoornRename "frame" folder to "queue" folder, add extra file to this folder which contains statistics about all hardware queues. This will help debugging and spotting problems in the queue indexing system.
--- drivers/net/wireless/rt2x00/rt2x00debug.c | 90 ++++++++++++++++++++++++----- 1 files changed, 76 insertions(+), 14 deletions(-)
drivers/net/wireless/rt2x00/rt2x00debug.c +76 -14
@@ -33,7 +33,7 @@#include "rt2x00lib.h" #include "rt2x00dump.h" -#define PRINT_LINE_LEN_MAX 32 +#define MAX_LINE_LENGTH 64struct rt2x00debug_intf {/*
@@ -60,8 +60,9 @@ struct rt2x00debug_intf {* - eeprom offset/value files * - bbp offset/value files * - rf offset/value files -* - frame dump folder +* - queue folder * - frame dump file +* - queue stats file */ struct dentry *driver_folder;struct dentry *driver_entry;
@@ -76,8 +77,9 @@ struct rt2x00debug_intf {struct dentry *bbp_val_entry;struct dentry *rf_off_entry;struct dentry *rf_val_entry; -struct dentry *frame_folder; -struct dentry *frame_dump_entry; +struct dentry *queue_folder; +struct dentry *queue_frame_dump_entry; +struct dentry *queue_stats_entry;/* * The frame dump file only allows a single reader,
@@ -269,6 +271,61 @@ static const struct file_operations rt2x00debug_fop_queue_dump = { .release = rt2x00debug_release_queue_dump, }; +static ssize_t rt2x00debug_read_queue_stats (struct file *file, +char __user *buf, +size_t length, +loff_t *offset) +{ +struct rt2x00debug_intf *intf = file->private_data; +struct data_queue *queue; +unsigned int lines =1 + intf->rt2x00dev->data_queues; +size_t size; +char *data; +char *temp; + +if (*offset) +return 0 ; + + data =kzalloc (lines *MAX_LINE_LENGTH ,GFP_KERNEL ); +if (!data) +return -ENOMEM ; + + temp = data + +sprintf (data,"qid\tcount\tlimit\tlength\tindex\tdone\tcrypto\n" ); + +queue_for_each (intf->rt2x00dev, queue) { +spin_lock (&queue->lock); + + temp +=sprintf (temp,"%d\t%d\t%d\t%d\t%d\t%d\t%d\n" , queue->qid, + queue->count, queue->limit, queue->length, + queue->index[Q_INDEX ], + queue->index[Q_INDEX_DONE ], + queue->index[Q_INDEX_CRYPTO ]); + +spin_unlock (&queue->lock); + } + + size =strlen (data); + size =min (size, length); + +if (copy_to_user (buf, data, size)) { +kfree (data); +return -EFAULT ; + } + +kfree (data); + + *offset += size; +return size; +} + +static const struct file_operations rt2x00debug_fop_queue_stats = { + .owner =THIS_MODULE , + .read = rt2x00debug_read_queue_stats, + .open = rt2x00debug_file_open, + .release = rt2x00debug_file_release, +}; +#define RT2X00DEBUGFS_OPS_READ (__name, __format, __type) \ static ssize_t rt2x00debug_read_##__name(struct file *file, \ char __user *buf, \
@@ -386,7 +443,7 @@ static struct dentry *rt2x00debug_create_file_driver(const char *name, {char *data; - data =kzalloc (3 *PRINT_LINE_LEN_MAX ,GFP_KERNEL ); + data =kzalloc (3 *MAX_LINE_LENGTH ,GFP_KERNEL );if (!data)return NULL ;
@@ -409,7 +466,7 @@ static struct dentry *rt2x00debug_create_file_chipset(const char *name,const struct rt2x00debug *debug = intf->debug;char *data; - data =kzalloc (8 *PRINT_LINE_LEN_MAX ,GFP_KERNEL ); + data =kzalloc (8 *MAX_LINE_LENGTH ,GFP_KERNEL );if (!data)return NULL ;
@@ -496,20 +553,24 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)#undef RT2X00DEBUGFS_CREATE_REGISTER_ENTRY - intf->frame_folder = -debugfs_create_dir ("frame" , intf->driver_folder); -if (IS_ERR (intf->frame_folder)) + intf->queue_folder = +debugfs_create_dir ("queue" , intf->driver_folder); +if (IS_ERR (intf->queue_folder)) goto exit; - intf->frame_dump_entry = -debugfs_create_file ("dump" ,S_IRUGO , intf->frame_folder, + intf->queue_frame_dump_entry = +debugfs_create_file ("dump" ,S_IRUGO , intf->queue_folder, intf, &rt2x00debug_fop_queue_dump); -if (IS_ERR (intf->frame_dump_entry)) +if (IS_ERR (intf->queue_frame_dump_entry)) goto exit;skb_queue_head_init (&intf->frame_dump_skbqueue);init_waitqueue_head (&intf->frame_dump_waitqueue); + intf->queue_stats_entry = +debugfs_create_file ("queue" ,S_IRUGO , intf->queue_folder, + intf, &rt2x00debug_fop_queue_stats); +return ; exit:
@@ -528,8 +589,9 @@ void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)skb_queue_purge (&intf->frame_dump_skbqueue); -debugfs_remove (intf->frame_dump_entry); -debugfs_remove (intf->frame_folder); +debugfs_remove (intf->queue_stats_entry); +debugfs_remove (intf->queue_frame_dump_entry); +debugfs_remove (intf->queue_folder);debugfs_remove (intf->rf_val_entry);debugfs_remove (intf->rf_off_entry);debugfs_remove (intf->bbp_val_entry);
Signature · 1 line
1.5.4
PATCH 9/14 rt2x00: Fix typo in debug statement
In reply to Ivo van DoornThe second eeprom recovery message is about
the RSSI offset for ieee802.11 A.
--- drivers/net/wireless/rt2x00/rt61pci.c | 2 +- drivers/net/wireless/rt2x00/rt73usb.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
drivers/net/wireless/rt2x00/rt61pci.c +1 -1
@@ -1876,7 +1876,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)rt2x00_set_field16 (&word,EEPROM_RSSI_OFFSET_A_1 ,0 );rt2x00_set_field16 (&word,EEPROM_RSSI_OFFSET_A_2 ,0 );rt2x00_eeprom_write (rt2x00dev,EEPROM_RSSI_OFFSET_A , word); -EEPROM (rt2x00dev,"RSSI OFFSET BG: 0x%04x\n" , word); +EEPROM (rt2x00dev,"RSSI OFFSET A: 0x%04x\n" , word); }else { value =rt2x00_get_field16 (word,EEPROM_RSSI_OFFSET_A_1 );if (value <-10 || value >10 )
drivers/net/wireless/rt2x00/rt73usb.c +1 -1
@@ -1496,7 +1496,7 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)rt2x00_set_field16 (&word,EEPROM_RSSI_OFFSET_A_1 ,0 );rt2x00_set_field16 (&word,EEPROM_RSSI_OFFSET_A_2 ,0 );rt2x00_eeprom_write (rt2x00dev,EEPROM_RSSI_OFFSET_A , word); -EEPROM (rt2x00dev,"RSSI OFFSET BG: 0x%04x\n" , word); +EEPROM (rt2x00dev,"RSSI OFFSET A: 0x%04x\n" , word); }else { value =rt2x00_get_field16 (word,EEPROM_RSSI_OFFSET_A_1 );if (value <-10 || value >10 )
Signature · 1 line
1.5.4
PATCH 10/14 rt2x00: Fix skbdesc->data_len initialization
In reply to Ivo van Doornskbdesc->data_len was not initialized correctly in rt2x00pci, rt2x00usb, rt2500usb and rt73usb.
The value was set to queue->data_size which means that the incorrect frame size was pased to the upper layers.
Correctly base the value on either the skb->len, or the rx frame size passed to the driver by the device.
--- drivers/net/wireless/rt2x00/rt2500usb.c | 2 +- drivers/net/wireless/rt2x00/rt2x00pci.c | 4 ++-- drivers/net/wireless/rt2x00/rt2x00usb.c | 2 +- drivers/net/wireless/rt2x00/rt73usb.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-)
drivers/net/wireless/rt2x00/rt2500usb.c +1 -1
@@ -1145,7 +1145,7 @@ static void rt2500usb_fill_rxdone(struct queue_entry *entry,* Set descriptor pointer. */ skbdesc->data = entry->skb->data; - skbdesc->data_len = entry->queue->data_size; + skbdesc->data_len = rxdesc->size; skbdesc->desc = entry->skb->data + rxdesc->size; skbdesc->desc_len = entry->queue->desc_size;
drivers/net/wireless/rt2x00/rt2x00pci.c +2 -2
@@ -63,7 +63,7 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev, skbdesc =get_skb_frame_desc (skb);memset (skbdesc,0 ,sizeof (*skbdesc)); skbdesc->data = skb->data; - skbdesc->data_len = queue->data_size; + skbdesc->data_len = skb->len; skbdesc->desc = priv_tx->desc; skbdesc->desc_len = queue->desc_size; skbdesc->entry = entry;
@@ -131,7 +131,7 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) skbdesc =get_skb_frame_desc (entry->skb);memset (skbdesc,0 ,sizeof (*skbdesc)); skbdesc->data = entry->skb->data; - skbdesc->data_len = queue->data_size; + skbdesc->data_len = entry->skb->len; skbdesc->desc = priv_rx->desc; skbdesc->desc_len = queue->desc_size; skbdesc->entry = entry;
drivers/net/wireless/rt2x00/rt2x00usb.c +1 -1
@@ -254,7 +254,7 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev, skbdesc =get_skb_frame_desc (skb);memset (skbdesc,0 ,sizeof (*skbdesc)); skbdesc->data = skb->data + queue->desc_size; - skbdesc->data_len = queue->data_size; + skbdesc->data_len = skb->len - queue->desc_size; skbdesc->desc = skb->data; skbdesc->desc_len = queue->desc_size; skbdesc->entry = entry;
drivers/net/wireless/rt2x00/rt73usb.c +1 -1
@@ -1395,7 +1395,7 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry,* Set descriptor and data pointer. */ skbdesc->data = entry->skb->data + entry->queue->desc_size; - skbdesc->data_len = entry->queue->data_size; + skbdesc->data_len = rxdesc->size; skbdesc->desc = entry->skb->data; skbdesc->desc_len = entry->queue->desc_size;
Signature · 1 line
1.5.4
PATCH 11/14 rt2x00: Fix queue->qid initialization
In reply to Ivo van DoornAs Adam Baker reported the queue->qid was not initialized correctly. The QID_AC_BE was assigned to the RX ring.
This will move the queue initialization into a seperate function and makes sure that all queues are initialized directly with the correct qids.
--- drivers/net/wireless/rt2x00/rt2x00queue.c | 33 +++++++++++++++------------- 1 files changed, 18 insertions(+), 15 deletions(-)
drivers/net/wireless/rt2x00/rt2x00queue.c +18 -15
@@ -228,6 +228,18 @@ void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev) } } +static void rt2x00queue_init (struct rt2x00_dev *rt2x00dev, +struct data_queue *queue,enum data_queue_qid qid) +{ +spin_lock_init (&queue->lock); + + queue->rt2x00dev = rt2x00dev; + queue->qid = qid; + queue->aifs =2 ; + queue->cw_min =5 ; + queue->cw_max =10 ; +} +int rt2x00queue_allocate (struct rt2x00_dev *rt2x00dev) {struct data_queue *queue;
@@ -265,24 +277,15 @@ int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev)* TX: cw_max: 2^10 = 1024. * BCN & Atim: qid = QID_MGMT */ - qid =QID_AC_BE ; -queue_for_each (rt2x00dev, queue) { -spin_lock_init (&queue->lock); +rt2x00queue_init (rt2x00dev, rt2x00dev->rx,QID_RX ); - queue->rt2x00dev = rt2x00dev; - queue->qid = qid++; - queue->aifs =2 ; - queue->cw_min =5 ; - queue->cw_max =10 ; - } + qid =QID_AC_BE ; +tx_queue_for_each (rt2x00dev, queue) +rt2x00queue_init (rt2x00dev, queue, qid++); -/* -* Fix non-TX data qid's -*/ - rt2x00dev->rx->qid =QID_RX ; - rt2x00dev->bcn[0 ].qid =QID_MGMT ; +rt2x00queue_init (rt2x00dev, &rt2x00dev->bcn[0 ],QID_MGMT );if (req_atim) - rt2x00dev->bcn[1 ].qid =QID_MGMT ; +rt2x00queue_init (rt2x00dev, &rt2x00dev->bcn[1 ],QID_MGMT );return 0 ; }
Signature · 1 line
1.5.4
PATCH 12/14 rt2x00: Cleanup Makefile
In reply to Ivo van DoornSimplify the way rt2x00 assigns new objects to the rt2x00lib module. This saves a few if statements and overall does this looks much nicer.
--- drivers/net/wireless/rt2x00/Makefile | 41 +++++++++++++-------------------- 1 files changed, 16 insertions(+), 25 deletions(-)
drivers/net/wireless/rt2x00/Makefile +16 -25
@@ -1,26 +1,17 @@ -rt2x00lib-objs := rt2x00dev.o rt2x00mac.o rt2x00config.o rt2x00queue.o +rt2x00lib-y += rt2x00dev.o +rt2x00lib-y += rt2x00mac.o +rt2x00lib-y += rt2x00config.o +rt2x00lib-y += rt2x00queue.o +rt2x00lib-$(CONFIG_RT2X00_LIB_DEBUGFS) += rt2x00debug.o +rt2x00lib-$(CONFIG_RT2X00_LIB_RFKILL) += rt2x00rfkill.o +rt2x00lib-$(CONFIG_RT2X00_LIB_FIRMWARE) += rt2x00firmware.o +rt2x00lib-$(CONFIG_RT2X00_LIB_LEDS) += rt2x00leds.o -ifeq ($(CONFIG_RT2X00_LIB_DEBUGFS),y) - rt2x00lib-objs += rt2x00debug.o -endif - -ifeq ($(CONFIG_RT2X00_LIB_RFKILL),y) - rt2x00lib-objs += rt2x00rfkill.o -endif - -ifeq ($(CONFIG_RT2X00_LIB_FIRMWARE),y) - rt2x00lib-objs += rt2x00firmware.o -endif - -ifeq ($(CONFIG_RT2X00_LIB_LEDS),y) - rt2x00lib-objs += rt2x00leds.o -endif - -obj-$(CONFIG_RT2X00_LIB) += rt2x00lib.o -obj-$(CONFIG_RT2X00_LIB_PCI) += rt2x00pci.o -obj-$(CONFIG_RT2X00_LIB_USB) += rt2x00usb.o -obj-$(CONFIG_RT2400PCI) += rt2400pci.o -obj-$(CONFIG_RT2500PCI) += rt2500pci.o -obj-$(CONFIG_RT61PCI) += rt61pci.o -obj-$(CONFIG_RT2500USB) += rt2500usb.o -obj-$(CONFIG_RT73USB) += rt73usb.o +obj-$(CONFIG_RT2X00_LIB) += rt2x00lib.o +obj-$(CONFIG_RT2X00_LIB_PCI) += rt2x00pci.o +obj-$(CONFIG_RT2X00_LIB_USB) += rt2x00usb.o +obj-$(CONFIG_RT2400PCI) += rt2400pci.o +obj-$(CONFIG_RT2500PCI) += rt2500pci.o +obj-$(CONFIG_RT61PCI) += rt61pci.o +obj-$(CONFIG_RT2500USB) += rt2500usb.o +obj-$(CONFIG_RT73USB) += rt73usb.o
Signature · 1 line
1.5.4
PATCH 13/14 rt2x00: Kill guardian urb during disable_radio
In reply to Ivo van DoornWhen the radio is being disabled we should also kill the guardian urb which could still be pending in the device.
--- drivers/net/wireless/rt2x00/rt2x00usb.c | 19 ++++++++++++++++++- 1 files changed, 18 insertions(+), 1 deletions(-)
drivers/net/wireless/rt2x00/rt2x00usb.c +18 -1
@@ -378,6 +378,7 @@ void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev) {struct queue_entry_priv_usb_rx *priv_rx;struct queue_entry_priv_usb_tx *priv_tx; +struct queue_entry_priv_usb_bcn *priv_bcn;struct data_queue *queue;unsigned int i;
@@ -392,12 +393,28 @@ void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev)usb_kill_urb (priv_rx->urb); } -txall_queue_for_each (rt2x00dev, queue) { +tx_queue_for_each (rt2x00dev, queue) {for (i =0 ; i < queue->limit; i++) { priv_tx = queue->entries[i].priv_data;usb_kill_urb (priv_tx->urb); } } + +for (i =0 ; i < rt2x00dev->bcn->limit; i++) { + priv_bcn = rt2x00dev->bcn->entries[i].priv_data; +usb_kill_urb (priv_bcn->urb); + +if (priv_bcn->guardian_urb) +usb_kill_urb (priv_bcn->guardian_urb); + } + +if (!test_bit (DRIVER_REQUIRE_ATIM_QUEUE , &rt2x00dev->flags)) +return ; + +for (i =0 ; i < rt2x00dev->bcn[1 ].limit; i++) { + priv_tx = rt2x00dev->bcn[1 ].entries[i].priv_data; +usb_kill_urb (priv_tx->urb); + } }EXPORT_SYMBOL_GPL (rt2x00usb_disable_radio);
Signature · 1 line
1.5.4
PATCH 14/14 rt2x00: Release rt2x00 2.1.1
In reply to Ivo van Doorn--- drivers/net/wireless/rt2x00/rt2x00.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/net/wireless/rt2x00/rt2x00.h +1 -1
@@ -44,7 +44,7 @@/* * Module information. */ -#define DRV_VERSION "2.1.0" +#define DRV_VERSION "2.1.1"#define DRV_PROJECT "http://rt2x00.serialmonkey.com"/*
Signature · 1 line
1.5.4