Skip to contentSkip to conversation

Please pull 'upstream' branch of rt2x00

PATCH New Ivo van Doorn 1 participant 15 messages Feb 10, 2008 Networking drivers (wireless)

lore
Share & tools
lore
#0 lore raw

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(-)
#1 lore raw

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
index 275c8a1..238f1c1 100644
@@ -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
#2 lore raw

PATCH 2/14 rt2x00: Make rt2x00 less verbose

In reply to Ivo van Doorn

Remove 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
index 693f3d3..330b162 100644
@@ -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
index 7ad8967..a590416 100644
@@ -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
index eb98d28..1ae9e3c 100644
@@ -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
index 9fd2dd8..da0491b 100644
@@ -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
index 146135f..ee2ee7b 100644
@@ -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
#3 lore raw

PATCH 3/14 rt2x00: Remove MGMT ring initialization

In reply to Ivo van Doorn

Remove 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
index da0491b..41ea0c4 100644
@@ -1070,7 +1070,6 @@ static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev)
 	rt2x00_set_field32(&reg, TX_DMA_DST_CSR_DEST_AC1, 2);
 	rt2x00_set_field32(&reg, TX_DMA_DST_CSR_DEST_AC2, 2);
 	rt2x00_set_field32(&reg, TX_DMA_DST_CSR_DEST_AC3, 2);
-	rt2x00_set_field32(&reg, TX_DMA_DST_CSR_DEST_MGMT, 0);
 	rt2x00pci_register_write(rt2x00dev, TX_DMA_DST_CSR, reg);
 
 	rt2x00pci_register_read(rt2x00dev, LOAD_TX_RING_CSR, &reg);
@@ -1078,7 +1077,6 @@ static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev)
 	rt2x00_set_field32(&reg, LOAD_TX_RING_CSR_LOAD_TXD_AC1, 1);
 	rt2x00_set_field32(&reg, LOAD_TX_RING_CSR_LOAD_TXD_AC2, 1);
 	rt2x00_set_field32(&reg, LOAD_TX_RING_CSR_LOAD_TXD_AC3, 1);
-	rt2x00_set_field32(&reg, LOAD_TX_RING_CSR_LOAD_TXD_MGMT, 0);
 	rt2x00pci_register_write(rt2x00dev, LOAD_TX_RING_CSR, reg);
 
 	rt2x00pci_register_read(rt2x00dev, RX_CNTL_CSR, &reg);
drivers/net/wireless/rt2x00/rt61pci.h +1 -1
index d291c0f..2f9a889 100644
@@ -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
#4 lore raw

PATCH 4/14 rt2x00: correct address calc for queue private data

In reply to Ivo van Doorn

From: 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
index fde64ea..943afc9 100644
@@ -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
#5 lore raw

PATCH 5/14 rt2x00: Select CONFIG_NEW_LEDS

In reply to Ivo van Doorn

Select 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
index 51adb2f..4bb46e9 100644
@@ -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
#6 lore raw

PATCH 6/14 rt2x00: make csr_cache and csr_addr an union

In reply to Ivo van Doorn

The 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
index f6ec9fe..9098532 100644
@@ -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
index 238f1c1..b8c6a8c 100644
@@ -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
index 71335e1..8932b31 100644
@@ -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
index 44ab216..4219057 100644
@@ -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
#7 lore raw

PATCH 7/14 rt2x00: Fix scheduling while atomic errors in usb drivers

In reply to Ivo van Doorn

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 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
index 8c24d3b..91b62dd 100644
@@ -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
#8 lore raw

PATCH 8/14 rt2x00: Add queue statistics to debugfs

In reply to Ivo van Doorn

Rename "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
index 4e048ac..21af11a 100644
@@ -33,7 +33,7 @@
 #include "rt2x00lib.h"
 #include "rt2x00dump.h"
 
-#define PRINT_LINE_LEN_MAX 32
+#define MAX_LINE_LENGTH 64
 
 struct 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
#9 lore raw

PATCH 9/14 rt2x00: Fix typo in debug statement

In reply to Ivo van Doorn

The 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
index 41ea0c4..43d5dd3 100644
@@ -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
index ee2ee7b..1802898 100644
@@ -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
#10 lore raw

PATCH 10/14 rt2x00: Fix skbdesc->data_len initialization

In reply to Ivo van Doorn

skbdesc->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
index 1ae9e3c..ad8b6a0 100644
@@ -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
index b8c6a8c..8f88ca2 100644
@@ -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
index 4219057..450043b 100644
@@ -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
index 1802898..af1bb91 100644
@@ -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
#11 lore raw

PATCH 11/14 rt2x00: Fix queue->qid initialization

In reply to Ivo van Doorn

As 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
index 943afc9..9188323 100644
@@ -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
#12 lore raw

PATCH 12/14 rt2x00: Cleanup Makefile

In reply to Ivo van Doorn

Simplify 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
index 757bbc0..1087dbc 100644
@@ -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
#13 lore raw

PATCH 13/14 rt2x00: Kill guardian urb during disable_radio

In reply to Ivo van Doorn

When 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
index 450043b..6cb4432 100644
@@ -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
#14 lore raw

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
index 9098532..7a83e0a 100644
@@ -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