linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/9] update for 2.6.37
@ 2010-10-14 18:02 Wey-Yi Guy
  2010-10-14 18:02 ` [PATCH 1/9] iwlagn: need longer tx queue stuck timer for coex devices Wey-Yi Guy
                   ` (8 more replies)
  0 siblings, 9 replies; 14+ messages in thread
From: Wey-Yi Guy @ 2010-10-14 18:02 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy

We do more code cleanup to prepare for P2P support
We also do more cleanup to prepare separate the legacy and advance devices

Johannes Berg (6):
  iwlwifi: allow probe-after-rx on 2.4 GHz
  iwlwifi: rename ibss_beacon variable
  iwlwifi: clean up some beacon handling
  iwlwifi: rewrite RXON checks
  iwlwifi: blink LED in IBSS mode
  iwlagn: check beacon frame size

Wey-Yi Guy (3):
  iwlagn: need longer tx queue stuck timer for coex devices
  iwlagn: 6050 ops should be used;
  iwlwifi: move agn only eeprom functions to separate file

these patches are also available from wireless-next-2.6 branch on
 git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-2.6.git

 drivers/net/wireless/iwlwifi/Makefile         |    2 +-
 drivers/net/wireless/iwlwifi/iwl-6000.c       |   40 ++-
 drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c |  454 +++++++++++++++++++++++++
 drivers/net/wireless/iwlwifi/iwl-agn-lib.c    |   40 ++--
 drivers/net/wireless/iwlwifi/iwl-agn.c        |   39 +--
 drivers/net/wireless/iwlwifi/iwl-agn.h        |    6 +
 drivers/net/wireless/iwlwifi/iwl-core.c       |  130 ++++----
 drivers/net/wireless/iwlwifi/iwl-dev.h        |    4 +-
 drivers/net/wireless/iwlwifi/iwl-eeprom.c     |  374 +--------------------
 drivers/net/wireless/iwlwifi/iwl-eeprom.h     |    7 +-
 drivers/net/wireless/iwlwifi/iwl3945-base.c   |   42 ++--
 11 files changed, 632 insertions(+), 506 deletions(-)
 create mode 100644 drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c


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

* [PATCH 1/9] iwlagn: need longer tx queue stuck timer for coex devices
  2010-10-14 18:02 [PATCH 0/9] update for 2.6.37 Wey-Yi Guy
@ 2010-10-14 18:02 ` Wey-Yi Guy
  2010-10-15 16:44   ` Stanislaw Gruszka
  2010-10-14 18:02 ` [PATCH 2/9] iwlwifi: allow probe-after-rx on 2.4 GHz Wey-Yi Guy
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 14+ messages in thread
From: Wey-Yi Guy @ 2010-10-14 18:02 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy

For BT/WiFi combo devices, need longer tx stuck queue
timer, so those devices won't reload firmware too often.

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-6000.c |   38 ++++++++++++++++++++++++------
 drivers/net/wireless/iwlwifi/iwl-core.c |   11 +++-----
 2 files changed, 34 insertions(+), 15 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index 4810258..3eaea6f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -509,6 +509,28 @@ static struct iwl_base_params iwl6050_base_params = {
 	.sensitivity_calib_by_driver = true,
 	.chain_noise_calib_by_driver = true,
 };
+static struct iwl_base_params iwl6000_coex_base_params = {
+	.eeprom_size = OTP_LOW_IMAGE_SIZE,
+	.num_of_queues = IWLAGN_NUM_QUEUES,
+	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
+	.pll_cfg_val = 0,
+	.set_l0s = true,
+	.use_bsm = false,
+	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
+	.shadow_ram_support = true,
+	.led_compensation = 51,
+	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
+	.supports_idle = true,
+	.adv_thermal_throttle = true,
+	.support_ct_kill_exit = true,
+	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
+	.chain_noise_scale = 1000,
+	.monitor_recover_period = IWL_LONG_MONITORING_PERIOD,
+	.max_event_log_size = 512,
+	.ucode_tracing = true,
+	.sensitivity_calib_by_driver = true,
+	.chain_noise_calib_by_driver = true,
+};
 
 static struct iwl_ht_params iwl6000_ht_params = {
 	.ht_greenfield_support = true,
@@ -587,7 +609,7 @@ struct iwl_cfg iwl6000g2b_2agn_cfg = {
 	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
 	.ops = &iwl6000g2b_ops,
 	.mod_params = &iwlagn_mod_params,
-	.base_params = &iwl6000_base_params,
+	.base_params = &iwl6000_coex_base_params,
 	.bt_params = &iwl6000_bt_params,
 	.ht_params = &iwl6000_ht_params,
 	.need_dc_calib = true,
@@ -608,7 +630,7 @@ struct iwl_cfg iwl6000g2b_2abg_cfg = {
 	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
 	.ops = &iwl6000g2b_ops,
 	.mod_params = &iwlagn_mod_params,
-	.base_params = &iwl6000_base_params,
+	.base_params = &iwl6000_coex_base_params,
 	.bt_params = &iwl6000_bt_params,
 	.need_dc_calib = true,
 	.need_temp_offset_calib = true,
@@ -628,7 +650,7 @@ struct iwl_cfg iwl6000g2b_2bgn_cfg = {
 	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
 	.ops = &iwl6000g2b_ops,
 	.mod_params = &iwlagn_mod_params,
-	.base_params = &iwl6000_base_params,
+	.base_params = &iwl6000_coex_base_params,
 	.bt_params = &iwl6000_bt_params,
 	.ht_params = &iwl6000_ht_params,
 	.need_dc_calib = true,
@@ -649,7 +671,7 @@ struct iwl_cfg iwl6000g2b_2bg_cfg = {
 	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
 	.ops = &iwl6000g2b_ops,
 	.mod_params = &iwlagn_mod_params,
-	.base_params = &iwl6000_base_params,
+	.base_params = &iwl6000_coex_base_params,
 	.bt_params = &iwl6000_bt_params,
 	.need_dc_calib = true,
 	.need_temp_offset_calib = true,
@@ -669,7 +691,7 @@ struct iwl_cfg iwl6000g2b_bgn_cfg = {
 	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
 	.ops = &iwl6000g2b_ops,
 	.mod_params = &iwlagn_mod_params,
-	.base_params = &iwl6000_base_params,
+	.base_params = &iwl6000_coex_base_params,
 	.bt_params = &iwl6000_bt_params,
 	.ht_params = &iwl6000_ht_params,
 	.need_dc_calib = true,
@@ -690,7 +712,7 @@ struct iwl_cfg iwl6000g2b_bg_cfg = {
 	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
 	.ops = &iwl6000g2b_ops,
 	.mod_params = &iwlagn_mod_params,
-	.base_params = &iwl6000_base_params,
+	.base_params = &iwl6000_coex_base_params,
 	.bt_params = &iwl6000_bt_params,
 	.need_dc_calib = true,
 	.need_temp_offset_calib = true,
@@ -829,7 +851,7 @@ struct iwl_cfg iwl130_bgn_cfg = {
 	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
 	.ops = &iwl6000g2b_ops,
 	.mod_params = &iwlagn_mod_params,
-	.base_params = &iwl6000_base_params,
+	.base_params = &iwl6000_coex_base_params,
 	.bt_params = &iwl6000_bt_params,
 	.ht_params = &iwl6000_ht_params,
 	.need_dc_calib = true,
@@ -849,7 +871,7 @@ struct iwl_cfg iwl130_bg_cfg = {
 	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
 	.ops = &iwl6000g2b_ops,
 	.mod_params = &iwlagn_mod_params,
-	.base_params = &iwl6000_base_params,
+	.base_params = &iwl6000_coex_base_params,
 	.bt_params = &iwl6000_bt_params,
 	.need_dc_calib = true,
 	/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index b3efbe0..89b1827 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -2483,13 +2483,10 @@ static int iwl_check_stuck_queue(struct iwl_priv *priv, int cnt)
 					"queue %d, not read %d time\n",
 					q->id,
 					q->repeat_same_read_ptr);
-			if (priv->cfg->bt_params &&
-			    !priv->cfg->bt_params->advanced_bt_coexist) {
-				mod_timer(&priv->monitor_recover,
-					jiffies + msecs_to_jiffies(
-					IWL_ONE_HUNDRED_MSECS));
-				return 1;
-			}
+			mod_timer(&priv->monitor_recover,
+				jiffies + msecs_to_jiffies(
+				IWL_ONE_HUNDRED_MSECS));
+			return 1;
 		}
 	} else {
 		q->last_read_ptr = q->read_ptr;
-- 
1.7.0.4


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

* [PATCH 2/9] iwlwifi: allow probe-after-rx on 2.4 GHz
  2010-10-14 18:02 [PATCH 0/9] update for 2.6.37 Wey-Yi Guy
  2010-10-14 18:02 ` [PATCH 1/9] iwlagn: need longer tx queue stuck timer for coex devices Wey-Yi Guy
@ 2010-10-14 18:02 ` Wey-Yi Guy
  2010-10-14 18:02 ` [PATCH 3/9] iwlwifi: rename ibss_beacon variable Wey-Yi Guy
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: Wey-Yi Guy @ 2010-10-14 18:02 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Johannes Berg, Wey-Yi Guy

From: Johannes Berg <johannes.berg@intel.com>

There are two passive 2.4 GHz channels: 12 and 13.
If you have a hidden SSID on those, you will not
be able to connect to it because we don't send out
probe requests there. We can allow this by using
the firmware's probe-after-rx functionality on
those channels as well.

This fixes
https://bugzilla.kernel.org/show_bug.cgi?id=16462

Reported-by: Daniel J Blueman <daniel.blueman@gmail.com>
Tested-by: Daniel J Blueman <daniel.blueman@gmail.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-agn-lib.c  |   40 +++++++++++++-------------
 drivers/net/wireless/iwlwifi/iwl3945-base.c |   16 +++++-----
 2 files changed, 28 insertions(+), 28 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index c1a3898..b555edd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -1447,35 +1447,35 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
 		if (priv->cfg->bt_params &&
 		    priv->cfg->bt_params->advanced_bt_coexist)
 			scan->tx_cmd.tx_flags |= TX_CMD_FLG_IGNORE_BT;
-		scan->good_CRC_th = IWL_GOOD_CRC_TH_DISABLED;
 		break;
 	case IEEE80211_BAND_5GHZ:
 		rate = IWL_RATE_6M_PLCP;
