Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH 05/13] ath9k_hw: Fix async fifo for AR9287
From: Sujith @ 2010-06-01  9:44 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless

Async fifo is now enabled only for versions 1.3 and above.
Enable it in the appropriate place, in the reset routine,
instead of process_ini().

Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
---
 drivers/net/wireless/ath/ath9k/ar5008_phy.c |   11 -----
 drivers/net/wireless/ath/ath9k/ar9002_hw.c  |   24 ++++++++---
 drivers/net/wireless/ath/ath9k/hw.c         |    5 ++-
 drivers/net/wireless/ath/ath9k/hw.h         |    1 +
 drivers/net/wireless/ath/ath9k/reg.h        |   58 +++++++++++++++------------
 5 files changed, 55 insertions(+), 44 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
index c594814..cde411c 100644
--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
@@ -744,17 +744,6 @@ static int ar5008_hw_process_ini(struct ath_hw *ah,
 		return -EINVAL;
 	}
 
-	if (AR_SREV_9287_12_OR_LATER(ah)) {
-		/* Enable ASYNC FIFO */
-		REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
-				AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL);
-		REG_SET_BIT(ah, AR_PHY_MODE, AR_PHY_MODE_ASYNCFIFO);
-		REG_CLR_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
-				AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
-		REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
-				AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
-	}
-
 	/*
 	 * Set correct baseband to analog shift setting to
 	 * access analog chips.
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
index 748449c..7ba9dd6 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
@@ -18,6 +18,7 @@
 #include "ar5008_initvals.h"
 #include "ar9001_initvals.h"
 #include "ar9002_initvals.h"
+#include "ar9002_phy.h"
 
 /* General hardware code for the A5008/AR9001/AR9002 hadware families */
 
@@ -565,18 +566,29 @@ int ar9002_hw_rf_claim(struct ath_hw *ah)
 	return 0;
 }
 
+void ar9002_hw_enable_async_fifo(struct ath_hw *ah)
+{
+	if (AR_SREV_9287_13_OR_LATER(ah)) {
+		REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
+				AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL);
+		REG_SET_BIT(ah, AR_PHY_MODE, AR_PHY_MODE_ASYNCFIFO);
+		REG_CLR_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
+				AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
+		REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3,
+				AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
+	}
+}
+
 /*
- * Enable ASYNC FIFO
- *
  * If Async FIFO is enabled, the following counters change as MAC now runs
  * at 117 Mhz instead of 88/44MHz when async FIFO is disabled.
  *
  * The values below tested for ht40 2 chain.
  * Overwrite the delay/timeouts initialized in process ini.
  */
-void ar9002_hw_enable_async_fifo(struct ath_hw *ah)
+void ar9002_hw_update_async_fifo(struct ath_hw *ah)
 {
-	if (AR_SREV_9287_12_OR_LATER(ah)) {
+	if (AR_SREV_9287_13_OR_LATER(ah)) {
 		REG_WRITE(ah, AR_D_GBL_IFS_SIFS,
 			  AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR);
 		REG_WRITE(ah, AR_D_GBL_IFS_SLOT,
@@ -600,9 +612,9 @@ void ar9002_hw_enable_async_fifo(struct ath_hw *ah)
  */
 void ar9002_hw_enable_wep_aggregation(struct ath_hw *ah)
 {
-	if (AR_SREV_9287_12_OR_LATER(ah)) {
+	if (AR_SREV_9287_13_OR_LATER(ah)) {
 		REG_SET_BIT(ah, AR_PCU_MISC_MODE2,
-				AR_PCU_MISC_MODE2_ENABLE_AGGWEP);
+			    AR_PCU_MISC_MODE2_ENABLE_AGGWEP);
 	}
 }
 
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 45a9c84..1c541b4 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1303,6 +1303,9 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 	if (AR_SREV_9280_10_OR_LATER(ah))
 		REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE);
 
+	if (!AR_SREV_9300_20_OR_LATER(ah))
+		ar9002_hw_enable_async_fifo(ah);
+
 	r = ath9k_hw_process_ini(ah, chan);
 	if (r)
 		return r;
@@ -1375,7 +1378,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 	ath9k_hw_init_global_settings(ah);
 
 	if (!AR_SREV_9300_20_OR_LATER(ah)) {
-		ar9002_hw_enable_async_fifo(ah);
+		ar9002_hw_update_async_fifo(ah);
 		ar9002_hw_enable_wep_aggregation(ah);
 	}
 
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index a95e88d..f9cad8c 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -908,6 +908,7 @@ void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled,
 void ar9002_hw_cck_chan14_spread(struct ath_hw *ah);
 int ar9002_hw_rf_claim(struct ath_hw *ah);
 void ar9002_hw_enable_async_fifo(struct ath_hw *ah);
+void ar9002_hw_update_async_fifo(struct ath_hw *ah);
 void ar9002_hw_enable_wep_aggregation(struct ath_hw *ah);
 
 /*
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index 854e681..216c71b 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -759,32 +759,33 @@
 #define AR_SREV_REVISION2        	      0x00000F00
 #define AR_SREV_REVISION2_S     	      8
 
-#define AR_SREV_VERSION_5416_PCI               0xD
-#define AR_SREV_VERSION_5416_PCIE              0xC
-#define AR_SREV_REVISION_5416_10               0
-#define AR_SREV_REVISION_5416_20               1
-#define AR_SREV_REVISION_5416_22               2
-#define AR_SREV_VERSION_9100                  0x14
-#define AR_SREV_VERSION_9160        	      0x40
-#define AR_SREV_REVISION_9160_10    	      0
-#define AR_SREV_REVISION_9160_11    	      1
-#define AR_SREV_VERSION_9280                0x80
-#define AR_SREV_REVISION_9280_10            0
-#define AR_SREV_REVISION_9280_20            1
-#define AR_SREV_REVISION_9280_21            2
-#define AR_SREV_VERSION_9285                  0xC0
-#define AR_SREV_REVISION_9285_10              0
-#define AR_SREV_REVISION_9285_11              1
-#define AR_SREV_REVISION_9285_12              2
-#define AR_SREV_VERSION_9287                  0x180
-#define AR_SREV_REVISION_9287_10              0
-#define AR_SREV_REVISION_9287_11              1
-#define AR_SREV_REVISION_9287_12              2
-#define AR_SREV_VERSION_9271			0x140
-#define AR_SREV_REVISION_9271_10		0
-#define AR_SREV_REVISION_9271_11		1
-#define AR_SREV_VERSION_9300                  0x1c0
-#define AR_SREV_REVISION_9300_20              2 /* 2.0 and 2.1 */
+#define AR_SREV_VERSION_5416_PCI	0xD
+#define AR_SREV_VERSION_5416_PCIE	0xC
+#define AR_SREV_REVISION_5416_10	0
+#define AR_SREV_REVISION_5416_20	1
+#define AR_SREV_REVISION_5416_22	2
+#define AR_SREV_VERSION_9100		0x14
+#define AR_SREV_VERSION_9160		0x40
+#define AR_SREV_REVISION_9160_10	0
+#define AR_SREV_REVISION_9160_11	1
+#define AR_SREV_VERSION_9280		0x80
+#define AR_SREV_REVISION_9280_10	0
+#define AR_SREV_REVISION_9280_20	1
+#define AR_SREV_REVISION_9280_21	2
+#define AR_SREV_VERSION_9285		0xC0
+#define AR_SREV_REVISION_9285_10	0
+#define AR_SREV_REVISION_9285_11	1
+#define AR_SREV_REVISION_9285_12	2
+#define AR_SREV_VERSION_9287		0x180
+#define AR_SREV_REVISION_9287_10	0
+#define AR_SREV_REVISION_9287_11	1
+#define AR_SREV_REVISION_9287_12	2
+#define AR_SREV_REVISION_9287_13	3
+#define AR_SREV_VERSION_9271		0x140
+#define AR_SREV_REVISION_9271_10	0
+#define AR_SREV_REVISION_9271_11	1
+#define AR_SREV_VERSION_9300		0x1c0
+#define AR_SREV_REVISION_9300_20	2 /* 2.0 and 2.1 */
 
 #define AR_SREV_5416(_ah) \
 	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \
@@ -862,6 +863,11 @@
 	(((_ah)->hw_version.macVersion > AR_SREV_VERSION_9287) || \
 	 (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \
 	  ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9287_12)))
+#define AR_SREV_9287_13_OR_LATER(_ah) \
+	(((_ah)->hw_version.macVersion > AR_SREV_VERSION_9287) || \
+	 (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \
+	  ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9287_13)))
+
 #define AR_SREV_9271(_ah) \
     (((_ah))->hw_version.macVersion == AR_SREV_VERSION_9271)
 #define AR_SREV_9271_10(_ah) \
-- 
1.7.1


^ permalink raw reply related

* [PATCH 13/13] ath9k_htc: Fix fair beacon distribution
From: Sujith @ 2010-06-01  9:44 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless

This patch fixes beacon distribution in IBSS mode
by configuring the hardware beacon queue properly.

Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
---
 drivers/net/wireless/ath/ath9k/htc.h            |    1 +
 drivers/net/wireless/ath/ath9k/htc_drv_beacon.c |   23 +++++++++++++++++++++++
 drivers/net/wireless/ath/ath9k/htc_drv_main.c   |    8 +++++++-
 3 files changed, 31 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index bf2bd42..f2cbc55 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -409,6 +409,7 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz)
 	common->bus_ops->read_cachesize(common, csz);
 }
 
+void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv);
 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);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
index c10c7d0..12a3bb0 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
@@ -222,6 +222,29 @@ void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending)
 	spin_unlock_bh(&priv->beacon_lock);
 }
 
+/* Currently, only for IBSS */
+void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv)
+{
+	struct ath_hw *ah = priv->ah;
+	struct ath9k_tx_queue_info qi, qi_be;
+	int qnum = priv->hwq_map[ATH9K_WME_AC_BE];
+
+	memset(&qi, 0, sizeof(struct ath9k_tx_queue_info));
+	memset(&qi_be, 0, sizeof(struct ath9k_tx_queue_info));
+
+	ath9k_hw_get_txq_props(ah, qnum, &qi_be);
+
+	qi.tqi_aifs = qi_be.tqi_aifs;
+	qi.tqi_cwmin = 4*qi_be.tqi_cwmin;
+	qi.tqi_cwmax = qi_be.tqi_cwmax;
+
+	if (!ath9k_hw_set_txq_props(ah, priv->beaconq, &qi)) {
+		ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL,
+			  "Unable to update beacon queue %u!\n", qnum);
+	} else {
+		ath9k_hw_resettxqueue(ah, priv->beaconq);
+	}
+}
 
 void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv,
 			     struct ieee80211_vif *vif)
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 86145ef..569b9c0 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -1580,9 +1580,15 @@ static int ath9k_htc_conf_tx(struct ieee80211_hw *hw, u16 queue,
 		  params->cw_max, params->txop);
 
 	ret = ath_htc_txq_update(priv, qnum, &qi);
-	if (ret)
+	if (ret) {
 		ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n");
+		goto out;
+	}
 
+	if ((priv->ah->opmode == NL80211_IFTYPE_ADHOC) &&
+	    (qnum == priv->hwq_map[ATH9K_WME_AC_BE]))
+		    ath9k_htc_beaconq_config(priv);
+out:
 	ath9k_htc_ps_restore(priv);
 	mutex_unlock(&priv->mutex);
 
-- 
1.7.1


^ permalink raw reply related

* [PATCH 08/13] ath9k_htc: Fix bug in handling CONF_IDLE
From: Sujith @ 2010-06-01  9:44 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless

Disable the radio only when mac80211 indicates it,
through the IEEE80211_CONF_CHANGE_IDLE flag.
Not handling this properly will result in multiple
calls to radio_disable() even though the radio is
already idle.

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

diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index d6c1f2f..bdd76cd 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -1453,7 +1453,7 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
 		}
 	}
 
