Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH] rt2x00: Fix RF3052 channel initialization
From: Ivo van Doorn @ 2010-05-06 12:45 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless, users

Update channel initialization for the RF3052 chipset.
According to the Ralink drivers, the rt3x array must be
used for this chipset, rather then the rt2x array.

Furthermore RF3052 supports the 5GHz band, extend
the rt3x array with the 5GHz channels, and use them
for the RF3052 chip.

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

diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index e37bbea..6c0abc3 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -2219,7 +2219,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
 EXPORT_SYMBOL_GPL(rt2800_init_eeprom);
 
 /*
- * RF value list for rt28x0
+ * RF value list for rt28xx
  * Supports: 2.4 GHz (all) & 5.2 GHz (RF2850 & RF2750)
  */
 static const struct rf_channel rf_vals[] = {
@@ -2294,10 +2294,10 @@ static const struct rf_channel rf_vals[] = {
 };
 
 /*
- * RF value list for rt3070
- * Supports: 2.4 GHz
+ * RF value list for rt3xxx
+ * Supports: 2.4 GHz (all) & 5.2 GHz (RF3052)
  */
-static const struct rf_channel rf_vals_302x[] = {
+static const struct rf_channel rf_vals_3x[] = {
 	{1,  241, 2, 2 },
 	{2,  241, 2, 7 },
 	{3,  242, 2, 2 },
@@ -2312,6 +2312,51 @@ static const struct rf_channel rf_vals_302x[] = {
 	{12, 246, 2, 7 },
 	{13, 247, 2, 2 },
 	{14, 248, 2, 4 },
+
+	/* 802.11 UNI / HyperLan 2 */
+	{36, 0x56, 0, 4},
+	{38, 0x56, 0, 6},
+	{40, 0x56, 0, 8},
+	{44, 0x57, 0, 0},
+	{46, 0x57, 0, 2},
+	{48, 0x57, 0, 4},
+	{52, 0x57, 0, 8},
+	{54, 0x57, 0, 10},
+	{56, 0x58, 0, 0},
+	{60, 0x58, 0, 4},
+	{62, 0x58, 0, 6},
+	{64, 0x58, 0, 8},
+
+	/* 802.11 HyperLan 2 */
+	{100, 0x5b, 0, 8},
+	{102, 0x5b, 0, 10},
+	{104, 0x5c, 0, 0},
+	{108, 0x5c, 0, 4},
+	{110, 0x5c, 0, 6},
+	{112, 0x5c, 0, 8},
+	{116, 0x5d, 0, 0},
+	{118, 0x5d, 0, 2},
+	{120, 0x5d, 0, 4},
+	{124, 0x5d, 0, 8},
+	{126, 0x5d, 0, 10},
+	{128, 0x5e, 0, 0},
+	{132, 0x5e, 0, 4},
+	{134, 0x5e, 0, 6},
+	{136, 0x5e, 0, 8},
+	{140, 0x5f, 0, 0},
+
+	/* 802.11 UNII */
+	{149, 0x5f, 0, 9},
+	{151, 0x5f, 0, 11},
+	{153, 0x60, 0, 1},
+	{157, 0x60, 0, 5},
+	{159, 0x60, 0, 7},
+	{161, 0x60, 0, 9},
+	{165, 0x61, 0, 1},
+	{167, 0x61, 0, 3},
+	{169, 0x61, 0, 5},
+	{171, 0x61, 0, 7},
+	{173, 0x61, 0, 9},
 };
 
 int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
@@ -2352,11 +2397,11 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 	spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
 
 	if (rt2x00_rf(rt2x00dev, RF2820) ||
-	    rt2x00_rf(rt2x00dev, RF2720) ||
-	    rt2x00_rf(rt2x00dev, RF3052)) {
+	    rt2x00_rf(rt2x00dev, RF2720)) {
 		spec->num_channels = 14;
 		spec->channels = rf_vals;
-	} else if (rt2x00_rf(rt2x00dev, RF2850) || rt2x00_rf(rt2x00dev, RF2750)) {
+	} else if (rt2x00_rf(rt2x00dev, RF2850) ||
+		   rt2x00_rf(rt2x00dev, RF2750)) {
 		spec->supported_bands |= SUPPORT_BAND_5GHZ;
 		spec->num_channels = ARRAY_SIZE(rf_vals);
 		spec->channels = rf_vals;
@@ -2364,8 +2409,12 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 		   rt2x00_rf(rt2x00dev, RF2020) ||
 		   rt2x00_rf(rt2x00dev, RF3021) ||
 		   rt2x00_rf(rt2x00dev, RF3022)) {
-		spec->num_channels = ARRAY_SIZE(rf_vals_302x);
-		spec->channels = rf_vals_302x;
+		spec->num_channels = 14;
+		spec->channels = rf_vals_3x;
+	} else if (rt2x00_rf(rt2x00dev, RF3052)) {
+		spec->supported_bands |= SUPPORT_BAND_5GHZ;
+		spec->num_channels = ARRAY_SIZE(rf_vals_3x);
+		spec->channels = rf_vals_3x;
 	}
 
 	/*
-- 
1.6.6.1


^ permalink raw reply related

* Re: [PATCH] rt2x00: Add 5GHz support for RF3052 devices
From: Ivo Van Doorn @ 2010-05-06 12:06 UTC (permalink / raw)
  To: John Linville; +Cc: Gertjan van Wingerde, linux-wireless, users
In-Reply-To: <p2ha32f33a41005060422xe89addc7s1e4de3f36ebd3278@mail.gmail.com>

John,

Please drop this patch. I just talked with Gertjan and I will be
sending an updated patch in a few minutes.

Ivo

On Thu, May 6, 2010 at 1:22 PM, Ivo Van Doorn <ivdoorn@gmail.com> wrote:
> On Thu, May 6, 2010 at 1:12 PM, Gertjan van Wingerde
> <gwingerde@gmail.com> wrote:
>> On Thu, May 6, 2010 at 1:01 PM, Ivo van Doorn <ivdoorn@gmail.com> wrote:
>>> According to the Ralink drivers, the RF3052 chipset
>>> supports the 5GHz band. Update channel initialization
>>> to add the corresponding channels for this chip.
>>>
>>> Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
>>
>> Actually, I believe that this is not correct (sorry I don't have the
>> Ralink driver at hand at the moment, nor the rt2x00 tree).
>
> Well the original Ralink driver does state this device is a 5GHz device.
>
>> AFAIK the RF3052 needs the same initialization as for RF3020, RF3021,
>> RF3022, etc extended with the correct values for
>> 5GHz band.
>
> RF3020 and RF3021 are 2.4GHz devices.
>
>> So, NAK for this patch.
>>
>> Also, please keep in mind that for proper RT3572 support more needs to
>> be done, also in the register, BPP, and RFCSR initializations.
>
> It could be that the initialization of RF3052 is incomplete, however that is not
> limited to the 5GHz feature, but for both bands. Note that the
> difference in initialization
> only exists for settings the antenna and channel which already detect
> if the initialization
> should be done on the 2.4 or 5 GHz band.
> So this argument shouldn't block this patch...
>
> Ivo
>

^ permalink raw reply

* rt61pci: WEP broken in current wireless-testing
From: Pavel Roskin @ 2010-05-06 11:51 UTC (permalink / raw)
  To: linux-wireless

Hello!

Recent changes in wireless-testing have broken WEP support in rt61pci.  
  An older kernel from wireless-testing identified as 2.6.34-rc5-wl is  
working fine.

I'm using an x86_64 system.  The device is

Network controller [0280]: RaLink RT2561/RT61 rev B 802.11g [1814:0302]

The device is in managed mode.  I'm using WEP with a 40-bit key (I  
know it's ridiculously insecure, but it's not my choice).  With the  
current kernel, the association works, but no traffic is received by  
the station.

That's the relevant part of .config:

CONFIG_RT2X00=m
# CONFIG_RT2400PCI is not set
# CONFIG_RT2500PCI is not set
CONFIG_RT61PCI=m
CONFIG_RT2800PCI_PCI=y
# CONFIG_RT2800PCI is not set
# CONFIG_RT2500USB is not set
# CONFIG_RT73USB is not set
# CONFIG_RT2800USB is not set
CONFIG_RT2X00_LIB_PCI=m
CONFIG_RT2X00_LIB=m
CONFIG_RT2X00_LIB_FIRMWARE=y
CONFIG_RT2X00_LIB_CRYPTO=y
CONFIG_RT2X00_LIB_LEDS=y
CONFIG_RT2X00_LIB_DEBUGFS=y
CONFIG_RT2X00_DEBUG=y

arc4 support is compiled as a module and it's loaded.  I haven't seen  
anything unusual in the kernel log.

Curiously, I'm seeing some interesting warnings with the working  
kernel (2.6.34-rc5-wl).  They don't appear immediately, as you can see  
from the timestamps:

[   74.534338] phy1 -> rt2x00lib_request_firmware: Info - Loading  
firmware file 'rt2561.bin'.
[   74.534343] rt61pci 0000:04:03.0: firmware: requesting rt2561.bin
[   74.638978] phy1 -> rt2x00lib_request_firmware: Info - Firmware  
detected - version: 0.8.
[   74.801343] phy1 -> rt2x00mac_conf_tx: Info - Configured TX queue 0  
- CWmin: 3, CWmax: 4, Aifs: 2, TXop: 102.
[   74.801350] phy1 -> rt2x00mac_conf_tx: Info - Configured TX queue 1  
- CWmin: 4, CWmax: 5, Aifs: 2, TXop: 188.
[   74.801357] phy1 -> rt2x00mac_conf_tx: Info - Configured TX queue 2  
- CWmin: 5, CWmax: 10, Aifs: 3, TXop: 0.
[   74.801363] phy1 -> rt2x00mac_conf_tx: Info - Configured TX queue 3  
- CWmin: 5, CWmax: 10, Aifs: 7, TXop: 0.
[   81.212513] wlan2: authenticate with 00:23:97:5c:82:7e (try 1)
[   81.214001] wlan2: authenticated
[   81.250009] wlan2: associate with 00:23:97:5c:82:7e (try 1)
[   81.251750] wlan2: RX AssocResp from 00:23:97:5c:82:7e (capab=0x411  
status=0 aid=1)
[   81.251753] wlan2: associated
[   81.252014] phy1 -> rt2x00mac_conf_tx: Info - Configured TX queue 0  
- CWmin: 2, CWmax: 3, Aifs: 2, TXop: 47.
[   81.252020] phy1 -> rt2x00mac_conf_tx: Info - Configured TX queue 1  
- CWmin: 3, CWmax: 4, Aifs: 2, TXop: 94.
[   81.252027] phy1 -> rt2x00mac_conf_tx: Info - Configured TX queue 2  
- CWmin: 4, CWmax: 10, Aifs: 3, TXop: 0.
[   81.252034] phy1 -> rt2x00mac_conf_tx: Info - Configured TX queue 3  
- CWmin: 4, CWmax: 10, Aifs: 7, TXop: 0.
[  652.484017] phy1 -> rt61pci_txdone: Warning - TX status report  
missed for entry 15
[  652.970531] phy1 -> rt61pci_txdone: Warning - TX status report  
missed for entry 2

It's should be rather straightforward to bisect, but I'll be away from  
that system until next Monday.

-- 
Regards,
Pavel Roskin

^ permalink raw reply

* Re: [PATCH] rt2x00: Add 5GHz support for RF3052 devices
From: Ivo Van Doorn @ 2010-05-06 11:22 UTC (permalink / raw)
  To: Gertjan van Wingerde; +Cc: John Linville, linux-wireless, users
In-Reply-To: <s2o14add3d11005060412xf64df988x239517f049930d58@mail.gmail.com>

On Thu, May 6, 2010 at 1:12 PM, Gertjan van Wingerde
<gwingerde@gmail.com> wrote:
> On Thu, May 6, 2010 at 1:01 PM, Ivo van Doorn <ivdoorn@gmail.com> wrote:
>> According to the Ralink drivers, the RF3052 chipset
>> supports the 5GHz band. Update channel initialization
>> to add the corresponding channels for this chip.
>>
>> Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
>
> Actually, I believe that this is not correct (sorry I don't have the
> Ralink driver at hand at the moment, nor the rt2x00 tree).

Well the original Ralink driver does state this device is a 5GHz device.

> AFAIK the RF3052 needs the same initialization as for RF3020, RF3021,
> RF3022, etc extended with the correct values for
> 5GHz band.

RF3020 and RF3021 are 2.4GHz devices.

> So, NAK for this patch.
>
> Also, please keep in mind that for proper RT3572 support more needs to
> be done, also in the register, BPP, and RFCSR initializations.

It could be that the initialization of RF3052 is incomplete, however that is not
limited to the 5GHz feature, but for both bands. Note that the
difference in initialization
only exists for settings the antenna and channel which already detect
if the initialization
should be done on the 2.4 or 5 GHz band.
So this argument shouldn't block this patch...

Ivo

^ permalink raw reply

* Re: [PATCH] rt2x00: Add 5GHz support for RF3052 devices
From: Gertjan van Wingerde @ 2010-05-06 11:12 UTC (permalink / raw)
  To: Ivo van Doorn; +Cc: John Linville, linux-wireless, users
In-Reply-To: <201005061301.22323.IvDoorn@gmail.com>

On Thu, May 6, 2010 at 1:01 PM, Ivo van Doorn <ivdoorn@gmail.com> wrote:
> According to the Ralink drivers, the RF3052 chipset
> supports the 5GHz band. Update channel initialization
> to add the corresponding channels for this chip.
>
> Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>

Actually, I believe that this is not correct (sorry I don't have the
Ralink driver at hand at the moment, nor the rt2x00 tree).
AFAIK the RF3052 needs the same initialization as for RF3020, RF3021,
RF3022, etc extended with the correct values for
5GHz band.

So, NAK for this patch.

Also, please keep in mind that for proper RT3572 support more needs to
be done, also in the register, BPP, and RFCSR initializations.

> ---
>  drivers/net/wireless/rt2x00/rt2800lib.c |    9 +++++----
>  1 files changed, 5 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
> index e7a61a3..0d6f715 100644
> --- a/drivers/net/wireless/rt2x00/rt2800lib.c
> +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
> @@ -2223,7 +2223,7 @@ EXPORT_SYMBOL_GPL(rt2800_init_eeprom);
>
>  /*
>  * RF value list for rt28x0
> - * Supports: 2.4 GHz (all) & 5.2 GHz (RF2850 & RF2750)
> + * Supports: 2.4 GHz (all) & 5.2 GHz (RF2850, RF2750 & RF3052)
>  */
>  static const struct rf_channel rf_vals[] = {
>        { 1,  0x18402ecc, 0x184c0786, 0x1816b455, 0x1800510b },
> @@ -2355,11 +2355,12 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
>        spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
>
>        if (rt2x00_rf(rt2x00dev, RF2820) ||
> -           rt2x00_rf(rt2x00dev, RF2720) ||
> -           rt2x00_rf(rt2x00dev, RF3052)) {
> +           rt2x00_rf(rt2x00dev, RF2720)) {
>                spec->num_channels = 14;
>                spec->channels = rf_vals;
> -       } else if (rt2x00_rf(rt2x00dev, RF2850) || rt2x00_rf(rt2x00dev, RF2750)) {
> +       } else if (rt2x00_rf(rt2x00dev, RF2850) ||
> +                  rt2x00_rf(rt2x00dev, RF2750) ||
> +                  rt2x00_rf(rt2x00dev, RF3052)) {
>                spec->supported_bands |= SUPPORT_BAND_5GHZ;
>                spec->num_channels = ARRAY_SIZE(rf_vals);
>                spec->channels = rf_vals;
> --
> 1.6.6.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply

* [PATCH] rt2x00: Add 5GHz support for RF3052 devices
From: Ivo van Doorn @ 2010-05-06 11:01 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless, users

According to the Ralink drivers, the RF3052 chipset
supports the 5GHz band. Update channel initialization
to add the corresponding channels for this chip.

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

diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index e7a61a3..0d6f715 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -2223,7 +2223,7 @@ EXPORT_SYMBOL_GPL(rt2800_init_eeprom);
 
 /*
  * RF value list for rt28x0
- * Supports: 2.4 GHz (all) & 5.2 GHz (RF2850 & RF2750)
+ * Supports: 2.4 GHz (all) & 5.2 GHz (RF2850, RF2750 & RF3052)
  */
 static const struct rf_channel rf_vals[] = {
 	{ 1,  0x18402ecc, 0x184c0786, 0x1816b455, 0x1800510b },
@@ -2355,11 +2355,12 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 	spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
 
 	if (rt2x00_rf(rt2x00dev, RF2820) ||
-	    rt2x00_rf(rt2x00dev, RF2720) ||
-	    rt2x00_rf(rt2x00dev, RF3052)) {
+	    rt2x00_rf(rt2x00dev, RF2720)) {
 		spec->num_channels = 14;
 		spec->channels = rf_vals;
-	} else if (rt2x00_rf(rt2x00dev, RF2850) || rt2x00_rf(rt2x00dev, RF2750)) {
+	} else if (rt2x00_rf(rt2x00dev, RF2850) ||
+		   rt2x00_rf(rt2x00dev, RF2750) ||
+		   rt2x00_rf(rt2x00dev, RF3052)) {
 		spec->supported_bands |= SUPPORT_BAND_5GHZ;
 		spec->num_channels = ARRAY_SIZE(rf_vals);
 		spec->channels = rf_vals;
-- 
1.6.6.1


^ permalink raw reply related

* Re: [PATCH 2/3] rt2x00: rt2800: don't overwrite SIFS values on erp changes
From: Helmut Schaa @ 2010-05-06 10:56 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless, Ivo van Doorn, Gertjan van Wingerde
In-Reply-To: <201005061251.09142.helmut.schaa@googlemail.com>

Am Donnerstag 06 Mai 2010 schrieb Helmut Schaa:
> Nevertheless I don't get good transfer speeds. I didn't measure exactly but
> just with scp. And I got ~600-700 KByte/s for TX and 400-500KByte/s for RX.
> This is still quite low.

Nevermind, tested on a MIPS board. So maybe it's not the wireless but the CPU
that's limiting scp performance.

When I find some time I'll try plain TCP connections.

Helmut

^ permalink raw reply

* Re: [PATCH 2/3] rt2x00: rt2800: don't overwrite SIFS values on erp changes
From: Helmut Schaa @ 2010-05-06 10:51 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless, Ivo van Doorn, Gertjan van Wingerde
In-Reply-To: <201005061229.44923.helmut.schaa@googlemail.com>

JFI, with this and the previous patch I can reliable transmit and receive
data at 11b and 11g rates with only sporadic retries. Before that I had a
huge amount of retries while transmitting with 11g rates (and enabled CTS
protection).

Nevertheless I don't get good transfer speeds. I didn't measure exactly but
just with scp. And I got ~600-700 KByte/s for TX and 400-500KByte/s for RX.
This is still quite low.

Helmut

Am Donnerstag 06 Mai 2010 schrieb Helmut Schaa:
> The SIFS value is a constant and doesn't need to be updated on erp changes.
> Furthermore the code used 10us for both, the OFDM SIFS and CCK SIFS time
> which broke CTS protected 11g connections (see patch "rt2x00: rt2800: update
> initial SIFS values" for details).
> 
> Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
> ---
>  drivers/net/wireless/rt2x00/rt2800lib.c |    2 --
>  1 files changed, 0 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
> index f786068..858455f 100644
> --- a/drivers/net/wireless/rt2x00/rt2800lib.c
> +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
> @@ -640,8 +640,6 @@ void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp)
>  	rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg);
>  
>  	rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, &reg);
> -	rt2x00_set_field32(&reg, XIFS_TIME_CFG_CCKM_SIFS_TIME, erp->sifs);
> -	rt2x00_set_field32(&reg, XIFS_TIME_CFG_OFDM_SIFS_TIME, erp->sifs);
>  	rt2x00_set_field32(&reg, XIFS_TIME_CFG_EIFS, erp->eifs);
>  	rt2800_register_write(rt2x00dev, XIFS_TIME_CFG, reg);
>  
> 


^ permalink raw reply

* [PATCH 3/3] rt2x00: rt2800: use correct txop value in tx descriptor
From: Helmut Schaa @ 2010-05-06 10:29 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless, Ivo van Doorn, Gertjan van Wingerde

rt2800 devices use a different enumeration to specify what IFS values should
be used on frame transmission compared to the other rt2x00 devices. Hence,
create a new enum called txop that contains the valid values.

Furthermore use TXOP_HTTXOP as default on HT devices which means that the
hardware should select the correct IFS value on its own.

I'm not sure if we have the need to specify one of the other txop values
in the future but as far as I could see TXOP_HTTXOP is used by the Ralink
drivers for all normal data frames and should be a reasonable default.

This patch doesn't really fix anything as until now the IFS_BACKOFF(=0)
value was used as txop which luckily mapped to TXOP_HTTXOP(=0).

Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
---
 drivers/net/wireless/rt2x00/rt2800pci.c   |    2 +-
 drivers/net/wireless/rt2x00/rt2800usb.c   |    2 +-
 drivers/net/wireless/rt2x00/rt2x00ht.c    |    2 ++
 drivers/net/wireless/rt2x00/rt2x00queue.h |    2 ++
 drivers/net/wireless/rt2x00/rt2x00reg.h   |   10 ++++++++++
 5 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index f08b6a3..df2c3fb 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -643,7 +643,7 @@ static int rt2800pci_write_tx_data(struct queue_entry* entry,
 	rt2x00_set_field32(&word, TXWI_W0_AMPDU,
 			   test_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags));
 	rt2x00_set_field32(&word, TXWI_W0_MPDU_DENSITY, txdesc->mpdu_density);
-	rt2x00_set_field32(&word, TXWI_W0_TX_OP, txdesc->ifs);
+	rt2x00_set_field32(&word, TXWI_W0_TX_OP, txdesc->txop);
 	rt2x00_set_field32(&word, TXWI_W0_MCS, txdesc->mcs);
 	rt2x00_set_field32(&word, TXWI_W0_BW,
 			   test_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags));
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index e3f3a97..c9e1320 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -417,7 +417,7 @@ static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
 	rt2x00_set_field32(&word, TXWI_W0_AMPDU,
 			   test_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags));
 	rt2x00_set_field32(&word, TXWI_W0_MPDU_DENSITY, txdesc->mpdu_density);
-	rt2x00_set_field32(&word, TXWI_W0_TX_OP, txdesc->ifs);
+	rt2x00_set_field32(&word, TXWI_W0_TX_OP, txdesc->txop);
 	rt2x00_set_field32(&word, TXWI_W0_MCS, txdesc->mcs);
 	rt2x00_set_field32(&word, TXWI_W0_BW,
 			   test_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags));
diff --git a/drivers/net/wireless/rt2x00/rt2x00ht.c b/drivers/net/wireless/rt2x00/rt2x00ht.c
index 1056c92..5483fec 100644
--- a/drivers/net/wireless/rt2x00/rt2x00ht.c
+++ b/drivers/net/wireless/rt2x00/rt2x00ht.c
@@ -66,4 +66,6 @@ void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
 		__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);
+
+	txdesc->txop = TXOP_HTTXOP;
 }
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
index 94a48c1..36a957a 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -299,6 +299,7 @@ enum txentry_desc_flags {
  * @retry_limit: Max number of retries.
  * @aifs: AIFS value.
  * @ifs: IFS value.
+ * @txop: IFS value for 11n capable chips.
  * @cw_min: cwmin value.
  * @cw_max: cwmax value.
  * @cipher: Cipher type used for encryption.
@@ -328,6 +329,7 @@ struct txentry_desc {
 	short retry_limit;
 	short aifs;
 	short ifs;
+	short txop;
 	short cw_min;
 	short cw_max;
 
diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h
index 603bfc0..894ff78 100644
--- a/drivers/net/wireless/rt2x00/rt2x00reg.h
+++ b/drivers/net/wireless/rt2x00/rt2x00reg.h
@@ -101,6 +101,16 @@ enum ifs {
 };
 
 /*
+ * IFS values for HT devices
+ */
+enum txop {
+	TXOP_HTTXOP = 0,
+	TXOP_PIFS = 1,
+	TXOP_SIFS = 2,
+	TXOP_BACKOFF = 3,
+};
+
+/*
  * Cipher types for hardware encryption
  */
 enum cipher {
-- 
1.6.4.2


^ permalink raw reply related

* [PATCH 2/3] rt2x00: rt2800: don't overwrite SIFS values on erp changes
From: Helmut Schaa @ 2010-05-06 10:29 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless, Ivo van Doorn, Gertjan van Wingerde

The SIFS value is a constant and doesn't need to be updated on erp changes.
Furthermore the code used 10us for both, the OFDM SIFS and CCK SIFS time
which broke CTS protected 11g connections (see patch "rt2x00: rt2800: update
initial SIFS values" for details).

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

diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index f786068..858455f 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -640,8 +640,6 @@ void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp)
 	rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg);
 
 	rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, &reg);
-	rt2x00_set_field32(&reg, XIFS_TIME_CFG_CCKM_SIFS_TIME, erp->sifs);
-	rt2x00_set_field32(&reg, XIFS_TIME_CFG_OFDM_SIFS_TIME, erp->sifs);
 	rt2x00_set_field32(&reg, XIFS_TIME_CFG_EIFS, erp->eifs);
 	rt2800_register_write(rt2x00dev, XIFS_TIME_CFG, reg);
 
-- 
1.6.4.2


^ permalink raw reply related

* [PATCH 1/3] rt2x00: rt2800: update initial SIFS values
From: Helmut Schaa @ 2010-05-06 10:29 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless, Ivo van Doorn, Gertjan van Wingerde

Currently the CCK and OFDM SIFS value is set to 32us. This value is neither
used by the Ralink driver nor specified in 802.11.

Instead of using 10us for CCK SIFS (as defined in 802.11) use 16us like in the
Ralink drivers. And indeed using a SIFS value of 10us breaks connectivity with
11g + CTS protected connections. Add a comment to the code why we don't use 10us
for CCK SIFS value.

The OFDM SIFS value is set to 16us (as defined in 802.11 and also used by the
Ralink drivers).

Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
---
 drivers/net/wireless/rt2x00/rt2800lib.c |   11 +++++++++--
 1 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index e37bbea..f786068 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -1415,9 +1415,16 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 
 	rt2800_register_write(rt2x00dev, EXP_ACK_TIME, 0x002400ca);
 
+	/*
+	 * Usually the CCK SIFS time should be set to 10 and the OFDM SIFS
+	 * time should be set to 16. However, the original Ralink driver uses
+	 * 16 for both and indeed using a value of 10 for CCK SIFS results in
+	 * connection problems with 11g + CTS protection. Hence, use the same
+	 * defaults as the Ralink driver: 16 for both, CCK and OFDM SIFS.
+	 */
 	rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, &reg);