-		/*
-		 * If active scanning is requested but a certain channel is
-		 * marked passive, we can do active scanning if we detect
-		 * transmissions.
-		 *
-		 * There is an issue with some firmware versions that triggers
-		 * a sysassert on a "good CRC threshold" of zero (== disabled),
-		 * on a radar channel even though this means that we should NOT
-		 * send probes.
-		 *
-		 * The "good CRC threshold" is the number of frames that we
-		 * need to receive during our dwell time on a channel before
-		 * sending out probes -- setting this to a huge value will
-		 * mean we never reach it, but at the same time work around
-		 * the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER
-		 * here instead of IWL_GOOD_CRC_TH_DISABLED.
-		 */
-		scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
-						IWL_GOOD_CRC_TH_NEVER;
 		break;
 	default:
 		IWL_WARN(priv, "Invalid scan band\n");
 		return -EIO;
 	}
 
+	/*
+	 * If active scanning is requested but a certain channel is
+	 * marked passive, we can do active scanning if we detect
+	 * transmissions.
+	 *
+	 * There is an issue with some firmware versions that triggers
+	 * a sysassert on a "good CRC threshold" of zero (== disabled),
+	 * on a radar channel even though this means that we should NOT
+	 * send probes.
+	 *
+	 * The "good CRC threshold" is the number of frames that we
+	 * need to receive during our dwell time on a channel before
+	 * sending out probes -- setting this to a huge value will
+	 * mean we never reach it, but at the same time work around
+	 * the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER
+	 * here instead of IWL_GOOD_CRC_TH_DISABLED.
+	 */
+	scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
+					IWL_GOOD_CRC_TH_NEVER;
+
 	band = priv->scan_band;
 
 	if (priv->cfg->scan_rx_antennas[band])
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 980c609..3ee3e55 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -2938,18 +2938,10 @@ int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
 	case IEEE80211_BAND_2GHZ:
 		scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
 		scan->tx_cmd.rate = IWL_RATE_1M_PLCP;
-		scan->good_CRC_th = 0;
 		band = IEEE80211_BAND_2GHZ;
 		break;
 	case IEEE80211_BAND_5GHZ:
 		scan->tx_cmd.rate = IWL_RATE_6M_PLCP;
-		/*
-		 * If active scaning is requested but a certain channel
-		 * is marked passive, we can do active scanning if we
-		 * detect transmissions.
-		 */
-		scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
-						IWL_GOOD_CRC_TH_DISABLED;
 		band = IEEE80211_BAND_5GHZ;
 		break;
 	default:
@@ -2957,6 +2949,14 @@ int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
 		return -EIO;
 	}
 
+	/*
+	 * If active scaning is requested but a certain channel
+	 * is marked passive, we can do active scanning if we
+	 * detect transmissions.
+	 */
+	scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
+					IWL_GOOD_CRC_TH_DISABLED;
+
 	if (!priv->is_internal_short_scan) {
 		scan->tx_cmd.len = cpu_to_le16(
 			iwl_fill_probe_req(priv,
-- 
1.7.0.4


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

* [PATCH 3/9] iwlwifi: rename ibss_beacon variable
  2010-10-14 18:02 [PATCH 0/9] update for 2.6.37 Wey-Yi Guy
  2010-10-14 18:02 ` [PATCH 1/9] iwlagn: need longer tx queue stuck timer for coex devices Wey-Yi Guy
  2010-10-14 18:02 ` [PATCH 2/9] iwlwifi: allow probe-after-rx on 2.4 GHz Wey-Yi Guy
@ 2010-10-14 18:02 ` Wey-Yi Guy
  2010-10-14 18:02 ` [PATCH 4/9] iwlwifi: clean up some beacon handling Wey-Yi Guy
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: Wey-Yi Guy @ 2010-10-14 18:02 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Johannes Berg, Wey-Yi Guy

From: Johannes Berg <johannes.berg@intel.com>

Since we're also going to support AP (GO) mode,
the variable isn't used for just IBSS beacons
any more -- rename it to not mislead readers.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-agn.c      |   26 +++++++++++++-------------
 drivers/net/wireless/iwlwifi/iwl-core.c     |   16 ++++++++--------
 drivers/net/wireless/iwlwifi/iwl-dev.h      |    4 ++--
 drivers/net/wireless/iwlwifi/iwl3945-base.c |   26 +++++++++++++-------------
 4 files changed, 36 insertions(+), 36 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 6771c40..0cc090b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -317,15 +317,15 @@ static u32 iwl_fill_beacon_frame(struct iwl_priv *priv,
 					  struct ieee80211_hdr *hdr,
 					  int left)
 {
-	if (!priv->ibss_beacon)
+	if (!priv->beacon_skb)
 		return 0;
 
-	if (priv->ibss_beacon->len > left)
+	if (priv->beacon_skb->len > left)
 		return 0;
 
-	memcpy(hdr, priv->ibss_beacon->data, priv->ibss_beacon->len);
+	memcpy(hdr, priv->beacon_skb->data, priv->beacon_skb->len);
 
-	return priv->ibss_beacon->len;
+	return priv->beacon_skb->len;
 }
 
 /* Parse the beacon frame to find the TIM element and set tim_idx & tim_size */
@@ -653,10 +653,10 @@ static void iwl_bg_beacon_update(struct work_struct *work)
 	}
 
 	/* new beacon skb is allocated every time; dispose previous.*/
-	if (priv->ibss_beacon)
-		dev_kfree_skb(priv->ibss_beacon);
+	if (priv->beacon_skb)
+		dev_kfree_skb(priv->beacon_skb);
 
-	priv->ibss_beacon = beacon;
+	priv->beacon_skb = beacon;
 
 	iwl_send_beacon_cmd(priv);
  out:
@@ -2993,9 +2993,9 @@ static void __iwl_down(struct iwl_priv *priv)
  exit:
 	memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));
 
-	if (priv->ibss_beacon)
-		dev_kfree_skb(priv->ibss_beacon);
-	priv->ibss_beacon = NULL;
+	if (priv->beacon_skb)
+		dev_kfree_skb(priv->beacon_skb);
+	priv->beacon_skb = NULL;
 
 	/* clear out any free frames */
 	iwl_clear_free_frames(priv);
@@ -4131,7 +4131,7 @@ static int iwl_init_drv(struct iwl_priv *priv)
 {
 	int ret;
 
-	priv->ibss_beacon = NULL;
+	priv->beacon_skb = NULL;
 
 	spin_lock_init(&priv->sta_lock);
 	spin_lock_init(&priv->hcmd_lock);
@@ -4645,8 +4645,8 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
 
 	iwl_free_isr_ict(priv);
 
-	if (priv->ibss_beacon)
-		dev_kfree_skb(priv->ibss_beacon);
+	if (priv->beacon_skb)
+		dev_kfree_skb(priv->beacon_skb);
 
 	ieee80211_free_hw(priv->hw);
 }
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 89b1827..09a4d17 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1552,10 +1552,10 @@ static void iwlcore_beacon_update(struct ieee80211_hw *hw,
 
 	spin_lock_irqsave(&priv->lock, flags);
 
-	if (priv->ibss_beacon)
-		dev_kfree_skb(priv->ibss_beacon);
+	if (priv->beacon_skb)
+		dev_kfree_skb(priv->beacon_skb);
 
-	priv->ibss_beacon = skb;
+	priv->beacon_skb = skb;
 
 	timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
 	priv->timestamp = le64_to_cpu(timestamp);
@@ -1610,8 +1610,8 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
 	}
 
 	if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_AP) {
-		dev_kfree_skb(priv->ibss_beacon);
-		priv->ibss_beacon = ieee80211_beacon_get(hw, vif);
+		dev_kfree_skb(priv->beacon_skb);
+		priv->beacon_skb = ieee80211_beacon_get(hw, vif);
 	}
 
 	if (changes & BSS_CHANGED_BEACON_INT && vif->type == NL80211_IFTYPE_AP)
@@ -2060,10 +2060,10 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
 	spin_lock_irqsave(&priv->lock, flags);
 
 	/* new association get rid of ibss beacon skb */
-	if (priv->ibss_beacon)
-		dev_kfree_skb(priv->ibss_beacon);
+	if (priv->beacon_skb)
+		dev_kfree_skb(priv->beacon_skb);
 
-	priv->ibss_beacon = NULL;
+	priv->beacon_skb = NULL;
 
 	priv->timestamp = 0;
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index de43e13..70e07fa 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1383,8 +1383,6 @@ struct iwl_priv {
 
 	enum nl80211_iftype iw_mode;
 
-	struct sk_buff *ibss_beacon;
-
 	/* Last Rx'd beacon timestamp */
 	u64 timestamp;
 
@@ -1496,8 +1494,10 @@ struct iwl_priv {
 	struct work_struct scan_completed;
 	struct work_struct rx_replenish;
 	struct work_struct abort_scan;
+
 	struct work_struct beacon_update;
 	struct iwl_rxon_context *beacon_ctx;
+	struct sk_buff *beacon_skb;
 
 	struct work_struct tt_work;
 	struct work_struct ct_enter;
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 3ee3e55..8f8c4b7 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -317,15 +317,15 @@ unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv,
 				int left)
 {
 
-	if (!iwl_is_associated(priv, IWL_RXON_CTX_BSS) || !priv->ibss_beacon)
+	if (!iwl_is_associated(priv, IWL_RXON_CTX_BSS) || !priv->beacon_skb)
 		return 0;
 
-	if (priv->ibss_beacon->len > left)
+	if (priv->beacon_skb->len > left)
 		return 0;
 
-	memcpy(hdr, priv->ibss_beacon->data, priv->ibss_beacon->len);
+	memcpy(hdr, priv->beacon_skb->data, priv->beacon_skb->len);
 
-	return priv->ibss_beacon->len;
+	return priv->beacon_skb->len;
 }
 
 static int iwl3945_send_beacon_cmd(struct iwl_priv *priv)
@@ -813,10 +813,10 @@ static void iwl3945_bg_beacon_update(struct work_struct *work)
 
 	mutex_lock(&priv->mutex);
 	/* new beacon skb is allocated every time; dispose previous.*/
-	if (priv->ibss_beacon)
-		dev_kfree_skb(priv->ibss_beacon);
+	if (priv->beacon_skb)
+		dev_kfree_skb(priv->beacon_skb);
 
-	priv->ibss_beacon = beacon;
+	priv->beacon_skb = beacon;
 	mutex_unlock(&priv->mutex);
 
 	iwl3945_send_beacon_cmd(priv);
@@ -2642,9 +2642,9 @@ static void __iwl3945_down(struct iwl_priv *priv)
  exit:
 	memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));
 