-	if (priv->ps_idle) {
+	if ((changed & IEEE80211_CONF_CHANGE_IDLE) && priv->ps_idle) {
 		ath_print(common, ATH_DBG_CONFIG,
 			  "idle: disabling radio\n");
 		ath9k_htc_radio_disable(hw);
-- 
1.7.1


^ permalink raw reply related

* [PATCH 12/13] ath9k_htc: Handle host RX disable
From: Sujith @ 2010-06-01  9:44 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless

The MIB counters used by ANI have to be disabled
on the host because the FW doesn't do it on the target side.
Also, flush the receive buffers before initializing
RX on the target.

Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
---
 drivers/net/wireless/ath/ath9k/ani.c          |    1 +
 drivers/net/wireless/ath/ath9k/htc_drv_main.c |   10 ++++++++++
 2 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c
index ba8b20f..3da820f 100644
--- a/drivers/net/wireless/ath/ath9k/ani.c
+++ b/drivers/net/wireless/ath/ath9k/ani.c
@@ -495,6 +495,7 @@ void ath9k_hw_disable_mib_counters(struct ath_hw *ah)
 	REG_WRITE(ah, AR_FILT_OFDM, 0);
 	REG_WRITE(ah, AR_FILT_CCK, 0);
 }
+EXPORT_SYMBOL(ath9k_hw_disable_mib_counters);
 
 u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah,
 				  u32 *rxc_pcnt,
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 1ed88fb..86145ef 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -1117,6 +1117,12 @@ static void ath9k_htc_radio_disable(struct ieee80211_hw *hw)
 	/* 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);
 
@@ -1198,6 +1204,10 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
 		  "Starting driver with initial channel: %d MHz\n",
 		  curchan->center_freq);
 
+	/* Ensure that HW is awake before flushing RX */
+	ath9k_htc_setpower(priv, ATH9K_PM_AWAKE);
+	WMI_CMD(WMI_FLUSH_RECV_CMDID);
+
 	/* setup initial channel */
 	init_channel = ath9k_cmn_get_curchannel(hw, ah);
 
-- 
1.7.1


^ permalink raw reply related

* [PATCH 07/13] ath9k_htc: Add PS wrappers
From: Sujith @ 2010-06-01  9:46 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless

The HW has to be awake when registers are accessed.
Ensure this is so by using the PS wrappers at
appropriate places.

Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
---
 drivers/net/wireless/ath/ath9k/htc_drv_main.c |   25 ++++++++++++++++++++-----
 1 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 08afd6e..d6c1f2f 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -1357,6 +1357,7 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
 out:
 	ath9k_htc_ps_restore(priv);
 	mutex_unlock(&priv->mutex);
+
 	return ret;
 }
 
@@ -1373,6 +1374,7 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw,
 	ath_print(common, ATH_DBG_CONFIG, "Detach Interface\n");
 
 	mutex_lock(&priv->mutex);
+	ath9k_htc_ps_wakeup(priv);
 
 	memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
 	memcpy(&hvif.myaddr, vif->addr, ETH_ALEN);
@@ -1383,6 +1385,7 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw,
 	ath9k_htc_remove_station(priv, vif, NULL);
 	priv->vif = NULL;
 
+	ath9k_htc_ps_restore(priv);
 	mutex_unlock(&priv->mutex);
 }
 
@@ -1479,8 +1482,8 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw,
 	u32 rfilt;
 
 	mutex_lock(&priv->mutex);
-
 	ath9k_htc_ps_wakeup(priv);
+
 	changed_flags &= SUPPORTED_FILTERS;
 	*total_flags &= SUPPORTED_FILTERS;
 
@@ -1503,9 +1506,11 @@ static int ath9k_htc_sta_add(struct ieee80211_hw *hw,
 	int ret;
 
 	mutex_lock(&priv->mutex);
+	ath9k_htc_ps_wakeup(priv);
 	ret = ath9k_htc_add_station(priv, vif, sta);
 	if (!ret)
 		ath9k_htc_init_rate(priv, sta);
+	ath9k_htc_ps_restore(priv);
 	mutex_unlock(&priv->mutex);
 
 	return ret;
@@ -1519,7 +1524,9 @@ static int ath9k_htc_sta_remove(struct ieee80211_hw *hw,
 	int ret;
 
 	mutex_lock(&priv->mutex);
+	ath9k_htc_ps_wakeup(priv);
 	ret = ath9k_htc_remove_station(priv, vif, sta);
+	ath9k_htc_ps_restore(priv);
 	mutex_unlock(&priv->mutex);
 
 	return ret;
@@ -1537,6 +1544,7 @@ static int ath9k_htc_conf_tx(struct ieee80211_hw *hw, u16 queue,
 		return 0;
 
 	mutex_lock(&priv->mutex);
+	ath9k_htc_ps_wakeup(priv);
 
 	memset(&qi, 0, sizeof(struct ath9k_tx_queue_info));
 
@@ -1557,6 +1565,7 @@ static int ath9k_htc_conf_tx(struct ieee80211_hw *hw, u16 queue,
 	if (ret)
 		ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n");
 
+	ath9k_htc_ps_restore(priv);
 	mutex_unlock(&priv->mutex);
 
 	return ret;
@@ -1699,7 +1708,9 @@ static u64 ath9k_htc_get_tsf(struct ieee80211_hw *hw)
 	u64 tsf;
 
 	mutex_lock(&priv->mutex);
+	ath9k_htc_ps_wakeup(priv);
 	tsf = ath9k_hw_gettsf64(priv->ah);
+	ath9k_htc_ps_restore(priv);
 	mutex_unlock(&priv->mutex);
 
 	return tsf;
@@ -1710,7 +1721,9 @@ static void ath9k_htc_set_tsf(struct ieee80211_hw *hw, u64 tsf)
 	struct ath9k_htc_priv *priv = hw->priv;
 
 	mutex_lock(&priv->mutex);
+	ath9k_htc_ps_wakeup(priv);
 	ath9k_hw_settsf64(priv->ah, tsf);
+	ath9k_htc_ps_restore(priv);
 	mutex_unlock(&priv->mutex);
 }
 
@@ -1718,11 +1731,11 @@ static void ath9k_htc_reset_tsf(struct ieee80211_hw *hw)
 {
 	struct ath9k_htc_priv *priv = hw->priv;
 
-	ath9k_htc_ps_wakeup(priv);
 	mutex_lock(&priv->mutex);
+	ath9k_htc_ps_wakeup(priv);
 	ath9k_hw_reset_tsf(priv->ah);
-	mutex_unlock(&priv->mutex);
 	ath9k_htc_ps_restore(priv);
+	mutex_unlock(&priv->mutex);
 }
 
 static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw,
@@ -1780,8 +1793,8 @@ static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw)
 {
 	struct ath9k_htc_priv *priv = hw->priv;
 
-	ath9k_htc_ps_wakeup(priv);
 	mutex_lock(&priv->mutex);
+	ath9k_htc_ps_wakeup(priv);
 	spin_lock_bh(&priv->beacon_lock);
 	priv->op_flags &= ~OP_SCANNING;
 	spin_unlock_bh(&priv->beacon_lock);
@@ -1789,8 +1802,8 @@ static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw)
 	if (priv->op_flags & OP_ASSOCIATED)
 		ath9k_htc_beacon_config(priv, priv->vif);
 	ath_start_ani(priv);
-	mutex_unlock(&priv->mutex);
 	ath9k_htc_ps_restore(priv);
+	mutex_unlock(&priv->mutex);
 }
 
 static int ath9k_htc_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
@@ -1804,8 +1817,10 @@ static void ath9k_htc_set_coverage_class(struct ieee80211_hw *hw,
 	struct ath9k_htc_priv *priv = hw->priv;
 
 	mutex_lock(&priv->mutex);
+	ath9k_htc_ps_wakeup(priv);
 	priv->ah->coverage_class = coverage_class;
 	ath9k_hw_init_global_settings(priv->ah);
+	ath9k_htc_ps_restore(priv);
 	mutex_unlock(&priv->mutex);
 }
 
-- 
1.7.1


^ permalink raw reply related

* [PATCH 02/13] ath9k_hw: Optimize ath9k_hw_ar9287_set_board_values
From: Sujith @ 2010-06-01 10:14 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless

Rather than doing a series of RMWs, calculate the
value to be written to the register in question and
do a single REGWRITE. This improves bringup time.

This depends on the analog_shiftreg configuration option,
which is currently buggy. For AP mode, a delay of 100us
has to be the default. For station mode, this knob has to
be enabled on a per-case basis, though it is a little
unclear on when to enable a delay. This can be fixed later though.

Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
---
 drivers/net/wireless/ath/ath9k/eeprom.c      |    8 +++
 drivers/net/wireless/ath/ath9k/eeprom.h      |    1 +
 drivers/net/wireless/ath/ath9k/eeprom_9287.c |   69 ++++++++++++--------------
 3 files changed, 41 insertions(+), 37 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c
index ca8704a..a29b2d9 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom.c
@@ -24,6 +24,14 @@ static inline u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz)
 	return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin));
 }
 
+void ath9k_hw_analog_shift_regwrite(struct ath_hw *ah, u32 reg, u32 val)
+{
+        REG_WRITE(ah, reg, val);
+
+        if (ah->config.analog_shiftreg)
+		udelay(100);
+}
+
 void ath9k_hw_analog_shift_rmw(struct ath_hw *ah, u32 reg, u32 mask,
 			       u32 shift, u32 val)
 {
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h
index 21354c1..14186f2 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom.h
+++ b/drivers/net/wireless/ath/ath9k/eeprom.h
@@ -679,6 +679,7 @@ struct eeprom_ops {
 	u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz);
 };
 
+void ath9k_hw_analog_shift_regwrite(struct ath_hw *ah, u32 reg, u32 val);
 void ath9k_hw_analog_shift_rmw(struct ath_hw *ah, u32 reg, u32 mask,
 			       u32 shift, u32 val);
 int16_t ath9k_hw_interpolate(u16 target, u16 srcLeft, u16 srcRight,
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
index 5010cd1..27abfba 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
@@ -988,7 +988,7 @@ static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah,
 	struct ar9287_eeprom *eep = &ah->eeprom.map9287;
 	struct modal_eep_ar9287_header *pModal = &eep->modalHeader;
 	u16 antWrites[AR9287_ANT_16S];
-	u32 regChainOffset;
+	u32 regChainOffset, regval;
 	u8 txRxAttenLocal;
 	int i, j, offset_num;
 
@@ -1075,42 +1075,37 @@ static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah,
 	REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0,
 		      AR_PHY_EXT_CCA0_THRESH62, pModal->thresh62);
 
