linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 01/23] Enable WLAN LED on Ralink SoC (rt305x) devices
@ 2011-04-18 13:26 Ivo van Doorn
  2011-04-18 13:26 ` [PATCH 02/23] rt2x00: Fix stuck queue in tx failure case Ivo van Doorn
  0 siblings, 1 reply; 37+ messages in thread
From: Ivo van Doorn @ 2011-04-18 13:26 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users

From: Layne Edwards <ledwards@astrumtech.net>

This patch adds WLAN LED support to the mac80211 rt2x00 driver for
Ralink SoC (rt305x) devices.  The current WLAN LED drivers in
rt2800lib.c set the LED brightness via an MCU request, but do nothing
for SoC.  This patch checks for SoC and sets the register to enable the
WLAN LED (instead of an MCU request).  This enables the WLAN LED for
RT305x devices.

Signed-off-by: Layne Edwards <ledwards@astrumtech.net>
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2800lib.c |   60 +++++++++++++++++++++---------
 1 files changed, 42 insertions(+), 18 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 769c05c..13ccc1b 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -949,25 +949,49 @@ static void rt2800_brightness_set(struct led_classdev *led_cdev,
 	unsigned int ledmode =
 		rt2x00_get_field16(led->rt2x00dev->led_mcu_reg,
 				   EEPROM_FREQ_LED_MODE);
+	u32 reg;
 
-	if (led->type == LED_TYPE_RADIO) {
-		rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode,
-				      enabled ? 0x20 : 0);
-	} else if (led->type == LED_TYPE_ASSOC) {
-		rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode,
-				      enabled ? (bg_mode ? 0x60 : 0xa0) : 0x20);
-	} else if (led->type == LED_TYPE_QUALITY) {
-		/*
-		 * The brightness is divided into 6 levels (0 - 5),
-		 * The specs tell us the following levels:
-		 *	0, 1 ,3, 7, 15, 31
-		 * to determine the level in a simple way we can simply
-		 * work with bitshifting:
-		 *	(1 << level) - 1
-		 */
-		rt2800_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff,
-				      (1 << brightness / (LED_FULL / 6)) - 1,
-				      polarity);
+	/* Check for SoC (SOC devices don't support MCU requests) */
+	if (rt2x00_is_soc(led->rt2x00dev)) {
+		rt2800_register_read(led->rt2x00dev, LED_CFG, &reg);
+
+		/* Set LED Polarity */
+		rt2x00_set_field32(&reg, LED_CFG_LED_POLAR, polarity);
+
+		/* Set LED Mode */
+		if (led->type == LED_TYPE_RADIO) {
+			rt2x00_set_field32(&reg, LED_CFG_G_LED_MODE,
+					   enabled ? 3 : 0);
+		} else if (led->type == LED_TYPE_ASSOC) {
+			rt2x00_set_field32(&reg, LED_CFG_Y_LED_MODE,
+					   enabled ? 3 : 0);
+		} else if (led->type == LED_TYPE_QUALITY) {
+			rt2x00_set_field32(&reg, LED_CFG_R_LED_MODE,
+					   enabled ? 3 : 0);
+		}
+
+		rt2800_register_write(led->rt2x00dev, LED_CFG, reg);
+
+	} else {
+		if (led->type == LED_TYPE_RADIO) {
+			rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode,
+					      enabled ? 0x20 : 0);
+		} else if (led->type == LED_TYPE_ASSOC) {
+			rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode,
+					      enabled ? (bg_mode ? 0x60 : 0xa0) : 0x20);
+		} else if (led->type == LED_TYPE_QUALITY) {
+			/*
+			 * The brightness is divided into 6 levels (0 - 5),
+			 * The specs tell us the following levels:
+			 *	0, 1 ,3, 7, 15, 31
+			 * to determine the level in a simple way we can simply
+			 * work with bitshifting:
+			 *	(1 << level) - 1
+			 */
+			rt2800_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff,
+					      (1 << brightness / (LED_FULL / 6)) - 1,
+					      polarity);
+		}
 	}
 }
 
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 02/23] rt2x00: Fix stuck queue in tx failure case
  2011-04-18 13:26 [PATCH 01/23] Enable WLAN LED on Ralink SoC (rt305x) devices Ivo van Doorn
@ 2011-04-18 13:26 ` Ivo van Doorn
  2011-04-18 13:27   ` [PATCH 03/23] rt2x00: Split rt2x00dev->flags Ivo van Doorn
  0 siblings, 1 reply; 37+ messages in thread
From: Ivo van Doorn @ 2011-04-18 13:26 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users

From: Helmut Schaa <helmut.schaa@googlemail.com>

Since commit 0b7fde54f94979edc67bbf86b5adba702ebfefe8 "rt2x00: Protect
queue control with mutex" rt2x00 used rt2x00queue_pause_queue for
stopping a tx queue in mac80211. But in case of a failure in the tx
path rt2x00 still called ieee80211_stop_queue which stopped the queue
but prevented rt2x00queue_unpause_queue to wake the queue up again
resulting in a stuck tx queue.

Fix this by also using rt2x00queue_pause_queue in case of tx failures.

Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2x00mac.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 661c6ba..4a1c41b 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -158,7 +158,7 @@ void rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 	return;
 
  exit_fail:
-	ieee80211_stop_queue(rt2x00dev->hw, qid);
+	rt2x00queue_pause_queue(queue);
 	dev_kfree_skb_any(skb);
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_tx);
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 03/23] rt2x00: Split rt2x00dev->flags
  2011-04-18 13:26 ` [PATCH 02/23] rt2x00: Fix stuck queue in tx failure case Ivo van Doorn
@ 2011-04-18 13:27   ` Ivo van Doorn
  2011-04-18 13:27     ` [PATCH 04/23] rt2x00: Make rt2x00_queue_entry_for_each more flexible Ivo van Doorn
  0 siblings, 1 reply; 37+ messages in thread
From: Ivo van Doorn @ 2011-04-18 13:27 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users

From: Ivo van Doorn <IvDoorn@gmail.com>

The number of flags defined for the rt2x00dev->flags field,
has been growing over the years. Currently we are approaching
the maximum number of bits which are available in the field.

A secondary problem, is that one part of the field are initialized only
during boot, because the driver requirements are initialized or device
requirements are loaded from the EEPROM. In both cases, the flags are
fixed and will not change during device operation. The other flags are
the device state, and will change frequently. So far this resulted in the fact
that for some flags, the atomic bit accessors are used, while for the others
the non-atomic variants are used.

By splitting the flags up into a "flags" and "cap_flags" we can put all flags
which are fixed inside "cap_flags". This field can then be read non-atomically.
In the "flags" field we keep the device state, which is going to be read atomically.

This adds more room for more flags in the future, and sanitizes the field access methods.

Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Acked-by: Helmut Schaa <helmut.schaa@googlemail.com>
---
 drivers/net/wireless/rt2x00/rt2400pci.c      |   10 ++--
 drivers/net/wireless/rt2x00/rt2500pci.c      |   10 ++--
 drivers/net/wireless/rt2x00/rt2500usb.c      |   12 ++--
 drivers/net/wireless/rt2x00/rt2800lib.c      |   20 +++---
 drivers/net/wireless/rt2x00/rt2800pci.c      |   22 ++++----
 drivers/net/wireless/rt2x00/rt2800usb.c      |   14 ++--
 drivers/net/wireless/rt2x00/rt2x00.h         |   84 +++++++++++++++-----------
 drivers/net/wireless/rt2x00/rt2x00config.c   |    4 +-
 drivers/net/wireless/rt2x00/rt2x00crypto.c   |    4 +-
 drivers/net/wireless/rt2x00/rt2x00debug.c    |   42 ++++++++++++-
 drivers/net/wireless/rt2x00/rt2x00dev.c      |   14 ++--
 drivers/net/wireless/rt2x00/rt2x00firmware.c |    2 +-
 drivers/net/wireless/rt2x00/rt2x00lib.h      |    4 +-
 drivers/net/wireless/rt2x00/rt2x00link.c     |    2 +-
 drivers/net/wireless/rt2x00/rt2x00mac.c      |   12 ++--
 drivers/net/wireless/rt2x00/rt2x00queue.c    |   20 +++---
 drivers/net/wireless/rt2x00/rt2x00usb.c      |    6 +-
 drivers/net/wireless/rt2x00/rt61pci.c        |   42 +++++++-------
 drivers/net/wireless/rt2x00/rt73usb.c        |   32 +++++-----
 19 files changed, 203 insertions(+), 153 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 137a24e..5d1654a 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -1536,13 +1536,13 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
 	 * Detect if this device has an hardware controlled radio.
 	 */
 	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
-		__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);
 
 	/*
 	 * Check if the BBP tuning should be enabled.
 	 */
 	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_AGCVGC_TUNING))
-		__set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
 
 	return 0;
 }
@@ -1640,9 +1640,9 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)
 	/*
 	 * This device requires the atim queue and DMA-mapped skbs.
 	 */
-	__set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
-	__set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);
-	__set_bit(DRIVER_REQUIRE_SW_SEQNO, &rt2x00dev->flags);
+	__set_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags);
+	__set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags);
+	__set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags);
 
 	/*
 	 * Set the rssi offset.
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index 198fc0a..3da954e 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -1687,14 +1687,14 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
 	 * Detect if this device has an hardware controlled radio.
 	 */
 	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
-		__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);
 
 	/*
 	 * Check if the BBP tuning should be enabled.
 	 */
 	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
 	if (!rt2x00_get_field16(eeprom, EEPROM_NIC_DYN_BBP_TUNE))
-		__set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
 
 	/*
 	 * Read the RSSI <-> dBm offset information.
@@ -1958,9 +1958,9 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)
 	/*
 	 * This device requires the atim queue and DMA-mapped skbs.
 	 */
-	__set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
-	__set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);
-	__set_bit(DRIVER_REQUIRE_SW_SEQNO, &rt2x00dev->flags);
+	__set_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags);
+	__set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags);
+	__set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags);
 
 	/*
 	 * Set the rssi offset.
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index eac7881..dbbd8bc 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -1519,7 +1519,7 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
 	 * Detect if this device has an hardware controlled radio.
 	 */
 	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
-		__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);
 
 	/*
 	 * Read the RSSI <-> dBm offset information.
@@ -1790,13 +1790,13 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
 	/*
 	 * This device requires the atim queue
 	 */
-	__set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
-	__set_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags);
+	__set_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags);
+	__set_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags);
 	if (!modparam_nohwcrypt) {
-		__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
-		__set_bit(DRIVER_REQUIRE_COPY_IV, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
+		__set_bit(REQUIRE_COPY_IV, &rt2x00dev->cap_flags);
 	}
-	__set_bit(DRIVER_REQUIRE_SW_SEQNO, &rt2x00dev->flags);
+	__set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags);
 
 	/*
 	 * Set the rssi offset.
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 13ccc1b..c6f5584 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -1763,8 +1763,8 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
 
 	if (rf->channel <= 14) {
 		if (!rt2x00_rt(rt2x00dev, RT5390)) {
-			if (test_bit(CONFIG_EXTERNAL_LNA_BG,
-				     &rt2x00dev->flags)) {
+			if (test_bit(CAPABILITY_EXTERNAL_LNA_BG,
+				     &rt2x00dev->cap_flags)) {
 				rt2800_bbp_write(rt2x00dev, 82, 0x62);
 				rt2800_bbp_write(rt2x00dev, 75, 0x46);
 			} else {
@@ -1775,7 +1775,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
 	} else {
 		rt2800_bbp_write(rt2x00dev, 82, 0xf2);
 
-		if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags))
+		if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags))
 			rt2800_bbp_write(rt2x00dev, 75, 0x46);
 		else
 			rt2800_bbp_write(rt2x00dev, 75, 0x50);
@@ -2008,7 +2008,7 @@ static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b,
 	if (!((band == IEEE80211_BAND_5GHZ) && is_rate_b))
 		return txpower;
 
-	if (test_bit(CONFIG_SUPPORT_POWER_LIMIT, &rt2x00dev->flags)) {
+	if (test_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags)) {
 		/*
 		 * Check if eirp txpower exceed txpower_limit.
 		 * We use OFDM 6M as criterion and its eirp txpower
@@ -3309,8 +3309,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
 		    rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
 		    rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) ||
 		    rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) {
-			if (!test_bit(CONFIG_EXTERNAL_LNA_BG,
-				      &rt2x00dev->flags))
+			if (!test_bit(CAPABILITY_EXTERNAL_LNA_BG,
+				      &rt2x00dev->cap_flags))
 				rt2x00_set_field8(&rfcsr, RFCSR17_R, 1);
 		}
 		rt2x00_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &eeprom);
@@ -3733,15 +3733,15 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
 	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
 
 	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_LNA_5G))
-		__set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);
 	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_LNA_2G))
-		__set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags);
 
 	/*
 	 * Detect if this device has an hardware controlled radio.
 	 */
 	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_HW_RADIO))
-		__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);
 
 	/*
 	 * Store led settings, for correct led behaviour.
@@ -3761,7 +3761,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
 
 	if (rt2x00_get_field16(eeprom, EEPROM_EIRP_MAX_TX_POWER_2GHZ) <
 					EIRP_MAX_TX_POWER_LIMIT)
-		__set_bit(CONFIG_SUPPORT_POWER_LIMIT, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags);
 
 	return 0;
 }
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index adc3534..4241f19 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -966,28 +966,28 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
 	 * This device has multiple filters for control frames
 	 * and has a separate filter for PS Poll frames.
 	 */
-	__set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags);
-	__set_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags);
+	__set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags);
+	__set_bit(CAPABILITY_CONTROL_FILTER_PSPOLL, &rt2x00dev->cap_flags);
 
 	/*
 	 * This device has a pre tbtt interrupt and thus fetches
 	 * a new beacon directly prior to transmission.
 	 */
-	__set_bit(DRIVER_SUPPORT_PRE_TBTT_INTERRUPT, &rt2x00dev->flags);
+	__set_bit(CAPABILITY_PRE_TBTT_INTERRUPT, &rt2x00dev->cap_flags);
 
 	/*
 	 * This device requires firmware.
 	 */
 	if (!rt2x00_is_soc(rt2x00dev))
-		__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
-	__set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);
-	__set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags);
-	__set_bit(DRIVER_REQUIRE_TXSTATUS_FIFO, &rt2x00dev->flags);
-	__set_bit(DRIVER_REQUIRE_TASKLET_CONTEXT, &rt2x00dev->flags);
+		__set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags);
+	__set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags);
+	__set_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags);
+	__set_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags);
+	__set_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags);
 	if (!modparam_nohwcrypt)
-		__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
-	__set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
-	__set_bit(DRIVER_REQUIRE_HT_TX_DESC, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
+	__set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
+	__set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags);
 
 	/*
 	 * Set the rssi offset.
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index d2f5c87..f3ce5e8 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -553,18 +553,18 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
 	 * This device has multiple filters for control frames
 	 * and has a separate filter for PS Poll frames.
 	 */
-	__set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags);
-	__set_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags);
+	__set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags);
+	__set_bit(CAPABILITY_CONTROL_FILTER_PSPOLL, &rt2x00dev->cap_flags);
 
 	/*
 	 * This device requires firmware.
 	 */
-	__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
-	__set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags);
+	__set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags);
+	__set_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags);
 	if (!modparam_nohwcrypt)
-		__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
-	__set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
-	__set_bit(DRIVER_REQUIRE_HT_TX_DESC, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
+	__set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
+	__set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags);
 
 	/*
 	 * Set the rssi offset.
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index dd0f66a..79c385a 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -643,11 +643,11 @@ struct rt2x00_ops {
 };
 
 /*
- * rt2x00 device flags
+ * rt2x00 state flags
  */
-enum rt2x00_flags {
+enum rt2x00_state_flags {
 	/*
-	 * Device state flags
+	 * Device flags
 	 */
 	DEVICE_STATE_PRESENT,
 	DEVICE_STATE_REGISTERED_HW,
@@ -657,42 +657,47 @@ enum rt2x00_flags {
 	DEVICE_STATE_SCANNING,
 
 	/*
-	 * Driver requirements
-	 */
-	DRIVER_REQUIRE_FIRMWARE,
-	DRIVER_REQUIRE_BEACON_GUARD,
-	DRIVER_REQUIRE_ATIM_QUEUE,
-	DRIVER_REQUIRE_DMA,
-	DRIVER_REQUIRE_COPY_IV,
-	DRIVER_REQUIRE_L2PAD,
-	DRIVER_REQUIRE_TXSTATUS_FIFO,
-	DRIVER_REQUIRE_TASKLET_CONTEXT,
-	DRIVER_REQUIRE_SW_SEQNO,
-	DRIVER_REQUIRE_HT_TX_DESC,
-
-	/*
-	 * Driver features
-	 */
-	CONFIG_SUPPORT_HW_BUTTON,
-	CONFIG_SUPPORT_HW_CRYPTO,
-	CONFIG_SUPPORT_POWER_LIMIT,
-	DRIVER_SUPPORT_CONTROL_FILTERS,
-	DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL,
-	DRIVER_SUPPORT_PRE_TBTT_INTERRUPT,
-	DRIVER_SUPPORT_LINK_TUNING,
-
-	/*
 	 * Driver configuration
 	 */
-	CONFIG_FRAME_TYPE,
-	CONFIG_RF_SEQUENCE,
-	CONFIG_EXTERNAL_LNA_A,
-	CONFIG_EXTERNAL_LNA_BG,
-	CONFIG_DOUBLE_ANTENNA,
 	CONFIG_CHANNEL_HT40,
 };
 
 /*
+ * rt2x00 capability flags
+ */
+enum rt2x00_capability_flags {
+	/*
+	 * Requirements
+	 */
+	REQUIRE_FIRMWARE,
+	REQUIRE_BEACON_GUARD,
+	REQUIRE_ATIM_QUEUE,
+	REQUIRE_DMA,
+	REQUIRE_COPY_IV,
+	REQUIRE_L2PAD,
+	REQUIRE_TXSTATUS_FIFO,
+	REQUIRE_TASKLET_CONTEXT,
+	REQUIRE_SW_SEQNO,
+	REQUIRE_HT_TX_DESC,
+
+	/*
+	 * Capabilities
+	 */
+	CAPABILITY_HW_BUTTON,
+	CAPABILITY_HW_CRYPTO,
+	CAPABILITY_POWER_LIMIT,
+	CAPABILITY_CONTROL_FILTERS,
+	CAPABILITY_CONTROL_FILTER_PSPOLL,
+	CAPABILITY_PRE_TBTT_INTERRUPT,
+	CAPABILITY_LINK_TUNING,
+	CAPABILITY_FRAME_TYPE,
+	CAPABILITY_RF_SEQUENCE,
+	CAPABILITY_EXTERNAL_LNA_A,
+	CAPABILITY_EXTERNAL_LNA_BG,
+	CAPABILITY_DOUBLE_ANTENNA,
+};
+
+/*
  * rt2x00 device structure.
  */
 struct rt2x00_dev {
@@ -738,13 +743,20 @@ struct rt2x00_dev {
 #endif /* CONFIG_RT2X00_LIB_LEDS */
 
 	/*
-	 * Device flags.
-	 * In these flags the current status and some
-	 * of the device capabilities are stored.
+	 * Device state flags.
+	 * In these flags the current status is stored.
+	 * Access to these flags should occur atomically.
 	 */
 	unsigned long flags;
 
 	/*
+	 * Device capabiltiy flags.
+	 * In these flags the device/driver capabilities are stored.
+	 * Access to these flags should occur non-atomically.
+	 */
+	unsigned long cap_flags;
+
+	/*
 	 * Device information, Bus IRQ and name (PCI, SoC)
 	 */
 	int irq;
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
index e7f67d5..e225a66 100644
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
@@ -176,10 +176,10 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
 
 	if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) {
 		if (conf_is_ht40(conf)) {
-			__set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
+			set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
 			hw_value = rt2x00ht_center_channel(rt2x00dev, conf);
 		} else {
-			__clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
+			clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);
 			hw_value = conf->channel->hw_value;
 		}
 
diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c
index 5e9074b..e1e0c51 100644
--- a/drivers/net/wireless/rt2x00/rt2x00crypto.c
+++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c
@@ -52,7 +52,7 @@ void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry,
 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
 	struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
 
-	if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags) || !hw_key)
+	if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags) || !hw_key)
 		return;
 
 	__set_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags);
@@ -80,7 +80,7 @@ unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev,
 	struct ieee80211_key_conf *key = tx_info->control.hw_key;
 	unsigned int overhead = 0;
 
-	if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags) || !key)
+	if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags) || !key)
 		return overhead;
 
 	/*
diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c
index 66166ef..78787fc 100644
--- a/drivers/net/wireless/rt2x00/rt2x00debug.c
+++ b/drivers/net/wireless/rt2x00/rt2x00debug.c
@@ -63,7 +63,8 @@ struct rt2x00debug_intf {
 	 * - driver folder
 	 *   - driver file
 	 *   - chipset file
-	 *   - device flags file
+	 *   - device state flags file
+	 *   - device capability flags file
 	 *   - register folder
 	 *     - csr offset/value files
 	 *     - eeprom offset/value files
@@ -78,6 +79,7 @@ struct rt2x00debug_intf {
 	struct dentry *driver_entry;
 	struct dentry *chipset_entry;
 	struct dentry *dev_flags;
+	struct dentry *cap_flags;
 	struct dentry *register_folder;
 	struct dentry *csr_off_entry;
 	struct dentry *csr_val_entry;
@@ -553,6 +555,35 @@ static const struct file_operations rt2x00debug_fop_dev_flags = {
 	.llseek		= default_llseek,
 };
 
+static ssize_t rt2x00debug_read_cap_flags(struct file *file,
+					  char __user *buf,
+					  size_t length,
+					  loff_t *offset)
+{
+	struct rt2x00debug_intf *intf =	file->private_data;
+	char line[16];
+	size_t size;
+
+	if (*offset)
+		return 0;
+
+	size = sprintf(line, "0x%.8x\n", (unsigned int)intf->rt2x00dev->cap_flags);
+
+	if (copy_to_user(buf, line, size))
+		return -EFAULT;
+
+	*offset += size;
+	return size;
+}
+
+static const struct file_operations rt2x00debug_fop_cap_flags = {
+	.owner		= THIS_MODULE,
+	.read		= rt2x00debug_read_cap_flags,
+	.open		= rt2x00debug_file_open,
+	.release	= rt2x00debug_file_release,
+	.llseek		= default_llseek,
+};
+
 static struct dentry *rt2x00debug_create_file_driver(const char *name,
 						     struct rt2x00debug_intf
 						     *intf,
@@ -652,6 +683,12 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
 	if (IS_ERR(intf->dev_flags) || !intf->dev_flags)
 		goto exit;
 
+	intf->cap_flags = debugfs_create_file("cap_flags", S_IRUSR,
+					      intf->driver_folder, intf,
+					      &rt2x00debug_fop_cap_flags);
+	if (IS_ERR(intf->cap_flags) || !intf->cap_flags)
+		goto exit;
+
 	intf->register_folder =
 	    debugfs_create_dir("register", intf->driver_folder);
 	if (IS_ERR(intf->register_folder) || !intf->register_folder)
@@ -705,7 +742,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
 				intf, &rt2x00debug_fop_queue_stats);
 
 #ifdef CONFIG_RT2X00_LIB_CRYPTO
-	if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags))
+	if (test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags))
 		intf->crypto_stats_entry =
 		    debugfs_create_file("crypto", S_IRUGO, intf->queue_folder,
 					intf, &rt2x00debug_fop_crypto_stats);
@@ -743,6 +780,7 @@ void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
 	debugfs_remove(intf->csr_off_entry);
 	debugfs_remove(intf->register_folder);
 	debugfs_remove(intf->dev_flags);
+	debugfs_remove(intf->cap_flags);
 	debugfs_remove(intf->chipset_entry);
 	debugfs_remove(intf->driver_entry);
 	debugfs_remove(intf->driver_folder);
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 9bffe84..af25b01 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -200,7 +200,7 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
 	 * here as they will fetch the next beacon directly prior to
 	 * transmission.
 	 */
-	if (test_bit(DRIVER_SUPPORT_PRE_TBTT_INTERRUPT, &rt2x00dev->flags))
+	if (test_bit(CAPABILITY_PRE_TBTT_INTERRUPT, &rt2x00dev->cap_flags))
 		return;
 
 	/* fetch next beacon */
@@ -271,7 +271,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,
 	/*
 	 * Remove L2 padding which was added during
 	 */
-	if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags))
+	if (test_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags))
 		rt2x00queue_remove_l2pad(entry->skb, header_length);
 
 	/*
@@ -280,7 +280,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,
 	 * mac80211 will expect the same data to be present it the
 	 * frame as it was passed to us.
 	 */
-	if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags))
+	if (test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags))
 		rt2x00crypto_tx_insert_iv(entry->skb, header_length);
 
 	/*
@@ -377,7 +377,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,
 	 * send the status report back.
 	 */
 	if (!(skbdesc_flags & SKBDESC_NOT_MAC80211)) {
-		if (test_bit(DRIVER_REQUIRE_TASKLET_CONTEXT, &rt2x00dev->flags))
+		if (test_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags))
 			ieee80211_tx_status(rt2x00dev->hw, entry->skb);
 		else
 			ieee80211_tx_status_ni(rt2x00dev->hw, entry->skb);
@@ -806,15 +806,15 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
 	/*
 	 * Take TX headroom required for alignment into account.
 	 */
-	if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags))
+	if (test_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags))
 		rt2x00dev->hw->extra_tx_headroom += RT2X00_L2PAD_SIZE;
-	else if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags))
+	else if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags))
 		rt2x00dev->hw->extra_tx_headroom += RT2X00_ALIGN_SIZE;
 
 	/*
 	 * Allocate tx status FIFO for driver use.
 	 */
-	if (test_bit(DRIVER_REQUIRE_TXSTATUS_FIFO, &rt2x00dev->flags)) {
+	if (test_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags)) {
 		/*
 		 * Allocate the txstatus fifo. In the worst case the tx
 		 * status fifo has to hold the tx status of all entries
diff --git a/drivers/net/wireless/rt2x00/rt2x00firmware.c b/drivers/net/wireless/rt2x00/rt2x00firmware.c
index be0ff78..f316aad 100644
--- a/drivers/net/wireless/rt2x00/rt2x00firmware.c
+++ b/drivers/net/wireless/rt2x00/rt2x00firmware.c
@@ -99,7 +99,7 @@ int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev)
 {
 	int retval;
 
-	if (!test_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags))
+	if (!test_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags))
 		return 0;
 
 	if (!rt2x00dev->fw) {
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index 88f2f92..bbee2cd 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -416,13 +416,13 @@ static inline u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev,
  */
 static inline void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev)
 {
-	if (test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
+	if (test_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags))
 		wiphy_rfkill_start_polling(rt2x00dev->hw->wiphy);
 }
 
 static inline void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev)
 {
-	if (test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
+	if (test_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags))
 		wiphy_rfkill_stop_polling(rt2x00dev->hw->wiphy);
 }
 
diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c
index 128b361..ba0bb76 100644
--- a/drivers/net/wireless/rt2x00/rt2x00link.c
+++ b/drivers/net/wireless/rt2x00/rt2x00link.c
@@ -383,7 +383,7 @@ static void rt2x00link_tuner(struct work_struct *work)
 	 * do not support link tuning at all, while other devices can disable
 	 * the feature from the EEPROM.
 	 */
-	if (test_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags))
+	if (test_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags))
 		rt2x00dev->ops->lib->link_tuner(rt2x00dev, qual, link->count);
 
 	/*
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 4a1c41b..4770156 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -119,7 +119,7 @@ void rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 	 * Use the ATIM queue if appropriate and present.
 	 */
 	if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM &&
-	    test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags))
+	    test_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags))
 		qid = QID_ATIM;
 
 	queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
@@ -411,11 +411,11 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
 	 * of different types, but has no a separate filter for PS Poll frames,
 	 * FIF_CONTROL flag implies FIF_PSPOLL.
 	 */
-	if (!test_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags)) {
+	if (!test_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags)) {
 		if (*total_flags & FIF_CONTROL || *total_flags & FIF_PSPOLL)
 			*total_flags |= FIF_CONTROL | FIF_PSPOLL;
 	}
-	if (!test_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags)) {
+	if (!test_bit(CAPABILITY_CONTROL_FILTER_PSPOLL, &rt2x00dev->cap_flags)) {
 		if (*total_flags & FIF_CONTROL)
 			*total_flags |= FIF_PSPOLL;
 	}
@@ -496,7 +496,7 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 
 	if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
 		return 0;
-	else if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags))
+	else if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags))
 		return -EOPNOTSUPP;
 	else if (key->keylen > 32)
 		return -ENOSPC;
@@ -562,7 +562,7 @@ EXPORT_SYMBOL_GPL(rt2x00mac_set_key);
 void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw)
 {
 	struct rt2x00_dev *rt2x00dev = hw->priv;
-	__set_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags);
+	set_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags);
 	rt2x00link_stop_tuner(rt2x00dev);
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_start);
@@ -570,7 +570,7 @@ EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_start);
 void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw)
 {
 	struct rt2x00_dev *rt2x00dev = hw->priv;
-	__clear_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags);
+	clear_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags);
 	rt2x00link_start_tuner(rt2x00dev);
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_complete);
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 9fc4a1e..d03eef2 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -60,7 +60,7 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry)
 	 * at least 8 bytes bytes available in headroom for IV/EIV
 	 * and 8 bytes for ICV data as tailroon.
 	 */
-	if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) {
+	if (test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags)) {
 		head_size += 8;
 		tail_size += 8;
 	}
@@ -86,7 +86,7 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry)
 	memset(skbdesc, 0, sizeof(*skbdesc));
 	skbdesc->entry = entry;
 
-	if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags)) {
+	if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags)) {
 		skbdesc->skb_dma = dma_map_single(rt2x00dev->dev,
 						  skb->data,
 						  skb->len,
@@ -213,7 +213,7 @@ static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry,
 
 	__set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags);
 
-	if (!test_bit(DRIVER_REQUIRE_SW_SEQNO, &entry->queue->rt2x00dev->flags))
+	if (!test_bit(REQUIRE_SW_SEQNO, &entry->queue->rt2x00dev->cap_flags))
 		return;
 
 	/*
@@ -396,7 +396,7 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
 	rt2x00crypto_create_tx_descriptor(entry, txdesc);
 	rt2x00queue_create_tx_descriptor_seq(entry, txdesc);
 
-	if (test_bit(DRIVER_REQUIRE_HT_TX_DESC, &rt2x00dev->flags))
+	if (test_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags))
 		rt2x00ht_create_tx_descriptor(entry, txdesc, hwrate);
 	else
 		rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate);
@@ -436,7 +436,7 @@ static int rt2x00queue_write_tx_data(struct queue_entry *entry,
 	/*
 	 * Map the skb to DMA.
 	 */
-	if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags))
+	if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags))
 		rt2x00queue_map_txskb(entry);
 
 	return 0;
@@ -529,7 +529,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
 	 */
 	if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) &&
 	    !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) {
-		if (test_bit(DRIVER_REQUIRE_COPY_IV, &queue->rt2x00dev->flags))
+		if (test_bit(REQUIRE_COPY_IV, &queue->rt2x00dev->cap_flags))
 			rt2x00crypto_tx_copy_iv(skb, &txdesc);
 		else
 			rt2x00crypto_tx_remove_iv(skb, &txdesc);
@@ -543,9 +543,9 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
 	 * PCI and USB devices, while header alignment only is valid
 	 * for PCI devices.
 	 */
-	if (test_bit(DRIVER_REQUIRE_L2PAD, &queue->rt2x00dev->flags))
+	if (test_bit(REQUIRE_L2PAD, &queue->rt2x00dev->cap_flags))
 		rt2x00queue_insert_l2pad(entry->skb, txdesc.header_length);
-	else if (test_bit(DRIVER_REQUIRE_DMA, &queue->rt2x00dev->flags))
+	else if (test_bit(REQUIRE_DMA, &queue->rt2x00dev->cap_flags))
 		rt2x00queue_align_frame(entry->skb);
 
 	/*
@@ -1069,7 +1069,7 @@ int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev)
 	if (status)
 		goto exit;
 
-	if (test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags)) {
+	if (test_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags)) {
 		status = rt2x00queue_alloc_entries(rt2x00dev->atim,
 						   rt2x00dev->ops->atim);
 		if (status)
@@ -1121,7 +1121,7 @@ int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev)
 	struct data_queue *queue;
 	enum data_queue_qid qid;
 	unsigned int req_atim =
-	    !!test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
+	    !!test_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags);
 
 	/*
 	 * We need the following queues:
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index fbe735f..94047e9 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -387,7 +387,7 @@ static void rt2x00usb_flush_entry(struct queue_entry *entry)
 	 * Kill guardian urb (if required by driver).
 	 */
 	if ((entry->queue->qid == QID_BEACON) &&
-	    (test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags)))
+	    (test_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags)))
 		usb_kill_urb(bcn_priv->guardian_urb);
 }
 