-	if (priv->ibss_beacon)
-		dev_kfree_skb(priv->ibss_beacon);
-	priv->ibss_beacon = NULL;
+	if (priv->beacon_skb)
+		dev_kfree_skb(priv->beacon_skb);
+	priv->beacon_skb = NULL;
 
 	/* clear out any free frames */
 	iwl3945_clear_free_frames(priv);
@@ -3848,7 +3848,7 @@ static int iwl3945_init_drv(struct iwl_priv *priv)
 	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
 
 	priv->retry_rate = 1;
-	priv->ibss_beacon = NULL;
+	priv->beacon_skb = NULL;
 
 	spin_lock_init(&priv->sta_lock);
 	spin_lock_init(&priv->hcmd_lock);
@@ -4256,8 +4256,8 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
 	iwl_free_channel_map(priv);
 	iwlcore_free_geos(priv);
 	kfree(priv->scan_cmd);
-	if (priv->ibss_beacon)
-		dev_kfree_skb(priv->ibss_beacon);
+	if (priv->beacon_skb)
+		dev_kfree_skb(priv->beacon_skb);
 
 	ieee80211_free_hw(priv->hw);
 }
-- 
1.7.0.4


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

* [PATCH 4/9] iwlwifi: clean up some beacon handling
  2010-10-14 18:02 [PATCH 0/9] update for 2.6.37 Wey-Yi Guy
                   ` (2 preceding siblings ...)
  2010-10-14 18:02 ` [PATCH 3/9] iwlwifi: rename ibss_beacon variable Wey-Yi Guy
@ 2010-10-14 18:02 ` Wey-Yi Guy
  2010-10-14 18:02 ` [PATCH 5/9] iwlagn: 6050 ops should be used; Wey-Yi Guy
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: Wey-Yi Guy @ 2010-10-14 18:02 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Johannes Berg, Wey-Yi Guy

From: Johannes Berg <johannes.berg@intel.com>

There's no need to check for NULL before
calling dev_kfree_skb() since it is valid
to call it on NULL -- it becomes a no-op.

There's also no need to initialise the
beacon_skb variable to NULL just after
the memory it is in has been kzalloc'ed.

Some minor whitespace cleanups, and a
lock assertion in a function that needs
the mutex (to access the beacon_skb var)
complete the patch.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-agn.c |   25 +++++++++++--------------
 1 files changed, 11 insertions(+), 14 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 0cc090b..7079efb 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -314,9 +314,11 @@ static void iwl_free_frame(struct iwl_priv *priv, struct iwl_frame *frame)
 }
 
 static u32 iwl_fill_beacon_frame(struct iwl_priv *priv,
-					  struct ieee80211_hdr *hdr,
-					  int left)
+				 struct ieee80211_hdr *hdr,
+				 int left)
 {
+	lockdep_assert_held(&priv->mutex);
+
 	if (!priv->beacon_skb)
 		return 0;
 
@@ -330,8 +332,8 @@ static u32 iwl_fill_beacon_frame(struct iwl_priv *priv,
 
 /* Parse the beacon frame to find the TIM element and set tim_idx & tim_size */
 static void iwl_set_beacon_tim(struct iwl_priv *priv,
-		struct iwl_tx_beacon_cmd *tx_beacon_cmd,
-		u8 *beacon, u32 frame_size)
+			       struct iwl_tx_beacon_cmd *tx_beacon_cmd,
+			       u8 *beacon, u32 frame_size)
 {
 	u16 tim_idx;
 	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)beacon;
@@ -393,7 +395,7 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
 
 	/* Set up TX beacon command fields */
 	iwl_set_beacon_tim(priv, tx_beacon_cmd, (u8 *)tx_beacon_cmd->frame,
-			frame_size);
+			   frame_size);
 
 	/* Set up packet rate and flags */
 	rate = iwl_rate_get_lowest_plcp(priv, priv->beacon_ctx);
@@ -648,13 +650,12 @@ static void iwl_bg_beacon_update(struct work_struct *work)
 	/* Pull updated AP beacon from mac80211. will fail if not in AP mode */
 	beacon = ieee80211_beacon_get(priv->hw, priv->beacon_ctx->vif);
 	if (!beacon) {
-		IWL_ERR(priv, "update beacon failed\n");
+		IWL_ERR(priv, "update beacon failed -- keeping old\n");
 		goto out;
 	}
 
 	/* new beacon skb is allocated every time; dispose previous.*/
-	if (priv->beacon_skb)
-		dev_kfree_skb(priv->beacon_skb);
+	dev_kfree_skb(priv->beacon_skb);
 
 	priv->beacon_skb = beacon;
 
@@ -2993,8 +2994,7 @@ static void __iwl_down(struct iwl_priv *priv)
  exit:
 	memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));
 
-	if (priv->beacon_skb)
-		dev_kfree_skb(priv->beacon_skb);
+	dev_kfree_skb(priv->beacon_skb);
 	priv->beacon_skb = NULL;
 
 	/* clear out any free frames */
@@ -4131,8 +4131,6 @@ static int iwl_init_drv(struct iwl_priv *priv)
 {
 	int ret;
 
-	priv->beacon_skb = NULL;
-
 	spin_lock_init(&priv->sta_lock);
 	spin_lock_init(&priv->hcmd_lock);
 
@@ -4645,8 +4643,7 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
 
 	iwl_free_isr_ict(priv);
 
-	if (priv->beacon_skb)
-		dev_kfree_skb(priv->beacon_skb);
+	dev_kfree_skb(priv->beacon_skb);
 
 	ieee80211_free_hw(priv->hw);
 }
-- 
1.7.0.4


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

* [PATCH 5/9] iwlagn: 6050 ops should be used;
  2010-10-14 18:02 [PATCH 0/9] update for 2.6.37 Wey-Yi Guy
                   ` (3 preceding siblings ...)
  2010-10-14 18:02 ` [PATCH 4/9] iwlwifi: clean up some beacon handling Wey-Yi Guy
@ 2010-10-14 18:02 ` Wey-Yi Guy
  2010-10-14 18:02 ` [PATCH 6/9] iwlwifi: rewrite RXON checks Wey-Yi Guy
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: Wey-Yi Guy @ 2010-10-14 18:02 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy

For 6050 series of devices, 6050 ops should be used;
One of the 6050 config still use 6000 ops, fix it.

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

diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index 3eaea6f..11e6532 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -780,7 +780,7 @@ struct iwl_cfg iwl6050_2agn_cfg = {
 	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
 	.valid_tx_ant = ANT_AB,
 	.valid_rx_ant = ANT_AB,
-	.ops = &iwl6000_ops,
+	.ops = &iwl6050_ops,
 	.eeprom_ver = EEPROM_6050_EEPROM_VERSION,
 	.eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION,
 	.mod_params = &iwlagn_mod_params,
-- 
1.7.0.4


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

* [PATCH 6/9] iwlwifi: rewrite RXON checks
  2010-10-14 18:02 [PATCH 0/9] update for 2.6.37 Wey-Yi Guy
                   ` (4 preceding siblings ...)
  2010-10-14 18:02 ` [PATCH 5/9] iwlagn: 6050 ops should be used; Wey-Yi Guy
@ 2010-10-14 18:02 ` Wey-Yi Guy
  2010-10-14 18:02 ` [PATCH 7/9] iwlwifi: blink LED in IBSS mode Wey-Yi Guy
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 14+ messages in thread
From: Wey-Yi Guy @ 2010-10-14 18:02 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

The RXON checking is a bit magical, and prints
out too much information if something goes wrong.
Make it less magical and print out only the items
that were actually wrong.

Also remove the comment about removing it -- the
driver is constantly changing so these checks are
useful.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-core.c |  100 +++++++++++++++----------------
 1 files changed, 49 insertions(+), 51 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 09a4d17..ecf5c9b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -510,76 +510,74 @@ void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
 }
 EXPORT_SYMBOL(iwl_set_rxon_hwcrypto);
 
-/**
- * iwl_check_rxon_cmd - validate RXON structure is valid
- *
- * NOTE:  This is really only useful during development and can eventually
- * be #ifdef'd out once the driver is stable and folks aren't actively
- * making changes
- */
+/* validate RXON structure is valid */
 int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
 {
-	int error = 0;
-	int counter = 1;
 	struct iwl_rxon_cmd *rxon = &ctx->staging;
+	bool error = false;
 
 	if (rxon->flags & RXON_FLG_BAND_24G_MSK) {
-		error |= le32_to_cpu(rxon->flags &
-				(RXON_FLG_TGJ_NARROW_BAND_MSK |
-				 RXON_FLG_RADAR_DETECT_MSK));
-		if (error)
-			IWL_WARN(priv, "check 24G fields %d | %d\n",
-				    counter++, error);
+		if (rxon->flags & RXON_FLG_TGJ_NARROW_BAND_MSK) {
+			IWL_WARN(priv, "check 2.4G: wrong narrow\n");
+			error = true;
+		}
+		if (rxon->flags & RXON_FLG_RADAR_DETECT_MSK) {
+			IWL_WARN(priv, "check 2.4G: wrong radar\n");
+			error = true;
+		}
 	} else {
-		error |= (rxon->flags & RXON_FLG_SHORT_SLOT_MSK) ?
-				0 : le32_to_cpu(RXON_FLG_SHORT_SLOT_MSK);
-		if (error)
-			IWL_WARN(priv, "check 52 fields %d | %d\n",
-				    counter++, error);
-		error |= le32_to_cpu(rxon->flags & RXON_FLG_CCK_MSK);
-		if (error)
-			IWL_WARN(priv, "check 52 CCK %d | %d\n",
-				    counter++, error);
-	}
-	error |= (rxon->node_addr[0] | rxon->bssid_addr[0]) & 0x1;
-	if (error)
-		IWL_WARN(priv, "check mac addr %d | %d\n", counter++, error);
+		if (!(rxon->flags & RXON_FLG_SHORT_SLOT_MSK)) {
+			IWL_WARN(priv, "check 5.2G: not short slot!\n");
+			error = true;
+		}
+		if (rxon->flags & RXON_FLG_CCK_MSK) {
+			IWL_WARN(priv, "check 5.2G: CCK!\n");
+			error = true;
+		}
+	}
+	if ((rxon->node_addr[0] | rxon->bssid_addr[0]) & 0x1) {
+		IWL_WARN(priv, "mac/bssid mcast!\n");
+		error = true;
+	}
 
 	/* make sure basic rates 6Mbps and 1Mbps are supported */