-	ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, AR9287_AN_RF2G3_DB1,
-				  AR9287_AN_RF2G3_DB1_S, pModal->db1);
-	ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, AR9287_AN_RF2G3_DB2,
-				  AR9287_AN_RF2G3_DB2_S, pModal->db2);
-	ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0,
-				  AR9287_AN_RF2G3_OB_CCK,
-				  AR9287_AN_RF2G3_OB_CCK_S, pModal->ob_cck);
-	ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0,
-				  AR9287_AN_RF2G3_OB_PSK,
-				  AR9287_AN_RF2G3_OB_PSK_S, pModal->ob_psk);
-	ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0,
-				  AR9287_AN_RF2G3_OB_QAM,
-				  AR9287_AN_RF2G3_OB_QAM_S, pModal->ob_qam);
-	ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0,
-				  AR9287_AN_RF2G3_OB_PAL_OFF,
-				  AR9287_AN_RF2G3_OB_PAL_OFF_S,
-				  pModal->ob_pal_off);
-
-	ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1,
-				  AR9287_AN_RF2G3_DB1, AR9287_AN_RF2G3_DB1_S,
-				  pModal->db1);
-	ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, AR9287_AN_RF2G3_DB2,
-				  AR9287_AN_RF2G3_DB2_S, pModal->db2);
-	ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1,
-				  AR9287_AN_RF2G3_OB_CCK,
-				  AR9287_AN_RF2G3_OB_CCK_S, pModal->ob_cck);
-	ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1,
-				  AR9287_AN_RF2G3_OB_PSK,
-				  AR9287_AN_RF2G3_OB_PSK_S, pModal->ob_psk);
-	ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1,
-				  AR9287_AN_RF2G3_OB_QAM,
-				  AR9287_AN_RF2G3_OB_QAM_S, pModal->ob_qam);
-	ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1,
-				  AR9287_AN_RF2G3_OB_PAL_OFF,
-				  AR9287_AN_RF2G3_OB_PAL_OFF_S,
-				  pModal->ob_pal_off);
+	regval = REG_READ(ah, AR9287_AN_RF2G3_CH0);
+	regval &= ~(AR9287_AN_RF2G3_DB1 |
+		    AR9287_AN_RF2G3_DB2 |
+		    AR9287_AN_RF2G3_OB_CCK |
+		    AR9287_AN_RF2G3_OB_PSK |
+		    AR9287_AN_RF2G3_OB_QAM |
+		    AR9287_AN_RF2G3_OB_PAL_OFF);
+	regval |= (SM(pModal->db1, AR9287_AN_RF2G3_DB1) |
+		   SM(pModal->db2, AR9287_AN_RF2G3_DB2) |
+		   SM(pModal->ob_cck, AR9287_AN_RF2G3_OB_CCK) |
+		   SM(pModal->ob_psk, AR9287_AN_RF2G3_OB_PSK) |
+		   SM(pModal->ob_qam, AR9287_AN_RF2G3_OB_QAM) |
+		   SM(pModal->ob_pal_off, AR9287_AN_RF2G3_OB_PAL_OFF));
+
+	ath9k_hw_analog_shift_regwrite(ah, AR9287_AN_RF2G3_CH0, regval);
+
+	regval = REG_READ(ah, AR9287_AN_RF2G3_CH1);
+	regval &= ~(AR9287_AN_RF2G3_DB1 |
+		    AR9287_AN_RF2G3_DB2 |
+		    AR9287_AN_RF2G3_OB_CCK |
+		    AR9287_AN_RF2G3_OB_PSK |
+		    AR9287_AN_RF2G3_OB_QAM |
+		    AR9287_AN_RF2G3_OB_PAL_OFF);
+	regval |= (SM(pModal->db1, AR9287_AN_RF2G3_DB1) |
+		   SM(pModal->db2, AR9287_AN_RF2G3_DB2) |
+		   SM(pModal->ob_cck, AR9287_AN_RF2G3_OB_CCK) |
+		   SM(pModal->ob_psk, AR9287_AN_RF2G3_OB_PSK) |
+		   SM(pModal->ob_qam, AR9287_AN_RF2G3_OB_QAM) |
+		   SM(pModal->ob_pal_off, AR9287_AN_RF2G3_OB_PAL_OFF));
+
+	ath9k_hw_analog_shift_regwrite(ah, AR9287_AN_RF2G3_CH1, regval);
 
 	REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
 		      AR_PHY_TX_END_DATA_START, pModal->txFrameToDataStart);
-- 
1.7.1


^ permalink raw reply related

* [PATCH 04/13] ath9k_hw: Update the PCI WAR register
From: Sujith @ 2010-06-01 10:14 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless

This patch updates the PCI power save handling
code, fixing ASPM hangs and handling device state D3
properly.

The WAR register is programmed with the correct
values now.

Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
---
 drivers/net/wireless/ath/ath9k/ar9002_hw.c |   85 +++++++++++++++++++---------
 drivers/net/wireless/ath/ath9k/reg.h       |    3 +
 2 files changed, 60 insertions(+), 28 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
index a8a8cdc..748449c 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
@@ -436,55 +436,84 @@ static void ar9002_hw_configpcipowersave(struct ath_hw *ah,
 		}
 
 		udelay(1000);
+	}
 
-		/* set bit 19 to allow forcing of pcie core into L1 state */
-		REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
+	if (power_off) {
+		/* clear bit 19 to disable L1 */
+		REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
+
+		val = REG_READ(ah, AR_WA);
 
-		/* Several PCIe massages to ensure proper behaviour */
+		/*
+		 * Set PCIe workaround bits
+		 * In AR9280 and AR9285, bit 14 in WA register (disable L1)
+		 * should only  be set when device enters D3 and be
+		 * cleared when device comes back to D0.
+		 */
+		if (ah->config.pcie_waen) {
+			if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE)
+				val |= AR_WA_D3_L1_DISABLE;
+		} else {
+			if (((AR_SREV_9285(ah) ||
+			      AR_SREV_9271(ah) ||
+			      AR_SREV_9287(ah)) &&
+			     (AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)) ||
+			    (AR_SREV_9280(ah) &&
+			     (AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE))) {
+				val |= AR_WA_D3_L1_DISABLE;
+			}
+		}
+
+		if (AR_SREV_9280(ah) || AR_SREV_9285(ah) || AR_SREV_9287(ah)) {
+			/*
+			 * Disable bit 6 and 7 before entering D3 to
+			 * prevent system hang.
+			 */
+			val &= ~(AR_WA_BIT6 | AR_WA_BIT7);
+		}
+
+		if (AR_SREV_9285E_20(ah))
+			val |= AR_WA_BIT23;
+
+		REG_WRITE(ah, AR_WA, val);
+	} else {
 		if (ah->config.pcie_waen) {
 			val = ah->config.pcie_waen;
 			if (!power_off)
 				val &= (~AR_WA_D3_L1_DISABLE);
 		} else {
-			if (AR_SREV_9285(ah) || AR_SREV_9271(ah) ||
+			if (AR_SREV_9285(ah) ||
+			    AR_SREV_9271(ah) ||
 			    AR_SREV_9287(ah)) {
 				val = AR9285_WA_DEFAULT;
 				if (!power_off)
 					val &= (~AR_WA_D3_L1_DISABLE);
-			} else if (AR_SREV_9280(ah)) {
+			}
+			else if (AR_SREV_9280(ah)) {
 				/*
-				 * On AR9280 chips bit 22 of 0x4004 needs to be
-				 * set otherwise card may disappear.
+				 * For AR9280 chips, bit 22 of 0x4004
+				 * needs to be set.
 				 */
 				val = AR9280_WA_DEFAULT;
 				if (!power_off)
 					val &= (~AR_WA_D3_L1_DISABLE);
-			} else
+			} else {
 				val = AR_WA_DEFAULT;
+			}
+		}
+
+		/* WAR for ASPM system hang */
+		if (AR_SREV_9280(ah) || AR_SREV_9285(ah) || AR_SREV_9287(ah)) {
+			val |= (AR_WA_BIT6 | AR_WA_BIT7);
 		}
 
+		if (AR_SREV_9285E_20(ah))
+			val |= AR_WA_BIT23;
+
 		REG_WRITE(ah, AR_WA, val);
-	}
 
-	if (power_off) {
-		/*
-		 * Set PCIe workaround bits
-		 * bit 14 in WA register (disable L1) should only
-		 * be set when device enters D3 and be cleared
-		 * when device comes back to D0.
-		 */
-		if (ah->config.pcie_waen) {
-			if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE)
-				REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE);
-		} else {
-			if (((AR_SREV_9285(ah) || AR_SREV_9271(ah) ||
-			      AR_SREV_9287(ah)) &&
-			     (AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)) ||
-			    (AR_SREV_9280(ah) &&
-			     (AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE))) {
-				REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE);
-			}
-		}
+		/* set bit 19 to allow forcing of pcie core into L1 state */
+		REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
 	}
 }
 
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index d4371a4..854e681 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -699,6 +699,9 @@
 #define AR_RC_HOSTIF         0x00000100
 
 #define AR_WA                		0x4004
+#define AR_WA_BIT6			(1 << 6)
+#define AR_WA_BIT7			(1 << 7)
+#define AR_WA_BIT23			(1 << 23)
 #define AR_WA_D3_L1_DISABLE		(1 << 14)
 #define AR9285_WA_DEFAULT		0x004a050b
 #define AR9280_WA_DEFAULT           	0x0040073b
-- 
1.7.1


^ permalink raw reply related

* [PATCH 06/13] ath9k_htc: Revamp CONF_IDLE handling
From: Sujith @ 2010-06-01 10:14 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless

This patch revamps IDLE power save handling in the driver.
Two separate functions (radio enable/disable) are introduced,
because the semantics of radio handling is just not the same
as the start()/stop() callbacks. For example, the HW must not
be disabled, instead, the PHY has to be disabled in radio_disable().
Also, the HW has to be reset properly in radio enable/disable and
certain registers have to be programmed only once, in the
start() callback.

The radio_enable() routine doesn't need the PS wrappers since
we set the HW power mode to AWAKE anyway before calling it.

Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
---
 drivers/net/wireless/ath/ath9k/htc_drv_main.c |  129 ++++++++++++++++++-------
 1 files changed, 93 insertions(+), 36 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 340d281..08afd6e 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -1052,6 +1052,89 @@ void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv)
 		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, false);
+	if (ret) {
+		ath_print(common, ATH_DBG_FATAL,
+			  "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);
+
+	if (!ah->curchan)
+		ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
+
+	/* Reset the HW */
+	ret = ath9k_hw_reset(ah, ah->curchan, false);
+	if (ret) {
+		ath_print(common, ATH_DBG_FATAL,
+			  "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 */
 /**********************/
@@ -1097,7 +1180,7 @@ fail_tx:
 	return 0;
 }
 
-static int ath9k_htc_radio_enable(struct ieee80211_hw *hw, bool led)
+static int ath9k_htc_start(struct ieee80211_hw *hw)
 {
 	struct ath9k_htc_priv *priv = hw->priv;
 	struct ath_hw *ah = priv->ah;
@@ -1109,6 +1192,8 @@ static int ath9k_htc_radio_enable(struct ieee80211_hw *hw, bool led)
 	__be16 htc_mode;
 	u8 cmd_rsp;
 
+	mutex_lock(&priv->mutex);
+
 	ath_print(common, ATH_DBG_CONFIG,
 		  "Starting driver with initial channel: %d MHz\n",
 		  curchan->center_freq);
@@ -1125,6 +1210,7 @@ static int ath9k_htc_radio_enable(struct ieee80211_hw *hw, bool led)
 		ath_print(common, ATH_DBG_FATAL,
 			  "Unable to reset hardware; reset status %d "
 			  "(freq %u MHz)\n", ret, curchan->center_freq);
+		mutex_unlock(&priv->mutex);
 		return ret;
 	}
 
@@ -1145,31 +1231,14 @@ static int ath9k_htc_radio_enable(struct ieee80211_hw *hw, bool led)
 	priv->tx_queues_stop = false;
 	spin_unlock_bh(&priv->tx_lock);
 
-	if (led) {
-		/* 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);
-	}
-
 	ieee80211_wake_queues(hw);
 
-	return ret;
-}
-
-static int ath9k_htc_start(struct ieee80211_hw *hw)
-{
-	struct ath9k_htc_priv *priv = hw->priv;
-	int ret = 0;
-
-	mutex_lock(&priv->mutex);
-	ret = ath9k_htc_radio_enable(hw, false);
 	mutex_unlock(&priv->mutex);
 
 	return ret;
 }
 
-static void ath9k_htc_radio_disable(struct ieee80211_hw *hw, bool led)
+static void ath9k_htc_stop(struct ieee80211_hw *hw)
 {
 	struct ath9k_htc_priv *priv = hw->priv;
 	struct ath_hw *ah = priv->ah;
@@ -1177,17 +1246,14 @@ static void ath9k_htc_radio_disable(struct ieee80211_hw *hw, bool led)
 	int ret = 0;
 	u8 cmd_rsp;
 
+	mutex_lock(&priv->mutex);
+
 	if (priv->op_flags & OP_INVALID) {
 		ath_print(common, ATH_DBG_ANY, "Device not present\n");
+		mutex_unlock(&priv->mutex);
 		return;
 	}
 
-	if (led) {
-		/* Disable LED */
-		ath9k_hw_set_gpio(ah, ah->led_pin, 1);
-		ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
-	}
-
 	/* Cancel all the running timers/work .. */
 	cancel_work_sync(&priv->ps_work);
 	cancel_delayed_work_sync(&priv->ath9k_ani_work);
@@ -1221,18 +1287,9 @@ static void ath9k_htc_radio_disable(struct ieee80211_hw *hw, bool led)
 	priv->op_flags |= OP_INVALID;
 
 	ath_print(common, ATH_DBG_CONFIG, "Driver halt\n");
-}
-
-static void ath9k_htc_stop(struct ieee80211_hw *hw)
-{
-	struct ath9k_htc_priv *priv = hw->priv;
-
-	mutex_lock(&priv->mutex);
-	ath9k_htc_radio_disable(hw, false);
 	mutex_unlock(&priv->mutex);
 }
 
-
 static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
 				   struct ieee80211_vif *vif)
 {
@@ -1348,7 +1405,7 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
 
 		if (enable_radio) {
 			ath9k_htc_setpower(priv, ATH9K_PM_AWAKE);
-			ath9k_htc_radio_enable(hw, true);
+			ath9k_htc_radio_enable(hw);
 			ath_print(common, ATH_DBG_CONFIG,
 				  "not-idle: enabling radio\n");
 		}
@@ -1396,7 +1453,7 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
 	if (priv->ps_idle) {
 		ath_print(common, ATH_DBG_CONFIG,
 			  "idle: disabling radio\n");
-		ath9k_htc_radio_disable(hw, true);
+		ath9k_htc_radio_disable(hw);
 	}
 
 	mutex_unlock(&priv->mutex);
-- 
1.7.1


^ permalink raw reply related

* [PATCH 09/13] ath9k_htc: Remove useless cancel_work_sync
From: Sujith @ 2010-06-01 10:15 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless

There is no need to cancel the PS work when disassociation
happens. The work handlers are cancelled in the stop()
callback.

Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
---
 drivers/net/wireless/ath/ath9k/htc_drv_main.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index bdd76cd..011d967 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -1638,7 +1638,6 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
 			ath_start_ani(priv);
 		} else {
 			priv->op_flags &= ~OP_ASSOCIATED;
-			cancel_work_sync(&priv->ps_work);
 			cancel_delayed_work_sync(&priv->ath9k_ani_work);
 		}
 	}