@@ -583,7 +583,7 @@ static int rt2x00usb_alloc_entries(struct data_queue *queue)
 	 * then we are done.
 	 */
 	if (queue->qid != QID_BEACON ||
-	    !test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags))
+	    !test_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags))
 		return 0;
 
 	for (i = 0; i < queue->limit; i++) {
@@ -618,7 +618,7 @@ static void rt2x00usb_free_entries(struct data_queue *queue)
 	 * then we are done.
 	 */
 	if (queue->qid != QID_BEACON ||
-	    !test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags))
+	    !test_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags))
 		return;
 
 	for (i = 0; i < queue->limit; i++) {
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 8ee1514..c16c150 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -683,7 +683,7 @@ static void rt61pci_config_antenna_2x(struct rt2x00_dev *rt2x00dev,
 
 	rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, rt2x00_rf(rt2x00dev, RF2529));
 	rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
-			  !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags));
+			  !test_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags));
 
 	/*
 	 * Configure the RX antenna.
@@ -811,10 +811,10 @@ static void rt61pci_config_ant(struct rt2x00_dev *rt2x00dev,
 
 	if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
 		sel = antenna_sel_a;
-		lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
+		lna = test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);
 	} else {
 		sel = antenna_sel_bg;
-		lna = test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags);
+		lna = test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags);
 	}
 
 	for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++)
@@ -834,7 +834,7 @@ static void rt61pci_config_ant(struct rt2x00_dev *rt2x00dev,
 	else if (rt2x00_rf(rt2x00dev, RF2527))
 		rt61pci_config_antenna_2x(rt2x00dev, ant);
 	else if (rt2x00_rf(rt2x00dev, RF2529)) {
-		if (test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags))
+		if (test_bit(CAPABILITY_DOUBLE_ANTENNA, &rt2x00dev->cap_flags))
 			rt61pci_config_antenna_2x(rt2x00dev, ant);
 		else
 			rt61pci_config_antenna_2529(rt2x00dev, ant);
@@ -848,13 +848,13 @@ static void rt61pci_config_lna_gain(struct rt2x00_dev *rt2x00dev,
 	short lna_gain = 0;
 
 	if (libconf->conf->channel->band == IEEE80211_BAND_2GHZ) {
-		if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags))
+		if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags))
 			lna_gain += 14;
 
 		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom);
 		lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1);
 	} else {
-		if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags))
+		if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags))
 			lna_gain += 14;
 
 		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom);
@@ -1050,14 +1050,14 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev,
 	if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
 		low_bound = 0x28;
 		up_bound = 0x48;
-		if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) {
+		if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) {
 			low_bound += 0x10;
 			up_bound += 0x10;
 		}
 	} else {
 		low_bound = 0x20;
 		up_bound = 0x40;
-		if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) {
+		if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags)) {
 			low_bound += 0x10;
 			up_bound += 0x10;
 		}
@@ -2537,7 +2537,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
 	 * Determine number of antennas.
 	 */
 	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_NUM) == 2)
-		__set_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_DOUBLE_ANTENNA, &rt2x00dev->cap_flags);
 
 	/*
 	 * Identify default antenna configuration.
@@ -2551,20 +2551,20 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
 	 * Read the Frame type.
 	 */
 	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_FRAME_TYPE))
-		__set_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags);
 
 	/*
 	 * Detect if this device has a hardware controlled radio.
 	 */
 	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
-		__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);
 
 	/*
 	 * Read frequency offset and RF programming sequence.
 	 */
 	rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
 	if (rt2x00_get_field16(eeprom, EEPROM_FREQ_SEQ))
-		__set_bit(CONFIG_RF_SEQUENCE, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_RF_SEQUENCE, &rt2x00dev->cap_flags);
 
 	rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET);
 
@@ -2574,9 +2574,9 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
 	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
 
 	if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_A))
-		__set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);
 	if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_BG))
-		__set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags);
 
 	/*
 	 * When working with a RF2529 chip without double antenna,
@@ -2584,7 +2584,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
 	 * eeprom word.
 	 */
 	if (rt2x00_rf(rt2x00dev, RF2529) &&
-	    !test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) {
+	    !test_bit(CAPABILITY_DOUBLE_ANTENNA, &rt2x00dev->cap_flags)) {
 		rt2x00dev->default_ant.rx =
 		    ANTENNA_A + rt2x00_get_field16(eeprom, EEPROM_NIC_RX_FIXED);
 		rt2x00dev->default_ant.tx =
@@ -2799,7 +2799,7 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 	spec->supported_bands = SUPPORT_BAND_2GHZ;
 	spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
 
-	if (!test_bit(CONFIG_RF_SEQUENCE, &rt2x00dev->flags)) {
+	if (!test_bit(CAPABILITY_RF_SEQUENCE, &rt2x00dev->cap_flags)) {
 		spec->num_channels = 14;
 		spec->channels = rf_vals_noseq;
 	} else {
@@ -2869,16 +2869,16 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
 	 * This device has multiple filters for control frames,
 	 * but has no a separate filter for PS Poll frames.
 	 */
-	__set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags);
+	__set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags);
 
 	/*
 	 * This device requires firmware and DMA mapped skbs.
 	 */
-	__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
-	__set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);
+	__set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags);
+	__set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags);
 	if (!modparam_nohwcrypt)
-		__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
-	__set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
+	__set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
 
 	/*
 	 * Set the rssi offset.
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 6593059..cdb026d 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -595,7 +595,7 @@ static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
 	switch (ant->rx) {
 	case ANTENNA_HW_DIVERSITY:
 		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2);
-		temp = !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)
+		temp = !test_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags)
 		       && (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ);
 		rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, temp);
 		break;
@@ -636,7 +636,7 @@ static void rt73usb_config_antenna_2x(struct rt2x00_dev *rt2x00dev,
 
 	rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, 0);
 	rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
-			  !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags));
+			  !test_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags));
 
 	/*
 	 * Configure the RX antenna.
@@ -709,10 +709,10 @@ static void rt73usb_config_ant(struct rt2x00_dev *rt2x00dev,
 
 	if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
 		sel = antenna_sel_a;
-		lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
+		lna = test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);
 	} else {
 		sel = antenna_sel_bg;
-		lna = test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags);
+		lna = test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags);
 	}
 
 	for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++)
@@ -740,7 +740,7 @@ static void rt73usb_config_lna_gain(struct rt2x00_dev *rt2x00dev,
 	short lna_gain = 0;
 
 	if (libconf->conf->channel->band == IEEE80211_BAND_2GHZ) {
-		if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags))
+		if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags))
 			lna_gain += 14;
 
 		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom);
@@ -930,7 +930,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev,
 		low_bound = 0x28;
 		up_bound = 0x48;
 
-		if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) {
+		if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) {
 			low_bound += 0x10;
 			up_bound += 0x10;
 		}
@@ -946,7 +946,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev,
 			up_bound = 0x1c;
 		}
 
-		if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) {
+		if (test_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags)) {
 			low_bound += 0x14;
 			up_bound += 0x10;
 		}
@@ -1661,7 +1661,7 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
 	}
 
 	if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
-		if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) {
+		if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) {
 			if (lna == 3 || lna == 2)
 				offset += 10;
 		} else {
@@ -1899,13 +1899,13 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
 	 * Read the Frame type.
 	 */
 	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_FRAME_TYPE))
-		__set_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags);
 
 	/*
 	 * Detect if this device has an hardware controlled radio.
 	 */
 	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
-		__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);
 
 	/*
 	 * Read frequency offset.
@@ -1919,8 +1919,8 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
 	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
 
 	if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA)) {
-		__set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
-		__set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);
+		__set_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags);
 	}
 
 	/*
@@ -2200,15 +2200,15 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
 	 * This device has multiple filters for control frames,
 	 * but has no a separate filter for PS Poll frames.
 	 */
-	__set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags);
+	__set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags);
 
 	/*
 	 * This device requires firmware.
 	 */
-	__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
+	__set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags);
 	if (!modparam_nohwcrypt)
-		__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
-	__set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
+		__set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
+	__set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
 
 	/*
 	 * Set the rssi offset.
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 04/23] rt2x00: Make rt2x00_queue_entry_for_each more flexible
  2011-04-18 13:27   ` [PATCH 03/23] rt2x00: Split rt2x00dev->flags Ivo van Doorn
@ 2011-04-18 13:27     ` Ivo van Doorn
  2011-04-18 13:28       ` [PATCH 05/23] rt2x00: Use correct TBTT_SYNC config in AP mode Ivo van Doorn
                         ` (2 more replies)
  0 siblings, 3 replies; 37+ messages in thread
From: Ivo van Doorn @ 2011-04-18 13:27 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users

From: Helmut Schaa <helmut.schaa@googlemail.com>

Allow passing a void pointer to rt2x00_queue_entry_for_each which in
turn in provided to the callback function.

Furthermore, allow the callback function to stop processing by returning
true. And also notify the caller of rt2x00_queue_entry_for_each if the
loop was canceled by the callback.

No functional changes, just preparation for an upcoming patch.

Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Acked-by: Gertjan van Wingerde <gwingerde@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2x00queue.c |   28 +++++++++++++++++--------
 drivers/net/wireless/rt2x00/rt2x00queue.h |   10 +++++++-
 drivers/net/wireless/rt2x00/rt2x00usb.c   |   32 +++++++++++++++++++---------
 3 files changed, 49 insertions(+), 21 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index d03eef2..458bb48 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -650,10 +650,12 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
 	return ret;
 }
 
-void rt2x00queue_for_each_entry(struct data_queue *queue,
+bool rt2x00queue_for_each_entry(struct data_queue *queue,
 				enum queue_index start,
 				enum queue_index end,
-				void (*fn)(struct queue_entry *entry))
+				void *data,
+				bool (*fn)(struct queue_entry *entry,
+					   void *data))
 {
 	unsigned long irqflags;
 	unsigned int index_start;
@@ -664,7 +666,7 @@ void rt2x00queue_for_each_entry(struct data_queue *queue,
 		ERROR(queue->rt2x00dev,
 		      "Entry requested from invalid index range (%d - %d)\n",
 		      start, end);
-		return;
+		return true;
 	}
 
 	/*
@@ -683,15 +685,23 @@ void rt2x00queue_for_each_entry(struct data_queue *queue,
 	 * send out all frames in the correct order.
 	 */
 	if (index_start < index_end) {
-		for (i = index_start; i < index_end; i++)
-			fn(&queue->entries[i]);
+		for (i = index_start; i < index_end; i++) {
+			if (fn(&queue->entries[i], data))
+				return true;
+		}
 	} else {
-		for (i = index_start; i < queue->limit; i++)
-			fn(&queue->entries[i]);
+		for (i = index_start; i < queue->limit; i++) {
+			if (fn(&queue->entries[i], data))
+				return true;
+		}
 
-		for (i = 0; i < index_end; i++)
-			fn(&queue->entries[i]);
+		for (i = 0; i < index_end; i++) {
+			if (fn(&queue->entries[i], data))
+				return true;
+		}
 	}
+
+	return false;
 }
 EXPORT_SYMBOL_GPL(rt2x00queue_for_each_entry);
 
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
index 6ae8200..6b66452 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -580,16 +580,22 @@ struct data_queue_desc {
  * @queue: Pointer to @data_queue
  * @start: &enum queue_index Pointer to start index
  * @end: &enum queue_index Pointer to end index
+ * @data: Data to pass to the callback function
  * @fn: The function to call for each &struct queue_entry
  *
  * This will walk through all entries in the queue, in chronological
  * order. This means it will start at the current @start pointer
  * and will walk through the queue until it reaches the @end pointer.
+ *
+ * If fn returns true for an entry rt2x00queue_for_each_entry will stop
+ * processing and return true as well.
  */
-void rt2x00queue_for_each_entry(struct data_queue *queue,
+bool rt2x00queue_for_each_entry(struct data_queue *queue,
 				enum queue_index start,
 				enum queue_index end,
-				void (*fn)(struct queue_entry *entry));
+				void *data,
+				bool (*fn)(struct queue_entry *entry,
+					   void *data));
 
 /**
  * rt2x00queue_empty - Check if the queue is empty.
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 94047e9..0bc8dcc 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -230,7 +230,7 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
 	queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
 }
 
-static void rt2x00usb_kick_tx_entry(struct queue_entry *entry)
+static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry, void* data)
 {
 	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
 	struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
@@ -240,7 +240,7 @@ static void rt2x00usb_kick_tx_entry(struct queue_entry *entry)
 
 	if (!test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags) ||
 	    test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
-		return;
+		return true;
 
 	/*
 	 * USB devices cannot blindly pass the skb->len as the
@@ -261,6 +261,8 @@ static void rt2x00usb_kick_tx_entry(struct queue_entry *entry)
 		set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
 		rt2x00lib_dmadone(entry);
 	}
+
+	return false;
 }
 
 /*
@@ -323,7 +325,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
 	queue_work(rt2x00dev->workqueue, &rt2x00dev->rxdone_work);
 }
 
-static void rt2x00usb_kick_rx_entry(struct queue_entry *entry)
+static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry, void* data)
 {
 	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
 	struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
@@ -332,7 +334,7 @@ static void rt2x00usb_kick_rx_entry(struct queue_entry *entry)
 
 	if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
 	    test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
-		return;
+		return true;
 
 	rt2x00lib_dmastart(entry);
 
@@ -348,6 +350,8 @@ static void rt2x00usb_kick_rx_entry(struct queue_entry *entry)
 		set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
 		rt2x00lib_dmadone(entry);
 	}
+
+	return false;
 }
 
 void rt2x00usb_kick_queue(struct data_queue *queue)
@@ -358,12 +362,18 @@ void rt2x00usb_kick_queue(struct data_queue *queue)
 	case QID_AC_BE:
 	case QID_AC_BK:
 		if (!rt2x00queue_empty(queue))
-			rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX,
+			rt2x00queue_for_each_entry(queue,
+						   Q_INDEX_DONE,
+						   Q_INDEX,
+						   NULL,
 						   rt2x00usb_kick_tx_entry);
 		break;
 	case QID_RX:
 		if (!rt2x00queue_full(queue))
-			rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX,
+			rt2x00queue_for_each_entry(queue,
+						   Q_INDEX_DONE,
+						   Q_INDEX,
+						   NULL,
 						   rt2x00usb_kick_rx_entry);
 		break;
 	default:
@@ -372,14 +382,14 @@ void rt2x00usb_kick_queue(struct data_queue *queue)
 }
 EXPORT_SYMBOL_GPL(rt2x00usb_kick_queue);
 
-static void rt2x00usb_flush_entry(struct queue_entry *entry)
+static bool rt2x00usb_flush_entry(struct queue_entry *entry, void* data)
 {
 	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
 	struct queue_entry_priv_usb *entry_priv = entry->priv_data;
 	struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data;
 
 	if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
-		return;
+		return true;
 
 	usb_kill_urb(entry_priv->urb);
 
@@ -389,6 +399,8 @@ static void rt2x00usb_flush_entry(struct queue_entry *entry)
 	if ((entry->queue->qid == QID_BEACON) &&
 	    (test_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags)))
 		usb_kill_urb(bcn_priv->guardian_urb);
+
+	return false;
 }
 
 void rt2x00usb_flush_queue(struct data_queue *queue)
@@ -396,7 +408,7 @@ void rt2x00usb_flush_queue(struct data_queue *queue)
 	struct work_struct *completion;
 	unsigned int i;
 
-	rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX,
+	rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, NULL,
 				   rt2x00usb_flush_entry);
 
 	/*
@@ -489,7 +501,7 @@ void rt2x00usb_clear_entry(struct queue_entry *entry)
 	entry->flags = 0;
 
 	if (entry->queue->qid == QID_RX)
-		rt2x00usb_kick_rx_entry(entry);
+		rt2x00usb_kick_rx_entry(entry, NULL);
 }
 EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry);
 
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 05/23] rt2x00: Use correct TBTT_SYNC config in AP mode
  2011-04-18 13:27     ` [PATCH 04/23] rt2x00: Make rt2x00_queue_entry_for_each more flexible Ivo van Doorn
@ 2011-04-18 13:28       ` Ivo van Doorn
  2011-04-18 13:28         ` [PATCH 06/23] rt2x00: Update TX_SW_CFG2 init value Ivo van Doorn
  2011-04-28  2:55       ` [PATCH 04/23] rt2x00: Make rt2x00_queue_entry_for_each more flexible Yasushi SHOJI
  2011-04-28  2:55       ` Yasushi SHOJI
  2 siblings, 1 reply; 37+ messages in thread
From: Ivo van Doorn @ 2011-04-18 13:28 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users

From: Helmut Schaa <helmut.schaa@googlemail.com>

This seems to fix problems with some powersaving clients since a
positive value in TBTT_SYNC_CFG_TBTT_ADJUST introduces beacon skew,
which is not wanted in AP mode.

Also update the rest of the TBTT_SYNC config according to the
legacy drivers in AP mode.

Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2800lib.c |   19 +++++++++++++++++++
 1 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index c6f5584..e0fa559 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -1245,6 +1245,25 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
 		rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_SYNC, conf->sync);
 		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+
+		if (conf->sync == TSF_SYNC_AP_NONE) {
+			/*
+			 * Tune beacon queue transmit parameters for AP mode
+			 */
+			rt2800_register_read(rt2x00dev, TBTT_SYNC_CFG, &reg);
+			rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_CWMIN, 0);
+			rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_AIFSN, 1);
+			rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_EXP_WIN, 32);
+			rt2x00_set_field32(&reg, TBTT_SYNC_CFG_TBTT_ADJUST, 0);
+			rt2800_register_write(rt2x00dev, TBTT_SYNC_CFG, reg);
+		} else {
+			rt2800_register_read(rt2x00dev, TBTT_SYNC_CFG, &reg);
+			rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_CWMIN, 4);
+			rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_AIFSN, 2);
+			rt2x00_set_field32(&reg, TBTT_SYNC_CFG_BCN_EXP_WIN, 32);
+			rt2x00_set_field32(&reg, TBTT_SYNC_CFG_TBTT_ADJUST, 16);
+			rt2800_register_write(rt2x00dev, TBTT_SYNC_CFG, reg);
+		}
 	}
 
 	if (flags & CONFIG_UPDATE_MAC) {
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 06/23] rt2x00: Update TX_SW_CFG2 init value
  2011-04-18 13:28       ` [PATCH 05/23] rt2x00: Use correct TBTT_SYNC config in AP mode Ivo van Doorn
@ 2011-04-18 13:28         ` Ivo van Doorn
  2011-04-18 13:28           ` [PATCH 07/23] rt2x00: Use TXOP_HTTXOP for beacons Ivo van Doorn
  0 siblings, 1 reply; 37+ messages in thread
From: Ivo van Doorn @ 2011-04-18 13:28 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users

From: Helmut Schaa <helmut.schaa@googlemail.com>

Bring the TX_SW_CFG2 initialisation for rt305x devices in sync with the
ralink legacy drivers.

Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
Acked-by: Gertjan van Wingerde <gwingerde@gmail.com>
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2800lib.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index e0fa559..0e2c006 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -2427,7 +2427,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 	} else if (rt2800_is_305x_soc(rt2x00dev)) {
 		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
 		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
-		rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x0000001f);
+		rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000030);
 	} else if (rt2x00_rt(rt2x00dev, RT5390)) {
 		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
 		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 07/23] rt2x00: Use TXOP_HTTXOP for beacons
  2011-04-18 13:28         ` [PATCH 06/23] rt2x00: Update TX_SW_CFG2 init value Ivo van Doorn
@ 2011-04-18 13:28           ` Ivo van Doorn
  2011-04-18 13:29             ` [PATCH 08/23] rt2800usb: read TX_STA_FIFO asynchronously Ivo van Doorn
  0 siblings, 1 reply; 37+ messages in thread
From: Ivo van Doorn @ 2011-04-18 13:28 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users

From: Helmut Schaa <helmut.schaa@googlemail.com>

Use TXOP_HTTXOP for beacons to stay in sync with the legacy drivers.

Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
Acked-by: Gertjan van Wingerde <gwingerde@gmail.com>
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2x00ht.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2x00ht.c b/drivers/net/wireless/rt2x00/rt2x00ht.c
index e8c0c3e..a30f68c 100644
--- a/drivers/net/wireless/rt2x00/rt2x00ht.c
+++ b/drivers/net/wireless/rt2x00/rt2x00ht.c
@@ -92,14 +92,15 @@ void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
 
 	/*
 	 * Determine IFS values
-	 * - Use TXOP_BACKOFF for management frames
+	 * - Use TXOP_BACKOFF for management frames except beacons
 	 * - Use TXOP_SIFS for fragment bursts
 	 * - Use TXOP_HTTXOP for everything else
 	 *
 	 * Note: rt2800 devices won't use CTS protection (if used)
 	 * for frames not transmitted with TXOP_HTTXOP
 	 */
-	if (ieee80211_is_mgmt(hdr->frame_control))
+	if (ieee80211_is_mgmt(hdr->frame_control) &&
+	    !ieee80211_is_beacon(hdr->frame_control))
 		txdesc->u.ht.txop = TXOP_BACKOFF;
 	else if (!(tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT))
 		txdesc->u.ht.txop = TXOP_SIFS;
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 08/23] rt2800usb: read TX_STA_FIFO asynchronously
  2011-04-18 13:28           ` [PATCH 07/23] rt2x00: Use TXOP_HTTXOP for beacons Ivo van Doorn
@ 2011-04-18 13:29             ` Ivo van Doorn
  2011-04-18 13:29               ` [PATCH 09/23] rt2x00: fix queue timeout checks Ivo van Doorn
  0 siblings, 1 reply; 37+ messages in thread
From: Ivo van Doorn @ 2011-04-18 13:29 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users

From: Johannes Stezenbach <js@sig21.net>

Trying to fix the "TX status report missed" warnings
by reading the TX_STA_FIFO entries as quickly as possible.
The TX_STA_FIFO is too small in hardware, thus reading
it only from the workqueue is too slow and entries get lost.

Start an asynchronous read of the TX_STA_FIFO directly from
the TX URB completion callback (atomic context, thus it cannot
use the blocking rt2800_register_read()). If the async
read returns a valid FIFO entry, it is pushed into a larger
FIFO inside struct rt2x00_dev, until rt2800_txdone() picks
it up.

A .tx_dma_done callback is added to struct rt2x00lib_ops
to trigger the async read from the URB completion callback.

Signed-off-by: Johannes Stezenbach <js@sig21.net>
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2800lib.c |   34 ++++++--------------
 drivers/net/wireless/rt2x00/rt2800usb.c |   31 ++++++++++++++++++
 drivers/net/wireless/rt2x00/rt2x00.h    |    1 +
 drivers/net/wireless/rt2x00/rt2x00usb.c |   53 +++++++++++++++++++++++++++++++
 drivers/net/wireless/rt2x00/rt2x00usb.h |   15 +++++++++
 5 files changed, 110 insertions(+), 24 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 0e2c006..d79c8fd 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -730,34 +730,20 @@ void rt2800_txdone(struct rt2x00_dev *rt2x00dev)
 	struct data_queue *queue;
 	struct queue_entry *entry;
 	u32 reg;
-	u8 pid;
-	int i;
+	u8 qid;
 
-	/*
-	 * TX_STA_FIFO is a stack of X entries, hence read TX_STA_FIFO
-	 * at most X times and also stop processing once the TX_STA_FIFO_VALID
-	 * flag is not set anymore.
-	 *
-	 * The legacy drivers use X=TX_RING_SIZE but state in a comment
-	 * that the TX_STA_FIFO stack has a size of 16. We stick to our
-	 * tx ring size for now.
-	 */
-	for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) {
-		rt2800_register_read(rt2x00dev, TX_STA_FIFO, &reg);
-		if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID))
-			break;
+	while (kfifo_get(&rt2x00dev->txstatus_fifo, &reg)) {
 
-		/*
-		 * Skip this entry when it contains an invalid
-		 * queue identication number.
+		/* TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus
+		 * qid is guaranteed to be one of the TX QIDs
 		 */
-		pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE);
-		if (pid >= QID_RX)
-			continue;
-
-		queue = rt2x00queue_get_tx_queue(rt2x00dev, pid);
-		if (unlikely(!queue))
+		qid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE);
+		queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
+		if (unlikely(!queue)) {
+			WARNING(rt2x00dev, "Got TX status for an unavailable "
+					   "queue %u, dropping\n", qid);
 			continue;
+		}
 
 		/*
 		 * Inside each queue, we process each entry in a chronological
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index f3ce5e8..862430e 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -98,6 +98,35 @@ static void rt2800usb_stop_queue(struct data_queue *queue)
 	}
 }
 
+static void rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev,
+						 int urb_status, u32 tx_status)
+{
+	if (urb_status) {
+		WARNING(rt2x00dev, "rt2x00usb_register_read_async failed: %d\n", urb_status);
+		return;
+	}
+
+	/* try to read all TX_STA_FIFO entries before scheduling txdone_work */
+	if (rt2x00_get_field32(tx_status, TX_STA_FIFO_VALID)) {
+		if (!kfifo_put(&rt2x00dev->txstatus_fifo, &tx_status)) {
+			WARNING(rt2x00dev, "TX status FIFO overrun, "
+				"drop tx status report.\n");
+			queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
+		} else
+			rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO,
+						      rt2800usb_tx_sta_fifo_read_completed);
+	} else if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo))
+		queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
+}
+
+static void rt2800usb_tx_dma_done(struct queue_entry *entry)
+{
+	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+
+	rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO,
+				      rt2800usb_tx_sta_fifo_read_completed);
+}
+
 /*
  * Firmware functions
  */
@@ -565,6 +594,7 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
 		__set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags);
 	__set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);
 	__set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags);
+	__set_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags);
 
 	/*
 	 * Set the rssi offset.
@@ -635,6 +665,7 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
 	.kick_queue		= rt2x00usb_kick_queue,
 	.stop_queue		= rt2800usb_stop_queue,
 	.flush_queue		= rt2x00usb_flush_queue,
+	.tx_dma_done		= rt2800usb_tx_dma_done,
 	.write_tx_desc		= rt2800usb_write_tx_desc,
 	.write_tx_data		= rt2800usb_write_tx_data,
 	.write_beacon		= rt2800_write_beacon,
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 79c385a..e3b9b51 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -571,6 +571,7 @@ struct rt2x00lib_ops {
 	void (*kick_queue) (struct data_queue *queue);
 	void (*stop_queue) (struct data_queue *queue);
 	void (*flush_queue) (struct data_queue *queue);
+	void (*tx_dma_done) (struct queue_entry *entry);
 
 	/*
 	 * TX control handlers
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 0bc8dcc..5fbab6f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -165,6 +165,56 @@ int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
 }
 EXPORT_SYMBOL_GPL(rt2x00usb_regbusy_read);
 
+
+struct rt2x00_async_read_data {
+	__le32 reg;
+	struct usb_ctrlrequest cr;
+	struct rt2x00_dev *rt2x00dev;
+	void (*callback)(struct rt2x00_dev *,int,u32);
+};
+
+static void rt2x00usb_register_read_async_cb(struct urb *urb)
+{
+	struct rt2x00_async_read_data *rd = urb->context;
+	rd->callback(rd->rt2x00dev, urb->status, le32_to_cpu(rd->reg));
+	kfree(urb->context);
+}
+
+void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev,
+				   const unsigned int offset,
+				   void (*callback)(struct rt2x00_dev*,int,u32))
+{
+	struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
+	struct urb *urb;
+	struct rt2x00_async_read_data *rd;
+
+	rd = kmalloc(sizeof(*rd), GFP_ATOMIC);
+	if (!rd)
+		return;
+
+	urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!urb) {
+		kfree(rd);
+		return;
+	}
+
+	rd->rt2x00dev = rt2x00dev;
+	rd->callback = callback;
+	rd->cr.bRequestType = USB_VENDOR_REQUEST_IN;
+	rd->cr.bRequest = USB_MULTI_READ;
+	rd->cr.wValue = 0;
+	rd->cr.wIndex = cpu_to_le16(offset);
+	rd->cr.wLength = cpu_to_le16(sizeof(u32));
+
+	usb_fill_control_urb(urb, usb_dev, usb_rcvctrlpipe(usb_dev, 0),
+			     (unsigned char *)(&rd->cr), &rd->reg, sizeof(rd->reg),
+			     rt2x00usb_register_read_async_cb, rd);
+	if (usb_submit_urb(urb, GFP_ATOMIC) < 0)
+		kfree(rd);
+	usb_free_urb(urb);
+}
+EXPORT_SYMBOL_GPL(rt2x00usb_register_read_async);
+
 /*
  * TX data handlers.
  */
@@ -212,6 +262,9 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
 	if (!test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
 		return;
 
+	if (rt2x00dev->ops->lib->tx_dma_done)
+		rt2x00dev->ops->lib->tx_dma_done(entry);
+
 	/*
 	 * Report the frame as DMA done
 	 */
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h
index 6aaf51f..e3faca6 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.h
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.h
@@ -345,6 +345,21 @@ int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
 			   const struct rt2x00_field32 field,
 			   u32 *reg);
 
+/**
+ * rt2x00usb_register_read_async - Asynchronously read 32bit register word
+ * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
+ * @offset: Register offset
+ * @callback: Functon to call when read completes.
+ *
+ * Submit a control URB to read a 32bit register. This safe to
+ * be called from atomic context.  The callback will be called
+ * when the URB completes. Otherwise the function is similar
+ * to rt2x00usb_register_read().
+ */
+void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev,
+				   const unsigned int offset,
+				   void (*callback)(struct rt2x00_dev*,int,u32));
+
 /*
  * Radio handlers
  */
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 09/23] rt2x00: fix queue timeout checks
  2011-04-18 13:29             ` [PATCH 08/23] rt2800usb: read TX_STA_FIFO asynchronously Ivo van Doorn
@ 2011-04-18 13:29               ` Ivo van Doorn
  2011-04-18 13:30                 ` [PATCH 10/23] rt2800usb: handle TX status timeouts Ivo van Doorn
  0 siblings, 1 reply; 37+ messages in thread
From: Ivo van Doorn @ 2011-04-18 13:29 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users

From: Johannes Stezenbach <js@sig21.net>

Add a timestamp to each queue entry which is updated whenever
the status of the entry changes, and remove the per-queue
timestamps.  The previous check was incorrect and caused both
false positives and false negatives.

With the corrected check it comes apparent that the TX status
usually times out on rt2800usb unless there is sufficient traffic
(i.e. the next TX will complete the previous TX status).

Signed-off-by: Johannes Stezenbach <js@sig21.net>
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2x00dev.c   |    8 ++++----
 drivers/net/wireless/rt2x00/rt2x00lib.h   |    6 +++---
 drivers/net/wireless/rt2x00/rt2x00queue.c |   11 +++++------
 drivers/net/wireless/rt2x00/rt2x00queue.h |   23 +++++++++++++----------
 drivers/net/wireless/rt2x00/rt2x00usb.c   |   20 ++++++++++++++++++--
 5 files changed, 43 insertions(+), 25 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index af25b01..2e490e0 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -225,7 +225,7 @@ EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt);
 void rt2x00lib_dmastart(struct queue_entry *entry)
 {
 	set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
-	rt2x00queue_index_inc(entry->queue, Q_INDEX);
+	rt2x00queue_index_inc(entry, Q_INDEX);
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_dmastart);
 
@@ -233,7 +233,7 @@ void rt2x00lib_dmadone(struct queue_entry *entry)
 {
 	set_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags);
 	clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
-	rt2x00queue_index_inc(entry->queue, Q_INDEX_DMA_DONE);
+	rt2x00queue_index_inc(entry, Q_INDEX_DMA_DONE);
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_dmadone);
 
@@ -392,7 +392,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,
 
 	rt2x00dev->ops->lib->clear_entry(entry);
 
-	rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE);
+	rt2x00queue_index_inc(entry, Q_INDEX_DONE);
 
 	/*
 	 * If the data queue was below the threshold before the txdone
@@ -559,7 +559,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry)
 
 submit_entry:
 	entry->flags = 0;
-	rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE);
+	rt2x00queue_index_inc(entry, Q_INDEX_DONE);
 	if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
 	    test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
 		rt2x00dev->ops->lib->clear_entry(entry);
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index bbee2cd..57ede6c 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -175,14 +175,14 @@ int rt2x00queue_clear_beacon(struct rt2x00_dev *rt2x00dev,
 
 /**
  * rt2x00queue_index_inc - Index incrementation function
- * @queue: Queue (&struct data_queue) to perform the action on.
+ * @entry: Queue entry (&struct queue_entry) to perform the action on.
  * @index: Index type (&enum queue_index) to perform the action on.
  *
- * This function will increase the requested index on the queue,
+ * This function will increase the requested index on the entry's queue,
  * it will grab the appropriate locks and handle queue overflow events by
  * resetting the index to the start of the queue.
  */