-	error |= (((rxon->ofdm_basic_rates & IWL_RATE_6M_MASK) == 0) &&
-		  ((rxon->cck_basic_rates & IWL_RATE_1M_MASK) == 0));
-	if (error)
-		IWL_WARN(priv, "check basic rate %d | %d\n", counter++, error);
+	if ((rxon->ofdm_basic_rates & IWL_RATE_6M_MASK) == 0 &&
+	    (rxon->cck_basic_rates & IWL_RATE_1M_MASK) == 0) {
+		IWL_WARN(priv, "neither 1 nor 6 are basic\n");
+		error = true;
+	}
 
-	error |= (le16_to_cpu(rxon->assoc_id) > 2007);
-	if (error)
-		IWL_WARN(priv, "check assoc id %d | %d\n", counter++, error);
+	if (le16_to_cpu(rxon->assoc_id) > 2007) {
+		IWL_WARN(priv, "aid > 2007\n");
+		error = true;
+	}
 
-	error |= ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK))
-			== (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK));
-	if (error)
-		IWL_WARN(priv, "check CCK and short slot %d | %d\n",
-			    counter++, error);
+	if ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK))
+			== (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)) {
+		IWL_WARN(priv, "CCK and short slot\n");
+		error = true;
+	}
 
-	error |= ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK))
-			== (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK));
-	if (error)
-		IWL_WARN(priv, "check CCK & auto detect %d | %d\n",
-			    counter++, error);
+	if ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK))
+			== (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) {
+		IWL_WARN(priv, "CCK and auto detect");
+		error = true;
+	}
 
-	error |= ((rxon->flags & (RXON_FLG_AUTO_DETECT_MSK |
-			RXON_FLG_TGG_PROTECT_MSK)) == RXON_FLG_TGG_PROTECT_MSK);
-	if (error)
-		IWL_WARN(priv, "check TGG and auto detect %d | %d\n",
-			    counter++, error);
+	if ((rxon->flags & (RXON_FLG_AUTO_DETECT_MSK |
+			    RXON_FLG_TGG_PROTECT_MSK)) ==
+			    RXON_FLG_TGG_PROTECT_MSK) {
+		IWL_WARN(priv, "TGg but no auto-detect\n");
+		error = true;
+	}
 
 	if (error)
 		IWL_WARN(priv, "Tuning to channel %d\n",
 			    le16_to_cpu(rxon->channel));
 
 	if (error) {
-		IWL_ERR(priv, "Not a valid iwl_rxon_assoc_cmd field values\n");
-		return -1;
+		IWL_ERR(priv, "Invalid RXON\n");
+		return -EINVAL;
 	}
 	return 0;
 }
-- 
1.7.0.4


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

* [PATCH 7/9] iwlwifi: blink LED in IBSS mode
  2010-10-14 18:02 [PATCH 0/9] update for 2.6.37 Wey-Yi Guy
                   ` (5 preceding siblings ...)
  2010-10-14 18:02 ` [PATCH 6/9] iwlwifi: rewrite RXON checks Wey-Yi Guy
@ 2010-10-14 18:02 ` Wey-Yi Guy
  2010-10-14 18:02 ` [PATCH 8/9] iwlagn: check beacon frame size Wey-Yi Guy
  2010-10-14 18:02 ` [PATCH 9/9] iwlwifi: move agn only eeprom functions to separate file Wey-Yi Guy
  8 siblings, 0 replies; 14+ messages in thread
From: Wey-Yi Guy @ 2010-10-14 18:02 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Johannes Berg, Wey-Yi Guy

From: Johannes Berg <johannes.berg@intel.com>

We recently found that contrary to expectations,
the LED is not blinking in IBSS mode. Fix this.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-core.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index ecf5c9b..25fb391 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1727,6 +1727,7 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
 			memcpy(ctx->staging.bssid_addr,
 			       bss_conf->bssid, ETH_ALEN);
 			memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
+			iwl_led_associate(priv);
 			iwlcore_config_ap(priv, vif);
 		} else
 			iwl_set_no_assoc(priv, vif);
-- 
1.7.0.4


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

* [PATCH 8/9] iwlagn: check beacon frame size
  2010-10-14 18:02 [PATCH 0/9] update for 2.6.37 Wey-Yi Guy
                   ` (6 preceding siblings ...)
  2010-10-14 18:02 ` [PATCH 7/9] iwlwifi: blink LED in IBSS mode Wey-Yi Guy
@ 2010-10-14 18:02 ` Wey-Yi Guy
  2010-10-14 18:02 ` [PATCH 9/9] iwlwifi: move agn only eeprom functions to separate file Wey-Yi Guy
  8 siblings, 0 replies; 14+ messages in thread
From: Wey-Yi Guy @ 2010-10-14 18:02 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Johannes Berg, Wey-Yi Guy

From: Johannes Berg <johannes.berg@intel.com>

When the beacon_skb is NULL, we might still
attempt to use it in this code path (if we
ever get here) -- make the code a bit more
defensive and check the return value of
iwl_fill_beacon_frame() against zero.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-agn.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 7079efb..c2636a7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -385,6 +385,8 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
 				sizeof(frame->u) - sizeof(*tx_beacon_cmd));
 	if (WARN_ON_ONCE(frame_size > MAX_MPDU_SIZE))
 		return 0;
+	if (!frame_size)
+		return 0;
 
 	/* Set up TX command fields */
 	tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size);
-- 
1.7.0.4


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

* [PATCH 9/9] iwlwifi: move agn only eeprom functions to separate file
  2010-10-14 18:02 [PATCH 0/9] update for 2.6.37 Wey-Yi Guy
                   ` (7 preceding siblings ...)
  2010-10-14 18:02 ` [PATCH 8/9] iwlagn: check beacon frame size Wey-Yi Guy
@ 2010-10-14 18:02 ` Wey-Yi Guy
  8 siblings, 0 replies; 14+ messages in thread
From: Wey-Yi Guy @ 2010-10-14 18:02 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy

Some of the functions in iwl-eeprom.c file are for agn devices only,
Those functions do not have to be part of iwlcore.ko, so move those
to iwl-agn-eeprom.c file.

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
---
 drivers/net/wireless/iwlwifi/Makefile         |    2 +-
 drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c |  454 +++++++++++++++++++++++++
 drivers/net/wireless/iwlwifi/iwl-agn.h        |    6 +
 drivers/net/wireless/iwlwifi/iwl-eeprom.c     |  374 +--------------------
 drivers/net/wireless/iwlwifi/iwl-eeprom.h     |    7 +-
 5 files changed, 476 insertions(+), 367 deletions(-)
 create mode 100644 drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c

diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile
index b4b24b6..63edbe2 100644
--- a/drivers/net/wireless/iwlwifi/Makefile
+++ b/drivers/net/wireless/iwlwifi/Makefile
@@ -12,7 +12,7 @@ obj-$(CONFIG_IWLAGN)	+= iwlagn.o
 iwlagn-objs		:= iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o
 iwlagn-objs		+= iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o
 iwlagn-objs		+= iwl-agn-lib.o iwl-agn-rx.o iwl-agn-calib.o