-	rt2x00_set_field32(&reg, XIFS_TIME_CFG_CCKM_SIFS_TIME, 32);
-	rt2x00_set_field32(&reg, XIFS_TIME_CFG_OFDM_SIFS_TIME, 32);
+	rt2x00_set_field32(&reg, XIFS_TIME_CFG_CCKM_SIFS_TIME, 16);
+	rt2x00_set_field32(&reg, XIFS_TIME_CFG_OFDM_SIFS_TIME, 16);
 	rt2x00_set_field32(&reg, XIFS_TIME_CFG_OFDM_XIFS_TIME, 4);
 	rt2x00_set_field32(&reg, XIFS_TIME_CFG_EIFS, 314);
 	rt2x00_set_field32(&reg, XIFS_TIME_CFG_BB_RXEND_ENABLE, 1);
-- 
1.6.4.2


^ permalink raw reply related

* Re: [RFC/RFT] ssb: resolve alternate SPROM offset for 14e4:4315
From: Michael Buesch @ 2010-05-06 10:01 UTC (permalink / raw)
  To: b43-dev; +Cc: Larry Finger, linux-wireless
In-Reply-To: <201005061153.01488.mb@bu3sch.de>

On Thursday 06 May 2010 11:53:01 Michael Buesch wrote:
> On Thursday 06 May 2010 07:00:13 Larry Finger wrote:
> > This patch and the patch by Gabor entitled "[PATCH] ssb: Implement
> > fast powerup delay calculation" are enough to allow the netbook from
> > John to work with ssb/b43. As this patch tampers with the SPROM offset for
> > 14e4:4315 devices, it should be tested by anyone with an LP PHY that works
> > to ensure that it is not killed.
> > 
> > The essential elements of this patch will also be tested as part of kernel Bug
> > #15825.
> > 
> > Larry
> >  
> > Index: wireless-testing/drivers/ssb/pci.c
> > ===================================================================
> > --- wireless-testing.orig/drivers/ssb/pci.c
> > +++ wireless-testing/drivers/ssb/pci.c
> > @@ -631,8 +631,17 @@ static int ssb_pci_sprom_get(struct ssb_
> >  		return -ENODEV;
> >  	}
> >  
> > -	bus->sprom_offset = (bus->chipco.dev->id.revision < 31) ?
> > -		SSB_SPROM_BASE1 : SSB_SPROM_BASE31;
> > +	/* get SPROM offset: SSB_SPROM_BASE1 except for chipcommon rev >= 31
> > +	 * or chip ID is 0x4312 and bit 0x2 is set in chipcommon status
> > +	 */
> > +	if (bus->chipco.dev->id.revision >= 31)
> > +		bus->sprom_offset = SSB_SPROM_BASE31;
> > +	else if (bus->chip_id == 0x4312 && (bus->chipco.status & 0x02))
> > +		bus->sprom_offset = SSB_SPROM_BASE31;
> > +	else
> > +		bus->sprom_offset = SSB_SPROM_BASE1;
> > +
> > +	ssb_dprintk(KERN_INFO PFX "SPROM offset is 0x%x\n", bus->sprom_offset);
> >  
> >  	buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
> >  	if (!buf)
> > Index: wireless-testing/drivers/ssb/scan.c
> > ===================================================================
> > --- wireless-testing.orig/drivers/ssb/scan.c
> > +++ wireless-testing/drivers/ssb/scan.c
> > @@ -306,6 +306,11 @@ int ssb_bus_scan(struct ssb_bus *bus,
> >  		}
> >  		tmp = scan_read32(bus, 0, SSB_CHIPCO_CAP);
> >  		bus->chipco.capabilities = tmp;
> > +		if (bus->chip_rev >= 11)
> 
> This still is wrong. the chip_rev is not the chipcommon core revision.