-void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index);
+void rt2x00queue_index_inc(struct queue_entry *entry, enum queue_index index);
 
 /**
  * rt2x00queue_init_queues - Initialize all data queues
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 458bb48..df8817f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -561,7 +561,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
 
 	set_bit(ENTRY_DATA_PENDING, &entry->flags);
 
-	rt2x00queue_index_inc(queue, Q_INDEX);
+	rt2x00queue_index_inc(entry, Q_INDEX);
 	rt2x00queue_write_tx_descriptor(entry, &txdesc);
 	rt2x00queue_kick_tx_queue(queue, &txdesc);
 
@@ -727,8 +727,9 @@ struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue,
 }
 EXPORT_SYMBOL_GPL(rt2x00queue_get_entry);
 
-void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index)
+void rt2x00queue_index_inc(struct queue_entry *entry, enum queue_index index)
 {
+	struct data_queue *queue = entry->queue;
 	unsigned long irqflags;
 
 	if (unlikely(index >= Q_INDEX_MAX)) {
@@ -743,7 +744,7 @@ void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index)
 	if (queue->index[index] >= queue->limit)
 		queue->index[index] = 0;
 
-	queue->last_action[index] = jiffies;
+	entry->last_action = jiffies;
 
 	if (index == Q_INDEX) {
 		queue->length++;
@@ -969,10 +970,8 @@ static void rt2x00queue_reset(struct data_queue *queue)
 	queue->count = 0;
 	queue->length = 0;
 
-	for (i = 0; i < Q_INDEX_MAX; i++) {
+	for (i = 0; i < Q_INDEX_MAX; i++)
 		queue->index[i] = 0;
-		queue->last_action[i] = jiffies;
-	}
 
 	spin_unlock_irqrestore(&queue->index_lock, irqflags);
 }
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
index 6b66452..36f4d03 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -364,6 +364,7 @@ enum queue_entry_flags {
  * struct queue_entry: Entry inside the &struct data_queue
  *
  * @flags: Entry flags, see &enum queue_entry_flags.
+ * @last_action: Timestamp of last change.
  * @queue: The data queue (&struct data_queue) to which this entry belongs.
  * @skb: The buffer which is currently being transmitted (for TX queue),
  *	or used to directly recieve data in (for RX queue).
@@ -373,6 +374,7 @@ enum queue_entry_flags {
  */
 struct queue_entry {
 	unsigned long flags;
+	unsigned long last_action;
 
 	struct data_queue *queue;
 
@@ -463,7 +465,6 @@ struct data_queue {
 	unsigned short threshold;
 	unsigned short length;
 	unsigned short index[Q_INDEX_MAX];
-	unsigned long last_action[Q_INDEX_MAX];
 
 	unsigned short txop;
 	unsigned short aifs;
@@ -635,22 +636,24 @@ static inline int rt2x00queue_threshold(struct data_queue *queue)
 
 /**
  * rt2x00queue_status_timeout - Check if a timeout occured for STATUS reports
- * @queue: Queue to check.
+ * @entry: Queue entry to check.
  */
-static inline int rt2x00queue_status_timeout(struct data_queue *queue)
+static inline int rt2x00queue_status_timeout(struct queue_entry *entry)
 {
-	return time_after(queue->last_action[Q_INDEX_DMA_DONE],
-			  queue->last_action[Q_INDEX_DONE] + (HZ / 10));
+	if (!test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
+		return false;
+	return time_after(jiffies, entry->last_action + msecs_to_jiffies(100));
 }
 
 /**
- * rt2x00queue_timeout - Check if a timeout occured for DMA transfers
- * @queue: Queue to check.
+ * rt2x00queuedma__timeout - Check if a timeout occured for DMA transfers
+ * @entry: Queue entry to check.
  */
-static inline int rt2x00queue_dma_timeout(struct data_queue *queue)
+static inline int rt2x00queue_dma_timeout(struct queue_entry *entry)
 {
-	return time_after(queue->last_action[Q_INDEX],
-			  queue->last_action[Q_INDEX_DMA_DONE] + (HZ / 10));
+	if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+		return false;
+	return time_after(jiffies, entry->last_action + msecs_to_jiffies(100));
 }
 
 /**
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 5fbab6f..14736e2 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -521,15 +521,31 @@ static void rt2x00usb_watchdog_tx_status(struct data_queue *queue)
 	queue_work(queue->rt2x00dev->workqueue, &queue->rt2x00dev->txdone_work);
 }
 
+static int rt2x00usb_status_timeout(struct data_queue *queue)
+{
+	struct queue_entry *entry;
+
+	entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
+	return rt2x00queue_status_timeout(entry);
+}
+
+static int rt2x00usb_dma_timeout(struct data_queue *queue)
+{
+	struct queue_entry *entry;
+
+	entry = rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE);
+	return rt2x00queue_dma_timeout(entry);
+}
+
 void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev)
 {
 	struct data_queue *queue;
 
 	tx_queue_for_each(rt2x00dev, queue) {
 		if (!rt2x00queue_empty(queue)) {
-			if (rt2x00queue_dma_timeout(queue))
+			if (rt2x00usb_dma_timeout(queue))
 				rt2x00usb_watchdog_tx_dma(queue);
-			if (rt2x00queue_status_timeout(queue))
+			if (rt2x00usb_status_timeout(queue))
 				rt2x00usb_watchdog_tx_status(queue);
 		}
 	}
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 10/23] rt2800usb: handle TX status timeouts
  2011-04-18 13:29               ` [PATCH 09/23] rt2x00: fix queue timeout checks Ivo van Doorn
@ 2011-04-18 13:30                 ` Ivo van Doorn
  2011-04-18 13:30                   ` [PATCH 11/23] rt2800usb: add timer to handle TX_STA_FIFO Ivo van Doorn
  0 siblings, 1 reply; 37+ messages in thread
From: Ivo van Doorn @ 2011-04-18 13:30 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users

From: Johannes Stezenbach <js@sig21.net>

The watchdog just triggers rt2800usb_work_txdone() when it
detects a TX status timeout, thus rt2800usb_work_txdone() needs to
handle this case.

Signed-off-by: Johannes Stezenbach <js@sig21.net>
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2800usb.c |   11 +++++++----
 1 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 862430e..69004b9 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -449,11 +449,14 @@ static void rt2800usb_work_txdone(struct work_struct *work)
 		while (!rt2x00queue_empty(queue)) {
 			entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
 
-			if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
-			    !test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
+			if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
+				break;
+			if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
+				rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
+			else if (rt2x00queue_status_timeout(entry))
+				rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN);
+			else
 				break;
-
-			rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
 		}
 	}
 }
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 11/23] rt2800usb: add timer to handle TX_STA_FIFO
  2011-04-18 13:30                 ` [PATCH 10/23] rt2800usb: handle TX status timeouts Ivo van Doorn
@ 2011-04-18 13:30                   ` Ivo van Doorn
  2011-04-18 13:31                     ` [PATCH 12/23] Decrease association time for USB devices Ivo van Doorn
  0 siblings, 1 reply; 37+ messages in thread
From: Ivo van Doorn @ 2011-04-18 13:30 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users

From: Johannes Stezenbach <js@sig21.net>

TX status is reported by the hardware when a packet has been
sent (or after TX failed after possible retries), which is some
time after the DMA completion.  Since the rt2800usb hardware can
not signal interrupts we have to use a timer, otherwise the
TX status would only be read by the next packet's TX DMA
completion, or by the watchdog thread.

Signed-off-by: Johannes Stezenbach <js@sig21.net>
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2800usb.c |   41 ++++++++++++++++++++++++++++++-
 drivers/net/wireless/rt2x00/rt2x00.h    |    6 ++++
 drivers/net/wireless/rt2x00/rt2x00dev.c |    1 +
 drivers/net/wireless/rt2x00/rt2x00usb.c |    5 +++-
 4 files changed, 51 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 69004b9..2005972 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -98,6 +98,22 @@ static void rt2800usb_stop_queue(struct data_queue *queue)
 	}
 }
 
+/*
+ * test if there is an entry in any TX queue for which DMA is done
+ * but the TX status has not been returned yet
+ */
+static bool rt2800usb_txstatus_pending(struct rt2x00_dev *rt2x00dev)
+{
+	struct data_queue *queue;
+
+	tx_queue_for_each(rt2x00dev, queue) {
+		if (rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE) !=
+		    rt2x00queue_get_entry(queue, Q_INDEX_DONE))
+			return true;
+	}
+	return false;
+}
+
 static void rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev,
 						 int urb_status, u32 tx_status)
 {
@@ -115,8 +131,11 @@ static void rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev,
 		} else
 			rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO,
 						      rt2800usb_tx_sta_fifo_read_completed);
-	} else if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo))
+	} else if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo)) {
 		queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
+	} else if (rt2800usb_txstatus_pending(rt2x00dev)) {
+		mod_timer(&rt2x00dev->txstatus_timer, jiffies + msecs_to_jiffies(20));
+	}
 }
 
 static void rt2800usb_tx_dma_done(struct queue_entry *entry)
@@ -127,6 +146,14 @@ static void rt2800usb_tx_dma_done(struct queue_entry *entry)
 				      rt2800usb_tx_sta_fifo_read_completed);
 }
 
+static void rt2800usb_tx_sta_fifo_timeout(unsigned long data)
+{
+	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+
+	rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO,
+				      rt2800usb_tx_sta_fifo_read_completed);
+}
+
 /*
  * Firmware functions
  */
@@ -459,6 +486,14 @@ static void rt2800usb_work_txdone(struct work_struct *work)
 				break;
 		}
 	}
+
+	/*
+	 * The hw may delay sending the packet after DMA complete
+	 * if the medium is busy, thus the TX_STA_FIFO entry is
+	 * also delayed -> use a timer to retrieve it.
+	 */
+	if (rt2800usb_txstatus_pending(rt2x00dev))
+		mod_timer(&rt2x00dev->txstatus_timer, jiffies + msecs_to_jiffies(20));
 }
 
 /*
@@ -599,6 +634,10 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
 	__set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags);
 	__set_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags);
 
+	setup_timer(&rt2x00dev->txstatus_timer,
+		    rt2800usb_tx_sta_fifo_timeout,
+		    (unsigned long) rt2x00dev);
+
 	/*
 	 * Set the rssi offset.
 	 */
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index e3b9b51..8f37121 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -37,6 +37,7 @@
 #include <linux/etherdevice.h>
 #include <linux/input-polldev.h>
 #include <linux/kfifo.h>
+#include <linux/timer.h>
 
 #include <net/mac80211.h>
 
@@ -924,6 +925,11 @@ struct rt2x00_dev {
 	DECLARE_KFIFO_PTR(txstatus_fifo, u32);
 
 	/*
+	 * Timer to ensure tx status reports are read (rt2800usb).
+	 */
+	struct timer_list txstatus_timer;
+
+	/*
 	 * Tasklet for processing tx status reports (rt2800pci).
 	 */
 	struct tasklet_struct txstatus_tasklet;
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 2e490e0..7776d9f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -1071,6 +1071,7 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
 	/*
 	 * Stop all work.
 	 */
+	del_timer_sync(&rt2x00dev->txstatus_timer);
 	cancel_work_sync(&rt2x00dev->intf_work);
 	if (rt2x00_is_usb(rt2x00dev)) {
 		cancel_work_sync(&rt2x00dev->rxdone_work);
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 14736e2..34b8a88 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -280,7 +280,9 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
 	 * Schedule the delayed work for reading the TX status
 	 * from the device.
 	 */
-	queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
+	if (!test_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags) ||
+	    !kfifo_is_empty(&rt2x00dev->txstatus_fifo))
+		queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
 }
 
 static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry, void* data)
@@ -816,6 +818,7 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
 
 	INIT_WORK(&rt2x00dev->rxdone_work, rt2x00usb_work_rxdone);
 	INIT_WORK(&rt2x00dev->txdone_work, rt2x00usb_work_txdone);
+	init_timer(&rt2x00dev->txstatus_timer);
 
 	retval = rt2x00usb_alloc_reg(rt2x00dev);
 	if (retval)
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 12/23] Decrease association time for USB devices
  2011-04-18 13:30                   ` [PATCH 11/23] rt2800usb: add timer to handle TX_STA_FIFO Ivo van Doorn
@ 2011-04-18 13:31                     ` Ivo van Doorn
  2011-04-18 13:31                       ` [PATCH 13/23] rt2x00: Always inline rt2x00pci_enable_interrupt Ivo van Doorn
  0 siblings, 1 reply; 37+ messages in thread
From: Ivo van Doorn @ 2011-04-18 13:31 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users

From: Ivo van Doorn <IvDoorn@gmail.com>

When powersaving is enabled, assocaition times are very high
(for WPA2 networks, the time can easily be around the 3 seconds).

This is caused, because the flushing of the queues takes
too much time. Without the flushing callback mac80211 assumes
a timeout of 100ms while scanning. Limit all flush waiting
loops to the same maximum.

We can apply this maximum by passing the drop status to the
driver, which makes sure the driver performs extra actions
during the waiting for the queue to become empty.

After these changes, association times fall within the
healthy range of ~0.6 seconds with powersaving enabled.
The difference between association time between powersaving
enabled and disabled is now only ~0.1 second (which can also
be due to the measuring method).

Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Acked-by: Gertjan van Wingerde <gwingerde@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2400pci.c   |    1 +
 drivers/net/wireless/rt2x00/rt2500pci.c   |    1 +
 drivers/net/wireless/rt2x00/rt2800pci.c   |    1 +
 drivers/net/wireless/rt2x00/rt2x00.h      |    2 +-
 drivers/net/wireless/rt2x00/rt2x00pci.c   |    9 +++++++++
 drivers/net/wireless/rt2x00/rt2x00pci.h   |   10 ++++++++++
 drivers/net/wireless/rt2x00/rt2x00queue.c |   19 +++++--------------
 drivers/net/wireless/rt2x00/rt2x00usb.c   |    9 +++++----
 drivers/net/wireless/rt2x00/rt2x00usb.h   |    8 +++++---
 drivers/net/wireless/rt2x00/rt61pci.c     |    1 +
 10 files changed, 39 insertions(+), 22 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 5d1654a..6b7206e 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -1740,6 +1740,7 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
 	.start_queue		= rt2400pci_start_queue,
 	.kick_queue		= rt2400pci_kick_queue,
 	.stop_queue		= rt2400pci_stop_queue,
+	.flush_queue		= rt2x00pci_flush_queue,
 	.write_tx_desc		= rt2400pci_write_tx_desc,
 	.write_beacon		= rt2400pci_write_beacon,
 	.fill_rxdone		= rt2400pci_fill_rxdone,
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index 3da954e..82e8012 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -2033,6 +2033,7 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
 	.start_queue		= rt2500pci_start_queue,
 	.kick_queue		= rt2500pci_kick_queue,
 	.stop_queue		= rt2500pci_stop_queue,
+	.flush_queue		= rt2x00pci_flush_queue,
 	.write_tx_desc		= rt2500pci_write_tx_desc,
 	.write_beacon		= rt2500pci_write_beacon,
 	.fill_rxdone		= rt2500pci_fill_rxdone,
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 4241f19..d2fe5fd 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -1057,6 +1057,7 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
 	.start_queue		= rt2800pci_start_queue,
 	.kick_queue		= rt2800pci_kick_queue,
 	.stop_queue		= rt2800pci_stop_queue,
+	.flush_queue		= rt2x00pci_flush_queue,
 	.write_tx_desc		= rt2800pci_write_tx_desc,
 	.write_tx_data		= rt2800_write_tx_data,
 	.write_beacon		= rt2800_write_beacon,
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 8f37121..dcdc50d 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -571,7 +571,7 @@ struct rt2x00lib_ops {
 	void (*start_queue) (struct data_queue *queue);
 	void (*kick_queue) (struct data_queue *queue);
 	void (*stop_queue) (struct data_queue *queue);
-	void (*flush_queue) (struct data_queue *queue);
+	void (*flush_queue) (struct data_queue *queue, bool drop);
 	void (*tx_dma_done) (struct queue_entry *entry);
 
 	/*
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
index 9649bd0..695aecf 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
@@ -99,6 +99,15 @@ bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
 }
 EXPORT_SYMBOL_GPL(rt2x00pci_rxdone);
 
+void rt2x00pci_flush_queue(struct data_queue *queue, bool drop)
+{
+	unsigned int i;
+
+	for (i = 0; !rt2x00queue_empty(queue) && i < 10; i++)
+		msleep(10);
+}
+EXPORT_SYMBOL_GPL(rt2x00pci_flush_queue);
+
 /*
  * Device initialization handlers.
  */
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h
index 07961b8..5d58874 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.h
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.h
@@ -107,6 +107,16 @@ struct queue_entry_priv_pci {
  */
 bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev);
 
+/**
+ * rt2x00pci_flush_queue - Flush data queue
+ * @queue: Data queue to stop
+ * @drop: True to drop all pending frames.
+ *
+ * This will wait for a maximum of 100ms, waiting for the queues
+ * to become empty.
+ */
+void rt2x00pci_flush_queue(struct data_queue *queue, bool drop);
+
 /*
  * Device initialization handlers.
  */
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index df8817f..0d79278 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -849,7 +849,6 @@ EXPORT_SYMBOL_GPL(rt2x00queue_stop_queue);
 
 void rt2x00queue_flush_queue(struct data_queue *queue, bool drop)
 {
-	unsigned int i;
 	bool started;
 	bool tx_queue =
 		(queue->qid == QID_AC_VO) ||
@@ -884,20 +883,12 @@ void rt2x00queue_flush_queue(struct data_queue *queue, bool drop)
 	}
 
 	/*
-	 * Check if driver supports flushing, we can only guarentee
-	 * full support for flushing if the driver is able
-	 * to cancel all pending frames (drop = true).
-	 */
-	if (drop && queue->rt2x00dev->ops->lib->flush_queue)
-		queue->rt2x00dev->ops->lib->flush_queue(queue);
-
-	/*
-	 * When we don't want to drop any frames, or when
-	 * the driver doesn't fully flush the queue correcly,
-	 * we must wait for the queue to become empty.
+	 * Check if driver supports flushing, if that is the case we can
+	 * defer the flushing to the driver. Otherwise we must use the
+	 * alternative which just waits for the queue to become empty.
 	 */
-	for (i = 0; !rt2x00queue_empty(queue) && i < 100; i++)
-		msleep(10);
+	if (likely(queue->rt2x00dev->ops->lib->flush_queue))
+		queue->rt2x00dev->ops->lib->flush_queue(queue, drop);
 
 	/*
 	 * The queue flush has failed...
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 34b8a88..9957579 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -458,13 +458,14 @@ static bool rt2x00usb_flush_entry(struct queue_entry *entry, void* data)
 	return false;
 }
 
-void rt2x00usb_flush_queue(struct data_queue *queue)
+void rt2x00usb_flush_queue(struct data_queue *queue, bool drop)
 {
 	struct work_struct *completion;
 	unsigned int i;
 
-	rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, NULL,
-				   rt2x00usb_flush_entry);
+	if (drop)
+		rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, NULL,
+					   rt2x00usb_flush_entry);
 
 	/*
 	 * Obtain the queue completion handler
@@ -483,7 +484,7 @@ void rt2x00usb_flush_queue(struct data_queue *queue)
 		return;
 	}
 
-	for (i = 0; i < 20; i++) {
+	for (i = 0; i < 10; i++) {
 		/*
 		 * Check if the driver is already done, otherwise we
 		 * have to sleep a little while to give the driver/hw
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h
index e3faca6..6aeba71 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.h
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.h
@@ -404,11 +404,13 @@ void rt2x00usb_kick_queue(struct data_queue *queue);
 /**
  * rt2x00usb_flush_queue - Flush data queue
  * @queue: Data queue to stop
+ * @drop: True to drop all pending frames.
  *
- * This will walk through all entries of the queue and kill all
- * URB's which were send to the device.
+ * This will walk through all entries of the queue and will optionally
+ * kill all URB's which were send to the device, or at least wait until
+ * they have been returned from the device..
  */
-void rt2x00usb_flush_queue(struct data_queue *queue);
+void rt2x00usb_flush_queue(struct data_queue *queue, bool drop);
 
 /**
  * rt2x00usb_watchdog - Watchdog for USB communication
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index c16c150..35c5d20 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -3003,6 +3003,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
 	.start_queue		= rt61pci_start_queue,
 	.kick_queue		= rt61pci_kick_queue,
 	.stop_queue		= rt61pci_stop_queue,
+	.flush_queue		= rt2x00pci_flush_queue,
 	.write_tx_desc		= rt61pci_write_tx_desc,
 	.write_beacon		= rt61pci_write_beacon,
 	.clear_beacon		= rt61pci_clear_beacon,
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 13/23] rt2x00: Always inline rt2x00pci_enable_interrupt
  2011-04-18 13:31                     ` [PATCH 12/23] Decrease association time for USB devices Ivo van Doorn
@ 2011-04-18 13:31                       ` Ivo van Doorn
  2011-04-18 13:31                         ` [PATCH 14/23] rt2x00: Linksys WUSB600N rev2 is a RT3572 device Ivo van Doorn
  0 siblings, 1 reply; 37+ messages in thread
From: Ivo van Doorn @ 2011-04-18 13:31 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users

From: Helmut Schaa <helmut.schaa@googlemail.com>

This allows the compiler to perform the necessary bitfield calculations
during compile time instead of run time and thus reduces the number of
instructions to run during each tasklet invocation. This should improve
performance in the RX hotpath.

This comes at the cost of a slight increase in the module size (for
example rt2800pci):

Before:
   text    data     bss     dec     hex filename
  14133     832       4   14969    3a79 drivers/net/wireless/rt2x00/rt2800pci.ko

After:
   text    data     bss     dec     hex filename
  14149     832       4   14985    3a89 drivers/net/wireless/rt2x00/rt2800pci.ko

Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
Acked-by: Gertjan van Wingerde <gwingerde@gmail.com>
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2400pci.c |    4 ++--
 drivers/net/wireless/rt2x00/rt2500pci.c |    4 ++--
 drivers/net/wireless/rt2x00/rt2800pci.c |    4 ++--
 drivers/net/wireless/rt2x00/rt61pci.c   |    4 ++--
 4 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 6b7206e..01e9517 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -1314,8 +1314,8 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev,
 	}
 }
 
-static void rt2400pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
-				       struct rt2x00_field32 irq_field)
+static inline void rt2400pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
+					      struct rt2x00_field32 irq_field)
 {
 	u32 reg;
 
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index 82e8012..c8deeeb 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -1446,8 +1446,8 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev,
 	}
 }
 
-static void rt2500pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
-				       struct rt2x00_field32 irq_field)
+static inline void rt2500pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
+					      struct rt2x00_field32 irq_field)
 {
 	u32 reg;
 
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index d2fe5fd..46c3e3c 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -768,8 +768,8 @@ static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
 	return !max_tx_done;
 }
 
-static void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
-				       struct rt2x00_field32 irq_field)
+static inline void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
+					      struct rt2x00_field32 irq_field)
 {
 	u32 reg;
 
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 35c5d20..264508f 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -2260,8 +2260,8 @@ static void rt61pci_wakeup(struct rt2x00_dev *rt2x00dev)
 	rt61pci_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS);
 }
 
-static void rt61pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
-				     struct rt2x00_field32 irq_field)
+static inline void rt61pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
+					    struct rt2x00_field32 irq_field)
 {
 	u32 reg;
 
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 14/23] rt2x00: Linksys WUSB600N rev2 is a RT3572 device.
  2011-04-18 13:31                       ` [PATCH 13/23] rt2x00: Always inline rt2x00pci_enable_interrupt Ivo van Doorn
@ 2011-04-18 13:31                         ` Ivo van Doorn
  2011-04-18 13:32                           ` [PATCH 15/23] rt2x00: Allow dynamic addition of PCI/USB IDs Ivo van Doorn
  0 siblings, 1 reply; 37+ messages in thread
From: Ivo van Doorn @ 2011-04-18 13:31 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users

From: Gertjan van Wingerde <gwingerde@gmail.com>

Move the USB ID entry from the unknown devices to the list of RT35xx based
devices.

Signed-off-by: Gertjan van Wingerde <gwingerde@gmail.com>
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2800usb.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 2005972..1bb9a7d 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -983,6 +983,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
 	{ USB_DEVICE(0x04bb, 0x0944), USB_DEVICE_DATA(&rt2800usb_ops) },
 	/* Linksys */
 	{ USB_DEVICE(0x13b1, 0x002f), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1737, 0x0079), USB_DEVICE_DATA(&rt2800usb_ops) },
 	/* Ralink */
 	{ USB_DEVICE(0x148f, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) },
 	/* Sitecom */
@@ -1041,7 +1042,6 @@ static struct usb_device_id rt2800usb_device_table[] = {
 	/* Linksys */
 	{ USB_DEVICE(0x1737, 0x0077), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x1737, 0x0078), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1737, 0x0079), USB_DEVICE_DATA(&rt2800usb_ops) },
 	/* Motorola */
 	{ USB_DEVICE(0x100d, 0x9032), USB_DEVICE_DATA(&rt2800usb_ops) },
 	/* Ovislink */
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 15/23] rt2x00: Allow dynamic addition of PCI/USB IDs.
  2011-04-18 13:31                         ` [PATCH 14/23] rt2x00: Linksys WUSB600N rev2 is a RT3572 device Ivo van Doorn
@ 2011-04-18 13:32                           ` Ivo van Doorn
  2011-04-18 13:32                             ` [PATCH 16/23] rt2x00: Add USB IDs Ivo van Doorn
  0 siblings, 1 reply; 37+ messages in thread
From: Ivo van Doorn @ 2011-04-18 13:32 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users

From: Gertjan van Wingerde <gwingerde@gmail.com>

Both USB and PCI drivers allow a system administrator to dynamically add
USB/PCI IDs to the device table that a driver supports via the
/sys/bus/{usb,pci,pci_express}/drivers/<driver-name>/new_id files.

However, for the rt2x00 drivers using this method currently crashes the
system with a NULL pointer failure.

This is due to the set-up of rt2x00 where the probe functions require a
rt2x00_ops structure in the driver_info field of the probed device. As
this field is empty for the dynamically added devices this fails for
these devices.

Fix this by introducing driver-specific probe wrappers that do nothing
but calling the bus-specific probe functions with the rt2x00_ops structure
as an argument, rather than depending on the driver_info field.

Signed-off-by: Gertjan van Wingerde <gwingerde@gmail.com>
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2400pci.c |   11 +-
 drivers/net/wireless/rt2x00/rt2500pci.c |   10 +-
 drivers/net/wireless/rt2x00/rt2500usb.c |   70 +++---
 drivers/net/wireless/rt2x00/rt2800pci.c |   58 +++--
 drivers/net/wireless/rt2x00/rt2800usb.c |  440 ++++++++++++++++---------------
 drivers/net/wireless/rt2x00/rt2x00pci.c |    3 +-
 drivers/net/wireless/rt2x00/rt2x00pci.h |    2 +-
 drivers/net/wireless/rt2x00/rt2x00usb.c |    3 +-
 drivers/net/wireless/rt2x00/rt2x00usb.h |    8 +-
 drivers/net/wireless/rt2x00/rt61pci.c   |   14 +-
 drivers/net/wireless/rt2x00/rt73usb.c   |  154 ++++++-----
 11 files changed, 404 insertions(+), 369 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 01e9517..d4acdde 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -1802,10 +1802,11 @@ static const struct rt2x00_ops rt2400pci_ops = {
  * RT2400pci module information.
  */
 static DEFINE_PCI_DEVICE_TABLE(rt2400pci_device_table) = {
-	{ PCI_DEVICE(0x1814, 0x0101), PCI_DEVICE_DATA(&rt2400pci_ops) },
+	{ PCI_DEVICE(0x1814, 0x0101) },
 	{ 0, }
 };
 
+
 MODULE_AUTHOR(DRV_PROJECT);
 MODULE_VERSION(DRV_VERSION);
 MODULE_DESCRIPTION("Ralink RT2400 PCI & PCMCIA Wireless LAN driver.");
@@ -1813,10 +1814,16 @@ MODULE_SUPPORTED_DEVICE("Ralink RT2460 PCI & PCMCIA chipset based cards");
 MODULE_DEVICE_TABLE(pci, rt2400pci_device_table);
 MODULE_LICENSE("GPL");
 
+static int rt2400pci_probe(struct pci_dev *pci_dev,
+			   const struct pci_device_id *id)
+{
+	return rt2x00pci_probe(pci_dev, &rt2400pci_ops);
+}
+
 static struct pci_driver rt2400pci_driver = {
 	.name		= KBUILD_MODNAME,
 	.id_table	= rt2400pci_device_table,
-	.probe		= rt2x00pci_probe,
+	.probe		= rt2400pci_probe,
 	.remove		= __devexit_p(rt2x00pci_remove),
 	.suspend	= rt2x00pci_suspend,
 	.resume		= rt2x00pci_resume,
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index c8deeeb..15f5649 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -2095,7 +2095,7 @@ static const struct rt2x00_ops rt2500pci_ops = {
  * RT2500pci module information.
  */
 static DEFINE_PCI_DEVICE_TABLE(rt2500pci_device_table) = {
-	{ PCI_DEVICE(0x1814, 0x0201), PCI_DEVICE_DATA(&rt2500pci_ops) },
+	{ PCI_DEVICE(0x1814, 0x0201) },
 	{ 0, }
 };
 
@@ -2106,10 +2106,16 @@ MODULE_SUPPORTED_DEVICE("Ralink RT2560 PCI & PCMCIA chipset based cards");
 MODULE_DEVICE_TABLE(pci, rt2500pci_device_table);
 MODULE_LICENSE("GPL");
 
+static int rt2500pci_probe(struct pci_dev *pci_dev,
+			   const struct pci_device_id *id)
+{
+	return rt2x00pci_probe(pci_dev, &rt2500pci_ops);
+}
+
 static struct pci_driver rt2500pci_driver = {
 	.name		= KBUILD_MODNAME,
 	.id_table	= rt2500pci_device_table,
-	.probe		= rt2x00pci_probe,
+	.probe		= rt2500pci_probe,
 	.remove		= __devexit_p(rt2x00pci_remove),
 	.suspend	= rt2x00pci_suspend,
 	.resume		= rt2x00pci_resume,
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index dbbd8bc..d88c367 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -1904,54 +1904,54 @@ static const struct rt2x00_ops rt2500usb_ops = {
  */
 static struct usb_device_id rt2500usb_device_table[] = {
 	/* ASUS */
-	{ USB_DEVICE(0x0b05, 0x1706), USB_DEVICE_DATA(&rt2500usb_ops) },
-	{ USB_DEVICE(0x0b05, 0x1707), USB_DEVICE_DATA(&rt2500usb_ops) },
+	{ USB_DEVICE(0x0b05, 0x1706) },
+	{ USB_DEVICE(0x0b05, 0x1707) },
 	/* Belkin */
-	{ USB_DEVICE(0x050d, 0x7050), USB_DEVICE_DATA(&rt2500usb_ops) },
-	{ USB_DEVICE(0x050d, 0x7051), USB_DEVICE_DATA(&rt2500usb_ops) },
+	{ USB_DEVICE(0x050d, 0x7050) },
+	{ USB_DEVICE(0x050d, 0x7051) },
 	/* Cisco Systems */
-	{ USB_DEVICE(0x13b1, 0x000d), USB_DEVICE_DATA(&rt2500usb_ops) },
-	{ USB_DEVICE(0x13b1, 0x0011), USB_DEVICE_DATA(&rt2500usb_ops) },
-	{ USB_DEVICE(0x13b1, 0x001a), USB_DEVICE_DATA(&rt2500usb_ops) },
+	{ USB_DEVICE(0x13b1, 0x000d) },
+	{ USB_DEVICE(0x13b1, 0x0011) },
+	{ USB_DEVICE(0x13b1, 0x001a) },
 	/* Conceptronic */
-	{ USB_DEVICE(0x14b2, 0x3c02), USB_DEVICE_DATA(&rt2500usb_ops) },
+	{ USB_DEVICE(0x14b2, 0x3c02) },
 	/* D-LINK */
-	{ USB_DEVICE(0x2001, 0x3c00), USB_DEVICE_DATA(&rt2500usb_ops) },
+	{ USB_DEVICE(0x2001, 0x3c00) },
 	/* Gigabyte */
-	{ USB_DEVICE(0x1044, 0x8001), USB_DEVICE_DATA(&rt2500usb_ops) },
-	{ USB_DEVICE(0x1044, 0x8007), USB_DEVICE_DATA(&rt2500usb_ops) },
+	{ USB_DEVICE(0x1044, 0x8001) },
+	{ USB_DEVICE(0x1044, 0x8007) },
 	/* Hercules */
-	{ USB_DEVICE(0x06f8, 0xe000), USB_DEVICE_DATA(&rt2500usb_ops) },
+	{ USB_DEVICE(0x06f8, 0xe000) },
 	/* Melco */
-	{ USB_DEVICE(0x0411, 0x005e), USB_DEVICE_DATA(&rt2500usb_ops) },
-	{ USB_DEVICE(0x0411, 0x0066), USB_DEVICE_DATA(&rt2500usb_ops) },
-	{ USB_DEVICE(0x0411, 0x0067), USB_DEVICE_DATA(&rt2500usb_ops) },
-	{ USB_DEVICE(0x0411, 0x008b), USB_DEVICE_DATA(&rt2500usb_ops) },
-	{ USB_DEVICE(0x0411, 0x0097), USB_DEVICE_DATA(&rt2500usb_ops) },
+	{ USB_DEVICE(0x0411, 0x005e) },
+	{ USB_DEVICE(0x0411, 0x0066) },
+	{ USB_DEVICE(0x0411, 0x0067) },
+	{ USB_DEVICE(0x0411, 0x008b) },
+	{ USB_DEVICE(0x0411, 0x0097) },
 	/* MSI */
-	{ USB_DEVICE(0x0db0, 0x6861), USB_DEVICE_DATA(&rt2500usb_ops) },
-	{ USB_DEVICE(0x0db0, 0x6865), USB_DEVICE_DATA(&rt2500usb_ops) },
-	{ USB_DEVICE(0x0db0, 0x6869), USB_DEVICE_DATA(&rt2500usb_ops) },
+	{ USB_DEVICE(0x0db0, 0x6861) },
+	{ USB_DEVICE(0x0db0, 0x6865) },
+	{ USB_DEVICE(0x0db0, 0x6869) },
 	/* Ralink */
-	{ USB_DEVICE(0x148f, 0x1706), USB_DEVICE_DATA(&rt2500usb_ops) },
-	{ USB_DEVICE(0x148f, 0x2570), USB_DEVICE_DATA(&rt2500usb_ops) },
-	{ USB_DEVICE(0x148f, 0x9020), USB_DEVICE_DATA(&rt2500usb_ops) },
+	{ USB_DEVICE(0x148f, 0x1706) },
+	{ USB_DEVICE(0x148f, 0x2570) },
+	{ USB_DEVICE(0x148f, 0x9020) },
 	/* Sagem */
-	{ USB_DEVICE(0x079b, 0x004b), USB_DEVICE_DATA(&rt2500usb_ops) },
+	{ USB_DEVICE(0x079b, 0x004b) },
 	/* Siemens */
-	{ USB_DEVICE(0x0681, 0x3c06), USB_DEVICE_DATA(&rt2500usb_ops) },
+	{ USB_DEVICE(0x0681, 0x3c06) },
 	/* SMC */
-	{ USB_DEVICE(0x0707, 0xee13), USB_DEVICE_DATA(&rt2500usb_ops) },
+	{ USB_DEVICE(0x0707, 0xee13) },
 	/* Spairon */
-	{ USB_DEVICE(0x114b, 0x0110), USB_DEVICE_DATA(&rt2500usb_ops) },
+	{ USB_DEVICE(0x114b, 0x0110) },
 	/* SURECOM */
-	{ USB_DEVICE(0x0769, 0x11f3), USB_DEVICE_DATA(&rt2500usb_ops) },
+	{ USB_DEVICE(0x0769, 0x11f3) },
 	/* Trust */
-	{ USB_DEVICE(0x0eb0, 0x9020), USB_DEVICE_DATA(&rt2500usb_ops) },
+	{ USB_DEVICE(0x0eb0, 0x9020) },
 	/* VTech */
-	{ USB_DEVICE(0x0f88, 0x3012), USB_DEVICE_DATA(&rt2500usb_ops) },
+	{ USB_DEVICE(0x0f88, 0x3012) },
 	/* Zinwell */
-	{ USB_DEVICE(0x5a57, 0x0260), USB_DEVICE_DATA(&rt2500usb_ops) },
+	{ USB_DEVICE(0x5a57, 0x0260) },
 	{ 0, }
 };
 
@@ -1962,10 +1962,16 @@ MODULE_SUPPORTED_DEVICE("Ralink RT2570 USB chipset based cards");
 MODULE_DEVICE_TABLE(usb, rt2500usb_device_table);
 MODULE_LICENSE("GPL");
 
+static int rt2500usb_probe(struct usb_interface *usb_intf,
+			   const struct usb_device_id *id)
+{
+	return rt2x00usb_probe(usb_intf, &rt2500usb_ops);
+}
+
 static struct usb_driver rt2500usb_driver = {
 	.name		= KBUILD_MODNAME,
 	.id_table	= rt2500usb_device_table,
-	.probe		= rt2x00usb_probe,
+	.probe		= rt2500usb_probe,
 	.disconnect	= rt2x00usb_disconnect,
 	.suspend	= rt2x00usb_suspend,
 	.resume		= rt2x00usb_resume,
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 46c3e3c..6f91a9a 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -1117,36 +1117,36 @@ static const struct rt2x00_ops rt2800pci_ops = {
  */
 #ifdef CONFIG_PCI
 static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = {
-	{ PCI_DEVICE(0x1814, 0x0601), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1814, 0x0681), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1814, 0x0701), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1814, 0x0781), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1814, 0x3090), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1814, 0x3091), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1814, 0x3092), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1432, 0x7708), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1432, 0x7727), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1432, 0x7728), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1432, 0x7738), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1432, 0x7748), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1432, 0x7758), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1432, 0x7768), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1462, 0x891a), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1a3b, 0x1059), PCI_DEVICE_DATA(&rt2800pci_ops) },
+	{ PCI_DEVICE(0x1814, 0x0601) },
+	{ PCI_DEVICE(0x1814, 0x0681) },
+	{ PCI_DEVICE(0x1814, 0x0701) },
+	{ PCI_DEVICE(0x1814, 0x0781) },
+	{ PCI_DEVICE(0x1814, 0x3090) },
+	{ PCI_DEVICE(0x1814, 0x3091) },
+	{ PCI_DEVICE(0x1814, 0x3092) },
+	{ PCI_DEVICE(0x1432, 0x7708) },
+	{ PCI_DEVICE(0x1432, 0x7727) },
+	{ PCI_DEVICE(0x1432, 0x7728) },
+	{ PCI_DEVICE(0x1432, 0x7738) },
+	{ PCI_DEVICE(0x1432, 0x7748) },
+	{ PCI_DEVICE(0x1432, 0x7758) },
+	{ PCI_DEVICE(0x1432, 0x7768) },
+	{ PCI_DEVICE(0x1462, 0x891a) },
+	{ PCI_DEVICE(0x1a3b, 0x1059) },
 #ifdef CONFIG_RT2800PCI_RT33XX
