Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH] ath: move regulatory info into shared common structure
From: Luis R. Rodriguez @ 2009-08-18  1:07 UTC (permalink / raw)
  To: linux-wireless; +Cc: Luis R. Rodriguez

This moves the shared regulatory structure into the
common structure. We will use this ongoing for common
data.

Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
---

OK this goes now tested on ath5k, ath9k, and ar9170.

 drivers/net/wireless/ath/ar9170/ar9170.h     |    2 +-
 drivers/net/wireless/ath/ar9170/main.c       |   14 ++++---
 drivers/net/wireless/ath/ath.h               |   18 +++++++++
 drivers/net/wireless/ath/ath5k/ath5k.h       |    3 -
 drivers/net/wireless/ath/ath5k/base.c        |   14 +++---
 drivers/net/wireless/ath/ath5k/base.h        |   13 ++++++
 drivers/net/wireless/ath/ath5k/phy.c         |    3 +-
 drivers/net/wireless/ath/ath9k/ath9k.h       |   10 +++++
 drivers/net/wireless/ath/ath9k/eeprom_4k.c   |    8 ++-
 drivers/net/wireless/ath/ath9k/eeprom_9287.c |   16 ++++----
 drivers/net/wireless/ath/ath9k/eeprom_def.c  |   14 ++++---
 drivers/net/wireless/ath/ath9k/hw.c          |   53 +++++++++++++++-----------
 drivers/net/wireless/ath/ath9k/hw.h          |    1 -
 drivers/net/wireless/ath/ath9k/main.c        |    6 +-
 drivers/net/wireless/ath/regd.h              |   20 +---------
 15 files changed, 116 insertions(+), 79 deletions(-)

diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h
index e6c3ee3..95f8256 100644
--- a/drivers/net/wireless/ath/ar9170/ar9170.h
+++ b/drivers/net/wireless/ath/ar9170/ar9170.h
@@ -157,6 +157,7 @@ struct ar9170_sta_tid {
 
 struct ar9170 {
 	struct ieee80211_hw *hw;
+	struct ath_common common;
 	struct mutex mutex;
 	enum ar9170_device_state state;
 	unsigned long bad_hw_nagger;
@@ -222,7 +223,6 @@ struct ar9170 {
 
 	/* EEPROM */
 	struct ar9170_eeprom eeprom;
-	struct ath_regulatory regulatory;
 
 	/* tx queues - as seen by hw - */
 	struct sk_buff_head tx_pending[__AR9170_NUM_TXQ];
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c
index 6a9462e..d30f33d 100644
--- a/drivers/net/wireless/ath/ar9170/main.c
+++ b/drivers/net/wireless/ath/ar9170/main.c
@@ -2641,6 +2641,7 @@ static int ar9170_read_eeprom(struct ar9170 *ar)
 {
 #define RW	8	/* number of words to read at once */
 #define RB	(sizeof(u32) * RW)
+	struct ath_regulatory *regulatory = &ar->common.regulatory;
 	u8 *eeprom = (void *)&ar->eeprom;
 	u8 *addr = ar->eeprom.mac_address;
 	__le32 offsets[RW];
@@ -2707,8 +2708,8 @@ static int ar9170_read_eeprom(struct ar9170 *ar)
 	else
 		ar->hw->channel_change_time = 80 * 1000;
 
-	ar->regulatory.current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]);
-	ar->regulatory.current_rd_ext = le16_to_cpu(ar->eeprom.reg_domain[1]);
+	regulatory->current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]);
+	regulatory->current_rd_ext = le16_to_cpu(ar->eeprom.reg_domain[1]);
 
 	/* second part of wiphy init */
 	SET_IEEE80211_PERM_ADDR(ar->hw, addr);
@@ -2722,11 +2723,12 @@ static int ar9170_reg_notifier(struct wiphy *wiphy,
 	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
 	struct ar9170 *ar = hw->priv;
 
-	return ath_reg_notifier_apply(wiphy, request, &ar->regulatory);
+	return ath_reg_notifier_apply(wiphy, request, &ar->common.regulatory);
 }
 
 int ar9170_register(struct ar9170 *ar, struct device *pdev)
 {
+	struct ath_regulatory *regulatory = &ar->common.regulatory;
 	int err;
 
 	/* try to read EEPROM, init MAC addr */
@@ -2734,7 +2736,7 @@ int ar9170_register(struct ar9170 *ar, struct device *pdev)
 	if (err)
 		goto err_out;
 
-	err = ath_regd_init(&ar->regulatory, ar->hw->wiphy,
+	err = ath_regd_init(regulatory, ar->hw->wiphy,
 			    ar9170_reg_notifier);
 	if (err)
 		goto err_out;
@@ -2743,8 +2745,8 @@ int ar9170_register(struct ar9170 *ar, struct device *pdev)
 	if (err)
 		goto err_out;
 
-	if (!ath_is_world_regd(&ar->regulatory))
-		regulatory_hint(ar->hw->wiphy, ar->regulatory.alpha2);
+	if (!ath_is_world_regd(regulatory))
+		regulatory_hint(ar->hw->wiphy, regulatory->alpha2);
 
 	err = ar9170_init_leds(ar);
 	if (err)
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
index e284cd3..a63e90c 100644
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
@@ -19,8 +19,26 @@
 
 #include <linux/skbuff.h>
 
+struct reg_dmn_pair_mapping {
+	u16 regDmnEnum;
+	u16 reg_5ghz_ctl;
+	u16 reg_2ghz_ctl;
+};
+
+struct ath_regulatory {
+	char alpha2[2];
+	u16 country_code;
+	u16 max_power_level;
+	u32 tp_scale;
+	u16 current_rd;
+	u16 current_rd_ext;
+	int16_t power_limit;
+	struct reg_dmn_pair_mapping *regpair;
+};
+
 struct ath_common {
 	u16 cachelsz;
+	struct ath_regulatory regulatory;
 };
 
 struct sk_buff *ath_rxbuf_alloc(struct ath_common *common,
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index c09402e..862762c 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -27,8 +27,6 @@
 #include <linux/types.h>
 #include <net/mac80211.h>
 
-#include "../regd.h"
-
 /* RX/TX descriptor hw structs
  * TODO: Driver part should only see sw structs */
 #include "desc.h"
@@ -1077,7 +1075,6 @@ struct ath5k_hw {
 
 	int			ah_gpio_npins;
 
-	struct ath_regulatory	ah_regulatory;
 	struct ath5k_capabilities ah_capabilities;
 
 	struct ath5k_txq_info	ah_txq[AR5K_NUM_TX_QUEUES];
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 3951b5b..5056410 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -718,9 +718,9 @@ static int ath5k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *re
 {
 	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
 	struct ath5k_softc *sc = hw->priv;
-	struct ath_regulatory *reg = &sc->ah->ah_regulatory;
+	struct ath_regulatory *regulatory = &sc->common.regulatory;
 
-	return ath_reg_notifier_apply(wiphy, request, reg);
+	return ath_reg_notifier_apply(wiphy, request, regulatory);
 }
 
 static int
@@ -728,6 +728,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
 {
 	struct ath5k_softc *sc = hw->priv;
 	struct ath5k_hw *ah = sc->ah;
+	struct ath_regulatory *regulatory = &sc->common.regulatory;
 	u8 mac[ETH_ALEN] = {};
 	int ret;
 
@@ -817,9 +818,8 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
 	memset(sc->bssidmask, 0xff, ETH_ALEN);
 	ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask);
 
-	ah->ah_regulatory.current_rd =
-		ah->ah_capabilities.cap_eeprom.ee_regdomain;
-	ret = ath_regd_init(&ah->ah_regulatory, hw->wiphy, ath5k_reg_notifier);
+	regulatory->current_rd = ah->ah_capabilities.cap_eeprom.ee_regdomain;
+	ret = ath_regd_init(regulatory, hw->wiphy, ath5k_reg_notifier);
 	if (ret) {
 		ATH5K_ERR(sc, "can't initialize regulatory system\n");
 		goto err_queues;
@@ -831,8 +831,8 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
 		goto err_queues;
 	}
 
-	if (!ath_is_world_regd(&sc->ah->ah_regulatory))
-		regulatory_hint(hw->wiphy, sc->ah->ah_regulatory.alpha2);
+	if (!ath_is_world_regd(regulatory))
+		regulatory_hint(hw->wiphy, regulatory->alpha2);
 
 	ath5k_init_leds(sc);
 
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h
index 25a72a8..a28c42f 100644
--- a/drivers/net/wireless/ath/ath5k/base.h
+++ b/drivers/net/wireless/ath/ath5k/base.h
@@ -50,6 +50,8 @@
 
 #include "ath5k.h"
 #include "debug.h"
+
+#include "../regd.h"
 #include "../ath.h"
 
 #define	ATH_RXBUF	40		/* number of RX buffers */
@@ -200,4 +202,15 @@ struct ath5k_softc {
 #define ath5k_hw_hasveol(_ah) \
 	(ath5k_hw_get_capability(_ah, AR5K_CAP_VEOL, 0, NULL) == 0)
 
+static inline struct ath_common *ath5k_hw_common(struct ath5k_hw *ah)
+{
+	return &ah->ah_sc->common;
+}
+
+static inline struct ath_regulatory *ath5k_hw_regulatory(struct ath5k_hw *ah)
+{
+	return &(ath5k_hw_common(ah)->regulatory);
+
+}
+
 #endif
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c
index 298fcf0..1a039f2 100644
--- a/drivers/net/wireless/ath/ath5k/phy.c
+++ b/drivers/net/wireless/ath/ath5k/phy.c
@@ -2198,6 +2198,7 @@ static void
 ath5k_get_max_ctl_power(struct ath5k_hw *ah,
 			struct ieee80211_channel *channel)
 {
+	struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah);
 	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
 	struct ath5k_edge_power *rep = ee->ee_ctl_pwr;
 	u8 *ctl_val = ee->ee_ctl;
@@ -2208,7 +2209,7 @@ ath5k_get_max_ctl_power(struct ath5k_hw *ah,
 	u8 ctl_idx = 0xFF;
 	u32 target = channel->center_freq;
 
-	ctl_mode = ath_regd_get_band_ctl(&ah->ah_regulatory, channel->band);
+	ctl_mode = ath_regd_get_band_ctl(regulatory, channel->band);
 
 	switch (channel->hw_value & CHANNEL_MODES) {
 	case CHANNEL_A:
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 2c9f662..0e444a6 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -631,6 +631,16 @@ int ath_get_hal_qnum(u16 queue, struct ath_softc *sc);
 int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc);
 int ath_cabq_update(struct ath_softc *);
 
+static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah)
+{
+	return &ah->ah_sc->common;
+}
+
+static inline struct ath_regulatory *ath9k_hw_regulatory(struct ath_hw *ah)
+{
+	return &(ath9k_hw_common(ah)->regulatory);
+}
+
 static inline void ath_read_cachesize(struct ath_softc *sc, int *csz)
 {
 	sc->bus_ops->read_cachesize(sc, csz);
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
index d34dd23..b8eca7b 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
@@ -508,6 +508,7 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
 	|| (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \
 	    ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))
 
+	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
 	int i;
 	int16_t twiceLargestAntenna;
 	u16 twiceMinEdgePower;
@@ -541,9 +542,9 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
 					   twiceLargestAntenna, 0);
 
 	maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
-	if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) {
+	if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
 		maxRegAllowedPower -=
-			(tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2);
+			(tpScaleReductionTable[(regulatory->tp_scale)] * 2);
 	}
 
 	scaledPower = min(powerLimit, maxRegAllowedPower);
@@ -707,6 +708,7 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
 				    u8 twiceMaxRegulatoryPower,
 				    u8 powerLimit)
 {
+	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
 	struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
 	struct modal_eep_4k_header *pModal = &pEepData->modalHeader;
 	int16_t ratesArray[Ar5416RateSize];
@@ -744,7 +746,7 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
 	else if (IS_CHAN_HT20(chan))
 		i = rateHt20_0;
 
-	ah->regulatory.max_power_level = ratesArray[i];
+	regulatory->max_power_level = ratesArray[i];
 
 	if (AR_SREV_9280_10_OR_LATER(ah)) {
 		for (i = 0; i < Ar5416RateSize; i++)
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
index 9590979..c20c21a 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
@@ -599,7 +599,7 @@ static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah,
 {
 #define REDUCE_SCALED_POWER_BY_TWO_CHAIN     6
 #define REDUCE_SCALED_POWER_BY_THREE_CHAIN   10
-
+	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
 	u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
 	static const u16 tpScaleReductionTable[5] =
 		{ 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
@@ -632,9 +632,9 @@ static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah,
 					    twiceLargestAntenna, 0);
 
 	maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
-	if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX)
+	if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX)
 		maxRegAllowedPower -=
-			(tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2);
+			(tpScaleReductionTable[(regulatory->tp_scale)] * 2);
 
 	scaledPower = min(powerLimit, maxRegAllowedPower);
 
@@ -831,7 +831,7 @@ static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah,
 {
 #define INCREASE_MAXPOW_BY_TWO_CHAIN     6
 #define INCREASE_MAXPOW_BY_THREE_CHAIN   10
-
+	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
 	struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
 	struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader;
 	int16_t ratesArray[Ar5416RateSize];
@@ -949,20 +949,20 @@ static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah,
 		i = rate6mb;
 
 	if (AR_SREV_9280_10_OR_LATER(ah))
-		ah->regulatory.max_power_level =
+		regulatory->max_power_level =
 			ratesArray[i] + AR9287_PWR_TABLE_OFFSET_DB * 2;
 	else
-		ah->regulatory.max_power_level = ratesArray[i];
+		regulatory->max_power_level = ratesArray[i];
 
 	switch (ar5416_get_ntxchains(ah->txchainmask)) {
 	case 1:
 		break;
 	case 2:
-		ah->regulatory.max_power_level +=
+		regulatory->max_power_level +=
 			INCREASE_MAXPOW_BY_TWO_CHAIN;
 		break;
 	case 3:
-		ah->regulatory.max_power_level +=
+		regulatory->max_power_level +=
 			INCREASE_MAXPOW_BY_THREE_CHAIN;
 		break;
 	default:
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c
index 5211ad9..ae7fb5d 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
@@ -904,6 +904,7 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
 #define REDUCE_SCALED_POWER_BY_TWO_CHAIN     6  /* 10*log10(2)*2 */
 #define REDUCE_SCALED_POWER_BY_THREE_CHAIN   10 /* 10*log10(3)*2 */
 
+	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
 	struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
 	u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
 	static const u16 tpScaleReductionTable[5] =
@@ -953,9 +954,9 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
 
 	maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
 
-	if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) {
+	if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
 		maxRegAllowedPower -=
-			(tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2);
+			(tpScaleReductionTable[(regulatory->tp_scale)] * 2);
 	}
 
 	scaledPower = min(powerLimit, maxRegAllowedPower);
@@ -1163,6 +1164,7 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
 				    u8 powerLimit)
 {
 #define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta)
+	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
 	struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
 	struct modal_eep_header *pModal =
 		&(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]);
@@ -1292,19 +1294,19 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
 		i = rateHt20_0;
 
 	if (AR_SREV_9280_10_OR_LATER(ah))
-		ah->regulatory.max_power_level =
+		regulatory->max_power_level =
 			ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2;
 	else
-		ah->regulatory.max_power_level = ratesArray[i];
+		regulatory->max_power_level = ratesArray[i];
 
 	switch(ar5416_get_ntxchains(ah->txchainmask)) {
 	case 1:
 		break;
 	case 2:
-		ah->regulatory.max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN;
+		regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN;
 		break;
 	case 3:
-		ah->regulatory.max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
+		regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
 		break;
 	default:
 		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index df62113..4f3d5ea 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -439,8 +439,13 @@ static void ath9k_hw_init_config(struct ath_hw *ah)
 
 static void ath9k_hw_init_defaults(struct ath_hw *ah)
 {
+	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+
+	regulatory->country_code = CTRY_DEFAULT;
+	regulatory->power_limit = MAX_RATE_POWER;
+	regulatory->tp_scale = ATH9K_TP_SCALE_MAX;
+
 	ah->hw_version.magic = AR5416_MAGIC;
-	ah->regulatory.country_code = CTRY_DEFAULT;
 	ah->hw_version.subvendorid = 0;
 
 	ah->ah_flags = 0;
@@ -449,8 +454,6 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)
 	if (!AR_SREV_9100(ah))
 		ah->ah_flags = AH_USE_EEPROM;
 
-	ah->regulatory.power_limit = MAX_RATE_POWER;
-	ah->regulatory.tp_scale = ATH9K_TP_SCALE_MAX;
 	ah->atim_window = 0;
 	ah->sta_id1_defaults = AR_STA_ID1_CRPT_MIC_ENABLE;
 	ah->beacon_interval = 100;
@@ -1368,6 +1371,7 @@ static int ath9k_hw_process_ini(struct ath_hw *ah,
 				struct ath9k_channel *chan,
 				enum ath9k_ht_macmode macmode)
 {
+	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
 	int i, regWrites = 0;
 	struct ieee80211_channel *channel = chan->chan;
 	u32 modesIndex, freqIndex;
@@ -1474,11 +1478,11 @@ static int ath9k_hw_process_ini(struct ath_hw *ah,
 		ath9k_olc_init(ah);
 
 	ah->eep_ops->set_txpower(ah, chan,
-				 ath9k_regd_get_ctl(&ah->regulatory, chan),
+				 ath9k_regd_get_ctl(regulatory, chan),
 				 channel->max_antenna_gain * 2,
 				 channel->max_power * 2,
 				 min((u32) MAX_RATE_POWER,
-				 (u32) ah->regulatory.power_limit));
+				 (u32) regulatory->power_limit));
 
 	if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) {
 		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
@@ -1796,6 +1800,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
 				    struct ath9k_channel *chan,
 				    enum ath9k_ht_macmode macmode)
 {
+	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
 	struct ieee80211_channel *channel = chan->chan;
 	u32 synthDelay, qnum;
 
@@ -1828,11 +1833,11 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
 	}
 
 	ah->eep_ops->set_txpower(ah, chan,
-			     ath9k_regd_get_ctl(&ah->regulatory, chan),
+			     ath9k_regd_get_ctl(regulatory, chan),
 			     channel->max_antenna_gain * 2,
 			     channel->max_power * 2,
 			     min((u32) MAX_RATE_POWER,
-			     (u32) ah->regulatory.power_limit));
+			     (u32) regulatory->power_limit));
 
 	synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
 	if (IS_CHAN_B(chan))
@@ -3480,27 +3485,29 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
 void ath9k_hw_fill_cap_info(struct ath_hw *ah)
 {
 	struct ath9k_hw_capabilities *pCap = &ah->caps;
+	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+
 	u16 capField = 0, eeval;
 
 	eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_0);
-	ah->regulatory.current_rd = eeval;
+	regulatory->current_rd = eeval;
 
 	eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_1);
 	if (AR_SREV_9285_10_OR_LATER(ah))
 		eeval |= AR9285_RDEXT_DEFAULT;