Although technically in most (all?) cases it might be the same number.
I'm not sure on that one.
But it is read from an entirely different register and I think it's plain
wrong to assume that chip_rev equals the chipcommon core rev.

> We already went through this and we decided to read the chipstat later.
> Read it in chipcommon init. The bus scan is _way_ too early to read this.
> 
> > +			bus->chipco.status = scan_read32(bus, 0,
> > +					     SSB_CHIPCO_CHIPSTAT);
> > +		else
> > +			bus->chipco.status = 0;
> >  	} else {
> >  		if (bus->bustype == SSB_BUSTYPE_PCI) {
> >  			bus->chip_id = pcidev_to_chipid(bus->host_pci);
> > 
> > 
> 
> 

-- 
Greetings, Michael.

^ permalink raw reply

* Re: [RFC/RFT] ssb: resolve alternate SPROM offset for 14e4:4315
From: Michael Buesch @ 2010-05-06  9:53 UTC (permalink / raw)
  To: Larry Finger; +Cc: John W Linville, b43-dev, linux-wireless
In-Reply-To: <4be24cdd.Yg6pH2Z4OwSotB+K%Larry.Finger@lwfinger.net>

On Thursday 06 May 2010 07:00:13 Larry Finger wrote:
> This patch and the patch by Gabor entitled "[PATCH] ssb: Implement
> fast powerup delay calculation" are enough to allow the netbook from
> John to work with ssb/b43. As this patch tampers with the SPROM offset for
> 14e4:4315 devices, it should be tested by anyone with an LP PHY that works
> to ensure that it is not killed.
> 
> The essential elements of this patch will also be tested as part of kernel Bug
> #15825.
> 
> Larry
>  
> Index: wireless-testing/drivers/ssb/pci.c
> ===================================================================
> --- wireless-testing.orig/drivers/ssb/pci.c
> +++ wireless-testing/drivers/ssb/pci.c
> @@ -631,8 +631,17 @@ static int ssb_pci_sprom_get(struct ssb_
>  		return -ENODEV;
>  	}
>  
> -	bus->sprom_offset = (bus->chipco.dev->id.revision < 31) ?
> -		SSB_SPROM_BASE1 : SSB_SPROM_BASE31;
> +	/* get SPROM offset: SSB_SPROM_BASE1 except for chipcommon rev >= 31
> +	 * or chip ID is 0x4312 and bit 0x2 is set in chipcommon status
> +	 */
> +	if (bus->chipco.dev->id.revision >= 31)
> +		bus->sprom_offset = SSB_SPROM_BASE31;
> +	else if (bus->chip_id == 0x4312 && (bus->chipco.status & 0x02))
> +		bus->sprom_offset = SSB_SPROM_BASE31;
> +	else
> +		bus->sprom_offset = SSB_SPROM_BASE1;
> +
> +	ssb_dprintk(KERN_INFO PFX "SPROM offset is 0x%x\n", bus->sprom_offset);
>  
>  	buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
>  	if (!buf)
> Index: wireless-testing/drivers/ssb/scan.c
> ===================================================================
> --- wireless-testing.orig/drivers/ssb/scan.c
> +++ wireless-testing/drivers/ssb/scan.c
> @@ -306,6 +306,11 @@ int ssb_bus_scan(struct ssb_bus *bus,
>  		}
>  		tmp = scan_read32(bus, 0, SSB_CHIPCO_CAP);
>  		bus->chipco.capabilities = tmp;
> +		if (bus->chip_rev >= 11)

This still is wrong. the chip_rev is not the chipcommon core revision.
We already went through this and we decided to read the chipstat later.
Read it in chipcommon init. The bus scan is _way_ too early to read this.

> +			bus->chipco.status = scan_read32(bus, 0,
> +					     SSB_CHIPCO_CHIPSTAT);
> +		else
> +			bus->chipco.status = 0;
>  	} else {
>  		if (bus->bustype == SSB_BUSTYPE_PCI) {
>  			bus->chip_id = pcidev_to_chipid(bus->host_pci);
> 
> 

-- 
Greetings, Michael.

^ permalink raw reply

* [PATCH] ath9k_htc: Fix beaconing in IBSS mode
From: Sujith @ 2010-05-06  9:15 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless

The current way of managing beaconing in ad-hoc
mode has a subtle race - the beacon obtained from mac80211
is freed in the SWBA handler rather than the TX
completion routine. But transmission of beacons goes
through the normal SKB queue maintained in hif_usb,
leading to a situation where __skb_dequeue() in the TX
completion handler goes kaput.

Fix this by simply getting a beacon from mac80211 for
every SWBA and free it in its completion routine.

Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
---
 drivers/net/wireless/ath/ath9k/htc.h            |    5 +--
 drivers/net/wireless/ath/ath9k/htc_drv_beacon.c |   39 ++++++-----------------
 drivers/net/wireless/ath/ath9k/htc_drv_init.c   |    2 +-
 drivers/net/wireless/ath/ath9k/htc_drv_main.c   |   12 -------
 4 files changed, 13 insertions(+), 45 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index 1ae18bb..ad556aa 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -356,7 +356,6 @@ struct ath9k_htc_priv {
 	u16 seq_no;
 	u32 bmiss_cnt;
 
-	struct sk_buff *beacon;
 	spinlock_t beacon_lock;
 
 	bool tx_queues_stop;
@@ -408,13 +407,13 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz)
 void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv,
 			     struct ieee80211_vif *vif);
 void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending);
-void ath9k_htc_beacon_update(struct ath9k_htc_priv *priv,
-			     struct ieee80211_vif *vif);
 
 void ath9k_htc_rxep(void *priv, struct sk_buff *skb,
 		    enum htc_endpoint_id ep_id);
 void ath9k_htc_txep(void *priv, struct sk_buff *skb, enum htc_endpoint_id ep_id,
 		    bool txok);
+void ath9k_htc_beaconep(void *drv_priv, struct sk_buff *skb,
+			enum htc_endpoint_id ep_id, bool txok);
 
 void ath9k_htc_station_work(struct work_struct *work);
 void ath9k_htc_aggr_work(struct work_struct *work);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
index 7cb55f5..c10c7d0 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
@@ -165,22 +165,10 @@ static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv,
 	WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask);
 }
 