-	{ PCI_DEVICE(0x1814, 0x3390), PCI_DEVICE_DATA(&rt2800pci_ops) },
+	{ PCI_DEVICE(0x1814, 0x3390) },
 #endif
 #ifdef CONFIG_RT2800PCI_RT35XX
-	{ PCI_DEVICE(0x1432, 0x7711), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1432, 0x7722), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1814, 0x3060), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1814, 0x3062), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1814, 0x3562), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1814, 0x3592), PCI_DEVICE_DATA(&rt2800pci_ops) },
-	{ PCI_DEVICE(0x1814, 0x3593), PCI_DEVICE_DATA(&rt2800pci_ops) },
+	{ PCI_DEVICE(0x1432, 0x7711) },
+	{ PCI_DEVICE(0x1432, 0x7722) },
+	{ PCI_DEVICE(0x1814, 0x3060) },
+	{ PCI_DEVICE(0x1814, 0x3062) },
+	{ PCI_DEVICE(0x1814, 0x3562) },
+	{ PCI_DEVICE(0x1814, 0x3592) },
+	{ PCI_DEVICE(0x1814, 0x3593) },
 #endif
 #ifdef CONFIG_RT2800PCI_RT53XX
-	{ PCI_DEVICE(0x1814, 0x5390), PCI_DEVICE_DATA(&rt2800pci_ops) },
+	{ PCI_DEVICE(0x1814, 0x5390) },
 #endif
 	{ 0, }
 };
@@ -1182,10 +1182,16 @@ static struct platform_driver rt2800soc_driver = {
 #endif /* CONFIG_RALINK_RT288X || CONFIG_RALINK_RT305X */
 
 #ifdef CONFIG_PCI
+static int rt2800pci_probe(struct pci_dev *pci_dev,
+			   const struct pci_device_id *id)
+{
+	return rt2x00pci_probe(pci_dev, &rt2800pci_ops);
+}
+
 static struct pci_driver rt2800pci_driver = {
 	.name		= KBUILD_MODNAME,
 	.id_table	= rt2800pci_device_table,
-	.probe		= rt2x00pci_probe,
+	.probe		= rt2800pci_probe,
 	.remove		= __devexit_p(rt2x00pci_remove),
 	.suspend	= rt2x00pci_suspend,
 	.resume		= rt2x00pci_resume,
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 1bb9a7d..6f7c161 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -768,230 +768,230 @@ static const struct rt2x00_ops rt2800usb_ops = {
  */
 static struct usb_device_id rt2800usb_device_table[] = {
 	/* Abocom */
-	{ USB_DEVICE(0x07b8, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x07b8, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x07b8, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x07b8, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x07b8, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1482, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x07b8, 0x2870) },
+	{ USB_DEVICE(0x07b8, 0x2770) },
+	{ USB_DEVICE(0x07b8, 0x3070) },
+	{ USB_DEVICE(0x07b8, 0x3071) },
+	{ USB_DEVICE(0x07b8, 0x3072) },
+	{ USB_DEVICE(0x1482, 0x3c09) },
 	/* AirTies */
-	{ USB_DEVICE(0x1eda, 0x2310), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1eda, 0x2310) },
 	/* Allwin */
-	{ USB_DEVICE(0x8516, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x8516, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x8516, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x8516, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x8516, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x8516, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x8516, 0x2070) },
+	{ USB_DEVICE(0x8516, 0x2770) },
+	{ USB_DEVICE(0x8516, 0x2870) },
+	{ USB_DEVICE(0x8516, 0x3070) },
+	{ USB_DEVICE(0x8516, 0x3071) },
+	{ USB_DEVICE(0x8516, 0x3072) },
 	/* Alpha Networks */
-	{ USB_DEVICE(0x14b2, 0x3c06), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x14b2, 0x3c07), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x14b2, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x14b2, 0x3c12), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x14b2, 0x3c23), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x14b2, 0x3c25), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x14b2, 0x3c27), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x14b2, 0x3c28), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x14b2, 0x3c2c), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x14b2, 0x3c06) },
+	{ USB_DEVICE(0x14b2, 0x3c07) },
+	{ USB_DEVICE(0x14b2, 0x3c09) },
+	{ USB_DEVICE(0x14b2, 0x3c12) },
+	{ USB_DEVICE(0x14b2, 0x3c23) },
+	{ USB_DEVICE(0x14b2, 0x3c25) },
+	{ USB_DEVICE(0x14b2, 0x3c27) },
+	{ USB_DEVICE(0x14b2, 0x3c28) },
+	{ USB_DEVICE(0x14b2, 0x3c2c) },
 	/* Amit */
-	{ USB_DEVICE(0x15c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x15c5, 0x0008) },
 	/* Askey */
-	{ USB_DEVICE(0x1690, 0x0740), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1690, 0x0740) },
 	/* ASUS */
-	{ USB_DEVICE(0x0b05, 0x1731), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0b05, 0x1732), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0b05, 0x1742), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0b05, 0x1784), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1761, 0x0b05), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0b05, 0x1731) },
+	{ USB_DEVICE(0x0b05, 0x1732) },
+	{ USB_DEVICE(0x0b05, 0x1742) },
+	{ USB_DEVICE(0x0b05, 0x1784) },
+	{ USB_DEVICE(0x1761, 0x0b05) },
 	/* AzureWave */
-	{ USB_DEVICE(0x13d3, 0x3247), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x13d3, 0x3273), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x13d3, 0x3305), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x13d3, 0x3307), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x13d3, 0x3321), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x13d3, 0x3247) },
+	{ USB_DEVICE(0x13d3, 0x3273) },
+	{ USB_DEVICE(0x13d3, 0x3305) },
+	{ USB_DEVICE(0x13d3, 0x3307) },
+	{ USB_DEVICE(0x13d3, 0x3321) },
 	/* Belkin */
-	{ USB_DEVICE(0x050d, 0x8053), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x050d, 0x805c), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x050d, 0x815c), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x050d, 0x825b), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x050d, 0x935a), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x050d, 0x935b), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x050d, 0x8053) },
+	{ USB_DEVICE(0x050d, 0x805c) },
+	{ USB_DEVICE(0x050d, 0x815c) },
+	{ USB_DEVICE(0x050d, 0x825b) },
+	{ USB_DEVICE(0x050d, 0x935a) },
+	{ USB_DEVICE(0x050d, 0x935b) },
 	/* Buffalo */
-	{ USB_DEVICE(0x0411, 0x00e8), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0411, 0x016f), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0411, 0x01a2), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0411, 0x00e8) },
+	{ USB_DEVICE(0x0411, 0x016f) },
+	{ USB_DEVICE(0x0411, 0x01a2) },
 	/* Corega */
-	{ USB_DEVICE(0x07aa, 0x002f), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x07aa, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x07aa, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x18c5, 0x0012), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x07aa, 0x002f) },
+	{ USB_DEVICE(0x07aa, 0x003c) },
+	{ USB_DEVICE(0x07aa, 0x003f) },
+	{ USB_DEVICE(0x18c5, 0x0012) },
 	/* D-Link */
-	{ USB_DEVICE(0x07d1, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x07d1, 0x3c0a), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x07d1, 0x3c0d), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x07d1, 0x3c0e), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x07d1, 0x3c0f), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x07d1, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x07d1, 0x3c16), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x07d1, 0x3c09) },
+	{ USB_DEVICE(0x07d1, 0x3c0a) },
+	{ USB_DEVICE(0x07d1, 0x3c0d) },
+	{ USB_DEVICE(0x07d1, 0x3c0e) },
+	{ USB_DEVICE(0x07d1, 0x3c0f) },
+	{ USB_DEVICE(0x07d1, 0x3c11) },
+	{ USB_DEVICE(0x07d1, 0x3c16) },
 	/* Draytek */
-	{ USB_DEVICE(0x07fa, 0x7712), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x07fa, 0x7712) },
 	/* Edimax */
-	{ USB_DEVICE(0x7392, 0x7711), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x7392, 0x7717), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x7392, 0x7718), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x7392, 0x7711) },
+	{ USB_DEVICE(0x7392, 0x7717) },
+	{ USB_DEVICE(0x7392, 0x7718) },
 	/* Encore */
-	{ USB_DEVICE(0x203d, 0x1480), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x203d, 0x14a9), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x203d, 0x1480) },
+	{ USB_DEVICE(0x203d, 0x14a9) },
 	/* EnGenius */
-	{ USB_DEVICE(0x1740, 0x9701), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1740, 0x9702), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1740, 0x9703), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1740, 0x9705), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1740, 0x9706), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1740, 0x9707), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1740, 0x9708), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1740, 0x9709), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1740, 0x9701) },
+	{ USB_DEVICE(0x1740, 0x9702) },
+	{ USB_DEVICE(0x1740, 0x9703) },
+	{ USB_DEVICE(0x1740, 0x9705) },
+	{ USB_DEVICE(0x1740, 0x9706) },
+	{ USB_DEVICE(0x1740, 0x9707) },
+	{ USB_DEVICE(0x1740, 0x9708) },
+	{ USB_DEVICE(0x1740, 0x9709) },
 	/* Gemtek */
-	{ USB_DEVICE(0x15a9, 0x0012), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x15a9, 0x0012) },
 	/* Gigabyte */
-	{ USB_DEVICE(0x1044, 0x800b), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1044, 0x800d), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1044, 0x800b) },
+	{ USB_DEVICE(0x1044, 0x800d) },
 	/* Hawking */
-	{ USB_DEVICE(0x0e66, 0x0001), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0e66, 0x0003), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0e66, 0x0009), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0e66, 0x000b), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0e66, 0x0013), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0e66, 0x0017), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0e66, 0x0018), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0e66, 0x0001) },
+	{ USB_DEVICE(0x0e66, 0x0003) },
+	{ USB_DEVICE(0x0e66, 0x0009) },
+	{ USB_DEVICE(0x0e66, 0x000b) },
+	{ USB_DEVICE(0x0e66, 0x0013) },
+	{ USB_DEVICE(0x0e66, 0x0017) },
+	{ USB_DEVICE(0x0e66, 0x0018) },
 	/* I-O DATA */
-	{ USB_DEVICE(0x04bb, 0x0945), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x04bb, 0x0947), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x04bb, 0x0948), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x04bb, 0x0945) },
+	{ USB_DEVICE(0x04bb, 0x0947) },
+	{ USB_DEVICE(0x04bb, 0x0948) },
 	/* Linksys */
-	{ USB_DEVICE(0x13b1, 0x0031), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1737, 0x0070), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1737, 0x0071), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x13b1, 0x0031) },
+	{ USB_DEVICE(0x1737, 0x0070) },
+	{ USB_DEVICE(0x1737, 0x0071) },
 	/* Logitec */
-	{ USB_DEVICE(0x0789, 0x0162), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0789, 0x0163), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0789, 0x0164), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0789, 0x0166), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0789, 0x0162) },
+	{ USB_DEVICE(0x0789, 0x0163) },
+	{ USB_DEVICE(0x0789, 0x0164) },
+	{ USB_DEVICE(0x0789, 0x0166) },
 	/* Motorola */
-	{ USB_DEVICE(0x100d, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x100d, 0x9031) },
 	/* MSI */
-	{ USB_DEVICE(0x0db0, 0x3820), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0db0, 0x3821), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0db0, 0x3822), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0db0, 0x3870), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0db0, 0x3871), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0db0, 0x6899), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0db0, 0x821a), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0db0, 0x822a), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0db0, 0x822b), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0db0, 0x822c), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0db0, 0x870a), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0db0, 0x871a), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0db0, 0x871b), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0db0, 0x871c), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0db0, 0x899a), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0db0, 0x3820) },
+	{ USB_DEVICE(0x0db0, 0x3821) },
+	{ USB_DEVICE(0x0db0, 0x3822) },
+	{ USB_DEVICE(0x0db0, 0x3870) },
+	{ USB_DEVICE(0x0db0, 0x3871) },
+	{ USB_DEVICE(0x0db0, 0x6899) },
+	{ USB_DEVICE(0x0db0, 0x821a) },
+	{ USB_DEVICE(0x0db0, 0x822a) },
+	{ USB_DEVICE(0x0db0, 0x822b) },
+	{ USB_DEVICE(0x0db0, 0x822c) },
+	{ USB_DEVICE(0x0db0, 0x870a) },
+	{ USB_DEVICE(0x0db0, 0x871a) },
+	{ USB_DEVICE(0x0db0, 0x871b) },
+	{ USB_DEVICE(0x0db0, 0x871c) },
+	{ USB_DEVICE(0x0db0, 0x899a) },
 	/* Para */
-	{ USB_DEVICE(0x20b8, 0x8888), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x20b8, 0x8888) },
 	/* Pegatron */
-	{ USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1d4d, 0x000e), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1d4d, 0x0011), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1d4d, 0x000c) },
+	{ USB_DEVICE(0x1d4d, 0x000e) },
+	{ USB_DEVICE(0x1d4d, 0x0011) },
 	/* Philips */
-	{ USB_DEVICE(0x0471, 0x200f), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0471, 0x200f) },
 	/* Planex */
-	{ USB_DEVICE(0x2019, 0xab25), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x2019, 0xed06), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x2019, 0xab25) },
+	{ USB_DEVICE(0x2019, 0xed06) },
 	/* Quanta */
-	{ USB_DEVICE(0x1a32, 0x0304), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1a32, 0x0304) },
 	/* Ralink */
-	{ USB_DEVICE(0x148f, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x148f, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x148f, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x148f, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x148f, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x148f, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x148f, 0x2070) },
+	{ USB_DEVICE(0x148f, 0x2770) },
+	{ USB_DEVICE(0x148f, 0x2870) },
+	{ USB_DEVICE(0x148f, 0x3070) },
+	{ USB_DEVICE(0x148f, 0x3071) },
+	{ USB_DEVICE(0x148f, 0x3072) },
 	/* Samsung */
-	{ USB_DEVICE(0x04e8, 0x2018), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x04e8, 0x2018) },
 	/* Siemens */
-	{ USB_DEVICE(0x129b, 0x1828), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x129b, 0x1828) },
 	/* Sitecom */
-	{ USB_DEVICE(0x0df6, 0x0017), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0df6, 0x002b), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0df6, 0x002c), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0df6, 0x002d), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0df6, 0x0039), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0df6, 0x003b), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0df6, 0x003d), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0df6, 0x003e), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0df6, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0df6, 0x0040), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0df6, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0df6, 0x0047), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0df6, 0x0048), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0df6, 0x0017) },
+	{ USB_DEVICE(0x0df6, 0x002b) },
+	{ USB_DEVICE(0x0df6, 0x002c) },
+	{ USB_DEVICE(0x0df6, 0x002d) },
+	{ USB_DEVICE(0x0df6, 0x0039) },
+	{ USB_DEVICE(0x0df6, 0x003b) },
+	{ USB_DEVICE(0x0df6, 0x003d) },
+	{ USB_DEVICE(0x0df6, 0x003e) },
+	{ USB_DEVICE(0x0df6, 0x003f) },
+	{ USB_DEVICE(0x0df6, 0x0040) },
+	{ USB_DEVICE(0x0df6, 0x0042) },
+	{ USB_DEVICE(0x0df6, 0x0047) },
+	{ USB_DEVICE(0x0df6, 0x0048) },
 	/* SMC */
-	{ USB_DEVICE(0x083a, 0x6618), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x083a, 0x7511), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x083a, 0x7512), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x083a, 0x7522), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x083a, 0x8522), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x083a, 0xa618), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x083a, 0xa701), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x083a, 0xa702), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x083a, 0xa703), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x083a, 0xb522), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x083a, 0x6618) },
+	{ USB_DEVICE(0x083a, 0x7511) },
+	{ USB_DEVICE(0x083a, 0x7512) },
+	{ USB_DEVICE(0x083a, 0x7522) },
+	{ USB_DEVICE(0x083a, 0x8522) },
+	{ USB_DEVICE(0x083a, 0xa618) },
+	{ USB_DEVICE(0x083a, 0xa701) },
+	{ USB_DEVICE(0x083a, 0xa702) },
+	{ USB_DEVICE(0x083a, 0xa703) },
+	{ USB_DEVICE(0x083a, 0xb522) },
 	/* Sparklan */
-	{ USB_DEVICE(0x15a9, 0x0006), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x15a9, 0x0006) },
 	/* Sweex */
-	{ USB_DEVICE(0x177f, 0x0302), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x177f, 0x0302) },
 	/* U-Media */
-	{ USB_DEVICE(0x157e, 0x300e), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x157e, 0x3013), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x157e, 0x300e) },
+	{ USB_DEVICE(0x157e, 0x3013) },
 	/* ZCOM */
-	{ USB_DEVICE(0x0cde, 0x0022), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0cde, 0x0025), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0cde, 0x0022) },
+	{ USB_DEVICE(0x0cde, 0x0025) },
 	/* Zinwell */
-	{ USB_DEVICE(0x5a57, 0x0280), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x5a57, 0x0282), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x5a57, 0x0283), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x5a57, 0x0280) },
+	{ USB_DEVICE(0x5a57, 0x0282) },
+	{ USB_DEVICE(0x5a57, 0x0283) },
+	{ USB_DEVICE(0x5a57, 0x5257) },
 	/* Zyxel */
-	{ USB_DEVICE(0x0586, 0x3416), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0586, 0x3418), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0586, 0x341e), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0586, 0x3416) },
+	{ USB_DEVICE(0x0586, 0x3418) },
+	{ USB_DEVICE(0x0586, 0x341e) },
 #ifdef CONFIG_RT2800USB_RT33XX
 	/* Ralink */
-	{ USB_DEVICE(0x148f, 0x3370), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x148f, 0x8070), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x148f, 0x3370) },
+	{ USB_DEVICE(0x148f, 0x8070) },
 	/* Sitecom */
-	{ USB_DEVICE(0x0df6, 0x0050), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0df6, 0x0050) },
 #endif
 #ifdef CONFIG_RT2800USB_RT35XX
 	/* Allwin */
-	{ USB_DEVICE(0x8516, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x8516, 0x3572) },
 	/* Askey */
-	{ USB_DEVICE(0x1690, 0x0744), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1690, 0x0744) },
 	/* Cisco */
-	{ USB_DEVICE(0x167b, 0x4001), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x167b, 0x4001) },
 	/* EnGenius */
-	{ USB_DEVICE(0x1740, 0x9801), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1740, 0x9801) },
 	/* I-O DATA */
-	{ USB_DEVICE(0x04bb, 0x0944), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x04bb, 0x0944) },
 	/* Linksys */
-	{ USB_DEVICE(0x13b1, 0x002f), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1737, 0x0079), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x13b1, 0x002f) },
+	{ USB_DEVICE(0x1737, 0x0079) },
 	/* Ralink */
-	{ USB_DEVICE(0x148f, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x148f, 0x3572) },
 	/* Sitecom */
-	{ USB_DEVICE(0x0df6, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0df6, 0x0041) },
 	/* Toshiba */
-	{ USB_DEVICE(0x0930, 0x0a07), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0930, 0x0a07) },
 	/* Zinwell */
-	{ USB_DEVICE(0x5a57, 0x0284), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x5a57, 0x0284) },
 #endif
 #ifdef CONFIG_RT2800USB_UNKNOWN
 	/*
@@ -999,73 +999,73 @@ static struct usb_device_id rt2800usb_device_table[] = {
 	 * vendor linux driver).
 	 */
 	/* Alpha Networks */
-	{ USB_DEVICE(0x14b2, 0x3c08), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x14b2, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x14b2, 0x3c08) },
+	{ USB_DEVICE(0x14b2, 0x3c11) },
 	/* Amigo */
-	{ USB_DEVICE(0x0e0b, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0e0b, 0x9041), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0e0b, 0x9031) },
+	{ USB_DEVICE(0x0e0b, 0x9041) },
 	/* ASUS */
-	{ USB_DEVICE(0x0b05, 0x1760), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0b05, 0x1761), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0b05, 0x1790), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0b05, 0x1760) },
+	{ USB_DEVICE(0x0b05, 0x1761) },
+	{ USB_DEVICE(0x0b05, 0x1790) },
 	/* AzureWave */
-	{ USB_DEVICE(0x13d3, 0x3262), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x13d3, 0x3284), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x13d3, 0x3322), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x13d3, 0x3262) },
+	{ USB_DEVICE(0x13d3, 0x3284) },
+	{ USB_DEVICE(0x13d3, 0x3322) },
 	/* Belkin */
-	{ USB_DEVICE(0x050d, 0x825a), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x050d, 0x825a) },
 	/* Buffalo */
-	{ USB_DEVICE(0x0411, 0x012e), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0411, 0x0148), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0411, 0x0150), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x0411, 0x015d), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0411, 0x012e) },
+	{ USB_DEVICE(0x0411, 0x0148) },
+	{ USB_DEVICE(0x0411, 0x0150) },
+	{ USB_DEVICE(0x0411, 0x015d) },
 	/* Corega */
-	{ USB_DEVICE(0x07aa, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x07aa, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x18c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x07aa, 0x0041) },
+	{ USB_DEVICE(0x07aa, 0x0042) },
+	{ USB_DEVICE(0x18c5, 0x0008) },
 	/* D-Link */
-	{ USB_DEVICE(0x07d1, 0x3c0b), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x07d1, 0x3c13), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x07d1, 0x3c15), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x07d1, 0x3c17), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x07d1, 0x3c0b) },
+	{ USB_DEVICE(0x07d1, 0x3c13) },
+	{ USB_DEVICE(0x07d1, 0x3c15) },
+	{ USB_DEVICE(0x07d1, 0x3c17) },
 	/* Edimax */
-	{ USB_DEVICE(0x7392, 0x4085), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x7392, 0x4085) },
 	/* Encore */
-	{ USB_DEVICE(0x203d, 0x14a1), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x203d, 0x14a1) },
 	/* Gemtek */
-	{ USB_DEVICE(0x15a9, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x15a9, 0x0010) },
 	/* Gigabyte */
-	{ USB_DEVICE(0x1044, 0x800c), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1044, 0x800c) },
 	/* LevelOne */
-	{ USB_DEVICE(0x1740, 0x0605), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1740, 0x0615), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1740, 0x0605) },
+	{ USB_DEVICE(0x1740, 0x0615) },
 	/* Linksys */
-	{ USB_DEVICE(0x1737, 0x0077), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1737, 0x0078), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1737, 0x0077) },
+	{ USB_DEVICE(0x1737, 0x0078) },
 	/* Motorola */
-	{ USB_DEVICE(0x100d, 0x9032), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x100d, 0x9032) },
 	/* Ovislink */
-	{ USB_DEVICE(0x1b75, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1b75, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1b75, 0x3071) },
+	{ USB_DEVICE(0x1b75, 0x3072) },
 	/* Pegatron */
-	{ USB_DEVICE(0x05a6, 0x0101), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1d4d, 0x0002), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1d4d, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x05a6, 0x0101) },
+	{ USB_DEVICE(0x1d4d, 0x0002) },
+	{ USB_DEVICE(0x1d4d, 0x0010) },
 	/* Planex */
-	{ USB_DEVICE(0x2019, 0x5201), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x2019, 0xab24), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x2019, 0x5201) },
+	{ USB_DEVICE(0x2019, 0xab24) },
 	/* Qcom */
-	{ USB_DEVICE(0x18e8, 0x6259), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x18e8, 0x6259) },
 	/* SMC */
-	{ USB_DEVICE(0x083a, 0xa512), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x083a, 0xc522), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x083a, 0xd522), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x083a, 0xf511), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x083a, 0xa512) },
+	{ USB_DEVICE(0x083a, 0xc522) },
+	{ USB_DEVICE(0x083a, 0xd522) },
+	{ USB_DEVICE(0x083a, 0xf511) },
 	/* Sweex */
-	{ USB_DEVICE(0x177f, 0x0153), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x177f, 0x0313), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x177f, 0x0153) },
+	{ USB_DEVICE(0x177f, 0x0313) },
 	/* Zyxel */
-	{ USB_DEVICE(0x0586, 0x341a), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0586, 0x341a) },
 #endif
 	{ 0, }
 };
@@ -1078,10 +1078,16 @@ MODULE_DEVICE_TABLE(usb, rt2800usb_device_table);
 MODULE_FIRMWARE(FIRMWARE_RT2870);
 MODULE_LICENSE("GPL");
 
+static int rt2800usb_probe(struct usb_interface *usb_intf,
+			   const struct usb_device_id *id)
+{
+	return rt2x00usb_probe(usb_intf, &rt2800usb_ops);
+}
+
 static struct usb_driver rt2800usb_driver = {
 	.name		= KBUILD_MODNAME,
 	.id_table	= rt2800usb_device_table,
-	.probe		= rt2x00usb_probe,
+	.probe		= rt2800usb_probe,
 	.disconnect	= rt2x00usb_disconnect,
 	.suspend	= rt2x00usb_suspend,
 	.resume		= rt2x00usb_resume,
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
index 695aecf..17148bb 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
@@ -251,9 +251,8 @@ exit:
 	return -ENOMEM;
 }
 
-int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
+int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops)
 {
-	struct rt2x00_ops *ops = (struct rt2x00_ops *)id->driver_data;
 	struct ieee80211_hw *hw;
 	struct rt2x00_dev *rt2x00dev;
 	int retval;
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h
index 5d58874..e2c99f2 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.h
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.h
@@ -126,7 +126,7 @@ void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev);
 /*
  * PCI driver handlers.
  */
-int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id);
+int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops);
 void rt2x00pci_remove(struct pci_dev *pci_dev);
 #ifdef CONFIG_PM
 int rt2x00pci_suspend(struct pci_dev *pci_dev, pm_message_t state);
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 9957579..570184e 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -791,10 +791,9 @@ exit:
 }
 
 int rt2x00usb_probe(struct usb_interface *usb_intf,
-		    const struct usb_device_id *id)
+		    const struct rt2x00_ops *ops)
 {
 	struct usb_device *usb_dev = interface_to_usbdev(usb_intf);
-	struct rt2x00_ops *ops = (struct rt2x00_ops *)id->driver_info;
 	struct ieee80211_hw *hw;
 	struct rt2x00_dev *rt2x00dev;
 	int retval;
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h
index 6aeba71..52b09d2 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.h
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.h
@@ -35,12 +35,6 @@
 })
 
 /*
- * This variable should be used with the
- * usb_driver structure initialization.
- */
-#define USB_DEVICE_DATA(__ops)	.driver_info = (kernel_ulong_t)(__ops)
-
-/*
  * For USB vendor requests we need to pass a timeout
  * time in ms, for this we use the REGISTER_TIMEOUT,
  * however when loading firmware a higher value is
@@ -433,7 +427,7 @@ void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev);
  * USB driver handlers.
  */
 int rt2x00usb_probe(struct usb_interface *usb_intf,
-		    const struct usb_device_id *id);
+		    const struct rt2x00_ops *ops);
 void rt2x00usb_disconnect(struct usb_interface *usb_intf);
 #ifdef CONFIG_PM
 int rt2x00usb_suspend(struct usb_interface *usb_intf, pm_message_t state);
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 264508f..c5dccdb 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -3061,11 +3061,11 @@ static const struct rt2x00_ops rt61pci_ops = {
  */
 static DEFINE_PCI_DEVICE_TABLE(rt61pci_device_table) = {
 	/* RT2561s */
-	{ PCI_DEVICE(0x1814, 0x0301), PCI_DEVICE_DATA(&rt61pci_ops) },
+	{ PCI_DEVICE(0x1814, 0x0301) },
 	/* RT2561 v2 */
-	{ PCI_DEVICE(0x1814, 0x0302), PCI_DEVICE_DATA(&rt61pci_ops) },
+	{ PCI_DEVICE(0x1814, 0x0302) },
 	/* RT2661 */
-	{ PCI_DEVICE(0x1814, 0x0401), PCI_DEVICE_DATA(&rt61pci_ops) },
+	{ PCI_DEVICE(0x1814, 0x0401) },
 	{ 0, }
 };
 
@@ -3080,10 +3080,16 @@ MODULE_FIRMWARE(FIRMWARE_RT2561s);
 MODULE_FIRMWARE(FIRMWARE_RT2661);
 MODULE_LICENSE("GPL");
 
+static int rt61pci_probe(struct pci_dev *pci_dev,
+			 const struct pci_device_id *id)
+{
+	return rt2x00pci_probe(pci_dev, &rt61pci_ops);
+}
+
 static struct pci_driver rt61pci_driver = {
 	.name		= KBUILD_MODNAME,
 	.id_table	= rt61pci_device_table,
-	.probe		= rt2x00pci_probe,
+	.probe		= rt61pci_probe,
 	.remove		= __devexit_p(rt2x00pci_remove),
 	.suspend	= rt2x00pci_suspend,
 	.resume		= rt2x00pci_resume,
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index cdb026d..be3eb5e 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -2388,113 +2388,113 @@ static const struct rt2x00_ops rt73usb_ops = {
  */
 static struct usb_device_id rt73usb_device_table[] = {
 	/* AboCom */
-	{ USB_DEVICE(0x07b8, 0xb21b), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x07b8, 0xb21c), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x07b8, 0xb21d), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x07b8, 0xb21e), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x07b8, 0xb21f), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x07b8, 0xb21b) },
+	{ USB_DEVICE(0x07b8, 0xb21c) },
+	{ USB_DEVICE(0x07b8, 0xb21d) },
+	{ USB_DEVICE(0x07b8, 0xb21e) },
+	{ USB_DEVICE(0x07b8, 0xb21f) },
 	/* AL */
-	{ USB_DEVICE(0x14b2, 0x3c10), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x14b2, 0x3c10) },
 	/* Amigo */
-	{ USB_DEVICE(0x148f, 0x9021), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x0eb0, 0x9021), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x148f, 0x9021) },
+	{ USB_DEVICE(0x0eb0, 0x9021) },
 	/* AMIT  */
-	{ USB_DEVICE(0x18c5, 0x0002), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x18c5, 0x0002) },
 	/* Askey */
-	{ USB_DEVICE(0x1690, 0x0722), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x1690, 0x0722) },
 	/* ASUS */
-	{ USB_DEVICE(0x0b05, 0x1723), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x0b05, 0x1724), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x0b05, 0x1723) },
+	{ USB_DEVICE(0x0b05, 0x1724) },
 	/* Belkin */