-	ah->regulatory.current_rd_ext = eeval;
+	regulatory->current_rd_ext = eeval;
 
 	capField = ah->eep_ops->get_eeprom(ah, EEP_OP_CAP);
 
 	if (ah->opmode != NL80211_IFTYPE_AP &&
 	    ah->hw_version.subvendorid == AR_SUBVENDOR_ID_NEW_A) {
-		if (ah->regulatory.current_rd == 0x64 ||
-		    ah->regulatory.current_rd == 0x65)
-			ah->regulatory.current_rd += 5;
-		else if (ah->regulatory.current_rd == 0x41)
-			ah->regulatory.current_rd = 0x43;
+		if (regulatory->current_rd == 0x64 ||
+		    regulatory->current_rd == 0x65)
+			regulatory->current_rd += 5;
+		else if (regulatory->current_rd == 0x41)
+			regulatory->current_rd = 0x43;
 		DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
-			"regdomain mapped to 0x%x\n", ah->regulatory.current_rd);
+			"regdomain mapped to 0x%x\n", regulatory->current_rd);
 	}
 
 	eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE);
@@ -3635,7 +3642,7 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah)
 	else
 		pCap->hw_caps |= ATH9K_HW_CAP_4KB_SPLITTRANS;
 
-	if (ah->regulatory.current_rd_ext & (1 << REG_EXT_JAPAN_MIDBAND)) {
+	if (regulatory->current_rd_ext & (1 << REG_EXT_JAPAN_MIDBAND)) {
 		pCap->reg_cap =
 			AR_EEPROM_EEREGCAP_EN_KK_NEW_11A |
 			AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN |
@@ -3664,6 +3671,7 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah)
 bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type,
 			    u32 capability, u32 *result)
 {
+	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
 	switch (type) {
 	case ATH9K_CAP_CIPHER:
 		switch (capability) {
@@ -3712,13 +3720,13 @@ bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type,
 		case 0:
 			return 0;
 		case 1:
-			*result = ah->regulatory.power_limit;
+			*result = regulatory->power_limit;
 			return 0;
 		case 2:
-			*result = ah->regulatory.max_power_level;
+			*result = regulatory->max_power_level;
 			return 0;
 		case 3:
-			*result = ah->regulatory.tp_scale;
+			*result = regulatory->tp_scale;
 			return 0;
 		}
 		return false;
@@ -3956,17 +3964,18 @@ bool ath9k_hw_disable(struct ath_hw *ah)
 
 void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit)
 {
+	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
 	struct ath9k_channel *chan = ah->curchan;
 	struct ieee80211_channel *channel = chan->chan;
 
-	ah->regulatory.power_limit = min(limit, (u32) MAX_RATE_POWER);
+	regulatory->power_limit = min(limit, (u32) MAX_RATE_POWER);
 
 	ah->eep_ops->set_txpower(ah, chan,
-				 ath9k_regd_get_ctl(&ah->regulatory, chan),
+				 ath9k_regd_get_ctl(regulatory, chan),
 				 channel->max_antenna_gain * 2,
 				 channel->max_power * 2,
 				 min((u32) MAX_RATE_POWER,
-				 (u32) ah->regulatory.power_limit));
+				 (u32) regulatory->power_limit));
 }
 
 void ath9k_hw_setmac(struct ath_hw *ah, const u8 *mac)
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index de31a15..24b3063 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -396,7 +396,6 @@ struct ath_hw {
 	struct ath9k_hw_version hw_version;
 	struct ath9k_ops_config config;
 	struct ath9k_hw_capabilities caps;
-	struct ath_regulatory regulatory;
 	struct ath9k_channel channels[38];
 	struct ath9k_channel *curchan;
 
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 2f9c149..55fbce2 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1293,7 +1293,7 @@ static int ath9k_reg_notifier(struct wiphy *wiphy,
 	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
 	struct ath_wiphy *aphy = hw->priv;
 	struct ath_softc *sc = aphy->sc;
-	struct ath_regulatory *reg = &sc->sc_ah->regulatory;
+	struct ath_regulatory *reg = &sc->common.regulatory;
 
 	return ath_reg_notifier_apply(wiphy, request, reg);
 }
@@ -1586,12 +1586,12 @@ int ath_init_device(u16 devid, struct ath_softc *sc)
 
 	ath_set_hw_capab(sc, hw);
 
-	error = ath_regd_init(&sc->sc_ah->regulatory, sc->hw->wiphy,
+	error = ath_regd_init(&sc->common.regulatory, sc->hw->wiphy,
 			      ath9k_reg_notifier);
 	if (error)
 		return error;
 
-	reg = &sc->sc_ah->regulatory;
+	reg = &sc->common.regulatory;
 
 	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
 		setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
diff --git a/drivers/net/wireless/ath/regd.h b/drivers/net/wireless/ath/regd.h
index 07291cc..4d3c536 100644
--- a/drivers/net/wireless/ath/regd.h
+++ b/drivers/net/wireless/ath/regd.h
@@ -18,9 +18,10 @@
 #define REGD_H
 
 #include <linux/nl80211.h>
-
 #include <net/cfg80211.h>
 
+#include "ath.h"
+
 #define NO_CTL 0xff
 #define SD_NO_CTL               0xE0
 #define NO_CTL                  0xff
@@ -47,29 +48,12 @@
 #define CHANNEL_HALF_BW         10
 #define CHANNEL_QUARTER_BW      5
 
-struct reg_dmn_pair_mapping {
-	u16 regDmnEnum;
-	u16 reg_5ghz_ctl;
-	u16 reg_2ghz_ctl;
-};
-
 struct country_code_to_enum_rd {
 	u16 countryCode;
 	u16 regDmnEnum;
 	const char *isoName;
 };
 
-struct ath_regulatory {
-	char alpha2[2];
-	u16 country_code;
-	u16 max_power_level;
-	u32 tp_scale;
-	u16 current_rd;
-	u16 current_rd_ext;
-	int16_t power_limit;
-	struct reg_dmn_pair_mapping *regpair;
-};
-
 enum CountryCode {
 	CTRY_ALBANIA = 8,
 	CTRY_ALGERIA = 12,
-- 
1.6.3.3


^ permalink raw reply related

* Re: question about ieee80211_tx.c (fwd)
From: Zhu Yi @ 2009-08-18  1:13 UTC (permalink / raw)
  To: Gábor Stefanik
  Cc: Julia Lawall, linux-wireless@vger.kernel.org, gregkh@suse.de
In-Reply-To: <69e28c910908170450l65d493dbnb1d2e8f14d29dadc@mail.gmail.com>

On Mon, 2009-08-17 at 19:50 +0800, Gábor Stefanik wrote:
> On Mon, Aug 17, 2009 at 10:03 AM, Julia Lawall<julia@diku.dk> wrote:
> > The files ieee80211_tx.c in the directories
> > drivers/staging/rtl8192su/ieee80211 and
> drivers/staging/rtl8192e/ieee80211
> > both contain the following code in the function
> > ieee80211_query_protectionmode:
> >
> >       if (ieee->mode == IW_MODE_MASTER)
> >                        goto NO_PROTECTION;
> >
> > Elsewhere in these files when there is a comparison against an
> IW_MODE
> > value, the field that is compared is iw_mode.  Should that be the
> case
> > here as well?
> >
> > thanks,
> > julia
> 
> I don't know; rtl8192su & rtl8192e use a modified version of the
> libipw stack, rather than the mac80211 stack found behind non-staging
> drivers.

This is clearly a bug. The question is: who is maintaining this driver
and why it doesn't use/extend ieee80211/libipw?

Thanks,
-yi


^ permalink raw reply

* Re: [PATCH] cfg80211: report userspace SME connected event properly
From: Zhu Yi @ 2009-08-18  1:34 UTC (permalink / raw)
  To: Johannes Berg; +Cc: John Linville, linux-wireless
In-Reply-To: <1250504534.15103.0.camel@johannes.local>

On Mon, 2009-08-17 at 18:22 +0800, Johannes Berg wrote:
> Instead of hacking the event reporting into the
> __cfg80211_connect_result() function which is also
> invoked by others, set up things correctly and then
> invoke that function, so that it can do more sanity
> checking.
> 
> Also, it is currently not possible to get a ROAMED
> event from the userspace SME anyway since we send
> out a DISCONNECTED event when it disassociates and
> then a new CONNECTED event on the next association.
> 
> Thanks to Zhu Yi for pointing out that the code is
> somewhat convoluted and doesn't warn when it should.
> 
> Signed-off-by: Johannes Berg <johannes@sipsolutions.net>

This makes it clear cfg80211_connect_result() shouldn't be called in !
CFG80211_SME_CONNECTING state. Thanks!

-yi


^ permalink raw reply

* Re: question about ieee80211_tx.c (fwd)
From: Greg KH @ 2009-08-18  1:35 UTC (permalink / raw)
  To: Zhu Yi; +Cc: Gábor Stefanik, Julia Lawall, linux-wireless@vger.kernel.org
In-Reply-To: <1250558021.9651.35.camel@debian>

On Tue, Aug 18, 2009 at 09:13:41AM +0800, Zhu Yi wrote:
> On Mon, 2009-08-17 at 19:50 +0800, Gábor Stefanik wrote:
> > On Mon, Aug 17, 2009 at 10:03 AM, Julia Lawall<julia@diku.dk> wrote:
> > > The files ieee80211_tx.c in the directories
> > > drivers/staging/rtl8192su/ieee80211 and
> > drivers/staging/rtl8192e/ieee80211
> > > both contain the following code in the function
> > > ieee80211_query_protectionmode:
> > >
> > >       if (ieee->mode == IW_MODE_MASTER)
> > >                        goto NO_PROTECTION;
> > >
> > > Elsewhere in these files when there is a comparison against an
> > IW_MODE
> > > value, the field that is compared is iw_mode.  Should that be the
> > case
> > > here as well?
> > >
> > > thanks,
> > > julia
> > 
> > I don't know; rtl8192su & rtl8192e use a modified version of the
> > libipw stack, rather than the mac80211 stack found behind non-staging
> > drivers.
> 
> This is clearly a bug. The question is: who is maintaining this driver
> and why it doesn't use/extend ieee80211/libipw?

I maintain it, and I am working to convert it to use the existing
ieee80211 stack that is in the kernel.  Remember, these are drivers in
the staging tree, they are usually "crap" :)

thanks,

greg k-h

^ permalink raw reply

* [ANN] wireless-regdb: master-2009-08-17
From: wireless @ 2009-08-18  3:10 UTC (permalink / raw)
  To: linux-wireless


A new release of wireless-regdb (master-2009-08-17) is available at:

http://wireless.kernel.org/download/wireless-regdb/wireless-regdb-2009.08.17.tar.bz2

SHA1 sum: ab87bfd0b2f26a8e1213da16ce2add47c831ac66


For your convenience the individual regulatory.bin file can be downloaded from:

http://wireless.kernel.org/download/wireless-regdb/regulatory.bins/2009.08.17-regulatory.bin

SHA1 sum fb30b37c3e838f8d71f66a435febfbbef692504f

Here is the short log of the changes included in this 
release:

Kel Modderman -  wireless-regdb: manual page section mismatch

^ permalink raw reply

* [PATCH] wl1251: halt the embedded CPU before loading firmware
From: Bob Copeland @ 2009-08-18  3:33 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless

After initial power-up, the embedded cpu is usually halted.  However,
if we down the interface and only do a soft reset before bringing
the interface back up, it will still be running and the firmware
loading code will bail out.  This change halts the CPU before loading
the firmware, enabling a second call to wl1251_boot() to succeed
without a hard reset.

Signed-off-by: Bob Copeland <me@bobcopeland.com>
---

Hi Kalle,

Thoughts on this?  It fixes my remaining issue with warm card reset.
I think Android code does this in the firmware loader:

http://android.git.kernel.org/?p=platform/system/wlan/ti.git;a=blob;f=sta_dk_4_0_4_32/common/src/TNETW_Driver/FW_Transfer/HwInit/HwInit.c;h=e5cc2becdd2b9010903598fc56574776f6aeec8d;hb=HEAD#l291

 drivers/net/wireless/wl12xx/wl1251_boot.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.c b/drivers/net/wireless/wl12xx/wl1251_boot.c
index 592c3b5..452d748 100644
--- a/drivers/net/wireless/wl12xx/wl1251_boot.c
+++ b/drivers/net/wireless/wl12xx/wl1251_boot.c
@@ -465,6 +465,9 @@ int wl1251_boot(struct wl1251 *wl)
 	int ret = 0, minor_minor_e2_ver;
 	u32 tmp, boot_data;
 
+	/* halt embedded ARM CPU while loading firmware */
+	wl1251_reg_write32(wl, ACX_REG_ECPU_CONTROL, ECPU_CONTROL_HALT);
+
 	ret = wl1251_boot_soft_reset(wl);
 	if (ret < 0)
 		goto out;
-- 
1.6.2.5

-- 
Bob Copeland %% www.bobcopeland.com


^ permalink raw reply related

* [PATCH 00/29] mwl8k update to version 0.10
From: Lennert Buytenhek @ 2009-08-18  3:49 UTC (permalink / raw)
  To: linville, linux-wireless

In this series, various mwl8k coding style cleanups, removal of the
usage of radio_enabled, some minor bug fixes, optimisations, and
removal of most of the driver's workqueue use.  (Against latest
wireless-testing.)

^ permalink raw reply

* [PATCH 01/29] mwl8k: remove various unused struct members and defines
From: Lennert Buytenhek @ 2009-08-18  3:50 UTC (permalink / raw)
  To: linville, linux-wireless

Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
---
 drivers/net/wireless/mwl8k.c |   73 ++++-------------------------------------
 1 files changed, 8 insertions(+), 65 deletions(-)

diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 8a6d3af..6f78fae 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -58,7 +58,6 @@ MODULE_DEVICE_TABLE(pci, mwl8k_table);
 #define MWL8K_HIU_H2A_INTERRUPT_STATUS_MASK	0x00000c28
 #define  MWL8K_H2A_INT_DUMMY			(1 << 20)
 #define  MWL8K_H2A_INT_RESET			(1 << 15)
-#define  MWL8K_H2A_INT_PS			(1 << 2)
 #define  MWL8K_H2A_INT_DOORBELL			(1 << 1)
 #define  MWL8K_H2A_INT_PPA_READY		(1 << 0)
 
@@ -161,10 +160,8 @@ struct mwl8k_priv {
 
 	/* lock held over TX and TX reap */
 	spinlock_t tx_lock;
-	u32 int_mask;
 
 	struct ieee80211_vif *vif;
-	struct list_head vif_list;
 
 	struct ieee80211_channel *current_channel;
 
@@ -173,10 +170,8 @@ struct mwl8k_priv {
 	dma_addr_t cookie_dma;
 
 	u16 num_mcaddrs;
-	u16 region_code;
 	u8 hw_rev;
 	__le32 fw_rev;
-	u32 wep_enabled;
 
 	/*
 	 * Running count of TX packets in flight, to avoid
@@ -226,8 +221,6 @@ struct mwl8k_priv {
 
 /* Per interface specific private data */
 struct mwl8k_vif {
-	struct list_head node;
-
 	/* backpointer to parent config block */
 	struct mwl8k_priv *priv;
 
@@ -247,18 +240,11 @@ struct mwl8k_vif {
 	/* number of supported legacy rates */
 	u8	legacy_nrates;
 
-	/* Number of supported MCS rates. Work in progress */
-	u8	mcs_nrates;
-
 	 /* Index into station database.Returned by update_sta_db call */
 	u8	peer_id;
 
 	/* Non AMPDU sequence number assigned by driver */
 	u16	seqno;
-
-	/* Note:There is no channel info,
-	 * refer to the master channel info in priv
-	 */
 };
 
 #define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv))
@@ -681,11 +667,9 @@ struct ewc_ht_info {
 
 /* Peer Entry flags - used to define the type of the peer node */
 #define MWL8K_PEER_TYPE_ACCESSPOINT	2
-#define MWL8K_PEER_TYPE_ADHOC_STATION	4
 
 #define MWL8K_IEEE_LEGACY_DATA_RATES	12
 #define MWL8K_MCS_BITMAP_SIZE		16
-#define pad_size			16
 
 struct peer_capability_info {
 	/* Peer type - AP vs. STA.  */
@@ -707,7 +691,7 @@ struct peer_capability_info {
 
 	/* HT rate table. Intersection of our rates and peer rates.  */
 	__u8	ht_rates[MWL8K_MCS_BITMAP_SIZE];
-	__u8	pad[pad_size];
+	__u8	pad[16];
 
 	/* If set, interoperability mode, no proprietary extensions.  */
 	__u8	interop;
@@ -717,15 +701,6 @@ struct peer_capability_info {
 } __attribute__((packed));
 
 /* Inline functions to manipulate QoS field in data descriptor.  */
-static inline u16 mwl8k_qos_setbit_tid(u16 qos, u8 tid)
-{
-	u16 val_mask = 0x000f;
-	u16 qos_mask = ~val_mask;
-
-	/* TID bits 0-3 */
-	return (qos & qos_mask) | (tid & val_mask);
-}
-
 static inline u16 mwl8k_qos_setbit_eosp(u16 qos)
 {
 	u16 val_mask = 1 << 4;
@@ -826,9 +801,7 @@ static inline struct sk_buff *mwl8k_add_dma_header(struct sk_buff *skb)
 /*
  * Packet reception.
  */
-#define MWL8K_RX_CTRL_KEY_INDEX_MASK	0x30
 #define MWL8K_RX_CTRL_OWNED_BY_HOST	0x02
-#define MWL8K_RX_CTRL_AMPDU		0x01
 
 struct mwl8k_rx_desc {
 	__le16 pkt_len;
@@ -1073,8 +1046,6 @@ enum {
 
 /* Transmit packet ACK policy */
 #define MWL8K_TXD_ACK_POLICY_NORMAL		0
-#define MWL8K_TXD_ACK_POLICY_NONE		1
-#define MWL8K_TXD_ACK_POLICY_NO_EXPLICIT	2
 #define MWL8K_TXD_ACK_POLICY_BLOCKACK		3
 
 #define GET_TXQ(_ac) (\
@@ -1083,20 +1054,11 @@ enum {
 		((_ac) == WME_AC_BK) ? MWL8K_WME_AC_BK : \
 		MWL8K_WME_AC_BE)
 
-#define MWL8K_TXD_STATUS_IDLE			0x00000000
-#define MWL8K_TXD_STATUS_USED			0x00000001
 #define MWL8K_TXD_STATUS_OK			0x00000001
 #define MWL8K_TXD_STATUS_OK_RETRY		0x00000002
 #define MWL8K_TXD_STATUS_OK_MORE_RETRY		0x00000004
 #define MWL8K_TXD_STATUS_MULTICAST_TX		0x00000008
-#define MWL8K_TXD_STATUS_BROADCAST_TX		0x00000010
-#define MWL8K_TXD_STATUS_FAILED_LINK_ERROR	0x00000020
-#define MWL8K_TXD_STATUS_FAILED_EXCEED_LIMIT	0x00000040
-#define MWL8K_TXD_STATUS_FAILED_AGING		0x00000080
-#define MWL8K_TXD_STATUS_HOST_CMD		0x40000000
 #define MWL8K_TXD_STATUS_FW_OWNED		0x80000000
-#define  MWL8K_TXD_SOFTSTALE				0x80
-#define  MWL8K_TXD_SOFTSTALE_MGMT_RETRY			0x01
 
 struct mwl8k_tx_desc {
 	__le32 status;
@@ -1279,12 +1241,10 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw, u32 delay_ms)
 	return 0;
 }
 
-#define MWL8K_TXD_OK	(MWL8K_TXD_STATUS_OK | \
-			 MWL8K_TXD_STATUS_OK_RETRY | \
-			 MWL8K_TXD_STATUS_OK_MORE_RETRY)
-#define MWL8K_TXD_SUCCESS(stat)		((stat) & MWL8K_TXD_OK)
-#define MWL8K_TXD_FAIL_RETRY(stat)	\
-	((stat) & (MWL8K_TXD_STATUS_FAILED_EXCEED_LIMIT))
+#define MWL8K_TXD_SUCCESS(status)				\
+	((status) & (MWL8K_TXD_STATUS_OK |			\
+		     MWL8K_TXD_STATUS_OK_RETRY |		\
+		     MWL8K_TXD_STATUS_OK_MORE_RETRY))
 
 static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force)
 {
@@ -1671,7 +1631,6 @@ static int mwl8k_cmd_get_hw_spec(struct ieee80211_hw *hw)
 		priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs);
 		priv->fw_rev = le32_to_cpu(cmd->fw_rev);
 		priv->hw_rev = cmd->hw_rev;
-		priv->region_code = le16_to_cpu(cmd->region_code);
 	}
 
 	kfree(cmd);
@@ -2150,7 +2109,6 @@ struct mwl8k_cmd_set_edca_params {
 	__u8 txq;
 } __attribute__((packed));
 
-#define MWL8K_GET_EDCA_ALL	0
 #define MWL8K_SET_EDCA_CW	0x01
 #define MWL8K_SET_EDCA_TXOP	0x02
 #define MWL8K_SET_EDCA_AIFS	0x04
@@ -2323,18 +2281,12 @@ static int mwl8k_cmd_update_sta_db(struct ieee80211_hw *hw,
 /*
  * CMD_SET_AID.
  */
-#define IEEE80211_OPMODE_DISABLED			0x00
-#define IEEE80211_OPMODE_NON_MEMBER_PROT_MODE		0x01
-#define IEEE80211_OPMODE_ONE_20MHZ_STA_PROT_MODE	0x02
-#define IEEE80211_OPMODE_HTMIXED_PROT_MODE		0x03
-
 #define MWL8K_RATE_INDEX_MAX_ARRAY			14
 
 #define MWL8K_FRAME_PROT_DISABLED			0x00
 #define MWL8K_FRAME_PROT_11G				0x07
 #define MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY		0x02
 #define MWL8K_FRAME_PROT_11N_HT_ALL			0x06
-#define MWL8K_FRAME_PROT_MASK				0x07
 
 struct mwl8k_cmd_update_set_aid {
 	struct	mwl8k_cmd_pkt header;
@@ -2439,10 +2391,6 @@ static int mwl8k_update_rateset(struct ieee80211_hw *hw,
  */
 #define MWL8K_RATE_TABLE_SIZE	8
 #define MWL8K_UCAST_RATE	0
-#define MWL8K_MCAST_RATE	1
-#define MWL8K_BCAST_RATE	2
-
-#define MWL8K_USE_FIXED_RATE	0x0001
 #define MWL8K_USE_AUTO_RATE	0x0002
 
 struct mwl8k_rate_entry {
@@ -2535,7 +2483,6 @@ static irqreturn_t mwl8k_interrupt(int irq, void *dev_id)
 	status = ioread32(priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS);
 	iowrite32(~status, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS);
 
-	status &= priv->int_mask;
 	if (!status)
 		return IRQ_NONE;
 
@@ -2873,7 +2820,7 @@ static int mwl8k_start(struct ieee80211_hw *hw)
 	}
 
 	/* Enable interrupts */
-	iowrite32(priv->int_mask, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
+	iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
 
 	worker = kzalloc(sizeof(*worker), GFP_KERNEL);
 	if (worker == NULL) {
@@ -3519,7 +3466,6 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
 	priv->hostcmd_wait = NULL;
 	priv->tx_wait = NULL;
 	priv->inconfig = false;
-	priv->wep_enabled = 0;
 	priv->wmm_mode = false;
 	priv->pending_tx_pkts = 0;
 	strncpy(priv->name, MWL8K_NAME, sizeof(priv->name));
@@ -3601,8 +3547,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
 	}
 
 	iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS);
-	priv->int_mask = 0;
-	iowrite32(priv->int_mask, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
+	iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
 	iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL);
 	iowrite32(0xffffffff, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK);
 
@@ -3639,9 +3584,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
 	 * commands use interrupts and avoids polling.  Disable
 	 * interrupts when done.
 	 */
-	priv->int_mask |= MWL8K_A2H_EVENTS;
-
-	iowrite32(priv->int_mask, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
+	iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
 
 	/* Get config data, mac addrs etc */
 	rc = mwl8k_cmd_get_hw_spec(hw);
-- 
1.5.6.4

^ permalink raw reply related

* [PATCH 02/29] mwl8k: s/IEEE80211_ADDR_LEN/ETH_ALEN/g
From: Lennert Buytenhek @ 2009-08-18  3:50 UTC (permalink / raw)
  To: linville, linux-wireless

Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
---
 drivers/net/wireless/mwl8k.c |   47 +++++++++++++++++++----------------------
 1 files changed, 22 insertions(+), 25 deletions(-)

diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 6f78fae..55abf27 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -38,8 +38,6 @@ static DEFINE_PCI_DEVICE_TABLE(mwl8k_table) = {
 };
 MODULE_DEVICE_TABLE(pci, mwl8k_table);
 
-#define IEEE80211_ADDR_LEN			ETH_ALEN
-
 /* Register definitions */
 #define MWL8K_HIU_GEN_PTR			0x00000c10
 #define  MWL8K_MODE_STA				0x0000005a
@@ -199,7 +197,7 @@ struct mwl8k_priv {
 
 	/* XXX need to convert this to handle multiple interfaces */
 	bool capture_beacon;
-	u8 capture_bssid[IEEE80211_ADDR_LEN];
+	u8 capture_bssid[ETH_ALEN];
 	struct sk_buff *beacon_skb;
 
 	/*
@@ -228,8 +226,8 @@ struct mwl8k_vif {
 	struct ieee80211_bss_conf bss_info;
 
 	/* BSSID of AP or IBSS */
-	u8	bssid[IEEE80211_ADDR_LEN];
-	u8	mac_addr[IEEE80211_ADDR_LEN];
+	u8	bssid[ETH_ALEN];
+	u8	mac_addr[ETH_ALEN];
 
 	/*
 	 * Subset of supported legacy rates.
@@ -785,7 +783,7 @@ static inline struct sk_buff *mwl8k_add_dma_header(struct sk_buff *skb)
 		memmove(&tr->wh, wh, hdrlen);
 
 	/* Clear addr4 */
-	memset(tr->wh.addr4, 0, IEEE80211_ADDR_LEN);
+	memset(tr->wh.addr4, 0, ETH_ALEN);
 
 	/*
 	 * Firmware length is the length of the fully formed "802.11
@@ -952,7 +950,7 @@ static inline void mwl8k_save_beacon(struct mwl8k_priv *priv,
 							struct sk_buff *skb)
 {
 	priv->capture_beacon = false;
-	memset(priv->capture_bssid, 0, IEEE80211_ADDR_LEN);
+	memset(priv->capture_bssid, 0, ETH_ALEN);
 
 	/*
 	 * Use GFP_ATOMIC as rxq_process is called from
@@ -1067,7 +1065,7 @@ struct mwl8k_tx_desc {
 	__le16 qos_control;
 	__le32 pkt_phys_addr;
 	__le16 pkt_len;
-	__u8 dest_MAC_addr[IEEE80211_ADDR_LEN];
+	__u8 dest_MAC_addr[ETH_ALEN];
 	__le32 next_tx_desc_phys_addr;
 	__le32 reserved;
 	__le16 rate_info;
@@ -1587,7 +1585,7 @@ struct mwl8k_cmd_get_hw_spec {
 	__u8 hw_rev;
 	__u8 host_interface;
 	__le16 num_mcaddrs;
-	__u8 perm_addr[IEEE80211_ADDR_LEN];
+	__u8 perm_addr[ETH_ALEN];
 	__le16 region_code;
 	__le32 fw_rev;
 	__le32 ps_cookie;
@@ -1644,7 +1642,7 @@ struct mwl8k_cmd_mac_multicast_adr {
 	struct mwl8k_cmd_pkt header;
 	__le16 action;
 	__le16 numaddr;
-	__u8 addr[1][IEEE80211_ADDR_LEN];
+	__u8 addr[1][ETH_ALEN];
 };
 
 #define MWL8K_ENABLE_RX_MULTICAST 0x000F
@@ -1655,7 +1653,7 @@ static int mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw,
 	struct mwl8k_cmd_mac_multicast_adr *cmd;
 	int index = 0;
 	int rc;
-	int size = sizeof(*cmd) + ((mc_count - 1) * IEEE80211_ADDR_LEN);
+	int size = sizeof(*cmd) + ((mc_count - 1) * ETH_ALEN);
 	cmd = kzalloc(size, GFP_KERNEL);
 	if (cmd == NULL)
 		return -ENOMEM;
@@ -1665,11 +1663,11 @@ static int mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw,
 	cmd->action = cpu_to_le16(MWL8K_ENABLE_RX_MULTICAST);
 	cmd->numaddr = cpu_to_le16(mc_count);
 	while ((index < mc_count) && mclist) {
-		if (mclist->da_addrlen != IEEE80211_ADDR_LEN) {
+		if (mclist->da_addrlen != ETH_ALEN) {
 			rc = -EINVAL;
 			goto mwl8k_cmd_mac_multicast_adr_exit;
 		}
-		memcpy(cmd->addr[index], mclist->da_addr, IEEE80211_ADDR_LEN);
+		memcpy(cmd->addr[index], mclist->da_addr, ETH_ALEN);
 		index++;
 		mclist = mclist->next;
 	}
@@ -1848,11 +1846,11 @@ static int mwl8k_cmd_set_pre_scan(struct ieee80211_hw *hw)
 struct mwl8k_cmd_set_post_scan {
 	struct mwl8k_cmd_pkt header;
 	__le32 isibss;
-	__u8 bssid[IEEE80211_ADDR_LEN];
+	__u8 bssid[ETH_ALEN];
 } __attribute__((packed));
 
 static int
-mwl8k_cmd_set_post_scan(struct ieee80211_hw *hw, __u8 mac[IEEE80211_ADDR_LEN])
+mwl8k_cmd_set_post_scan(struct ieee80211_hw *hw, __u8 mac[ETH_ALEN])
 {
 	struct mwl8k_cmd_set_post_scan *cmd;
 	int rc;
@@ -1864,7 +1862,7 @@ mwl8k_cmd_set_post_scan(struct ieee80211_hw *hw, __u8 mac[IEEE80211_ADDR_LEN])
 	cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_POST_SCAN);
 	cmd->header.length = cpu_to_le16(sizeof(*cmd));
 	cmd->isibss = 0;
-	memcpy(cmd->bssid, mac, IEEE80211_ADDR_LEN);
+	memcpy(cmd->bssid, mac, ETH_ALEN);
 
 	rc = mwl8k_post_cmd(hw, &cmd->header);
 	kfree(cmd);
@@ -2216,7 +2214,7 @@ struct mwl8k_cmd_update_sta_db {
 	__le32	action;
 
 	/* Peer MAC address */
-	__u8	peer_addr[IEEE80211_ADDR_LEN];
+	__u8	peer_addr[ETH_ALEN];
 
 	__le32	reserved;
 
@@ -2244,7 +2242,7 @@ static int mwl8k_cmd_update_sta_db(struct ieee80211_hw *hw,
 
 	cmd->action = cpu_to_le32(action);
 	peer_info = &cmd->peer_info;
-	memcpy(cmd->peer_addr, mv_vif->bssid, IEEE80211_ADDR_LEN);
+	memcpy(cmd->peer_addr, mv_vif->bssid, ETH_ALEN);
 
 	switch (action) {
 	case MWL8K_STA_DB_ADD_ENTRY:
@@ -2293,7 +2291,7 @@ struct mwl8k_cmd_update_set_aid {
 	__le16	aid;
 
 	 /* AP's MAC address (BSSID) */
-	__u8	bssid[IEEE80211_ADDR_LEN];
+	__u8	bssid[ETH_ALEN];
 	__le16	protection_mode;
 	__u8	supp_rates[MWL8K_RATE_INDEX_MAX_ARRAY];
 } __attribute__((packed));
@@ -2317,7 +2315,7 @@ static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw,
 	cmd->header.length = cpu_to_le16(sizeof(*cmd));
 	cmd->aid = cpu_to_le16(info->aid);
 
-	memcpy(cmd->bssid, mv_vif->bssid, IEEE80211_ADDR_LEN);
+	memcpy(cmd->bssid, mv_vif->bssid, ETH_ALEN);
 
 	prot_mode = MWL8K_FRAME_PROT_DISABLED;
 
@@ -2934,7 +2932,7 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw,
 	memset(mwl8k_vif, 0, sizeof(*mwl8k_vif));
 
 	/* Save the mac address */
-	memcpy(mwl8k_vif->mac_addr, conf->mac_addr, IEEE80211_ADDR_LEN);
+	memcpy(mwl8k_vif->mac_addr, conf->mac_addr, ETH_ALEN);
 
 	/* Back pointer to parent config block */
 	mwl8k_vif->priv = priv;
@@ -3098,14 +3096,13 @@ static int mwl8k_bss_info_changed_wt(struct work_struct *wt)
 		 * Finalize the join.  Tell rx handler to process
 		 * next beacon from our BSSID.
 		 */
-		memcpy(priv->capture_bssid,
-				mwl8k_vif->bssid, IEEE80211_ADDR_LEN);
+		memcpy(priv->capture_bssid, mwl8k_vif->bssid, ETH_ALEN);
 		priv->capture_beacon = true;
 	} else {
 		mwl8k_cmd_update_sta_db(hw, vif, MWL8K_STA_DB_DEL_ENTRY);
 		memset(&mwl8k_vif->bss_info, 0,
 			sizeof(struct ieee80211_bss_conf));
-		memset(mwl8k_vif->bssid, 0, IEEE80211_ADDR_LEN);
+		memset(mwl8k_vif->bssid, 0, ETH_ALEN);
 	}
 
 mwl8k_bss_info_changed_exit:
@@ -3124,7 +3121,7 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw,
 	int rc;
 
 	if (changed & BSS_CHANGED_BSSID)
-		memcpy(mv_vif->bssid, info->bssid, IEEE80211_ADDR_LEN);
+		memcpy(mv_vif->bssid, info->bssid, ETH_ALEN);
 
 	if ((changed & BSS_CHANGED_ASSOC) == 0)
 		return;
-- 
1.5.6.4

^ permalink raw reply related

* [PATCH 03/29] mwl8k: sort firmware command list by opcode, and trim unused commands
From: Lennert Buytenhek @ 2009-08-18  3:51 UTC (permalink / raw)
  To: linville, linux-wireless

Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
---
 drivers/net/wireless/mwl8k.c |   42 +++++++++++++++++++-----------------------
 1 files changed, 19 insertions(+), 23 deletions(-)

diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 55abf27..9fab145 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -307,25 +307,23 @@ static const struct ieee80211_rate mwl8k_rates[] = {
 #define MWL8K_CMD_GET_HW_SPEC		0x0003
 #define MWL8K_CMD_MAC_MULTICAST_ADR	0x0010
 #define MWL8K_CMD_GET_STAT		0x0014
-#define MWL8K_CMD_RADIO_CONTROL		0x001C
-#define MWL8K_CMD_RF_TX_POWER		0x001E
+#define MWL8K_CMD_RADIO_CONTROL		0x001c
+#define MWL8K_CMD_RF_TX_POWER		0x001e
 #define MWL8K_CMD_SET_PRE_SCAN		0x0107
 #define MWL8K_CMD_SET_POST_SCAN		0x0108
-#define MWL8K_CMD_SET_RF_CHANNEL	0x010A
+#define MWL8K_CMD_SET_RF_CHANNEL	0x010a
+#define MWL8K_CMD_SET_AID		0x010d
+#define MWL8K_CMD_SET_RATE		0x0110
+#define MWL8K_CMD_SET_FINALIZE_JOIN	0x0111
+#define MWL8K_CMD_RTS_THRESHOLD		0x0113
 #define MWL8K_CMD_SET_SLOT		0x0114
+#define MWL8K_CMD_SET_EDCA_PARAMS	0x0115
+#define MWL8K_CMD_SET_WMM_MODE		0x0123
 #define MWL8K_CMD_MIMO_CONFIG		0x0125
+#define MWL8K_CMD_USE_FIXED_RATE	0x0126
 #define MWL8K_CMD_ENABLE_SNIFFER	0x0150
-#define MWL8K_CMD_SET_WMM_MODE		0x0123
-#define MWL8K_CMD_SET_EDCA_PARAMS	0x0115
-#define MWL8K_CMD_SET_FINALIZE_JOIN	0x0111
-#define MWL8K_CMD_UPDATE_STADB		0x1123
 #define MWL8K_CMD_SET_RATEADAPT_MODE	0x0203
-#define MWL8K_CMD_SET_LINKADAPT_MODE	0x0129
-#define MWL8K_CMD_SET_AID		0x010d
-#define MWL8K_CMD_SET_RATE		0x0110
-#define MWL8K_CMD_USE_FIXED_RATE	0x0126
-#define MWL8K_CMD_RTS_THRESHOLD		0x0113
-#define MWL8K_CMD_ENCRYPTION		0x1122
+#define MWL8K_CMD_UPDATE_STADB		0x1123
 
 static const char *mwl8k_cmd_name(u16 cmd, char *buf, int bufsize)
 {
@@ -343,20 +341,18 @@ static const char *mwl8k_cmd_name(u16 cmd, char *buf, int bufsize)
 		MWL8K_CMDNAME(SET_PRE_SCAN);
 		MWL8K_CMDNAME(SET_POST_SCAN);
 		MWL8K_CMDNAME(SET_RF_CHANNEL);
+		MWL8K_CMDNAME(SET_AID);
+		MWL8K_CMDNAME(SET_RATE);
+		MWL8K_CMDNAME(SET_FINALIZE_JOIN);
+		MWL8K_CMDNAME(RTS_THRESHOLD);
 		MWL8K_CMDNAME(SET_SLOT);
+		MWL8K_CMDNAME(SET_EDCA_PARAMS);
+		MWL8K_CMDNAME(SET_WMM_MODE);
 		MWL8K_CMDNAME(MIMO_CONFIG);
+		MWL8K_CMDNAME(USE_FIXED_RATE);
 		MWL8K_CMDNAME(ENABLE_SNIFFER);
-		MWL8K_CMDNAME(SET_WMM_MODE);
-		MWL8K_CMDNAME(SET_EDCA_PARAMS);
-		MWL8K_CMDNAME(SET_FINALIZE_JOIN);
-		MWL8K_CMDNAME(UPDATE_STADB);
 		MWL8K_CMDNAME(SET_RATEADAPT_MODE);
-		MWL8K_CMDNAME(SET_LINKADAPT_MODE);
-		MWL8K_CMDNAME(SET_AID);
-		MWL8K_CMDNAME(SET_RATE);
-		MWL8K_CMDNAME(USE_FIXED_RATE);
-		MWL8K_CMDNAME(RTS_THRESHOLD);
-		MWL8K_CMDNAME(ENCRYPTION);
+		MWL8K_CMDNAME(UPDATE_STADB);
 	default:
 		snprintf(buf, bufsize, "0x%x", cmd);
 	}
-- 
1.5.6.4

^ permalink raw reply related

* [PATCH 04/29] mwl8k: various coding style cleanups
From: Lennert Buytenhek @ 2009-08-18  3:51 UTC (permalink / raw)
  To: linville, linux-wireless

Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
---
 drivers/net/wireless/mwl8k.c |  130 ++++++++++++++++++-----------------------
 1 files changed, 57 insertions(+), 73 deletions(-)

diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 9fab145..a3b0e19 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -1,5 +1,6 @@
 /*
- * drivers/net/wireless/mwl8k.c driver for Marvell TOPDOG 802.11 Wireless cards
+ * drivers/net/wireless/mwl8k.c
+ * Driver for Marvell TOPDOG 802.11 Wireless cards
  *
  * Copyright (C) 2008 Marvell Semiconductor Inc.
  *
@@ -40,12 +41,12 @@ MODULE_DEVICE_TABLE(pci, mwl8k_table);
 
 /* Register definitions */
 #define MWL8K_HIU_GEN_PTR			0x00000c10
-#define  MWL8K_MODE_STA				0x0000005a
-#define  MWL8K_MODE_AP				0x000000a5
+#define  MWL8K_MODE_STA				 0x0000005a
+#define  MWL8K_MODE_AP				 0x000000a5
 #define MWL8K_HIU_INT_CODE			0x00000c14
-#define  MWL8K_FWSTA_READY			0xf0f1f2f4
-#define  MWL8K_FWAP_READY			0xf1f2f4a5
-#define  MWL8K_INT_CODE_CMD_FINISHED		0x00000005
+#define  MWL8K_FWSTA_READY			 0xf0f1f2f4
+#define  MWL8K_FWAP_READY			 0xf1f2f4a5
+#define  MWL8K_INT_CODE_CMD_FINISHED		 0x00000005
 #define MWL8K_HIU_SCRATCH			0x00000c40
 
 /* Host->device communications */
@@ -54,10 +55,10 @@ MODULE_DEVICE_TABLE(pci, mwl8k_table);
 #define MWL8K_HIU_H2A_INTERRUPT_MASK		0x00000c20
 #define MWL8K_HIU_H2A_INTERRUPT_CLEAR_SEL	0x00000c24
 #define MWL8K_HIU_H2A_INTERRUPT_STATUS_MASK	0x00000c28
-#define  MWL8K_H2A_INT_DUMMY			(1 << 20)
-#define  MWL8K_H2A_INT_RESET			(1 << 15)
-#define  MWL8K_H2A_INT_DOORBELL			(1 << 1)
-#define  MWL8K_H2A_INT_PPA_READY		(1 << 0)
+#define  MWL8K_H2A_INT_DUMMY			 (1 << 20)
+#define  MWL8K_H2A_INT_RESET			 (1 << 15)
+#define  MWL8K_H2A_INT_DOORBELL			 (1 << 1)
+#define  MWL8K_H2A_INT_PPA_READY		 (1 << 0)
 
 /* Device->host communications */
 #define MWL8K_HIU_A2H_INTERRUPT_EVENTS		0x00000c2c
@@ -65,16 +66,16 @@ MODULE_DEVICE_TABLE(pci, mwl8k_table);
 #define MWL8K_HIU_A2H_INTERRUPT_MASK		0x00000c34
 #define MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL	0x00000c38
 #define MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK	0x00000c3c
-#define  MWL8K_A2H_INT_DUMMY			(1 << 20)
-#define  MWL8K_A2H_INT_CHNL_SWITCHED		(1 << 11)
-#define  MWL8K_A2H_INT_QUEUE_EMPTY		(1 << 10)
-#define  MWL8K_A2H_INT_RADAR_DETECT		(1 << 7)
-#define  MWL8K_A2H_INT_RADIO_ON			(1 << 6)
-#define  MWL8K_A2H_INT_RADIO_OFF		(1 << 5)
-#define  MWL8K_A2H_INT_MAC_EVENT		(1 << 3)
-#define  MWL8K_A2H_INT_OPC_DONE			(1 << 2)
-#define  MWL8K_A2H_INT_RX_READY			(1 << 1)
-#define  MWL8K_A2H_INT_TX_DONE			(1 << 0)
+#define  MWL8K_A2H_INT_DUMMY			 (1 << 20)
+#define  MWL8K_A2H_INT_CHNL_SWITCHED		 (1 << 11)
+#define  MWL8K_A2H_INT_QUEUE_EMPTY		 (1 << 10)
+#define  MWL8K_A2H_INT_RADAR_DETECT		 (1 << 7)
+#define  MWL8K_A2H_INT_RADIO_ON			 (1 << 6)
+#define  MWL8K_A2H_INT_RADIO_OFF		 (1 << 5)
+#define  MWL8K_A2H_INT_MAC_EVENT		 (1 << 3)
+#define  MWL8K_A2H_INT_OPC_DONE			 (1 << 2)
+#define  MWL8K_A2H_INT_RX_READY			 (1 << 1)
+#define  MWL8K_A2H_INT_TX_DONE			 (1 << 0)
 
 #define MWL8K_A2H_EVENTS	(MWL8K_A2H_INT_DUMMY | \
 				 MWL8K_A2H_INT_CHNL_SWITCHED | \
@@ -331,7 +332,7 @@ static const char *mwl8k_cmd_name(u16 cmd, char *buf, int bufsize)
 					snprintf(buf, bufsize, "%s", #x);\
 					return buf;\
 					} while (0)
-	switch (cmd & (~0x8000)) {
+	switch (cmd & ~0x8000) {
 		MWL8K_CMDNAME(CODE_DNLD);
 		MWL8K_CMDNAME(GET_HW_SPEC);
 		MWL8K_CMDNAME(MAC_MULTICAST_ADR);
@@ -1078,8 +1079,7 @@ static int mwl8k_txq_init(struct ieee80211_hw *hw, int index)
 	int size;
 	int i;
 
-	memset(&txq->tx_stats, 0,
-		sizeof(struct ieee80211_tx_queue_stats));
+	memset(&txq->tx_stats, 0, sizeof(struct ieee80211_tx_queue_stats));
 	txq->tx_stats.limit = MWL8K_TX_DESCS;
 	txq->tx_head = 0;
 	txq->tx_tail = 0;
@@ -1181,10 +1181,10 @@ static int mwl8k_scan_tx_ring(struct mwl8k_priv *priv,
 
 static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw, u32 delay_ms)
 {
-	u32 count = 0;
-	unsigned long timeout = 0;
 	struct mwl8k_priv *priv = hw->priv;
 	DECLARE_COMPLETION_ONSTACK(cmd_wait);
+	u32 count;
+	unsigned long timeout;
 
 	might_sleep();
 
@@ -1219,7 +1219,7 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw, u32 delay_ms)
 		       __func__, __LINE__, delay_ms, count, newcount);
 
 		mwl8k_scan_tx_ring(priv, txinfo, 4);
-		for (index = 0 ; index < 4; index++)
+		for (index = 0; index < 4; index++)
 			printk(KERN_ERR
 				"TXQ:%u L:%u H:%u T:%u FW:%u DRV:%u U:%u\n",
 					index,
@@ -1229,6 +1229,7 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw, u32 delay_ms)
 					txinfo[index].fw_owned,
 					txinfo[index].drv_owned,
 					txinfo[index].unused);
+
 		return -ETIMEDOUT;
 	}
 
@@ -1251,7 +1252,7 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force)
 		int rc;
 		struct mwl8k_tx_desc *tx_desc;
 		unsigned long addr;
-		size_t size;
+		int size;
 		struct sk_buff *skb;
 		struct ieee80211_tx_info *info;
 		u32 status;
@@ -1275,7 +1276,7 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force)
 		priv->pending_tx_pkts--;
 
 		addr = le32_to_cpu(tx_desc->pkt_phys_addr);
-		size = (u32)(le16_to_cpu(tx_desc->pkt_len));
+		size = le16_to_cpu(tx_desc->pkt_len);
 		skb = txq->tx_skb[tx].skb;
 		txq->tx_skb[tx].skb = NULL;
 
@@ -1312,12 +1313,8 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force)
 
 		info = IEEE80211_SKB_CB(skb);
 		ieee80211_tx_info_clear_status(info);
-
-		/* Convert firmware status stuff into tx_status */
-		if (MWL8K_TXD_SUCCESS(status)) {
-			/* Transmit OK */
+		if (MWL8K_TXD_SUCCESS(status))
 			info->flags |= IEEE80211_TX_STAT_ACK;
-		}
 
 		ieee80211_tx_status_irqsafe(hw, skb);
 
@@ -1522,7 +1519,6 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd)
 	dma_addr_t dma_addr;
 	unsigned int dma_size;
 	int rc;
-	u16 __iomem *result;
 	unsigned long timeout = 0;
 	u8 buf[32];
 
@@ -1551,7 +1547,6 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd)
 	pci_unmap_single(priv->pdev, dma_addr, dma_size,
 					PCI_DMA_BIDIRECTIONAL);
 
-	result = &cmd->result;
 	if (!timeout) {
 		spin_lock_irq(&priv->fw_lock);
 		priv->hostcmd_wait = NULL;
@@ -1562,12 +1557,12 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd)
 		       MWL8K_CMD_TIMEOUT_MS);
 		rc = -ETIMEDOUT;
 	} else {
-		rc = *result ? -EINVAL : 0;
+		rc = cmd->result ? -EINVAL : 0;
 		if (rc)
 			printk(KERN_ERR "%s: Command %s error 0x%x\n",
 			       priv->name,
 			       mwl8k_cmd_name(cmd->code, buf, sizeof(buf)),
-			       *result);
+			       cmd->result);
 	}
 
 	return rc;
@@ -1638,10 +1633,11 @@ struct mwl8k_cmd_mac_multicast_adr {
 	struct mwl8k_cmd_pkt header;
 	__le16 action;
 	__le16 numaddr;
-	__u8 addr[1][ETH_ALEN];
+	__u8 addr[0][ETH_ALEN];
 };
 
 #define MWL8K_ENABLE_RX_MULTICAST 0x000F
+
 static int mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw,
 					int mc_count,
 					struct dev_addr_list *mclist)
@@ -1649,7 +1645,8 @@ static int mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw,
 	struct mwl8k_cmd_mac_multicast_adr *cmd;
 	int index = 0;
 	int rc;
-	int size = sizeof(*cmd) + ((mc_count - 1) * ETH_ALEN);
+	int size = sizeof(*cmd) + mc_count * ETH_ALEN;
+
 	cmd = kzalloc(size, GFP_KERNEL);
 	if (cmd == NULL)
 		return -ENOMEM;
@@ -1658,13 +1655,13 @@ static int mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw,
 	cmd->header.length = cpu_to_le16(size);
 	cmd->action = cpu_to_le16(MWL8K_ENABLE_RX_MULTICAST);
 	cmd->numaddr = cpu_to_le16(mc_count);
-	while ((index < mc_count) && mclist) {
+
+	while (index < mc_count && mclist) {
 		if (mclist->da_addrlen != ETH_ALEN) {
 			rc = -EINVAL;
 			goto mwl8k_cmd_mac_multicast_adr_exit;
 		}
-		memcpy(cmd->addr[index], mclist->da_addr, ETH_ALEN);
-		index++;
+		memcpy(cmd->addr[index++], mclist->da_addr, ETH_ALEN);
 		mclist = mclist->next;
 	}
 
@@ -1846,7 +1843,7 @@ struct mwl8k_cmd_set_post_scan {
 } __attribute__((packed));
 
 static int
-mwl8k_cmd_set_post_scan(struct ieee80211_hw *hw, __u8 mac[ETH_ALEN])
+mwl8k_cmd_set_post_scan(struct ieee80211_hw *hw, __u8 *mac)
 {
 	struct mwl8k_cmd_set_post_scan *cmd;
 	int rc;
@@ -1980,7 +1977,7 @@ static int mwl8k_enable_sniffer(struct ieee80211_hw *hw, bool enable)
 
 	cmd->header.code = cpu_to_le16(MWL8K_CMD_ENABLE_SNIFFER);
 	cmd->header.length = cpu_to_le16(sizeof(*cmd));
-	cmd->action = enable ? cpu_to_le32((u32)MWL8K_CMD_SET) : 0;
+	cmd->action = cpu_to_le32(!!enable);
 
 	rc = mwl8k_post_cmd(hw, &cmd->header);
 	kfree(cmd);
@@ -1989,7 +1986,7 @@ static int mwl8k_enable_sniffer(struct ieee80211_hw *hw, bool enable)
 }
 
 /*
- * CMD_SET_RATE_ADAPT_MODE.
+ * CMD_SET_RATEADAPT_MODE.
  */
 struct mwl8k_cmd_set_rate_adapt_mode {
 	struct mwl8k_cmd_pkt header;
@@ -2117,22 +2114,18 @@ mwl8k_set_edca_params(struct ieee80211_hw *hw, __u8 qnum,
 		__u8 aifs, __u16 txop)
 {
 	struct mwl8k_cmd_set_edca_params *cmd;
-	u32 log_cw_min, log_cw_max;
 	int rc;
 
 	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
 	if (cmd == NULL)
 		return -ENOMEM;
 
-	log_cw_min = ilog2(cw_min+1);
-	log_cw_max = ilog2(cw_max+1);
 	cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_EDCA_PARAMS);
 	cmd->header.length = cpu_to_le16(sizeof(*cmd));
-
 	cmd->action = cpu_to_le16(MWL8K_SET_EDCA_ALL);
 	cmd->txop = cpu_to_le16(txop);
-	cmd->log_cw_max = (u8)log_cw_max;
-	cmd->log_cw_min = (u8)log_cw_min;
+	cmd->log_cw_max = (u8)ilog2(cw_max + 1);
+	cmd->log_cw_min = (u8)ilog2(cw_min + 1);
 	cmd->aifs = aifs;
 	cmd->txq = qnum;
 
@@ -2173,11 +2166,7 @@ static int mwl8k_finalize_join(struct ieee80211_hw *hw, void *frame,
 
 	cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_FINALIZE_JOIN);
 	cmd->header.length = cpu_to_le16(sizeof(*cmd));
-
-	if (dtim)
-		cmd->sleep_interval = cpu_to_le32(dtim);
-	else
-		cmd->sleep_interval = cpu_to_le32(1);
+	cmd->sleep_interval = cpu_to_le32(dtim ? dtim : 1);
 
 	hdrlen = ieee80211_hdrlen(payload->frame_control);
 
@@ -2189,8 +2178,8 @@ static int mwl8k_finalize_join(struct ieee80211_hw *hw, void *frame,
 			"sent to firmware. Sz=%u MAX=%u\n", __func__,
 			payload_len, MWL8K_FJ_BEACON_MAXLEN);
 
-	payload_len = payload_len > MWL8K_FJ_BEACON_MAXLEN ?
-				MWL8K_FJ_BEACON_MAXLEN : payload_len;
+	if (payload_len > MWL8K_FJ_BEACON_MAXLEN)
+		payload_len = MWL8K_FJ_BEACON_MAXLEN;
 
 	if (payload && payload_len)
 		memcpy(cmd->beacon_data, &payload->u.beacon, payload_len);
@@ -2250,7 +2239,7 @@ static int mwl8k_cmd_update_sta_db(struct ieee80211_hw *hw,
 		peer_info->amsdu_enabled = 0;
 
 		rates = peer_info->legacy_rates;
-		for (count = 0 ; count < mv_vif->legacy_nrates; count++)
+		for (count = 0; count < mv_vif->legacy_nrates; count++)
 			rates[count] = bitrates[count].hw_value;
 
 		rc = mwl8k_post_cmd(hw, &cmd->header);
@@ -2313,8 +2302,6 @@ static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw,
 
 	memcpy(cmd->bssid, mv_vif->bssid, ETH_ALEN);
 
-	prot_mode = MWL8K_FRAME_PROT_DISABLED;
-
 	if (info->use_cts_prot) {
 		prot_mode = MWL8K_FRAME_PROT_11G;
 	} else {
@@ -2331,7 +2318,6 @@ static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw,
 			break;
 		}
 	}
-
 	cmd->protection_mode = cpu_to_le16(prot_mode);
 
 	for (count = 0; count < mv_vif->legacy_nrates; count++)
@@ -2934,7 +2920,7 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw,
 	mwl8k_vif->priv = priv;
 
 	/* Setup initial PHY parameters */
-	memcpy(mwl8k_vif->legacy_rates ,
+	memcpy(mwl8k_vif->legacy_rates,
 		priv->rates, sizeof(mwl8k_vif->legacy_rates));
 	mwl8k_vif->legacy_nrates = ARRAY_SIZE(priv->rates);
 
@@ -3178,8 +3164,9 @@ static int mwl8k_configure_filter_wt(struct work_struct *wt)
 	if (rc)
 		goto mwl8k_configure_filter_exit;
 	if (mc_count) {
-		mc_count = mc_count < priv->num_mcaddrs ?
-				mc_count : priv->num_mcaddrs;
+		if (mc_count > priv->num_mcaddrs)
+			mc_count = priv->num_mcaddrs;
+
 		rc = mwl8k_cmd_mac_multicast_adr(hw, mc_count, mclist);
 		if (rc)
 			printk(KERN_ERR
@@ -3398,12 +3385,9 @@ static void mwl8k_tx_reclaim_handler(unsigned long data)
 	for (i = 0; i < MWL8K_TX_QUEUES; i++)
 		mwl8k_txq_reclaim(hw, i, 0);
 
-	if (priv->tx_wait != NULL) {
-		int count = mwl8k_txq_busy(priv);
-		if (count == 0) {
-			complete(priv->tx_wait);
-			priv->tx_wait = NULL;
-		}
+	if (priv->tx_wait != NULL && mwl8k_txq_busy(priv) == 0) {
+		complete(priv->tx_wait);
+		priv->tx_wait = NULL;
 	}
 	spin_unlock_bh(&priv->tx_lock);
 }
@@ -3413,7 +3397,7 @@ static void mwl8k_finalize_join_worker(struct work_struct *work)
 	struct mwl8k_priv *priv =
 		container_of(work, struct mwl8k_priv, finalize_join_worker);
 	struct sk_buff *skb = priv->beacon_skb;
-	u8 dtim = (MWL8K_VIF(priv->vif))->bss_info.dtim_period;
+	u8 dtim = MWL8K_VIF(priv->vif)->bss_info.dtim_period;
 
 	mwl8k_finalize_join(priv->hw, skb->data, skb->len, dtim);
 	dev_kfree_skb(skb);
@@ -3500,7 +3484,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
 		BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_MONITOR);
 
 	/* Set rssi and noise values to dBm */
-	hw->flags |= (IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM);
+	hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM;
 	hw->vif_data_size = sizeof(struct mwl8k_vif);
 	priv->vif = NULL;
 
-- 
1.5.6.4

^ permalink raw reply related

* [PATCH 05/29] mwl8k: remove MWL8K_RADIO_* defines
From: Lennert Buytenhek @ 2009-08-18  3:51 UTC (permalink / raw)
  To: linville, linux-wireless

Instead of passing a flag bitmask to mwl8k_cmd_802_11_radio_control,
pass the 'enable' and 'force' arguments as separate parameters, and
introduce wrappers for the common cases of enabling and disabling
without forcing.

Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
---
 drivers/net/wireless/mwl8k.c |   52 +++++++++++++++++++++--------------------
 1 files changed, 27 insertions(+), 25 deletions(-)

diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index a3b0e19..f57d28c 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -186,9 +186,10 @@ struct mwl8k_priv {
 	struct ieee80211_channel channels[14];
 	struct ieee80211_rate rates[12];
 
+	bool radio_on;
+
 	/* RF preamble: Short, Long or Auto */
 	u8	radio_preamble;
-	u8	radio_state;
 
 	/* WMM MODE 1 for enabled; 0 for disabled */
 	bool wmm_mode;
@@ -278,9 +279,6 @@ static const struct ieee80211_rate mwl8k_rates[] = {
 };
 
 /* Radio settings */
-#define MWL8K_RADIO_FORCE		0x2
-#define MWL8K_RADIO_ENABLE		0x1
-#define MWL8K_RADIO_DISABLE		0x0
 #define MWL8K_RADIO_AUTO_PREAMBLE	0x0005
 #define MWL8K_RADIO_SHORT_PREAMBLE	0x0003
 #define MWL8K_RADIO_LONG_PREAMBLE	0x0001
@@ -1195,7 +1193,7 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw, u32 delay_ms)
 	count = mwl8k_txq_busy(priv);
 	if (count) {
 		priv->tx_wait = &cmd_wait;
-		if (priv->radio_state)
+		if (priv->radio_on)
 			mwl8k_tx_start(priv);
 	}
 	spin_unlock_bh(&priv->tx_lock);
@@ -1318,7 +1316,7 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force)
 
 		ieee80211_tx_status_irqsafe(hw, skb);
 
-		wake = !priv->inconfig && priv->radio_state;
+		wake = !priv->inconfig && priv->radio_on;
 	}
 
 	if (wake)
@@ -1726,18 +1724,16 @@ struct mwl8k_cmd_802_11_radio_control {
 	__le16 radio_on;
 } __attribute__((packed));
 
-static int mwl8k_cmd_802_11_radio_control(struct ieee80211_hw *hw, int enable)
+static int
+mwl8k_cmd_802_11_radio_control(struct ieee80211_hw *hw, bool enable, bool force)
 {
 	struct mwl8k_priv *priv = hw->priv;
 	struct mwl8k_cmd_802_11_radio_control *cmd;
 	int rc;
 
-	if (((enable & MWL8K_RADIO_ENABLE) == priv->radio_state) &&
-	    !(enable & MWL8K_RADIO_FORCE))
+	if (enable == priv->radio_on && !force)
 		return 0;
 
-	enable &= MWL8K_RADIO_ENABLE;
-
 	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
 	if (cmd == NULL)
 		return -ENOMEM;
@@ -1752,11 +1748,21 @@ static int mwl8k_cmd_802_11_radio_control(struct ieee80211_hw *hw, int enable)
 	kfree(cmd);
 
 	if (!rc)
-		priv->radio_state = enable;
+		priv->radio_on = enable;
 
 	return rc;
 }
 
+static int mwl8k_cmd_802_11_radio_disable(struct ieee80211_hw *hw)
+{
+	return mwl8k_cmd_802_11_radio_control(hw, 0, 0);
+}
+
+static int mwl8k_cmd_802_11_radio_enable(struct ieee80211_hw *hw)
+{
+	return mwl8k_cmd_802_11_radio_control(hw, 1, 0);
+}
+
 static int
 mwl8k_set_radio_preamble(struct ieee80211_hw *hw, bool short_preamble)
 {
@@ -1770,8 +1776,7 @@ mwl8k_set_radio_preamble(struct ieee80211_hw *hw, bool short_preamble)
 		MWL8K_RADIO_SHORT_PREAMBLE :
 		MWL8K_RADIO_LONG_PREAMBLE);
 
-	return mwl8k_cmd_802_11_radio_control(hw,
-			MWL8K_RADIO_ENABLE | MWL8K_RADIO_FORCE);
+	return mwl8k_cmd_802_11_radio_control(hw, 1, 1);
 }
 
 /*
@@ -2483,7 +2488,7 @@ static irqreturn_t mwl8k_interrupt(int irq, void *dev_id)
 
 	if (status & MWL8K_A2H_INT_QUEUE_EMPTY) {
 		if (!priv->inconfig &&
-			priv->radio_state &&
+			priv->radio_on &&
 			mwl8k_txq_busy(priv))
 				mwl8k_tx_start(priv);
 	}
@@ -2661,7 +2666,7 @@ static void mwl8k_config_thread(struct work_struct *wt)
 
 	spin_lock_irq(&priv->tx_lock);
 	priv->inconfig = false;
-	if (priv->pending_tx_pkts && priv->radio_state)
+	if (priv->pending_tx_pkts && priv->radio_on)
 		mwl8k_tx_start(priv);
 	spin_unlock_irq(&priv->tx_lock);
 	ieee80211_wake_queues(hw);
@@ -2745,7 +2750,7 @@ static int mwl8k_start_wt(struct work_struct *wt)
 	}
 
 	/* Turn on radio */
-	if (mwl8k_cmd_802_11_radio_control(hw, MWL8K_RADIO_ENABLE)) {
+	if (mwl8k_cmd_802_11_radio_enable(hw)) {
 		rc = -EIO;
 		goto mwl8k_start_exit;
 	}
@@ -2839,11 +2844,8 @@ static int mwl8k_stop_wt(struct work_struct *wt)
 {
 	struct mwl8k_stop_worker *worker = (struct mwl8k_stop_worker *)wt;
 	struct ieee80211_hw *hw = worker->header.hw;
-	int rc;
-
-	rc = mwl8k_cmd_802_11_radio_control(hw, MWL8K_RADIO_DISABLE);
 
-	return rc;
+	return mwl8k_cmd_802_11_radio_disable(hw);
 }
 
 static void mwl8k_stop(struct ieee80211_hw *hw)
@@ -2959,13 +2961,13 @@ static int mwl8k_config_wt(struct work_struct *wt)
 	int rc = 0;
 
 	if (!conf->radio_enabled) {
-		mwl8k_cmd_802_11_radio_control(hw, MWL8K_RADIO_DISABLE);
+		mwl8k_cmd_802_11_radio_disable(hw);
 		priv->current_channel = NULL;
 		rc = 0;
 		goto mwl8k_config_exit;
 	}
 
-	if (mwl8k_cmd_802_11_radio_control(hw, MWL8K_RADIO_ENABLE)) {
+	if (mwl8k_cmd_802_11_radio_enable(hw)) {
 		rc = -EINVAL;
 		goto mwl8k_config_exit;
 	}
@@ -3490,7 +3492,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
 
 	/* Set default radio state and preamble */
 	priv->radio_preamble = MWL8K_RADIO_DEFAULT_PREAMBLE;
-	priv->radio_state = MWL8K_RADIO_DISABLE;
+	priv->radio_on = 0;
 
 	/* Finalize join worker */
 	INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker);
@@ -3571,7 +3573,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
 	}
 
 	/* Turn radio off */
-	rc = mwl8k_cmd_802_11_radio_control(hw, MWL8K_RADIO_DISABLE);
+	rc = mwl8k_cmd_802_11_radio_disable(hw);
 	if (rc) {
 		printk(KERN_ERR "%s: Cannot disable\n", priv->name);
 		goto err_stop_firmware;
-- 
1.5.6.4

^ permalink raw reply related

* [PATCH 06/29] mwl8k: remove MWL8K_RADIO_*_PREAMBLE defines
From: Lennert Buytenhek @ 2009-08-18  3:51 UTC (permalink / raw)
  To: linville, linux-wireless

Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
---
 drivers/net/wireless/mwl8k.c |   22 +++++-----------------
 1 files changed, 5 insertions(+), 17 deletions(-)

diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index f57d28c..92b2fce 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -187,9 +187,7 @@ struct mwl8k_priv {
 	struct ieee80211_rate rates[12];
 
 	bool radio_on;
-
-	/* RF preamble: Short, Long or Auto */
-	u8	radio_preamble;
+	bool radio_short_preamble;
 
 	/* WMM MODE 1 for enabled; 0 for disabled */
 	bool wmm_mode;
@@ -278,17 +276,10 @@ static const struct ieee80211_rate mwl8k_rates[] = {
 	{ .bitrate = 540, .hw_value = 108, },
 };
 
-/* Radio settings */
-#define MWL8K_RADIO_AUTO_PREAMBLE	0x0005
-#define MWL8K_RADIO_SHORT_PREAMBLE	0x0003
-#define MWL8K_RADIO_LONG_PREAMBLE	0x0001
-
 /* WMM */
 #define MWL8K_WMM_ENABLE		1
 #define MWL8K_WMM_DISABLE		0
 
-#define MWL8K_RADIO_DEFAULT_PREAMBLE	MWL8K_RADIO_LONG_PREAMBLE
-
 /* Slot time */
 
 /* Short Slot: 9us slot time */
@@ -1741,7 +1732,7 @@ mwl8k_cmd_802_11_radio_control(struct ieee80211_hw *hw, bool enable, bool force)
 	cmd->header.code = cpu_to_le16(MWL8K_CMD_RADIO_CONTROL);
 	cmd->header.length = cpu_to_le16(sizeof(*cmd));
 	cmd->action = cpu_to_le16(MWL8K_CMD_SET);
-	cmd->control = cpu_to_le16(priv->radio_preamble);
+	cmd->control = cpu_to_le16(priv->radio_short_preamble ? 3 : 1);
 	cmd->radio_on = cpu_to_le16(enable ? 0x0001 : 0x0000);
 
 	rc = mwl8k_post_cmd(hw, &cmd->header);
@@ -1772,9 +1763,7 @@ mwl8k_set_radio_preamble(struct ieee80211_hw *hw, bool short_preamble)
 		return -EINVAL;
 	priv = hw->priv;
 
-	priv->radio_preamble = (short_preamble ?
-		MWL8K_RADIO_SHORT_PREAMBLE :
-		MWL8K_RADIO_LONG_PREAMBLE);
+	priv->radio_short_preamble = short_preamble;
 
 	return mwl8k_cmd_802_11_radio_control(hw, 1, 1);
 }
@@ -3058,8 +3047,7 @@ static int mwl8k_bss_info_changed_wt(struct work_struct *wt)
 			goto mwl8k_bss_info_changed_exit;
 
 		/* Set radio preamble */
-		if (mwl8k_set_radio_preamble(hw,
-				info->use_short_preamble))
+		if (mwl8k_set_radio_preamble(hw, info->use_short_preamble))
 			goto mwl8k_bss_info_changed_exit;
 
 		/* Set slot time */
@@ -3491,8 +3479,8 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
 	priv->vif = NULL;
 
 	/* Set default radio state and preamble */
-	priv->radio_preamble = MWL8K_RADIO_DEFAULT_PREAMBLE;
 	priv->radio_on = 0;
+	priv->radio_short_preamble = 0;
 
 	/* Finalize join worker */
 	INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker);
-- 
1.5.6.4

^ permalink raw reply related

* [PATCH 07/29] mwl8k: remove MWL8K_WMM_* defines
From: Lennert Buytenhek @ 2009-08-18  3:52 UTC (permalink / raw)
  To: linville, linux-wireless

Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
---
 drivers/net/wireless/mwl8k.c |   21 ++++++++-------------
 1 files changed, 8 insertions(+), 13 deletions(-)

diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 92b2fce..c9bb9b1 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -188,9 +188,7 @@ struct mwl8k_priv {
 
 	bool radio_on;
 	bool radio_short_preamble;
-
-	/* WMM MODE 1 for enabled; 0 for disabled */
-	bool wmm_mode;
+	bool wmm_enabled;
 
 	/* Set if PHY config is in progress */
 	bool inconfig;
@@ -276,10 +274,6 @@ static const struct ieee80211_rate mwl8k_rates[] = {
 	{ .bitrate = 540, .hw_value = 108, },
 };
 
-/* WMM */
-#define MWL8K_WMM_ENABLE		1
-#define MWL8K_WMM_DISABLE		0
-
 /* Slot time */
 
 /* Short Slot: 9us slot time */
@@ -2028,13 +2022,13 @@ static int mwl8k_set_wmm(struct ieee80211_hw *hw, bool enable)
 
 	cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_WMM_MODE);
 	cmd->header.length = cpu_to_le16(sizeof(*cmd));
-	cmd->action = enable ? cpu_to_le16(MWL8K_CMD_SET) : 0;
+	cmd->action = cpu_to_le16(!!enable);
 
 	rc = mwl8k_post_cmd(hw, &cmd->header);
 	kfree(cmd);
 
 	if (!rc)
-		priv->wmm_mode = enable;
+		priv->wmm_enabled = enable;
 
 	return rc;
 }
@@ -2762,7 +2756,7 @@ static int mwl8k_start_wt(struct work_struct *wt)
 	}
 
 	/* Disable WMM. WMM gets enabled when stack sends WMM parms */
-	if (mwl8k_set_wmm(hw, MWL8K_WMM_DISABLE)) {
+	if (mwl8k_set_wmm(hw, 0)) {
 		rc = -EIO;
 		goto mwl8k_start_exit;
 	}
@@ -3260,10 +3254,11 @@ static int mwl8k_conf_tx_wt(struct work_struct *wt)
 	struct mwl8k_priv *priv = hw->priv;
 	int rc = 0;
 
-	if (priv->wmm_mode == MWL8K_WMM_DISABLE)
-		if (mwl8k_set_wmm(hw, MWL8K_WMM_ENABLE)) {
+	if (!priv->wmm_enabled) {
+		if (mwl8k_set_wmm(hw, 1)) {
 			rc = -EINVAL;
 			goto mwl8k_conf_tx_exit;
+		}
 	}
 
 	if (mwl8k_set_edca_params(hw, GET_TXQ(queue), params->cw_min,
@@ -3433,7 +3428,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
 	priv->hostcmd_wait = NULL;
 	priv->tx_wait = NULL;
 	priv->inconfig = false;
-	priv->wmm_mode = false;
+	priv->wmm_enabled = false;
 	priv->pending_tx_pkts = 0;
 	strncpy(priv->name, MWL8K_NAME, sizeof(priv->name));
 
-- 
1.5.6.4

^ permalink raw reply related

* [PATCH 08/29] mwl8k: remove MWL8K_*_SLOTTIME defines
From: Lennert Buytenhek @ 2009-08-18  3:52 UTC (permalink / raw)
  To: linville, linux-wireless

Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
---
 drivers/net/wireless/mwl8k.c |   15 +++------------
 1 files changed, 3 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index c9bb9b1..9f54204 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -274,14 +274,6 @@ static const struct ieee80211_rate mwl8k_rates[] = {
 	{ .bitrate = 540, .hw_value = 108, },
 };
 
-/* Slot time */
-
-/* Short Slot: 9us slot time */
-#define MWL8K_SHORT_SLOTTIME		1
-
-/* Long slot: 20us slot time */
-#define MWL8K_LONG_SLOTTIME		0
-
 /* Set or get info from Firmware */
 #define MWL8K_CMD_SET			0x0001
 #define MWL8K_CMD_GET			0x0000
@@ -1895,7 +1887,7 @@ struct mwl8k_cmd_set_slot {
 	__u8 short_slot;
 } __attribute__((packed));
 
-static int mwl8k_cmd_set_slot(struct ieee80211_hw *hw, int slot_time)
+static int mwl8k_cmd_set_slot(struct ieee80211_hw *hw, bool short_slot_time)
 {
 	struct mwl8k_cmd_set_slot *cmd;
 	int rc;
@@ -1907,7 +1899,7 @@ static int mwl8k_cmd_set_slot(struct ieee80211_hw *hw, int slot_time)
 	cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_SLOT);
 	cmd->header.length = cpu_to_le16(sizeof(*cmd));
 	cmd->action = cpu_to_le16(MWL8K_CMD_SET);
-	cmd->short_slot = slot_time == MWL8K_SHORT_SLOTTIME ? 1 : 0;
+	cmd->short_slot = short_slot_time;
 
 	rc = mwl8k_post_cmd(hw, &cmd->header);
 	kfree(cmd);
@@ -3045,8 +3037,7 @@ static int mwl8k_bss_info_changed_wt(struct work_struct *wt)
 			goto mwl8k_bss_info_changed_exit;
 
 		/* Set slot time */
-		if (mwl8k_cmd_set_slot(hw, info->use_short_slot ?
-				MWL8K_SHORT_SLOTTIME : MWL8K_LONG_SLOTTIME))
+		if (mwl8k_cmd_set_slot(hw, info->use_short_slot))
 			goto mwl8k_bss_info_changed_exit;
 
 		/* Update peer rate info */
-- 
1.5.6.4

^ permalink raw reply related

* [PATCH 09/29] mwl8k: remove usage of deprecated radio_enabled
From: Lennert Buytenhek @ 2009-08-18  3:52 UTC (permalink / raw)
  To: linville, linux-wireless

Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
---
 drivers/net/wireless/mwl8k.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 9f54204..3a201a2 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -2935,7 +2935,7 @@ static int mwl8k_config_wt(struct work_struct *wt)
 	struct mwl8k_priv *priv = hw->priv;
 	int rc = 0;
 
-	if (!conf->radio_enabled) {
+	if (conf->flags & IEEE80211_CONF_IDLE) {
 		mwl8k_cmd_802_11_radio_disable(hw);
 		priv->current_channel = NULL;
 		rc = 0;
-- 
1.5.6.4

^ permalink raw reply related

* [PATCH 10/29] mwl8k: fix mwl8k_configure_filter() parameter lifetime issue
From: Lennert Buytenhek @ 2009-08-18  3:52 UTC (permalink / raw)
  To: linville, linux-wireless

mwl8k_configure_filter() passes pointers to total_flags and the
multicast address list to a workqueue function, while there is no
guarantee that those pointers will still be valid by the time the
workqueue function runs.

Solve this by passing total_flags by value, and by passing an
already built multicast address setup command packet to the workqueue
function so that we don't have to look at the multicast address list
itself outside of mwl8k_configure_filter().

Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
---
 drivers/net/wireless/mwl8k.c |   72 +++++++++++++++++------------------------
 1 files changed, 30 insertions(+), 42 deletions(-)

diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 3a201a2..e266bc1 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -1613,38 +1613,39 @@ struct mwl8k_cmd_mac_multicast_adr {
 
 #define MWL8K_ENABLE_RX_MULTICAST 0x000F
 
-static int mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw,
-					int mc_count,
-					struct dev_addr_list *mclist)
+static struct mwl8k_cmd_pkt *
+__mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw,
+			      int mc_count, struct dev_addr_list *mclist)
 {
+	struct mwl8k_priv *priv = hw->priv;
 	struct mwl8k_cmd_mac_multicast_adr *cmd;
-	int index = 0;
-	int rc;
-	int size = sizeof(*cmd) + mc_count * ETH_ALEN;
+	int size;
+	int i;
+
+	if (mc_count > priv->num_mcaddrs)
+		mc_count = priv->num_mcaddrs;
 
-	cmd = kzalloc(size, GFP_KERNEL);
+	size = sizeof(*cmd) + mc_count * ETH_ALEN;
+
+	cmd = kzalloc(size, GFP_ATOMIC);
 	if (cmd == NULL)
-		return -ENOMEM;
+		return NULL;
 
 	cmd->header.code = cpu_to_le16(MWL8K_CMD_MAC_MULTICAST_ADR);
 	cmd->header.length = cpu_to_le16(size);
 	cmd->action = cpu_to_le16(MWL8K_ENABLE_RX_MULTICAST);
 	cmd->numaddr = cpu_to_le16(mc_count);
 
-	while (index < mc_count && mclist) {
+	for (i = 0; i < mc_count && mclist; i++) {
 		if (mclist->da_addrlen != ETH_ALEN) {
-			rc = -EINVAL;
-			goto mwl8k_cmd_mac_multicast_adr_exit;
+			kfree(cmd);
+			return NULL;
 		}
-		memcpy(cmd->addr[index++], mclist->da_addr, ETH_ALEN);
+		memcpy(cmd->addr[i], mclist->da_addr, ETH_ALEN);
 		mclist = mclist->next;
 	}
 
-	rc = mwl8k_post_cmd(hw, &cmd->header);
-
-mwl8k_cmd_mac_multicast_adr_exit:
-	kfree(cmd);
-	return rc;
+	return &cmd->header;
 }
 
 /*
@@ -3101,9 +3102,8 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw,
 struct mwl8k_configure_filter_worker {
 	struct mwl8k_work_struct header;
 	unsigned int changed_flags;
-	unsigned int *total_flags;
-	int mc_count;
-	struct dev_addr_list *mclist;
+	unsigned int total_flags;
+	struct mwl8k_cmd_pkt *set_multicast_adr;
 };
 
 #define MWL8K_SUPPORTED_IF_FLAGS	FIF_BCN_PRBRESP_PROMISC
@@ -3112,18 +3112,14 @@ static int mwl8k_configure_filter_wt(struct work_struct *wt)
 {
 	struct mwl8k_configure_filter_worker *worker =
 		(struct mwl8k_configure_filter_worker *)wt;
-
 	struct ieee80211_hw *hw = worker->header.hw;
 	unsigned int changed_flags = worker->changed_flags;
-	unsigned int *total_flags = worker->total_flags;
-	int mc_count = worker->mc_count;
-	struct dev_addr_list *mclist = worker->mclist;
-
+	unsigned int total_flags = worker->total_flags;
 	struct mwl8k_priv *priv = hw->priv;
 	int rc = 0;
 
 	if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
-		if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
+		if (total_flags & FIF_BCN_PRBRESP_PROMISC)
 			rc = mwl8k_cmd_set_pre_scan(hw);
 		else {
 			u8 *bssid;
@@ -3136,20 +3132,12 @@ static int mwl8k_configure_filter_wt(struct work_struct *wt)
 		}
 	}
 
-	if (rc)
-		goto mwl8k_configure_filter_exit;
-	if (mc_count) {
-		if (mc_count > priv->num_mcaddrs)
-			mc_count = priv->num_mcaddrs;
-
-		rc = mwl8k_cmd_mac_multicast_adr(hw, mc_count, mclist);
-		if (rc)
-			printk(KERN_ERR
-			"%s()Error setting multicast addresses\n",
-			__func__);
+	if (worker->set_multicast_adr != NULL) {
+		if (!rc)
+			rc = mwl8k_post_cmd(hw, worker->set_multicast_adr);
+		kfree(worker->set_multicast_adr);
 	}
 
-mwl8k_configure_filter_exit:
 	return rc;
 }
 
@@ -3159,7 +3147,6 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw,
 				   int mc_count,
 				   struct dev_addr_list *mclist)
 {
-
 	struct mwl8k_configure_filter_worker *worker;
 	struct mwl8k_priv *priv = hw->priv;
 
@@ -3175,9 +3162,10 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw,
 
 	worker->header.options = MWL8K_WQ_QUEUE_ONLY | MWL8K_WQ_TX_WAIT_EMPTY;
 	worker->changed_flags = changed_flags;
-	worker->total_flags = total_flags;
-	worker->mc_count = mc_count;
-	worker->mclist = mclist;
+	worker->total_flags = *total_flags;
+	if (mc_count)
+		worker->set_multicast_adr =
+			__mwl8k_cmd_mac_multicast_adr(hw, mc_count, mclist);
 
 	mwl8k_queue_work(hw, &worker->header, priv->config_wq,
 			 mwl8k_configure_filter_wt);
-- 
1.5.6.4

^ permalink raw reply related

* [PATCH 11/29] mwl8k: ->add_interface() is not called for monitor interfaces
From: Lennert Buytenhek @ 2009-08-18  3:52 UTC (permalink / raw)
  To: linville, linux-wireless

There is no need to check for NL80211_IFTYPE_MONITOR in
->add_interface(), as this function is never called for monitor
interfaces.  Also, there is no need to advertise this bit in our
wiphy's ->interface_modes.

Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
---
 drivers/net/wireless/mwl8k.c |    6 ++----
 1 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index e266bc1..4580b1d 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -2883,8 +2883,7 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw,
 	/*
 	 * We only support managed interfaces for now.
 	 */
-	if (conf->type != NL80211_IFTYPE_STATION &&
-	    conf->type != NL80211_IFTYPE_MONITOR)
+	if (conf->type != NL80211_IFTYPE_STATION)
 		return -EINVAL;
 
 	/* Clean out driver private area */
@@ -3444,8 +3443,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
 
 	hw->queues = MWL8K_TX_QUEUES;
 
-	hw->wiphy->interface_modes =
-		BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_MONITOR);
+	hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
 
 	/* Set rssi and noise values to dBm */
 	hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM;
-- 
1.5.6.4

^ permalink raw reply related

* [PATCH 12/29] mwl8k: dma header manipulations can't fail
From: Lennert Buytenhek @ 2009-08-18  3:52 UTC (permalink / raw)
  To: linville, linux-wireless

Adding and removing the DMA header that the mwl8k hardware requires
on tx and provides on rx can never fail, since we are guaranteed to
have enough headroom on the tx path to expand the packet, and we only
ever shrink the packet on the rx path.  (And on both paths we are
guaranteed to be the only user of the skb we are handling.)

This allows removing all of the skb clone handling in the tx and tx
reclaim paths, and eliminates error checks in both the tx and rx
paths, simplifying the code a bit more.

Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
---
 drivers/net/wireless/mwl8k.c |   83 +++++++-----------------------------------
 1 files changed, 13 insertions(+), 70 deletions(-)

diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 4580b1d..f4b197b 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -111,17 +111,6 @@ struct mwl8k_rx_queue {
 	struct sk_buff **rx_skb;
 };
 
-struct mwl8k_skb {
-	/*
-	 * The DMA engine requires a modification to the payload.
-	 * If the skbuff is shared/cloned, it needs to be unshared.
-	 * This method is used to ensure the stack always gets back
-	 * the skbuff it sent for transmission.
-	 */
-	struct sk_buff *clone;
-	struct sk_buff *skb;
-};
-
 struct mwl8k_tx_queue {
 	/* hw transmits here */
 	int tx_head;
@@ -132,7 +121,7 @@ struct mwl8k_tx_queue {
 	struct ieee80211_tx_queue_stats tx_stats;
 	struct mwl8k_tx_desc *tx_desc_area;
 	dma_addr_t tx_desc_dma;
-	struct mwl8k_skb *tx_skb;
+	struct sk_buff **tx_skb;
 };
 
 /* Pointers to the firmware data and meta information about it.  */
@@ -714,12 +703,11 @@ struct mwl8k_dma_data {
 } __attribute__((packed));
 
 /* Routines to add/remove DMA header from skb.  */
-static inline int mwl8k_remove_dma_header(struct sk_buff *skb)
+static inline void mwl8k_remove_dma_header(struct sk_buff *skb)
 {
-	struct mwl8k_dma_data *tr = (struct mwl8k_dma_data *)(skb->data);
+	struct mwl8k_dma_data *tr = (struct mwl8k_dma_data *)skb->data;
 	void *dst, *src = &tr->wh;
-	__le16 fc = tr->wh.frame_control;
-	int hdrlen = ieee80211_hdrlen(fc);
+	int hdrlen = ieee80211_hdrlen(tr->wh.frame_control);
 	u16 space = sizeof(struct mwl8k_dma_data) - hdrlen;
 
 	dst = (void *)tr + space;
@@ -727,11 +715,9 @@ static inline int mwl8k_remove_dma_header(struct sk_buff *skb)
 		memmove(dst, src, hdrlen);
 		skb_pull(skb, space);
 	}
-
-	return 0;
 }
 
-static inline struct sk_buff *mwl8k_add_dma_header(struct sk_buff *skb)
+static inline void mwl8k_add_dma_header(struct sk_buff *skb)
 {
 	struct ieee80211_hdr *wh;
 	u32 hdrlen, pktlen;
@@ -763,8 +749,6 @@ static inline struct sk_buff *mwl8k_add_dma_header(struct sk_buff *skb)
 	 * This includes all crypto material including the MIC.
 	 */
 	tr->fwlen = cpu_to_le16(pktlen - hdrlen);
-
-	return skb;
 }
 
 
@@ -967,10 +951,7 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit)
 					MWL8K_RX_MAXSZ, PCI_DMA_FROMDEVICE);
 
 		skb_put(skb, le16_to_cpu(rx_desc->pkt_len));
-		if (mwl8k_remove_dma_header(skb)) {
-			dev_kfree_skb(skb);
-			continue;
-		}
+		mwl8k_remove_dma_header(skb);
 
 		wh = (struct ieee80211_hdr *)skb->data;
 
@@ -1224,7 +1205,6 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force)
 
 	while (txq->tx_stats.len > 0) {
 		int tx;
-		int rc;
 		struct mwl8k_tx_desc *tx_desc;
 		unsigned long addr;
 		int size;
@@ -1232,7 +1212,6 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force)
 		struct ieee80211_tx_info *info;
 		u32 status;
 
-		rc = 0;
 		tx = txq->tx_head;
 		tx_desc = txq->tx_desc_area + tx;
 
@@ -1252,40 +1231,18 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force)
 
 		addr = le32_to_cpu(tx_desc->pkt_phys_addr);
 		size = le16_to_cpu(tx_desc->pkt_len);
-		skb = txq->tx_skb[tx].skb;
-		txq->tx_skb[tx].skb = NULL;
+		skb = txq->tx_skb[tx];
+		txq->tx_skb[tx] = NULL;
 
 		BUG_ON(skb == NULL);
 		pci_unmap_single(priv->pdev, addr, size, PCI_DMA_TODEVICE);
 
-		rc = mwl8k_remove_dma_header(skb);
+		mwl8k_remove_dma_header(skb);
 
 		/* Mark descriptor as unused */
 		tx_desc->pkt_phys_addr = 0;
 		tx_desc->pkt_len = 0;
 
-		if (txq->tx_skb[tx].clone) {
-			/* Replace with original skb
-			 * before returning to stack
-			 * as buffer has been cloned
-			 */
-			dev_kfree_skb(skb);
-			skb = txq->tx_skb[tx].clone;
-			txq->tx_skb[tx].clone = NULL;
-		}
-
-		if (rc) {
-			/* Something has gone wrong here.
-			 * Failed to remove DMA header.
-			 * Print error message and drop packet.
-			 */
-			printk(KERN_ERR "%s: Error removing DMA header from "
-					"tx skb 0x%p.\n", priv->name, skb);
-
-			dev_kfree_skb(skb);
-			continue;
-		}
-
 		info = IEEE80211_SKB_CB(skb);
 		ieee80211_tx_info_clear_status(info);
 		if (MWL8K_TXD_SUCCESS(status))
@@ -1327,7 +1284,6 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
 	struct mwl8k_tx_desc *tx;
 	struct mwl8k_dma_data *tr;
 	struct mwl8k_vif *mwl8k_vif;
-	struct sk_buff *org_skb = skb;
 	dma_addr_t dma;
 	u16 qos = 0;
 	bool qosframe = false, ampduframe = false;
@@ -1338,21 +1294,12 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
 	txq = priv->txq + index;
 	tx = txq->tx_desc_area + txq->tx_tail;
 
-	BUG_ON(txq->tx_skb[txq->tx_tail].skb != NULL);
+	BUG_ON(txq->tx_skb[txq->tx_tail] != NULL);
 
 	/*
-	 * Append HW DMA header to start of packet.  Drop packet if
-	 * there is not enough space or a failure to unshare/unclone
-	 * the skb.
+	 * Append HW DMA header to start of packet.
 	 */
-	skb = mwl8k_add_dma_header(skb);
-
-	if (skb == NULL) {
-		printk(KERN_DEBUG "%s: failed to prepend HW DMA "
-			"header, dropping TX frame.\n", priv->name);
-		dev_kfree_skb(org_skb);
-		return NETDEV_TX_OK;
-	}
+	mwl8k_add_dma_header(skb);
 
 	tx_info = IEEE80211_SKB_CB(skb);
 	mwl8k_vif = MWL8K_VIF(tx_info->control.vif);
@@ -1380,8 +1327,6 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
 		printk(KERN_DEBUG "%s: failed to dma map skb, "
 			"dropping TX frame.\n", priv->name);
 
-		if (org_skb != NULL)
-			dev_kfree_skb(org_skb);
 		if (skb != NULL)
 			dev_kfree_skb(skb);
 		return NETDEV_TX_OK;
@@ -1437,9 +1382,7 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
 	tx->pkt_phys_addr = cpu_to_le32(dma);
 	tx->pkt_len = cpu_to_le16(skb->len);
 
-	txq->tx_skb[txq->tx_tail].skb = skb;
-	txq->tx_skb[txq->tx_tail].clone =
-		skb == org_skb ? NULL : org_skb;
+	txq->tx_skb[txq->tx_tail] = skb;
 
 	spin_lock_bh(&priv->tx_lock);
 
-- 
1.5.6.4

^ permalink raw reply related

* [PATCH 13/29] mwl8k: don't touch 'command done' interrupt during firmware load
From: Lennert Buytenhek @ 2009-08-18  3:53 UTC (permalink / raw)
  To: linville, linux-wireless

Since firmware load commands don't generate 'command done' interrupts
like normal commands do, polling for command done interrupts just
unnecessarily slows down the firmware load process.  Removing this bit
of code speeds up loading a typical firmware image from 840 msec to
180 msec.

Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
---
 drivers/net/wireless/mwl8k.c |   24 +-----------------------
 1 files changed, 1 insertions(+), 23 deletions(-)

diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index f4b197b..86b6b5d 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -411,7 +411,6 @@ mwl8k_send_fw_load_cmd(struct mwl8k_priv *priv, void *data, int length)
 {
 	void __iomem *regs = priv->regs;
 	dma_addr_t dma_addr;
-	int rc;
 	int loops;
 
 	dma_addr = pci_map_single(priv->pdev, data, length, PCI_DMA_TODEVICE);
@@ -425,7 +424,6 @@ mwl8k_send_fw_load_cmd(struct mwl8k_priv *priv, void *data, int length)
 	iowrite32(MWL8K_H2A_INT_DUMMY,
 		regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS);
 
-	rc = -ETIMEDOUT;
 	loops = 1000;
 	do {
 		u32 int_code;
@@ -433,7 +431,6 @@ mwl8k_send_fw_load_cmd(struct mwl8k_priv *priv, void *data, int length)
 		int_code = ioread32(regs + MWL8K_HIU_INT_CODE);
 		if (int_code == MWL8K_INT_CODE_CMD_FINISHED) {
 			iowrite32(0, regs + MWL8K_HIU_INT_CODE);
-			rc = 0;
 			break;
 		}
 
@@ -442,26 +439,7 @@ mwl8k_send_fw_load_cmd(struct mwl8k_priv *priv, void *data, int length)
 
 	pci_unmap_single(priv->pdev, dma_addr, length, PCI_DMA_TODEVICE);
 
-	/*
-	 * Clear 'command done' interrupt bit.
-	 */
-	loops = 1000;
-	do {
-		u32 status;
-
-		status = ioread32(priv->regs +
-				MWL8K_HIU_A2H_INTERRUPT_STATUS);
-		if (status & MWL8K_A2H_INT_OPC_DONE) {
-			iowrite32(~MWL8K_A2H_INT_OPC_DONE,
-				priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS);
-			ioread32(priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS);
-			break;
-		}
-
-		udelay(1);
-	} while (--loops);
-
-	return rc;
+	return loops ? 0 : -ETIMEDOUT;
 }
 
 static int mwl8k_load_fw_image(struct mwl8k_priv *priv,
-- 
1.5.6.4

^ permalink raw reply related

* [PATCH 14/29] mwl8k: don't hardcode the number of transmit queues
From: Lennert Buytenhek @ 2009-08-18  3:53 UTC (permalink / raw)
  To: linville, linux-wireless

Use MWL8K_TX_QUEUES instead of a hardcoded "4" in a couple of places.

Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
---
 drivers/net/wireless/mwl8k.c |   14 +++++++-------
 1 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 86b6b5d..f482922 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -1080,17 +1080,17 @@ struct mwl8k_txq_info {
 };
 
 static int mwl8k_scan_tx_ring(struct mwl8k_priv *priv,
-				struct mwl8k_txq_info txinfo[],
-				u32 num_queues)
+				struct mwl8k_txq_info *txinfo)
 {
 	int count, desc, status;
 	struct mwl8k_tx_queue *txq;
 	struct mwl8k_tx_desc *tx_desc;
 	int ndescs = 0;
 
-	memset(txinfo, 0, num_queues * sizeof(struct mwl8k_txq_info));
+	memset(txinfo, 0, MWL8K_TX_QUEUES * sizeof(struct mwl8k_txq_info));
+
 	spin_lock_bh(&priv->tx_lock);
-	for (count = 0; count < num_queues; count++) {
+	for (count = 0; count < MWL8K_TX_QUEUES; count++) {
 		txq = priv->txq + count;
 		txinfo[count].len = txq->tx_stats.len;
 		txinfo[count].head = txq->tx_head;
@@ -1135,7 +1135,7 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw, u32 delay_ms)
 	spin_unlock_bh(&priv->tx_lock);
 
 	if (count) {
-		struct mwl8k_txq_info txinfo[4];
+		struct mwl8k_txq_info txinfo[MWL8K_TX_QUEUES];
 		int index;
 		int newcount;
 
@@ -1152,8 +1152,8 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw, u32 delay_ms)
 		printk(KERN_ERR "%s(%u) TIMEDOUT:%ums Pend:%u-->%u\n",
 		       __func__, __LINE__, delay_ms, count, newcount);
 
-		mwl8k_scan_tx_ring(priv, txinfo, 4);
-		for (index = 0; index < 4; index++)
+		mwl8k_scan_tx_ring(priv, txinfo);
+		for (index = 0; index < MWL8K_TX_QUEUES; index++)
 			printk(KERN_ERR
 				"TXQ:%u L:%u H:%u T:%u FW:%u DRV:%u U:%u\n",
 					index,
-- 
1.5.6.4

^ permalink raw reply related

* [PATCH 15/29] mwl8k: no need to hold ->tx_lock while setting the hardware interrupt mask
From: Lennert Buytenhek @ 2009-08-18  3:53 UTC (permalink / raw)
  To: linville, linux-wireless

Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
---
 drivers/net/wireless/mwl8k.c |    6 ------
 1 files changed, 0 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index f482922..e46cf3c 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -2768,9 +2768,7 @@ static void mwl8k_stop(struct ieee80211_hw *hw)
 		printk(KERN_ERR "%s() timed out\n", __func__);
 
 	/* Disable interrupts */
-	spin_lock_irq(&priv->tx_lock);
 	iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
-	spin_unlock_irq(&priv->tx_lock);
 	free_irq(priv->pdev->irq, hw);
 
 	/* Stop finalize join worker */
@@ -3461,9 +3459,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
 	}
 
 	/* Disable interrupts */
-	spin_lock_irq(&priv->tx_lock);
 	iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
-	spin_unlock_irq(&priv->tx_lock);
 	free_irq(priv->pdev->irq, hw);
 
 	rc = ieee80211_register_hw(hw);
@@ -3487,9 +3483,7 @@ err_stop_firmware:
 	mwl8k_release_firmware(priv);
 
 err_free_irq:
-	spin_lock_irq(&priv->tx_lock);
 	iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
-	spin_unlock_irq(&priv->tx_lock);
 	free_irq(priv->pdev->irq, hw);
 
 err_free_queues:
-- 
1.5.6.4

^ permalink raw reply related

* [PATCH 16/29] mwl8k: mwl8k_txq_xmit() rework
From: Lennert Buytenhek @ 2009-08-18  3:53 UTC (permalink / raw)
  To: linville, linux-wireless

Various mwl8k_txq_xmit changes:
- Extract the QoS field before adding the DMA header.
- Only write to tx->status once, and only after all the other
  descriptor fields have been set.
- Do all tx state manipulation under the tx spinlock.
- Remove the priv->inconfig check, as all transmit queues will
  be frozen during config cycles, so we won't ever be asked to
  transmit if a config cycle is running.
- Remove some more dead code.

Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
---
 drivers/net/wireless/mwl8k.c |  145 +++++++++++++++---------------------------
 1 files changed, 52 insertions(+), 93 deletions(-)

diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index e46cf3c..f0d1fa7 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -1257,46 +1257,60 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
 {
 	struct mwl8k_priv *priv = hw->priv;
 	struct ieee80211_tx_info *tx_info;
+	struct mwl8k_vif *mwl8k_vif;
 	struct ieee80211_hdr *wh;
 	struct mwl8k_tx_queue *txq;
 	struct mwl8k_tx_desc *tx;
-	struct mwl8k_dma_data *tr;
-	struct mwl8k_vif *mwl8k_vif;
 	dma_addr_t dma;
-	u16 qos = 0;
-	bool qosframe = false, ampduframe = false;
-	bool mcframe = false, eapolframe = false;
-	bool amsduframe = false;
-	__le16 fc;
+	u32 txstatus;
+	u8 txdatarate;
+	u16 qos;
 
-	txq = priv->txq + index;
-	tx = txq->tx_desc_area + txq->tx_tail;
-
-	BUG_ON(txq->tx_skb[txq->tx_tail] != NULL);
+	wh = (struct ieee80211_hdr *)skb->data;
+	if (ieee80211_is_data_qos(wh->frame_control))
+		qos = le16_to_cpu(*((__le16 *)ieee80211_get_qos_ctl(wh)));
+	else
+		qos = 0;
 
-	/*
-	 * Append HW DMA header to start of packet.
-	 */
 	mwl8k_add_dma_header(skb);
+	wh = &((struct mwl8k_dma_data *)skb->data)->wh;
 
 	tx_info = IEEE80211_SKB_CB(skb);
 	mwl8k_vif = MWL8K_VIF(tx_info->control.vif);
-	tr = (struct mwl8k_dma_data *)skb->data;
-	wh = &tr->wh;
-	fc = wh->frame_control;
-	qosframe = ieee80211_is_data_qos(fc);
-	mcframe = is_multicast_ether_addr(wh->addr1);
-	ampduframe = !!(tx_info->flags & IEEE80211_TX_CTL_AMPDU);
 
 	if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
 		u16 seqno = mwl8k_vif->seqno;
+
 		wh->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
 		wh->seq_ctrl |= cpu_to_le16(seqno << 4);
 		mwl8k_vif->seqno = seqno++ % 4096;
 	}
 
-	if (qosframe)
-		qos = le16_to_cpu(*((__le16 *)ieee80211_get_qos_ctl(wh)));
+	/* Setup firmware control bit fields for each frame type.  */
+	txstatus = 0;
+	txdatarate = 0;
+	if (ieee80211_is_mgmt(wh->frame_control) ||
+	    ieee80211_is_ctl(wh->frame_control)) {
+		txdatarate = 0;
+		qos = mwl8k_qos_setbit_eosp(qos);
+		/* Set Queue size to unspecified */
+		qos = mwl8k_qos_setbit_qlen(qos, 0xff);
+	} else if (ieee80211_is_data(wh->frame_control)) {
+		txdatarate = 1;
+		if (is_multicast_ether_addr(wh->addr1))
+			txstatus |= MWL8K_TXD_STATUS_MULTICAST_TX;
+
+		/* Send pkt in an aggregate if AMPDU frame.  */
+		if (tx_info->flags & IEEE80211_TX_CTL_AMPDU)
+			qos = mwl8k_qos_setbit_ack(qos,
+				MWL8K_TXD_ACK_POLICY_BLOCKACK);
+		else
+			qos = mwl8k_qos_setbit_ack(qos,
+				MWL8K_TXD_ACK_POLICY_NORMAL);
+
+		if (qos & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT)
+			qos = mwl8k_qos_setbit_amsdu(qos);
+	}
 
 	dma = pci_map_single(priv->pdev, skb->data,
 				skb->len, PCI_DMA_TODEVICE);
@@ -1304,95 +1318,40 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
 	if (pci_dma_mapping_error(priv->pdev, dma)) {
 		printk(KERN_DEBUG "%s: failed to dma map skb, "
 			"dropping TX frame.\n", priv->name);
-
-		if (skb != NULL)
-			dev_kfree_skb(skb);
+		dev_kfree_skb(skb);
 		return NETDEV_TX_OK;
 	}
 
-	/* Set desc header, cpu bit order.  */
-	tx->status = 0;
-	tx->data_rate = 0;
-	tx->tx_priority = index;
-	tx->qos_control = 0;
-	tx->rate_info = 0;
-	tx->peer_id = mwl8k_vif->peer_id;
-
-	amsduframe = !!(qos & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT);
-
-	/* Setup firmware control bit fields for each frame type.  */
-	if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) {
-		tx->data_rate = 0;
-		qos = mwl8k_qos_setbit_eosp(qos);
-		/* Set Queue size to unspecified */
-		qos = mwl8k_qos_setbit_qlen(qos, 0xff);
-	} else if (ieee80211_is_data(fc)) {
-		tx->data_rate = 1;
-		if (mcframe)
-			tx->status |= MWL8K_TXD_STATUS_MULTICAST_TX;
+	spin_lock_bh(&priv->tx_lock);
 
-		/*
-		 * Tell firmware to not send EAPOL pkts in an
-		 * aggregate.  Verify against mac80211 tx path.  If
-		 * stack turns off AMPDU for an EAPOL frame this
-		 * check will be removed.
-		 */
-		if (eapolframe) {
-			qos = mwl8k_qos_setbit_ack(qos,
-				MWL8K_TXD_ACK_POLICY_NORMAL);
-		} else {
-			/* Send pkt in an aggregate if AMPDU frame.  */
-			if (ampduframe)
-				qos = mwl8k_qos_setbit_ack(qos,
-					MWL8K_TXD_ACK_POLICY_BLOCKACK);
-			else
-				qos = mwl8k_qos_setbit_ack(qos,
-					MWL8K_TXD_ACK_POLICY_NORMAL);
+	txq = priv->txq + index;
 
-			if (amsduframe)
-				qos = mwl8k_qos_setbit_amsdu(qos);
-		}
-	}
+	BUG_ON(txq->tx_skb[txq->tx_tail] != NULL);
+	txq->tx_skb[txq->tx_tail] = skb;
 
-	/* Convert to little endian */
+	tx = txq->tx_desc_area + txq->tx_tail;
+	tx->data_rate = txdatarate;
+	tx->tx_priority = index;
 	tx->qos_control = cpu_to_le16(qos);
-	tx->status = cpu_to_le32(tx->status);
 	tx->pkt_phys_addr = cpu_to_le32(dma);
 	tx->pkt_len = cpu_to_le16(skb->len);
-
-	txq->tx_skb[txq->tx_tail] = skb;
-
-	spin_lock_bh(&priv->tx_lock);
-
-	tx->status = cpu_to_le32(MWL8K_TXD_STATUS_OK |
-					MWL8K_TXD_STATUS_FW_OWNED);
+	tx->rate_info = 0;
+	tx->peer_id = mwl8k_vif->peer_id;
 	wmb();
+	tx->status = cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED | txstatus);
+
+	txq->tx_stats.count++;
 	txq->tx_stats.len++;
 	priv->pending_tx_pkts++;
-	txq->tx_stats.count++;
-	txq->tx_tail++;
 
+	txq->tx_tail++;
 	if (txq->tx_tail == MWL8K_TX_DESCS)
 		txq->tx_tail = 0;
+
 	if (txq->tx_head == txq->tx_tail)
 		ieee80211_stop_queue(hw, index);
 
-	if (priv->inconfig) {
-		/*
-		 * Silently queue packet when we are in the middle of
-		 * a config cycle.  Notify firmware only if we are
-		 * waiting for TXQs to empty.  If a packet is sent
-		 * before .config() is complete, perhaps it is better
-		 * to drop the packet, as the channel is being changed
-		 * and the packet will end up on the wrong channel.
-		 */
-		printk(KERN_ERR "%s(): WARNING TX activity while "
-			"in config\n", __func__);
-
-		if (priv->tx_wait != NULL)
-			mwl8k_tx_start(priv);
-	} else
-		mwl8k_tx_start(priv);
+	mwl8k_tx_start(priv);
 
 	spin_unlock_bh(&priv->tx_lock);
 
-- 
1.5.6.4

^ permalink raw reply related

* [PATCH 17/29] mwl8k: mwl8k_queue_work() cleanup
From: Lennert Buytenhek @ 2009-08-18  3:53 UTC (permalink / raw)
  To: linville, linux-wireless

Delete most of the mwl8k_work_struct fields and options, since most
of them are unused or never changed from their defaults:
- We always use priv->config_wq, so delete the wqueue argument from
  mwl8k_queue_work().
- MWL8K_WQ_SPIN is never used.
- MWL8K_WQ_TX_WAIT_EMPTY is always set, so assume it unconditionally.
- MWL8K_WQ_FREE_WORKSTRUCT is implied by MWL8K_WQ_POST_REQUEST, so
  delete it and assume it whenever the latter is set.
- One of MWL8K_WQ_{POST_REQUEST,SLEEP} is always set, so change this
  into a bool flag.
- timeout_ms/txwait_attempts/tx_timeout_ms are never changed from
  their defaults, so just hardcode these in the workqueue worker.
- step is never used.

Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
---
 drivers/net/wireless/mwl8k.c |  210 +++++++++--------------------------------
 1 files changed, 46 insertions(+), 164 deletions(-)

diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index f0d1fa7..905f750 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -1113,7 +1113,7 @@ static int mwl8k_scan_tx_ring(struct mwl8k_priv *priv,
 	return ndescs;
 }
 
-static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw, u32 delay_ms)
+static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw)
 {
 	struct mwl8k_priv *priv = hw->priv;
 	DECLARE_COMPLETION_ONSTACK(cmd_wait);
@@ -1140,7 +1140,7 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw, u32 delay_ms)
 		int newcount;
 
 		timeout = wait_for_completion_timeout(&cmd_wait,
-					msecs_to_jiffies(delay_ms));
+					msecs_to_jiffies(1000));
 		if (timeout)
 			return 0;
 
@@ -1149,8 +1149,8 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw, u32 delay_ms)
 		newcount = mwl8k_txq_busy(priv);
 		spin_unlock_bh(&priv->tx_lock);
 