-void ath9k_htc_beacon_update(struct ath9k_htc_priv *priv,
-			     struct ieee80211_vif *vif)
+void ath9k_htc_beaconep(void *drv_priv, struct sk_buff *skb,
+			enum htc_endpoint_id ep_id, bool txok)
 {
-	struct ath_common *common = ath9k_hw_common(priv->ah);
-
-	spin_lock_bh(&priv->beacon_lock);
-
-	if (priv->beacon)
-		dev_kfree_skb_any(priv->beacon);
-
-	priv->beacon = ieee80211_beacon_get(priv->hw, vif);
-	if (!priv->beacon)
-		ath_print(common, ATH_DBG_BEACON,
-			  "Unable to allocate beacon\n");
-
-	spin_unlock_bh(&priv->beacon_lock);
+	dev_kfree_skb_any(skb);
 }
 
 void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending)
@@ -189,6 +177,7 @@ void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending)
 	struct tx_beacon_header beacon_hdr;
 	struct ath9k_htc_tx_ctl tx_ctl;
 	struct ieee80211_tx_info *info;
+	struct sk_buff *beacon;
 	u8 *tx_fhdr;
 
 	memset(&beacon_hdr, 0, sizeof(struct tx_beacon_header));
@@ -207,25 +196,17 @@ void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending)
 		return;
 	}
 