-	{ USB_DEVICE(0x050d, 0x705a), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x050d, 0x905b), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x050d, 0x905c), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x050d, 0x705a) },
+	{ USB_DEVICE(0x050d, 0x905b) },
+	{ USB_DEVICE(0x050d, 0x905c) },
 	/* Billionton */
-	{ USB_DEVICE(0x1631, 0xc019), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x08dd, 0x0120), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x1631, 0xc019) },
+	{ USB_DEVICE(0x08dd, 0x0120) },
 	/* Buffalo */
-	{ USB_DEVICE(0x0411, 0x00d8), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x0411, 0x00d9), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x0411, 0x00f4), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x0411, 0x0116), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x0411, 0x0119), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x0411, 0x0137), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x0411, 0x00d8) },
+	{ USB_DEVICE(0x0411, 0x00d9) },
+	{ USB_DEVICE(0x0411, 0x00f4) },
+	{ USB_DEVICE(0x0411, 0x0116) },
+	{ USB_DEVICE(0x0411, 0x0119) },
+	{ USB_DEVICE(0x0411, 0x0137) },
 	/* CEIVA */
-	{ USB_DEVICE(0x178d, 0x02be), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x178d, 0x02be) },
 	/* CNet */
-	{ USB_DEVICE(0x1371, 0x9022), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x1371, 0x9032), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x1371, 0x9022) },
+	{ USB_DEVICE(0x1371, 0x9032) },
 	/* Conceptronic */
-	{ USB_DEVICE(0x14b2, 0x3c22), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x14b2, 0x3c22) },
 	/* Corega */
-	{ USB_DEVICE(0x07aa, 0x002e), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x07aa, 0x002e) },
 	/* D-Link */
-	{ USB_DEVICE(0x07d1, 0x3c03), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x07d1, 0x3c04), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x07d1, 0x3c06), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x07d1, 0x3c07), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x07d1, 0x3c03) },
+	{ USB_DEVICE(0x07d1, 0x3c04) },
+	{ USB_DEVICE(0x07d1, 0x3c06) },
+	{ USB_DEVICE(0x07d1, 0x3c07) },
 	/* Edimax */
-	{ USB_DEVICE(0x7392, 0x7318), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x7392, 0x7618), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x7392, 0x7318) },
+	{ USB_DEVICE(0x7392, 0x7618) },
 	/* EnGenius */
-	{ USB_DEVICE(0x1740, 0x3701), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x1740, 0x3701) },
 	/* Gemtek */
-	{ USB_DEVICE(0x15a9, 0x0004), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x15a9, 0x0004) },
 	/* Gigabyte */
-	{ USB_DEVICE(0x1044, 0x8008), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x1044, 0x800a), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x1044, 0x8008) },
+	{ USB_DEVICE(0x1044, 0x800a) },
 	/* Huawei-3Com */
-	{ USB_DEVICE(0x1472, 0x0009), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x1472, 0x0009) },
 	/* Hercules */
-	{ USB_DEVICE(0x06f8, 0xe002), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x06f8, 0xe010), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x06f8, 0xe020), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x06f8, 0xe002) },
+	{ USB_DEVICE(0x06f8, 0xe010) },
+	{ USB_DEVICE(0x06f8, 0xe020) },
 	/* Linksys */
-	{ USB_DEVICE(0x13b1, 0x0020), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x13b1, 0x0023), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x13b1, 0x0028), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x13b1, 0x0020) },
+	{ USB_DEVICE(0x13b1, 0x0023) },
+	{ USB_DEVICE(0x13b1, 0x0028) },
 	/* MSI */
-	{ USB_DEVICE(0x0db0, 0x4600), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x0db0, 0x6877), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x0db0, 0x6874), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x0db0, 0xa861), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x0db0, 0xa874), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x0db0, 0x4600) },
+	{ USB_DEVICE(0x0db0, 0x6877) },
+	{ USB_DEVICE(0x0db0, 0x6874) },
+	{ USB_DEVICE(0x0db0, 0xa861) },
+	{ USB_DEVICE(0x0db0, 0xa874) },
 	/* Ovislink */
-	{ USB_DEVICE(0x1b75, 0x7318), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x1b75, 0x7318) },
 	/* Ralink */
-	{ USB_DEVICE(0x04bb, 0x093d), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x148f, 0x2573), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x148f, 0x2671), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x0812, 0x3101), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x04bb, 0x093d) },
+	{ USB_DEVICE(0x148f, 0x2573) },
+	{ USB_DEVICE(0x148f, 0x2671) },
+	{ USB_DEVICE(0x0812, 0x3101) },
 	/* Qcom */
-	{ USB_DEVICE(0x18e8, 0x6196), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x18e8, 0x6229), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x18e8, 0x6238), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x18e8, 0x6196) },
+	{ USB_DEVICE(0x18e8, 0x6229) },
+	{ USB_DEVICE(0x18e8, 0x6238) },
 	/* Samsung */
-	{ USB_DEVICE(0x04e8, 0x4471), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x04e8, 0x4471) },
 	/* Senao */
-	{ USB_DEVICE(0x1740, 0x7100), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x1740, 0x7100) },
 	/* Sitecom */
-	{ USB_DEVICE(0x0df6, 0x0024), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x0df6, 0x0027), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x0df6, 0x002f), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x0df6, 0x90ac), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x0df6, 0x9712), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x0df6, 0x0024) },
+	{ USB_DEVICE(0x0df6, 0x0027) },
+	{ USB_DEVICE(0x0df6, 0x002f) },
+	{ USB_DEVICE(0x0df6, 0x90ac) },
+	{ USB_DEVICE(0x0df6, 0x9712) },
 	/* Surecom */
-	{ USB_DEVICE(0x0769, 0x31f3), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x0769, 0x31f3) },
 	/* Tilgin */
-	{ USB_DEVICE(0x6933, 0x5001), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x6933, 0x5001) },
 	/* Philips */
-	{ USB_DEVICE(0x0471, 0x200a), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x0471, 0x200a) },
 	/* Planex */
-	{ USB_DEVICE(0x2019, 0xab01), USB_DEVICE_DATA(&rt73usb_ops) },
-	{ USB_DEVICE(0x2019, 0xab50), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x2019, 0xab01) },
+	{ USB_DEVICE(0x2019, 0xab50) },
 	/* WideTell */
-	{ USB_DEVICE(0x7167, 0x3840), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x7167, 0x3840) },
 	/* Zcom */
-	{ USB_DEVICE(0x0cde, 0x001c), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x0cde, 0x001c) },
 	/* ZyXEL */
-	{ USB_DEVICE(0x0586, 0x3415), USB_DEVICE_DATA(&rt73usb_ops) },
+	{ USB_DEVICE(0x0586, 0x3415) },
 	{ 0, }
 };
 
@@ -2506,10 +2506,16 @@ MODULE_DEVICE_TABLE(usb, rt73usb_device_table);
 MODULE_FIRMWARE(FIRMWARE_RT2571);
 MODULE_LICENSE("GPL");
 
+static int rt73usb_probe(struct usb_interface *usb_intf,
+			 const struct usb_device_id *id)
+{
+	return rt2x00usb_probe(usb_intf, &rt73usb_ops);
+}
+
 static struct usb_driver rt73usb_driver = {
 	.name		= KBUILD_MODNAME,
 	.id_table	= rt73usb_device_table,
-	.probe		= rt2x00usb_probe,
+	.probe		= rt73usb_probe,
 	.disconnect	= rt2x00usb_disconnect,
 	.suspend	= rt2x00usb_suspend,
 	.resume		= rt2x00usb_resume,
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 16/23] rt2x00: Add USB IDs.
  2011-04-18 13:32                           ` [PATCH 15/23] rt2x00: Allow dynamic addition of PCI/USB IDs Ivo van Doorn
@ 2011-04-18 13:32                             ` Ivo van Doorn
  2011-04-18 13:33                               ` [PATCH 17/23] rt2x00: RT33xx device support is no longer experimental Ivo van Doorn
  0 siblings, 1 reply; 37+ messages in thread
From: Ivo van Doorn @ 2011-04-18 13:32 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users

From: Gertjan van Wingerde <gwingerde@gmail.com>

Add USB IDs that are listed in the latest Ralink Windows and/or Linux drivers.

Signed-off-by: Gertjan van Wingerde <gwingerde@gmail.com>
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2800usb.c |   28 ++++++++++++++++++++++++++++
 1 files changed, 28 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 6f7c161..fd8aa99 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -775,6 +775,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
 	{ USB_DEVICE(0x07b8, 0x3072) },
 	{ USB_DEVICE(0x1482, 0x3c09) },
 	/* AirTies */
+	{ USB_DEVICE(0x1eda, 0x2012) },
 	{ USB_DEVICE(0x1eda, 0x2310) },
 	/* Allwin */
 	{ USB_DEVICE(0x8516, 0x2070) },
@@ -933,6 +934,8 @@ static struct usb_device_id rt2800usb_device_table[] = {
 	{ USB_DEVICE(0x0df6, 0x0042) },
 	{ USB_DEVICE(0x0df6, 0x0047) },
 	{ USB_DEVICE(0x0df6, 0x0048) },
+	{ USB_DEVICE(0x0df6, 0x0051) },
+	{ USB_DEVICE(0x0df6, 0x005f) },
 	/* SMC */
 	{ USB_DEVICE(0x083a, 0x6618) },
 	{ USB_DEVICE(0x083a, 0x7511) },
@@ -963,6 +966,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
 	{ USB_DEVICE(0x0586, 0x3416) },
 	{ USB_DEVICE(0x0586, 0x3418) },
 	{ USB_DEVICE(0x0586, 0x341e) },
+	{ USB_DEVICE(0x0586, 0x343e) },
 #ifdef CONFIG_RT2800USB_RT33XX
 	/* Ralink */
 	{ USB_DEVICE(0x148f, 0x3370) },
@@ -998,6 +1002,9 @@ static struct usb_device_id rt2800usb_device_table[] = {
 	 * Unclear what kind of devices these are (they aren't supported by the
 	 * vendor linux driver).
 	 */
+	/* Abocom */
+	{ USB_DEVICE(0x07b8, 0x3073) },
+	{ USB_DEVICE(0x07b8, 0x3074) },
 	/* Alpha Networks */
 	{ USB_DEVICE(0x14b2, 0x3c08) },
 	{ USB_DEVICE(0x14b2, 0x3c11) },
@@ -1005,14 +1012,17 @@ static struct usb_device_id rt2800usb_device_table[] = {
 	{ USB_DEVICE(0x0e0b, 0x9031) },
 	{ USB_DEVICE(0x0e0b, 0x9041) },
 	/* ASUS */
+	{ USB_DEVICE(0x0b05, 0x166a) },
 	{ USB_DEVICE(0x0b05, 0x1760) },
 	{ USB_DEVICE(0x0b05, 0x1761) },
 	{ USB_DEVICE(0x0b05, 0x1790) },
+	{ USB_DEVICE(0x0b05, 0x179d) },
 	/* AzureWave */
 	{ USB_DEVICE(0x13d3, 0x3262) },
 	{ USB_DEVICE(0x13d3, 0x3284) },
 	{ USB_DEVICE(0x13d3, 0x3322) },
 	/* Belkin */
+	{ USB_DEVICE(0x050d, 0x1003) },
 	{ USB_DEVICE(0x050d, 0x825a) },
 	/* Buffalo */
 	{ USB_DEVICE(0x0411, 0x012e) },
@@ -1028,20 +1038,29 @@ static struct usb_device_id rt2800usb_device_table[] = {
 	{ USB_DEVICE(0x07d1, 0x3c13) },
 	{ USB_DEVICE(0x07d1, 0x3c15) },
 	{ USB_DEVICE(0x07d1, 0x3c17) },
+	{ USB_DEVICE(0x2001, 0x3c17) },
 	/* Edimax */
 	{ USB_DEVICE(0x7392, 0x4085) },
+	{ USB_DEVICE(0x7392, 0x7722) },
 	/* Encore */
 	{ USB_DEVICE(0x203d, 0x14a1) },
 	/* Gemtek */
 	{ USB_DEVICE(0x15a9, 0x0010) },
 	/* Gigabyte */
 	{ USB_DEVICE(0x1044, 0x800c) },
+	/* Huawei */
+	{ USB_DEVICE(0x148f, 0xf101) },
+	/* I-O DATA */
+	{ USB_DEVICE(0x04bb, 0x094b) },
 	/* LevelOne */
 	{ USB_DEVICE(0x1740, 0x0605) },
 	{ USB_DEVICE(0x1740, 0x0615) },
 	/* Linksys */
 	{ USB_DEVICE(0x1737, 0x0077) },
 	{ USB_DEVICE(0x1737, 0x0078) },
+	/* Logitec */
+	{ USB_DEVICE(0x0789, 0x0168) },
+	{ USB_DEVICE(0x0789, 0x0169) },
 	/* Motorola */
 	{ USB_DEVICE(0x100d, 0x9032) },
 	/* Ovislink */
@@ -1056,6 +1075,15 @@ static struct usb_device_id rt2800usb_device_table[] = {
 	{ USB_DEVICE(0x2019, 0xab24) },
 	/* Qcom */
 	{ USB_DEVICE(0x18e8, 0x6259) },
+	/* RadioShack */
+	{ USB_DEVICE(0x08b9, 0x1197) },
+	/* Sitecom */
+	{ USB_DEVICE(0x0df6, 0x003c) },
+	{ USB_DEVICE(0x0df6, 0x004a) },
+	{ USB_DEVICE(0x0df6, 0x004d) },
+	{ USB_DEVICE(0x0df6, 0x0053) },
+	{ USB_DEVICE(0x0df6, 0x0060) },
+	{ USB_DEVICE(0x0df6, 0x0062) },
 	/* SMC */
 	{ USB_DEVICE(0x083a, 0xa512) },
 	{ USB_DEVICE(0x083a, 0xc522) },
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 17/23] rt2x00: RT33xx device support is no longer experimental.
  2011-04-18 13:32                             ` [PATCH 16/23] rt2x00: Add USB IDs Ivo van Doorn
@ 2011-04-18 13:33                               ` Ivo van Doorn
  2011-04-18 13:33                                 ` [PATCH 18/23] rt2x00: Enable support for RT53xx PCI devices by default Ivo van Doorn
  0 siblings, 1 reply; 37+ messages in thread
From: Ivo van Doorn @ 2011-04-18 13:33 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users

From: Gertjan van Wingerde <gwingerde@gmail.com>

The rt33xx devices support for both PCI and USB devices has been in
the tree for a couple of months now, and seems to be functional and
not in a worse shape than the support for rt28xx and rt30xx devices.

No longer mark it as experimental and enable the support for these
devices by default.

Signed-off-by: Gertjan van Wingerde <gwingerde@gmail.com>
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
 drivers/net/wireless/rt2x00/Kconfig |   16 ++++------------
 1 files changed, 4 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
index f630552..e7e361e 100644
--- a/drivers/net/wireless/rt2x00/Kconfig
+++ b/drivers/net/wireless/rt2x00/Kconfig
@@ -74,17 +74,13 @@ config RT2800PCI
 if RT2800PCI
 
 config RT2800PCI_RT33XX
-	bool "rt2800pci - Include support for rt33xx devices (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
-	default n
+	bool "rt2800pci - Include support for rt33xx devices"
+	default y
 	---help---
 	  This adds support for rt33xx wireless chipset family to the
 	  rt2800pci driver.
 	  Supported chips: RT3390
 
-	  Support for these devices is non-functional at the moment and is
-	  intended for testers and developers.
-
 config RT2800PCI_RT35XX
 	bool "rt2800pci - Include support for rt35xx devices (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
@@ -153,17 +149,13 @@ config RT2800USB
 if RT2800USB
 
 config RT2800USB_RT33XX
-	bool "rt2800usb - Include support for rt33xx devices (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
-	default n
+	bool "rt2800usb - Include support for rt33xx devices"
+	default y
 	---help---
 	  This adds support for rt33xx wireless chipset family to the
 	  rt2800usb driver.
 	  Supported chips: RT3370
 
-	  Support for these devices is non-functional at the moment and is
-	  intended for testers and developers.
-
 config RT2800USB_RT35XX
 	bool "rt2800usb - Include support for rt35xx devices (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 18/23] rt2x00: Enable support for RT53xx PCI devices by default.
  2011-04-18 13:33                               ` [PATCH 17/23] rt2x00: RT33xx device support is no longer experimental Ivo van Doorn
@ 2011-04-18 13:33                                 ` Ivo van Doorn
  2011-04-18 13:33                                   ` [PATCH 19/23] rt2x00: Merge rt2x00ht.c contents in other files Ivo van Doorn
  0 siblings, 1 reply; 37+ messages in thread
From: Ivo van Doorn @ 2011-04-18 13:33 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users

From: Gertjan van Wingerde <gwingerde@gmail.com>

Code seems to be feature-complete, so no reason to not enable
these devices by default.

Also, remove the sentence about the support for these devices being
non-functional.

Signed-off-by: Gertjan van Wingerde <gwingerde@gmail.com>
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
 drivers/net/wireless/rt2x00/Kconfig |    5 +----
 1 files changed, 1 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
index e7e361e..d7e27b3 100644
--- a/drivers/net/wireless/rt2x00/Kconfig
+++ b/drivers/net/wireless/rt2x00/Kconfig
@@ -96,15 +96,12 @@ config RT2800PCI_RT35XX
 config RT2800PCI_RT53XX
        bool "rt2800-pci - Include support for rt53xx devices (EXPERIMENTAL)"
        depends on EXPERIMENTAL
-       default n
+       default y
        ---help---
          This adds support for rt53xx wireless chipset family to the
          rt2800pci driver.
          Supported chips: RT5390
 
-         Support for these devices is non-functional at the moment and is
-         intended for testers and developers.
-
 endif
 
 config RT2500USB
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 19/23] rt2x00: Merge rt2x00ht.c contents in other files.
  2011-04-18 13:33                                 ` [PATCH 18/23] rt2x00: Enable support for RT53xx PCI devices by default Ivo van Doorn
@ 2011-04-18 13:33                                   ` Ivo van Doorn
  2011-04-18 13:34                                     ` [PATCH 20/23] rt2x00: Optimize register access in rt2800pci Ivo van Doorn
  0 siblings, 1 reply; 37+ messages in thread
From: Ivo van Doorn @ 2011-04-18 13:33 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users

From: Gertjan van Wingerde <gwingerde@gmail.com>

The two functions that are in rt2x00ht.c can be much better placed
closer to the places where the call-sites of these functions are (one
in rt2x00config.c and one in rt2x00queue.c) allowing us to make these
functions static.
Also, conditional compilations doesn't seem to be necessary anymore as
802.11n support is quite common nowadays.

This makes the code a bit easier readable and searchable.

Signed-off-by: Gertjan van Wingerde <gwingerde@gmail.com>
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
 drivers/net/wireless/rt2x00/Kconfig        |    5 -
 drivers/net/wireless/rt2x00/Makefile       |    1 -
 drivers/net/wireless/rt2x00/rt2x00config.c |   28 ++++++
 drivers/net/wireless/rt2x00/rt2x00ht.c     |  137 ----------------------------
 drivers/net/wireless/rt2x00/rt2x00lib.h    |   24 -----
 drivers/net/wireless/rt2x00/rt2x00queue.c  |   81 ++++++++++++++++-
 6 files changed, 108 insertions(+), 168 deletions(-)
 delete mode 100644 drivers/net/wireless/rt2x00/rt2x00ht.c

diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
index d7e27b3..c457731 100644
--- a/drivers/net/wireless/rt2x00/Kconfig
+++ b/drivers/net/wireless/rt2x00/Kconfig
@@ -59,7 +59,6 @@ config RT2800PCI
 	select RT2800_LIB
 	select RT2X00_LIB_PCI if PCI
 	select RT2X00_LIB_SOC if RALINK_RT288X || RALINK_RT305X
-	select RT2X00_LIB_HT
 	select RT2X00_LIB_FIRMWARE
 	select RT2X00_LIB_CRYPTO
 	select CRC_CCITT
@@ -133,7 +132,6 @@ config RT2800USB
 	depends on USB
 	select RT2800_LIB
 	select RT2X00_LIB_USB
-	select RT2X00_LIB_HT
 	select RT2X00_LIB_FIRMWARE
 	select RT2X00_LIB_CRYPTO
 	select CRC_CCITT
@@ -196,9 +194,6 @@ config RT2X00_LIB_USB
 config RT2X00_LIB
 	tristate
 
-config RT2X00_LIB_HT
-	boolean
-
 config RT2X00_LIB_FIRMWARE
 	boolean
 	select FW_LOADER
diff --git a/drivers/net/wireless/rt2x00/Makefile b/drivers/net/wireless/rt2x00/Makefile
index 9713398..349d5b8 100644
--- a/drivers/net/wireless/rt2x00/Makefile
+++ b/drivers/net/wireless/rt2x00/Makefile
@@ -7,7 +7,6 @@ rt2x00lib-$(CONFIG_RT2X00_LIB_DEBUGFS)	+= rt2x00debug.o
 rt2x00lib-$(CONFIG_RT2X00_LIB_CRYPTO)	+= rt2x00crypto.o
 rt2x00lib-$(CONFIG_RT2X00_LIB_FIRMWARE)	+= rt2x00firmware.o
 rt2x00lib-$(CONFIG_RT2X00_LIB_LEDS)	+= rt2x00leds.o
-rt2x00lib-$(CONFIG_RT2X00_LIB_HT)	+= rt2x00ht.o
 
 obj-$(CONFIG_RT2X00_LIB)		+= rt2x00lib.o
 obj-$(CONFIG_RT2X00_LIB_PCI)		+= rt2x00pci.o
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
index e225a66..f70a2b4 100644
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
@@ -163,6 +163,34 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
 		rt2x00queue_start_queue(rt2x00dev->rx);
 }
 
+static u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev,
+				   struct ieee80211_conf *conf)
+{
+	struct hw_mode_spec *spec = &rt2x00dev->spec;
+	int center_channel;
+	u16 i;
+
+	/*
+	 * Initialize center channel to current channel.
+	 */
+	center_channel = spec->channels[conf->channel->hw_value].channel;
+
+	/*
+	 * Adjust center channel to HT40+ and HT40- operation.
+	 */
+	if (conf_is_ht40_plus(conf))
+		center_channel += 2;
+	else if (conf_is_ht40_minus(conf))
+		center_channel -= (center_channel == 14) ? 1 : 2;
+
+	for (i = 0; i < spec->num_channels; i++)
+		if (spec->channels[i].channel == center_channel)
+			return i;
+
+	WARN_ON(1);
+	return conf->channel->hw_value;
+}
+
 void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
 		      struct ieee80211_conf *conf,
 		      unsigned int ieee80211_flags)
diff --git a/drivers/net/wireless/rt2x00/rt2x00ht.c b/drivers/net/wireless/rt2x00/rt2x00ht.c
deleted file mode 100644
index a30f68c..0000000
--- a/drivers/net/wireless/rt2x00/rt2x00ht.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
-	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
-	<http://rt2x00.serialmonkey.com>
-
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the GNU General Public License as published by
-	the Free Software Foundation; either version 2 of the License, or
-	(at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the
-	Free Software Foundation, Inc.,
-	59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/*
-	Module: rt2x00lib
-	Abstract: rt2x00 HT specific routines.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-
-#include "rt2x00.h"
-#include "rt2x00lib.h"
-
-void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
-				   struct txentry_desc *txdesc,
-				   const struct rt2x00_rate *hwrate)
-{
-	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
-	struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;
-
-	if (tx_info->control.sta)
-		txdesc->u.ht.mpdu_density =
-		    tx_info->control.sta->ht_cap.ampdu_density;
-
-	txdesc->u.ht.ba_size = 7;	/* FIXME: What value is needed? */
-
-	/*
-	 * Only one STBC stream is supported for now.
-	 */
-	if (tx_info->flags & IEEE80211_TX_CTL_STBC)
-		txdesc->u.ht.stbc = 1;
-
-	/*
-	 * If IEEE80211_TX_RC_MCS is set txrate->idx just contains the
-	 * mcs rate to be used
-	 */
-	if (txrate->flags & IEEE80211_TX_RC_MCS) {
-		txdesc->u.ht.mcs = txrate->idx;
-
-		/*
-		 * MIMO PS should be set to 1 for STA's using dynamic SM PS
-		 * when using more then one tx stream (>MCS7).
-		 */
-		if (tx_info->control.sta && txdesc->u.ht.mcs > 7 &&
-		    ((tx_info->control.sta->ht_cap.cap &
-		      IEEE80211_HT_CAP_SM_PS) >>
-		     IEEE80211_HT_CAP_SM_PS_SHIFT) ==
-		    WLAN_HT_CAP_SM_PS_DYNAMIC)
-			__set_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags);
-	} else {
-		txdesc->u.ht.mcs = rt2x00_get_rate_mcs(hwrate->mcs);
-		if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
-			txdesc->u.ht.mcs |= 0x08;
-	}
-
-	/*
-	 * This frame is eligible for an AMPDU, however, don't aggregate
-	 * frames that are intended to probe a specific tx rate.
-	 */
-	if (tx_info->flags & IEEE80211_TX_CTL_AMPDU &&
-	    !(tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE))
-		__set_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags);
-
-	/*
-	 * Set 40Mhz mode if necessary (for legacy rates this will
-	 * duplicate the frame to both channels).
-	 */
-	if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH ||
-	    txrate->flags & IEEE80211_TX_RC_DUP_DATA)
-		__set_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags);
-	if (txrate->flags & IEEE80211_TX_RC_SHORT_GI)
-		__set_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags);
-
-	/*
-	 * Determine IFS values
-	 * - Use TXOP_BACKOFF for management frames except beacons
-	 * - Use TXOP_SIFS for fragment bursts
-	 * - Use TXOP_HTTXOP for everything else
-	 *
-	 * Note: rt2800 devices won't use CTS protection (if used)
-	 * for frames not transmitted with TXOP_HTTXOP
-	 */
-	if (ieee80211_is_mgmt(hdr->frame_control) &&
-	    !ieee80211_is_beacon(hdr->frame_control))
-		txdesc->u.ht.txop = TXOP_BACKOFF;
-	else if (!(tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT))
-		txdesc->u.ht.txop = TXOP_SIFS;
-	else
-		txdesc->u.ht.txop = TXOP_HTTXOP;
-}
-
-u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev,
-			    struct ieee80211_conf *conf)
-{
-	struct hw_mode_spec *spec = &rt2x00dev->spec;
-	int center_channel;
-	u16 i;
-
-	/*
-	 * Initialize center channel to current channel.
-	 */
-	center_channel = spec->channels[conf->channel->hw_value].channel;
-
-	/*
-	 * Adjust center channel to HT40+ and HT40- operation.
-	 */
-	if (conf_is_ht40_plus(conf))
-		center_channel += 2;
-	else if (conf_is_ht40_minus(conf))
-		center_channel -= (center_channel == 14) ? 1 : 2;
-
-	for (i = 0; i < spec->num_channels; i++)
-		if (spec->channels[i].channel == center_channel)
-			return i;
-
-	WARN_ON(1);
-	return conf->channel->hw_value;
-}
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index 57ede6c..322cc4f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -388,30 +388,6 @@ static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb,
 #endif /* CONFIG_RT2X00_LIB_CRYPTO */
 
 /*
- * HT handlers.
- */
-#ifdef CONFIG_RT2X00_LIB_HT
-void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
-				   struct txentry_desc *txdesc,
-				   const struct rt2x00_rate *hwrate);
-
-u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev,
-			    struct ieee80211_conf *conf);
-#else
-static inline void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
-						 struct txentry_desc *txdesc,
-						 const struct rt2x00_rate *hwrate)
-{
-}
-
-static inline u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev,
-					  struct ieee80211_conf *conf)
-{
-	return conf->channel->hw_value;
-}
-#endif /* CONFIG_RT2X00_LIB_HT */
-
-/*
  * RFkill handlers.
  */
 static inline void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev)
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 0d79278..56f9d0d 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -302,6 +302,85 @@ static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry,
 	}
 }
 
+static void rt2x00queue_create_tx_descriptor_ht(struct queue_entry *entry,
+						struct txentry_desc *txdesc,
+						const struct rt2x00_rate *hwrate)
+{
+	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
+	struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;
+
+	if (tx_info->control.sta)
+		txdesc->u.ht.mpdu_density =
+		    tx_info->control.sta->ht_cap.ampdu_density;
+
+	txdesc->u.ht.ba_size = 7;	/* FIXME: What value is needed? */
+
+	/*
+	 * Only one STBC stream is supported for now.
+	 */
+	if (tx_info->flags & IEEE80211_TX_CTL_STBC)
+		txdesc->u.ht.stbc = 1;
+
+	/*
+	 * If IEEE80211_TX_RC_MCS is set txrate->idx just contains the
+	 * mcs rate to be used
+	 */
+	if (txrate->flags & IEEE80211_TX_RC_MCS) {
+		txdesc->u.ht.mcs = txrate->idx;
+
+		/*
+		 * MIMO PS should be set to 1 for STA's using dynamic SM PS
+		 * when using more then one tx stream (>MCS7).
+		 */
+		if (tx_info->control.sta && txdesc->u.ht.mcs > 7 &&
+		    ((tx_info->control.sta->ht_cap.cap &
+		      IEEE80211_HT_CAP_SM_PS) >>
+		     IEEE80211_HT_CAP_SM_PS_SHIFT) ==
+		    WLAN_HT_CAP_SM_PS_DYNAMIC)
+			__set_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags);
+	} else {
+		txdesc->u.ht.mcs = rt2x00_get_rate_mcs(hwrate->mcs);
+		if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
+			txdesc->u.ht.mcs |= 0x08;
+	}
+
+	/*
+	 * This frame is eligible for an AMPDU, however, don't aggregate
+	 * frames that are intended to probe a specific tx rate.
+	 */
+	if (tx_info->flags & IEEE80211_TX_CTL_AMPDU &&
+	    !(tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE))
+		__set_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags);
+
+	/*
+	 * Set 40Mhz mode if necessary (for legacy rates this will
+	 * duplicate the frame to both channels).
+	 */
+	if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH ||
+	    txrate->flags & IEEE80211_TX_RC_DUP_DATA)
+		__set_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags);
+	if (txrate->flags & IEEE80211_TX_RC_SHORT_GI)
+		__set_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags);
+
+	/*
+	 * Determine IFS values
+	 * - Use TXOP_BACKOFF for management frames except beacons
+	 * - Use TXOP_SIFS for fragment bursts
+	 * - Use TXOP_HTTXOP for everything else
+	 *
+	 * Note: rt2800 devices won't use CTS protection (if used)
+	 * for frames not transmitted with TXOP_HTTXOP
+	 */
+	if (ieee80211_is_mgmt(hdr->frame_control) &&
+	    !ieee80211_is_beacon(hdr->frame_control))
+		txdesc->u.ht.txop = TXOP_BACKOFF;
+	else if (!(tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT))
+		txdesc->u.ht.txop = TXOP_SIFS;
+	else
+		txdesc->u.ht.txop = TXOP_HTTXOP;
+}
+
 static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
 					     struct txentry_desc *txdesc)
 {
@@ -397,7 +476,7 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
 	rt2x00queue_create_tx_descriptor_seq(entry, txdesc);
 
 	if (test_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags))