-		printk(KERN_ERR "%s(%u) TIMEDOUT:%ums Pend:%u-->%u\n",
-		       __func__, __LINE__, delay_ms, count, newcount);
+		printk(KERN_ERR "%s(%u) TIMEDOUT:1000ms Pend:%u-->%u\n",
+		       __func__, __LINE__, count, newcount);
 
 		mwl8k_scan_tx_ring(priv, txinfo);
 		for (index = 0; index < MWL8K_TX_QUEUES; index++)
@@ -2391,82 +2391,18 @@ struct mwl8k_work_struct {
 	int rc;
 
 	/*
-	 * Optional field. Refer to explanation of MWL8K_WQ_XXX_XXX
-	 * flags for explanation.  Defaults to MWL8K_WQ_DEFAULT_OPTIONS.
+	 * Whether to sleep for request completion.
 	 */
-	u32 options;
-
-	/* Optional field.  Defaults to MWL8K_CONFIG_TIMEOUT_MS.  */
-	unsigned long timeout_ms;
-
-	/* Optional field.  Defaults to MWL8K_WQ_TXWAIT_ATTEMPTS.  */
-	u32 txwait_attempts;
-
-	/* Optional field.  Defaults to MWL8K_TXWAIT_MS.  */
-	u32 tx_timeout_ms;
-	u32 step;
+	bool sleep;
 };
 