-	if (unlikely(priv->beacon == NULL)) {
-		spin_unlock_bh(&priv->beacon_lock);
-		return;
-	}
-
-	/* Free the old SKB first */
-	dev_kfree_skb_any(priv->beacon);
-
 	/* Get a new beacon */
-	priv->beacon = ieee80211_beacon_get(priv->hw, priv->vif);
-	if (!priv->beacon) {
+	beacon = ieee80211_beacon_get(priv->hw, priv->vif);
+	if (!beacon) {
 		spin_unlock_bh(&priv->beacon_lock);
 		return;
 	}
 
-	info = IEEE80211_SKB_CB(priv->beacon);
+	info = IEEE80211_SKB_CB(beacon);
 	if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
 		struct ieee80211_hdr *hdr =
-			(struct ieee80211_hdr *) priv->beacon->data;
+			(struct ieee80211_hdr *) beacon->data;
 		priv->seq_no += 0x10;
 		hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
 		hdr->seq_ctrl |= cpu_to_le16(priv->seq_no);
@@ -233,10 +214,10 @@ void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending)
 
 	tx_ctl.type = ATH9K_HTC_NORMAL;
 	beacon_hdr.vif_index = avp->index;
-	tx_fhdr = skb_push(priv->beacon, sizeof(beacon_hdr));
+	tx_fhdr = skb_push(beacon, sizeof(beacon_hdr));
 	memcpy(tx_fhdr, (u8 *) &beacon_hdr, sizeof(beacon_hdr));
 
-	htc_send(priv->htc, priv->beacon, priv->beacon_ep, &tx_ctl);
+	htc_send(priv->htc, beacon, priv->beacon_ep, &tx_ctl);
 
 	spin_unlock_bh(&priv->beacon_lock);
 }
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index 701f2ef..17111fc 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -144,7 +144,7 @@ static int ath9k_init_htc_services(struct ath9k_htc_priv *priv)
 		goto err;
 
 	/* Beacon */
-	ret = ath9k_htc_connect_svc(priv, WMI_BEACON_SVC, NULL,
+	ret = ath9k_htc_connect_svc(priv, WMI_BEACON_SVC, ath9k_htc_beaconep,
 				    &priv->beacon_ep);
 	if (ret)
 		goto err;
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index ca7f3a7..7c9e33b 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -1313,15 +1313,6 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw,
 	priv->nvifs--;
 
 	ath9k_htc_remove_station(priv, vif, NULL);
-
-	if (vif->type == NL80211_IFTYPE_ADHOC) {
-		spin_lock_bh(&priv->beacon_lock);
-		if (priv->beacon)
-			dev_kfree_skb_any(priv->beacon);
-		priv->beacon = NULL;
-		spin_unlock_bh(&priv->beacon_lock);
-	}
-
 	priv->vif = NULL;
 
 	mutex_unlock(&priv->mutex);
@@ -1590,9 +1581,6 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
 		ath9k_htc_beacon_config(priv, vif);
 	}
 
-	if (changed & BSS_CHANGED_BEACON)
-		ath9k_htc_beacon_update(priv, vif);
-
 	if ((changed & BSS_CHANGED_BEACON_ENABLED) &&
 	    !bss_conf->enable_beacon) {
 		priv->op_flags &= ~OP_ENABLE_BEACON;
-- 
1.7.0.5


^ permalink raw reply related

* Re: kernel BUG in iwl-agn-rs.c:2076, WAS: iwlagn + some accesspoint == hardlock
From: Christian Borntraeger @ 2010-05-06  9:14 UTC (permalink / raw)
  To: John W. Linville
  Cc: NilsRadtkelkml, linux-kernel, reinette.chatre, linux-wireless
In-Reply-To: <20100503192219.GE25748@tuxdriver.com>

Am Montag 03 Mai 2010 21:22:19 schrieb John W. Linville:
> >   /* Sanity-check TPT calculations */
> >   BUG_ON(window->average_tpt != ((window->success_ratio *
> >       tbl->expected_tpt[index] + 64) / 128));
> 
> Interestingly enough, we have been discussing this line of code today.  Could you try the patch here?
> 
> 	http://marc.info/?l=linux-wireless&m=127290931304496&w=2

I also see a hard lockup some time after connection to my companies
wireless network. My private network does not seem to trigger that bug.
Unfortunately the kernel is not able to switch back graphics, so I 
cannot tell if I see the same BUG - even if the problem description is 
the same.
For reference, the patch above  does not help on my T61p.

It started soon after 2.6.34-rc4. Before and with rc4 I had to
apply this http://patchwork.ozlabs.org/patch/49850/mbox/ patch to avoid
the other crash. With only this patch on top of rc4 everything seemed to
work fine, so the lockup seems to be triggered by one of the other patches.
Sometimes it takes some minutes to crash, which makes it hard to bisect
the problem.

Christian

^ permalink raw reply

* Re: [PATCH 07/11] ath9k_htc: Use USB reboot
From: Sujith @ 2010-05-06  9:12 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linville@tuxdriver.com, linux-wireless@vger.kernel.org
In-Reply-To: <87zl0mjkx7.fsf@purkki.valot.fi>

Kalle Valo wrote:
> Sujith <Sujith.Manoharan@atheros.com> writes:
> 
> > So, apparently there is a USB reboot command
> > that the target accepts. Using this instead of
> > usb_reset_device() fixes the issue of "descriptor read error"
> > that pops up on repeated load/unload.
> 
> [...]
> 
> > +static void ath9k_hif_usb_reboot(struct usb_device *udev)
> > +{
> > +	u32 reboot_cmd = 0xffffffff;
> 
> A define for the actual command value would be nice here.

Sorry, I was out and John has merged this patch.
Will do this later, thanks for the review.

Sujith

^ permalink raw reply

* Re: [PATCH 1/2] mac80211: add offload channel switch support
From: Johannes Berg @ 2010-05-06  7:44 UTC (permalink / raw)
  To: wey-yi.w.guy; +Cc: linux-wireless
In-Reply-To: <1273116842-27189-1-git-send-email-wey-yi.w.guy@intel.com>

Sorry, just thought of something.

On Wed, 2010-05-05 at 20:34 -0700, wey-yi.w.guy@intel.com wrote:

> + * @timestamp: value in microseconds of the 64-bit Time Synchronization
> + *	Function (TSF) timer when the channel switch ie received.

This is not accurate now but see below.

> +		if (beacon)
> +			timestamp = le64_to_cpu(mgmt->u.beacon.timestamp);
> +		else
> +			timestamp = le64_to_cpu(mgmt->u.probe_resp.timestamp);
> +		ieee80211_sta_process_chanswitch(sdata, sw_elem,
> +						 bss, timestamp);
>  	}
>  }
>  
> @@ -1647,7 +1691,8 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
>  
>  			ieee80211_sta_process_chanswitch(sdata,
>  					&mgmt->u.action.u.chan_switch.sw_elem,
> -					(void *)ifmgd->associated->priv);
> +					(void *)ifmgd->associated->priv,
> +					rx_status->mactime);