-		rt2x00ht_create_tx_descriptor(entry, txdesc, hwrate);
+		rt2x00queue_create_tx_descriptor_ht(entry, txdesc, hwrate);
 	else
 		rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate);
 }
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 20/23] rt2x00: Optimize register access in rt2800pci
  2011-04-18 13:33                                   ` [PATCH 19/23] rt2x00: Merge rt2x00ht.c contents in other files Ivo van Doorn
@ 2011-04-18 13:34                                     ` Ivo van Doorn
  2011-04-18 13:34                                       ` [PATCH 21/23] rt2x00: Optimize register access in rt2800usb Ivo van Doorn
  0 siblings, 1 reply; 37+ messages in thread
From: Ivo van Doorn @ 2011-04-18 13:34 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users

From: Helmut Schaa <helmut.schaa@googlemail.com>

All register reads/writes in rt2800pci were previously done with
rt2800_register_read/rt2800_register_write. These however indirectly
call rt2x00pci_register_read/rt2x00pci_register_write which adds an
additional overhead of at least one call and several move instructions
to each register access.

Replacing the calls to rt2800_register_read/rt2800_register_write with
direct calls to rt2x00pci_register_read/rt2x00pci_register_write gets
rid of quite a number of instructions in the drivers hotpaths (IRQ
handling and txdone handling).

For consistency replace all references to rt2800_register_read/write
with the rt2x00pci_register_read/write variants.

Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2800pci.c |  158 ++++++++++++++++--------------
 1 files changed, 84 insertions(+), 74 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 6f91a9a..b0c729b 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -66,7 +66,7 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token)
 		return;
 
 	for (i = 0; i < 200; i++) {
-		rt2800_register_read(rt2x00dev, H2M_MAILBOX_CID, &reg);
+		rt2x00pci_register_read(rt2x00dev, H2M_MAILBOX_CID, &reg);
 
 		if ((rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD0) == token) ||
 		    (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD1) == token) ||
@@ -80,8 +80,8 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token)
 	if (i == 200)
 		ERROR(rt2x00dev, "MCU request failed, no response from hardware\n");
 
-	rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
-	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
+	rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
+	rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
 }
 
 #if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X)
@@ -105,7 +105,7 @@ static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
 	struct rt2x00_dev *rt2x00dev = eeprom->data;
 	u32 reg;
 
-	rt2800_register_read(rt2x00dev, E2PROM_CSR, &reg);
+	rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, &reg);
 
 	eeprom->reg_data_in = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_IN);
 	eeprom->reg_data_out = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_OUT);
@@ -127,7 +127,7 @@ static void rt2800pci_eepromregister_write(struct eeprom_93cx6 *eeprom)
 	rt2x00_set_field32(&reg, E2PROM_CSR_CHIP_SELECT,
 			   !!eeprom->reg_chip_select);
 
-	rt2800_register_write(rt2x00dev, E2PROM_CSR, reg);
+	rt2x00pci_register_write(rt2x00dev, E2PROM_CSR, reg);
 }
 
 static void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev)
@@ -135,7 +135,7 @@ static void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev)
 	struct eeprom_93cx6 eeprom;
 	u32 reg;
 
-	rt2800_register_read(rt2x00dev, E2PROM_CSR, &reg);
+	rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, &reg);
 
 	eeprom.data = rt2x00dev;
 	eeprom.register_read = rt2800pci_eepromregister_read;
@@ -195,9 +195,9 @@ static void rt2800pci_start_queue(struct data_queue *queue)
 
 	switch (queue->qid) {
 	case QID_RX:
-		rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+		rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
 		rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 1);
-		rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+		rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
 		break;
 	case QID_BEACON:
 		/*
@@ -207,15 +207,15 @@ static void rt2800pci_start_queue(struct data_queue *queue)
 		tasklet_enable(&rt2x00dev->tbtt_tasklet);
 		tasklet_enable(&rt2x00dev->pretbtt_tasklet);
 
-		rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+		rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 1);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 1);
-		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+		rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg);
 
-		rt2800_register_read(rt2x00dev, INT_TIMER_EN, &reg);
+		rt2x00pci_register_read(rt2x00dev, INT_TIMER_EN, &reg);
 		rt2x00_set_field32(&reg, INT_TIMER_EN_PRE_TBTT_TIMER, 1);
-		rt2800_register_write(rt2x00dev, INT_TIMER_EN, reg);
+		rt2x00pci_register_write(rt2x00dev, INT_TIMER_EN, reg);
 		break;
 	default:
 		break;
@@ -233,11 +233,13 @@ static void rt2800pci_kick_queue(struct data_queue *queue)
 	case QID_AC_BE:
 	case QID_AC_BK:
 		entry = rt2x00queue_get_entry(queue, Q_INDEX);
-		rt2800_register_write(rt2x00dev, TX_CTX_IDX(queue->qid), entry->entry_idx);
+		rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX(queue->qid),
+					 entry->entry_idx);
 		break;
 	case QID_MGMT:
 		entry = rt2x00queue_get_entry(queue, Q_INDEX);
-		rt2800_register_write(rt2x00dev, TX_CTX_IDX(5), entry->entry_idx);
+		rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX(5),
+					 entry->entry_idx);
 		break;
 	default:
 		break;
@@ -251,20 +253,20 @@ static void rt2800pci_stop_queue(struct data_queue *queue)
 
 	switch (queue->qid) {
 	case QID_RX:
-		rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+		rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
 		rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
-		rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+		rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
 		break;
 	case QID_BEACON:
-		rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+		rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 0);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 0);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
-		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+		rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg);
 
-		rt2800_register_read(rt2x00dev, INT_TIMER_EN, &reg);
+		rt2x00pci_register_read(rt2x00dev, INT_TIMER_EN, &reg);
 		rt2x00_set_field32(&reg, INT_TIMER_EN_PRE_TBTT_TIMER, 0);
-		rt2800_register_write(rt2x00dev, INT_TIMER_EN, reg);
+		rt2x00pci_register_write(rt2x00dev, INT_TIMER_EN, reg);
 
 		/*
 		 * Wait for tbtt tasklets to finish.
@@ -295,7 +297,7 @@ static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev,
 	 */
 	reg = 0;
 	rt2x00_set_field32(&reg, PBF_SYS_CTRL_HOST_RAM_WRITE, 1);
-	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, reg);
+	rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, reg);
 
 	/*
 	 * Write firmware to device.
@@ -303,11 +305,11 @@ static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev,
 	rt2800_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
 				   data, len);
 
-	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000);
-	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001);
+	rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000);
+	rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001);
 
-	rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
-	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+	rt2x00pci_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
+	rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
 
 	return 0;
 }
@@ -351,7 +353,7 @@ static void rt2800pci_clear_entry(struct queue_entry *entry)
 		 * Set RX IDX in register to inform hardware that we have
 		 * handled this entry and it is available for reuse again.
 		 */
-		rt2800_register_write(rt2x00dev, RX_CRX_IDX,
+		rt2x00pci_register_write(rt2x00dev, RX_CRX_IDX,
 				      entry->entry_idx);
 	} else {
 		rt2x00_desc_read(entry_priv->desc, 1, &word);
@@ -369,45 +371,51 @@ static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev)
 	 * Initialize registers.
 	 */
 	entry_priv = rt2x00dev->tx[0].entries[0].priv_data;
-	rt2800_register_write(rt2x00dev, TX_BASE_PTR0, entry_priv->desc_dma);
-	rt2800_register_write(rt2x00dev, TX_MAX_CNT0, rt2x00dev->tx[0].limit);
-	rt2800_register_write(rt2x00dev, TX_CTX_IDX0, 0);
-	rt2800_register_write(rt2x00dev, TX_DTX_IDX0, 0);
+	rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR0, entry_priv->desc_dma);
+	rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT0,
+				 rt2x00dev->tx[0].limit);
+	rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX0, 0);
+	rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX0, 0);
 
 	entry_priv = rt2x00dev->tx[1].entries[0].priv_data;
-	rt2800_register_write(rt2x00dev, TX_BASE_PTR1, entry_priv->desc_dma);
-	rt2800_register_write(rt2x00dev, TX_MAX_CNT1, rt2x00dev->tx[1].limit);
-	rt2800_register_write(rt2x00dev, TX_CTX_IDX1, 0);
-	rt2800_register_write(rt2x00dev, TX_DTX_IDX1, 0);
+	rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR1, entry_priv->desc_dma);
+	rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT1,
+				 rt2x00dev->tx[1].limit);
+	rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX1, 0);
+	rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX1, 0);
 
 	entry_priv = rt2x00dev->tx[2].entries[0].priv_data;
-	rt2800_register_write(rt2x00dev, TX_BASE_PTR2, entry_priv->desc_dma);
-	rt2800_register_write(rt2x00dev, TX_MAX_CNT2, rt2x00dev->tx[2].limit);
-	rt2800_register_write(rt2x00dev, TX_CTX_IDX2, 0);
-	rt2800_register_write(rt2x00dev, TX_DTX_IDX2, 0);
+	rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR2, entry_priv->desc_dma);
+	rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT2,
+				 rt2x00dev->tx[2].limit);
+	rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX2, 0);
+	rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX2, 0);
 
 	entry_priv = rt2x00dev->tx[3].entries[0].priv_data;
-	rt2800_register_write(rt2x00dev, TX_BASE_PTR3, entry_priv->desc_dma);
-	rt2800_register_write(rt2x00dev, TX_MAX_CNT3, rt2x00dev->tx[3].limit);
-	rt2800_register_write(rt2x00dev, TX_CTX_IDX3, 0);
-	rt2800_register_write(rt2x00dev, TX_DTX_IDX3, 0);
+	rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR3, entry_priv->desc_dma);
+	rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT3,
+				 rt2x00dev->tx[3].limit);
+	rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX3, 0);
+	rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX3, 0);
 
 	entry_priv = rt2x00dev->rx->entries[0].priv_data;
-	rt2800_register_write(rt2x00dev, RX_BASE_PTR, entry_priv->desc_dma);
-	rt2800_register_write(rt2x00dev, RX_MAX_CNT, rt2x00dev->rx[0].limit);
-	rt2800_register_write(rt2x00dev, RX_CRX_IDX, rt2x00dev->rx[0].limit - 1);
-	rt2800_register_write(rt2x00dev, RX_DRX_IDX, 0);
+	rt2x00pci_register_write(rt2x00dev, RX_BASE_PTR, entry_priv->desc_dma);
+	rt2x00pci_register_write(rt2x00dev, RX_MAX_CNT,
+				 rt2x00dev->rx[0].limit);
+	rt2x00pci_register_write(rt2x00dev, RX_CRX_IDX,
+				 rt2x00dev->rx[0].limit - 1);
+	rt2x00pci_register_write(rt2x00dev, RX_DRX_IDX, 0);
 
 	/*
 	 * Enable global DMA configuration
 	 */
-	rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
+	rt2x00pci_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
 	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0);
 	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
 	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1);
-	rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
+	rt2x00pci_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
 
-	rt2800_register_write(rt2x00dev, DELAY_INT_CFG, 0);
+	rt2x00pci_register_write(rt2x00dev, DELAY_INT_CFG, 0);
 
 	return 0;
 }
@@ -427,8 +435,8 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
 	 * should clear the register to assure a clean state.
 	 */
 	if (state == STATE_RADIO_IRQ_ON) {
-		rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
-		rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
+		rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
+		rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
 
 		/*
 		 * Enable tasklets. The beacon related tasklets are
@@ -440,7 +448,7 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
 	}
 
 	spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
-	rt2800_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+	rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
 	rt2x00_set_field32(&reg, INT_MASK_CSR_RXDELAYINT, 0);
 	rt2x00_set_field32(&reg, INT_MASK_CSR_TXDELAYINT, 0);
 	rt2x00_set_field32(&reg, INT_MASK_CSR_RX_DONE, mask);
@@ -459,7 +467,7 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
 	rt2x00_set_field32(&reg, INT_MASK_CSR_GPTIMER, 0);
 	rt2x00_set_field32(&reg, INT_MASK_CSR_RX_COHERENT, 0);
 	rt2x00_set_field32(&reg, INT_MASK_CSR_TX_COHERENT, 0);
-	rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg);
+	rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
 	spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
 
 	if (state == STATE_RADIO_IRQ_OFF) {
@@ -480,7 +488,7 @@ static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev)
 	/*
 	 * Reset DMA indexes
 	 */
-	rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, &reg);
+	rt2x00pci_register_read(rt2x00dev, WPDMA_RST_IDX, &reg);
 	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX0, 1);
 	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX1, 1);
 	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX2, 1);
@@ -488,26 +496,26 @@ static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev)
 	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX4, 1);
 	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX5, 1);
 	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DRX_IDX0, 1);
-	rt2800_register_write(rt2x00dev, WPDMA_RST_IDX, reg);
+	rt2x00pci_register_write(rt2x00dev, WPDMA_RST_IDX, reg);
 
-	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
-	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
+	rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
+	rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
 
 	if (rt2x00_rt(rt2x00dev, RT5390)) {
-		rt2800_register_read(rt2x00dev, AUX_CTRL, &reg);
+		rt2x00pci_register_read(rt2x00dev, AUX_CTRL, &reg);
 		rt2x00_set_field32(&reg, AUX_CTRL_FORCE_PCIE_CLK, 1);
 		rt2x00_set_field32(&reg, AUX_CTRL_WAKE_PCIE_EN, 1);
-		rt2800_register_write(rt2x00dev, AUX_CTRL, reg);
+		rt2x00pci_register_write(rt2x00dev, AUX_CTRL, reg);
 	}
 
-	rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
+	rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
 
-	rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+	rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
 	rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_CSR, 1);
 	rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_BBP, 1);
-	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+	rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
 
-	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);
+	rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);
 
 	return 0;
 }
@@ -525,8 +533,8 @@ static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev)
 {
 	if (rt2x00_is_soc(rt2x00dev)) {
 		rt2800_disable_radio(rt2x00dev);
-		rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0);
-		rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0);
+		rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0);
+		rt2x00pci_register_write(rt2x00dev, TX_PIN_CFG, 0);
 	}
 }
 
@@ -537,8 +545,10 @@ static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev,
 		rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0x02);
 		rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKUP);
 	} else if (state == STATE_SLEEP) {
-		rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, 0xffffffff);
-		rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, 0xffffffff);
+		rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS,
+					 0xffffffff);
+		rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID,
+					 0xffffffff);
 		rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0x01, 0xff, 0x01);
 	}
 
@@ -778,9 +788,9 @@ static inline void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
 	 * access needs locking.
 	 */
 	spin_lock_irq(&rt2x00dev->irqmask_lock);
-	rt2800_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+	rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
 	rt2x00_set_field32(&reg, irq_field, 1);
-	rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg);
+	rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
 	spin_unlock_irq(&rt2x00dev->irqmask_lock);
 }
 
@@ -851,7 +861,7 @@ static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
 	 * need to lock the kfifo.
 	 */
 	for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) {
-		rt2800_register_read(rt2x00dev, TX_STA_FIFO, &status);
+		rt2x00pci_register_read(rt2x00dev, TX_STA_FIFO, &status);
 
 		if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID))
 			break;
@@ -873,8 +883,8 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
 	u32 reg, mask;
 
 	/* Read status and ACK all interrupts */
-	rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
-	rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
+	rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
+	rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
 
 	if (!reg)
 		return IRQ_NONE;
@@ -914,9 +924,9 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
 	 * the tasklet will reenable the appropriate interrupts.
 	 */
 	spin_lock(&rt2x00dev->irqmask_lock);
-	rt2800_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+	rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
 	reg &= mask;
-	rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg);
+	rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
 	spin_unlock(&rt2x00dev->irqmask_lock);
 
 	return IRQ_HANDLED;
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 21/23] rt2x00: Optimize register access in rt2800usb
  2011-04-18 13:34                                     ` [PATCH 20/23] rt2x00: Optimize register access in rt2800pci Ivo van Doorn
@ 2011-04-18 13:34                                       ` Ivo van Doorn
  2011-04-18 13:34                                         ` [PATCH 22/23] rt2x00: Implement get_ringparam callback function Ivo van Doorn
  2011-04-18 13:56                                         ` [PATCH 21/23] rt2x00: Optimize register access in rt2800usb Rafał Miłecki
  0 siblings, 2 replies; 37+ messages in thread
From: Ivo van Doorn @ 2011-04-18 13:34 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users

From: Ivo van Doorn <IvDoorn@gmail.com>

All register reads/writes in rt2800usb were previously done with
rt2800_register_read/rt2800_register_write. These however indirectly
call rt2x00usb_register_read/rt2x00usb_register_write which adds an
additional overhead of at least one call and several move instructions
to each register access.

Replacing the calls to rt2800_register_read/rt2800_register_write with
direct calls to rt2x00usb_register_read/rt2x00usb_register_write gets
rid of quite a number of instructions in the drivers hotpaths (IRQ
handling and txdone handling).

For consistency replace all references to rt2800_register_read/write
with the rt2x00usb_register_read/write variants.

Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2800usb.c |   56 +++++++++++++++---------------
 1 files changed, 28 insertions(+), 28 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index fd8aa99..44ead75 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -59,16 +59,16 @@ static void rt2800usb_start_queue(struct data_queue *queue)
 
 	switch (queue->qid) {
 	case QID_RX:
-		rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+		rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
 		rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 1);
-		rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+		rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
 		break;
 	case QID_BEACON:
-		rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+		rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 1);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 1);
-		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+		rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg);
 		break;
 	default:
 		break;
@@ -82,16 +82,16 @@ static void rt2800usb_stop_queue(struct data_queue *queue)
 
 	switch (queue->qid) {
 	case QID_RX:
-		rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+		rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
 		rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
-		rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+		rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
 		break;
 	case QID_BEACON:
-		rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+		rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 0);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 0);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
-		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+		rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg);
 		break;
 	default:
 		break;
@@ -185,11 +185,11 @@ static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev,
 	/*
 	 * Write firmware to device.
 	 */
-	rt2800_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
-				   data + offset, length);
+	rt2x00usb_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
+				      data + offset, length);
 
-	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
-	rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
+	rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
+	rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
 
 	/*
 	 * Send firmware request to device to load firmware,
@@ -204,7 +204,7 @@ static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev,
 	}
 
 	msleep(10);
-	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+	rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
 
 	return 0;
 }
@@ -222,22 +222,22 @@ static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev)
 	if (rt2800_wait_csr_ready(rt2x00dev))
 		return -EBUSY;
 
-	rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
-	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000);
+	rt2x00usb_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
+	rt2x00usb_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000);
 
-	rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
+	rt2x00usb_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
 
-	rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+	rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
 	rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_CSR, 1);
 	rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_BBP, 1);
-	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+	rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
 
-	rt2800_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000);
+	rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000);
 
 	rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0,
 				    USB_MODE_RESET, REGISTER_TIMEOUT);
 
-	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);
+	rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);
 
 	return 0;
 }
@@ -249,7 +249,7 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev)
 	if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev)))
 		return -EIO;
 
-	rt2800_register_read(rt2x00dev, USB_DMA_CFG, &reg);
+	rt2x00usb_register_read(rt2x00dev, USB_DMA_CFG, &reg);
 	rt2x00_set_field32(&reg, USB_DMA_CFG_PHY_CLEAR, 0);
 	rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_AGG_EN, 0);
 	rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_AGG_TIMEOUT, 128);
@@ -262,7 +262,7 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev)
 			    / 1024) - 3);
 	rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_EN, 1);
 	rt2x00_set_field32(&reg, USB_DMA_CFG_TX_BULK_EN, 1);
-	rt2800_register_write(rt2x00dev, USB_DMA_CFG, reg);
+	rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, reg);
 
 	return rt2800_enable_radio(rt2x00dev);
 }
@@ -338,12 +338,12 @@ static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev)
 	unsigned int i;
 	u32 reg;
 
-	rt2800_register_read(rt2x00dev, TXRXQ_PCNT, &reg);
+	rt2x00usb_register_read(rt2x00dev, TXRXQ_PCNT, &reg);
 	if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX0Q)) {
 		WARNING(rt2x00dev, "TX HW queue 0 timed out,"
 			" invoke forced kick\n");
 
-		rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40012);
+		rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40012);
 
 		for (i = 0; i < 10; i++) {
 			udelay(10);
@@ -351,15 +351,15 @@ static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev)
 				break;
 		}
 
-		rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006);
+		rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40006);
 	}
 
-	rt2800_register_read(rt2x00dev, TXRXQ_PCNT, &reg);
+	rt2x00usb_register_read(rt2x00dev, TXRXQ_PCNT, &reg);
 	if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX1Q)) {
 		WARNING(rt2x00dev, "TX HW queue 1 timed out,"
 			" invoke forced kick\n");
 
-		rt2800_register_write(rt2x00dev, PBF_CFG, 0xf4000a);
+		rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf4000a);
 
 		for (i = 0; i < 10; i++) {
 			udelay(10);
@@ -367,7 +367,7 @@ static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev)
 				break;
 		}
 
-		rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006);
+		rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40006);
 	}
 
 	rt2x00usb_watchdog(rt2x00dev);
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 22/23] rt2x00: Implement get_ringparam callback function
  2011-04-18 13:34                                       ` [PATCH 21/23] rt2x00: Optimize register access in rt2800usb Ivo van Doorn
@ 2011-04-18 13:34                                         ` Ivo van Doorn
  2011-04-18 13:35                                           ` [PATCH 23/23] rt2x00: Implement get_antenna and set_antenna callback functions Ivo van Doorn
  2011-04-18 13:56                                         ` [PATCH 21/23] rt2x00: Optimize register access in rt2800usb Rafał Miłecki
  1 sibling, 1 reply; 37+ messages in thread
From: Ivo van Doorn @ 2011-04-18 13:34 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users

From: Ivo van Doorn <IvDoorn@gmail.com>

With the get_ringparam callback function we can export ring parameters
to ethtool through the mac80211 interface.

Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Acked-by: Gertjan van Wingerde <gwingerde@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2400pci.c |    1 +
 drivers/net/wireless/rt2x00/rt2500pci.c |    1 +
 drivers/net/wireless/rt2x00/rt2500usb.c |    1 +
 drivers/net/wireless/rt2x00/rt2800pci.c |    1 +
 drivers/net/wireless/rt2x00/rt2800usb.c |    1 +
 drivers/net/wireless/rt2x00/rt2x00.h    |    2 ++
 drivers/net/wireless/rt2x00/rt2x00mac.c |   16 ++++++++++++++++
 drivers/net/wireless/rt2x00/rt61pci.c   |    1 +
 drivers/net/wireless/rt2x00/rt73usb.c   |    1 +
 9 files changed, 25 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index d4acdde..bbe76f7 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -1720,6 +1720,7 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = {
 	.tx_last_beacon		= rt2400pci_tx_last_beacon,
 	.rfkill_poll		= rt2x00mac_rfkill_poll,
 	.flush			= rt2x00mac_flush,
+	.get_ringparam		= rt2x00mac_get_ringparam,
 };
 
 static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index 15f5649..6f48996 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -2013,6 +2013,7 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = {
 	.tx_last_beacon		= rt2500pci_tx_last_beacon,
 	.rfkill_poll		= rt2x00mac_rfkill_poll,
 	.flush			= rt2x00mac_flush,
+	.get_ringparam		= rt2x00mac_get_ringparam,
 };
 
 static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index d88c367..5ef3386 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -1823,6 +1823,7 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = {
 	.conf_tx		= rt2x00mac_conf_tx,
 	.rfkill_poll		= rt2x00mac_rfkill_poll,
 	.flush			= rt2x00mac_flush,
+	.get_ringparam		= rt2x00mac_get_ringparam,
 };
 
 static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index b0c729b..08d3947 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -1028,6 +1028,7 @@ static const struct ieee80211_ops rt2800pci_mac80211_ops = {
 	.ampdu_action		= rt2800_ampdu_action,
 	.flush			= rt2x00mac_flush,
 	.get_survey		= rt2800_get_survey,
+	.get_ringparam		= rt2x00mac_get_ringparam,
 };
 
 static const struct rt2800_ops rt2800pci_rt2800_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 44ead75..0d4e8fa 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -673,6 +673,7 @@ static const struct ieee80211_ops rt2800usb_mac80211_ops = {
 	.ampdu_action		= rt2800_ampdu_action,
 	.flush			= rt2x00mac_flush,
 	.get_survey		= rt2800_get_survey,
+	.get_ringparam		= rt2x00mac_get_ringparam,
 };
 
 static const struct rt2800_ops rt2800usb_rt2800_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index dcdc50d..f1d8f55 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -1254,6 +1254,8 @@ int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
 		      const struct ieee80211_tx_queue_params *params);
 void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw);
 void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop);
+void rt2x00mac_get_ringparam(struct ieee80211_hw *hw,
+			     u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max);
 
 /*
  * Driver allocation handlers.
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 4770156..6d1d383 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -737,3 +737,19 @@ void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop)
 		rt2x00queue_flush_queue(queue, drop);
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_flush);
+
+void rt2x00mac_get_ringparam(struct ieee80211_hw *hw,
+			     u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max)
+{
+	struct rt2x00_dev *rt2x00dev = hw->priv;
+	struct data_queue *queue;
+
+	tx_queue_for_each(rt2x00dev, queue) {
+		*tx += queue->length;
+		*tx_max += queue->limit;
+	}
+
+	*rx = rt2x00dev->rx->length;
+	*rx_max = rt2x00dev->rx->limit;
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_get_ringparam);
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index c5dccdb..eb54031 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -2979,6 +2979,7 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = {
 	.get_tsf		= rt61pci_get_tsf,
 	.rfkill_poll		= rt2x00mac_rfkill_poll,
 	.flush			= rt2x00mac_flush,
+	.get_ringparam		= rt2x00mac_get_ringparam,
 };
 
 static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index be3eb5e..bf7fea4 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -2310,6 +2310,7 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = {
 	.get_tsf		= rt73usb_get_tsf,
 	.rfkill_poll		= rt2x00mac_rfkill_poll,
 	.flush			= rt2x00mac_flush,
+	.get_ringparam		= rt2x00mac_get_ringparam,
 };
 
 static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 23/23] rt2x00: Implement get_antenna and set_antenna callback functions
  2011-04-18 13:34                                         ` [PATCH 22/23] rt2x00: Implement get_ringparam callback function Ivo van Doorn
@ 2011-04-18 13:35                                           ` Ivo van Doorn
  0 siblings, 0 replies; 37+ messages in thread
From: Ivo van Doorn @ 2011-04-18 13:35 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users

From: Ivo van Doorn <IvDoorn@gmail.com>

Implement the get_antenna and set_antenna callback functions, which will
allow clients to control the antenna for all non-11n hardware (Antenna handling
in rt2800 is still a bit magical, so we can't use the set_antenna for those drivers
yet).

To best support the set_antenna callback some modifications are needed in the
diversity handling. We should never look at the default antenna settings to determine
if software diversity is enabled. Instead we should set the diversity flag when
possible, which will allow the link_tuner to automatically pick up the tuning.

Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Acked-by: Gertjan van Wingerde <gwingerde@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2400pci.c    |    2 +
 drivers/net/wireless/rt2x00/rt2500pci.c    |    2 +
 drivers/net/wireless/rt2x00/rt2500usb.c    |    2 +
 drivers/net/wireless/rt2x00/rt2x00.h       |    2 +
 drivers/net/wireless/rt2x00/rt2x00config.c |   45 +++++++++++--------
 drivers/net/wireless/rt2x00/rt2x00link.c   |   10 ----
 drivers/net/wireless/rt2x00/rt2x00mac.c    |   65 ++++++++++++++++++++++++++++
 drivers/net/wireless/rt2x00/rt61pci.c      |    2 +
 drivers/net/wireless/rt2x00/rt73usb.c      |    2 +
 9 files changed, 103 insertions(+), 29 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index bbe76f7..937f9e8 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -1720,6 +1720,8 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = {
 	.tx_last_beacon		= rt2400pci_tx_last_beacon,
 	.rfkill_poll		= rt2x00mac_rfkill_poll,
 	.flush			= rt2x00mac_flush,
+	.set_antenna		= rt2x00mac_set_antenna,
+	.get_antenna		= rt2x00mac_get_antenna,
 	.get_ringparam		= rt2x00mac_get_ringparam,
 };
 
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index 6f48996..d27d7b8 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -2013,6 +2013,8 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = {
 	.tx_last_beacon		= rt2500pci_tx_last_beacon,
 	.rfkill_poll		= rt2x00mac_rfkill_poll,
 	.flush			= rt2x00mac_flush,
+	.set_antenna		= rt2x00mac_set_antenna,
+	.get_antenna		= rt2x00mac_get_antenna,
 	.get_ringparam		= rt2x00mac_get_ringparam,
 };
 
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 5ef3386..b21f812 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -1823,6 +1823,8 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = {
 	.conf_tx		= rt2x00mac_conf_tx,
 	.rfkill_poll		= rt2x00mac_rfkill_poll,
 	.flush			= rt2x00mac_flush,
+	.set_antenna		= rt2x00mac_set_antenna,
+	.get_antenna		= rt2x00mac_get_antenna,
 	.get_ringparam		= rt2x00mac_get_ringparam,
 };
 
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index f1d8f55..acf561f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -1254,6 +1254,8 @@ int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
 		      const struct ieee80211_tx_queue_params *params);
 void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw);
 void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop);
+int rt2x00mac_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant);
+int rt2x00mac_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant);
 void rt2x00mac_get_ringparam(struct ieee80211_hw *hw,
 			     u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max);
 
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
index f70a2b4..2a313b6 100644
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
@@ -109,15 +109,6 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
 	rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp, changed);
 }
 
-static inline
-enum antenna rt2x00lib_config_antenna_check(enum antenna current_ant,
-					    enum antenna default_ant)
-{
-	if (current_ant != ANTENNA_SW_DIVERSITY)
-		return current_ant;
-	return (default_ant != ANTENNA_SW_DIVERSITY) ? default_ant : ANTENNA_B;
-}
-
 void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
 			      struct antenna_setup config)
 {
@@ -126,19 +117,35 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
 	struct antenna_setup *active = &rt2x00dev->link.ant.active;
 
 	/*
-	 * Failsafe: Make sure we are not sending the
-	 * ANTENNA_SW_DIVERSITY state to the driver.
-	 * If that happens, fallback to hardware defaults,
-	 * or our own default.
+	 * When the caller tries to send the SW diversity,
+	 * we must update the ANTENNA_RX_DIVERSITY flag to
+	 * enable the antenna diversity in the link tuner.
+	 *
+	 * Secondly, we must guarentee we never send the
+	 * software antenna diversity command to the driver.
 	 */
-	if (!(ant->flags & ANTENNA_RX_DIVERSITY))
-		config.rx = rt2x00lib_config_antenna_check(config.rx, def->rx);
-	else if (config.rx == ANTENNA_SW_DIVERSITY)
+	if (!(ant->flags & ANTENNA_RX_DIVERSITY)) {
+		if (config.rx == ANTENNA_SW_DIVERSITY) {
+			ant->flags |= ANTENNA_RX_DIVERSITY;
+
+			if (def->rx == ANTENNA_SW_DIVERSITY)
+				config.rx = ANTENNA_B;
+			else
+				config.rx = def->rx;
+		}
+	} else if (config.rx == ANTENNA_SW_DIVERSITY)
 		config.rx = active->rx;
 
-	if (!(ant->flags & ANTENNA_TX_DIVERSITY))
-		config.tx = rt2x00lib_config_antenna_check(config.tx, def->tx);
-	else if (config.tx == ANTENNA_SW_DIVERSITY)
+	if (!(ant->flags & ANTENNA_TX_DIVERSITY)) {
+		if (config.tx == ANTENNA_SW_DIVERSITY) {
+			ant->flags |= ANTENNA_TX_DIVERSITY;
+
+			if (def->tx == ANTENNA_SW_DIVERSITY)
+				config.tx = ANTENNA_B;
+			else
+				config.tx = def->tx;
+		}
+	} else if (config.tx == ANTENNA_SW_DIVERSITY)
 		config.tx = active->tx;
 
 	/*
diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c
index ba0bb76..fa55399 100644
--- a/drivers/net/wireless/rt2x00/rt2x00link.c
+++ b/drivers/net/wireless/rt2x00/rt2x00link.c
@@ -192,17 +192,7 @@ static bool rt2x00lib_antenna_diversity(struct rt2x00_dev *rt2x00dev)
 	/*
 	 * Determine if software diversity is enabled for
 	 * either the TX or RX antenna (or both).
-	 * Always perform this check since within the link
-	 * tuner interval the configuration might have changed.
 	 */
-	ant->flags &= ~ANTENNA_RX_DIVERSITY;
-	ant->flags &= ~ANTENNA_TX_DIVERSITY;
-
-	if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY)
-		ant->flags |= ANTENNA_RX_DIVERSITY;
-	if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY)
-		ant->flags |= ANTENNA_TX_DIVERSITY;
-
 	if (!(ant->flags & ANTENNA_RX_DIVERSITY) &&
 	    !(ant->flags & ANTENNA_TX_DIVERSITY)) {
 		ant->flags = 0;
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 6d1d383..93bec14 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -738,6 +738,71 @@ void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop)
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_flush);
 
+int rt2x00mac_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
+{
+	struct rt2x00_dev *rt2x00dev = hw->priv;
+	struct link_ant *ant = &rt2x00dev->link.ant;
+	struct antenna_setup *def = &rt2x00dev->default_ant;
+	struct antenna_setup setup;
+
+	// The antenna value is not supposed to be 0,
+	// or exceed the maximum number of antenna's.
+	if (!tx_ant || (tx_ant & ~3) || !rx_ant || (rx_ant & ~3))
+		return -EINVAL;
+
+	// When the client tried to configure the antenna to or from
+	// diversity mode, we must reset the default antenna as well
+	// as that controls the diversity switch.
+	if (ant->flags & ANTENNA_TX_DIVERSITY && tx_ant != 3)
+		ant->flags &= ~ANTENNA_TX_DIVERSITY;
+	if (ant->flags & ANTENNA_RX_DIVERSITY && rx_ant != 3)
+		ant->flags &= ~ANTENNA_RX_DIVERSITY;
+
+	// If diversity is being enabled, check if we need hardware
+	// or software diversity. In the latter case, reset the value,
+	// and make sure we update the antenna flags to have the
+	// link tuner pick up the diversity tuning.
+	if (tx_ant == 3 && def->tx == ANTENNA_SW_DIVERSITY) {
+		tx_ant = ANTENNA_SW_DIVERSITY;
+		ant->flags |= ANTENNA_TX_DIVERSITY;
+	}
+
+	if (rx_ant == 3 && def->rx == ANTENNA_SW_DIVERSITY) {
+		rx_ant = ANTENNA_SW_DIVERSITY;
+		ant->flags |= ANTENNA_RX_DIVERSITY;
+	}
+
+	setup.tx = tx_ant;
+	setup.rx = rx_ant;
+
+	rt2x00lib_config_antenna(rt2x00dev, setup);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_set_antenna);
+
+int rt2x00mac_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
+{
+	struct rt2x00_dev *rt2x00dev = hw->priv;
+	struct link_ant *ant = &rt2x00dev->link.ant;
+	struct antenna_setup *active = &rt2x00dev->link.ant.active;
+
+	// When software diversity is active, we must report this to the
+	// client and not the current active antenna state.
+	if (ant->flags & ANTENNA_TX_DIVERSITY)
+		*tx_ant = ANTENNA_HW_DIVERSITY;
+	else
+		*tx_ant = active->tx;
+
+	if (ant->flags & ANTENNA_RX_DIVERSITY)
+		*rx_ant = ANTENNA_HW_DIVERSITY;
+	else
+		*rx_ant = active->rx;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_get_antenna);
+
 void rt2x00mac_get_ringparam(struct ieee80211_hw *hw,
 			     u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max)
 {
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index eb54031..9d35ec1 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -2979,6 +2979,8 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = {
 	.get_tsf		= rt61pci_get_tsf,
 	.rfkill_poll		= rt2x00mac_rfkill_poll,
 	.flush			= rt2x00mac_flush,
+	.set_antenna		= rt2x00mac_set_antenna,
+	.get_antenna		= rt2x00mac_get_antenna,
 	.get_ringparam		= rt2x00mac_get_ringparam,
 };
 
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index bf7fea4..a6ce7d6 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -2310,6 +2310,8 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = {
 	.get_tsf		= rt73usb_get_tsf,
 	.rfkill_poll		= rt2x00mac_rfkill_poll,
 	.flush			= rt2x00mac_flush,
+	.set_antenna		= rt2x00mac_set_antenna,
+	.get_antenna		= rt2x00mac_get_antenna,
 	.get_ringparam		= rt2x00mac_get_ringparam,
 };
 
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* Re: [PATCH 21/23] rt2x00: Optimize register access in rt2800usb
  2011-04-18 13:34                                       ` [PATCH 21/23] rt2x00: Optimize register access in rt2800usb Ivo van Doorn
  2011-04-18 13:34                                         ` [PATCH 22/23] rt2x00: Implement get_ringparam callback function Ivo van Doorn
@ 2011-04-18 13:56                                         ` Rafał Miłecki
  2011-04-18 14:06                                           ` Ivo Van Doorn
  1 sibling, 1 reply; 37+ messages in thread
From: Rafał Miłecki @ 2011-04-18 13:56 UTC (permalink / raw)
  To: Ivo van Doorn; +Cc: John W. Linville, linux-wireless, users

Hello Ivo,

I don't develop rt2x00 and I'm not sure about my solution, so of
course decision is up to you, just wanted to suggest you sth.

2011/4/18 Ivo van Doorn <ivdoorn@gmail.com>:
> From: Ivo van Doorn <IvDoorn@gmail.com>
>
> All register reads/writes in rt2800usb were previously done with
> rt2800_register_read/rt2800_register_write. These however indirectly
> call rt2x00usb_register_read/rt2x00usb_register_write which adds an
> additional overhead of at least one call and several move instructions
> to each register access.
>
> Replacing the calls to rt2800_register_read/rt2800_register_write with
> direct calls to rt2x00usb_register_read/rt2x00usb_register_write gets
> rid of quite a number of instructions in the drivers hotpaths (IRQ
> handling and txdone handling).
>
> For consistency replace all references to rt2800_register_read/write
> with the rt2x00usb_register_read/write variants.

This way you loose abstraction of writes/reads for usb vs. pci. And
you still can not optimize rt2800lib code which is shared between usb
and pci.

Wouldn't this be better to create two pointers in struct rt2x00_dev.
One for writing function and one for reading function? Am I right
thinking calling functions by pointers is quite fast? Or is this still
noticeably slower than using proper functions directly?

-- 
Rafał

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 21/23] rt2x00: Optimize register access in rt2800usb
  2011-04-18 13:56                                         ` [PATCH 21/23] rt2x00: Optimize register access in rt2800usb Rafał Miłecki