-iwlagn-objs		+= iwl-agn-tt.o iwl-agn-sta.o
+iwlagn-objs		+= iwl-agn-tt.o iwl-agn-sta.o iwl-agn-eeprom.o
 iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o
 
 iwlagn-$(CONFIG_IWL4965) += iwl-4965.o
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c
new file mode 100644
index 0000000..a650bab
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c
@@ -0,0 +1,454 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+
+#include <net/mac80211.h>
+
+#include "iwl-commands.h"
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-debug.h"
+#include "iwl-agn.h"
+#include "iwl-io.h"
+
+/************************** EEPROM BANDS ****************************
+ *
+ * The iwl_eeprom_band definitions below provide the mapping from the
+ * EEPROM contents to the specific channel number supported for each
+ * band.
+ *
+ * For example, iwl_priv->eeprom.band_3_channels[4] from the band_3
+ * definition below maps to physical channel 42 in the 5.2GHz spectrum.
+ * The specific geography and calibration information for that channel
+ * is contained in the eeprom map itself.
+ *
+ * During init, we copy the eeprom information and channel map
+ * information into priv->channel_info_24/52 and priv->channel_map_24/52
+ *
+ * channel_map_24/52 provides the index in the channel_info array for a
+ * given channel.  We have to have two separate maps as there is channel
+ * overlap with the 2.4GHz and 5.2GHz spectrum as seen in band_1 and
+ * band_2
+ *
+ * A value of 0xff stored in the channel_map indicates that the channel
+ * is not supported by the hardware at all.
+ *
+ * A value of 0xfe in the channel_map indicates that the channel is not
+ * valid for Tx with the current hardware.  This means that
+ * while the system can tune and receive on a given channel, it may not
+ * be able to associate or transmit any frames on that
+ * channel.  There is no corresponding channel information for that
+ * entry.
+ *
+ *********************************************************************/
+
+/**
+ * struct iwl_txpwr_section: eeprom section information
+ * @offset: indirect address into eeprom image
+ * @count: number of "struct iwl_eeprom_enhanced_txpwr" in this section
+ * @band: band type for the section
+ * @is_common - true: common section, false: channel section
+ * @is_cck - true: cck section, false: not cck section
+ * @is_ht_40 - true: all channel in the section are HT40 channel,
+ *	       false: legacy or HT 20 MHz
+ *	       ignore if it is common section
+ * @iwl_eeprom_section_channel: channel array in the section,
+ *	       ignore if common section
+ */
+struct iwl_txpwr_section {
+	u32 offset;
+	u8 count;
+	enum ieee80211_band band;
+	bool is_common;
+	bool is_cck;
+	bool is_ht40;
+	u8 iwl_eeprom_section_channel[EEPROM_MAX_TXPOWER_SECTION_ELEMENTS];
+};
+
+/**
+ * section 1 - 3 are regulatory tx power apply to all channels based on
+ *    modulation: CCK, OFDM
+ *    Band: 2.4GHz, 5.2GHz
+ * section 4 - 10 are regulatory tx power apply to specified channels
+ *    For example:
+ *	1L - Channel 1 Legacy
+ *	1HT - Channel 1 HT
+ *	(1,+1) - Channel 1 HT40 "_above_"
+ *
+ * Section 1: all CCK channels
+ * Section 2: all 2.4 GHz OFDM (Legacy, HT and HT40) channels
+ * Section 3: all 5.2 GHz OFDM (Legacy, HT and HT40) channels
+ * Section 4: 2.4 GHz 20MHz channels: 1L, 1HT, 2L, 2HT, 10L, 10HT, 11L, 11HT
+ * Section 5: 2.4 GHz 40MHz channels: (1,+1) (2,+1) (6,+1) (7,+1) (9,+1)
+ * Section 6: 5.2 GHz 20MHz channels: 36L, 64L, 100L, 36HT, 64HT, 100HT
+ * Section 7: 5.2 GHz 40MHz channels: (36,+1) (60,+1) (100,+1)
+ * Section 8: 2.4 GHz channel: 13L, 13HT
+ * Section 9: 2.4 GHz channel: 140L, 140HT
+ * Section 10: 2.4 GHz 40MHz channels: (132,+1)  (44,+1)
+ *
+ */
+static const struct iwl_txpwr_section enhinfo[] = {
+	{ EEPROM_LB_CCK_20_COMMON, 1, IEEE80211_BAND_2GHZ, true, true, false },
+	{ EEPROM_LB_OFDM_COMMON, 3, IEEE80211_BAND_2GHZ, true, false, false },
+	{ EEPROM_HB_OFDM_COMMON, 3, IEEE80211_BAND_5GHZ, true, false, false },
+	{ EEPROM_LB_OFDM_20_BAND, 8, IEEE80211_BAND_2GHZ,
+		false, false, false,
+		{1, 1, 2, 2, 10, 10, 11, 11 } },
+	{ EEPROM_LB_OFDM_HT40_BAND, 5, IEEE80211_BAND_2GHZ,
+		false, false, true,
+		{ 1, 2, 6, 7, 9 } },
+	{ EEPROM_HB_OFDM_20_BAND, 6, IEEE80211_BAND_5GHZ,
+		false, false, false,
+		{ 36, 64, 100, 36, 64, 100 } },
+	{ EEPROM_HB_OFDM_HT40_BAND, 3, IEEE80211_BAND_5GHZ,
+		false, false, true,
+		{ 36, 60, 100 } },
+	{ EEPROM_LB_OFDM_20_CHANNEL_13, 2, IEEE80211_BAND_2GHZ,
+		false, false, false,
+		{ 13, 13 } },
+	{ EEPROM_HB_OFDM_20_CHANNEL_140, 2, IEEE80211_BAND_5GHZ,
+		false, false, false,
+		{ 140, 140 } },
+	{ EEPROM_HB_OFDM_HT40_BAND_1, 2, IEEE80211_BAND_5GHZ,
+		false, false, true,
+		{ 132, 44 } },
+};
+
+/******************************************************************************
+ *
+ * EEPROM related functions
+ *
+******************************************************************************/
+
+/*
+ * The device's EEPROM semaphore prevents conflicts between driver and uCode
+ * when accessing the EEPROM; each access is a series of pulses to/from the
+ * EEPROM chip, not a single event, so even reads could conflict if they
+ * weren't arbitrated by the semaphore.
+ */
+int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv)
+{
+	u16 count;
+	int ret;
+
+	for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) {
+		/* Request semaphore */
+		iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+			    CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
+
+		/* See if we got it */
+		ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG,
+				CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
+				CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
+				EEPROM_SEM_TIMEOUT);
+		if (ret >= 0) {
+			IWL_DEBUG_IO(priv,
+				"Acquired semaphore after %d tries.\n",
+				count+1);
+			return ret;
+		}
+	}
+
+	return ret;
+}
+
+void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv)
+{
+	iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG,
+		CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
+
+}
+
+int iwl_eeprom_check_version(struct iwl_priv *priv)
+{
+	u16 eeprom_ver;
+	u16 calib_ver;
+
+	eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
+	calib_ver = priv->cfg->ops->lib->eeprom_ops.calib_version(priv);
+
+	if (eeprom_ver < priv->cfg->eeprom_ver ||
+	    calib_ver < priv->cfg->eeprom_calib_ver)
+		goto err;
+
+	IWL_INFO(priv, "device EEPROM VER=0x%x, CALIB=0x%x\n",
+		 eeprom_ver, calib_ver);
+
+	return 0;
+err:
+	IWL_ERR(priv, "Unsupported (too old) EEPROM VER=0x%x < 0x%x "
+		  "CALIB=0x%x < 0x%x\n",
+		  eeprom_ver, priv->cfg->eeprom_ver,
+		  calib_ver,  priv->cfg->eeprom_calib_ver);
+	return -EINVAL;
+
+}
+
+void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac)
+{
+	const u8 *addr = priv->cfg->ops->lib->eeprom_ops.query_addr(priv,
+					EEPROM_MAC_ADDRESS);
+	memcpy(mac, addr, ETH_ALEN);
+}
+
+/**
+ * iwl_get_max_txpower_avg - get the highest tx power from all chains.
+ *     find the highest tx power from all chains for the channel
+ */
+static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv,
+		struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
+		int element, s8 *max_txpower_in_half_dbm)
+{
+	s8 max_txpower_avg = 0; /* (dBm) */
+
+	IWL_DEBUG_INFO(priv, "%d - "
+			"chain_a: %d dB chain_b: %d dB "
+			"chain_c: %d dB mimo2: %d dB mimo3: %d dB\n",
+			element,
+			enhanced_txpower[element].chain_a_max >> 1,
+			enhanced_txpower[element].chain_b_max >> 1,
+			enhanced_txpower[element].chain_c_max >> 1,
+			enhanced_txpower[element].mimo2_max >> 1,
+			enhanced_txpower[element].mimo3_max >> 1);
+	/* Take the highest tx power from any valid chains */
+	if ((priv->cfg->valid_tx_ant & ANT_A) &&
+	    (enhanced_txpower[element].chain_a_max > max_txpower_avg))
+		max_txpower_avg = enhanced_txpower[element].chain_a_max;
+	if ((priv->cfg->valid_tx_ant & ANT_B) &&
+	    (enhanced_txpower[element].chain_b_max > max_txpower_avg))
+		max_txpower_avg = enhanced_txpower[element].chain_b_max;
+	if ((priv->cfg->valid_tx_ant & ANT_C) &&
+	    (enhanced_txpower[element].chain_c_max > max_txpower_avg))
+		max_txpower_avg = enhanced_txpower[element].chain_c_max;
+	if (((priv->cfg->valid_tx_ant == ANT_AB) |
+	    (priv->cfg->valid_tx_ant == ANT_BC) |
+	    (priv->cfg->valid_tx_ant == ANT_AC)) &&
+	    (enhanced_txpower[element].mimo2_max > max_txpower_avg))
+		max_txpower_avg =  enhanced_txpower[element].mimo2_max;
+	if ((priv->cfg->valid_tx_ant == ANT_ABC) &&
+	    (enhanced_txpower[element].mimo3_max > max_txpower_avg))
+		max_txpower_avg = enhanced_txpower[element].mimo3_max;
+
+	/*
+	 * max. tx power in EEPROM is in 1/2 dBm format
+	 * convert from 1/2 dBm to dBm (round-up convert)
+	 * but we also do not want to loss 1/2 dBm resolution which
+	 * will impact performance
+	 */
+	*max_txpower_in_half_dbm = max_txpower_avg;
+	return (max_txpower_avg & 0x01) + (max_txpower_avg >> 1);
+}
+
+/**
+ * iwl_update_common_txpower: update channel tx power
+ *     update tx power per band based on EEPROM enhanced tx power info.
+ */
+static s8 iwl_update_common_txpower(struct iwl_priv *priv,
+		struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
+		int section, int element, s8 *max_txpower_in_half_dbm)
+{
+	struct iwl_channel_info *ch_info;
+	int ch;
+	bool is_ht40 = false;
+	s8 max_txpower_avg; /* (dBm) */
+
+	/* it is common section, contain all type (Legacy, HT and HT40)
+	 * based on the element in the section to determine
+	 * is it HT 40 or not
+	 */
+	if (element == EEPROM_TXPOWER_COMMON_HT40_INDEX)
+		is_ht40 = true;
+	max_txpower_avg =
+		iwl_get_max_txpower_avg(priv, enhanced_txpower,
+					element, max_txpower_in_half_dbm);
+
+	ch_info = priv->channel_info;
+
+	for (ch = 0; ch < priv->channel_count; ch++) {
+		/* find matching band and update tx power if needed */
+		if ((ch_info->band == enhinfo[section].band) &&
+		    (ch_info->max_power_avg < max_txpower_avg) &&
+		    (!is_ht40)) {
+			/* Update regulatory-based run-time data */
+			ch_info->max_power_avg = ch_info->curr_txpow =
+				max_txpower_avg;
+			ch_info->scan_power = max_txpower_avg;
+		}
+		if ((ch_info->band == enhinfo[section].band) && is_ht40 &&
+		    (ch_info->ht40_max_power_avg < max_txpower_avg)) {
+			/* Update regulatory-based run-time data */
+			ch_info->ht40_max_power_avg = max_txpower_avg;
+		}
+		ch_info++;
+	}
+	return max_txpower_avg;
+}
+
+/**
+ * iwl_update_channel_txpower: update channel tx power
+ *      update channel tx power based on EEPROM enhanced tx power info.
+ */
+static s8 iwl_update_channel_txpower(struct iwl_priv *priv,
+		struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
+		int section, int element, s8 *max_txpower_in_half_dbm)
+{
+	struct iwl_channel_info *ch_info;
+	int ch;
+	u8 channel;
+	s8 max_txpower_avg; /* (dBm) */
+
+	channel = enhinfo[section].iwl_eeprom_section_channel[element];
+	max_txpower_avg =
+		iwl_get_max_txpower_avg(priv, enhanced_txpower,
+					element, max_txpower_in_half_dbm);
+
+	ch_info = priv->channel_info;
+	for (ch = 0; ch < priv->channel_count; ch++) {
+		/* find matching channel and update tx power if needed */
+		if (ch_info->channel == channel) {
+			if ((ch_info->max_power_avg < max_txpower_avg) &&
+			    (!enhinfo[section].is_ht40)) {
+				/* Update regulatory-based run-time data */
+				ch_info->max_power_avg = max_txpower_avg;
+				ch_info->curr_txpow = max_txpower_avg;
+				ch_info->scan_power = max_txpower_avg;
+			}
+			if ((enhinfo[section].is_ht40) &&
+			    (ch_info->ht40_max_power_avg < max_txpower_avg)) {
+				/* Update regulatory-based run-time data */
+				ch_info->ht40_max_power_avg = max_txpower_avg;
+			}
+			break;
+		}
+		ch_info++;
+	}
+	return max_txpower_avg;
+}
+
+/**
+ * iwlcore_eeprom_enhanced_txpower: process enhanced tx power info
+ */
+void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv)
+{
+	int eeprom_section_count = 0;
+	int section, element;
+	struct iwl_eeprom_enhanced_txpwr *enhanced_txpower;
+	u32 offset;
+	s8 max_txpower_avg; /* (dBm) */
+	s8 max_txpower_in_half_dbm; /* (half-dBm) */
+
+	/* Loop through all the sections
+	 * adjust bands and channel's max tx power
+	 * Set the tx_power_user_lmt to the highest power
+	 * supported by any channels and chains
+	 */
+	for (section = 0; section < ARRAY_SIZE(enhinfo); section++) {
+		eeprom_section_count = enhinfo[section].count;
+		offset = enhinfo[section].offset;
+		enhanced_txpower = (struct iwl_eeprom_enhanced_txpwr *)
+				iwl_eeprom_query_addr(priv, offset);
+
+		/*
+		 * check for valid entry -
+		 * different version of EEPROM might contain different set
+		 * of enhanced tx power table
+		 * always check for valid entry before process
+		 * the information
+		 */
+		if (!enhanced_txpower->common || enhanced_txpower->reserved)
+			continue;
+
+		for (element = 0; element < eeprom_section_count; element++) {
+			if (enhinfo[section].is_common)
+				max_txpower_avg =
+					iwl_update_common_txpower(priv,
+						enhanced_txpower, section,
+						element,
+						&max_txpower_in_half_dbm);
+			else
+				max_txpower_avg =
+					iwl_update_channel_txpower(priv,
+						enhanced_txpower, section,
+						element,
+						&max_txpower_in_half_dbm);
+
+			/* Update the tx_power_user_lmt to the highest power
+			 * supported by any channel */
+			if (max_txpower_avg > priv->tx_power_user_lmt)
+				priv->tx_power_user_lmt = max_txpower_avg;
+
+			/*
+			 * Update the tx_power_lmt_in_half_dbm to
+			 * the highest power supported by any channel
+			 */
+			if (max_txpower_in_half_dbm >
+			    priv->tx_power_lmt_in_half_dbm)
+				priv->tx_power_lmt_in_half_dbm =
+					max_txpower_in_half_dbm;
+		}
+	}
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h
index b4deef4..f525d55 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.h
@@ -312,4 +312,10 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags)
 	return cpu_to_le32(flags|(u32)rate);
 }
 