For some reason I didn't notice the action frame handling before. Maybe
it would be more consistent to keep using rx_status->mactime even for
beacons? I apologise, this is totally my fault since I suggested using
the beacon time before, but that has a slightly different value relative
to the frame... Hmm. Maybe it would be better after all to require
drivers to provide mactime at least for mgmt frames (beacons + actions)
when they want to implement this callback.

Anyone else have ideas?

johannes


^ permalink raw reply

* Re: [PATCH v2] mac80211: Add HT IE to IBSS beacons and probe responses.
From: Johannes Berg @ 2010-05-06  6:40 UTC (permalink / raw)
  To: Benoit Papillault; +Cc: linux-wireless
In-Reply-To: <1273098986-19330-2-git-send-email-benoit.papillault@free.fr>

On Thu, 2010-05-06 at 00:36 +0200, Benoit Papillault wrote:
> When an HT IBSS is configured, we add HT Information and HT Capabilities
> IE to beacons & probe responses. This is done according to channel_type
> transmitted by iw/cfg80211.
> 
> v2: Added helpers to build HT Capability & HT Information IE

This line belongs after the --- so it's not part of the commit log.

>  	local->oper_channel = chan;
> -	local->oper_channel_type = NL80211_CHAN_NO_HT;
> +	local->oper_channel_type = channel_type;

It would be helpful if you were to rebase over my patch that adds the
channel type tracking.

> @@ -165,6 +169,14 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
>  		memcpy(pos, &supp_rates[8], rates);
>  	}
>  
> +	if (channel_type != NL80211_CHAN_NO_HT &&
> +	    sband->ht_cap.ht_supported) {

You shouldn't be able to get here with an HT channel but !ht_supported,
no? Or is that to support the case where you have HT only on one band?

> +	}
> +	  

trailing whitespace

> @@ -202,6 +214,9 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
>  	u32 basic_rates;
>  	int i, j;
>  	u16 beacon_int = cbss->beacon_interval;
> +	const u8 * ht_info_ie;

CodingStyle.

> @@ -223,9 +238,28 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
>  		}
>  	}
>  
> +	/* parse HT Information IE, if present */
> +	ht_info_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_INFORMATION);
> +	if (ht_info_ie) {
> +		ht_info = (const struct ieee80211_ht_info *)(ht_info_ie + 2);
> +		switch (ht_info->ht_param
> +			& IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {

The parser in mlme.c looks different. Please see there and also make it
a helper function.

> --- a/net/mac80211/ieee80211_i.h
> +++ b/net/mac80211/ieee80211_i.h
> @@ -404,6 +404,7 @@ struct ieee80211_if_ibss {
>  	u8 ssid_len, ie_len;
>  	u8 *ie;
>  	struct ieee80211_channel *channel;
> +	enum nl80211_channel_type channel_type;
>  
>  	unsigned long ibss_join_req;
>  	/* probe response/beacon for IBSS */
> @@ -1193,6 +1194,15 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
>  			 u16 transaction, u16 auth_alg,
>  			 u8 *extra, size_t extra_len, const u8 *bssid,
>  			 const u8 *key, u8 key_len, u8 key_idx);
> +
> +int ieee80211_add_ht_cap(u8 **ppos,
> +			 struct ieee80211_supported_band *sband);

The length is fixed anyway, so how about just passing in
	...(u8 *buffer, ... sband)

> +int ieee80211_add_ht_info(u8 **ppos,
> +			  struct ieee80211_supported_band *sband,
> +			  struct ieee80211_channel *channel,
> +			  enum nl80211_channel_type channel_type);

same here.

> --- a/net/mac80211/util.c
> +++ b/net/mac80211/util.c
> @@ -898,6 +898,82 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
>  	ieee80211_tx_skb(sdata, skb);
>  }
>  
> +int ieee80211_add_ht_cap(u8 **ppos,
> +			 struct ieee80211_supported_band *sband)
> +{

Actually ... please split up the patches.

 1) pure code moving from the mlme code to helper functions
 2) helper function rewrite using the structures, like you did
 3) this patch

> +	u16 cap = sband->ht_cap.cap;
> +	struct ieee80211_ht_cap ht_cap;
> +	u8 *pos = *ppos;
> +
> +	if (ieee80211_disable_40mhz_24ghz &&
> +	    sband->band == IEEE80211_BAND_2GHZ) {
> +		cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
> +		cap &= ~IEEE80211_HT_CAP_SGI_40;
> +	}
> +
> +	ht_cap.cap_info = cpu_to_le16(cap);
> +	ht_cap.ampdu_params_info = sband->ht_cap.ampdu_factor |
> +		(sband->ht_cap.ampdu_density <<
> +		 IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
> +	ht_cap.mcs = sband->ht_cap.mcs;
> +	ht_cap.extended_ht_cap_info = cpu_to_le16(0);
> +	ht_cap.tx_BF_cap_info = cpu_to_le32(0);
> +	ht_cap.antenna_selection_info = 0;
> +
> +	/* HT Capabilities element */
> +	*pos++ = WLAN_EID_HT_CAPABILITY;
> +	*pos++ = sizeof(struct ieee80211_ht_cap);
> +	memcpy(pos, &ht_cap, sizeof(struct ieee80211_ht_cap));
> +	pos += sizeof(struct ieee80211_ht_cap);
> +
> +	*ppos = pos;
> +
> +	return 1;

oh and get rid of the entirely useless return value.

> +}
> +
> +int ieee80211_add_ht_info(u8 **ppos,
> +			  struct ieee80211_supported_band *sband,
> +			  struct ieee80211_channel *channel,
> +			  enum nl80211_channel_type channel_type)

what's wrong with ieee80211_add_ht_ie()

Some more effort please! Patches with such _basic_ errors are no fun to
review!

johannes


^ permalink raw reply

* Re: [rt2x00-users] [PATCH 3/4] rt2x00: Fix HT40+/HT40- setting in rt2800.
From: Benoit Papillault @ 2010-05-06  6:26 UTC (permalink / raw)
  To: rt2x00 Users List; +Cc: Gertjan van Wingerde, John W. Linville, linux-wireless
In-Reply-To: <1272919385-18004-4-git-send-email-gwingerde@gmail.com>

Le 03/05/2010 22:43, Gertjan van Wingerde a écrit :
> Inspection of the Ralink vendor driver shows that the TX_BAND_CFG register
> and BBP register 3 are about HT40- indication, not about HT40+ indication.
> Inverse the meaning of these fields in the code.
>
> Signed-off-by: Gertjan van Wingerde<gwingerde@gmail.com>

Acked-by: Benoit Papillault <benoit.papillault@free.fr>