@ 2011-04-18 14:06                                           ` Ivo Van Doorn
  2011-04-18 14:14                                             ` Rafał Miłecki
  2011-04-18 14:48                                             ` Helmut Schaa
  0 siblings, 2 replies; 37+ messages in thread
From: Ivo Van Doorn @ 2011-04-18 14:06 UTC (permalink / raw)
  To: Rafał Miłecki
  Cc: John W. Linville, linux-wireless, users, Helmut Schaa

Hi,

>> All register reads/writes in rt2800usb were previously done with
>> rt2800_register_read/rt2800_register_write. These however indirectly
>> call rt2x00usb_register_read/rt2x00usb_register_write which adds an
>> additional overhead of at least one call and several move instructions
>> to each register access.
>>
>> Replacing the calls to rt2800_register_read/rt2800_register_write with
>> direct calls to rt2x00usb_register_read/rt2x00usb_register_write gets
>> rid of quite a number of instructions in the drivers hotpaths (IRQ
>> handling and txdone handling).
>>
>> For consistency replace all references to rt2800_register_read/write
>> with the rt2x00usb_register_read/write variants.
>
> This way you loose abstraction of writes/reads for usb vs. pci. And
> you still can not optimize rt2800lib code which is shared between usb
> and pci.

Well the rt2800lib code is not changed by this (or patch 20 of this series).

> Wouldn't this be better to create two pointers in struct rt2x00_dev.
> One for writing function and one for reading function? Am I right
> thinking calling functions by pointers is quite fast? Or is this still
> noticeably slower than using proper functions directly?

We already have the pointer inside struct rt2x00_dev which references
the register access functions for rt2800pci/usb. These pointers are used
by rt2800lib to access the common registers. What this patch does, is
optimize the case where we exactly know which function we need, because
we are in the actual driver.

As for the performance, I'll let Helmut comment on that as he created patch 20,
which introduced this change to rt2800pci. :)

Ivo

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 21/23] rt2x00: Optimize register access in rt2800usb
  2011-04-18 14:06                                           ` Ivo Van Doorn
@ 2011-04-18 14:14                                             ` Rafał Miłecki
  2011-04-18 14:48                                             ` Helmut Schaa
  1 sibling, 0 replies; 37+ messages in thread
From: Rafał Miłecki @ 2011-04-18 14:14 UTC (permalink / raw)
  To: Ivo Van Doorn; +Cc: John W. Linville, linux-wireless, users, Helmut Schaa

W dniu 18 kwietnia 2011 16:06 użytkownik Ivo Van Doorn
<ivdoorn@gmail.com> napisał:
> Hi,
>
>>> All register reads/writes in rt2800usb were previously done with
>>> rt2800_register_read/rt2800_register_write. These however indirectly
>>> call rt2x00usb_register_read/rt2x00usb_register_write which adds an
>>> additional overhead of at least one call and several move instructions
>>> to each register access.
>>>
>>> Replacing the calls to rt2800_register_read/rt2800_register_write with
>>> direct calls to rt2x00usb_register_read/rt2x00usb_register_write gets
>>> rid of quite a number of instructions in the drivers hotpaths (IRQ
>>> handling and txdone handling).
>>>
>>> For consistency replace all references to rt2800_register_read/write
>>> with the rt2x00usb_register_read/write variants.
>>
>> This way you loose abstraction of writes/reads for usb vs. pci. And
>> you still can not optimize rt2800lib code which is shared between usb
>> and pci.
>
> Well the rt2800lib code is not changed by this (or patch 20 of this series).
>
>> Wouldn't this be better to create two pointers in struct rt2x00_dev.
>> One for writing function and one for reading function? Am I right
>> thinking calling functions by pointers is quite fast? Or is this still
>> noticeably slower than using proper functions directly?
>
> We already have the pointer inside struct rt2x00_dev which references
> the register access functions for rt2800pci/usb. These pointers are used
> by rt2800lib to access the common registers. What this patch does, is
> optimize the case where we exactly know which function we need, because
> we are in the actual driver.

Ah, OK, I can see rt2800_register_read/write indeed are using pointers:
rt2800ops->register_read(rt2x00dev, offset, value);
So I believe it was still not fast enough for you.

It's OK then. I just though you were using
if (dev->usb)
rt2x00usb_register_read
else
...


> As for the performance, I'll let Helmut comment on that as he created patch 20,
> which introduced this change to rt2800pci. :)

-- 
Rafał

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 21/23] rt2x00: Optimize register access in rt2800usb
  2011-04-18 14:06                                           ` Ivo Van Doorn
  2011-04-18 14:14                                             ` Rafał Miłecki
@ 2011-04-18 14:48                                             ` Helmut Schaa
  2011-04-18 15:02                                               ` Rafał Miłecki
  1 sibling, 1 reply; 37+ messages in thread
From: Helmut Schaa @ 2011-04-18 14:48 UTC (permalink / raw)
  To: Rafał Miłecki
  Cc: Ivo Van Doorn, John W. Linville, linux-wireless, users

Hi,

Am Montag, 18. April 2011 schrieb Ivo Van Doorn:
> > Wouldn't this be better to create two pointers in struct rt2x00_dev.
> > One for writing function and one for reading function? Am I right
> > thinking calling functions by pointers is quite fast? Or is this still
> > noticeably slower than using proper functions directly?
> 
> We already have the pointer inside struct rt2x00_dev which references
> the register access functions for rt2800pci/usb. These pointers are used
> by rt2800lib to access the common registers. What this patch does, is
> optimize the case where we exactly know which function we need, because
> we are in the actual driver.
> 
> As for the performance, I'll let Helmut comment on that as he created patch 20,
> which introduced this change to rt2800pci. :)

Sure, I was comparing some assembly in the rt2800pci hotpaths (on a 380Mhz
MIPS CPU btw). A register read/write on PCI is just a readl or writel,
nothing more but using the indirect wrappers we get something like this
(This is x86_64 as I didn't want to cross compile right now). For example
the register read + write in rt2800pci_enable_interrupt (which is called
in every tasklet invocation, which can happen for every rx'ed frame and
every tx'ed frame).

movq    8(%rbx), %rax   # rt2x00dev_1(D)->ops, rt2x00dev_1(D)->ops
leaq    -36(%rbp), %rdx #, tmp82
movq    %rbx, %rdi      # rt2x00dev,
movq    72(%rax), %rax  # D.47612_27->drv, D.47612_27->drv
movl    $516, %esi      #,
call    *(%rax) # rt2800ops_29->register_read
movb    %r14b, %cl      #,
movq    8(%rbx), %rax   # rt2x00dev_1(D)->ops, rt2x00dev_1(D)->ops
movq    %rbx, %rdi      # rt2x00dev,
movq    72(%rax), %rax  # D.47619_31->drv, D.47619_31->drv
movl    $516, %esi      #,
movl    $1, %edx        #, reg.119
sall    %cl, %edx       #, reg.119
andl    %r13d, %edx     # irq_field$bit_mask, reg.119
notl    %r13d   # tmp89
andl    -36(%rbp), %r13d        # reg, tmp89
orl     %r13d, %edx     # tmp89, reg.119
movl    %edx, -36(%rbp) # reg.119, reg
call    *16(%rax)       # rt2800ops_33->register_write

Also, this will trigger rt2x00pci_register_read

pushq   %rbp    #
mov     %esi, %esi      # offset, addr.27
movq    %rsp, %rbp      #,
addq    1056(%rdi), %rsi        # rt2x00dev_1(D)->csr.base, addr.27
movl    %eax, (%rdx)    # ret,* value

And rt2x00pci_register_write:

pushq   %rbp    #
mov     %esi, %esi      # offset, addr.26
movq    %rsp, %rbp      #,
addq    1056(%rdi), %rsi        # rt2x00dev_1(D)->csr.base, addr.26
movl 	%edx,(%rsi)        # value,* addr.26

And here the same when using rt2x00pci_register_read/write directly:

movq    1056(%rbx), %rax        # rt2x00dev_1(D)->csr.base, rt2x00dev_1(D)->csr.base
movl 	516(%rax),%eax     #, reg.119
movl    %r13d, %edx     # irq_field$bit_mask, tmp80
movb    %r14b, %cl      #,
notl    %edx    # tmp80
andl    %edx, %eax      # tmp80, reg.119
movl    $1, %edx        #, tmp85
sall    %cl, %edx       #, tmp85
andl    %r13d, %edx     # irq_field$bit_mask, tmp85
orl     %edx, %eax      # tmp85, reg.119
movq    1056(%rbx), %rdx        # rt2x00dev_1(D)->csr.base, rt2x00dev_1(D)->csr.base
movl 	%eax,516(%rdx)     # reg.119,

As you can see we save more then just one indirect function call:

17 movs -> 7 movs
2 calls -> 0 calls
1 add -> 0 adds

This happens because the compiler is able to apply a number of optimizations
that are only possible by inlining rt2x00pci_register_read/write. When using
the indirect function call the compiler is not able to inline them.

So, I first thought about using direct calls only in the interrupt handler
and the RX/TX hotpaths but since using rt2800_register_read and
rt2x00pci_register_read in different locations in rt2800pci would be even
more confusing I just replaced every rt2800_register_read with
rt2x00pci_register_read in rt2800pci.

One way to keep the abstraction and still improve the register_read/write
operations would be to introduce a inlined rt2800pci_register_read/write
which directly calls rt2x00pci_register_read/write and provide that via
rt2800_ops to rt2800lib. That way all calls in rt2800pci can directly
inline rt2x00_register_read/write while rt2800lib will still use indirect
calls to do the same.

However, I didn't see any need for this.

Helmut

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 21/23] rt2x00: Optimize register access in rt2800usb
  2011-04-18 14:48                                             ` Helmut Schaa
@ 2011-04-18 15:02                                               ` Rafał Miłecki
  0 siblings, 0 replies; 37+ messages in thread
From: Rafał Miłecki @ 2011-04-18 15:02 UTC (permalink / raw)
  To: Helmut Schaa; +Cc: Ivo Van Doorn, John W. Linville, linux-wireless, users

W dniu 18 kwietnia 2011 16:48 użytkownik Helmut Schaa
<helmut.schaa@googlemail.com> napisał:
> Hi,
>
> Am Montag, 18. April 2011 schrieb Ivo Van Doorn:
>> > Wouldn't this be better to create two pointers in struct rt2x00_dev.
>> > One for writing function and one for reading function? Am I right
>> > thinking calling functions by pointers is quite fast? Or is this still
>> > noticeably slower than using proper functions directly?
>>
>> We already have the pointer inside struct rt2x00_dev which references
>> the register access functions for rt2800pci/usb. These pointers are used
>> by rt2800lib to access the common registers. What this patch does, is
>> optimize the case where we exactly know which function we need, because
>> we are in the actual driver.
>>
>> As for the performance, I'll let Helmut comment on that as he created patch 20,
>> which introduced this change to rt2800pci. :)
>
> Sure, I was comparing some assembly in the rt2800pci hotpaths (on a 380Mhz
> MIPS CPU btw). A register read/write on PCI is just a readl or writel,
> nothing more but using the indirect wrappers we get something like this
> (This is x86_64 as I didn't want to cross compile right now). For example
> the register read + write in rt2800pci_enable_interrupt (which is called
> in every tasklet invocation, which can happen for every rx'ed frame and
> every tx'ed frame).
>
> movq    8(%rbx), %rax   # rt2x00dev_1(D)->ops, rt2x00dev_1(D)->ops
> leaq    -36(%rbp), %rdx #, tmp82
> movq    %rbx, %rdi      # rt2x00dev,
> movq    72(%rax), %rax  # D.47612_27->drv, D.47612_27->drv
> movl    $516, %esi      #,
> call    *(%rax) # rt2800ops_29->register_read
> movb    %r14b, %cl      #,
> movq    8(%rbx), %rax   # rt2x00dev_1(D)->ops, rt2x00dev_1(D)->ops
> movq    %rbx, %rdi      # rt2x00dev,
> movq    72(%rax), %rax  # D.47619_31->drv, D.47619_31->drv
> movl    $516, %esi      #,
> movl    $1, %edx        #, reg.119
> sall    %cl, %edx       #, reg.119
> andl    %r13d, %edx     # irq_field$bit_mask, reg.119
> notl    %r13d   # tmp89
> andl    -36(%rbp), %r13d        # reg, tmp89
> orl     %r13d, %edx     # tmp89, reg.119
> movl    %edx, -36(%rbp) # reg.119, reg
> call    *16(%rax)       # rt2800ops_33->register_write
>
> Also, this will trigger rt2x00pci_register_read
>
> pushq   %rbp    #
> mov     %esi, %esi      # offset, addr.27
> movq    %rsp, %rbp      #,
> addq    1056(%rdi), %rsi        # rt2x00dev_1(D)->csr.base, addr.27
> movl    %eax, (%rdx)    # ret,* value
>
> And rt2x00pci_register_write:
>
> pushq   %rbp    #
> mov     %esi, %esi      # offset, addr.26
> movq    %rsp, %rbp      #,
> addq    1056(%rdi), %rsi        # rt2x00dev_1(D)->csr.base, addr.26
> movl    %edx,(%rsi)        # value,* addr.26
>
> And here the same when using rt2x00pci_register_read/write directly:
>
> movq    1056(%rbx), %rax        # rt2x00dev_1(D)->csr.base, rt2x00dev_1(D)->csr.base
> movl    516(%rax),%eax     #, reg.119
> movl    %r13d, %edx     # irq_field$bit_mask, tmp80
> movb    %r14b, %cl      #,
> notl    %edx    # tmp80
> andl    %edx, %eax      # tmp80, reg.119
> movl    $1, %edx        #, tmp85
> sall    %cl, %edx       #, tmp85
> andl    %r13d, %edx     # irq_field$bit_mask, tmp85
> orl     %edx, %eax      # tmp85, reg.119
> movq    1056(%rbx), %rdx        # rt2x00dev_1(D)->csr.base, rt2x00dev_1(D)->csr.base
> movl    %eax,516(%rdx)     # reg.119,
>
> As you can see we save more then just one indirect function call:
>
> 17 movs -> 7 movs
> 2 calls -> 0 calls
> 1 add -> 0 adds
>
> This happens because the compiler is able to apply a number of optimizations
> that are only possible by inlining rt2x00pci_register_read/write. When using
> the indirect function call the compiler is not able to inline them.
>
> So, I first thought about using direct calls only in the interrupt handler
> and the RX/TX hotpaths but since using rt2800_register_read and
> rt2x00pci_register_read in different locations in rt2800pci would be even
> more confusing I just replaced every rt2800_register_read with
> rt2x00pci_register_read in rt2800pci.
>
> One way to keep the abstraction and still improve the register_read/write
> operations would be to introduce a inlined rt2800pci_register_read/write
> which directly calls rt2x00pci_register_read/write and provide that via
> rt2800_ops to rt2800lib. That way all calls in rt2800pci can directly
> inline rt2x00_register_read/write while rt2800lib will still use indirect
> calls to do the same.
>
> However, I didn't see any need for this.

Huh, thanks a lot for great explanation :)

-- 
Rafał

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 04/23] rt2x00: Make rt2x00_queue_entry_for_each more flexible
  2011-04-18 13:27     ` [PATCH 04/23] rt2x00: Make rt2x00_queue_entry_for_each more flexible Ivo van Doorn
  2011-04-18 13:28       ` [PATCH 05/23] rt2x00: Use correct TBTT_SYNC config in AP mode Ivo van Doorn
@ 2011-04-28  2:55       ` Yasushi SHOJI
  2011-04-28  2:55       ` Yasushi SHOJI
  2 siblings, 0 replies; 37+ messages in thread
From: Yasushi SHOJI @ 2011-04-28  2:55 UTC (permalink / raw)
  To: helmut.schaa; +Cc: ivdoorn, hanada, linux-wireless

Hi,

At Mon, 18 Apr 2011 15:27:43 +0200,
Ivo van Doorn wrote:
> 
> From: Helmut Schaa <helmut.schaa-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
> 
> Allow passing a void pointer to rt2x00_queue_entry_for_each which in
> turn in provided to the callback function.
> 
> Furthermore, allow the callback function to stop processing by returning
> true. And also notify the caller of rt2x00_queue_entry_for_each if the
> loop was canceled by the callback.

My colleague just tested this patch set and found out that the in
question makes our 400MHz ARM cpu board with ralink usb dongle non
functional due to high cpu consumption.  it seems for us that exiting
from function every time it finds an entry is too expensive on systems
slower than PCs.

To verify our thought, we changed the source code as the patch below.
What we intended to do with this change is to continue processing all
entry without breaking semantics.

With the patch below our board seem to work fine again, but not sure
exactly why it takes so much time to check the list again.  We are not
against the idea of the patch at all.  We just want to ask you guys
how we should go to track this problem. it might be the slow usb?

Thanks,

> diff -urN compat-wireless-2011-04-26/drivers/net/wireless/rt2x00/rt2x00queue.c compat-wireless-2011-04-26-armadillo/drivers/net/wireless/rt2x00/rt2x00queue.c
> --- compat-wireless-2011-04-26/drivers/net/wireless/rt2x00/rt2x00queue.c	2011-04-27 04:04:26.000000000 +0900
> +++ compat-wireless-2011-04-26-armadillo/drivers/net/wireless/rt2x00/rt2x00queue.c	2011-04-27 17:13:45.000000000 +0900
> @@ -740,6 +740,7 @@
>  	unsigned int index_start;
>  	unsigned int index_end;
>  	unsigned int i;
> +	bool ret = false;
>  
>  	if (unlikely(start >= Q_INDEX_MAX || end >= Q_INDEX_MAX)) {
>  		ERROR(queue->rt2x00dev,
> @@ -766,21 +767,21 @@
>  	if (index_start < index_end) {
>  		for (i = index_start; i < index_end; i++) {
>  			if (fn(&queue->entries[i], data))
> -				return true;
> +				ret = true;
>  		}
>  	} else {
>  		for (i = index_start; i < queue->limit; i++) {
>  			if (fn(&queue->entries[i], data))
> -				return true;
> +				ret = true;
>  		}
>  
>  		for (i = 0; i < index_end; i++) {
>  			if (fn(&queue->entries[i], data))
> -				return true;
> +				ret = true;
>  		}
>  	}
>  
> -	return false;
> +	return ret;
>  }
>  EXPORT_SYMBOL_GPL(rt2x00queue_for_each_entry);
-- 
          yashi

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 04/23] rt2x00: Make rt2x00_queue_entry_for_each more flexible
  2011-04-18 13:27     ` [PATCH 04/23] rt2x00: Make rt2x00_queue_entry_for_each more flexible Ivo van Doorn
  2011-04-18 13:28       ` [PATCH 05/23] rt2x00: Use correct TBTT_SYNC config in AP mode Ivo van Doorn
  2011-04-28  2:55       ` [PATCH 04/23] rt2x00: Make rt2x00_queue_entry_for_each more flexible Yasushi SHOJI
@ 2011-04-28  2:55       ` Yasushi SHOJI
  2011-04-28 18:55         ` Ivo Van Doorn
  2 siblings, 1 reply; 37+ messages in thread
From: Yasushi SHOJI @ 2011-04-28  2:55 UTC (permalink / raw)
  To: helmut.schaa; +Cc: ivdoorn, hanada, linux-wireless

Hi,

At Mon, 18 Apr 2011 15:27:43 +0200,
Ivo van Doorn wrote:
> 
> From: Helmut Schaa <helmut.schaa-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
> 
> Allow passing a void pointer to rt2x00_queue_entry_for_each which in
> turn in provided to the callback function.
> 
> Furthermore, allow the callback function to stop processing by returning
> true. And also notify the caller of rt2x00_queue_entry_for_each if the
> loop was canceled by the callback.

My colleague just tested this patch set and found out that the in
question makes our 400MHz ARM cpu board with ralink usb dongle non
functional due to high cpu consumption.  it seems for us that exiting
from function every time it finds an entry is too expensive on systems
slower than PCs.

To verify our thought, we changed the source code as the patch below.
What we intended to do with this change is to continue processing all
entry without breaking semantics.

With the patch below our board seem to work fine again, but not sure
exactly why it takes so much time to check the list again.  We are not
against the idea of the patch at all.  We just want to ask you guys
how we should go to track this problem. it might be the slow usb?

Thanks,

> diff -urN compat-wireless-2011-04-26/drivers/net/wireless/rt2x00/rt2x00queue.c compat-wireless-2011-04-26-armadillo/drivers/net/wireless/rt2x00/rt2x00queue.c
> --- compat-wireless-2011-04-26/drivers/net/wireless/rt2x00/rt2x00queue.c	2011-04-27 04:04:26.000000000 +0900
> +++ compat-wireless-2011-04-26-armadillo/drivers/net/wireless/rt2x00/rt2x00queue.c	2011-04-27 17:13:45.000000000 +0900
> @@ -740,6 +740,7 @@
>  	unsigned int index_start;
>  	unsigned int index_end;
>  	unsigned int i;
> +	bool ret = false;
>  
>  	if (unlikely(start >= Q_INDEX_MAX || end >= Q_INDEX_MAX)) {
>  		ERROR(queue->rt2x00dev,
> @@ -766,21 +767,21 @@
>  	if (index_start < index_end) {
>  		for (i = index_start; i < index_end; i++) {
>  			if (fn(&queue->entries[i], data))
> -				return true;
> +				ret = true;
>  		}
>  	} else {
>  		for (i = index_start; i < queue->limit; i++) {
>  			if (fn(&queue->entries[i], data))
> -				return true;
> +				ret = true;
>  		}
>  
>  		for (i = 0; i < index_end; i++) {
>  			if (fn(&queue->entries[i], data))
> -				return true;
> +				ret = true;
>  		}
>  	}
>  
> -	return false;
> +	return ret;
>  }
>  EXPORT_SYMBOL_GPL(rt2x00queue_for_each_entry);
-- 
          yashi

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 04/23] rt2x00: Make rt2x00_queue_entry_for_each more flexible
  2011-04-28  2:55       ` Yasushi SHOJI
@ 2011-04-28 18:55         ` Ivo Van Doorn
  2011-04-29  6:06           ` Gertjan van Wingerde
  0 siblings, 1 reply; 37+ messages in thread
From: Ivo Van Doorn @ 2011-04-28 18:55 UTC (permalink / raw)
  To: Yasushi SHOJI; +Cc: helmut.schaa, hanada, linux-wireless

Hi,

> My colleague just tested this patch set and found out that the in
> question makes our 400MHz ARM cpu board with ralink usb dongle non
> functional due to high cpu consumption.  it seems for us that exiting
> from function every time it finds an entry is too expensive on systems
> slower than PCs.

Interesting, I would suspected the patch to reduce the CPU consumption
rather then increasing it. I can do some testing regarding this looping
during the weekend, but I haven't seen high CPU consumption on my
system during my last test. However I wasn't testing on an embedded system...

> To verify our thought, we changed the source code as the patch below.
> What we intended to do with this change is to continue processing all
> entry without breaking semantics.
>
> With the patch below our board seem to work fine again, but not sure
> exactly why it takes so much time to check the list again.  We are not
> against the idea of the patch at all.  We just want to ask you guys
> how we should go to track this problem. it might be the slow usb?

Could you try use debugfs and see if some queue and packet counters
of mac80211/rt2x00 show excessive values?

Have you been running the test with powersaving enabled or disabled?

Ivo

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 04/23] rt2x00: Make rt2x00_queue_entry_for_each more flexible
  2011-04-28 18:55         ` Ivo Van Doorn
@ 2011-04-29  6:06           ` Gertjan van Wingerde
  2011-04-30 14:01             ` Ivo van Doorn
  0 siblings, 1 reply; 37+ messages in thread
From: Gertjan van Wingerde @ 2011-04-29  6:06 UTC (permalink / raw)
  To: Ivo Van Doorn; +Cc: Yasushi SHOJI, helmut.schaa, hanada, linux-wireless

On 04/28/11 20:55, Ivo Van Doorn wrote:
> Hi,
> 
>> My colleague just tested this patch set and found out that the in
>> question makes our 400MHz ARM cpu board with ralink usb dongle non
>> functional due to high cpu consumption.  it seems for us that exiting
>> from function every time it finds an entry is too expensive on systems
>> slower than PCs.
> 
> Interesting, I would suspected the patch to reduce the CPU consumption
> rather then increasing it. I can do some testing regarding this looping
> during the weekend, but I haven't seen high CPU consumption on my
> system during my last test. However I wasn't testing on an embedded system...
> 
>> To verify our thought, we changed the source code as the patch below.
>> What we intended to do with this change is to continue processing all
>> entry without breaking semantics.
>>
>> With the patch below our board seem to work fine again, but not sure
>> exactly why it takes so much time to check the list again.  We are not
>> against the idea of the patch at all.  We just want to ask you guys
>> how we should go to track this problem. it might be the slow usb?
> 
> Could you try use debugfs and see if some queue and packet counters
> of mac80211/rt2x00 show excessive values?
> 
> Have you been running the test with powersaving enabled or disabled?
> 

Yeah, I had the same impression as Ivo, that it should save CPU cycles,
especially since the patch was submitted by Helmut, who is very keen
on saving CPU cycles, as he tests on an embedded (PCI-based) platform as
well.

But, if this proves to not be useful for now, then we should revert the
entire patch, as the patch proposed simply negates the intended behavior
and leaves a mess.

I believe the offending patch was preparation for another patch which so
far has not materialized in a usable form, so there should be no harm in
reverting the offending patch.
 
---
Gertjan

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 04/23] rt2x00: Make rt2x00_queue_entry_for_each more flexible
  2011-04-29  6:06           ` Gertjan van Wingerde
@ 2011-04-30 14:01             ` Ivo van Doorn
  2011-05-02 13:33               ` Yasushi SHOJI
  0 siblings, 1 reply; 37+ messages in thread
From: Ivo van Doorn @ 2011-04-30 14:01 UTC (permalink / raw)
  To: Gertjan van Wingerde; +Cc: Yasushi SHOJI, helmut.schaa, hanada, linux-wireless

Hi,

> >> My colleague just tested this patch set and found out that the in
> >> question makes our 400MHz ARM cpu board with ralink usb dongle non
> >> functional due to high cpu consumption.  it seems for us that exiting
> >> from function every time it finds an entry is too expensive on systems
> >> slower than PCs.
> > 
> > Interesting, I would suspected the patch to reduce the CPU consumption
> > rather then increasing it. I can do some testing regarding this looping
> > during the weekend, but I haven't seen high CPU consumption on my
> > system during my last test. However I wasn't testing on an embedded system...
> > 
> >> To verify our thought, we changed the source code as the patch below.
> >> What we intended to do with this change is to continue processing all
> >> entry without breaking semantics.
> >>
> >> With the patch below our board seem to work fine again, but not sure
> >> exactly why it takes so much time to check the list again.  We are not
> >> against the idea of the patch at all.  We just want to ask you guys
> >> how we should go to track this problem. it might be the slow usb?
> > 
> > Could you try use debugfs and see if some queue and packet counters
> > of mac80211/rt2x00 show excessive values?
> > 
> > Have you been running the test with powersaving enabled or disabled?
> > 
> 
> Yeah, I had the same impression as Ivo, that it should save CPU cycles,
> especially since the patch was submitted by Helmut, who is very keen
> on saving CPU cycles, as he tests on an embedded (PCI-based) platform as
> well.
> 
> But, if this proves to not be useful for now, then we should revert the
> entire patch, as the patch proposed simply negates the intended behavior
> and leaves a mess.
> 
> I believe the offending patch was preparation for another patch which so
> far has not materialized in a usable form, so there should be no harm in
> reverting the offending patch.

I've have a different idea, after a discussion with Helmut, I had changed his
original patch. But I think below patch should resolve the issue as well.

Yasushi, can you please test this patch.

Thanks,

Ivo
--
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index bfbb446..6b0ca7e 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -392,7 +392,7 @@ static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry, void* data)
 
 	if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
 	    test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
-		return true;
+		return false;
 
 	rt2x00lib_dmastart(entry);
 
@@ -447,7 +447,7 @@ static bool rt2x00usb_flush_entry(struct queue_entry *entry, void* data)
 	struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data;
 
 	if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