+/* eeprom */
+void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv);
+void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac);
+int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv);
+void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv);
+
 #endif /* __iwl_agn_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
index 66eccb1..87cd10f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -136,78 +136,6 @@ static const u8 iwl_eeprom_band_7[] = {       /* 5.2 ht40 channel */
 	36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157
 };
 
-/**
- * struct iwl_txpwr_section: eeprom section information
- * @offset: indirect address into eeprom image
- * @count: number of "struct iwl_eeprom_enhanced_txpwr" in this section
- * @band: band type for the section
- * @is_common - true: common section, false: channel section
- * @is_cck - true: cck section, false: not cck section
- * @is_ht_40 - true: all channel in the section are HT40 channel,
- * 	       false: legacy or HT 20 MHz
- *	       ignore if it is common section
- * @iwl_eeprom_section_channel: channel array in the section,
- *	       ignore if common section
- */
-struct iwl_txpwr_section {
-	u32 offset;
-	u8 count;
-	enum ieee80211_band band;
-	bool is_common;
-	bool is_cck;
-	bool is_ht40;
-	u8 iwl_eeprom_section_channel[EEPROM_MAX_TXPOWER_SECTION_ELEMENTS];
-};
-
-/**
- * section 1 - 3 are regulatory tx power apply to all channels based on
- *    modulation: CCK, OFDM
- *    Band: 2.4GHz, 5.2GHz
- * section 4 - 10 are regulatory tx power apply to specified channels
- *    For example:
- *	1L - Channel 1 Legacy
- *	1HT - Channel 1 HT
- *	(1,+1) - Channel 1 HT40 "_above_"
- *
- * Section 1: all CCK channels
- * Section 2: all 2.4 GHz OFDM (Legacy, HT and HT40) channels
- * Section 3: all 5.2 GHz OFDM (Legacy, HT and HT40) channels
- * Section 4: 2.4 GHz 20MHz channels: 1L, 1HT, 2L, 2HT, 10L, 10HT, 11L, 11HT
- * Section 5: 2.4 GHz 40MHz channels: (1,+1) (2,+1) (6,+1) (7,+1) (9,+1)
- * Section 6: 5.2 GHz 20MHz channels: 36L, 64L, 100L, 36HT, 64HT, 100HT
- * Section 7: 5.2 GHz 40MHz channels: (36,+1) (60,+1) (100,+1)
- * Section 8: 2.4 GHz channel: 13L, 13HT
- * Section 9: 2.4 GHz channel: 140L, 140HT
- * Section 10: 2.4 GHz 40MHz channels: (132,+1)  (44,+1)
- *
- */
-static const struct iwl_txpwr_section enhinfo[] = {
-	{ EEPROM_LB_CCK_20_COMMON, 1, IEEE80211_BAND_2GHZ, true, true, false },
-	{ EEPROM_LB_OFDM_COMMON, 3, IEEE80211_BAND_2GHZ, true, false, false },
-	{ EEPROM_HB_OFDM_COMMON, 3, IEEE80211_BAND_5GHZ, true, false, false },
-	{ EEPROM_LB_OFDM_20_BAND, 8, IEEE80211_BAND_2GHZ,
-		false, false, false,
-		{1, 1, 2, 2, 10, 10, 11, 11 } },
-	{ EEPROM_LB_OFDM_HT40_BAND, 5, IEEE80211_BAND_2GHZ,
-		false, false, true,
-		{ 1, 2, 6, 7, 9 } },
-	{ EEPROM_HB_OFDM_20_BAND, 6, IEEE80211_BAND_5GHZ,
-		false, false, false,
-		{ 36, 64, 100, 36, 64, 100 } },
-	{ EEPROM_HB_OFDM_HT40_BAND, 3, IEEE80211_BAND_5GHZ,
-		false, false, true,
-		{ 36, 60, 100 } },
-	{ EEPROM_LB_OFDM_20_CHANNEL_13, 2, IEEE80211_BAND_2GHZ,
-		false, false, false,
-		{ 13, 13 } },
-	{ EEPROM_HB_OFDM_20_CHANNEL_140, 2, IEEE80211_BAND_5GHZ,
-		false, false, false,
-		{ 140, 140 } },
-	{ EEPROM_HB_OFDM_HT40_BAND_1, 2, IEEE80211_BAND_5GHZ,
-		false, false, true,
-		{ 132, 44 } },
-};
-
 /******************************************************************************
  *
  * EEPROM related functions
@@ -289,46 +217,6 @@ static int iwlcore_get_nvm_type(struct iwl_priv *priv)
 	return  nvm_type;
 }
 
-/*
- * The device's EEPROM semaphore prevents conflicts between driver and uCode
- * when accessing the EEPROM; each access is a series of pulses to/from the
- * EEPROM chip, not a single event, so even reads could conflict if they
- * weren't arbitrated by the semaphore.
- */
-int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv)
-{
-	u16 count;
-	int ret;
-
-	for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) {
-		/* Request semaphore */
-		iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-			    CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
-
-		/* See if we got it */
-		ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG,
-				CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
-				CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
-				EEPROM_SEM_TIMEOUT);
-		if (ret >= 0) {
-			IWL_DEBUG_IO(priv, "Acquired semaphore after %d tries.\n",
-				count+1);
-			return ret;
-		}
-	}
-
-	return ret;
-}
-EXPORT_SYMBOL(iwlcore_eeprom_acquire_semaphore);
-
-void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv)
-{
-	iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG,
-		CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
-
-}
-EXPORT_SYMBOL(iwlcore_eeprom_release_semaphore);
-
 const u8 *iwlcore_eeprom_query_addr(const struct iwl_priv *priv, size_t offset)
 {
 	BUG_ON(offset >= priv->cfg->base_params->eeprom_size);
@@ -490,6 +378,20 @@ static int iwl_find_otp_image(struct iwl_priv *priv,
 	return -EINVAL;
 }
 
+const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset)
+{
+	return priv->cfg->ops->lib->eeprom_ops.query_addr(priv, offset);
+}
+EXPORT_SYMBOL(iwl_eeprom_query_addr);
+
+u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset)
+{
+	if (!priv->eeprom)
+		return 0;
+	return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8);
+}
+EXPORT_SYMBOL(iwl_eeprom_query16);
+
 /**
  * iwl_eeprom_init - read EEPROM contents
  *
@@ -616,53 +518,6 @@ void iwl_eeprom_free(struct iwl_priv *priv)
 }
 EXPORT_SYMBOL(iwl_eeprom_free);
 
-int iwl_eeprom_check_version(struct iwl_priv *priv)
-{
-	u16 eeprom_ver;
-	u16 calib_ver;
-
-	eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
-	calib_ver = priv->cfg->ops->lib->eeprom_ops.calib_version(priv);
-
-	if (eeprom_ver < priv->cfg->eeprom_ver ||
-	    calib_ver < priv->cfg->eeprom_calib_ver)
-		goto err;
-
-	IWL_INFO(priv, "device EEPROM VER=0x%x, CALIB=0x%x\n",
-		 eeprom_ver, calib_ver);
-
-	return 0;
-err:
-	IWL_ERR(priv, "Unsupported (too old) EEPROM VER=0x%x < 0x%x CALIB=0x%x < 0x%x\n",
-		  eeprom_ver, priv->cfg->eeprom_ver,
-		  calib_ver,  priv->cfg->eeprom_calib_ver);
-	return -EINVAL;
-
-}
-EXPORT_SYMBOL(iwl_eeprom_check_version);
-
-const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset)
-{
-	return priv->cfg->ops->lib->eeprom_ops.query_addr(priv, offset);
-}
-EXPORT_SYMBOL(iwl_eeprom_query_addr);
-
-u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset)
-{
-	if (!priv->eeprom)
-		return 0;
-	return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8);
-}
-EXPORT_SYMBOL(iwl_eeprom_query16);
-
-void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac)
-{
-	const u8 *addr = priv->cfg->ops->lib->eeprom_ops.query_addr(priv,
-					EEPROM_MAC_ADDRESS);
-	memcpy(mac, addr, ETH_ALEN);
-}
-EXPORT_SYMBOL(iwl_eeprom_get_mac);
-
 static void iwl_init_band_reference(const struct iwl_priv *priv,
 			int eep_band, int *eeprom_ch_count,
 			const struct iwl_eeprom_channel **eeprom_ch_info,
@@ -721,7 +576,6 @@ static void iwl_init_band_reference(const struct iwl_priv *priv,
 
 #define CHECK_AND_PRINT(x) ((eeprom_ch->flags & EEPROM_CHANNEL_##x) \
 			    ? # x " " : "")
-
 /**
  * iwl_mod_ht40_chan_info - Copy ht40 channel info into driver's priv.
  *
@@ -765,205 +619,6 @@ static int iwl_mod_ht40_chan_info(struct iwl_priv *priv,
 	return 0;
 }
 
-/**
- * iwl_get_max_txpower_avg - get the highest tx power from all chains.
- *     find the highest tx power from all chains for the channel
- */
-static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv,
-		struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
-		int element, s8 *max_txpower_in_half_dbm)
-{
-	s8 max_txpower_avg = 0; /* (dBm) */
-
-	IWL_DEBUG_INFO(priv, "%d - "
-			"chain_a: %d dB chain_b: %d dB "
-			"chain_c: %d dB mimo2: %d dB mimo3: %d dB\n",
-			element,
-			enhanced_txpower[element].chain_a_max >> 1,
-			enhanced_txpower[element].chain_b_max >> 1,
-			enhanced_txpower[element].chain_c_max >> 1,
-			enhanced_txpower[element].mimo2_max >> 1,
-			enhanced_txpower[element].mimo3_max >> 1);
-	/* Take the highest tx power from any valid chains */
-	if ((priv->cfg->valid_tx_ant & ANT_A) &&
-	    (enhanced_txpower[element].chain_a_max > max_txpower_avg))
-		max_txpower_avg = enhanced_txpower[element].chain_a_max;
-	if ((priv->cfg->valid_tx_ant & ANT_B) &&
-	    (enhanced_txpower[element].chain_b_max > max_txpower_avg))
-		max_txpower_avg = enhanced_txpower[element].chain_b_max;
-	if ((priv->cfg->valid_tx_ant & ANT_C) &&
-	    (enhanced_txpower[element].chain_c_max > max_txpower_avg))
-		max_txpower_avg = enhanced_txpower[element].chain_c_max;
-	if (((priv->cfg->valid_tx_ant == ANT_AB) |
-	    (priv->cfg->valid_tx_ant == ANT_BC) |
-	    (priv->cfg->valid_tx_ant == ANT_AC)) &&
-	    (enhanced_txpower[element].mimo2_max > max_txpower_avg))
-		max_txpower_avg =  enhanced_txpower[element].mimo2_max;
-	if ((priv->cfg->valid_tx_ant == ANT_ABC) &&
-	    (enhanced_txpower[element].mimo3_max > max_txpower_avg))
-		max_txpower_avg = enhanced_txpower[element].mimo3_max;
-
-	/*
-	 * max. tx power in EEPROM is in 1/2 dBm format
-	 * convert from 1/2 dBm to dBm (round-up convert)
-	 * but we also do not want to loss 1/2 dBm resolution which
-	 * will impact performance
-	 */
-	*max_txpower_in_half_dbm = max_txpower_avg;
-	return (max_txpower_avg & 0x01) + (max_txpower_avg >> 1);
-}
-
-/**
- * iwl_update_common_txpower: update channel tx power
- *     update tx power per band based on EEPROM enhanced tx power info.
- */
-static s8 iwl_update_common_txpower(struct iwl_priv *priv,
-		struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
-		int section, int element, s8 *max_txpower_in_half_dbm)
-{
-	struct iwl_channel_info *ch_info;
-	int ch;
-	bool is_ht40 = false;
-	s8 max_txpower_avg; /* (dBm) */
-
-	/* it is common section, contain all type (Legacy, HT and HT40)
-	 * based on the element in the section to determine
-	 * is it HT 40 or not
-	 */
-	if (element == EEPROM_TXPOWER_COMMON_HT40_INDEX)
-		is_ht40 = true;
-	max_txpower_avg =
-		iwl_get_max_txpower_avg(priv, enhanced_txpower,
-					element, max_txpower_in_half_dbm);
-
-	ch_info = priv->channel_info;
-
-	for (ch = 0; ch < priv->channel_count; ch++) {
-		/* find matching band and update tx power if needed */
-		if ((ch_info->band == enhinfo[section].band) &&
-		    (ch_info->max_power_avg < max_txpower_avg) &&
-		    (!is_ht40)) {
-			/* Update regulatory-based run-time data */
-			ch_info->max_power_avg = ch_info->curr_txpow =
-				max_txpower_avg;
-			ch_info->scan_power = max_txpower_avg;
-		}
-		if ((ch_info->band == enhinfo[section].band) && is_ht40 &&
-		    (ch_info->ht40_max_power_avg < max_txpower_avg)) {
-			/* Update regulatory-based run-time data */
-			ch_info->ht40_max_power_avg = max_txpower_avg;
-		}
-		ch_info++;
-	}
-	return max_txpower_avg;
-}
-
-/**
- * iwl_update_channel_txpower: update channel tx power
- *      update channel tx power based on EEPROM enhanced tx power info.
- */
-static s8 iwl_update_channel_txpower(struct iwl_priv *priv,
-		struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
-		int section, int element, s8 *max_txpower_in_half_dbm)
-{
-	struct iwl_channel_info *ch_info;
-	int ch;
-	u8 channel;
-	s8 max_txpower_avg; /* (dBm) */
-
-	channel = enhinfo[section].iwl_eeprom_section_channel[element];
-	max_txpower_avg =
-		iwl_get_max_txpower_avg(priv, enhanced_txpower,
-					element, max_txpower_in_half_dbm);
-
-	ch_info = priv->channel_info;
-	for (ch = 0; ch < priv->channel_count; ch++) {
-		/* find matching channel and update tx power if needed */
-		if (ch_info->channel == channel) {
-			if ((ch_info->max_power_avg < max_txpower_avg) &&
-			    (!enhinfo[section].is_ht40)) {
-				/* Update regulatory-based run-time data */
-				ch_info->max_power_avg = max_txpower_avg;
-				ch_info->curr_txpow = max_txpower_avg;
-				ch_info->scan_power = max_txpower_avg;
-			}
-			if ((enhinfo[section].is_ht40) &&
-			    (ch_info->ht40_max_power_avg < max_txpower_avg)) {
-				/* Update regulatory-based run-time data */
-				ch_info->ht40_max_power_avg = max_txpower_avg;
-			}
-			break;
-		}
-		ch_info++;
-	}
-	return max_txpower_avg;
-}
-
-/**
- * iwlcore_eeprom_enhanced_txpower: process enhanced tx power info
- */
-void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv)
-{
-	int eeprom_section_count = 0;
-	int section, element;
-	struct iwl_eeprom_enhanced_txpwr *enhanced_txpower;
-	u32 offset;
-	s8 max_txpower_avg; /* (dBm) */
-	s8 max_txpower_in_half_dbm; /* (half-dBm) */
-
-	/* Loop through all the sections
-	 * adjust bands and channel's max tx power
-	 * Set the tx_power_user_lmt to the highest power
-	 * supported by any channels and chains
-	 */
-	for (section = 0; section < ARRAY_SIZE(enhinfo); section++) {
-		eeprom_section_count = enhinfo[section].count;
-		offset = enhinfo[section].offset;
-		enhanced_txpower = (struct iwl_eeprom_enhanced_txpwr *)
-				iwl_eeprom_query_addr(priv, offset);
-
-		/*
-		 * check for valid entry -
-		 * different version of EEPROM might contain different set
-		 * of enhanced tx power table
-		 * always check for valid entry before process
-		 * the information
-		 */
-		if (!enhanced_txpower->common || enhanced_txpower->reserved)
-			continue;
-
-		for (element = 0; element < eeprom_section_count; element++) {
-			if (enhinfo[section].is_common)
-				max_txpower_avg =
-					iwl_update_common_txpower(priv,
-						enhanced_txpower, section,
-						element,
-						&max_txpower_in_half_dbm);
-			else
-				max_txpower_avg =
-					iwl_update_channel_txpower(priv,
-						enhanced_txpower, section,
-						element,
-						&max_txpower_in_half_dbm);
-
-			/* Update the tx_power_user_lmt to the highest power
-			 * supported by any channel */
-			if (max_txpower_avg > priv->tx_power_user_lmt)
-				priv->tx_power_user_lmt = max_txpower_avg;
-
-			/*
-			 * Update the tx_power_lmt_in_half_dbm to
-			 * the highest power supported by any channel
-			 */
-			if (max_txpower_in_half_dbm >
-			    priv->tx_power_lmt_in_half_dbm)
-				priv->tx_power_lmt_in_half_dbm =
-					max_txpower_in_half_dbm;
-		}
-	}
-}
-EXPORT_SYMBOL(iwlcore_eeprom_enhanced_txpower);
-
 #define CHECK_AND_PRINT_I(x) ((eeprom_ch_info[ch].flags & EEPROM_CHANNEL_##x) \
 			    ? # x " " : "")
 