-- 
1.7.1


^ permalink raw reply related

* [PATCH 10/13] ath9k_htc: Fix locking for ps_idle
From: Sujith @ 2010-06-01 10:15 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless

ps_idle is protected by the htc_pm_lock mutex.
Use it to protect the variable.

Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
---
 drivers/net/wireless/ath/ath9k/htc_drv_main.c |   18 +++++++++++++-----
 1 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 011d967..5dad5cd 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -1401,16 +1401,17 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
 		bool enable_radio = false;
 		bool idle = !!(conf->flags & IEEE80211_CONF_IDLE);
 
+		mutex_lock(&priv->htc_pm_lock);
 		if (!idle && priv->ps_idle)
 			enable_radio = true;
-
 		priv->ps_idle = idle;
+		mutex_unlock(&priv->htc_pm_lock);
 
 		if (enable_radio) {
-			ath9k_htc_setpower(priv, ATH9K_PM_AWAKE);
-			ath9k_htc_radio_enable(hw);
 			ath_print(common, ATH_DBG_CONFIG,
 				  "not-idle: enabling radio\n");
+			ath9k_htc_setpower(priv, ATH9K_PM_AWAKE);
+			ath9k_htc_radio_enable(hw);
 		}
 	}
 
@@ -1453,14 +1454,21 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
 		}
 	}
 
-	if ((changed & IEEE80211_CONF_CHANGE_IDLE) && priv->ps_idle) {
+	if (changed & IEEE80211_CONF_CHANGE_IDLE) {
+		mutex_lock(&priv->htc_pm_lock);
+		if (!priv->ps_idle) {
+			mutex_unlock(&priv->htc_pm_lock);
+			goto out;
+		}
+		mutex_unlock(&priv->htc_pm_lock);
+
 		ath_print(common, ATH_DBG_CONFIG,
 			  "idle: disabling radio\n");
 		ath9k_htc_radio_disable(hw);
 	}
 
+out:
 	mutex_unlock(&priv->mutex);
-
 	return 0;
 }
 
-- 
1.7.1


^ permalink raw reply related

* [PATCH 11/13] ath9k_htc: Handle monitor interface removal
From: Sujith @ 2010-06-01 10:15 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless

The monitor interface instance on the target has
to be removed before setting it to FULLSLEEP.
Handle this properly.

Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
---
 drivers/net/wireless/ath/ath9k/htc_drv_main.c |   12 ++++++------
 1 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 5dad5cd..1ed88fb 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -1266,12 +1266,6 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
 	WMI_CMD(WMI_DISABLE_INTR_CMDID);
 	WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
 	WMI_CMD(WMI_STOP_RECV_CMDID);
-	ath9k_hw_phy_disable(ah);
-	ath9k_hw_disable(ah);
-	ath9k_hw_configpcipowersave(ah, 1, 1);
-	ath9k_htc_ps_restore(priv);
-	ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP);
-
 	skb_queue_purge(&priv->tx_queue);
 
 	/* Remove monitor interface here */
@@ -1284,6 +1278,12 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
 				  "Monitor interface removed\n");
 	}
 
+	ath9k_hw_phy_disable(ah);
+	ath9k_hw_disable(ah);
+	ath9k_hw_configpcipowersave(ah, 1, 1);
+	ath9k_htc_ps_restore(priv);
+	ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP);
+
 	priv->op_flags |= OP_INVALID;
 
 	ath_print(common, ATH_DBG_CONFIG, "Driver halt\n");
-- 
1.7.1


^ permalink raw reply related

* IWL3945 problems in 2.6.35-rc1
From: Maxim Levitsky @ 2010-06-01 12:25 UTC (permalink / raw)
  To: linux-wireless; +Cc: iwlwifi maling list

Hi,

in 2.6.35-rc1 the wireless became just unusable.

These are problems that I have:

1. very frequent oopses.This appears to be mention on the list already,
but patches I tried don't help.

I currently use this bandaid patch, and I still get some crashes:

diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 3e5bffb..1aef988 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -1861,6 +1861,11 @@ static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
        if (!sband)
                return 0;
 
+       if(!priv->scan_request) {
+               WARN_ON(1);
+               return 0;
+       }
+
        active_dwell = iwl_get_active_dwell_time(priv, band, n_probes);
        passive_dwell = iwl_get_passive_dwell_time(priv, band, vif);


2. mulicast/broadcast is broken.
this results in DHCP non working on open access point.
It seems that DHCP does work on my home wireless, but avahi-autoipd doesn't see any neighbours, and this is annoying.
It can be worked around by doing (sudo ifconfig wlan0 promisc)


Best regards,
	Maxim Levitsky



^ permalink raw reply related

* [PATCHv3] mac80211: Add interface for driver to temporarily disable dynamic ps
From: Juuso Oikarinen @ 2010-06-01 12:36 UTC (permalink / raw)
  To: linux-wireless

This mechanism introduced in this patch applies (at least) for hardware
designs using a single shared antenna for both WLAN and BT. In these designs,
the antenna must be toggled between WLAN and BT.

In those hardware, managing WLAN co-existence with Bluetooth requires WLAN
full power save whenever there is Bluetooth activity in order for WLAN to be
able to periodically relinquish the antenna to be used for BT. This is because
BT can only access the shared antenna when WLAN is idle or asleep.

Some hardware, for instance the wl1271, are able to indicate to the host
whenever there is BT traffic. In essence, the hardware will send an indication
to the host whenever there is, for example, SCO traffic or A2DP traffic, and
will send another indication when the traffic is over.

The hardware gets information of Bluetooth traffic via hardware co-existence
control lines - these lines are used to negotiate the shared antenna
ownership. The hardware will give the antenna to BT whenever WLAN is sleeping.

This patch adds the interface to mac80211 to facilitate temporarily disabling
of dynamic power save as per request of the WLAN driver. This interface will
immediately force WLAN to full powersave, hence allowing BT coexistence as
described above.