-		return true;
+		return false;
 
 	usb_kill_urb(entry_priv->urb);
 

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* Re: [PATCH 04/23] rt2x00: Make rt2x00_queue_entry_for_each more flexible
  2011-04-30 14:01             ` Ivo van Doorn
@ 2011-05-02 13:33               ` Yasushi SHOJI
  2011-05-02 19:24                 ` Ivo van Doorn
  0 siblings, 1 reply; 37+ messages in thread
From: Yasushi SHOJI @ 2011-05-02 13:33 UTC (permalink / raw)
  To: Ivo van Doorn; +Cc: Gertjan van Wingerde, helmut.schaa, hanada, linux-wireless

Hi Ivo,

At Sat, 30 Apr 2011 16:01:14 +0200,
Ivo van Doorn wrote:
>
> I've have a different idea, after a discussion with Helmut, I had changed his
> original patch. But I think below patch should resolve the issue as well.
>
> Yasushi, can you please test this patch.

We've tried your patch and the result is not as good as the original.
before we go into our test description, let me correct and add to my
previous comment:

 - CPU consumption was not an issue (sorry for wrong info. my bad)
 -- but network throughput performance is bad
 - USB controller on the CPU is not fast
 -- max throughput for USB memory read is about 50 Mbps on our test
 -- max client mode transfer rate is about 20 Mbps (at best)

all test is done on our Freescale i.MX25[1] ARM based board,
Armadillo-440[2], a440 for short, and using HostAP[3] and netpipe[4].
As you can see, we are using the board as an access point instead of
client mode.  this might have some impacts.

here is the summary of the test result we did:

               |ping pc -> a440    |netpipe
    -----------+-------------------+--------------------------------------
    original   |a few ms           |starts at a few Mbps to 18 Mbps
    flexible   |fast for small,    |error and exit on large packets
               |not work for large |
    ours       |a few ms           |starts at a few Mbps to 18 Mbps (same as orig)
    ivo's      |tens of ms         |works but less than 1.0 Mbps throughput

here "original" means 7dab73b37[5], just before flexible patch.
flexible is 10e11568ca[6].  ours is the patch I sent in the previous
mail[7], ivo's is s/true/false/ on rt2x00usb.c[8].

detailed test result is at the end of this email.

BTW, we are in the big holiday week[10] right now.  so please bear
with us. we might not reply promptly.

[1]:http://www.freescale.com/webapp/sps/site/overview.jsp?code=IMX25_FAMILY
[2]:http://www.atmark-techno.com/products/armadillo/a440/specs
[3]:http://hostap.epitest.fi/
[4]:http://www.scl.ameslab.gov/netpipe/

[5]:http://git.kernel.org/?p=linux/kernel/git/ivd/rt2x00.git;a=commit;h=7dab73b37f5e8885cb73efd25e73861f9b4f0246
[6]:http://git.kernel.org/?p=linux/kernel/git/ivd/rt2x00.git;a=commit;h=10e11568ca8b8a15f7478f6a4ceebabcbdba1018
[7]:http://article.gmane.org/gmane.linux.kernel.wireless.general/68843
[8]:http://article.gmane.org/gmane.linux.kernel.wireless.general/68987

[10]:http://en.wikipedia.org/wiki/Golden_Week_%28Japan%29

-------- detailed test results --------

flexible
========

right after windows client connected to the board with WPA2(AES)
----------------------------------------------------------------
$ cat /sys/kernel/debug/ieee80211/phy0/rt2800usb/queue/queue                    
qid     flags           count   limit   length  index   dma done        done    
14      0x00000001      61      128     128     61      61              61      
0       0x00000001      49      64      1       50      49              49      
1       0x00000001      0       64      0       0       0               0       
2       0x00000001      0       64      0       0       0               0       
3       0x00000001      0       64      0       0       0               0       
16      0x00000001      0       8       0       0       0               0       

right after four pings from windows client
------------------------------------------
$ cat /sys/kernel/debug/ieee80211/phy0/rt2800usb/queue/queue                    
qid     flags           count   limit   length  index   dma done        done    
14      0x00000001      226     128     128     98      98              98      
0       0x00000001      201     64      0       9       9               9       
1       0x00000001      0       64      0       0       0               0       
2       0x00000001      0       64      0       0       0               0       
3       0x00000001      0       64      0       0       0               0       
16      0x00000001      0       8       0       0       0               0       

NetPIPE
-------
$ NPtcp -h 192.168.40.101
  0:       1 bytes      3 times -->      0.01 Mbps in     814.67 usec           
  1:       2 bytes    122 times -->      0.00 Mbps in   10791.37 usec           
  2:       3 bytes      9 times -->      0.03 Mbps in     729.17 usec           
  3:       4 bytes     91 times --> 
(stopped...)



flexible + ivo patch
====================

right after windows client connected to the board with WPA2(AES)
----------------------------------------------------------------
$ cat /sys/kernel/debug/ieee80211/phy0/rt2800usb/queue/queue                    
qid     flags           count   limit   length  index   dma done        done    
14      0x00000001      83      128     128     83      83              83      
0       0x00000001      57      64      1       58      57              57      
1       0x00000001      0       64      0       0       0               0       
2       0x00000001      0       64      0       0       0               0       
3       0x00000001      0       64      0       0       0               0       
16      0x00000001      0       8       0       0       0               0       

right after four pings from windows client
------------------------------------------
$ cat /sys/kernel/debug/ieee80211/phy0/rt2800usb/queue/queue                    
qid     flags           count   limit   length  index   dma done        done    
14      0x00000001      173     128     128     45      45              45      
0       0x00000001      148     64      1       21      20              20      
1       0x00000001      0       64      0       0       0               0       
2       0x00000001      0       64      0       0       0               0       
3       0x00000001      0       64      0       0       0               0       
16      0x00000001      0       8       0       0       0               0       

NetPIPE
-------
$ NPtcp -h 192.168.40.101
  0:       1 bytes      3 times -->      0.00 Mbps in   83008.00 usec           
  1:       2 bytes      3 times -->      0.00 Mbps in   33693.33 usec           
  2:       3 bytes      3 times -->      0.00 Mbps in  240411.83 usec           
  3:       4 bytes      3 times -->      0.00 Mbps in   47299.17 usec           
  4:       6 bytes      3 times -->      0.00 Mbps in  179131.50 usec           
  5:       8 bytes      3 times -->      0.04 Mbps in    1588.50 usec           
  6:      12 bytes     39 times -->      0.02 Mbps in    3682.92 usec           
  7:      13 bytes     11 times -->      0.14 Mbps in     719.14 usec           
  8:      16 bytes     64 times -->      0.02 Mbps in    7699.98 usec           
  9:      19 bytes      7 times -->      0.20 Mbps in     735.07 usec           
 10:      21 bytes     85 times -->      0.02 Mbps in    6706.57 usec           
 11:      24 bytes      9 times -->      0.00 Mbps in  141140.44 usec           
 12:      27 bytes      3 times -->      0.00 Mbps in  166763.17 usec           
 13:      29 bytes      3 times -->      0.29 Mbps in     764.00 usec           
 14:      32 bytes     63 times -->      0.32 Mbps in     772.13 usec           
 15:      35 bytes     68 times -->      0.06 Mbps in    4222.35 usec           
 16:      45 bytes     13 times -->      0.48 Mbps in     721.85 usec           
 17:      48 bytes     92 times -->      0.03 Mbps in   11973.77 usec           
 18:      51 bytes      5 times -->      0.51 Mbps in     764.70 usec           
 19:      61 bytes     51 times -->      0.01 Mbps in   42452.69 usec           
 20:      64 bytes      3 times -->      0.57 Mbps in     852.17 usec           
 21:      67 bytes     60 times -->      0.02 Mbps in   20637.03 usec           
 22:      93 bytes      3 times -->      0.00 Mbps in 1000327.83 usec           
 23:      96 bytes      3 times -->      0.00 Mbps in  961784.50 usec           
 24:      99 bytes      3 times -->      0.00 Mbps in  497735.83 usec           
 25:     125 bytes      3 times -->      0.00 Mbps in  832843.50 usec           
 26:     128 bytes      3 times -->      0.00 Mbps in  204765.50 usec           
 27:     131 bytes      3 times -->      0.01 Mbps in  126846.00 usec           
 28:     189 bytes      3 times -->      0.05 Mbps in   27758.17 usec           
 29:     192 bytes      3 times -->      1.79 Mbps in     817.83 usec           
 30:     195 bytes     82 times --> 
(stopped...)



flexible + ours
===============

right after windows client connected to the board with WPA2(AES)
----------------------------------------------------------------
$ cat /sys/kernel/debug/ieee80211/phy0/rt2800usb/queue/queue                    
qid     flags           count   limit   length  index   dma done        done    
14      0x00000001      55      128     128     55      55              55      
0       0x00000001      41      64      0       41      41              41      
1       0x00000001      0       64      0       0       0               0       
2       0x00000001      0       64      0       0       0               0       
3       0x00000001      0       64      0       0       0               0       
16      0x00000001      0       8       0       0       0               0       

right after four pings from windows client
------------------------------------------
$ cat /sys/kernel/debug/ieee80211/phy0/rt2800usb/queue/queue                    
qid     flags           count   limit   length  index   dma done        done    
14      0x00000001      154     128     128     26      26              26      
0       0x00000001      140     64      0       12      12              12      
1       0x00000001      0       64      0       0       0               0       
2       0x00000001      0       64      0       0       0               0       
3       0x00000001      0       64      0       0       0               0       
16      0x00000001      0       8       0       0       0               0       

NetPIPE
-------
$ NPtcp -h 192.168.40.101
  0:       1 bytes    120 times -->      0.01 Mbps in     750.40 usec           
  1:       2 bytes    133 times -->      0.02 Mbps in     748.81 usec           
  2:       3 bytes    133 times -->      0.03 Mbps in     728.36 usec           
  3:       4 bytes     91 times -->      0.04 Mbps in     754.80 usec           
  4:       6 bytes     99 times -->      0.06 Mbps in     723.39 usec           
  5:       8 bytes     69 times -->      0.08 Mbps in     737.79 usec           
  6:      12 bytes     84 times -->      0.12 Mbps in     740.74 usec           
  7:      13 bytes     56 times -->      0.13 Mbps in     752.49 usec           
  8:      16 bytes     61 times -->      0.17 Mbps in     700.23 usec           
  9:      19 bytes     80 times -->      0.19 Mbps in     751.41 usec           
 10:      21 bytes     84 times -->      0.22 Mbps in     739.90 usec           
 11:      24 bytes     90 times -->      0.25 Mbps in     742.70 usec           
 12:      27 bytes     95 times -->      0.28 Mbps in     728.53 usec           
 13:      29 bytes     61 times -->      0.30 Mbps in     736.39 usec           
 14:      32 bytes     65 times -->      0.34 Mbps in     718.62 usec           
 15:      35 bytes     73 times -->      0.35 Mbps in     757.30 usec           
 16:      45 bytes     75 times -->      0.46 Mbps in     740.49 usec           
 17:      48 bytes     90 times -->      0.51 Mbps in     722.49 usec           
 18:      51 bytes     95 times -->      0.53 Mbps in     736.47 usec           
 19:      61 bytes     53 times -->      0.62 Mbps in     748.58 usec           
 20:      64 bytes     65 times -->      0.65 Mbps in     754.20 usec           
 21:      67 bytes     68 times -->      0.70 Mbps in     732.01 usec           
 22:      93 bytes     73 times -->      0.95 Mbps in     747.98 usec           
 23:      96 bytes     89 times -->      0.98 Mbps in     745.40 usec           
 24:      99 bytes     90 times -->      1.02 Mbps in     743.47 usec           
 25:     125 bytes     48 times -->      1.30 Mbps in     734.55 usec           
 26:     128 bytes     67 times -->      1.31 Mbps in     744.35 usec           
 27:     131 bytes     68 times -->      1.34 Mbps in     745.50 usec           
 28:     189 bytes     69 times -->      1.86 Mbps in     775.32 usec           
 29:     192 bytes     85 times -->      1.85 Mbps in     792.12 usec           
 30:     195 bytes     84 times -->      1.92 Mbps in     774.57 usec           
 31:     253 bytes     45 times -->      2.41 Mbps in     802.03 usec           
 32:     256 bytes     62 times -->      2.48 Mbps in     788.34 usec           
 33:     259 bytes     63 times -->      2.48 Mbps in     795.95 usec           
 34:     381 bytes     64 times -->      3.64 Mbps in     798.36 usec           
 35:     384 bytes     83 times -->      3.67 Mbps in     797.61 usec           
 36:     387 bytes     83 times -->      3.67 Mbps in     804.17 usec           
 37:     509 bytes     42 times -->      4.49 Mbps in     865.31 usec           
 38:     512 bytes     57 times -->      4.57 Mbps in     854.59 usec           
 39:     515 bytes     58 times -->      4.58 Mbps in     857.14 usec           
 40:     765 bytes     58 times -->      6.61 Mbps in     883.34 usec           
 41:     768 bytes     75 times -->      6.77 Mbps in     865.93 usec           
 42:     771 bytes     77 times -->      6.62 Mbps in     888.43 usec           
 43:    1021 bytes     37 times -->      8.30 Mbps in     939.04 usec           
 44:    1024 bytes     53 times -->      8.17 Mbps in     955.88 usec           
 45:    1027 bytes     52 times -->      8.06 Mbps in     972.20 usec           
 46:    1533 bytes     51 times -->      7.66 Mbps in    1525.97 usec           
 47:    1536 bytes     43 times -->      7.46 Mbps in    1570.44 usec           
 48:    1539 bytes     42 times -->      7.60 Mbps in    1545.51 usec           
 49:    2045 bytes     21 times -->     10.09 Mbps in    1546.31 usec           
 50:    2048 bytes     32 times -->      9.75 Mbps in    1601.77 usec           
 51:    2051 bytes     31 times -->      9.83 Mbps in    1592.16 usec           
 52:    3069 bytes     31 times -->     12.37 Mbps in    1892.11 usec           
 53:    3072 bytes     35 times -->     12.31 Mbps in    1904.36 usec           
 54:    3075 bytes     35 times -->     12.02 Mbps in    1952.34 usec           
 55:    4093 bytes     17 times -->     15.79 Mbps in    1977.85 usec           
 56:    4096 bytes     25 times -->     15.37 Mbps in    2032.76 usec           
 57:    4099 bytes     24 times -->     15.10 Mbps in    2070.98 usec           
 58:    6141 bytes     24 times -->     13.74 Mbps in    3410.75 usec           
 59:    6144 bytes     19 times -->     13.72 Mbps in    3417.03 usec           
 60:    6147 bytes     19 times -->     13.80 Mbps in    3397.32 usec           
 61:    8189 bytes      9 times -->     15.29 Mbps in    4086.61 usec           
 62:    8192 bytes     12 times -->     14.93 Mbps in    4185.71 usec           
 63:    8195 bytes     11 times -->     14.99 Mbps in    4170.91 usec           
 64:   12285 bytes     11 times -->     15.38 Mbps in    6095.45 usec           
 65:   12288 bytes     10 times -->     16.12 Mbps in    5814.15 usec           
 66:   12291 bytes     11 times -->     16.20 Mbps in    5790.18 usec           
 67:   16381 bytes      5 times -->     16.05 Mbps in    7787.10 usec           
 68:   16384 bytes      6 times -->     15.27 Mbps in    8187.83 usec           
 69:   16387 bytes      6 times -->     16.26 Mbps in    7686.83 usec           
 70:   24573 bytes      6 times -->     16.59 Mbps in   11301.75 usec           
 71:   24576 bytes      5 times -->     17.07 Mbps in   10982.60 usec           
 72:   24579 bytes      6 times -->     17.46 Mbps in   10737.75 usec           
 73:   32765 bytes      3 times -->     17.40 Mbps in   14369.67 usec           
 74:   32768 bytes      3 times -->     17.83 Mbps in   14019.67 usec           
 75:   32771 bytes      3 times -->     17.34 Mbps in   14418.17 usec           
 76:   49149 bytes      3 times -->     17.16 Mbps in   21856.33 usec           
 77:   49152 bytes      3 times -->     17.06 Mbps in   21987.50 usec           
 78:   49155 bytes      3 times -->     17.27 Mbps in   21715.00 usec           
 79:   65533 bytes      3 times -->     17.92 Mbps in   27894.50 usec           
 80:   65536 bytes      3 times -->     17.52 Mbps in   28542.00 usec           
 81:   65539 bytes      3 times -->     17.55 Mbps in   28490.00 usec           
 82:   98301 bytes      3 times -->     17.94 Mbps in   41802.83 usec           
 83:   98304 bytes      3 times -->     16.13 Mbps in   46505.17 usec           
 84:   98307 bytes      3 times -->     17.44 Mbps in   43001.00 usec           
 85:  131069 bytes      3 times -->     17.74 Mbps in   56360.50 usec           
 86:  131072 bytes      3 times -->     18.14 Mbps in   55120.33 usec           
 87:  131075 bytes      3 times -->     18.08 Mbps in   55323.17 usec           
 88:  196605 bytes      3 times -->     17.87 Mbps in   83919.67 usec           
 89:  196608 bytes      3 times -->     16.90 Mbps in   88738.67 usec           
 90:  196611 bytes      3 times -->     17.73 Mbps in   84627.00 usec           
 91:  262141 bytes      3 times -->     17.84 Mbps in  112088.50 usec           
 92:  262144 bytes      3 times -->     17.58 Mbps in  113748.67 usec           
 93:  262147 bytes      3 times -->     17.88 Mbps in  111867.67 usec           
 94:  393213 bytes      3 times -->     17.27 Mbps in  173754.83 usec           
 95:  393216 bytes      3 times -->     17.55 Mbps in  170984.50 usec           
 96:  393219 bytes      3 times -->     17.86 Mbps in  167983.67 usec           
 97:  524285 bytes      3 times -->     17.47 Mbps in  228930.00 usec           
 98:  524288 bytes      3 times -->     16.85 Mbps in  237405.00 usec           
 99:  524291 bytes      3 times -->     16.75 Mbps in  238756.33 usec           
100:  786429 bytes      3 times -->     17.27 Mbps in  347394.50 usec           
101:  786432 bytes      3 times -->     17.11 Mbps in  350626.17 usec           
102:  786435 bytes      3 times -->     16.84 Mbps in  356215.50 usec           
103: 1048573 bytes      3 times -->     17.57 Mbps in  455389.83 usec           
104: 1048576 bytes      3 times -->     17.07 Mbps in  468556.83 usec           
105: 1048579 bytes      3 times -->     17.47 Mbps in  457837.50 usec           
106: 1572861 bytes      3 times -->     16.99 Mbps in  706165.00 usec           
107: 1572864 bytes      3 times -->     17.47 Mbps in  686900.50 usec           
108: 1572867 bytes      3 times -->     17.91 Mbps in  670021.00 usec           
109: 2097149 bytes      3 times -->     16.74 Mbps in  955773.67 usec           
110: 2097152 bytes      3 times -->     16.97 Mbps in  942824.67 usec           
111: 2097155 bytes      3 times -->     17.30 Mbps in  925022.67 usec           
112: 3145725 bytes      3 times -->     17.39 Mbps in 1379715.33 usec           
113: 3145728 bytes      3 times -->     17.06 Mbps in 1406779.83 usec           
114: 3145731 bytes      3 times -->     17.30 Mbps in 1387511.17 usec           
(done successfully)
--
           Yashi

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 04/23] rt2x00: Make rt2x00_queue_entry_for_each more flexible
  2011-05-02 13:33               ` Yasushi SHOJI
@ 2011-05-02 19:24                 ` Ivo van Doorn
  2011-05-09  8:08                   ` Yasushi SHOJI
  0 siblings, 1 reply; 37+ messages in thread
From: Ivo van Doorn @ 2011-05-02 19:24 UTC (permalink / raw)
  To: Yasushi SHOJI; +Cc: Gertjan van Wingerde, helmut.schaa, hanada, linux-wireless

Hi,
 
>  - CPU consumption was not an issue (sorry for wrong info. my bad)
>  -- but network throughput performance is bad
>  - USB controller on the CPU is not fast
>  -- max throughput for USB memory read is about 50 Mbps on our test
>  -- max client mode transfer rate is about 20 Mbps (at best)

Ah ok, as CPU consumption is not the problem, then I better understand the problem.
My previous patch missed one fix for a return value. Could you try this one.

> BTW, we are in the big holiday week[10] right now.  so please bear
> with us. we might not reply promptly.

Not a problem. Have fun this week. :)

Thanks,

Ivo
---
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index e027ebd..dc6b662 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -298,7 +298,7 @@ static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry, void* data)
 
 	if (!test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags) ||
 	    test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
-		return true;
+		return false;
 
 	/*
 	 * USB devices cannot blindly pass the skb->len as the
@@ -392,7 +392,7 @@ static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry, void* data)
 
 	if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
 	    test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
-		return true;
+		return false;
 
 	rt2x00lib_dmastart(entry);
 
@@ -447,7 +447,7 @@ static bool rt2x00usb_flush_entry(struct queue_entry *entry, void* data)
 	struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data;
 
 	if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
-		return true;
+		return false;
 
 	usb_kill_urb(entry_priv->urb);
 

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* Re: [PATCH 04/23] rt2x00: Make rt2x00_queue_entry_for_each more flexible
  2011-05-02 19:24                 ` Ivo van Doorn
@ 2011-05-09  8:08                   ` Yasushi SHOJI
  2011-05-09  8:50                     ` Ivo Van Doorn
  0 siblings, 1 reply; 37+ messages in thread
From: Yasushi SHOJI @ 2011-05-09  8:08 UTC (permalink / raw)
  To: Ivo van Doorn; +Cc: Gertjan van Wingerde, helmut.schaa, hanada, linux-wireless

Hi,

At Mon, 2 May 2011 21:24:09 +0200,
Ivo van Doorn wrote:
> 
> >  - CPU consumption was not an issue (sorry for wrong info. my bad)
> >  -- but network throughput performance is bad
> >  - USB controller on the CPU is not fast
> >  -- max throughput for USB memory read is about 50 Mbps on our test
> >  -- max client mode transfer rate is about 20 Mbps (at best)
> 
> Ah ok, as CPU consumption is not the problem, then I better understand the problem.
> My previous patch missed one fix for a return value. Could you try this one.

it works like a charm!  you can put a tested-by tag on this patch. :-)

here is the log, just in case.

  0:       1 bytes    152 times -->      0.01 Mbps in     636.50 usec           
  1:       2 bytes    157 times -->      0.02 Mbps in     623.46 usec           
  2:       3 bytes    160 times -->      0.04 Mbps in     635.17 usec           
  3:       4 bytes    104 times -->      0.05 Mbps in     630.07 usec           
  4:       6 bytes    119 times -->      0.07 Mbps in     627.37 usec           
  5:       8 bytes     79 times -->      0.10 Mbps in     638.94 usec           
  6:      12 bytes     97 times -->      0.14 Mbps in     632.43 usec           
  7:      13 bytes     65 times -->      0.15 Mbps in     642.17 usec           
  8:      16 bytes     71 times -->      0.19 Mbps in     644.30 usec           
  9:      19 bytes     87 times -->      0.23 Mbps in     638.12 usec           
 10:      21 bytes     98 times -->      0.26 Mbps in     628.27 usec           
 11:      24 bytes    106 times -->      0.29 Mbps in     640.48 usec           
 12:      27 bytes    110 times -->      0.32 Mbps in     640.86 usec           
 13:      29 bytes     69 times -->      0.34 Mbps in     652.47 usec           
 14:      32 bytes     73 times -->      0.38 Mbps in     636.44 usec           
 15:      35 bytes     83 times -->      0.41 Mbps in     643.99 usec           
 16:      45 bytes     88 times -->      0.53 Mbps in     652.65 usec           
 17:      48 bytes    102 times -->      0.57 Mbps in     640.93 usec           
 18:      51 bytes    107 times -->      0.61 Mbps in     636.09 usec           
 19:      61 bytes     61 times -->      0.71 Mbps in     656.20 usec           
 20:      64 bytes     74 times -->      0.76 Mbps in     645.27 usec           
 21:      67 bytes     79 times -->      0.80 Mbps in     638.46 usec           
 22:      93 bytes     84 times -->      1.08 Mbps in     654.99 usec           
 23:      96 bytes    101 times -->      1.11 Mbps in     660.91 usec           
 24:      99 bytes    102 times -->      1.14 Mbps in     661.90 usec           
 25:     125 bytes     54 times -->      1.47 Mbps in     648.71 usec           
 26:     128 bytes     76 times -->      1.47 Mbps in     662.16 usec           
 27:     131 bytes     76 times -->      1.48 Mbps in     674.74 usec           
 28:     189 bytes     76 times -->      2.12 Mbps in     679.56 usec           
 29:     192 bytes     98 times -->      2.18 Mbps in     671.52 usec           
 30:     195 bytes    100 times -->      2.25 Mbps in     660.97 usec           
 31:     253 bytes     52 times -->      2.65 Mbps in     728.64 usec           
 32:     256 bytes     68 times -->      2.80 Mbps in     696.39 usec           
 33:     259 bytes     72 times -->      2.79 Mbps in     707.86 usec           
 34:     381 bytes     71 times -->      4.02 Mbps in     722.25 usec           
 35:     384 bytes     92 times -->      4.03 Mbps in     726.59 usec           
 36:     387 bytes     92 times -->      4.07 Mbps in     725.15 usec           
 37:     509 bytes     47 times -->      5.34 Mbps in     726.62 usec           
 38:     512 bytes     68 times -->      5.11 Mbps in     764.62 usec           
 39:     515 bytes     65 times -->      5.31 Mbps in     739.70 usec           
 40:     765 bytes     68 times -->      7.25 Mbps in     804.85 usec           
 41:     768 bytes     82 times -->      7.43 Mbps in     788.91 usec           
 42:     771 bytes     84 times -->      7.35 Mbps in     800.44 usec           
 43:    1021 bytes     42 times -->      9.23 Mbps in     844.04 usec           
 44:    1024 bytes     59 times -->      9.09 Mbps in     859.82 usec           
 45:    1027 bytes     58 times -->      9.08 Mbps in     862.79 usec           
 46:    1533 bytes     58 times -->      8.38 Mbps in    1395.98 usec           
 47:    1536 bytes     47 times -->      8.51 Mbps in    1377.14 usec           
 48:    1539 bytes     48 times -->      8.35 Mbps in    1405.50 usec           
 49:    2045 bytes     23 times -->     11.05 Mbps in    1411.89 usec           
 50:    2048 bytes     35 times -->     10.68 Mbps in    1463.26 usec           
 51:    2051 bytes     34 times -->     10.59 Mbps in    1477.41 usec           
 52:    3069 bytes     33 times -->     12.50 Mbps in    1873.76 usec           
 53:    3072 bytes     35 times -->     12.46 Mbps in    1881.50 usec           
 54:    3075 bytes     35 times -->     12.82 Mbps in    1829.67 usec           
 55:    4093 bytes     18 times -->     15.42 Mbps in    2025.56 usec           
 56:    4096 bytes     24 times -->     15.19 Mbps in    2056.62 usec           
 57:    4099 bytes     24 times -->     15.14 Mbps in    2065.52 usec           
 58:    6141 bytes     24 times -->     14.95 Mbps in    3133.44 usec           
 59:    6144 bytes     21 times -->     14.77 Mbps in    3174.33 usec           
 60:    6147 bytes     21 times -->     15.32 Mbps in    3061.95 usec           
 61:    8189 bytes     10 times -->     15.69 Mbps in    3981.60 usec           
 62:    8192 bytes     12 times -->     15.60 Mbps in    4005.46 usec           
 63:    8195 bytes     12 times -->     15.23 Mbps in    4104.79 usec           
 64:   12285 bytes     12 times -->     16.35 Mbps in    5731.54 usec           
 65:   12288 bytes     11 times -->     15.95 Mbps in    5877.59 usec           
 66:   12291 bytes     11 times -->     16.70 Mbps in    5615.00 usec           
 67:   16381 bytes      5 times -->     16.08 Mbps in    7770.10 usec           
 68:   16384 bytes      6 times -->     16.31 Mbps in    7662.92 usec           
 69:   16387 bytes      6 times -->     16.35 Mbps in    7645.50 usec           
 70:   24573 bytes      6 times -->     17.68 Mbps in   10605.92 usec           
 71:   24576 bytes      6 times -->     17.15 Mbps in   10930.00 usec           
 72:   24579 bytes      6 times -->     17.19 Mbps in   10907.83 usec           
 73:   32765 bytes      3 times -->     17.30 Mbps in   14453.17 usec           
 74:   32768 bytes      3 times -->     17.91 Mbps in   13956.67 usec           
 75:   32771 bytes      3 times -->     17.83 Mbps in   14023.33 usec           
 76:   49149 bytes      3 times -->     17.47 Mbps in   21468.17 usec           
 77:   49152 bytes      3 times -->     17.82 Mbps in   21048.17 usec           
 78:   49155 bytes      3 times -->     17.54 Mbps in   21384.67 usec           
 79:   65533 bytes      3 times -->     17.86 Mbps in   27996.33 usec           
 80:   65536 bytes      3 times -->     17.58 Mbps in   28433.50 usec           
 81:   65539 bytes      3 times -->     17.63 Mbps in   28366.50 usec           
 82:   98301 bytes      3 times -->     17.87 Mbps in   41966.67 usec           
 83:   98304 bytes      3 times -->     16.70 Mbps in   44917.83 usec           
 84:   98307 bytes      3 times -->     17.90 Mbps in   41894.33 usec           
 85:  131069 bytes      3 times -->     17.60 Mbps in   56809.17 usec           
 86:  131072 bytes      3 times -->     17.90 Mbps in   55871.83 usec           
 87:  131075 bytes      3 times -->     17.91 Mbps in   55821.17 usec           
 88:  196605 bytes      3 times -->     17.53 Mbps in   85542.50 usec           
 89:  196608 bytes      3 times -->     17.76 Mbps in   84443.33 usec           
 90:  196611 bytes      3 times -->     17.70 Mbps in   84745.83 usec           
 91:  262141 bytes      3 times -->     17.50 Mbps in  114315.50 usec           
 92:  262144 bytes      3 times -->     17.30 Mbps in  115606.00 usec           
 93:  262147 bytes      3 times -->     17.53 Mbps in  114096.50 usec           
 94:  393213 bytes      3 times -->     17.09 Mbps in  175546.83 usec           
 95:  393216 bytes      3 times -->     17.68 Mbps in  169663.67 usec           
 96:  393219 bytes      3 times -->     17.36 Mbps in  172796.83 usec           
 97:  524285 bytes      3 times -->     17.73 Mbps in  225642.83 usec           
 98:  524288 bytes      3 times -->     17.24 Mbps in  232031.17 usec           
 99:  524291 bytes      3 times -->     17.50 Mbps in  228568.83 usec           
100:  786429 bytes      3 times -->     17.31 Mbps in  346536.33 usec           
101:  786432 bytes      3 times -->     17.46 Mbps in  343555.00 usec           
102:  786435 bytes      3 times -->     17.47 Mbps in  343362.00 usec           
103: 1048573 bytes      3 times -->     17.50 Mbps in  457247.83 usec           
104: 1048576 bytes      3 times -->     17.37 Mbps in  460508.33 usec           
105: 1048579 bytes      3 times -->     17.58 Mbps in  455134.50 usec           
106: 1572861 bytes      3 times -->     16.59 Mbps in  723288.00 usec           
107: 1572864 bytes      3 times -->     17.55 Mbps in  683682.50 usec           
108: 1572867 bytes      3 times -->     17.43 Mbps in  688538.00 usec           
109: 2097149 bytes      3 times -->     17.32 Mbps in  923881.67 usec           
110: 2097152 bytes      3 times -->     17.26 Mbps in  926999.17 usec           
111: 2097155 bytes      3 times -->     17.10 Mbps in  935760.17 usec           
112: 3145725 bytes      3 times -->     17.35 Mbps in 1383678.83 usec           
113: 3145728 bytes      3 times -->     17.22 Mbps in 1393693.17 usec           
114: 3145731 bytes      3 times -->     17.29 Mbps in 1387717.67 usec          

Thanks,
-- 
          yashi

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH 04/23] rt2x00: Make rt2x00_queue_entry_for_each more flexible
  2011-05-09  8:08                   ` Yasushi SHOJI
@ 2011-05-09  8:50                     ` Ivo Van Doorn
  0 siblings, 0 replies; 37+ messages in thread
From: Ivo Van Doorn @ 2011-05-09  8:50 UTC (permalink / raw)
  To: Yasushi SHOJI; +Cc: Gertjan van Wingerde, helmut.schaa, hanada, linux-wireless

Hi,

> At Mon, 2 May 2011 21:24:09 +0200,
> Ivo van Doorn wrote:
>>
>> >  - CPU consumption was not an issue (sorry for wrong info. my bad)
>> >  -- but network throughput performance is bad
>> >  - USB controller on the CPU is not fast
>> >  -- max throughput for USB memory read is about 50 Mbps on our test
>> >  -- max client mode transfer rate is about 20 Mbps (at best)
>>
>> Ah ok, as CPU consumption is not the problem, then I better understand the problem.
>> My previous patch missed one fix for a return value. Could you try this one.
>
> it works like a charm!  you can put a tested-by tag on this patch. :-)

Good news. :)
The patch has been sent upstream, it has already been picked up in
wireless-testing.git
and wireless-next-2.6.git a few days ago but hasn't yet by the
compat-wireless package.
So if all goes correct, the compat-wireless package which will be
generated today will
contain the fix.

Ivo

^ permalink raw reply	[flat|nested] 37+ messages in thread

end of thread, other threads:[~2011-05-09  8:51 UTC | newest]

Thread overview: 37+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-04-18 13:26 [PATCH 01/23] Enable WLAN LED on Ralink SoC (rt305x) devices Ivo van Doorn
2011-04-18 13:26 ` [PATCH 02/23] rt2x00: Fix stuck queue in tx failure case Ivo van Doorn
2011-04-18 13:27   ` [PATCH 03/23] rt2x00: Split rt2x00dev->flags Ivo van Doorn
2011-04-18 13:27     ` [PATCH 04/23] rt2x00: Make rt2x00_queue_entry_for_each more flexible Ivo van Doorn
2011-04-18 13:28       ` [PATCH 05/23] rt2x00: Use correct TBTT_SYNC config in AP mode Ivo van Doorn
2011-04-18 13:28         ` [PATCH 06/23] rt2x00: Update TX_SW_CFG2 init value Ivo van Doorn
2011-04-18 13:28           ` [PATCH 07/23] rt2x00: Use TXOP_HTTXOP for beacons Ivo van Doorn
2011-04-18 13:29             ` [PATCH 08/23] rt2800usb: read TX_STA_FIFO asynchronously Ivo van Doorn
2011-04-18 13:29               ` [PATCH 09/23] rt2x00: fix queue timeout checks Ivo van Doorn
2011-04-18 13:30                 ` [PATCH 10/23] rt2800usb: handle TX status timeouts Ivo van Doorn
2011-04-18 13:30                   ` [PATCH 11/23] rt2800usb: add timer to handle TX_STA_FIFO Ivo van Doorn
2011-04-18 13:31                     ` [PATCH 12/23] Decrease association time for USB devices Ivo van Doorn
2011-04-18 13:31                       ` [PATCH 13/23] rt2x00: Always inline rt2x00pci_enable_interrupt Ivo van Doorn
2011-04-18 13:31                         ` [PATCH 14/23] rt2x00: Linksys WUSB600N rev2 is a RT3572 device Ivo van Doorn
2011-04-18 13:32                           ` [PATCH 15/23] rt2x00: Allow dynamic addition of PCI/USB IDs Ivo van Doorn
2011-04-18 13:32                             ` [PATCH 16/23] rt2x00: Add USB IDs Ivo van Doorn
2011-04-18 13:33                               ` [PATCH 17/23] rt2x00: RT33xx device support is no longer experimental Ivo van Doorn
2011-04-18 13:33                                 ` [PATCH 18/23] rt2x00: Enable support for RT53xx PCI devices by default Ivo van Doorn
2011-04-18 13:33                                   ` [PATCH 19/23] rt2x00: Merge rt2x00ht.c contents in other files Ivo van Doorn
2011-04-18 13:34                                     ` [PATCH 20/23] rt2x00: Optimize register access in rt2800pci Ivo van Doorn
2011-04-18 13:34                                       ` [PATCH 21/23] rt2x00: Optimize register access in rt2800usb Ivo van Doorn
2011-04-18 13:34                                         ` [PATCH 22/23] rt2x00: Implement get_ringparam callback function Ivo van Doorn
2011-04-18 13:35                                           ` [PATCH 23/23] rt2x00: Implement get_antenna and set_antenna callback functions Ivo van Doorn
2011-04-18 13:56                                         ` [PATCH 21/23] rt2x00: Optimize register access in rt2800usb Rafał Miłecki
2011-04-18 14:06                                           ` Ivo Van Doorn
2011-04-18 14:14                                             ` Rafał Miłecki
2011-04-18 14:48                                             ` Helmut Schaa
2011-04-18 15:02                                               ` Rafał Miłecki
2011-04-28  2:55       ` [PATCH 04/23] rt2x00: Make rt2x00_queue_entry_for_each more flexible Yasushi SHOJI
2011-04-28  2:55       ` Yasushi SHOJI
2011-04-28 18:55         ` Ivo Van Doorn
2011-04-29  6:06           ` Gertjan van Wingerde
2011-04-30 14:01             ` Ivo van Doorn
2011-05-02 13:33               ` Yasushi SHOJI
2011-05-02 19:24                 ` Ivo van Doorn
2011-05-09  8:08                   ` Yasushi SHOJI
2011-05-09  8:50                     ` Ivo Van Doorn

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).