Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH v3 01/18] wl1271: Add AP related configuration to conf_drv_settings
From: Arik Nemtsov @ 2010-12-28 17:36 UTC (permalink / raw)
  To: linux-wireless; +Cc: Luciano Coelho, Arik Nemtsov
In-Reply-To: <1293557808-27068-1-git-send-email-arik@wizery.com>

Rate class configuration has been split up for AP and STA modes.
Template related configuration likewise separated.

Signed-off-by: Arik Nemtsov <arik@wizery.com>
---
 drivers/net/wireless/wl12xx/acx.c  |    2 +-
 drivers/net/wireless/wl12xx/cmd.c  |    4 +-
 drivers/net/wireless/wl12xx/conf.h |   46 ++++++++++++++++++++++++++++++++++-
 drivers/net/wireless/wl12xx/main.c |   45 +++++++++++++++++++++++++++++++++-
 4 files changed, 90 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
index cc4068d..30ff32a 100644
--- a/drivers/net/wireless/wl12xx/acx.c
+++ b/drivers/net/wireless/wl12xx/acx.c
@@ -754,7 +754,7 @@ int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats)
 int wl1271_acx_rate_policies(struct wl1271 *wl)
 {
 	struct acx_rate_policy *acx;
-	struct conf_tx_rate_class *c = &wl->conf.tx.rc_conf;
+	struct conf_tx_rate_class *c = &wl->conf.tx.sta_rc_conf;
 	int idx = 0;
 	int ret = 0;
 
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index 0106628..15f4077 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -490,8 +490,8 @@ int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id,
 	cmd->len = cpu_to_le16(buf_len);
 	cmd->template_type = template_id;
 	cmd->enabled_rates = cpu_to_le32(rates);
-	cmd->short_retry_limit = wl->conf.tx.rc_conf.short_retry_limit;
-	cmd->long_retry_limit = wl->conf.tx.rc_conf.long_retry_limit;
+	cmd->short_retry_limit = wl->conf.tx.tmpl_short_retry_limit;
+	cmd->long_retry_limit = wl->conf.tx.tmpl_long_retry_limit;
 	cmd->index = index;
 
 	if (buf)
diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h
index a16b361..7563ce3 100644
--- a/drivers/net/wireless/wl12xx/conf.h
+++ b/drivers/net/wireless/wl12xx/conf.h
@@ -496,6 +496,26 @@ struct conf_rx_settings {
 					CONF_HW_BIT_RATE_2MBPS)
 #define CONF_TX_RATE_RETRY_LIMIT       10
 
+/*
+ * Rates supported for data packets when operating as AP. Note the absense
+ * of the 22Mbps rate. There is a FW limitation on 12 rates so we must drop
+ * one. The rate dropped is not mandatory under any operating mode.
+ */
+#define CONF_TX_AP_ENABLED_RATES       (CONF_HW_BIT_RATE_1MBPS | \
+	CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS |      \
+	CONF_HW_BIT_RATE_6MBPS | CONF_HW_BIT_RATE_9MBPS |        \
+	CONF_HW_BIT_RATE_11MBPS | CONF_HW_BIT_RATE_12MBPS |      \
+	CONF_HW_BIT_RATE_18MBPS | CONF_HW_BIT_RATE_24MBPS |      \
+	CONF_HW_BIT_RATE_36MBPS | CONF_HW_BIT_RATE_48MBPS |      \
+	CONF_HW_BIT_RATE_54MBPS)
+
+/*
+ * Default rates for management traffic when operating in AP mode. This
+ * should be configured according to the basic rate set of the AP
+ */
+#define CONF_TX_AP_DEFAULT_MGMT_RATES  (CONF_HW_BIT_RATE_1MBPS | \
+	CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS)
+
 struct conf_tx_rate_class {
 
 	/*
@@ -636,9 +656,9 @@ struct conf_tx_settings {
 
 	/*
 	 * Configuration for rate classes for TX (currently only one
-	 * rate class supported.)
+	 * rate class supported). Used in non-AP mode.
 	 */
-	struct conf_tx_rate_class rc_conf;
+	struct conf_tx_rate_class sta_rc_conf;
 
 	/*
 	 * Configuration for access categories for TX rate control.
@@ -647,6 +667,22 @@ struct conf_tx_settings {
 	struct conf_tx_ac_category ac_conf[CONF_TX_MAX_AC_COUNT];
 
 	/*
+	 * Configuration for rate classes in AP-mode. These rate classes
+	 * are for the AC TX queues
+	 */
+	struct conf_tx_rate_class ap_rc_conf[CONF_TX_MAX_AC_COUNT];
+
+	/*
+	 * Management TX rate class for AP-mode.
+	 */
+	struct conf_tx_rate_class ap_mgmt_conf;
+
+	/*
+	 * Broadcast TX rate class for AP-mode.
+	 */
+	struct conf_tx_rate_class ap_bcst_conf;
+
+	/*
 	 * Configuration for TID parameters.
 	 */
 	u8 tid_conf_count;
@@ -687,6 +723,12 @@ struct conf_tx_settings {
 	 * Range: CONF_HW_BIT_RATE_* bit mask
 	 */
 	u32 basic_rate_5;
+
+	/*
+	 * TX retry limits for templates
+	 */
+	u8 tmpl_short_retry_limit;
+	u8 tmpl_long_retry_limit;
 };
 
 enum {
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 062247e..788959a 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -116,11 +116,11 @@ static struct conf_drv_settings default_conf = {
 	},
 	.tx = {
 		.tx_energy_detection         = 0,
-		.rc_conf                     = {
+		.sta_rc_conf                 = {
 			.enabled_rates       = 0,
 			.short_retry_limit   = 10,
 			.long_retry_limit    = 10,
-			.aflags              = 0
+			.aflags              = 0,
 		},
 		.ac_conf_count               = 4,
 		.ac_conf                     = {
@@ -153,6 +153,45 @@ static struct conf_drv_settings default_conf = {
 				.tx_op_limit = 1504,
 			},
 		},
+		.ap_rc_conf                  = {
+			[0] = {
+				.enabled_rates = CONF_TX_AP_ENABLED_RATES,
+				.short_retry_limit = 10,
+				.long_retry_limit = 10,
+				.aflags      = 0,
+			},
+			[1] = {
+				.enabled_rates = CONF_TX_AP_ENABLED_RATES,
+				.short_retry_limit = 10,
+				.long_retry_limit = 10,
+				.aflags      = 0,
+			},
+			[2] = {
+				.enabled_rates = CONF_TX_AP_ENABLED_RATES,
+				.short_retry_limit = 10,
+				.long_retry_limit = 10,
+				.aflags      = 0,
+			},
+			[3] = {
+				.enabled_rates = CONF_TX_AP_ENABLED_RATES,
+				.short_retry_limit = 10,
+				.long_retry_limit = 10,
+				.aflags      = 0,
+			},
+		},
+		.ap_mgmt_conf = {
+			.enabled_rates       = CONF_TX_AP_DEFAULT_MGMT_RATES,
+			.short_retry_limit   = 10,
+			.long_retry_limit    = 10,
+			.aflags              = 0,
+		},
+		.ap_bcst_conf = {
+			.enabled_rates       = CONF_HW_BIT_RATE_1MBPS,
+			.short_retry_limit   = 10,
+			.long_retry_limit    = 10,
+			.aflags              = 0,
+		},
+
 		.tid_conf_count = 4,
 		.tid_conf = {
 			[CONF_TX_AC_BE] = {
@@ -193,6 +232,8 @@ static struct conf_drv_settings default_conf = {
 		.tx_compl_threshold          = 4,
 		.basic_rate                  = CONF_HW_BIT_RATE_1MBPS,
 		.basic_rate_5                = CONF_HW_BIT_RATE_6MBPS,
+		.tmpl_short_retry_limit      = 10,
+		.tmpl_long_retry_limit       = 10,
 	},
 	.conn = {
 		.wake_up_event               = CONF_WAKE_UP_EVENT_DTIM,
-- 
1.7.1


^ permalink raw reply related

* [PATCH v3 00/18] AP mode support for wl12xx
From: Arik Nemtsov @ 2010-12-28 17:36 UTC (permalink / raw)
  To: linux-wireless; +Cc: Luciano Coelho, Arik Nemtsov

These patches add access point mode support to the wl12xx driver.
This mode uses a separate firmware and has a different initialization
sequence.

In all instances, the flow has been split according to the operating
mode of the driver (AP/STA), so as not to affect STA mode functionality.

v1->2: rebased on latest wl12xx tree
v2->3: refactoring

Arik Nemtsov (18):
  wl1271: Add AP related configuration to conf_drv_settings
  wl1271: AP mode - AP specific CMD_CONFIGURE sub-commands
  wl1271: AP mode - add AP specific event
  wl1271: AP-mode high level commands
  wl1271: AP mode - workaround for FW bug on station remove
  wl1271: AP mode - init sequence
  wl1271: AP specific RX filter configuration
  wl1271: Add AP related definitions to HOST-FW interface
  wl1271: Configure AP on BSS info change
  wl1271: AP mode config in ieee80211_ops.config
  wl1271: AP mode - change filter config
  wl1271: AP mode - add STA add/remove ops
  wl1271: AP mode - changes in TX path
  wl1271: AP mode - record TX configuration settings
  wl1271: AP mode - encryption support
  wl1271: AP mode - fetch appropriate firmware for AP
  wl1271: Read MAC address from NVS file on HW startup
  wl1271: Enable AP-mode

 drivers/net/wireless/wl12xx/acx.c          |   62 ++-
 drivers/net/wireless/wl12xx/acx.h          |   29 +-
 drivers/net/wireless/wl12xx/boot.c         |   11 +-
 drivers/net/wireless/wl12xx/cmd.c          |  300 +++++++++-
 drivers/net/wireless/wl12xx/cmd.h          |  147 ++++-
 drivers/net/wireless/wl12xx/conf.h         |   52 ++-
 drivers/net/wireless/wl12xx/event.c        |    7 +-
 drivers/net/wireless/wl12xx/event.h        |    8 +-
 drivers/net/wireless/wl12xx/init.c         |  352 ++++++++---
 drivers/net/wireless/wl12xx/init.h         |    2 +-
 drivers/net/wireless/wl12xx/main.c         |  955 +++++++++++++++++++++-------
 drivers/net/wireless/wl12xx/rx.c           |   11 +
 drivers/net/wireless/wl12xx/rx.h           |   11 +-
 drivers/net/wireless/wl12xx/tx.c           |  105 +++-
 drivers/net/wireless/wl12xx/tx.h           |   10 +-
 drivers/net/wireless/wl12xx/wl12xx.h       |   68 ++-
 drivers/net/wireless/wl12xx/wl12xx_80211.h |    5 +
 17 files changed, 1770 insertions(+), 365 deletions(-)


^ permalink raw reply

* Re: [PATCH v2 15/18] wl1271: AP mode - encryption support
From: Arik Nemtsov @ 2010-12-28 17:16 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless
In-Reply-To: <1293537823.24274.18.camel@chilepepper>

On Tue, Dec 28, 2010 at 14:03, Luciano Coelho <luciano.coelho@nokia.com> wrote:
> On Wed, 2010-12-22 at 16:27 +0200, ext Arik Nemtsov wrote:
>> Encryption key configuration is different for AP/STA modes.
>>
>> AP encryption keys are recorded when the BSS is not started. On BSS
>> start they are propagated to the AP (in wl1271_ap_init_hwenc).
>>
>> Signed-off-by: Arik Nemtsov <arik@wizery.com>
>> ---
>
> [...]
>
>> diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h
>> index 0662b19..81ba75d 100644
>> --- a/drivers/net/wireless/wl12xx/tx.h
>> +++ b/drivers/net/wireless/wl12xx/tx.h
>> @@ -152,4 +152,8 @@ void wl1271_tx_flush(struct wl1271 *wl);
>>  u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band);
>>  u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set);
>>
>> +/* Functions from wl1271_main.c */
>> +
>> +int wl1271_set_default_wep_key(struct wl1271 *wl, u8 id);
>> +
>>  #endif
>
> Again, same thing.  Can we put this somewhere else?
>

Actually the WEP default key is used for TX, so we can put this in tx.c.

Regards,
Arik

^ permalink raw reply

* Re: Compile error for the last week inside rtlwifi/base.c
From: Larry Finger @ 2010-12-28 16:23 UTC (permalink / raw)
  To: Weedy; +Cc: linux-wireless
In-Reply-To: <loom.20101228T075242-208@post.gmane.org>

[-- Attachment #1: Type: text/plain, Size: 992 bytes --]

On 12/28/2010 12:58 AM, Weedy wrote:
> I'm not sure if my kernel is too old or what but since nothing has changed I'm
> going to ask.

Older kernels used create_workqueue(), which is replaced by alloc_workqueue().
If you really need the driver for RTL8192CE/RTL8188CE, then apply the patch
shown below. If you do not need the driver, then disable it in the configuration.

Larry
---

diff --git a/drivers/net/wireless/rtlwifi/base.c
b/drivers/net/wireless/rtlwifi/base.c
index 77fa59a..f6cc073 100644
--- a/drivers/net/wireless/rtlwifi/base.c
+++ b/drivers/net/wireless/rtlwifi/base.c
@@ -225,7 +225,7 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw)

 	/* <2> work queue */
 	rtlpriv->works.hw = hw;
`	rtlpriv->works.rtl_wq = alloc_workqueue(rtlpriv->cfg->name, 0, 0);
+	rtlpriv->works.rtl_wq = create_workqueue(rtlpriv->cfg->name);
 	INIT_DELAYED_WORK(&rtlpriv->works.watchdog_wq,
 			  (void *)rtl_watchdog_wq_callback);
 	INIT_DELAYED_WORK(&rtlpriv->works.ips_nic_off_wq,


[-- Attachment #2: reverse_alloc --]
[-- Type: text/plain, Size: 1087 bytes --]

commit 3d986b25b5faa50ba6afd94f60f270b6c3061e5e
Author: John W. Linville <linville@tuxdriver.com>
Date:   Thu Dec 16 14:59:49 2010 -0500

    rtlwifi: use alloc_workqueue
    
    create_workqueue is deprecated.  The workqueue usage does not seem to
    demand any special treatment, so do not set any flags either.
    
    Signed-off-by: John W. Linville <linville@tuxdriver.com>
    Tested-by: Larry Finger <Larry.Finger@lwfinger.net>
    Acked-by: Tejun Heo <tj@kernel.org>

diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c
index 77fa59a..f6cc073 100644
--- a/drivers/net/wireless/rtlwifi/base.c
+++ b/drivers/net/wireless/rtlwifi/base.c
@@ -225,7 +225,7 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw)
 
 	/* <2> work queue */
 	rtlpriv->works.hw = hw;
-	rtlpriv->works.rtl_wq = create_workqueue(rtlpriv->cfg->name);
+	rtlpriv->works.rtl_wq = alloc_workqueue(rtlpriv->cfg->name, 0, 0);
 	INIT_DELAYED_WORK(&rtlpriv->works.watchdog_wq,
 			  (void *)rtl_watchdog_wq_callback);
 	INIT_DELAYED_WORK(&rtlpriv->works.ips_nic_off_wq,

^ permalink raw reply related

* [PATCH] ath9k_hw: fix dma descriptor rx error bit parsing
From: Felix Fietkau @ 2010-12-28 14:46 UTC (permalink / raw)
  To: linux-wireless; +Cc: linville, lrodriguez, Felix Fietkau

An Rx DMA descriptor can have multiple error bits set, and some error
bits (e.g. MIC failure) are filtered by the driver based on other criteria.
Remove the 'else' in various error bit checks so that all error information
is properly passed to the driver.

Signed-off-by: Felix Fietkau <nbd@openwrt.org>
---
 drivers/net/wireless/ath/ath9k/ar9003_mac.c |   11 ++++++-----
 drivers/net/wireless/ath/ath9k/mac.c        |    9 +++++----
 2 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
index b6e4ee4..4ceddbb 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
@@ -613,9 +613,9 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs,
 		 * possibly be reviewing the last subframe. AR_CRCErr
 		 * is the CRC of the actual data.
 		 */
-		if (rxsp->status11 & AR_CRCErr) {
+		if (rxsp->status11 & AR_CRCErr)
 			rxs->rs_status |= ATH9K_RXERR_CRC;
-		} else if (rxsp->status11 & AR_PHYErr) {
+		if (rxsp->status11 & AR_PHYErr) {
 			phyerr = MS(rxsp->status11, AR_PHYErrCode);
 			/*
 			 * If we reach a point here where AR_PostDelimCRCErr is
@@ -638,11 +638,12 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs,
 				rxs->rs_phyerr = phyerr;
 			}
 
-		} else if (rxsp->status11 & AR_DecryptCRCErr) {
+		}
+		if (rxsp->status11 & AR_DecryptCRCErr)
 			rxs->rs_status |= ATH9K_RXERR_DECRYPT;
-		} else if (rxsp->status11 & AR_MichaelErr) {
+		if (rxsp->status11 & AR_MichaelErr)
 			rxs->rs_status |= ATH9K_RXERR_MIC;
-		} else if (rxsp->status11 & AR_KeyMiss)
+		if (rxsp->status11 & AR_KeyMiss)
 			rxs->rs_status |= ATH9K_RXERR_DECRYPT;
 	}
 
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index e3d2ebf..180170d 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -692,15 +692,16 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
 	if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) {
 		if (ads.ds_rxstatus8 & AR_CRCErr)
 			rs->rs_status |= ATH9K_RXERR_CRC;
-		else if (ads.ds_rxstatus8 & AR_PHYErr) {
+		if (ads.ds_rxstatus8 & AR_PHYErr) {
 			rs->rs_status |= ATH9K_RXERR_PHY;
 			phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode);
 			rs->rs_phyerr = phyerr;
-		} else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
+		}
+		if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
 			rs->rs_status |= ATH9K_RXERR_DECRYPT;
-		else if (ads.ds_rxstatus8 & AR_MichaelErr)
+		if (ads.ds_rxstatus8 & AR_MichaelErr)
 			rs->rs_status |= ATH9K_RXERR_MIC;
-		else if (ads.ds_rxstatus8 & AR_KeyMiss)
+		if (ads.ds_rxstatus8 & AR_KeyMiss)
 			rs->rs_status |= ATH9K_RXERR_DECRYPT;
 	}
 
-- 
1.7.3.2


^ permalink raw reply related

* Re: [PATCH v2 17/18] wl1271: Read MAC address from NVS file on HW startup
From: Luciano Coelho @ 2010-12-28 12:57 UTC (permalink / raw)
  To: ext Arik Nemtsov; +Cc: linux-wireless
In-Reply-To: <1293028057-6212-18-git-send-email-arik@wizery.com>

On Wed, 2010-12-22 at 16:27 +0200, ext Arik Nemtsov wrote:
> Try to read the MAC address from the on-disk NVS file.
> A non-zero MAC address is required to add an AP interface.
> 
> Signed-off-by: Arik Nemtsov <arik@wizery.com>
> ---

[...]

> diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
> index eb2c3c5..a9f95c6 100644
> --- a/drivers/net/wireless/wl12xx/main.c
> +++ b/drivers/net/wireless/wl12xx/main.c
> @@ -3025,6 +3025,18 @@ int wl1271_register_hw(struct wl1271 *wl)
>  	if (wl->mac80211_registered)
>  		return 0;
>  
> +	ret = wl1271_fetch_nvs(wl);
> +	if (ret == 0) {
> +		u8 *nvs_ptr = (u8 *)wl->nvs->nvs;
> +
> +		wl->mac_addr[0] = nvs_ptr[11];
> +		wl->mac_addr[1] = nvs_ptr[10];
> +		wl->mac_addr[2] = nvs_ptr[6];
> +		wl->mac_addr[3] = nvs_ptr[5];
> +		wl->mac_addr[4] = nvs_ptr[4];
> +		wl->mac_addr[5] = nvs_ptr[3];
> +	}
> +
>  	SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr);
>  
>  	ret = ieee80211_register_hw(wl->hw);

I think we need to check whether the MAC address is valid in the NVS.
Also this goes a little bit against the way we are doing things in Nokia
devices.  In our devices we don't have different files during
production, the only part that is different from one individual device
to another is in a protected area.  The NVS file in the file system is
always the same.  The one that changes is in the protected area and is
passed to the driver by a special application.

Also, how would this work if the hw is registered before udev is
running?

We need to revise the entire NVS thing.  But at least for now, while we
don't come up with a good and final solution, we should not be inventing
new ways of setting the MAC.


-- 
Cheers,
Luca.


^ permalink raw reply

* Re: [PATCH v2 15/18] wl1271: AP mode - encryption support
From: Luciano Coelho @ 2010-12-28 12:03 UTC (permalink / raw)
  To: ext Arik Nemtsov; +Cc: linux-wireless
In-Reply-To: <1293028057-6212-16-git-send-email-arik@wizery.com>

On Wed, 2010-12-22 at 16:27 +0200, ext Arik Nemtsov wrote:
> Encryption key configuration is different for AP/STA modes.
> 
> AP encryption keys are recorded when the BSS is not started. On BSS
> start they are propagated to the AP (in wl1271_ap_init_hwenc).
> 
> Signed-off-by: Arik Nemtsov <arik@wizery.com>
> ---

[...]

> diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h
> index 0662b19..81ba75d 100644
> --- a/drivers/net/wireless/wl12xx/tx.h
> +++ b/drivers/net/wireless/wl12xx/tx.h
> @@ -152,4 +152,8 @@ void wl1271_tx_flush(struct wl1271 *wl);
>  u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band);
>  u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set);
>  
> +/* Functions from wl1271_main.c */
> +
> +int wl1271_set_default_wep_key(struct wl1271 *wl, u8 id);
> +
>  #endif

Again, same thing.  Can we put this somewhere else?


-- 
Cheers,
Luca.


^ permalink raw reply

* Re: [PATCH v2 14/18] wl1271: AP mode - record TX configuration settings
From: Arik Nemtsov @ 2010-12-28 11:37 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless
In-Reply-To: <1293536140.24274.16.camel@chilepepper>

On Tue, Dec 28, 2010 at 13:35, Luciano Coelho <luciano.coelho@nokia.com> wrote:
> On Wed, 2010-12-22 at 16:27 +0200, ext Arik Nemtsov wrote:
>> Record TX configuration settings in the "conf" member of our global
>> structure (struct wl1271) if conf_tx is called when the firmware is
>> not loaded.
>>
>> Later on when the firmware is loaded, we apply the tx conf as part of
>> the init sequence.
>>
>> Important for AP mode since conf_tx is called before add_interface
>> (where the firmware is initialized).
>>
>> Signed-off-by: Arik Nemtsov <arik@wizery.com>
>> ---
>
> [...]
>
>> diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
>> index 3cc4f79..71a67f1 100644
>> --- a/drivers/net/wireless/wl12xx/main.c
>> +++ b/drivers/net/wireless/wl12xx/main.c
>> @@ -1462,6 +1462,8 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
>>               goto out;
>>       }
>>
>> +     is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
>> +
>>       ret = wl1271_ps_elp_wakeup(wl, false);
>>       if (ret < 0)
>>               goto out;
>
> This is cross-patch and should be in 10/18.

You're right. Actually fixed this already.

Regards,
Arik

^ permalink raw reply

* Re: [PATCH v2 14/18] wl1271: AP mode - record TX configuration settings
From: Luciano Coelho @ 2010-12-28 11:35 UTC (permalink / raw)
  To: ext Arik Nemtsov; +Cc: linux-wireless
In-Reply-To: <1293028057-6212-15-git-send-email-arik@wizery.com>

On Wed, 2010-12-22 at 16:27 +0200, ext Arik Nemtsov wrote:
> Record TX configuration settings in the "conf" member of our global
> structure (struct wl1271) if conf_tx is called when the firmware is
> not loaded.
> 
> Later on when the firmware is loaded, we apply the tx conf as part of
> the init sequence.
> 
> Important for AP mode since conf_tx is called before add_interface
> (where the firmware is initialized).
> 
> Signed-off-by: Arik Nemtsov <arik@wizery.com>
> ---

[...]

> diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
> index 3cc4f79..71a67f1 100644
> --- a/drivers/net/wireless/wl12xx/main.c
> +++ b/drivers/net/wireless/wl12xx/main.c
> @@ -1462,6 +1462,8 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
>  		goto out;
>  	}
>  
> +	is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
> +
>  	ret = wl1271_ps_elp_wakeup(wl, false);
>  	if (ret < 0)
>  		goto out;

This is cross-patch and should be in 10/18.


-- 
Cheers,
Luca.


^ permalink raw reply

* Re: iwlwifi: Intel 3945ABG speed issues finally identified.
From: Stanislaw Gruszka @ 2010-12-28 10:52 UTC (permalink / raw)
  To: Eric Appleman; +Cc: linux-wireless
In-Reply-To: <loom.20101223T071403-99@post.gmane.org>

On Thu, Dec 23, 2010 at 06:15:18AM +0000, Eric Appleman wrote:
> I spent most of the day bisecting and testing numerous kernels and my work has
> finally paid off.
> 
> I've found 2 candidate commits.
> 
> a6866ac93e6cb68091326e80b4fa4619a5957644
> 1402364162afbaac1b8a74ee21aeb013e817ac7d
> 
> iwl3945 definitely broke between 2.6.35-rc2 and -rc3.

For sure breakage is between -rc2 and -rc3 ?

We have these commits:
$ git log --pretty=oneline v2.6.35-rc2..v2.6.35-rc3 -- net/mac80211/ drivers/net/wireless/iwlwifi/
b054b747a694927879c94dd11af54d04346aed7d mac80211: fix deauth before assoc
6db6340c42d027b6364d49fa99d69019aca24de4 iwlwifi: add missing rcu_read_lock
35dd0509b21e4b5bab36b9eb80c8dab0322f5007 mac80211: fix function pointer check
7d47618a2ade0cb6d8a0b2597029c383c1662fa0 iwlwifi: move sysfs_create_group to post request firmware
1402364162afbaac1b8a74ee21aeb013e817ac7d iwl3945: fix internal scan
a6866ac93e6cb68091326e80b4fa4619a5957644 iwl3945: enable stuck queue detection on 3945
8b9a4e6e442756f670ef507f09bbc6c11dc0fca6 mac80211: process station blockack action frames from work

Also there are some general network commits.

What I can tell, none of them could cause performance problems in
obvious way. If breakage is really between 2.6.35 -rc2 and -rc3, could
you install 2.6.35 kernel from source, and revert these commits 
one by one to see revert of which commit fix the problem?

Stanislaw 

^ permalink raw reply

* Re: stable compat-wireless releases are 404
From: Stanislaw Gruszka @ 2010-12-28 10:28 UTC (permalink / raw)
  To: Luis R. Rodriguez; +Cc: linux-wireless, Justin Case
In-Reply-To: <loom.20101227T073819-206@post.gmane.org>

On Mon, Dec 27, 2010 at 06:39:04AM +0000, Justin Case wrote:
> I am trying to download a stable compat-wireless release from this website:
> http://linuxwireless.org/en/users/Download/stable/
> 
> however the main download site:
> http://www.orbit-lab.org/kernel/
> is giving 404 errors.

Luis, could you fix this?

> Is there an alternative download site or mirror?
?

Stanislaw

^ permalink raw reply

* Re: [PATCH RFC] mac80211: Extend channel to frequency mapping for 802.11j
From: Johannes Berg @ 2010-12-28  9:53 UTC (permalink / raw)
  To: Bruno Randolf; +Cc: Dave Kilroy, linville, linux-wireless
In-Reply-To: <1293529861.3526.8.camel@jlt3.sipsolutions.net>

On Tue, 2010-12-28 at 10:51 +0100, Johannes Berg wrote:

> > ieee80211_dsss_chan_to_freq - atmel, airo, wl3501_cs, orinoco, rndis_wlan
> > ieee80211_freq_to_dsss_chan - atmel, airo, orinoco, zd1201
> > 
> > Anyhow i guess it would make sense to have a common channel to frequency 
> > mapping function for mac80211 and other wireless drivers? The problem is now 
> > we have to use enum ieee80211_band which is defined cfg80211.h...

Interestingly, I just noticed that the above ones also have different
semantics -- they try to round to the nearest channel rather than
returning an error if the center frequency isn't exact.

johannes


^ permalink raw reply

* Re: [PATCH RFC] mac80211: Extend channel to frequency mapping for 802.11j
From: Johannes Berg @ 2010-12-28  9:51 UTC (permalink / raw)
  To: Bruno Randolf; +Cc: Dave Kilroy, linville, linux-wireless
In-Reply-To: <201012281843.57453.br1@einfach.org>

On Tue, 2010-12-28 at 18:43 +0900, Bruno Randolf wrote:

> > You don't have to use them, but there are a few channel/frequency
> > conversion routines in include/ieee80211.h which could be reused in
> > these functions.
> 
> Thanks for that info, I didn't know about those functions. I just checked 
> them and it seems most of them are not used, AFAICT:
> 
> ieee80211_fhss_chan_to_freq - not used
> ieee80211_freq_to_fhss_chan - not used
> ieee80211_hr_chan_to_freq - not used
> ieee80211_freq_to_hr_chan - not used
> ieee80211_erp_chan_to_freq - not used
> ieee80211_freq_to_erp_chan - not used
> ieee80211_ofdm_chan_to_freq - not used
> ieee80211_freq_to_ofdm_chan - not used

Cute -- we should probably just remove these.

> The only two which are used are for 2GHz channels:
> 
> ieee80211_dsss_chan_to_freq - atmel, airo, wl3501_cs, orinoco, rndis_wlan
> ieee80211_freq_to_dsss_chan - atmel, airo, orinoco, zd1201
> 
> Anyhow i guess it would make sense to have a common channel to frequency 
> mapping function for mac80211 and other wireless drivers? The problem is now 
> we have to use enum ieee80211_band which is defined cfg80211.h...

Well, you're a bit wrong -- the function you're modifying is part of
cfg80211. Therefore, including cfg80211.h makes perfect sense, it's also
defined in there (therefore, your patch subject should begin with
"cfg80211:" instead of "mac80211:").

However, of those drivers you list only orinoco and rndis_wlan already
use cfg80211, so for the others using it would introduce an almost
"fake" dependency. In any case, it seems like all that should be
separate patches.

johannes


^ permalink raw reply

* Re: [PATCH RFC] mac80211: Extend channel to frequency mapping for 802.11j
From: Bruno Randolf @ 2010-12-28  9:43 UTC (permalink / raw)
  To: Dave Kilroy; +Cc: johannes, linville, linux-wireless
In-Reply-To: <AANLkTi=R58EGLrsT5sTk7JTqWvaeJ5caytHMt3VCSOki@mail.gmail.com>

On Sat December 25 2010 01:46:00 Dave Kilroy wrote:
> On Fri, Dec 24, 2010 at 7:44 AM, Bruno Randolf <br1@einfach.org> wrote:
> > Extend channel to frequency mapping for 802.11j Japan 4.9GHz band,
> > according to IEEE802.11 section 17.3.8.3.2 and Annex J. Because there
> > are now overlapping channel numbers in the 2GHz and 5GHz band we can't
> > map from channel to frequency without knowing the band. This is no
> > problem as in most contexts we know the band. In places where we don't
> > know the band (and WEXT compatibility) we assume the 2GHz band for
> > channels below 14.
> > 
> > Signed-off-by: Bruno Randolf <br1@einfach.org>
> > ---
> > -int ieee80211_channel_to_frequency(int chan)
> > +int ieee80211_channel_to_frequency(int chan, enum ieee80211_band band)
> >  {
> > -       if (chan < 14)
> > -               return 2407 + chan * 5;
> > -
> > -       if (chan == 14)
> > -               return 2484;
> > -
> > -       /* FIXME: 802.11j 17.3.8.3.2 */
> > -       return (chan + 1000) * 5;
> > +       /* see 802.11 17.3.8.3.2 and Annex J
> > +        * there are overlapping channel numbers in 5GHz and 2GHz bands
> > */ +       if (band == IEEE80211_BAND_5GHZ) {
> > +               if (chan >= 182 && chan <= 196)
> > +                       return 4000 + chan * 5;
> > +               else
> > +                       return 5000 + chan * 5;
> > +       } else { /* IEEE80211_BAND_2GHZ */
> > +               if (chan == 14)
> > +                       return 2484;
> > +               else if (chan < 14)
> > +                       return 2407 + chan * 5;
> > +               else
> > +                       return 0; /* not supported */
> > +       }
> >  }
> >  EXPORT_SYMBOL(ieee80211_channel_to_frequency);
> > 
> >  int ieee80211_frequency_to_channel(int freq)
> >  {
> > +       /* see 802.11 17.3.8.3.2 and Annex J */
> >        if (freq == 2484)
> >                return 14;
> > -
> > -       if (freq < 2484)
> > +       else if (freq < 2484)
> >                return (freq - 2407) / 5;
> > -
> > -       /* FIXME: 802.11j 17.3.8.3.2 */
> > -       return freq/5 - 1000;
> > +       else if (freq >= 4910 && freq <= 4980)
> > +               return (freq - 4000) / 5;
> > +       else
> > +               return (freq - 5000) / 5;
> >  }
> >  EXPORT_SYMBOL(ieee80211_frequency_to_channel);
> 
> You don't have to use them, but there are a few channel/frequency
> conversion routines in include/ieee80211.h which could be reused in
> these functions.

Thanks for that info, I didn't know about those functions. I just checked 
them and it seems most of them are not used, AFAICT:

ieee80211_fhss_chan_to_freq - not used
ieee80211_freq_to_fhss_chan - not used
ieee80211_hr_chan_to_freq - not used
ieee80211_freq_to_hr_chan - not used
ieee80211_erp_chan_to_freq - not used
ieee80211_freq_to_erp_chan - not used
ieee80211_ofdm_chan_to_freq - not used
ieee80211_freq_to_ofdm_chan - not used

The only two which are used are for 2GHz channels:

ieee80211_dsss_chan_to_freq - atmel, airo, wl3501_cs, orinoco, rndis_wlan
ieee80211_freq_to_dsss_chan - atmel, airo, orinoco, zd1201

Anyhow i guess it would make sense to have a common channel to frequency 
mapping function for mac80211 and other wireless drivers? The problem is now 
we have to use enum ieee80211_band which is defined cfg80211.h...

Any opinions?

bruno

^ permalink raw reply

* Re: [PATCH RFC] mac80211: Extend channel to frequency mapping for 802.11j
From: Bruno Randolf @ 2010-12-28  9:39 UTC (permalink / raw)
  To: Jouni Malinen; +Cc: Johannes Berg, linville, linux-wireless, mcgrof
In-Reply-To: <20101228092510.GA22967@jm.kir.nu>

On Tue December 28 2010 18:25:10 Jouni Malinen wrote:
> On Tue, Dec 28, 2010 at 10:08:02AM +0100, Johannes Berg wrote:
> > On Tue, 2010-12-28 at 11:01 +0200, Jouni Malinen wrote:
> > > Quite a few.. At least 4.85 GHz and 3.0 GHz for 20 MHz channels and
> > > more for 5 and 10 MHz channels (4.9375 GHz, 4.89 GHz, 3.0025 GHz,
> > > 4.0025 GHz, 5.0025 GHz) in channels defined by IEEE 802.11.
> > 
> > That's what I kinda thought ... doesn't that mean this patch is
> > insufficient?
> 
> Depends on what it is trying to achieve. Based on the Subject: line, it
> aims to add support for channels defined in 802.11j and it does indeed
> seem to do that (most of those odd channel starting frequencies come
> from 802.11y). If the goal were to cover all channels defined in the
> current IEEE 802.11 standard, then sure, it would be insufficient, but
> it is not like we support 3.6 GHz band or sub-20 MHz channels anyway, so
> only the 4.85 GHz starting frequency for some emergency channels from
> 802.11y would not be covered.

Well, yeah, I'm was only concerned about the 802.11j part. And I left out all 
stuff for non 20MHz channels. If it's needed these functions can be extended 
more later... The Japanese need 802.11j now, not a theoretically complete 
channel to frequency mapping... ;)

bruno

^ permalink raw reply

* Re: Patches submitted should apply to which git repository?
From: Johannes Berg @ 2010-12-28  9:33 UTC (permalink / raw)
  To: Naveenan; +Cc: linux-wireless
In-Reply-To: <AANLkTinxwNuZ1QxBKVMLycS=kmCmB1A9fpKrQYDH+TZV@mail.gmail.com>

On Tue, 2010-12-28 at 03:28 -0600, Naveenan wrote:
> [I apologize, I am resending this email with CC to the list]
> 
> >> I would say that the fix is not a critical one would would be useful
> >> if applied to wireless-2.6 too.
> >
> > Yes, if it's an important fix then you would have to send two versions.
> > Without seeing it, I can offer no advice on whether it is important
> > enough though.
> 
> Thanks a lot. I guess I will include the git repository I am diffing
> against after the "---" marker so that it would be applied to the
> right repository. Could you let me know if this style of sending
> patches is ok? I kind of would like to not send a patch and have it
> rejected due to a merge conflict :)

Yes, you can put anything after the first --- marker.

You can also indicate it in the subject: if it's intended for the
current kernel release still -- which is kinda late -- you can say
"[PATCH 2.6.37] mac80211: foobar"

johannes


^ permalink raw reply

* Re: Patches submitted should apply to which git repository?
From: Naveenan @ 2010-12-28  9:28 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <1293527720.3526.3.camel@jlt3.sipsolutions.net>

[I apologize, I am resending this email with CC to the list]

>> I would say that the fix is not a critical one would would be useful
>> if applied to wireless-2.6 too.
>
> Yes, if it's an important fix then you would have to send two versions.
> Without seeing it, I can offer no advice on whether it is important
> enough though.

Thanks a lot. I guess I will include the git repository I am diffing
against after the "---" marker so that it would be applied to the
right repository. Could you let me know if this style of sending
patches is ok? I kind of would like to not send a patch and have it
rejected due to a merge conflict :)

Thanks

^ permalink raw reply

* Re: [PATCH RFC] mac80211: Extend channel to frequency mapping for 802.11j
From: Jouni Malinen @ 2010-12-28  9:25 UTC (permalink / raw)
  To: Johannes Berg; +Cc: Bruno Randolf, linville, linux-wireless, mcgrof
In-Reply-To: <1293527282.3526.2.camel@jlt3.sipsolutions.net>

On Tue, Dec 28, 2010 at 10:08:02AM +0100, Johannes Berg wrote:
> On Tue, 2010-12-28 at 11:01 +0200, Jouni Malinen wrote:
> > Quite a few.. At least 4.85 GHz and 3.0 GHz for 20 MHz channels and more
> > for 5 and 10 MHz channels (4.9375 GHz, 4.89 GHz, 3.0025 GHz, 4.0025 GHz,
> > 5.0025 GHz) in channels defined by IEEE 802.11.
> 
> That's what I kinda thought ... doesn't that mean this patch is
> insufficient?

Depends on what it is trying to achieve. Based on the Subject: line, it
aims to add support for channels defined in 802.11j and it does indeed
seem to do that (most of those odd channel starting frequencies come
from 802.11y). If the goal were to cover all channels defined in the
current IEEE 802.11 standard, then sure, it would be insufficient, but
it is not like we support 3.6 GHz band or sub-20 MHz channels anyway, so
only the 4.85 GHz starting frequency for some emergency channels from
802.11y would not be covered.

-- 
Jouni Malinen                                            PGP id EFC895FA

^ permalink raw reply

* Re: Patches submitted should apply to which git repository?
From: Johannes Berg @ 2010-12-28  9:15 UTC (permalink / raw)
  To: Naveenan; +Cc: linux-wireless
In-Reply-To: <AANLkTik9=r8tCouEg0joexH0_S9+WPfyDGDzq5fbMKOe@mail.gmail.com>

On Tue, 2010-12-28 at 03:12 -0600, Naveenan wrote:

> Would it be ok if I can send 2 different patches for both these 2 versions?
> 
> Unfortunately someone changed a line of code (that is a few lines
> before my patch
> but not related to it) in a recent commit to wireless-testing and this
> makes the patch
> not apply-able to both wireless-2.6 and wireless-next.
> 
> I would say that the fix is not a critical one would would be useful
> if applied to wireless-2.6 too.

Yes, if it's an important fix then you would have to send two versions.
Without seeing it, I can offer no advice on whether it is important
enough though.

johannes


^ permalink raw reply

* Re: Patches submitted should apply to which git repository?
From: Naveenan @ 2010-12-28  9:12 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <1293526293.3526.1.camel@jlt3.sipsolutions.net>

Hi Johannes,

Thanks for your email.

>> I went through:
>> http://wireless.kernel.org/en/developers/Documentation/SubmittingPatches
>> but couldn't find this information there so was hoping someone could
>> point the exact git repository. My current patch applies to
>> wireless-testing but doesn't apply to wireless-2.6 (due to a trivial
>> merge conflict) . The changes I'm making are to mac80211.
>
> If they're fixes and required in wireless-2.6, then you should make them
> apply there, but ask yourself if they really need to be there. If not,
> you can typically just submit them on top of wireless-testing, although
> they will have to be applied to wireless-next-2.6.

Would it be ok if I can send 2 different patches for both these 2 versions?

Unfortunately someone changed a line of code (that is a few lines
before my patch
but not related to it) in a recent commit to wireless-testing and this
makes the patch
not apply-able to both wireless-2.6 and wireless-next.

I would say that the fix is not a critical one would would be useful
if applied to
wireless-2.6 too.

Thanks

^ permalink raw reply

* Re: [PATCH RFC] mac80211: Extend channel to frequency mapping for 802.11j
From: Johannes Berg @ 2010-12-28  9:08 UTC (permalink / raw)
  To: Jouni Malinen; +Cc: Bruno Randolf, linville, linux-wireless, mcgrof
In-Reply-To: <20101228090102.GA22580@jm.kir.nu>

On Tue, 2010-12-28 at 11:01 +0200, Jouni Malinen wrote:
> On Tue, Dec 28, 2010 at 09:38:33AM +0100, Johannes Berg wrote:
> > Not really. I guess it seems fine. Do you know if there are ever any
> > starting values used other than 4900 and 5000?
> 
> Quite a few.. At least 4.85 GHz and 3.0 GHz for 20 MHz channels and more
> for 5 and 10 MHz channels (4.9375 GHz, 4.89 GHz, 3.0025 GHz, 4.0025 GHz,
> 5.0025 GHz) in channels defined by IEEE 802.11.

That's what I kinda thought ... doesn't that mean this patch is
insufficient?

johannes


^ permalink raw reply

* Re: [PATCH RFC] mac80211: Extend channel to frequency mapping for 802.11j
From: Jouni Malinen @ 2010-12-28  9:01 UTC (permalink / raw)
  To: Johannes Berg; +Cc: Bruno Randolf, linville, linux-wireless, mcgrof
In-Reply-To: <1293525513.3526.0.camel@jlt3.sipsolutions.net>

On Tue, Dec 28, 2010 at 09:38:33AM +0100, Johannes Berg wrote:
> Not really. I guess it seems fine. Do you know if there are ever any
> starting values used other than 4900 and 5000?

Quite a few.. At least 4.85 GHz and 3.0 GHz for 20 MHz channels and more
for 5 and 10 MHz channels (4.9375 GHz, 4.89 GHz, 3.0025 GHz, 4.0025 GHz,
5.0025 GHz) in channels defined by IEEE 802.11.

-- 
Jouni Malinen                                            PGP id EFC895FA

^ permalink raw reply

* [PATCH v2 6/6] ath9k_htc: Move LED/RFKILL code to htc_drv_gpio.c
From: Sujith @ 2010-12-28  8:58 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Sujith.Manoharan

From: Sujith Manoharan <Sujith.Manoharan@atheros.com>

And add the copyright/license header.

Signed-off-by: Sujith Manoharan <Sujith.Manoharan@atheros.com>
---
 drivers/net/wireless/ath/ath9k/htc.h          |    5 +
 drivers/net/wireless/ath/ath9k/htc_drv_gpio.c |  327 +++++++++++++++++++++++++
 drivers/net/wireless/ath/ath9k/htc_drv_main.c |  313 +-----------------------
 3 files changed, 333 insertions(+), 312 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index 34456a8..a099b3e 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -459,8 +459,13 @@ void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv);
 void ath9k_ps_work(struct work_struct *work);
 bool ath9k_htc_setpower(struct ath9k_htc_priv *priv,
 			enum ath9k_power_mode mode);
+void ath_update_txpow(struct ath9k_htc_priv *priv);
 
 void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv);
+void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw);
+void ath9k_htc_radio_enable(struct ieee80211_hw *hw);
+void ath9k_htc_radio_disable(struct ieee80211_hw *hw);
+void ath9k_led_stop_brightness(struct ath9k_htc_priv *priv);
 void ath9k_init_leds(struct ath9k_htc_priv *priv);
 void ath9k_deinit_leds(struct ath9k_htc_priv *priv);
 
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
index 283ff97..fe70f67 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (c) 2010 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
 #include "htc.h"
 
 /******************/
@@ -131,3 +147,314 @@ void ath_htc_cancel_btcoex_work(struct ath9k_htc_priv *priv)
 	cancel_delayed_work_sync(&priv->coex_period_work);
 	cancel_delayed_work_sync(&priv->duty_cycle_work);
 }
+
+/*******/
+/* LED */
+/*******/
+
+static void ath9k_led_blink_work(struct work_struct *work)
+{
+	struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv,
+						   ath9k_led_blink_work.work);
+
+	if (!(priv->op_flags & OP_LED_ASSOCIATED))
+		return;
+
+	if ((priv->led_on_duration == ATH_LED_ON_DURATION_IDLE) ||
+	    (priv->led_off_duration == ATH_LED_OFF_DURATION_IDLE))
+		ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 0);
+	else
+		ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin,
+				  (priv->op_flags & OP_LED_ON) ? 1 : 0);
+
+	ieee80211_queue_delayed_work(priv->hw,
+				     &priv->ath9k_led_blink_work,
+				     (priv->op_flags & OP_LED_ON) ?
+				     msecs_to_jiffies(priv->led_off_duration) :
+				     msecs_to_jiffies(priv->led_on_duration));
+
+	priv->led_on_duration = priv->led_on_cnt ?
+		max((ATH_LED_ON_DURATION_IDLE - priv->led_on_cnt), 25) :
+		ATH_LED_ON_DURATION_IDLE;
+	priv->led_off_duration = priv->led_off_cnt ?
+		max((ATH_LED_OFF_DURATION_IDLE - priv->led_off_cnt), 10) :
+		ATH_LED_OFF_DURATION_IDLE;
+	priv->led_on_cnt = priv->led_off_cnt = 0;
+
+	if (priv->op_flags & OP_LED_ON)
+		priv->op_flags &= ~OP_LED_ON;
+	else
+		priv->op_flags |= OP_LED_ON;
+}
+
+static void ath9k_led_brightness_work(struct work_struct *work)
+{
+	struct ath_led *led = container_of(work, struct ath_led,
+					   brightness_work.work);
+	struct ath9k_htc_priv *priv = led->priv;
+
+	switch (led->brightness) {
+	case LED_OFF:
+		if (led->led_type == ATH_LED_ASSOC ||
+		    led->led_type == ATH_LED_RADIO) {
+			ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin,
+					  (led->led_type == ATH_LED_RADIO));
+			priv->op_flags &= ~OP_LED_ASSOCIATED;
+			if (led->led_type == ATH_LED_RADIO)
+				priv->op_flags &= ~OP_LED_ON;
+		} else {
+			priv->led_off_cnt++;
+		}
+		break;
+	case LED_FULL:
+		if (led->led_type == ATH_LED_ASSOC) {
+			priv->op_flags |= OP_LED_ASSOCIATED;
+			ieee80211_queue_delayed_work(priv->hw,
+					     &priv->ath9k_led_blink_work, 0);
+		} else if (led->led_type == ATH_LED_RADIO) {
+			ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 0);
+			priv->op_flags |= OP_LED_ON;
+		} else {
+			priv->led_on_cnt++;
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+static void ath9k_led_brightness(struct led_classdev *led_cdev,
+				 enum led_brightness brightness)
+{
+	struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev);
+	struct ath9k_htc_priv *priv = led->priv;
+
+	led->brightness = brightness;
+	if (!(priv->op_flags & OP_LED_DEINIT))
+		ieee80211_queue_delayed_work(priv->hw,
+					     &led->brightness_work, 0);
+}
+
+void ath9k_led_stop_brightness(struct ath9k_htc_priv *priv)
+{
+	cancel_delayed_work_sync(&priv->radio_led.brightness_work);
+	cancel_delayed_work_sync(&priv->assoc_led.brightness_work);
+	cancel_delayed_work_sync(&priv->tx_led.brightness_work);
+	cancel_delayed_work_sync(&priv->rx_led.brightness_work);
+}
+
+static int ath9k_register_led(struct ath9k_htc_priv *priv, struct ath_led *led,
+			      char *trigger)
+{
+	int ret;
+
+	led->priv = priv;
+	led->led_cdev.name = led->name;
+	led->led_cdev.default_trigger = trigger;
+	led->led_cdev.brightness_set = ath9k_led_brightness;
+
+	ret = led_classdev_register(wiphy_dev(priv->hw->wiphy), &led->led_cdev);
+	if (ret)
+		ath_err(ath9k_hw_common(priv->ah),
+			"Failed to register led:%s", led->name);
+	else
+		led->registered = 1;
+
+	INIT_DELAYED_WORK(&led->brightness_work, ath9k_led_brightness_work);
+
+	return ret;
+}
+
+static void ath9k_unregister_led(struct ath_led *led)
+{
+	if (led->registered) {
+		led_classdev_unregister(&led->led_cdev);
+		led->registered = 0;
+	}
+}
+
+void ath9k_deinit_leds(struct ath9k_htc_priv *priv)
+{
+	priv->op_flags |= OP_LED_DEINIT;
+	ath9k_unregister_led(&priv->assoc_led);
+	priv->op_flags &= ~OP_LED_ASSOCIATED;
+	ath9k_unregister_led(&priv->tx_led);
+	ath9k_unregister_led(&priv->rx_led);
+	ath9k_unregister_led(&priv->radio_led);
+}
+
+void ath9k_init_leds(struct ath9k_htc_priv *priv)
+{
+	char *trigger;
+	int ret;
+
+	if (AR_SREV_9287(priv->ah))
+		priv->ah->led_pin = ATH_LED_PIN_9287;
+	else if (AR_SREV_9271(priv->ah))
+		priv->ah->led_pin = ATH_LED_PIN_9271;
+	else if (AR_DEVID_7010(priv->ah))
+		priv->ah->led_pin = ATH_LED_PIN_7010;
+	else
+		priv->ah->led_pin = ATH_LED_PIN_DEF;
+
+	/* Configure gpio 1 for output */
+	ath9k_hw_cfg_output(priv->ah, priv->ah->led_pin,
+			    AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+	/* LED off, active low */
+	ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1);
+
+	INIT_DELAYED_WORK(&priv->ath9k_led_blink_work, ath9k_led_blink_work);
+
+	trigger = ieee80211_get_radio_led_name(priv->hw);
+	snprintf(priv->radio_led.name, sizeof(priv->radio_led.name),
+		"ath9k-%s::radio", wiphy_name(priv->hw->wiphy));
+	ret = ath9k_register_led(priv, &priv->radio_led, trigger);
+	priv->radio_led.led_type = ATH_LED_RADIO;
+	if (ret)
+		goto fail;
+
+	trigger = ieee80211_get_assoc_led_name(priv->hw);
+	snprintf(priv->assoc_led.name, sizeof(priv->assoc_led.name),
+		"ath9k-%s::assoc", wiphy_name(priv->hw->wiphy));
+	ret = ath9k_register_led(priv, &priv->assoc_led, trigger);
+	priv->assoc_led.led_type = ATH_LED_ASSOC;
+	if (ret)
+		goto fail;
+
+	trigger = ieee80211_get_tx_led_name(priv->hw);
+	snprintf(priv->tx_led.name, sizeof(priv->tx_led.name),
+		"ath9k-%s::tx", wiphy_name(priv->hw->wiphy));
+	ret = ath9k_register_led(priv, &priv->tx_led, trigger);
+	priv->tx_led.led_type = ATH_LED_TX;
+	if (ret)
+		goto fail;
+
+	trigger = ieee80211_get_rx_led_name(priv->hw);
+	snprintf(priv->rx_led.name, sizeof(priv->rx_led.name),
+		"ath9k-%s::rx", wiphy_name(priv->hw->wiphy));
+	ret = ath9k_register_led(priv, &priv->rx_led, trigger);
+	priv->rx_led.led_type = ATH_LED_RX;
+	if (ret)
+		goto fail;
+
+	priv->op_flags &= ~OP_LED_DEINIT;
+
+	return;
+
+fail:
+	cancel_delayed_work_sync(&priv->ath9k_led_blink_work);
+	ath9k_deinit_leds(priv);
+}
+
+/*******************/
+/*	Rfkill	   */
+/*******************/
+
+static bool ath_is_rfkill_set(struct ath9k_htc_priv *priv)
+{
+	return ath9k_hw_gpio_get(priv->ah, priv->ah->rfkill_gpio) ==
+		priv->ah->rfkill_polarity;
+}
+
+void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw)
+{
+	struct ath9k_htc_priv *priv = hw->priv;
+	bool blocked = !!ath_is_rfkill_set(priv);
+
+	wiphy_rfkill_set_hw_state(hw->wiphy, blocked);
+}
+
+void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv)
+{
+	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
+		wiphy_rfkill_start_polling(priv->hw->wiphy);
+}
+
+void ath9k_htc_radio_enable(struct ieee80211_hw *hw)
+{
+	struct ath9k_htc_priv *priv = hw->priv;
+	struct ath_hw *ah = priv->ah;
+	struct ath_common *common = ath9k_hw_common(ah);
+	int ret;
+	u8 cmd_rsp;
+
+	if (!ah->curchan)
+		ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
+
+	/* Reset the HW */
+	ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
+	if (ret) {
+		ath_err(common,
+			"Unable to reset hardware; reset status %d (freq %u MHz)\n",
+			ret, ah->curchan->channel);
+	}
+
+	ath_update_txpow(priv);
+
+	/* Start RX */
+	WMI_CMD(WMI_START_RECV_CMDID);
+	ath9k_host_rx_init(priv);
+
+	/* Start TX */
+	htc_start(priv->htc);
+	spin_lock_bh(&priv->tx_lock);
+	priv->tx_queues_stop = false;
+	spin_unlock_bh(&priv->tx_lock);
+	ieee80211_wake_queues(hw);
+
+	WMI_CMD(WMI_ENABLE_INTR_CMDID);
+
+	/* Enable LED */
+	ath9k_hw_cfg_output(ah, ah->led_pin,
+			    AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+	ath9k_hw_set_gpio(ah, ah->led_pin, 0);
+}
+
+void ath9k_htc_radio_disable(struct ieee80211_hw *hw)
+{
+	struct ath9k_htc_priv *priv = hw->priv;
+	struct ath_hw *ah = priv->ah;
+	struct ath_common *common = ath9k_hw_common(ah);
+	int ret;
+	u8 cmd_rsp;
+
+	ath9k_htc_ps_wakeup(priv);
+
+	/* Disable LED */
+	ath9k_hw_set_gpio(ah, ah->led_pin, 1);
+	ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
+
+	WMI_CMD(WMI_DISABLE_INTR_CMDID);
+
+	/* Stop TX */
+	ieee80211_stop_queues(hw);
+	htc_stop(priv->htc);
+	WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
+	skb_queue_purge(&priv->tx_queue);
+
+	/* Stop RX */
+	WMI_CMD(WMI_STOP_RECV_CMDID);
+
+	/*
+	 * The MIB counters have to be disabled here,
+	 * since the target doesn't do it.
+	 */
+	ath9k_hw_disable_mib_counters(ah);
+
+	if (!ah->curchan)
+		ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
+
+	/* Reset the HW */
+	ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
+	if (ret) {
+		ath_err(common,
+			"Unable to reset hardware; reset status %d (freq %u MHz)\n",
+			ret, ah->curchan->channel);
+	}
+
+	/* Disable the PHY */
+	ath9k_hw_phy_disable(ah);
+
+	ath9k_htc_ps_restore(priv);
+	ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP);
+}
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 6da5e88..ad3dd31 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -24,7 +24,7 @@ static struct dentry *ath9k_debugfs_root;
 /* Utilities */
 /*************/
 
-static void ath_update_txpow(struct ath9k_htc_priv *priv)
+void ath_update_txpow(struct ath9k_htc_priv *priv)
 {
 	struct ath_hw *ah = priv->ah;
 
@@ -840,317 +840,6 @@ set_timer:
 				     msecs_to_jiffies(cal_interval));
 }
 
-/*******/
-/* LED */
-/*******/
-
-static void ath9k_led_blink_work(struct work_struct *work)
-{
-	struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv,
-						   ath9k_led_blink_work.work);
-
-	if (!(priv->op_flags & OP_LED_ASSOCIATED))
-		return;
-
-	if ((priv->led_on_duration == ATH_LED_ON_DURATION_IDLE) ||
-	    (priv->led_off_duration == ATH_LED_OFF_DURATION_IDLE))
-		ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 0);
-	else
-		ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin,
-				  (priv->op_flags & OP_LED_ON) ? 1 : 0);
-
-	ieee80211_queue_delayed_work(priv->hw,
-				     &priv->ath9k_led_blink_work,
-				     (priv->op_flags & OP_LED_ON) ?
-				     msecs_to_jiffies(priv->led_off_duration) :
-				     msecs_to_jiffies(priv->led_on_duration));
-
-	priv->led_on_duration = priv->led_on_cnt ?
-		max((ATH_LED_ON_DURATION_IDLE - priv->led_on_cnt), 25) :
-		ATH_LED_ON_DURATION_IDLE;
-	priv->led_off_duration = priv->led_off_cnt ?
-		max((ATH_LED_OFF_DURATION_IDLE - priv->led_off_cnt), 10) :
-		ATH_LED_OFF_DURATION_IDLE;
-	priv->led_on_cnt = priv->led_off_cnt = 0;
-
-	if (priv->op_flags & OP_LED_ON)
-		priv->op_flags &= ~OP_LED_ON;
-	else
-		priv->op_flags |= OP_LED_ON;
-}
-
-static void ath9k_led_brightness_work(struct work_struct *work)
-{
-	struct ath_led *led = container_of(work, struct ath_led,
-					   brightness_work.work);
-	struct ath9k_htc_priv *priv = led->priv;
-
-	switch (led->brightness) {
-	case LED_OFF:
-		if (led->led_type == ATH_LED_ASSOC ||
-		    led->led_type == ATH_LED_RADIO) {
-			ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin,
-					  (led->led_type == ATH_LED_RADIO));
-			priv->op_flags &= ~OP_LED_ASSOCIATED;
-			if (led->led_type == ATH_LED_RADIO)
-				priv->op_flags &= ~OP_LED_ON;
-		} else {
-			priv->led_off_cnt++;
-		}
-		break;
-	case LED_FULL:
-		if (led->led_type == ATH_LED_ASSOC) {
-			priv->op_flags |= OP_LED_ASSOCIATED;
-			ieee80211_queue_delayed_work(priv->hw,
-					     &priv->ath9k_led_blink_work, 0);
-		} else if (led->led_type == ATH_LED_RADIO) {
-			ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 0);
-			priv->op_flags |= OP_LED_ON;
-		} else {
-			priv->led_on_cnt++;
-		}
-		break;
-	default:
-		break;
-	}
-}
-
-static void ath9k_led_brightness(struct led_classdev *led_cdev,
-				 enum led_brightness brightness)
-{
-	struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev);
-	struct ath9k_htc_priv *priv = led->priv;
-
-	led->brightness = brightness;
-	if (!(priv->op_flags & OP_LED_DEINIT))
-		ieee80211_queue_delayed_work(priv->hw,
-					     &led->brightness_work, 0);
-}
-
-static void ath9k_led_stop_brightness(struct ath9k_htc_priv *priv)
-{
-	cancel_delayed_work_sync(&priv->radio_led.brightness_work);
-	cancel_delayed_work_sync(&priv->assoc_led.brightness_work);
-	cancel_delayed_work_sync(&priv->tx_led.brightness_work);
-	cancel_delayed_work_sync(&priv->rx_led.brightness_work);
-}
-
-static int ath9k_register_led(struct ath9k_htc_priv *priv, struct ath_led *led,
-			      char *trigger)
-{
-	int ret;
-
-	led->priv = priv;
-	led->led_cdev.name = led->name;
-	led->led_cdev.default_trigger = trigger;
-	led->led_cdev.brightness_set = ath9k_led_brightness;
-
-	ret = led_classdev_register(wiphy_dev(priv->hw->wiphy), &led->led_cdev);
-	if (ret)
-		ath_err(ath9k_hw_common(priv->ah),
-			"Failed to register led:%s", led->name);
-	else
-		led->registered = 1;
-
-	INIT_DELAYED_WORK(&led->brightness_work, ath9k_led_brightness_work);
-
-	return ret;
-}
-
-static void ath9k_unregister_led(struct ath_led *led)
-{
-	if (led->registered) {
-		led_classdev_unregister(&led->led_cdev);
-		led->registered = 0;
-	}
-}
-
-void ath9k_deinit_leds(struct ath9k_htc_priv *priv)
-{
-	priv->op_flags |= OP_LED_DEINIT;
-	ath9k_unregister_led(&priv->assoc_led);
-	priv->op_flags &= ~OP_LED_ASSOCIATED;
-	ath9k_unregister_led(&priv->tx_led);
-	ath9k_unregister_led(&priv->rx_led);
-	ath9k_unregister_led(&priv->radio_led);
-}
-
-void ath9k_init_leds(struct ath9k_htc_priv *priv)
-{
-	char *trigger;
-	int ret;
-
-	if (AR_SREV_9287(priv->ah))
-		priv->ah->led_pin = ATH_LED_PIN_9287;
-	else if (AR_SREV_9271(priv->ah))
-		priv->ah->led_pin = ATH_LED_PIN_9271;
-	else if (AR_DEVID_7010(priv->ah))
-		priv->ah->led_pin = ATH_LED_PIN_7010;
-	else
-		priv->ah->led_pin = ATH_LED_PIN_DEF;
-
-	/* Configure gpio 1 for output */
-	ath9k_hw_cfg_output(priv->ah, priv->ah->led_pin,
-			    AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
-	/* LED off, active low */
-	ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1);
-
-	INIT_DELAYED_WORK(&priv->ath9k_led_blink_work, ath9k_led_blink_work);
-
-	trigger = ieee80211_get_radio_led_name(priv->hw);
-	snprintf(priv->radio_led.name, sizeof(priv->radio_led.name),
-		"ath9k-%s::radio", wiphy_name(priv->hw->wiphy));
-	ret = ath9k_register_led(priv, &priv->radio_led, trigger);
-	priv->radio_led.led_type = ATH_LED_RADIO;
-	if (ret)
-		goto fail;
-
-	trigger = ieee80211_get_assoc_led_name(priv->hw);
-	snprintf(priv->assoc_led.name, sizeof(priv->assoc_led.name),
-		"ath9k-%s::assoc", wiphy_name(priv->hw->wiphy));
-	ret = ath9k_register_led(priv, &priv->assoc_led, trigger);
-	priv->assoc_led.led_type = ATH_LED_ASSOC;
-	if (ret)
-		goto fail;
-
-	trigger = ieee80211_get_tx_led_name(priv->hw);
-	snprintf(priv->tx_led.name, sizeof(priv->tx_led.name),
-		"ath9k-%s::tx", wiphy_name(priv->hw->wiphy));
-	ret = ath9k_register_led(priv, &priv->tx_led, trigger);
-	priv->tx_led.led_type = ATH_LED_TX;
-	if (ret)
-		goto fail;
-
-	trigger = ieee80211_get_rx_led_name(priv->hw);
-	snprintf(priv->rx_led.name, sizeof(priv->rx_led.name),
-		"ath9k-%s::rx", wiphy_name(priv->hw->wiphy));
-	ret = ath9k_register_led(priv, &priv->rx_led, trigger);
-	priv->rx_led.led_type = ATH_LED_RX;
-	if (ret)
-		goto fail;
-
-	priv->op_flags &= ~OP_LED_DEINIT;
-
-	return;
-
-fail:
-	cancel_delayed_work_sync(&priv->ath9k_led_blink_work);
-	ath9k_deinit_leds(priv);
-}
-
-/*******************/
-/*	Rfkill	   */
-/*******************/
-
-static bool ath_is_rfkill_set(struct ath9k_htc_priv *priv)
-{
-	return ath9k_hw_gpio_get(priv->ah, priv->ah->rfkill_gpio) ==
-		priv->ah->rfkill_polarity;
-}
-
-static void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw)
-{
-	struct ath9k_htc_priv *priv = hw->priv;
-	bool blocked = !!ath_is_rfkill_set(priv);
-
-	wiphy_rfkill_set_hw_state(hw->wiphy, blocked);
-}
-
-void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv)
-{
-	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
-		wiphy_rfkill_start_polling(priv->hw->wiphy);
-}
-
-static void ath9k_htc_radio_enable(struct ieee80211_hw *hw)
-{
-	struct ath9k_htc_priv *priv = hw->priv;
-	struct ath_hw *ah = priv->ah;
-	struct ath_common *common = ath9k_hw_common(ah);
-	int ret;
-	u8 cmd_rsp;
-
-	if (!ah->curchan)
-		ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
-
-	/* Reset the HW */
-	ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
-	if (ret) {
-		ath_err(common,
-			"Unable to reset hardware; reset status %d (freq %u MHz)\n",
-			ret, ah->curchan->channel);
-	}
-
-	ath_update_txpow(priv);
-
-	/* Start RX */
-	WMI_CMD(WMI_START_RECV_CMDID);
-	ath9k_host_rx_init(priv);
-
-	/* Start TX */
-	htc_start(priv->htc);
-	spin_lock_bh(&priv->tx_lock);
-	priv->tx_queues_stop = false;
-	spin_unlock_bh(&priv->tx_lock);
-	ieee80211_wake_queues(hw);
-
-	WMI_CMD(WMI_ENABLE_INTR_CMDID);
-
-	/* Enable LED */
-	ath9k_hw_cfg_output(ah, ah->led_pin,
-			    AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
-	ath9k_hw_set_gpio(ah, ah->led_pin, 0);
-}
-
-static void ath9k_htc_radio_disable(struct ieee80211_hw *hw)
-{
-	struct ath9k_htc_priv *priv = hw->priv;
-	struct ath_hw *ah = priv->ah;
-	struct ath_common *common = ath9k_hw_common(ah);
-	int ret;
-	u8 cmd_rsp;
-
-	ath9k_htc_ps_wakeup(priv);
-
-	/* Disable LED */
-	ath9k_hw_set_gpio(ah, ah->led_pin, 1);
-	ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
-
-	WMI_CMD(WMI_DISABLE_INTR_CMDID);
-
-	/* Stop TX */
-	ieee80211_stop_queues(hw);
-	htc_stop(priv->htc);
-	WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
-	skb_queue_purge(&priv->tx_queue);
-
-	/* Stop RX */
-	WMI_CMD(WMI_STOP_RECV_CMDID);
-
-	/*
-	 * The MIB counters have to be disabled here,
-	 * since the target doesn't do it.
-	 */
-	ath9k_hw_disable_mib_counters(ah);
-
-	if (!ah->curchan)
-		ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
-
-	/* Reset the HW */
-	ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
-	if (ret) {
-		ath_err(common,
-			"Unable to reset hardware; reset status %d (freq %u MHz)\n",
-			ret, ah->curchan->channel);
-	}
-
-	/* Disable the PHY */
-	ath9k_hw_phy_disable(ah);
-
-	ath9k_htc_ps_restore(priv);
-	ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP);
-}
-
 /**********************/
 /* mac80211 Callbacks */
 /**********************/
-- 
1.7.3.4


^ permalink raw reply related

* [PATCH v2 5/6] ath9k_htc: Fix fast channel change
From: Sujith @ 2010-12-28  8:58 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Sujith.Manoharan

From: Sujith Manoharan <Sujith.Manoharan@atheros.com>

When returning to the operating channel, a full HW
reset has to be done instead of a fast channel change.
Since sw_scan_complete() is called after the config() call for the
home channel, we end up doing a FCC. Fix this issue by checking
the OFFCHANNEL flag to determine FCC.

Signed-off-by: Sujith Manoharan <Sujith.Manoharan@atheros.com>
---
 drivers/net/wireless/ath/ath9k/htc.h          |   19 +++++++++----------
 drivers/net/wireless/ath/ath9k/htc_drv_main.c |    8 ++------
 2 files changed, 11 insertions(+), 16 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index 1062274..34456a8 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -331,16 +331,15 @@ void ath_htc_cancel_btcoex_work(struct ath9k_htc_priv *priv);
 
 #define OP_INVALID		   BIT(0)
 #define OP_SCANNING		   BIT(1)
-#define OP_FULL_RESET		   BIT(2)
-#define OP_LED_ASSOCIATED	   BIT(3)
-#define OP_LED_ON		   BIT(4)
-#define OP_PREAMBLE_SHORT	   BIT(5)
-#define OP_PROTECT_ENABLE	   BIT(6)
-#define OP_ASSOCIATED		   BIT(7)
-#define OP_ENABLE_BEACON	   BIT(8)
-#define OP_LED_DEINIT		   BIT(9)
-#define OP_BT_PRIORITY_DETECTED    BIT(10)
-#define OP_BT_SCAN                 BIT(11)
+#define OP_LED_ASSOCIATED	   BIT(2)
+#define OP_LED_ON		   BIT(3)
+#define OP_PREAMBLE_SHORT	   BIT(4)
+#define OP_PROTECT_ENABLE	   BIT(5)
+#define OP_ASSOCIATED		   BIT(6)
+#define OP_ENABLE_BEACON	   BIT(7)
+#define OP_LED_DEINIT		   BIT(8)
+#define OP_BT_PRIORITY_DETECTED    BIT(9)
+#define OP_BT_SCAN                 BIT(10)
 
 struct ath9k_htc_priv {
 	struct device *dev;
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 07f10dd..6da5e88 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -177,7 +177,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
 	struct ath_hw *ah = priv->ah;
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ieee80211_conf *conf = &common->hw->conf;
-	bool fastcc = true;
+	bool fastcc;
 	struct ieee80211_channel *channel = hw->conf.channel;
 	struct ath9k_hw_cal_data *caldata;
 	enum htc_phymode mode;
@@ -188,8 +188,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
 	if (priv->op_flags & OP_INVALID)
 		return -EIO;
 
-	if (priv->op_flags & OP_FULL_RESET)
-		fastcc = false;
+	fastcc = !!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL);
 
 	ath9k_htc_ps_wakeup(priv);
 	htc_stop(priv->htc);
@@ -231,8 +230,6 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
 		goto err;
 
 	htc_start(priv->htc);
-
-	priv->op_flags &= ~OP_FULL_RESET;
 err:
 	ath9k_htc_ps_restore(priv);
 	return ret;
@@ -1847,7 +1844,6 @@ static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw)
 	spin_lock_bh(&priv->beacon_lock);
 	priv->op_flags &= ~OP_SCANNING;
 	spin_unlock_bh(&priv->beacon_lock);
-	priv->op_flags |= OP_FULL_RESET;
 	if (priv->op_flags & OP_ASSOCIATED) {
 		ath9k_htc_beacon_config(priv, priv->vif);
 		ath_start_ani(priv);
-- 
1.7.3.4


^ permalink raw reply related

* [PATCH v2 4/6] ath9k_htc: Handle FATAL events
From: Sujith @ 2010-12-28  8:58 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Sujith.Manoharan

From: Sujith Manoharan <Sujith.Manoharan@atheros.com>

The device has to be reset when a FATAL event is received.
Not doing so would leave the card in a non-working state.

Signed-off-by: Sujith Manoharan <Sujith.Manoharan@atheros.com>
---
 drivers/net/wireless/ath/ath9k/htc.h          |    6 ++-
 drivers/net/wireless/ath/ath9k/htc_drv_init.c |    8 ++-
 drivers/net/wireless/ath/ath9k/htc_drv_main.c |   57 ++++++++++++++++++++++++-
 drivers/net/wireless/ath/ath9k/wmi.c          |   18 +++++++-
 drivers/net/wireless/ath/ath9k/wmi.h          |    3 +-
 5 files changed, 84 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index e6c2f0a..1062274 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -377,7 +377,7 @@ struct ath9k_htc_priv {
 	struct ieee80211_vif *vif;
 	struct htc_beacon_config cur_beacon_conf;
 	unsigned int rxfilter;
-	struct tasklet_struct wmi_tasklet;
+	struct tasklet_struct swba_tasklet;
 	struct tasklet_struct rx_tasklet;
 	struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
 	struct ath9k_htc_rx rx;
@@ -385,6 +385,7 @@ struct ath9k_htc_priv {
 	struct sk_buff_head tx_queue;
 	struct delayed_work ath9k_ani_work;
 	struct work_struct ps_work;
+	struct work_struct fatal_work;
 
 	struct mutex htc_pm_lock;
 	unsigned long ps_usecount;
@@ -419,6 +420,8 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz)
 	common->bus_ops->read_cachesize(common, csz);
 }
 
+void ath9k_htc_reset(struct ath9k_htc_priv *priv);
+
 void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv);
 void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv,
 			     struct ieee80211_vif *vif);
@@ -434,6 +437,7 @@ void ath9k_htc_beaconep(void *drv_priv, struct sk_buff *skb,
 void ath9k_htc_station_work(struct work_struct *work);
 void ath9k_htc_aggr_work(struct work_struct *work);
 void ath9k_ani_work(struct work_struct *work);;
+void ath_start_ani(struct ath9k_htc_priv *priv);
 
 int ath9k_tx_init(struct ath9k_htc_priv *priv);
 void ath9k_tx_tasklet(unsigned long data);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index 724f545..9150ca6 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -142,7 +142,7 @@ static void ath9k_deinit_priv(struct ath9k_htc_priv *priv)
 {
 	ath9k_htc_exit_debug(priv->ah);
 	ath9k_hw_deinit(priv->ah);
-	tasklet_kill(&priv->wmi_tasklet);
+	tasklet_kill(&priv->swba_tasklet);
 	tasklet_kill(&priv->rx_tasklet);
 	tasklet_kill(&priv->tx_tasklet);
 	kfree(priv->ah);
@@ -647,13 +647,15 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
 	spin_lock_init(&priv->tx_lock);
 	mutex_init(&priv->mutex);
 	mutex_init(&priv->htc_pm_lock);
-	tasklet_init(&priv->wmi_tasklet, ath9k_wmi_tasklet,
+	tasklet_init(&priv->swba_tasklet, ath9k_swba_tasklet,
 		     (unsigned long)priv);
 	tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet,
 		     (unsigned long)priv);
-	tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet, (unsigned long)priv);
+	tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet,
+		     (unsigned long)priv);
 	INIT_DELAYED_WORK(&priv->ath9k_ani_work, ath9k_ani_work);
 	INIT_WORK(&priv->ps_work, ath9k_ps_work);
+	INIT_WORK(&priv->fatal_work, ath9k_fatal_work);
 
 	/*
 	 * Cache line size is used to size and align various
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 5f75f70..07f10dd 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -116,6 +116,60 @@ void ath9k_ps_work(struct work_struct *work)
 	ath9k_htc_setpower(priv, ATH9K_PM_NETWORK_SLEEP);
 }
 
+void ath9k_htc_reset(struct ath9k_htc_priv *priv)
+{
+	struct ath_hw *ah = priv->ah;
+	struct ath_common *common = ath9k_hw_common(ah);
+	struct ieee80211_channel *channel = priv->hw->conf.channel;
+	struct ath9k_hw_cal_data *caldata;
+	enum htc_phymode mode;
+	__be16 htc_mode;
+	u8 cmd_rsp;
+	int ret;
+
+	mutex_lock(&priv->mutex);
+	ath9k_htc_ps_wakeup(priv);
+
+	if (priv->op_flags & OP_ASSOCIATED)
+		cancel_delayed_work_sync(&priv->ath9k_ani_work);
+
+	ieee80211_stop_queues(priv->hw);
+	htc_stop(priv->htc);
+	WMI_CMD(WMI_DISABLE_INTR_CMDID);
+	WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
+	WMI_CMD(WMI_STOP_RECV_CMDID);
+
+	caldata = &priv->caldata[channel->hw_value];
+	ret = ath9k_hw_reset(ah, ah->curchan, caldata, false);
+	if (ret) {
+		ath_err(common,
+			"Unable to reset device (%u Mhz) reset status %d\n",
+			channel->center_freq, ret);
+	}
+
+	ath_update_txpow(priv);
+
+	WMI_CMD(WMI_START_RECV_CMDID);
+	ath9k_host_rx_init(priv);
+
+	mode = ath9k_htc_get_curmode(priv, ah->curchan);
+	htc_mode = cpu_to_be16(mode);
+	WMI_CMD_BUF(WMI_SET_MODE_CMDID, &htc_mode);
+
+	WMI_CMD(WMI_ENABLE_INTR_CMDID);
+	htc_start(priv->htc);
+
+	if (priv->op_flags & OP_ASSOCIATED) {
+		ath9k_htc_beacon_config(priv, priv->vif);
+		ath_start_ani(priv);
+	}
+
+	ieee80211_wake_queues(priv->hw);
+
+	ath9k_htc_ps_restore(priv);
+	mutex_unlock(&priv->mutex);
+}
+
 static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
 				 struct ieee80211_hw *hw,
 				 struct ath9k_channel *hchan)
@@ -690,7 +744,7 @@ void ath9k_htc_debug_remove_root(void)
 /* ANI */
 /*******/
 
-static void ath_start_ani(struct ath9k_htc_priv *priv)
+void ath_start_ani(struct ath9k_htc_priv *priv)
 {
 	struct ath_common *common = ath9k_hw_common(priv->ah);
 	unsigned long timestamp = jiffies_to_msecs(jiffies);
@@ -1219,6 +1273,7 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
 	u8 cmd_rsp;
 
 	/* Cancel all the running timers/work .. */
+	cancel_work_sync(&priv->fatal_work);
 	cancel_work_sync(&priv->ps_work);
 	cancel_delayed_work_sync(&priv->ath9k_led_blink_work);
 	ath9k_led_stop_brightness(priv);
diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c
index 573daca..dc862f5 100644
--- a/drivers/net/wireless/ath/ath9k/wmi.c
+++ b/drivers/net/wireless/ath/ath9k/wmi.c
@@ -120,7 +120,7 @@ void ath9k_deinit_wmi(struct ath9k_htc_priv *priv)
 	kfree(priv->wmi);
 }
 
-void ath9k_wmi_tasklet(unsigned long data)
+void ath9k_swba_tasklet(unsigned long data)
 {
 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data;
 	struct ath_common *common = ath9k_hw_common(priv->ah);
@@ -131,6 +131,16 @@ void ath9k_wmi_tasklet(unsigned long data)
 
 }
 
+void ath9k_fatal_work(struct work_struct *work)
+{
+	struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv,
+						   fatal_work);
+	struct ath_common *common = ath9k_hw_common(priv->ah);
+
+	ath_dbg(common, ATH_DBG_FATAL, "FATAL Event received, resetting device\n");
+	ath9k_htc_reset(priv);
+}
+
 static void ath9k_wmi_rsp_callback(struct wmi *wmi, struct sk_buff *skb)
 {
 	skb_pull(skb, sizeof(struct wmi_cmd_hdr));
@@ -163,7 +173,11 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb,
 		switch (cmd_id) {
 		case WMI_SWBA_EVENTID:
 			wmi->beacon_pending = *(u8 *)wmi_event;
-			tasklet_schedule(&wmi->drv_priv->wmi_tasklet);
+			tasklet_schedule(&wmi->drv_priv->swba_tasklet);
+			break;
+		case WMI_FATAL_EVENTID:
+			ieee80211_queue_work(wmi->drv_priv->hw,
+					     &wmi->drv_priv->fatal_work);
 			break;
 		case WMI_TXRATE_EVENTID:
 #ifdef CONFIG_ATH9K_HTC_DEBUGFS
diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h
index ac61074..4208427 100644
--- a/drivers/net/wireless/ath/ath9k/wmi.h
+++ b/drivers/net/wireless/ath/ath9k/wmi.h
@@ -117,7 +117,8 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
 		  u8 *cmd_buf, u32 cmd_len,
 		  u8 *rsp_buf, u32 rsp_len,
 		  u32 timeout);
-void ath9k_wmi_tasklet(unsigned long data);
+void ath9k_swba_tasklet(unsigned long data);
+void ath9k_fatal_work(struct work_struct *work);
 
 #define WMI_CMD(_wmi_cmd)						\
 	do {								\
-- 
1.7.3.4


^ permalink raw reply related


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