In these kind of shared antenna desings, when WLAN powersave is fully disabled,
Bluetooth will not work simultaneously with WLAN at all. This patch does not
address that problem. This interface will not change PSM state, so if PSM is
disabled it will remain so. Solving this problem requires knowledge about BT
state, and is best done in user-space.

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
---
v3: set dynamic_ps_timeout to 0 to disable dyn-ps, instead of a bool

 include/net/mac80211.h |   36 +++++++++++++++++++++++++++++++++++-
 net/mac80211/mlme.c    |   31 +++++++++++++++++++++++++++++--
 2 files changed, 64 insertions(+), 3 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index de22cbf..81e0b5f 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -675,7 +675,12 @@ enum ieee80211_smps_mode {
  *	has been received and the DTIM period is known.
  * @dynamic_ps_timeout: The dynamic powersave timeout (in ms), see the
  *	powersave documentation below. This variable is valid only when
- *	the CONF_PS flag is set.
+ *	the CONF_PS flag is set. This value may change dynamically to zero if
+ *	the driver temporarily requires no dynamic ps to allow Bluetooth
+ *	co-existence management.
+ * @dynamic_ps_user_timeout: The dynamic powersave timeout (in ms) configured
+ *	for the device. This value is used for dynamic_ps_timeout whenever
+ *	not set to zero due to driver request.
  * @dynamic_ps_forced_timeout: The dynamic powersave timeout (in ms) configured
  *	by cfg80211 (essentially, wext) If set, this value overrules the value
  *	chosen by mac80211 based on ps qos network latency.
@@ -699,6 +704,8 @@ enum ieee80211_smps_mode {
 struct ieee80211_conf {
 	u32 flags;
 	int power_level, dynamic_ps_timeout, dynamic_ps_forced_timeout;
+	int dynamic_ps_user_timeout;
+	bool disable_dynamic_ps;
 	int max_sleep_period;
 
 	u16 listen_interval;
@@ -1260,6 +1267,15 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw,
  * dynamic PS feature in stack and will just keep %IEEE80211_CONF_PS
  * enabled whenever user has enabled powersave.
  *
+ * Some hardware need to toggle a single shared antenna between WLAN and
+ * Bluetooth to facilitate co-existence. These types of hardware set
+ * limitations on the use of host controlled dynamic powersave whenever there
+ * is simultaneous WLAN and Bluetooth traffic. For these types of hardware, the
+ * driver may request temporarily going into full power save, in order to
+ * enable toggling the antenna between BT and WLAN. If the driver requests
+ * disabling dynamic powersave, the @dynamic_ps_timeout value will be
+ * temporarily set to zero until the driver re-enables dynamic powersave.
+ *
  * Driver informs U-APSD client support by enabling
  * %IEEE80211_HW_SUPPORTS_UAPSD flag. The mode is configured through the
  * uapsd paramater in conf_tx() operation. Hardware needs to send the QoS
@@ -2460,6 +2476,24 @@ void ieee80211_beacon_loss(struct ieee80211_vif *vif);
 void ieee80211_connection_loss(struct ieee80211_vif *vif);
 
 /**
+ * ieee80211_disable_dyn_ps - force mac80211 to temporarily disable dynamic psm
+ *
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ *
+ * Some hardware require full power save to manage simultaneous BT traffic
+ * on the WLAN frequency. Full PSM is required periodically, whenever there are
+ * burst of BT traffic. The hardware gets information of BT traffic via
+ * hardware co-existence lines, and consequentially requests mac80211 to
+ * (temporarily) enter full psm.
+ * This function will only temporarily disable dynamic PS, not enable PSM if
+ * it was not already enabled.
+ * The driver must make sure to re-enable dynamic PS if the driver has disabled
+ * it.
+ *
+ */
+void ieee80211_disable_dyn_ps(struct ieee80211_vif *vif, bool disable);
+
+/**
  * ieee80211_cqm_rssi_notify - inform a configured connection quality monitoring
  *	rssi threshold triggered
  *
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 0839c4e..9ad0d90 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -478,6 +478,29 @@ static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
 	}
 }
 
+void ieee80211_disable_dyn_ps(struct ieee80211_vif *vif, bool disable)
+{
+	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+	struct ieee80211_local *local = sdata->local;
+	struct ieee80211_conf *conf = &local->hw.conf;
+
+	WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION ||
+		!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS) ||
+		(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS));
+
+	conf->disable_dynamic_ps = disable;
+
+	if (disable) {
+		conf->dynamic_ps_timeout = 0;
+		del_timer_sync(&local->dynamic_ps_timer);
+		ieee80211_queue_work(&local->hw,
+				     &local->dynamic_ps_enable_work);
+	} else {
+		conf->dynamic_ps_timeout = conf->dynamic_ps_user_timeout;
+	}
+}
+EXPORT_SYMBOL(ieee80211_disable_dyn_ps);
+
 /* powersave */
 static void ieee80211_enable_ps(struct ieee80211_local *local,
 				struct ieee80211_sub_if_data *sdata)
@@ -553,6 +576,7 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
 	    found->u.mgd.associated->beacon_ies &&
 	    !(found->u.mgd.flags & (IEEE80211_STA_BEACON_POLL |
 				    IEEE80211_STA_CONNECTION_POLL))) {
+		struct ieee80211_conf *conf = &local->hw.conf;
 		s32 beaconint_us;
 
 		if (latency < 0)
@@ -561,7 +585,7 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
 		beaconint_us = ieee80211_tu_to_usec(
 					found->vif.bss_conf.beacon_int);
 
-		timeout = local->hw.conf.dynamic_ps_forced_timeout;
+		timeout = conf->dynamic_ps_forced_timeout;
 		if (timeout < 0) {
 			/*
 			 * The 2 second value is there for compatibility until
@@ -579,7 +603,10 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
 			else
 				timeout = 0;
 		}
-		local->hw.conf.dynamic_ps_timeout = timeout;
+		conf->dynamic_ps_user_timeout = timeout;
+		if (!conf->disable_dynamic_ps)
+			conf->dynamic_ps_timeout =
+				conf->dynamic_ps_user_timeout;
 
 		if (beaconint_us > latency) {
 			local->ps_sdata = NULL;
-- 
1.6.3.3


^ permalink raw reply related

* Re: How the mac80211 handle "\0" essid?
From: leo liang @ 2010-06-01 13:29 UTC (permalink / raw)
  To: Dan Williams; +Cc: linux-wireless
In-Reply-To: <1274739877.19662.39.camel@localhost.localdomain>

Thank you for the answer.

On Mon, May 24, 2010 at 6:24 PM, Dan Williams <dcbw@redhat.com> wrote:
> On Fri, 2010-05-21 at 14:05 -0400, leo liang wrote:
>> On Thu, May 20, 2010 at 4:30 PM, Dan Williams <dcbw@redhat.com> wrote:
>> > On Thu, 2010-05-20 at 15:40 -0400, leo liang wrote:
>> >> Hi,
>> >>
>> >> Does any one know that if the application send "\0" as essid to
>> >> mac80211, how it handle this case?
>> >
>> > What are you trying to do?  Are you trying to work with a hidden AP, or
>> > do something else?
>>
>> I want to hide the associated AP name.  Or disassociate and do not let
>> the interface connect to any AP.
>
> "I want to hide the associated AP name"
>
> What do you mean by this?  Do you mean make 'iwconfig' or some other
> program not report the currently associated AP name?  Or do you mean
> something else?
>
> "Or disassociate and do not let..."
>
> For complete disassociation, you don't need to send an empty BSSID when
> using nl80211, just send the disassociate command using nl80211 (in
> code) or the 'iw' command.  When using WEXT (which is the older
> predecessor of nl80211) you need to send a random SSID (ie, 32 random
> ascii characters for example) not including \0.  That should cause
> devices to disassociate from the AP and not attempt to reconnect to it
> until you send a new, valid SSID.
>
>> >
>> > An SSID is simply a 32-byte array; the protocol and the stack don't care
>> > what's in that array.  So while you can't use command-line tools like
>> > 'iwconfig' to send an SSID containing a \0, you can use netlink or
>> > wpa_supplicant's nl80211 driver to do so.
>>
>> I checked "iwconfig" source code, if you run "iwconfig wlan0 essid
>> off", it will set the first char as "\0".
>
> Right, iwconfig is pretty old and does not correctly handle empty
> BSSIDs.  Don't depend on the iwconfig behavior.
>
> Dan
>
>> >
>> > But in the end, if you're trying to associate with an AP that has an
>> > SSID of only '\0', that AP is likely broken or trying to hide it's SSID,
>> > and you should be using the real SSID of that AP instead of '\0'.
>> >
>> > Dan
>> >
>> >
>> >
>> --
>> 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

* Re: IWL3945 problems in 2.6.35-rc1
From: Maxim Levitsky @ 2010-06-01 14:57 UTC (permalink / raw)
  To: linux-wireless; +Cc: iwlwifi maling list
In-Reply-To: <1275395142.14385.6.camel@maxim-laptop>

On Tue, 2010-06-01 at 15:25 +0300, Maxim Levitsky wrote: 
> Hi,
> 
> in 2.6.35-rc1 the wireless became just unusable.
> 
> These are problems that I have:
> 
> 1. very frequent oopses.This appears to be mention on the list already,
> but patches I tried don't help.
> 
> I currently use this bandaid patch, and I still get some crashes:


The crash happens here:

0xec3d is in iwl3945_request_scan (/home/maxim/software/kernel/linux-2.6/drivers/net/wireless/iwlwifi/iwl3945-base.c:1878).
1873			if (chan->band != band)
1874				continue;
1875	
1876			scan_ch->channel = chan->hw_value;
1877	
1878			ch_info = iwl_get_channel_info(priv, band, scan_ch->channel);
1879			if (!is_channel_valid(ch_info)) {
1880				IWL_DEBUG_SCAN(priv, "Channel %d is INVALID for this band.\n",
1881					       scan_ch->channel);
1882				continue;


The backtrace:

<1>[14212.708840] BUG: unable to handle kernel paging request at 00000002ffffffb1
<1>[14212.709870] IP: [<ffffffffa0305c0d>] iwl3945_request_scan+0x61d/0xf90 [iwl3945]
<4>[14212.710763] PGD 0 
<0>[14212.711636] Oops: 0000 [#1] PREEMPT SMP 
<0>[14212.712519] last sysfs file: /sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/hwmon/hwmon1/temp1_input
<4>[14212.713416] CPU 0 
<4>[14212.713432] Modules linked in: tg3 libphy iwl3945 iwlcore mac80211 cfg80211 ntfs vfat msdos fat lirc_ene0100 lirc_dev af_packet nfsd exportfs nfs lockd nfs_acl auth_rpcgss usb_storage usb_libusual cpufreq_powersave cpufreq_conservative r852 snd_hda_codec_realtek uvcvideo sm_common cpufreq_userspace acpi_cpufreq snd_hda_intel videodev mperf nand snd_hda_codec nand_ids sdhci_pci iTCO_wdt v4l2_compat_ioctl32 joydev snd_hwdep nand_ecc uhci_hcd sunrpc iTCO_vendor_support sdhci ehci_hcd psmouse snd_pcm mmc_core mtd usbcore coretemp ac sg battery evdev serio_raw snd_page_alloc video nouveau ttm drm_kms_helper drm i2c_algo_bit [last unloaded: cfg80211]
<4>[14212.718797] 
<4>[14212.718797] Pid: 4263, comm: iwl3945 Not tainted 2.6.35-rc1 #30 Nettiling/Aspire 5720     
<4>[14212.718797] RIP: 0010:[<ffffffffa0305c0d>]  [<ffffffffa0305c0d>] iwl3945_request_scan+0x61d/0xf90 [iwl3945]
<4>[14212.718797] RSP: 0018:ffff88006ce91c80  EFLAGS: 00010297
<4>[14212.718797] RAX: ffff880066e74100 RBX: ffff88001b2c1dc0 RCX: 00000002ffffffb1
<4>[14212.718797] RDX: 0000000000000000 RSI: 00000000ffff8800 RDI: ffff88001b2c1dc0
<4>[14212.718797] RBP: ffff88006ce91d70 R08: 000000000000030e R09: 00000000ffffffff
<4>[14212.718797] R10: 0000000000000058 R11: 0000000000000001 R12: 0000000000000000
<4>[14212.718797] R13: ffff88001b295800 R14: 0000000000000000 R15: ffff88001b2958f2
<4>[14212.718797] FS:  0000000000000000(0000) GS:ffff880002400000(0000) knlGS:0000000000000000
<4>[14212.718797] CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
<4>[14212.718797] CR2: 00000002ffffffb1 CR3: 000000000155b000 CR4: 00000000000006f0
<4>[14212.718797] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
<4>[14212.718797] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
<4>[14212.718797] Process iwl3945 (pid: 4263, threadinfo ffff88006ce90000, task ffff88006d04a280)
<0>[14212.718797] Stack:
<4>[14212.718797]  ffffffffa02c3810 ffff88006d04a2f0 ffff88006ce91cb0 ffffffff81036911
<4>[14212.718797] <0> 0000000000000000 0000000000000001 ffff88006ce91cd0 ffffffff00000000
<4>[14212.718797] <0> 0057000000000246 0000005800000021 ffff88006ce91fd8 0058ffff813a07bf
<0>[14212.718797] Call Trace:
<4>[14212.718797]  [<ffffffffa02c3810>] ? iwl_bg_start_internal_scan+0x0/0x3d0 [iwlcore]
<4>[14212.718797]  [<ffffffff81036911>] ? get_parent_ip+0x11/0x50
<4>[14212.718797]  [<ffffffffa02c3810>] ? iwl_bg_start_internal_scan+0x0/0x3d0 [iwlcore]
<4>[14212.718797]  [<ffffffffa02c3b2a>] iwl_bg_start_internal_scan+0x31a/0x3d0 [iwlcore]
<4>[14212.718797]  [<ffffffff81056dfe>] ? worker_thread+0x1ce/0x390
<4>[14212.718797]  [<ffffffff81056e50>] worker_thread+0x220/0x390
<4>[14212.718797]  [<ffffffff81056dfe>] ? worker_thread+0x1ce/0x390
<4>[14212.718797]  [<ffffffff8105bc80>] ? autoremove_wake_function+0x0/0x40
<4>[14212.718797]  [<ffffffff81056c30>] ? worker_thread+0x0/0x390
<4>[14212.718797]  [<ffffffff8105b7fe>] kthread+0xae/0xc0
<4>[14212.718797]  [<ffffffff81003b94>] kernel_thread_helper+0x4/0x10
<4>[14212.718797]  [<ffffffff8105b750>] ? kthread+0x0/0xc0
<4>[14212.718797]  [<ffffffff81003b90>] ? kernel_thread_helper+0x0/0x10
<0>[14212.718797] Code: ff ff 41 8d 52 ff 66 89 95 56 ff ff ff eb 14 0f 1f 80 00 00 00 00 41 ff c4 44 3b 60 0c 0f 83 eb 00 00 00 49 63 d4 48 8b 4c d0 38 <44> 3b 31 75 e6 0f b7 41 06 44 89 f6 41 88 47 01 0f b6 d0 48 89 
<1>[14212.718797] RIP  [<ffffffffa0305c0d>] iwl3945_request_scan+0x61d/0xf90 [iwl3945]
<4>[14212.718797]  RSP <ffff88006ce91c80>
<0>[14212.718797] CR2: 00000002ffffffb1
<4>[14212.760163] ---[ end trace 7075fd19298c88a3 ]---
<0>[14212.761267] Kernel panic - not syncing: Fatal exception
<4>[14212.762226] Pid: 4263, comm: iwl3945 Tainted: G      D     2.6.35-rc1 #30
<4>[14212.763193] Call Trace:
<4>[14212.764143]  [<ffffffff8139e487>] panic+0x90/0x10a
<4>[14212.765084]  [<ffffffff8100737c>] oops_end+0xcc/0xe0
<4>[14212.765095]  [<ffffffff81027c13>] no_context+0xf3/0x260
<4>[14212.765106]  [<ffffffff810622e5>] ? sched_clock_local+0x25/0x90
<4>[14212.765116]  [<ffffffff81027e95>] __bad_area_nosemaphore+0x115/0x1d0
<4>[14212.765128]  [<ffffffff81027f5e>] bad_area_nosemaphore+0xe/0x10
<4>[14212.765138]  [<ffffffff810283c6>] do_page_fault+0x2e6/0x390
<4>[14212.765148]  [<ffffffff810622e5>] ? sched_clock_local+0x25/0x90
<4>[14212.765158]  [<ffffffff81062410>] ? sched_clock_cpu+0xc0/0x110
<4>[14212.765169]  [<ffffffff8100add7>] ? native_sched_clock+0x27/0x80
<4>[14212.765179]  [<ffffffff810622e5>] ? sched_clock_local+0x25/0x90
<4>[14212.765191]  [<ffffffff813a309f>] page_fault+0x1f/0x30
<4>[14212.765207]  [<ffffffffa0305c0d>] ? iwl3945_request_scan+0x61d/0xf90 [iwl3945]
<4>[14212.765232]  [<ffffffffa02c3810>] ? iwl_bg_start_internal_scan+0x0/0x3d0 [iwlcore]
<4>[14212.765246]  [<ffffffff81036911>] ? get_parent_ip+0x11/0x50
<4>[14212.765266]  [<ffffffffa02c3810>] ? iwl_bg_start_internal_scan+0x0/0x3d0 [iwlcore]
<4>[14212.765286]  [<ffffffffa02c3b2a>] iwl_bg_start_internal_scan+0x31a/0x3d0 [iwlcore]
<4>[14212.765299]  [<ffffffff81056dfe>] ? worker_thread+0x1ce/0x390
<4>[14212.765310]  [<ffffffff81056e50>] worker_thread+0x220/0x390
<4>[14212.765320]  [<ffffffff81056dfe>] ? worker_thread+0x1ce/0x390
<4>[14212.765333]  [<ffffffff8105bc80>] ? autoremove_wake_function+0x0/0x40
<4>[14212.765344]  [<ffffffff81056c30>] ? worker_thread+0x0/0x390
<4>[14212.765353]  [<ffffffff8105b7fe>] kthread+0xae/0xc0
<4>[14212.765365]  [<ffffffff81003b94>] kernel_thread_helper+0x4/0x10
<4>[14212.765376]  [<ffffffff8105b750>] ? kthread+0x0/0xc0
<4>[14212.765386]  [<ffffffff81003b90>] ? kernel_thread_helper+0x0/0x10
<3>[14212.765402] [drm:drm_fb_helper_panic] *ERROR* panic occurred, switching back to text console
> 
> diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
> index 3e5bffb..1aef988 100644
> --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
> +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
> @@ -1861,6 +1861,11 @@ static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
>         if (!sband)
>                 return 0;
>  
> +       if(!priv->scan_request) {
> +               WARN_ON(1);
> +               return 0;
> +       }
> +
>         active_dwell = iwl_get_active_dwell_time(priv, band, n_probes);
>         passive_dwell = iwl_get_passive_dwell_time(priv, band, vif);
> 
> 
> 2. mulicast/broadcast is broken.
> this results in DHCP non working on open access point.
> It seems that DHCP does work on my home wireless, but avahi-autoipd doesn't see any neighbours, and this is annoying.
> It can be worked around by doing (sudo ifconfig wlan0 promisc)
> 
> 
Best regards,
	Maxim Levitsky


^ permalink raw reply

* Re: IWL3945 problems in 2.6.35-rc1
From: Sedat Dilek @ 2010-06-01 15:21 UTC (permalink / raw)
  To: Maxim Levitsky; +Cc: linux-wireless, iwlwifi maling list
In-Reply-To: <1275404221.2839.2.camel@maxim-laptop>

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

Hi Maxim,

that's a known issue... and there were several mails to LKML and here
on the ML (as I see you are very active on both lists :-)).
Unfortunately, the patch in [1] didnt go into any (GIT) reposoitory. I know.

I am attaching the original patch and give it a meaningfull name, so
people see it on patchwork.kernel.org (linux-wireless).

Kind Regards,
- Sedat -

[1] http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=2208

On Tue, Jun 1, 2010 at 4:57 PM, Maxim Levitsky <maximlevitsky@gmail.com> wrote:
> On Tue, 2010-06-01 at 15:25 +0300, Maxim Levitsky wrote:
>> Hi,
>>
>> in 2.6.35-rc1 the wireless became just unusable.
>>
>> These are problems that I have:
>>
>> 1. very frequent oopses.This appears to be mention on the list already,
>> but patches I tried don't help.
>>
>> I currently use this bandaid patch, and I still get some crashes:
>
>
> The crash happens here:
>
> 0xec3d is in iwl3945_request_scan (/home/maxim/software/kernel/linux-2.6/drivers/net/wireless/iwlwifi/iwl3945-base.c:1878).
> 1873                    if (chan->band != band)
> 1874                            continue;
> 1875
> 1876                    scan_ch->channel = chan->hw_value;
> 1877
> 1878                    ch_info = iwl_get_channel_info(priv, band, scan_ch->channel);
> 1879                    if (!is_channel_valid(ch_info)) {
> 1880                            IWL_DEBUG_SCAN(priv, "Channel %d is INVALID for this band.\n",
> 1881                                           scan_ch->channel);
> 1882                            continue;
>
>
> The backtrace:
>
> <1>[14212.708840] BUG: unable to handle kernel paging request at 00000002ffffffb1
> <1>[14212.709870] IP: [<ffffffffa0305c0d>] iwl3945_request_scan+0x61d/0xf90 [iwl3945]
> <4>[14212.710763] PGD 0
> <0>[14212.711636] Oops: 0000 [#1] PREEMPT SMP
> <0>[14212.712519] last sysfs file: /sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/hwmon/hwmon1/temp1_input
> <4>[14212.713416] CPU 0
> <4>[14212.713432] Modules linked in: tg3 libphy iwl3945 iwlcore mac80211 cfg80211 ntfs vfat msdos fat lirc_ene0100 lirc_dev af_packet nfsd exportfs nfs lockd nfs_acl auth_rpcgss usb_storage usb_libusual cpufreq_powersave cpufreq_conservative r852 snd_hda_codec_realtek uvcvideo sm_common cpufreq_userspace acpi_cpufreq snd_hda_intel videodev mperf nand snd_hda_codec nand_ids sdhci_pci iTCO_wdt v4l2_compat_ioctl32 joydev snd_hwdep nand_ecc uhci_hcd sunrpc iTCO_vendor_support sdhci ehci_hcd psmouse snd_pcm mmc_core mtd usbcore coretemp ac sg battery evdev serio_raw snd_page_alloc video nouveau ttm drm_kms_helper drm i2c_algo_bit [last unloaded: cfg80211]
> <4>[14212.718797]
> <4>[14212.718797] Pid: 4263, comm: iwl3945 Not tainted 2.6.35-rc1 #30 Nettiling/Aspire 5720
> <4>[14212.718797] RIP: 0010:[<ffffffffa0305c0d>]  [<ffffffffa0305c0d>] iwl3945_request_scan+0x61d/0xf90 [iwl3945]
> <4>[14212.718797] RSP: 0018:ffff88006ce91c80  EFLAGS: 00010297
> <4>[14212.718797] RAX: ffff880066e74100 RBX: ffff88001b2c1dc0 RCX: 00000002ffffffb1
> <4>[14212.718797] RDX: 0000000000000000 RSI: 00000000ffff8800 RDI: ffff88001b2c1dc0
> <4>[14212.718797] RBP: ffff88006ce91d70 R08: 000000000000030e R09: 00000000ffffffff
> <4>[14212.718797] R10: 0000000000000058 R11: 0000000000000001 R12: 0000000000000000
> <4>[14212.718797] R13: ffff88001b295800 R14: 0000000000000000 R15: ffff88001b2958f2
> <4>[14212.718797] FS:  0000000000000000(0000) GS:ffff880002400000(0000) knlGS:0000000000000000
> <4>[14212.718797] CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
> <4>[14212.718797] CR2: 00000002ffffffb1 CR3: 000000000155b000 CR4: 00000000000006f0
> <4>[14212.718797] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> <4>[14212.718797] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
> <4>[14212.718797] Process iwl3945 (pid: 4263, threadinfo ffff88006ce90000, task ffff88006d04a280)
> <0>[14212.718797] Stack:
> <4>[14212.718797]  ffffffffa02c3810 ffff88006d04a2f0 ffff88006ce91cb0 ffffffff81036911
> <4>[14212.718797] <0> 0000000000000000 0000000000000001 ffff88006ce91cd0 ffffffff00000000
> <4>[14212.718797] <0> 0057000000000246 0000005800000021 ffff88006ce91fd8 0058ffff813a07bf
> <0>[14212.718797] Call Trace:
> <4>[14212.718797]  [<ffffffffa02c3810>] ? iwl_bg_start_internal_scan+0x0/0x3d0 [iwlcore]
> <4>[14212.718797]  [<ffffffff81036911>] ? get_parent_ip+0x11/0x50
> <4>[14212.718797]  [<ffffffffa02c3810>] ? iwl_bg_start_internal_scan+0x0/0x3d0 [iwlcore]
> <4>[14212.718797]  [<ffffffffa02c3b2a>] iwl_bg_start_internal_scan+0x31a/0x3d0 [iwlcore]
> <4>[14212.718797]  [<ffffffff81056dfe>] ? worker_thread+0x1ce/0x390
> <4>[14212.718797]  [<ffffffff81056e50>] worker_thread+0x220/0x390
> <4>[14212.718797]  [<ffffffff81056dfe>] ? worker_thread+0x1ce/0x390
> <4>[14212.718797]  [<ffffffff8105bc80>] ? autoremove_wake_function+0x0/0x40
> <4>[14212.718797]  [<ffffffff81056c30>] ? worker_thread+0x0/0x390
> <4>[14212.718797]  [<ffffffff8105b7fe>] kthread+0xae/0xc0
> <4>[14212.718797]  [<ffffffff81003b94>] kernel_thread_helper+0x4/0x10
> <4>[14212.718797]  [<ffffffff8105b750>] ? kthread+0x0/0xc0
> <4>[14212.718797]  [<ffffffff81003b90>] ? kernel_thread_helper+0x0/0x10
> <0>[14212.718797] Code: ff ff 41 8d 52 ff 66 89 95 56 ff ff ff eb 14 0f 1f 80 00 00 00 00 41 ff c4 44 3b 60 0c 0f 83 eb 00 00 00 49 63 d4 48 8b 4c d0 38 <44> 3b 31 75 e6 0f b7 41 06 44 89 f6 41 88 47 01 0f b6 d0 48 89
> <1>[14212.718797] RIP  [<ffffffffa0305c0d>] iwl3945_request_scan+0x61d/0xf90 [iwl3945]
> <4>[14212.718797]  RSP <ffff88006ce91c80>
> <0>[14212.718797] CR2: 00000002ffffffb1
> <4>[14212.760163] ---[ end trace 7075fd19298c88a3 ]---
> <0>[14212.761267] Kernel panic - not syncing: Fatal exception
> <4>[14212.762226] Pid: 4263, comm: iwl3945 Tainted: G      D     2.6.35-rc1 #30
> <4>[14212.763193] Call Trace:
> <4>[14212.764143]  [<ffffffff8139e487>] panic+0x90/0x10a
> <4>[14212.765084]  [<ffffffff8100737c>] oops_end+0xcc/0xe0
> <4>[14212.765095]  [<ffffffff81027c13>] no_context+0xf3/0x260
> <4>[14212.765106]  [<ffffffff810622e5>] ? sched_clock_local+0x25/0x90
> <4>[14212.765116]  [<ffffffff81027e95>] __bad_area_nosemaphore+0x115/0x1d0
> <4>[14212.765128]  [<ffffffff81027f5e>] bad_area_nosemaphore+0xe/0x10
> <4>[14212.765138]  [<ffffffff810283c6>] do_page_fault+0x2e6/0x390
> <4>[14212.765148]  [<ffffffff810622e5>] ? sched_clock_local+0x25/0x90
> <4>[14212.765158]  [<ffffffff81062410>] ? sched_clock_cpu+0xc0/0x110
> <4>[14212.765169]  [<ffffffff8100add7>] ? native_sched_clock+0x27/0x80
> <4>[14212.765179]  [<ffffffff810622e5>] ? sched_clock_local+0x25/0x90
> <4>[14212.765191]  [<ffffffff813a309f>] page_fault+0x1f/0x30
> <4>[14212.765207]  [<ffffffffa0305c0d>] ? iwl3945_request_scan+0x61d/0xf90 [iwl3945]
> <4>[14212.765232]  [<ffffffffa02c3810>] ? iwl_bg_start_internal_scan+0x0/0x3d0 [iwlcore]
> <4>[14212.765246]  [<ffffffff81036911>] ? get_parent_ip+0x11/0x50
> <4>[14212.765266]  [<ffffffffa02c3810>] ? iwl_bg_start_internal_scan+0x0/0x3d0 [iwlcore]
> <4>[14212.765286]  [<ffffffffa02c3b2a>] iwl_bg_start_internal_scan+0x31a/0x3d0 [iwlcore]
> <4>[14212.765299]  [<ffffffff81056dfe>] ? worker_thread+0x1ce/0x390
> <4>[14212.765310]  [<ffffffff81056e50>] worker_thread+0x220/0x390
> <4>[14212.765320]  [<ffffffff81056dfe>] ? worker_thread+0x1ce/0x390
> <4>[14212.765333]  [<ffffffff8105bc80>] ? autoremove_wake_function+0x0/0x40
> <4>[14212.765344]  [<ffffffff81056c30>] ? worker_thread+0x0/0x390
> <4>[14212.765353]  [<ffffffff8105b7fe>] kthread+0xae/0xc0
> <4>[14212.765365]  [<ffffffff81003b94>] kernel_thread_helper+0x4/0x10
> <4>[14212.765376]  [<ffffffff8105b750>] ? kthread+0x0/0xc0
> <4>[14212.765386]  [<ffffffff81003b90>] ? kernel_thread_helper+0x0/0x10
> <3>[14212.765402] [drm:drm_fb_helper_panic] *ERROR* panic occurred, switching back to text console
>>
>> diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
>> index 3e5bffb..1aef988 100644
>> --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
>> +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
>> @@ -1861,6 +1861,11 @@ static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
>>         if (!sband)
>>                 return 0;
>>
>> +       if(!priv->scan_request) {
>> +               WARN_ON(1);
>> +               return 0;
>> +       }
>> +
>>         active_dwell = iwl_get_active_dwell_time(priv, band, n_probes);
>>         passive_dwell = iwl_get_passive_dwell_time(priv, band, vif);
>>
>>
>> 2. mulicast/broadcast is broken.
>> this results in DHCP non working on open access point.
>> It seems that DHCP does work on my home wireless, but avahi-autoipd doesn't see any neighbours, and this is annoying.
>> It can be worked around by doing (sudo ifconfig wlan0 promisc)
>>
>>
> Best regards,
>        Maxim Levitsky
>
> --
> 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
>

[-- Attachment #2: iwl3945-Fix-internal-scan-races.patch --]
[-- Type: text/x-diff, Size: 3295 bytes --]

diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 71aebbb..6e53154 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -1783,6 +1783,74 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
 #endif
 }
 
+static int iwl3945_get_single_channel_for_scan(struct iwl_priv *priv,
+					   struct ieee80211_vif *vif,
+					   enum ieee80211_band band,
+					   struct iwl3945_scan_channel *scan_ch)
+{
+	const struct ieee80211_supported_band *sband;
+	const struct iwl_channel_info *ch_info;
+	u16 passive_dwell = 0;
+	u16 active_dwell = 0;
+	int i, added = 0;
+	u16 channel = 0;
+
+	sband = iwl_get_hw_mode(priv, band);
+	if (!sband) {
+		IWL_ERR(priv, "invalid band\n");
+		return added;
+	}
+
+	active_dwell = iwl_get_active_dwell_time(priv, band, 0);
+	passive_dwell = iwl_get_passive_dwell_time(priv, band, vif);
+
+	if (passive_dwell <= active_dwell)
+		passive_dwell = active_dwell + 1;
+
+	/* only scan single channel, good enough to reset the RF */
+	/* pick the first valid not in-use channel */
+	if (band == IEEE80211_BAND_5GHZ) {
+		for (i = 14; i < priv->channel_count; i++) {
+			if (priv->channel_info[i].channel !=
+			    le16_to_cpu(priv->staging_rxon.channel)) {
+				channel = priv->channel_info[i].channel;
+				ch_info = iwl_get_channel_info(priv,
+					band, channel);
+				if (is_channel_valid(ch_info))
+					break;
+			}
+		}
+	} else {
+		for (i = 0; i < 14; i++) {
+			if (priv->channel_info[i].channel !=
+			    le16_to_cpu(priv->staging_rxon.channel)) {
+					channel =
+						priv->channel_info[i].channel;
+					ch_info = iwl_get_channel_info(priv,
+						band, channel);
+					if (is_channel_valid(ch_info))
+						break;
+			}
+		}
+	}
+
+	if (channel) {
+		scan_ch->channel = cpu_to_le16(channel);
+		scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
+		scan_ch->active_dwell = cpu_to_le16(active_dwell);
+		scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
+		/* Set txpower levels to defaults */
+		scan_ch->tpc.dsp_atten = 110;
+		if (band == IEEE80211_BAND_5GHZ)
+			scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3;
+		else
+			scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
+		added++;
+	} else
+		IWL_ERR(priv, "no valid channel found\n");
+	return added;
+}
+
 static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
 					 enum ieee80211_band band,
 				     u8 is_active, u8 n_probes,
@@ -2933,10 +3001,23 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
 	/* select Rx antennas */
 	scan->flags |= iwl3945_get_antenna_flags(priv);
 
-	scan->channel_count =
+	if (priv->is_internal_short_scan) {
+		scan->channel_count =
+			iwl3945_get_single_channel_for_scan(priv, vif, band,
+				(void *)&scan->data[le16_to_cpu(
+				scan->tx_cmd.len)]);
+	} else {
+		scan->channel_count =
+			iwl3945_get_channels_for_scan(priv, band,
+				is_active, n_probes,
+				(void *)&scan->data[le16_to_cpu(
+				scan->tx_cmd.len)], vif);
+	}
+
+	/*scan->channel_count =
 		iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
 			(void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)], vif);
-
+*/
 	if (scan->channel_count == 0) {
 		IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
 		goto done;

^ permalink raw reply related

* Re: mac80211 rx.c: in recent builds bridging between stations associated to an AP does not work
From: doddel @ 2010-06-01 15:38 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <loom.20100531T230843-554@post.gmane.org>

The effect may be caused by the newly introduced capability to set the
DO_NOT_BRIDGE parameter via nl80211 (thanks for that !).
The user-space tool iw however does not yet support setting this parameter. 


^ permalink raw reply

* Re: mac80211 rx.c: in recent builds bridging between stations associated to an AP does not work
From: Felix Fietkau @ 2010-06-01 15:45 UTC (permalink / raw)
  To: doddel; +Cc: linux-wireless
In-Reply-To: <loom.20100601T173508-447@post.gmane.org>

On 2010-06-01 5:38 PM, doddel wrote:
> The effect may be caused by the newly introduced capability to set the
> DO_NOT_BRIDGE parameter via nl80211 (thanks for that !).
> The user-space tool iw however does not yet support setting this parameter. 
So do you mean that you enabled this option in your wireless config and
now it took effect?
Or did you mean that you did not enable this option, however for some
reason it's still active even though it should not be?

- Felix

^ permalink raw reply

* Re: pull request: wireless-2.6 2010-05-28
From: reinette chatre @ 2010-06-01 16:22 UTC (permalink / raw)
  To: sedat.dilek@gmail.com
  Cc: John W. Linville, davem@davemloft.net,
	linux-wireless@vger.kernel.org, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org, Zheng, Jiajia, Kolekar, Abhijeet,
	Berg, Johannes
In-Reply-To: <AANLkTil8SLseSeq1M_Xg7P4AqMy3V_0jxc7by2Xuaqnb@mail.gmail.com>

Hi Sedat,

On Sat, 2010-05-29 at 06:34 -0700, Sedat Dilek wrote:
> Two people confirmed the patch in [2] fixes:
> 1. iwlwifi-2.6 GIT master (commit f10a237c95abd6d64a3a24553bd1d3bcddd9108b)
> 2. compat-wireless (2010-05-21)
> 
> And it fixes also the above mentionned combination.

We are working on getting this patch upstream. The version tested
contains a significant amount of duplicated code as well as some cleanup
code mixed in. It is thus not appropriate for an upstream submission at
this time.

> As a suggestion:
> What about "copying" bug-reports (incl. its history) from IWL-BTS into
> linux-wireless ML?
> For example (dri-devel related) bug-reports from
> bugzilla.freedesktop.org are "copied" into dri-devel ML.

Pointing people to the bug report seems to work ok. What benefit does
the above have?

Reinette



^ permalink raw reply

* Re: Association problems - again
From: Bob Copeland @ 2010-06-01 17:06 UTC (permalink / raw)
  To: Jaroslav Fojtik; +Cc: linux-wireless
In-Reply-To: <4C02E1CA.10757.239262@jafojtik.seznam.cz>

On Sun, May 30, 2010 at 6:08 PM, Jaroslav Fojtik <jafojtik@seznam.cz> wrote:
> Dears,
>
> I have found that ATH5k has severe problems during association to AP.
>
> Sometimes it needs more than 100 attempts to association, before it connects
> to AP.

Did it work in previous kernels?

You said you reverted 6b5d117eddc09cd976ad8030d715f4 and still have the
problem, right?  Are you sure you booted the kernel with the revert?

> [  149.926717] wlan1: direct probe to 00:15:6d:d6:2a:9d (try 1)
> [  150.013353] eth3: no IPv6 routers present
> [  150.126699] wlan1: direct probe to 00:15:6d:d6:2a:9d (try 2)
> [  150.326707] wlan1: direct probe to 00:15:6d:d6:2a:9d (try 3)
> [  150.526696] wlan1: direct probe to 00:15:6d:d6:2a:9d timed out

Probably traffic is not being sent or received from one side.

-- 
Bob Copeland %% www.bobcopeland.com

^ permalink raw reply

* [PATCH] ath9k: fix queue stop/start based on the number of pending frames
From: Felix Fietkau @ 2010-06-01 17:35 UTC (permalink / raw)
  To: linux-wireless; +Cc: John W. Linville, Luis R. Rodriguez

Because there is a limited number of tx buffers available, once the
queue has been filled to a certain point, ath9k needs to stop accepting
new frames from mac80211. In order to prevent a full WMM queue from
stopping another queue with fewer frames, this patch limits the number
of queued frames to a quarter of the total available tx buffers, minus
some reserved frames to be used for other purposes (e.g. beacons).

Because tx buffers are reserved for frames when they're staged in
software queues as well, the actual queue depth cannot be used for
this, so this patch stores a reference to the tx queue in the ath_buf
struct and keeps track of the total number of pending frames.

Signed-off-by: Felix Fietkau <nbd@openwrt.org>
---
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -137,6 +137,8 @@ void ath_descdma_cleanup(struct ath_soft
 #define ATH_MAX_ANTENNA         3
 #define ATH_RXBUF               512
 #define ATH_TXBUF               512
+#define ATH_TXBUF_RESERVE       5
+#define ATH_MAX_QDEPTH          (ATH_TXBUF / 4 - ATH_TXBUF_RESERVE)
 #define ATH_TXMAXTRY            13
 #define ATH_MGT_TXMAXTRY        4
 
@@ -205,6 +207,7 @@ struct ath_txq {
 	struct list_head txq_fifo_pending;
 	u8 txq_headidx;
 	u8 txq_tailidx;
+	int pending_frames;
 };
 
 struct ath_atx_ac {
@@ -242,6 +245,7 @@ struct ath_buf {
 	struct ath_buf_state bf_state;
 	dma_addr_t bf_dmacontext;
 	struct ath_wiphy *aphy;
+	struct ath_txq *txq;
 };
 
 struct ath_atx_tid {
@@ -331,7 +335,6 @@ void ath_tx_node_cleanup(struct ath_soft
 void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq);
 int ath_tx_init(struct ath_softc *sc, int nbufs);
 void ath_tx_cleanup(struct ath_softc *sc);
-struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb);
 int ath_txq_update(struct ath_softc *sc, int qnum,
 		   struct ath9k_tx_queue_info *q);
 int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -986,32 +986,6 @@ int ath_tx_get_qnum(struct ath_softc *sc
 	return qnum;
 }
 
-struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb)
-{
-	struct ath_txq *txq = NULL;
-	u16 skb_queue = skb_get_queue_mapping(skb);
-	int qnum;
-
-	qnum = ath_get_hal_qnum(skb_queue, sc);
-	txq = &sc->tx.txq[qnum];
-
-	spin_lock_bh(&txq->axq_lock);
-
-	if (txq->axq_depth >= (ATH_TXBUF - 20)) {
-		ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_XMIT,
-			  "TX queue: %d is full, depth: %d\n",
-			  qnum, txq->axq_depth);
-		ath_mac80211_stop_queue(sc, skb_queue);
-		txq->stopped = 1;
-		spin_unlock_bh(&txq->axq_lock);
-		return NULL;
-	}
-
-	spin_unlock_bh(&txq->axq_lock);
-
-	return txq;
-}
-
 int ath_txq_update(struct ath_softc *sc, int qnum,
 		   struct ath9k_tx_queue_info *qinfo)
 {
@@ -1811,6 +1785,7 @@ int ath_tx_start(struct ieee80211_hw *hw
 	struct ath_wiphy *aphy = hw->priv;
 	struct ath_softc *sc = aphy->sc;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+	struct ath_txq *txq = txctl->txq;
 	struct ath_buf *bf;
 	int r;
 
@@ -1820,10 +1795,16 @@ int ath_tx_start(struct ieee80211_hw *hw
 		return -1;
 	}
 
+	bf->txq = txctl->txq;
+	spin_lock_bh(&bf->txq->axq_lock);
+	if (++bf->txq->pending_frames > ATH_MAX_QDEPTH && !txq->stopped) {
+		ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb));
+		txq->stopped = 1;
+	}
+	spin_unlock_bh(&bf->txq->axq_lock);
+
 	r = ath_tx_setup_buffer(hw, bf, skb, txctl);
 	if (unlikely(r)) {
-		struct ath_txq *txq = txctl->txq;
-
 		ath_print(common, ATH_DBG_FATAL, "TX mem alloc failure\n");
 
 		/* upon ath_tx_processq() this TX queue will be resumed, we
@@ -1831,7 +1812,7 @@ int ath_tx_start(struct ieee80211_hw *hw
 		 * we will at least have to run TX completionon one buffer
 		 * on the queue */
 		spin_lock_bh(&txq->axq_lock);
-		if (sc->tx.txq[txq->axq_qnum].axq_depth > 1) {
+		if (!txq->stopped && txq->axq_depth > 1) {
 			ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb));
 			txq->stopped = 1;
 		}
@@ -1972,6 +1953,13 @@ static void ath_tx_complete_buf(struct a
 			tx_flags |= ATH_TX_XRETRY;
 	}
 
+	if (bf->txq) {
+		spin_lock_bh(&bf->txq->axq_lock);
+		bf->txq->pending_frames--;
+		spin_unlock_bh(&bf->txq->axq_lock);
+		bf->txq = NULL;
+	}
+
 	dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE);
 	ath_tx_complete(sc, skb, bf->aphy, tx_flags);
 	ath_debug_stat_tx(sc, txq, bf, ts);
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1026,6 +1026,7 @@ static int ath9k_tx(struct ieee80211_hw 
 	struct ath_tx_control txctl;
 	int padpos, padsize;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+	int qnum;
 
 	if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) {
 		ath_print(common, ATH_DBG_XMIT,
@@ -1098,11 +1099,8 @@ static int ath9k_tx(struct ieee80211_hw 
 		memmove(skb->data, skb->data + padsize, padpos);
 	}
 
-	/* Check if a tx queue is available */
-
-	txctl.txq = ath_test_get_txq(sc, skb);
-	if (!txctl.txq)
-		goto exit;
+	qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc);
+	txctl.txq = &sc->tx.txq[qnum];
 
 	ath_print(common, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb);
 


^ permalink raw reply

* Re: IWL3945 problems in 2.6.35-rc1
From: Maxim Levitsky @ 2010-06-01 18:12 UTC (permalink / raw)
  To: sedat.dilek; +Cc: linux-wireless, iwlwifi maling list
In-Reply-To: <AANLkTinmjlukRABwWWVuO6VRHrULcqB7Zk_HQZSDicKr@mail.gmail.com>

On Tue, 2010-06-01 at 17:21 +0200, Sedat Dilek wrote: 
> Hi Maxim,
> 
> that's a known issue... and there were several mails to LKML and here
> on the ML (as I see you are very active on both lists :-)).
> Unfortunately, the patch in [1] didnt go into any (GIT) reposoitory. I know.
> 
> I am attaching the original patch and give it a meaningfull name, so
> people see it on patchwork.kernel.org (linux-wireless).

The patch appears the work, Thanks!

Now the only problem remains is that I can associate only when device is
in promisc mode.
I think it doesn't receive broadcast frames.

Best regards,
Maxim Levitsky



^ permalink raw reply

* Re: Can't find firmware file
From: Christian Lamparter @ 2010-06-01 18:19 UTC (permalink / raw)
  To: Greg Munroe; +Cc: linux-wireless
In-Reply-To: <4B6B69AB42555546BF8AEBDA21196517011624B5@ihq-app01.keywcorp.com>

please send questions to: linux-wireless@vger.kernel.org ,
else they'll go straight into the spam trash folder.

On Tuesday 01 June 2010 17:18:56 Greg Munroe wrote:
> I'm having trouble loading the firmware files when I compile the
> carl9170 driver into the kernel instead of being mod-loadable.
> If I build "CONFIG_CARL9170_USB=m", it has no trouble locating the
> firmware files in /lib/firmware.
> If I build "CONFIG_CARL9170_USB=y", it can't find the firmware files?
> Thanks again for the help,

http://lkml.org/lkml/2010/3/11/490 et seq. ?

Or: add the firmware into the kernel image.

Regards,
	Chr

^ permalink raw reply

* Re: Path for fixed channel issue in aircrack-ng suite [V2]
From: Maxim Levitsky @ 2010-06-01 18:28 UTC (permalink / raw)
  To: Richard Farina
  Cc: Johannes Berg, Gábor Stefanik, Joker Joker, linux-wireless
In-Reply-To: <4C000B68.9000305@gmail.com>

While debugging recent wireless problems, I gave the aircrack suite a
shot, and found this thread.

How about this patch to fix this issue:


commit fffd6e63ea75850dafbf2ccfb38a4189f43c0282
Author: Maxim Levitsky <maximlevitsky@gmail.com>
Date:   Tue Jun 1 15:43:21 2010 +0300

    wireless: allow to retrieve the channel set on monitor interface
    
    This will allow to preserve compatibility with userspace
    
    Signed-off-by: Maxim Levitsky <maximlevitsky@gmail.com>

diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index b01a6f6..09d979b 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -49,9 +49,12 @@ int cfg80211_set_freq(struct cfg80211_registered_device *rdev,
 {
 	struct ieee80211_channel *chan;
 	int result;
+	struct wireless_dev *mon_dev = NULL;
 
-	if (wdev && wdev->iftype == NL80211_IFTYPE_MONITOR)
+	if (wdev && wdev->iftype == NL80211_IFTYPE_MONITOR) {
+		mon_dev = wdev;
 		wdev = NULL;
+	}
 
 	if (wdev) {
 		ASSERT_WDEV_LOCK(wdev);
@@ -76,5 +79,8 @@ int cfg80211_set_freq(struct cfg80211_registered_device *rdev,
 	if (wdev)
 		wdev->channel = chan;
 
+	if (mon_dev)
+		mon_dev->channel = chan;
+
 	return 0;
 }



^ permalink raw reply related

* Re: Path for fixed channel issue in aircrack-ng suite [V2]
From: Richard Farina @ 2010-06-01 18:36 UTC (permalink / raw)
  To: Maxim Levitsky
  Cc: Johannes Berg, Gábor Stefanik, Joker Joker, linux-wireless,
	mister_x
In-Reply-To: <1275416907.3778.11.camel@maxim-laptop>

Maxim Levitsky wrote:
> While debugging recent wireless problems, I gave the aircrack suite a
> shot, and found this thread.
>
>   
Thanks Maxim!
> How about this patch to fix this issue:
>
>   
I will definitely find some testers, the problem is that I have been 
unable to reliably reproduce the "channel -1".  Since I don't know the 
exact conditions this happens under the best I can do is have a few 
people test it and make sure no one sees the error.

Mister_X, how does this look to you? I assume you are familiar with the 
issue.

Thanks,
Rick Farina
> commit fffd6e63ea75850dafbf2ccfb38a4189f43c0282
> Author: Maxim Levitsky <maximlevitsky@gmail.com>
> Date:   Tue Jun 1 15:43:21 2010 +0300
>
>     wireless: allow to retrieve the channel set on monitor interface
>     
>     This will allow to preserve compatibility with userspace
>     
>     Signed-off-by: Maxim Levitsky <maximlevitsky@gmail.com>
>
> diff --git a/net/wireless/chan.c b/net/wireless/chan.c
> index b01a6f6..09d979b 100644
> --- a/net/wireless/chan.c
> +++ b/net/wireless/chan.c
> @@ -49,9 +49,12 @@ int cfg80211_set_freq(struct cfg80211_registered_device *rdev,
>  {
>  	struct ieee80211_channel *chan;
>  	int result;
> +	struct wireless_dev *mon_dev = NULL;
>  
> -	if (wdev && wdev->iftype == NL80211_IFTYPE_MONITOR)
> +	if (wdev && wdev->iftype == NL80211_IFTYPE_MONITOR) {
> +		mon_dev = wdev;
>  		wdev = NULL;
> +	}
>  
>  	if (wdev) {
>  		ASSERT_WDEV_LOCK(wdev);
> @@ -76,5 +79,8 @@ int cfg80211_set_freq(struct cfg80211_registered_device *rdev,
>  	if (wdev)
>  		wdev->channel = chan;
>  
> +	if (mon_dev)
> +		mon_dev->channel = chan;
> +
>  	return 0;
>  }
>
>
>
>   


^ 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