-/* Flags controlling behavior of config queue requests */
-
-/* Caller spins while waiting for completion.  */
-#define MWL8K_WQ_SPIN			0x00000001
-
-/* Wait for TX queues to empty before proceeding with configuration.  */
-#define MWL8K_WQ_TX_WAIT_EMPTY		0x00000002
-
-/* Queue request and return immediately.  */
-#define MWL8K_WQ_POST_REQUEST		0x00000004
-
-/*
- * Caller sleeps and waits for task complete notification.
- * Do not use in atomic context.
- */
-#define MWL8K_WQ_SLEEP			0x00000008
-
-/* Free work struct when task is done.  */
-#define MWL8K_WQ_FREE_WORKSTRUCT	0x00000010
-
-/*
- * Config request is queued and returns to caller imediately.  Use
- * this in atomic context. Work struct is freed by mwl8k_queue_work()
- * when this flag is set.
- */
-#define MWL8K_WQ_QUEUE_ONLY	(MWL8K_WQ_POST_REQUEST | \
-				 MWL8K_WQ_FREE_WORKSTRUCT)
-
-/* Default work queue behavior is to sleep and wait for tx completion.  */
-#define MWL8K_WQ_DEFAULT_OPTIONS (MWL8K_WQ_SLEEP | MWL8K_WQ_TX_WAIT_EMPTY)
-
-/*
- * Default config request timeout.  Add adjustments to make sure the
- * config thread waits long enough for both tx wait and cmd wait before
- * timing out.
- */
-
-/* Time to wait for all TXQs to drain.  TX Doorbell is pressed each time.  */
-#define MWL8K_TXWAIT_TIMEOUT_MS		1000
-
-/* Default number of TX wait attempts.  */
-#define MWL8K_WQ_TXWAIT_ATTEMPTS	4
-
-/* Total time to wait for TXQ to drain.  */
-#define MWL8K_TXWAIT_MS			(MWL8K_TXWAIT_TIMEOUT_MS * \
-						MWL8K_WQ_TXWAIT_ATTEMPTS)
-
-/* Scheduling slop.  */
-#define MWL8K_OS_SCHEDULE_OVERHEAD_MS	200
-
-#define MWL8K_CONFIG_TIMEOUT_MS	(MWL8K_CMD_TIMEOUT_MS + \
-				 MWL8K_TXWAIT_MS + \
-				 MWL8K_OS_SCHEDULE_OVERHEAD_MS)
-
 static void mwl8k_config_thread(struct work_struct *wt)
 {
 	struct mwl8k_work_struct *worker = (struct mwl8k_work_struct *)wt;
 	struct ieee80211_hw *hw = worker->hw;
 	struct mwl8k_priv *priv = hw->priv;
 	int rc = 0;
+	int iter;
 
 	spin_lock_irq(&priv->tx_lock);
 	priv->inconfig = true;
@@ -2479,44 +2415,16 @@ static void mwl8k_config_thread(struct work_struct *wt)
 	 * reconfiguration. This avoids interrupting any in-flight
 	 * DMA transfers to the hardware.
 	 */
-	if (worker->options & MWL8K_WQ_TX_WAIT_EMPTY) {
-		u32 timeout;
-		u32 time_remaining;
-		u32 iter;
-		u32 tx_wait_attempts = worker->txwait_attempts;
-
-		time_remaining = worker->tx_timeout_ms;
-		if (!tx_wait_attempts)
-			tx_wait_attempts = 1;
-
-		timeout = worker->tx_timeout_ms/tx_wait_attempts;
-		if (!timeout)
-			timeout = 1;
-
-		iter = tx_wait_attempts;
-		do {
-			int wait_time;
-
-			if (time_remaining > timeout) {
-				time_remaining -= timeout;
-				wait_time = timeout;
-			} else
-				wait_time = time_remaining;
-
-			if (!wait_time)
-				wait_time = 1;
-
-			rc = mwl8k_tx_wait_empty(hw, wait_time);
-			if (rc)
-				printk(KERN_ERR "%s() txwait timeout=%ums "
-					"Retry:%u/%u\n", __func__, timeout,
-					tx_wait_attempts - iter + 1,
-					tx_wait_attempts);
+	iter = 4;
+	do {
+		rc = mwl8k_tx_wait_empty(hw);
+		if (rc)
+			printk(KERN_ERR "%s() txwait timeout=1000ms "
+				"Retry:%u/%u\n", __func__, 4 - iter + 1, 4);
+	} while (rc && --iter);
 
-		} while (rc && --iter);
+	rc = iter ? 0 : -ETIMEDOUT;
 
-		rc = iter ? 0 : -ETIMEDOUT;
-	}
 	if (!rc)
 		rc = worker->wfunc(wt);
 
@@ -2525,58 +2433,38 @@ static void mwl8k_config_thread(struct work_struct *wt)
 	if (priv->pending_tx_pkts && priv->radio_on)
 		mwl8k_tx_start(priv);
 	spin_unlock_irq(&priv->tx_lock);
+
 	ieee80211_wake_queues(hw);
 
-	worker->rc = rc;
-	if (worker->options & MWL8K_WQ_SLEEP)
+	if (worker->sleep) {
+		worker->rc = rc;
 		complete(worker->cmd_wait);
-
-	if (worker->options & MWL8K_WQ_FREE_WORKSTRUCT)
+	} else {
 		kfree(wt);
+	}
 }
 
 static int mwl8k_queue_work(struct ieee80211_hw *hw,
 				struct mwl8k_work_struct *worker,
-				struct workqueue_struct *wqueue,
 				int (*wfunc)(struct work_struct *w))
 {
+	struct mwl8k_priv *priv = hw->priv;
 	unsigned long timeout = 0;
 	int rc = 0;
 
 	DECLARE_COMPLETION_ONSTACK(cmd_wait);
 
-	if (!worker->timeout_ms)
-		worker->timeout_ms = MWL8K_CONFIG_TIMEOUT_MS;
-
-	if (!worker->options)
-		worker->options = MWL8K_WQ_DEFAULT_OPTIONS;
-
-	if (!worker->txwait_attempts)
-		worker->txwait_attempts = MWL8K_WQ_TXWAIT_ATTEMPTS;
-
-	if (!worker->tx_timeout_ms)
-		worker->tx_timeout_ms = MWL8K_TXWAIT_MS;
-
 	worker->hw = hw;
 	worker->cmd_wait = &cmd_wait;
 	worker->rc = 1;
 	worker->wfunc = wfunc;
 
 	INIT_WORK(&worker->wt, mwl8k_config_thread);
-	queue_work(wqueue, &worker->wt);
+	queue_work(priv->config_wq, &worker->wt);
 
-	if (worker->options & MWL8K_WQ_POST_REQUEST) {
-		rc = 0;
-	} else {
-		if (worker->options & MWL8K_WQ_SPIN) {
-			timeout = worker->timeout_ms;
-			while (timeout && (worker->rc > 0)) {
-				mdelay(1);
-				timeout--;
-			}
-		} else if (worker->options & MWL8K_WQ_SLEEP)
-			timeout = wait_for_completion_timeout(&cmd_wait,
-				msecs_to_jiffies(worker->timeout_ms));
+	if (worker->sleep) {
+		timeout = wait_for_completion_timeout(&cmd_wait,
+			msecs_to_jiffies(10000));
 
 		if (timeout)
 			rc = worker->rc;
@@ -2669,8 +2557,9 @@ static int mwl8k_start(struct ieee80211_hw *hw)
 		goto mwl8k_start_disable_irq;
 	}
 
-	rc = mwl8k_queue_work(hw, &worker->header,
-			      priv->config_wq, mwl8k_start_wt);
+	worker->header.sleep = 1;
+
+	rc = mwl8k_queue_work(hw, &worker->header, mwl8k_start_wt);
 	kfree(worker);
 	if (!rc)
 		return rc;
@@ -2720,8 +2609,9 @@ static void mwl8k_stop(struct ieee80211_hw *hw)
 	if (worker == NULL)
 		return;
 
-	rc = mwl8k_queue_work(hw, &worker->header,
-			      priv->config_wq, mwl8k_stop_wt);
+	worker->header.sleep = 1;
+
+	rc = mwl8k_queue_work(hw, &worker->header, mwl8k_stop_wt);
 	kfree(worker);
 	if (rc == -ETIMEDOUT)
 		printk(KERN_ERR "%s() timed out\n", __func__);
@@ -2850,15 +2740,15 @@ static int mwl8k_config(struct ieee80211_hw *hw, u32 changed)
 {
 	int rc = 0;
 	struct mwl8k_config_worker *worker;
-	struct mwl8k_priv *priv = hw->priv;
 
 	worker = kzalloc(sizeof(*worker), GFP_KERNEL);
 	if (worker == NULL)
 		return -ENOMEM;
 
+	worker->header.sleep = 1;
 	worker->changed = changed;
-	rc = mwl8k_queue_work(hw, &worker->header,
-			      priv->config_wq, mwl8k_config_wt);
+
+	rc = mwl8k_queue_work(hw, &worker->header, mwl8k_config_wt);
 	if (rc == -ETIMEDOUT) {
 		printk(KERN_ERR "%s() timed out.\n", __func__);
 		rc = -EINVAL;
@@ -2951,7 +2841,6 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw,
 				   u32 changed)
 {
 	struct mwl8k_bss_info_changed_worker *worker;
-	struct mwl8k_priv *priv = hw->priv;
 	struct mwl8k_vif *mv_vif = MWL8K_VIF(vif);
 	int rc;
 
@@ -2965,12 +2854,11 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw,
 	if (worker == NULL)
 		return;
 
+	worker->header.sleep = 1;
 	worker->vif = vif;
 	worker->info = info;
 	worker->changed = changed;
-	rc = mwl8k_queue_work(hw, &worker->header,
-			      priv->config_wq,
-			      mwl8k_bss_info_changed_wt);
+	rc = mwl8k_queue_work(hw, &worker->header, mwl8k_bss_info_changed_wt);
 	kfree(worker);
 	if (rc == -ETIMEDOUT)
 		printk(KERN_ERR "%s() timed out\n", __func__);
@@ -3025,7 +2913,6 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw,
 				   struct dev_addr_list *mclist)
 {
 	struct mwl8k_configure_filter_worker *worker;
-	struct mwl8k_priv *priv = hw->priv;
 
 	/* Clear unsupported feature flags */
 	*total_flags &= MWL8K_SUPPORTED_IF_FLAGS;
@@ -3037,15 +2924,14 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw,
 	if (worker == NULL)
 		return;
 
-	worker->header.options = MWL8K_WQ_QUEUE_ONLY | MWL8K_WQ_TX_WAIT_EMPTY;
+	worker->header.sleep = 0;
 	worker->changed_flags = changed_flags;
 	worker->total_flags = *total_flags;
 	if (mc_count)
 		worker->set_multicast_adr =
 			__mwl8k_cmd_mac_multicast_adr(hw, mc_count, mclist);
 
-	mwl8k_queue_work(hw, &worker->header, priv->config_wq,
-			 mwl8k_configure_filter_wt);
+	mwl8k_queue_work(hw, &worker->header, mwl8k_configure_filter_wt);
 }
 
 struct mwl8k_set_rts_threshold_worker {
@@ -3071,17 +2957,15 @@ static int mwl8k_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
 {
 	int rc;
 	struct mwl8k_set_rts_threshold_worker *worker;
-	struct mwl8k_priv *priv = hw->priv;
 
 	worker = kzalloc(sizeof(*worker), GFP_KERNEL);
 	if (worker == NULL)
 		return -ENOMEM;
 
+	worker->header.sleep = 1;
 	worker->value = value;
 
-	rc = mwl8k_queue_work(hw, &worker->header,
-			      priv->config_wq,
-			      mwl8k_set_rts_threshold_wt);
+	rc = mwl8k_queue_work(hw, &worker->header, mwl8k_set_rts_threshold_wt);
 	kfree(worker);
 
 	if (rc == -ETIMEDOUT) {
@@ -3129,16 +3013,15 @@ static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue,
 {
 	int rc;
 	struct mwl8k_conf_tx_worker *worker;
-	struct mwl8k_priv *priv = hw->priv;
 
 	worker = kzalloc(sizeof(*worker), GFP_KERNEL);
 	if (worker == NULL)
 		return -ENOMEM;
 
+	worker->header.sleep = 1;
 	worker->queue = queue;
 	worker->params = params;
-	rc = mwl8k_queue_work(hw, &worker->header,
-			      priv->config_wq, mwl8k_conf_tx_wt);
+	rc = mwl8k_queue_work(hw, &worker->header, mwl8k_conf_tx_wt);
 	kfree(worker);
 	if (rc == -ETIMEDOUT) {
 		printk(KERN_ERR "%s() timed out\n", __func__);
@@ -3182,15 +3065,14 @@ static int mwl8k_get_stats(struct ieee80211_hw *hw,
 {
 	int rc;
 	struct mwl8k_get_stats_worker *worker;
-	struct mwl8k_priv *priv = hw->priv;
 
 	worker = kzalloc(sizeof(*worker), GFP_KERNEL);
 	if (worker == NULL)
 		return -ENOMEM;
 
+	worker->header.sleep = 1;
 	worker->stats = stats;
-	rc = mwl8k_queue_work(hw, &worker->header,
-			      priv->config_wq, mwl8k_get_stats_wt);
+	rc = mwl8k_queue_work(hw, &worker->header, mwl8k_get_stats_wt);
 
 	kfree(worker);
 	if (rc == -ETIMEDOUT) {
-- 
1.5.6.4

^ permalink raw reply related

* [PATCH 18/29] mwl8k: fix firmware command serialisation
From: Lennert Buytenhek @ 2009-08-18  3:53 UTC (permalink / raw)
  To: linville, linux-wireless

The current mwl8k_priv->fw_lock spinlock doesn't actually protect
against multiple commands being submitted at once, as it is not kept
held over the entire firmware command submission.  And since waiting
for command completion sleeps, we can't use a spinlock anyway.

To fix mwl8k firmware command serialisation properly, we have the
following requirements:
- Some commands require that the packet transmit path is idle when
  the command is issued.  (For simplicity, we'll just quiesce the
  transmit path for every command.)
- There are certain sequences of commands that need to be issued to
  the hardware sequentially, with no other intervening commands.

This leads to an implementation of a "firmware lock" as a mutex that
can be taken recursively, and which is taken by both the low-level
command submission function (mwl8k_post_cmd) as well as any users of
that function that require issuing of an atomic sequence of commands,
and quiesces the transmit path whenever it's taken.

Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
---
 drivers/net/wireless/mwl8k.c |  154 ++++++++++++++++++++++++------------------
 1 files changed, 89 insertions(+), 65 deletions(-)

diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 905f750..5516058 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -139,13 +139,18 @@ struct mwl8k_priv {
 
 	struct pci_dev *pdev;
 	u8 name[16];
-	/* firmware access lock */
-	spinlock_t fw_lock;
 
 	/* firmware files and meta data */
 	struct mwl8k_firmware fw;
 	u32 part_num;
 
+	/* firmware access */
+	struct mutex fw_mutex;
+	struct task_struct *fw_mutex_owner;
+	int fw_mutex_depth;
+	struct completion *tx_wait;
+	struct completion *hostcmd_wait;
+
 	/* lock held over TX and TX reap */
 	spinlock_t tx_lock;
 
@@ -179,9 +184,6 @@ struct mwl8k_priv {
 	bool radio_short_preamble;
 	bool wmm_enabled;
 
-	/* Set if PHY config is in progress */
-	bool inconfig;
-
 	/* XXX need to convert this to handle multiple interfaces */
 	bool capture_beacon;
 	u8 capture_bssid[ETH_ALEN];
@@ -200,8 +202,6 @@ struct mwl8k_priv {
 
 	/* Work thread to serialize configuration requests */
 	struct workqueue_struct *config_wq;
-	struct completion *hostcmd_wait;
-	struct completion *tx_wait;
 };
 
 /* Per interface specific private data */
@@ -1113,6 +1113,9 @@ static int mwl8k_scan_tx_ring(struct mwl8k_priv *priv,
 	return ndescs;
 }
 
+/*
+ * Must be called with hw->fw_mutex held and tx queues stopped.
+ */
 static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw)
 {
 	struct mwl8k_priv *priv = hw->priv;
@@ -1122,9 +1125,6 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw)
 
 	might_sleep();
 
-	if (priv->tx_wait != NULL)
-		printk(KERN_ERR "WARNING Previous TXWaitEmpty instance\n");
-
 	spin_lock_bh(&priv->tx_lock);
 	count = mwl8k_txq_busy(priv);
 	if (count) {
@@ -1140,7 +1140,7 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw)
 		int newcount;
 
 		timeout = wait_for_completion_timeout(&cmd_wait,
-					msecs_to_jiffies(1000));
+					msecs_to_jiffies(5000));
 		if (timeout)
 			return 0;
 
@@ -1149,7 +1149,7 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw)
 		newcount = mwl8k_txq_busy(priv);
 		spin_unlock_bh(&priv->tx_lock);
 
-		printk(KERN_ERR "%s(%u) TIMEDOUT:1000ms Pend:%u-->%u\n",
+		printk(KERN_ERR "%s(%u) TIMEDOUT:5000ms Pend:%u-->%u\n",
 		       __func__, __LINE__, count, newcount);
 
 		mwl8k_scan_tx_ring(priv, txinfo);
@@ -1228,10 +1228,10 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force)
 
 		ieee80211_tx_status_irqsafe(hw, skb);
 
-		wake = !priv->inconfig && priv->radio_on;
+		wake = 1;
 	}
 
-	if (wake)
+	if (wake && priv->radio_on && !mutex_is_locked(&priv->fw_mutex))
 		ieee80211_wake_queue(hw, index);
 }
 
@@ -1360,6 +1360,60 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
 
 
 /*
+ * Firmware access.
+ *
+ * We have the following requirements for issuing firmware commands:
+ * - Some commands require that the packet transmit path is idle when
+ *   the command is issued.  (For simplicity, we'll just quiesce the
+ *   transmit path for every command.)
+ * - There are certain sequences of commands that need to be issued to
+ *   the hardware sequentially, with no other intervening commands.
+ *
+ * This leads to an implementation of a "firmware lock" as a mutex that
+ * can be taken recursively, and which is taken by both the low-level
+ * command submission function (mwl8k_post_cmd) as well as any users of
+ * that function that require issuing of an atomic sequence of commands,
+ * and quiesces the transmit path whenever it's taken.
+ */
+static int mwl8k_fw_lock(struct ieee80211_hw *hw)
+{
+	struct mwl8k_priv *priv = hw->priv;
+
+	if (priv->fw_mutex_owner != current) {
+		int rc;
+
+		mutex_lock(&priv->fw_mutex);
+		ieee80211_stop_queues(hw);
+
+		rc = mwl8k_tx_wait_empty(hw);
+		if (rc) {
+			ieee80211_wake_queues(hw);
+			mutex_unlock(&priv->fw_mutex);
+
+			return rc;
+		}
+
+		priv->fw_mutex_owner = current;
+	}
+
+	priv->fw_mutex_depth++;
+
+	return 0;
+}
+
+static void mwl8k_fw_unlock(struct ieee80211_hw *hw)
+{
+	struct mwl8k_priv *priv = hw->priv;
+
+	if (!--priv->fw_mutex_depth) {
+		ieee80211_wake_queues(hw);
+		priv->fw_mutex_owner = NULL;
+		mutex_unlock(&priv->fw_mutex);
+	}
+}
+
+
+/*
  * Command processing.
  */
 
@@ -1384,28 +1438,28 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd)
 	if (pci_dma_mapping_error(priv->pdev, dma_addr))
 		return -ENOMEM;
 
-	if (priv->hostcmd_wait != NULL)
-		printk(KERN_ERR "WARNING host command in progress\n");
+	rc = mwl8k_fw_lock(hw);
+	if (rc)
+		return rc;
 
-	spin_lock_irq(&priv->fw_lock);
 	priv->hostcmd_wait = &cmd_wait;
 	iowrite32(dma_addr, regs + MWL8K_HIU_GEN_PTR);
 	iowrite32(MWL8K_H2A_INT_DOORBELL,
 		regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS);
 	iowrite32(MWL8K_H2A_INT_DUMMY,
 		regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS);
-	spin_unlock_irq(&priv->fw_lock);
 
 	timeout = wait_for_completion_timeout(&cmd_wait,
 				msecs_to_jiffies(MWL8K_CMD_TIMEOUT_MS));
 
+	priv->hostcmd_wait = NULL;
+
+	mwl8k_fw_unlock(hw);
+
 	pci_unmap_single(priv->pdev, dma_addr, dma_size,
 					PCI_DMA_BIDIRECTIONAL);
 
 	if (!timeout) {
-		spin_lock_irq(&priv->fw_lock);
-		priv->hostcmd_wait = NULL;
-		spin_unlock_irq(&priv->fw_lock);
 		printk(KERN_ERR "%s: Command %s timeout after %u ms\n",
 		       priv->name,
 		       mwl8k_cmd_name(cmd->code, buf, sizeof(buf)),
@@ -2336,17 +2390,14 @@ static irqreturn_t mwl8k_interrupt(int irq, void *dev_id)
 	}
 
 	if (status & MWL8K_A2H_INT_OPC_DONE) {
-		if (priv->hostcmd_wait != NULL) {
+		if (priv->hostcmd_wait != NULL)
 			complete(priv->hostcmd_wait);
-			priv->hostcmd_wait = NULL;
-		}
 	}
 
 	if (status & MWL8K_A2H_INT_QUEUE_EMPTY) {
-		if (!priv->inconfig &&
-			priv->radio_on &&
-			mwl8k_txq_busy(priv))
-				mwl8k_tx_start(priv);
+		if (!mutex_is_locked(&priv->fw_mutex) &&
+		    priv->radio_on && mwl8k_txq_busy(priv))
+			mwl8k_tx_start(priv);
 	}
 
 	return IRQ_HANDLED;
@@ -2400,41 +2451,13 @@ static void mwl8k_config_thread(struct work_struct *wt)
 {
 	struct mwl8k_work_struct *worker = (struct mwl8k_work_struct *)wt;
 	struct ieee80211_hw *hw = worker->hw;
-	struct mwl8k_priv *priv = hw->priv;
 	int rc = 0;
-	int iter;
 
-	spin_lock_irq(&priv->tx_lock);
-	priv->inconfig = true;
-	spin_unlock_irq(&priv->tx_lock);
-
-	ieee80211_stop_queues(hw);
-
-	/*
-	 * Wait for host queues to drain before doing PHY
-	 * reconfiguration. This avoids interrupting any in-flight
-	 * DMA transfers to the hardware.
-	 */
-	iter = 4;
-	do {
-		rc = mwl8k_tx_wait_empty(hw);
-		if (rc)
-			printk(KERN_ERR "%s() txwait timeout=1000ms "
-				"Retry:%u/%u\n", __func__, 4 - iter + 1, 4);
-	} while (rc && --iter);
-
-	rc = iter ? 0 : -ETIMEDOUT;
-
-	if (!rc)
+	rc = mwl8k_fw_lock(hw);
+	if (!rc) {
 		rc = worker->wfunc(wt);
-
-	spin_lock_irq(&priv->tx_lock);
-	priv->inconfig = false;
-	if (priv->pending_tx_pkts && priv->radio_on)
-		mwl8k_tx_start(priv);
-	spin_unlock_irq(&priv->tx_lock);
-
-	ieee80211_wake_queues(hw);
+		mwl8k_fw_unlock(hw);
+	}
 
 	if (worker->sleep) {
 		worker->rc = rc;
@@ -3163,15 +3186,10 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
 	priv = hw->priv;
 	priv->hw = hw;
 	priv->pdev = pdev;
-	priv->hostcmd_wait = NULL;
-	priv->tx_wait = NULL;
-	priv->inconfig = false;
 	priv->wmm_enabled = false;
 	priv->pending_tx_pkts = 0;
 	strncpy(priv->name, MWL8K_NAME, sizeof(priv->name));
 
-	spin_lock_init(&priv->fw_lock);
-
 	SET_IEEE80211_DEV(hw, &pdev->dev);
 	pci_set_drvdata(pdev, hw);
 
@@ -3237,6 +3255,12 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
 		goto err_iounmap;
 	rxq_refill(hw, 0, INT_MAX);
 
+	mutex_init(&priv->fw_mutex);
+	priv->fw_mutex_owner = NULL;
+	priv->fw_mutex_depth = 0;
+	priv->tx_wait = NULL;
+	priv->hostcmd_wait = NULL;
+
 	spin_lock_init(&priv->tx_lock);
 
 	for (i = 0; i < MWL8K_TX_QUEUES; i++) {
-- 
1.5.6.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