> ---
>   drivers/net/wireless/rt2x00/rt2800.h    |    4 ++--
>   drivers/net/wireless/rt2x00/rt2800lib.c |    4 ++--
>   2 files changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
> index 4c0b481..2aa0375 100644
> --- a/drivers/net/wireless/rt2x00/rt2800.h
> +++ b/drivers/net/wireless/rt2x00/rt2800.h
> @@ -845,7 +845,7 @@
>    * TX_BAND_CFG: 0x1 use upper 20MHz, 0x0 use lower 20MHz
>    */
>   #define TX_BAND_CFG			0x132c
> -#define TX_BAND_CFG_HT40_PLUS		FIELD32(0x00000001)
> +#define TX_BAND_CFG_HT40_MINUS		FIELD32(0x00000001)
>   #define TX_BAND_CFG_A			FIELD32(0x00000002)
>   #define TX_BAND_CFG_BG			FIELD32(0x00000004)
>
> @@ -1519,7 +1519,7 @@ struct mac_iveiv_entry {
>    * BBP 3: RX Antenna
>    */
>   #define BBP3_RX_ANTENNA			FIELD8(0x18)
> -#define BBP3_HT40_PLUS			FIELD8(0x20)
> +#define BBP3_HT40_MINUS			FIELD8(0x20)
>
>   /*
>    * BBP 4: Bandwidth
> diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
> index 7310f34..6d2c66d 100644
> --- a/drivers/net/wireless/rt2x00/rt2800lib.c
> +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
> @@ -867,7 +867,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
>   	}
>
>   	rt2800_register_read(rt2x00dev, TX_BAND_CFG,&reg);
> -	rt2x00_set_field32(&reg, TX_BAND_CFG_HT40_PLUS, conf_is_ht40_plus(conf));
> +	rt2x00_set_field32(&reg, TX_BAND_CFG_HT40_MINUS, conf_is_ht40_minus(conf));
>   	rt2x00_set_field32(&reg, TX_BAND_CFG_A, rf->channel>  14);
>   	rt2x00_set_field32(&reg, TX_BAND_CFG_BG, rf->channel<= 14);
>   	rt2800_register_write(rt2x00dev, TX_BAND_CFG, reg);
> @@ -900,7 +900,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
>   	rt2800_bbp_write(rt2x00dev, 4, bbp);
>
>   	rt2800_bbp_read(rt2x00dev, 3,&bbp);
> -	rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf));
> +	rt2x00_set_field8(&bbp, BBP3_HT40_MINUS, conf_is_ht40_minus(conf));
>   	rt2800_bbp_write(rt2x00dev, 3, bbp);
>
>   	if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) {


^ permalink raw reply

* Re: [PATCH v2] cfg80211/mac80211: better channel handling
From: Benoit Papillault @ 2010-05-06  5:46 UTC (permalink / raw)
  To: Johannes Berg; +Cc: John Linville, linux-wireless
In-Reply-To: <1273124159.3573.7.camel@jlt3.sipsolutions.net>

Le 06/05/2010 07:35, Johannes Berg a écrit :
> On Wed, 2010-05-05 at 22:58 +0200, Benoit Papillault wrote:
>
>> Real hardware are not capable of listening on multiple channels (except
>> 2 ht20 channels in ht40 mode, maybe?). So I don't understand why we
>> should have a per-interface channel.
>>
>> I think we should either have two strategies :
>>
>> - "first one is the winner" : once a channel has been set, it cannot be
>> changed. For instance, if you create an AP interface (with hostapd) and
>> latter a STA interface, the STA interface can only scan on the channel
>> the AP is.
>
> That's what you get now.
>
>> - "last one is the winner" : in this case, the last call to set the
>> channel is always successful. Of course, this will change channel on
>> existing interfaces which might change their IE accordingly, through an
>> appropriate API.
>
> That's pretty much impossible to implement with the current split
> between user and kernel space.
>
>> I might be wrong, but I don't see this multi-channel usage...
>
> Say you have two stations associated to two different APs. They can
> powersave while they are on the channel for the other AP. It'll be done,
> rather soon, trust me :)
>
> johannes

I understand now and I am impressed as well! I don't know how this could 
work in the details, but I trust you on this :-)

Regards,
Benoit

^ permalink raw reply

* Re: [PATCH v2] cfg80211/mac80211: better channel handling
From: Johannes Berg @ 2010-05-06  5:35 UTC (permalink / raw)
  To: Benoit Papillault; +Cc: John Linville, linux-wireless
In-Reply-To: <4BE1DBFE.2060909@free.fr>

On Wed, 2010-05-05 at 22:58 +0200, Benoit Papillault wrote:

> Real hardware are not capable of listening on multiple channels (except 
> 2 ht20 channels in ht40 mode, maybe?). So I don't understand why we 
> should have a per-interface channel.
> 
> I think we should either have two strategies :
> 
> - "first one is the winner" : once a channel has been set, it cannot be 
> changed. For instance, if you create an AP interface (with hostapd) and 
> latter a STA interface, the STA interface can only scan on the channel 
> the AP is.

That's what you get now.

> - "last one is the winner" : in this case, the last call to set the 
> channel is always successful. Of course, this will change channel on 
> existing interfaces which might change their IE accordingly, through an 
> appropriate API.

That's pretty much impossible to implement with the current split
between user and kernel space.

> I might be wrong, but I don't see this multi-channel usage...

Say you have two stations associated to two different APs. They can
powersave while they are on the channel for the other AP. It'll be done,
rather soon, trust me :)

johannes


^ permalink raw reply

* [RFC/RFT] ssb: resolve alternate SPROM offset for 14e4:4315
From: Larry Finger @ 2010-05-06  5:00 UTC (permalink / raw)
  To: John W Linville, Michael Buesch; +Cc: b43-dev, linux-wireless

This patch and the patch by Gabor entitled "[PATCH] ssb: Implement
fast powerup delay calculation" are enough to allow the netbook from
John to work with ssb/b43. As this patch tampers with the SPROM offset for
14e4:4315 devices, it should be tested by anyone with an LP PHY that works
to ensure that it is not killed.

The essential elements of this patch will also be tested as part of kernel Bug
#15825.

Larry
 
Index: wireless-testing/drivers/ssb/pci.c
===================================================================
--- wireless-testing.orig/drivers/ssb/pci.c
+++ wireless-testing/drivers/ssb/pci.c
@@ -631,8 +631,17 @@ static int ssb_pci_sprom_get(struct ssb_
 		return -ENODEV;
 	}
 
-	bus->sprom_offset = (bus->chipco.dev->id.revision < 31) ?
-		SSB_SPROM_BASE1 : SSB_SPROM_BASE31;
+	/* get SPROM offset: SSB_SPROM_BASE1 except for chipcommon rev >= 31
+	 * or chip ID is 0x4312 and bit 0x2 is set in chipcommon status
+	 */
+	if (bus->chipco.dev->id.revision >= 31)
+		bus->sprom_offset = SSB_SPROM_BASE31;
+	else if (bus->chip_id == 0x4312 && (bus->chipco.status & 0x02))
+		bus->sprom_offset = SSB_SPROM_BASE31;
+	else
+		bus->sprom_offset = SSB_SPROM_BASE1;
+
+	ssb_dprintk(KERN_INFO PFX "SPROM offset is 0x%x\n", bus->sprom_offset);
 
 	buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
 	if (!buf)
Index: wireless-testing/drivers/ssb/scan.c
===================================================================
--- wireless-testing.orig/drivers/ssb/scan.c
+++ wireless-testing/drivers/ssb/scan.c
@@ -306,6 +306,11 @@ int ssb_bus_scan(struct ssb_bus *bus,
 		}
 		tmp = scan_read32(bus, 0, SSB_CHIPCO_CAP);
 		bus->chipco.capabilities = tmp;
+		if (bus->chip_rev >= 11)
+			bus->chipco.status = scan_read32(bus, 0,
+					     SSB_CHIPCO_CHIPSTAT);
+		else
+			bus->chipco.status = 0;
 	} else {
 		if (bus->bustype == SSB_BUSTYPE_PCI) {
 			bus->chip_id = pcidev_to_chipid(bus->host_pci);

^ permalink raw reply

* [PATCH 2/2] mac80211: check channel switch mode for future frames transmit
From: wey-yi.w.guy @ 2010-05-06  3:34 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Wey-Yi Guy
In-Reply-To: <1273116842-27189-1-git-send-email-wey-yi.w.guy@intel.com>

From: Wey-Yi Guy <wey-yi.w.guy@intel.com>

Check the mode in channel switch ie for either 0 or 1 on transmission.
A channel switch mode set to 1 means that the STA in a BSS to which the
frame containing the element is addressed shall transmit no further
frames 	within the BSS until the scheduled channel switch.

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
---
 net/mac80211/mlme.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index f50d73f..ef98cac 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -437,7 +437,8 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
 	if (sw_elem->count <= 1) {
 		ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
 	} else {
-		ieee80211_stop_queues_by_reason(&sdata->local->hw,
+		if (sw_elem->mode)
+			ieee80211_stop_queues_by_reason(&sdata->local->hw,
 					IEEE80211_QUEUE_STOP_REASON_CSA);
 		ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED;
 		mod_timer(&ifmgd->chswitch_timer,
-- 
1.5.6.3


^ permalink raw reply related

* [PATCH 1/2] mac80211: add offload channel switch support
From: wey-yi.w.guy @ 2010-05-06  3:34 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Wey-Yi Guy

From: Wey-Yi Guy <wey-yi.w.guy@intel.com>

Adding support to offload the channel switch operation to driver if
driver can support the function.

The original approach, mac80211 utilize the mac_config callback function
and set the CHANNEL_CHANGE flag which is difficult to separate the true
channel switch request from all the other channel changes condition;
with this offload approach, driver has more control on how to handle the
channel switch request from AP, also can provide more accurate timing
calculation

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
---
 include/net/mac80211.h      |   32 ++++++++++++++++++++++++++
 net/mac80211/driver-ops.h   |   11 +++++++++
 net/mac80211/driver-trace.h |   49 +++++++++++++++++++++++++++++++++++++++
 net/mac80211/ieee80211_i.h  |    3 +-
 net/mac80211/mlme.c         |   53 +++++++++++++++++++++++++++++++++++++++---
 5 files changed, 143 insertions(+), 5 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 2879c8e..dc5ae23 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -708,6 +708,26 @@ struct ieee80211_conf {
 };
 
 /**
+ * struct ieee80211_channel_switch - holds the channel switch data
+ *
+ * The information provided in this structure is required for channel switch
+ * operation.
+ *
+ * @timestamp: value in microseconds of the 64-bit Time Synchronization
+ *	Function (TSF) timer when the channel switch ie received.
+ * @block_tx: set to true if no more future frames transmission within the BSS
+ *	until the scheduled channel switch
+ * @channel: pointer to ieee80211_channel contain then new channel information
+ * @count: specified the number of TBTT's until the channel switch event.
+ */
+struct ieee80211_channel_switch {
+	u64 timestamp;
+	bool block_tx;
+	struct ieee80211_channel *channel;
+	u8 count;
+};
+
+/**
  * struct ieee80211_vif - per-interface data
  *
  * Data in this structure is continually present for driver
@@ -1694,6 +1714,8 @@ struct ieee80211_ops {
 	int (*testmode_cmd)(struct ieee80211_hw *hw, void *data, int len);
 #endif
 	void (*flush)(struct ieee80211_hw *hw, bool drop);
+	void (*channel_switch)(struct ieee80211_hw *hw,
+			       struct ieee80211_channel_switch *ch_switch);
 };
 
 /**
@@ -2444,6 +2466,16 @@ void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif,
 			       enum nl80211_cqm_rssi_threshold_event rssi_event,
 			       gfp_t gfp);
 
+/**
+ * ieee80211_chswitch_done - Complete channel switch process
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @is_seccess: make the channel switch successful or not
+ *
+ * Complete the channel switch post-process: set the new operational channel
+ * and wake up the suspended queues.
+ */
+void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool is_success);
+
 /* Rate control API */
 
 /**
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 997008e..5662bb5 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -373,4 +373,15 @@ static inline void drv_flush(struct ieee80211_local *local, bool drop)
 	if (local->ops->flush)
 		local->ops->flush(&local->hw, drop);
 }
+
+static inline void drv_channel_switch(struct ieee80211_local *local,
+				     struct ieee80211_channel_switch *ch_switch)
+{
+	might_sleep();
+
+	local->ops->channel_switch(&local->hw, ch_switch);
+
+	trace_drv_channel_switch(local, ch_switch);
+}
+
 #endif /* __MAC80211_DRIVER_OPS */
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index ce734b5..cd1ae9f 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -774,6 +774,34 @@ TRACE_EVENT(drv_flush,
 	)
 );
 
+TRACE_EVENT(drv_channel_switch,
+	TP_PROTO(struct ieee80211_local *local,
+		 struct ieee80211_channel_switch *ch_switch),
+
+	TP_ARGS(local, ch_switch),
+
+	TP_STRUCT__entry(
+		LOCAL_ENTRY
+		__field(u64, timestamp)
+		__field(bool, block_tx)
+		__field(u16, freq)
+		__field(u8, count)
+	),
+
+	TP_fast_assign(
+		LOCAL_ASSIGN;
+		__entry->timestamp = ch_switch->timestamp;
+		__entry->block_tx = ch_switch->block_tx;
+		__entry->freq = ch_switch->channel->center_freq;
+		__entry->count = ch_switch->count;
+	),
+
+	TP_printk(
+		LOCAL_PR_FMT " new freq:%u count:%d",
+		LOCAL_PR_ARG, __entry->freq, __entry->count
+	)
+);
+
 /*
  * Tracing for API calls that drivers call.
  */
@@ -992,6 +1020,27 @@ TRACE_EVENT(api_sta_block_awake,
 	)
 );
 
+TRACE_EVENT(api_chswitch_done,
+	TP_PROTO(struct ieee80211_sub_if_data *sdata, bool is_success),
+
+	TP_ARGS(sdata, is_success),
+
+	TP_STRUCT__entry(
+		VIF_ENTRY
+		__field(bool, is_success)
+	),
+
+	TP_fast_assign(
+		VIF_ASSIGN;
+		__entry->is_success = is_success;
+	),
+
+	TP_printk(
+		VIF_PR_FMT " chswitch:%d",
+		VIF_PR_ARG, __entry->is_success
+	)
+);
+
 /*
  * Tracing for internal functions
  * (which may also be called in response to driver calls)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 4e73660..be9dda9 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -999,7 +999,8 @@ int ieee80211_max_network_latency(struct notifier_block *nb,
 				  unsigned long data, void *dummy);
 void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
 				      struct ieee80211_channel_sw_ie *sw_elem,
-				      struct ieee80211_bss *bss);
+				      struct ieee80211_bss *bss,
+				      u64 timestamp);
 void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata);
 void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata);
 
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 358226f..f50d73f 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -340,7 +340,11 @@ static void ieee80211_chswitch_work(struct work_struct *work)
 		goto out;
 
 	sdata->local->oper_channel = sdata->local->csa_channel;
-	ieee80211_hw_config(sdata->local, IEEE80211_CONF_CHANGE_CHANNEL);
+	if (!sdata->local->ops->channel_switch) {
+		/* call "hw_config" only if doing sw channel switch */
+		ieee80211_hw_config(sdata->local,
+			IEEE80211_CONF_CHANGE_CHANNEL);
+	}
 
 	/* XXX: shouldn't really modify cfg80211-owned data! */
 	ifmgd->associated->channel = sdata->local->oper_channel;
@@ -352,6 +356,22 @@ static void ieee80211_chswitch_work(struct work_struct *work)
 	mutex_unlock(&ifmgd->mtx);
 }
 