@@ -1161,4 +816,3 @@ const struct iwl_channel_info *iwl_get_channel_info(const struct iwl_priv *priv,
 	return NULL;
 }
 EXPORT_SYMBOL(iwl_get_channel_info);
-
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
index 2ae0a11..d9b5906 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
@@ -501,18 +501,13 @@ struct iwl_eeprom_ops {
 };
 
 
-void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac);
 int iwl_eeprom_init(struct iwl_priv *priv);
 void iwl_eeprom_free(struct iwl_priv *priv);
 int  iwl_eeprom_check_version(struct iwl_priv *priv);
 const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset);
-u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset);
-
 int iwlcore_eeprom_verify_signature(struct iwl_priv *priv);
-int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv);
-void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv);
+u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset);
 const u8 *iwlcore_eeprom_query_addr(const struct iwl_priv *priv, size_t offset);
-void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv);
 int iwl_init_channel_map(struct iwl_priv *priv);
 void iwl_free_channel_map(struct iwl_priv *priv);
 const struct iwl_channel_info *iwl_get_channel_info(
-- 
1.7.0.4


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

* Re: [PATCH 1/9] iwlagn: need longer tx queue stuck timer for coex devices
  2010-10-14 18:02 ` [PATCH 1/9] iwlagn: need longer tx queue stuck timer for coex devices Wey-Yi Guy
@ 2010-10-15 16:44   ` Stanislaw Gruszka
  2010-10-15 18:01     ` Guy, Wey-Yi W
  0 siblings, 1 reply; 14+ messages in thread
From: Stanislaw Gruszka @ 2010-10-15 16:44 UTC (permalink / raw)
  To: Wey-Yi Guy; +Cc: linville, linux-wireless, ipw3945-devel

Wey,

On Thu, Oct 14, 2010 at 11:02:42AM -0700, Wey-Yi Guy wrote:
> For BT/WiFi combo devices, need longer tx stuck queue
> timer, so those devices won't reload firmware too often.

Seeing how many tweaking queue hung monitoring we need, I started
to think that the watchdog design is not so good. Currently we compare 
q->read_ptr with q->last_read_ptr, and if they match 3 times in a row
during 200ms, we assume firmware hung. But maybe 200ms of no read_ptr
activity is too small time for device. Moreover we have unlikely but
possible situation when device is fully functional, but read_ptr will
wrap by accident to q->last_read_ptr on every check.

I think, better solution would be something like in rt2x00 or in 
net/sched/sch_generic.c (however rt2x00 is easier to understand). It is
based on time stamp. When we get tx complete notification from hardware
(and incise read_ptr) mark the time stamp. In watchdog, which tick
periodically, check if queue is not empty and if current time is
bigger than time_stamp + time_out, if it is - firmware hung. More
smaller watchog tick give more precise hung detect (with disadvantage
of more cpu usage).

Stanislaw

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

* RE: [PATCH 1/9] iwlagn: need longer tx queue stuck timer for coex devices
  2010-10-15 16:44   ` Stanislaw Gruszka
@ 2010-10-15 18:01     ` Guy, Wey-Yi W
  2010-10-18 12:12       ` Stanislaw Gruszka
  0 siblings, 1 reply; 14+ messages in thread
From: Guy, Wey-Yi W @ 2010-10-15 18:01 UTC (permalink / raw)
  To: Stanislaw Gruszka
  Cc: linville@tuxdriver.com, linux-wireless@vger.kernel.org,
	ipw3945-devel@lists.sourceforge.net

Hi Stanislaw,

-----Original Message-----
From: Stanislaw Gruszka [mailto:sgruszka@redhat.com]
Sent: Friday, October 15, 2010 9:45 AM
To: Guy, Wey-Yi W
Cc: linville@tuxdriver.com; linux-wireless@vger.kernel.org; ipw3945-devel@lists.sourceforge.net
Subject: Re: [PATCH 1/9] iwlagn: need longer tx queue stuck timer for coex devices

Wey,

On Thu, Oct 14, 2010 at 11:02:42AM -0700, Wey-Yi Guy wrote:
> For BT/WiFi combo devices, need longer tx stuck queue
> timer, so those devices won't reload firmware too often.

Seeing how many tweaking queue hung monitoring we need, I started
to think that the watchdog design is not so good. Currently we compare
q->read_ptr with q->last_read_ptr, and if they match 3 times in a row
during 200ms, we assume firmware hung. But maybe 200ms of no read_ptr
activity is too small time for device. Moreover we have unlikely but
possible situation when device is fully functional, but read_ptr will
wrap by accident to q->last_read_ptr on every check.

I think, better solution would be something like in rt2x00 or in
net/sched/sch_generic.c (however rt2x00 is easier to understand). It is
based on time stamp. When we get tx complete notification from hardware
(and incise read_ptr) mark the time stamp. In watchdog, which tick
periodically, check if queue is not empty and if current time is
bigger than time_stamp + time_out, if it is - firmware hung. More
smaller watchog tick give more precise hung detect (with disadvantage
of more cpu usage).


Me too not really like the current "monitor" approach, some thought about the design you propose.

1. "time_out" is something need to be define and has the similar problem like what we have today since different devices has different behavior. For example, in WiFi/BT combo case, the queue might not move for a while if BT traffic load is high
2. I don't really see much of "cpu usage" impact if we have a reasonable watchdog timer. But it is all relative.

By saying that, I think using timestamp might give more cleaner design, but still has the similar issues.

Thanks
Wey


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

* Re: [PATCH 1/9] iwlagn: need longer tx queue stuck timer for coex devices
  2010-10-15 18:01     ` Guy, Wey-Yi W
@ 2010-10-18 12:12       ` Stanislaw Gruszka
  2010-10-18 14:16         ` Guy, Wey-Yi
  0 siblings, 1 reply; 14+ messages in thread
From: Stanislaw Gruszka @ 2010-10-18 12:12 UTC (permalink / raw)
  To: Guy, Wey-Yi W
  Cc: linville@tuxdriver.com, linux-wireless@vger.kernel.org,
	ipw3945-devel@lists.sourceforge.net

Hi Wey

> activity is too small time for device. Moreover we have unlikely but
> possible situation when device is fully functional, but read_ptr will
> wrap by accident to q->last_read_ptr on every check.
> 
> I think, better solution would be something like in rt2x00 or in
> net/sched/sch_generic.c (however rt2x00 is easier to understand). It is
> based on time stamp. When we get tx complete notification from hardware
> (and incise read_ptr) mark the time stamp. In watchdog, which tick
> periodically, check if queue is not empty and if current time is
> bigger than time_stamp + time_out, if it is - firmware hung. More
> smaller watchog tick give more precise hung detect (with disadvantage
> of more cpu usage).
> 
> 
> Me too not really like the current "monitor" approach, some thought about the design you propose.
> 
> 1. "time_out" is something need to be define and has the similar problem like what we have today since different devices has different behavior. For example, in WiFi/BT combo case, the queue might not move for a while if BT traffic load is high

Sure.

However new watchdog could be more precise. Currently if hung will
happen just after watchdog tick we are detecting it in time about 2
ticks i.e. 10s, or when happen just before the tick we detect the hang
in 1 tick i.e. 5s, what gives 100% inaccuracy. New design can be much
more precise.

> 2. I don't really see much of "cpu usage" impact if we have a reasonable watchdog timer. But it is all relative.

Ohh, I was talking about cpu usage in new design I described.

> 
> By saying that, I think using timestamp might give more cleaner design, but still has the similar issues.

Ok, if Intel have no plan to change the monitor recovery and have nothing
against my watchdog approach, I'm going to cook some patches.

Stanislaw

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

* Re: [PATCH 1/9] iwlagn: need longer tx queue stuck timer for coex devices
  2010-10-18 12:12       ` Stanislaw Gruszka
@ 2010-10-18 14:16         ` Guy, Wey-Yi
  0 siblings, 0 replies; 14+ messages in thread
From: Guy, Wey-Yi @ 2010-10-18 14:16 UTC (permalink / raw)
  To: Stanislaw Gruszka
  Cc: linville@tuxdriver.com, linux-wireless@vger.kernel.org,
	ipw3945-devel@lists.sourceforge.net

Hi Stanislaw,

On Mon, 2010-10-18 at 05:12 -0700, Stanislaw Gruszka wrote:
> Hi Wey
> 
> > activity is too small time for device. Moreover we have unlikely but
> > possible situation when device is fully functional, but read_ptr will
> > wrap by accident to q->last_read_ptr on every check.
> > 
> > I think, better solution would be something like in rt2x00 or in
> > net/sched/sch_generic.c (however rt2x00 is easier to understand). It is
> > based on time stamp. When we get tx complete notification from hardware
> > (and incise read_ptr) mark the time stamp. In watchdog, which tick
> > periodically, check if queue is not empty and if current time is
> > bigger than time_stamp + time_out, if it is - firmware hung. More
> > smaller watchog tick give more precise hung detect (with disadvantage
> > of more cpu usage).
> > 
> > 
> > Me too not really like the current "monitor" approach, some thought about the design you propose.
> > 
> > 1. "time_out" is something need to be define and has the similar problem like what we have today since different devices has different behavior. For example, in WiFi/BT combo case, the queue might not move for a while if BT traffic load is high
> 
> Sure.
> 
> However new watchdog could be more precise. Currently if hung will
> happen just after watchdog tick we are detecting it in time about 2
> ticks i.e. 10s, or when happen just before the tick we detect the hang
> in 1 tick i.e. 5s, what gives 100% inaccuracy. New design can be much
> more precise.
> 
> > 2. I don't really see much of "cpu usage" impact if we have a reasonable watchdog timer. But it is all relative.
> 
> Ohh, I was talking about cpu usage in new design I described.
> 
> > 
> > By saying that, I think using timestamp might give more cleaner design, but still has the similar issues.
> 
> Ok, if Intel have no plan to change the monitor recovery and have nothing
> against my watchdog approach, I'm going to cook some patches.

Pleas do so and please do let us review it. I am very happy having you
looking at the iwlwifi driver and give great improvement.

Thank you very much
Wey


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

end of thread, other threads:[~2010-10-18 14:17 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-10-14 18:02 [PATCH 0/9] update for 2.6.37 Wey-Yi Guy
2010-10-14 18:02 ` [PATCH 1/9] iwlagn: need longer tx queue stuck timer for coex devices Wey-Yi Guy
2010-10-15 16:44   ` Stanislaw Gruszka
2010-10-15 18:01     ` Guy, Wey-Yi W
2010-10-18 12:12       ` Stanislaw Gruszka
2010-10-18 14:16         ` Guy, Wey-Yi
2010-10-14 18:02 ` [PATCH 2/9] iwlwifi: allow probe-after-rx on 2.4 GHz Wey-Yi Guy
2010-10-14 18:02 ` [PATCH 3/9] iwlwifi: rename ibss_beacon variable Wey-Yi Guy
2010-10-14 18:02 ` [PATCH 4/9] iwlwifi: clean up some beacon handling Wey-Yi Guy
2010-10-14 18:02 ` [PATCH 5/9] iwlagn: 6050 ops should be used; Wey-Yi Guy
2010-10-14 18:02 ` [PATCH 6/9] iwlwifi: rewrite RXON checks Wey-Yi Guy
2010-10-14 18:02 ` [PATCH 7/9] iwlwifi: blink LED in IBSS mode Wey-Yi Guy
2010-10-14 18:02 ` [PATCH 8/9] iwlagn: check beacon frame size Wey-Yi Guy
2010-10-14 18:02 ` [PATCH 9/9] iwlwifi: move agn only eeprom functions to separate file Wey-Yi Guy

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