+void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool is_success)
+{
+	struct ieee80211_sub_if_data *sdata;
+	struct ieee80211_if_managed *ifmgd;
+
+	sdata = vif_to_sdata(vif);
+	ifmgd = &sdata->u.mgd;
+
+	trace_api_chswitch_done(sdata, is_success);
+	if (!is_success)
+		sdata->local->csa_channel = sdata->local->oper_channel;
+
+	ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
+}
+EXPORT_SYMBOL(ieee80211_chswitch_done);
+
 static void ieee80211_chswitch_timer(unsigned long data)
 {
 	struct ieee80211_sub_if_data *sdata =
@@ -368,7 +388,8 @@ static void ieee80211_chswitch_timer(unsigned long data)
 
 void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
 				      struct ieee80211_channel_sw_ie *sw_elem,
-				      struct ieee80211_bss *bss)
+				      struct ieee80211_bss *bss,
+				      u64 timestamp)
 {
 	struct cfg80211_bss *cbss =
 		container_of((void *)bss, struct cfg80211_bss, priv);
@@ -396,6 +417,23 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
 
 	sdata->local->csa_channel = new_ch;
 
+	if (sdata->local->ops->channel_switch) {
+		/* use driver's channel switch callback */
+		struct ieee80211_channel_switch ch_switch;
+		memset(&ch_switch, 0, sizeof(ch_switch));
+		ch_switch.timestamp = timestamp;
+		if (sw_elem->mode) {
+			ch_switch.block_tx = true;
+			ieee80211_stop_queues_by_reason(&sdata->local->hw,
+					IEEE80211_QUEUE_STOP_REASON_CSA);
+		}
+		ch_switch.channel = new_ch;
+		ch_switch.count = sw_elem->count;
+		ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED;
+		drv_channel_switch(sdata->local, &ch_switch);
+		return;
+	}
+	/* mac80211 handle channel switch */
 	if (sw_elem->count <= 1) {
 		ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
 	} else {
@@ -1279,6 +1317,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
 	struct ieee80211_bss *bss;
 	struct ieee80211_channel *channel;
 	bool need_ps = false;
+	u64 timestamp;
 
 	if (sdata->u.mgd.associated) {
 		bss = (void *)sdata->u.mgd.associated->priv;
@@ -1315,7 +1354,12 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
 							ETH_ALEN) == 0)) {
 		struct ieee80211_channel_sw_ie *sw_elem =
 			(struct ieee80211_channel_sw_ie *)elems->ch_switch_elem;
-		ieee80211_sta_process_chanswitch(sdata, sw_elem, bss);
+		if (beacon)
+			timestamp = le64_to_cpu(mgmt->u.beacon.timestamp);
+		else
+			timestamp = le64_to_cpu(mgmt->u.probe_resp.timestamp);
+		ieee80211_sta_process_chanswitch(sdata, sw_elem,
+						 bss, timestamp);
 	}
 }
 
@@ -1647,7 +1691,8 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
 
 			ieee80211_sta_process_chanswitch(sdata,
 					&mgmt->u.action.u.chan_switch.sw_elem,
-					(void *)ifmgd->associated->priv);
+					(void *)ifmgd->associated->priv,
+					rx_status->mactime);
 			break;
 		}
 		mutex_unlock(&ifmgd->mtx);
-- 
1.5.6.3


^ permalink raw reply related

* Re: [PATCH] compat: backport eth_change_mtu and eth_validate_addr
From: Luis R. Rodriguez @ 2010-05-06  0:41 UTC (permalink / raw)
  To: Hauke Mehrtens; +Cc: linux-wireless, mcgrof
In-Reply-To: <1273098457-21658-1-git-send-email-hauke@hauke-m.de>

On Wed, May 5, 2010 at 3:27 PM, Hauke Mehrtens <hauke@hauke-m.de> wrote:
>
> Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>

Awesome, thanks.

  Luis

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox