linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/13] iwlwifi driver updates 08/13/2009
@ 2009-08-13 20:30 Reinette Chatre
  2009-08-13 20:30 ` [PATCH 01/13] iwlwifi: prevent read outside array bounds Reinette Chatre
                   ` (12 more replies)
  0 siblings, 13 replies; 14+ messages in thread
From: Reinette Chatre @ 2009-08-13 20:30 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Reinette Chatre

This series contains quite a few patches related to HT. Most are cleaning
up code in this area with a few issues being fixed also. We complete the
work related to potential reads outside array bounds. This series adds
thermal throttling support to the 5150. We also make use of the new
cfg80211 feature to override the PS default and disable power save support
until the issues with it have been resolved. A new feature introduced in
this series is the ability to traverse OTP memory to obtain a valid EEPROM
image to read.

[PATCH 01/13] iwlwifi: prevent read outside array bounds
[PATCH 02/13] iwlwifi: remove unused HT configuration entry tx_chan_width
[PATCH 03/13] iwlwifi: include HT configuration when adding stations through rs_rate_init
[PATCH 04/13] iwlwifi: cleanup HT40 extension channels setup
[PATCH 05/13] iwlwifi: traverse linklist to find the valid OTP block
[PATCH 06/13] iwlwifi: remove unused members of iwl_ht_info
[PATCH 07/13] iwlwifi: refactor packet reception code
[PATCH 08/13] iwlwifi: configure HT40 channels in iwl_mac_config
[PATCH 09/13] iwlwifi: check short GI support per-station rather than globally
[PATCH 10/13] iwlwifi: use station HT capabilities and BSS operating mode for Green-field
[PATCH 11/13] iwlwifi: add thermal throttling support to 5150
[PATCH 12/13] iwlwifi: fix erroneous use of iwl_rx_packet.len as a length
[PATCH 13/13] iwlwifi: disable PS by default

Thanks

Reinette

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

* [PATCH 01/13] iwlwifi: prevent read outside array bounds
  2009-08-13 20:30 [PATCH 0/13] iwlwifi driver updates 08/13/2009 Reinette Chatre
@ 2009-08-13 20:30 ` Reinette Chatre
  2009-08-13 20:30 ` [PATCH 02/13] iwlwifi: remove unused HT configuration entry tx_chan_width Reinette Chatre
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Reinette Chatre @ 2009-08-13 20:30 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Reinette Chatre

From: Reinette Chatre <reinette.chatre@intel.com>

With EDCA and HCCA we have 16 potential tid values. This is accommodated by
mac80211, but iwlwifi only supports EDCA. With this implementation it is
thus possible for mac80211 to request a tid that will cause iwlwifi to read
outside array bounds. A similar problem exists if traffic is received in an
unsupported category.

We add error checking to catch these situations.

Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-agn-rs.c   |    3 +++
 drivers/net/wireless/iwlwifi/iwl-tx.c       |    5 +++++
 drivers/net/wireless/iwlwifi/iwl3945-base.c |    2 ++
 3 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 2133155..1bd7cd4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -332,6 +332,9 @@ static u8 rs_tl_add_packet(struct iwl_lq_sta *lq_data,
 	} else
 		return MAX_TID_COUNT;
 
+	if (unlikely(tid >= TID_MAX_LOAD_COUNT))
+		return MAX_TID_COUNT;
+
 	tl = &lq_data->load[tid];
 
 	curr_time -= curr_time % TID_ROUND_VALUE;
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index 9b76bd4..7686fc7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -745,6 +745,8 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 	if (ieee80211_is_data_qos(fc)) {
 		qc = ieee80211_get_qos_ctl(hdr);
 		tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
+		if (unlikely(tid >= MAX_TID_COUNT))
+			goto drop_unlock;
 		seq_number = priv->stations[sta_id].tid[tid].seq_number;
 		seq_number &= IEEE80211_SCTL_SEQ;
 		hdr->seq_ctrl = hdr->seq_ctrl &
@@ -1238,6 +1240,9 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid)
 		return -EINVAL;
 	}
 
+	if (unlikely(tid >= MAX_TID_COUNT))
+		return -EINVAL;
+
 	if (likely(tid < ARRAY_SIZE(default_tid_to_tx_fifo)))
 		tx_fifo_id = default_tid_to_tx_fifo[tid];
 	else
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index e617411..f339c5b 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -544,6 +544,8 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 	if (ieee80211_is_data_qos(fc)) {
 		qc = ieee80211_get_qos_ctl(hdr);
 		tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
+		if (unlikely(tid >= MAX_TID_COUNT))
+			goto drop;
 		seq_number = priv->stations[sta_id].tid[tid].seq_number &
 				IEEE80211_SCTL_SEQ;
 		hdr->seq_ctrl = cpu_to_le16(seq_number) |
-- 
1.5.6.3


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

* [PATCH 02/13] iwlwifi: remove unused HT configuration entry tx_chan_width
  2009-08-13 20:30 [PATCH 0/13] iwlwifi driver updates 08/13/2009 Reinette Chatre
  2009-08-13 20:30 ` [PATCH 01/13] iwlwifi: prevent read outside array bounds Reinette Chatre
@ 2009-08-13 20:30 ` Reinette Chatre
  2009-08-13 20:30 ` [PATCH 03/13] iwlwifi: include HT configuration when adding stations through rs_rate_init Reinette Chatre
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Reinette Chatre @ 2009-08-13 20:30 UTC (permalink / raw)
  To: linville
  Cc: linux-wireless, ipw3945-devel, Daniel C Halperin, Reinette Chatre

From: Daniel C Halperin <daniel.c.halperin@intel.com>

The tx_chan_width entry is never used, supported_chan_width is used instead.

Signed-off-by: Daniel C Halperin <daniel.c.halperin@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-core.c |    1 -
 drivers/net/wireless/iwlwifi/iwl-dev.h  |    1 -
 2 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index af73512..479b7e1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -2423,7 +2423,6 @@ static void iwl_ht_conf(struct iwl_priv *priv,
 
 	memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16);
 
-	iwl_conf->tx_chan_width = iwl_conf->supported_chan_width != 0;
 	iwl_conf->ht_protection =
 		bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION;
 	iwl_conf->non_GF_STA_present =
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index b96c3c9..c34f9d7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -515,7 +515,6 @@ struct iwl_ht_info {
 	struct ieee80211_mcs_info mcs;
 	/* BSS related data */
 	u8 extension_chan_offset;
-	u8 tx_chan_width;
 	u8 ht_protection;
 	u8 non_GF_STA_present;
 };
-- 
1.5.6.3


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

* [PATCH 03/13] iwlwifi: include HT configuration when adding stations through rs_rate_init
  2009-08-13 20:30 [PATCH 0/13] iwlwifi driver updates 08/13/2009 Reinette Chatre
  2009-08-13 20:30 ` [PATCH 01/13] iwlwifi: prevent read outside array bounds Reinette Chatre
  2009-08-13 20:30 ` [PATCH 02/13] iwlwifi: remove unused HT configuration entry tx_chan_width Reinette Chatre
@ 2009-08-13 20:30 ` Reinette Chatre
  2009-08-13 20:30 ` [PATCH 04/13] iwlwifi: cleanup HT40 extension channels setup Reinette Chatre
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Reinette Chatre @ 2009-08-13 20:30 UTC (permalink / raw)
  To: linville
  Cc: linux-wireless, ipw3945-devel, Daniel C Halperin, Reinette Chatre

From: Daniel C Halperin <daniel.c.halperin@intel.com>

Driver's first notification of a new station from mac80211 can be through rate
selection API.  This patch fixes a bug where, in this code path, the HT
capabilities of the new station were ignored.

Signed-off-by: Daniel C Halperin <daniel.c.halperin@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-agn-rs.c |   18 ++++++++++--------
 1 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 1bd7cd4..551c4ba 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -2522,6 +2522,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
 	struct ieee80211_supported_band *sband = txrc->sband;
 	struct iwl_priv *priv = (struct iwl_priv *)priv_r;
 	struct ieee80211_conf *conf = &priv->hw->conf;
+	struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	struct iwl_lq_sta *lq_sta = priv_sta;
@@ -2554,7 +2555,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
 			IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n",
 				       hdr->addr1);
 			sta_id = iwl_add_station(priv, hdr->addr1,
-						false, CMD_ASYNC, NULL);
+						false, CMD_ASYNC, ht_cap);
 		}
 		if ((sta_id != IWL_INVALID_STATION)) {
 			lq_sta->lq.sta_id = sta_id;
@@ -2623,6 +2624,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
 	int i, j;
 	struct iwl_priv *priv = (struct iwl_priv *)priv_r;
 	struct ieee80211_conf *conf = &priv->hw->conf;
+	struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
 	struct iwl_lq_sta *lq_sta = priv_sta;
 	u16 mask_bit = 0;
 	int count;
@@ -2651,7 +2653,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
 		if (sta_id == IWL_INVALID_STATION) {
 			IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", sta->addr);
 			sta_id = iwl_add_station(priv, sta->addr, false,
-						CMD_ASYNC, NULL);
+						CMD_ASYNC, ht_cap);
 		}
 		if ((sta_id != IWL_INVALID_STATION)) {
 			lq_sta->lq.sta_id = sta_id;
@@ -2672,19 +2674,19 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
 	 * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3),
 	 * supp_rates[] does not; shift to convert format, force 9 MBits off.
 	 */
-	lq_sta->active_siso_rate = sta->ht_cap.mcs.rx_mask[0] << 1;
-	lq_sta->active_siso_rate |= sta->ht_cap.mcs.rx_mask[0] & 0x1;
+	lq_sta->active_siso_rate = ht_cap->mcs.rx_mask[0] << 1;
+	lq_sta->active_siso_rate |= ht_cap->mcs.rx_mask[0] & 0x1;
 	lq_sta->active_siso_rate &= ~((u16)0x2);
 	lq_sta->active_siso_rate <<= IWL_FIRST_OFDM_RATE;
 
 	/* Same here */
-	lq_sta->active_mimo2_rate = sta->ht_cap.mcs.rx_mask[1] << 1;
-	lq_sta->active_mimo2_rate |= sta->ht_cap.mcs.rx_mask[1] & 0x1;
+	lq_sta->active_mimo2_rate = ht_cap->mcs.rx_mask[1] << 1;
+	lq_sta->active_mimo2_rate |= ht_cap->mcs.rx_mask[1] & 0x1;
 	lq_sta->active_mimo2_rate &= ~((u16)0x2);
 	lq_sta->active_mimo2_rate <<= IWL_FIRST_OFDM_RATE;
 
-	lq_sta->active_mimo3_rate = sta->ht_cap.mcs.rx_mask[2] << 1;
-	lq_sta->active_mimo3_rate |= sta->ht_cap.mcs.rx_mask[2] & 0x1;
+	lq_sta->active_mimo3_rate = ht_cap->mcs.rx_mask[2] << 1;
+	lq_sta->active_mimo3_rate |= ht_cap->mcs.rx_mask[2] & 0x1;
 	lq_sta->active_mimo3_rate &= ~((u16)0x2);
 	lq_sta->active_mimo3_rate <<= IWL_FIRST_OFDM_RATE;
 
-- 
1.5.6.3


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

* [PATCH 04/13] iwlwifi: cleanup HT40 extension channels setup
  2009-08-13 20:30 [PATCH 0/13] iwlwifi driver updates 08/13/2009 Reinette Chatre
                   ` (2 preceding siblings ...)
  2009-08-13 20:30 ` [PATCH 03/13] iwlwifi: include HT configuration when adding stations through rs_rate_init Reinette Chatre
@ 2009-08-13 20:30 ` Reinette Chatre
  2009-08-13 20:30 ` [PATCH 05/13] iwlwifi: traverse linklist to find the valid OTP block Reinette Chatre
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Reinette Chatre @ 2009-08-13 20:30 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Zhu Yi, Reinette Chatre

From: Zhu Yi <yi.zhu@intel.com>

The patch cleans up the HT40 extension channels setup for EEPROM
band 6 and 7 to make it more readable.

Signed-off-by: Zhu Yi <yi.zhu@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-eeprom.c |   37 +++++++++-------------------
 1 files changed, 12 insertions(+), 25 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
index 78c4a32..ded6332 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -484,14 +484,14 @@ static void iwl_init_band_reference(const struct iwl_priv *priv,
 			    ? # x " " : "")
 
 /**
- * iwl_set_ht40_chan_info - Copy ht40 channel info into driver's priv.
+ * iwl_mod_ht40_chan_info - Copy ht40 channel info into driver's priv.
  *
  * Does not set up a command, or touch hardware.
  */
-static int iwl_set_ht40_chan_info(struct iwl_priv *priv,
+static int iwl_mod_ht40_chan_info(struct iwl_priv *priv,
 			      enum ieee80211_band band, u16 channel,
 			      const struct iwl_eeprom_channel *eeprom_ch,
-			      u8 ht40_extension_channel)
+			      u8 clear_ht40_extension_channel)
 {
 	struct iwl_channel_info *ch_info;
 
@@ -523,7 +523,7 @@ static int iwl_set_ht40_chan_info(struct iwl_priv *priv,
 	ch_info->ht40_min_power = 0;
 	ch_info->ht40_scan_power = eeprom_ch->max_power_avg;
 	ch_info->ht40_flags = eeprom_ch->flags;
-	ch_info->ht40_extension_channel = ht40_extension_channel;
+	ch_info->ht40_extension_channel &= ~clear_ht40_extension_channel;
 
 	return 0;
 }
@@ -592,8 +592,7 @@ int iwl_init_channel_map(struct iwl_priv *priv)
 			/* First write that ht40 is not enabled, and then enable
 			 * one by one */
 			ch_info->ht40_extension_channel =
-				(IEEE80211_CHAN_NO_HT40PLUS |
-				 IEEE80211_CHAN_NO_HT40MINUS);
+					IEEE80211_CHAN_NO_HT40;
 
 			if (!(is_channel_valid(ch_info))) {
 				IWL_DEBUG_INFO(priv, "Ch. %d Flags %x [%sGHz] - "
@@ -652,7 +651,6 @@ int iwl_init_channel_map(struct iwl_priv *priv)
 	/* Two additional EEPROM bands for 2.4 and 5 GHz HT40 channels */
 	for (band = 6; band <= 7; band++) {
 		enum ieee80211_band ieeeband;
-		u8 ht40_extension_chan;
 
 		iwl_init_band_reference(priv, band, &eeprom_ch_count,
 					&eeprom_ch_info, &eeprom_ch_index);
@@ -663,28 +661,17 @@ int iwl_init_channel_map(struct iwl_priv *priv)
 
 		/* Loop through each band adding each of the channels */
 		for (ch = 0; ch < eeprom_ch_count; ch++) {
-
-			if ((band == 6) &&
-				((eeprom_ch_index[ch] == 5) ||
-				 (eeprom_ch_index[ch] == 6) ||
-				 (eeprom_ch_index[ch] == 7)))
-				/* both are allowed: above and below */
-				ht40_extension_chan = 0;
-			else
-				ht40_extension_chan =
-					IEEE80211_CHAN_NO_HT40MINUS;
-
 			/* Set up driver's info for lower half */
-			iwl_set_ht40_chan_info(priv, ieeeband,
+			iwl_mod_ht40_chan_info(priv, ieeeband,
 						eeprom_ch_index[ch],
-						&(eeprom_ch_info[ch]),
-						ht40_extension_chan);
+						&eeprom_ch_info[ch],
+						IEEE80211_CHAN_NO_HT40PLUS);
 
 			/* Set up driver's info for upper half */
-			iwl_set_ht40_chan_info(priv, ieeeband,
-						(eeprom_ch_index[ch] + 4),
-						&(eeprom_ch_info[ch]),
-						IEEE80211_CHAN_NO_HT40PLUS);
+			iwl_mod_ht40_chan_info(priv, ieeeband,
+						eeprom_ch_index[ch] + 4,
+						&eeprom_ch_info[ch],
+						IEEE80211_CHAN_NO_HT40MINUS);
 		}
 	}
 
-- 
1.5.6.3


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

* [PATCH 05/13] iwlwifi: traverse linklist to find the valid OTP block
  2009-08-13 20:30 [PATCH 0/13] iwlwifi driver updates 08/13/2009 Reinette Chatre
                   ` (3 preceding siblings ...)
  2009-08-13 20:30 ` [PATCH 04/13] iwlwifi: cleanup HT40 extension channels setup Reinette Chatre
@ 2009-08-13 20:30 ` Reinette Chatre
  2009-08-13 20:30 ` [PATCH 06/13] iwlwifi: remove unused members of iwl_ht_info Reinette Chatre
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Reinette Chatre @ 2009-08-13 20:30 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy, Reinette Chatre

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

For devices using OTP memory, EEPROM image can start from
any one of the OTP blocks. If shadow RAM is disabled, we need to
traverse link list to find the last valid block, then start the EEPROM
image reading.

If OTP is not full, the valid block is the block _before_ the last block
on the link list; the last block on the link list is the empty block
ready for next OTP refresh/update.

If OTP is full, then the last block is the valid block to be used for
configure the device.

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-1000.c   |    4 +-
 drivers/net/wireless/iwlwifi/iwl-6000.c   |   20 +++-
 drivers/net/wireless/iwlwifi/iwl-core.h   |    4 +
 drivers/net/wireless/iwlwifi/iwl-dev.h    |   11 ++
 drivers/net/wireless/iwlwifi/iwl-eeprom.c |  185 +++++++++++++++++++++++------
 drivers/net/wireless/iwlwifi/iwl-eeprom.h |   10 ++-
 6 files changed, 191 insertions(+), 43 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c
index 191718a..9bb6a28 100644
--- a/drivers/net/wireless/iwlwifi/iwl-1000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-1000.c
@@ -149,12 +149,14 @@ struct iwl_cfg iwl1000_bgn_cfg = {
 	.ucode_api_min = IWL1000_UCODE_API_MIN,
 	.sku = IWL_SKU_G|IWL_SKU_N,
 	.ops = &iwl1000_ops,
-	.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+	.eeprom_size = OTP_LOW_IMAGE_SIZE,
 	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
 	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
 	.mod_params = &iwl50_mod_params,
 	.valid_tx_ant = ANT_A,
 	.valid_rx_ant = ANT_AB,
 	.need_pll_cfg = true,
+	.max_ll_items = OTP_MAX_LL_ITEMS_1000,
+	.shadow_ram_support = false,
 };
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index c3ec6c2..0b731fd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -161,7 +161,7 @@ struct iwl_cfg iwl6000h_2agn_cfg = {
 	.ucode_api_min = IWL6000_UCODE_API_MIN,
 	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
 	.ops = &iwl6000_ops,
-	.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+	.eeprom_size = OTP_LOW_IMAGE_SIZE,
 	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
 	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
 	.mod_params = &iwl50_mod_params,
@@ -169,6 +169,8 @@ struct iwl_cfg iwl6000h_2agn_cfg = {
 	.valid_rx_ant = ANT_AB,
 	.need_pll_cfg = false,
 	.pa_type = IWL_PA_HYBRID,
+	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
+	.shadow_ram_support = true,
 };
 
 /*
@@ -181,7 +183,7 @@ struct iwl_cfg iwl6000i_2agn_cfg = {
 	.ucode_api_min = IWL6000_UCODE_API_MIN,
 	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
 	.ops = &iwl6000_ops,
-	.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+	.eeprom_size = OTP_LOW_IMAGE_SIZE,
 	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
 	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
 	.mod_params = &iwl50_mod_params,
@@ -189,6 +191,8 @@ struct iwl_cfg iwl6000i_2agn_cfg = {
 	.valid_rx_ant = ANT_BC,
 	.need_pll_cfg = false,
 	.pa_type = IWL_PA_INTERNAL,
+	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
+	.shadow_ram_support = true,
 };
 
 struct iwl_cfg iwl6050_2agn_cfg = {
@@ -198,7 +202,7 @@ struct iwl_cfg iwl6050_2agn_cfg = {
 	.ucode_api_min = IWL6050_UCODE_API_MIN,
 	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
 	.ops = &iwl6000_ops,
-	.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+	.eeprom_size = OTP_LOW_IMAGE_SIZE,
 	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
 	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
 	.mod_params = &iwl50_mod_params,
@@ -206,6 +210,8 @@ struct iwl_cfg iwl6050_2agn_cfg = {
 	.valid_rx_ant = ANT_AB,
 	.need_pll_cfg = false,
 	.pa_type = IWL_PA_SYSTEM,
+	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
+	.shadow_ram_support = true,
 };
 
 struct iwl_cfg iwl6000_3agn_cfg = {
@@ -215,7 +221,7 @@ struct iwl_cfg iwl6000_3agn_cfg = {
 	.ucode_api_min = IWL6000_UCODE_API_MIN,
 	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
 	.ops = &iwl6000_ops,
-	.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+	.eeprom_size = OTP_LOW_IMAGE_SIZE,
 	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
 	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
 	.mod_params = &iwl50_mod_params,
@@ -223,6 +229,8 @@ struct iwl_cfg iwl6000_3agn_cfg = {
 	.valid_rx_ant = ANT_ABC,
 	.need_pll_cfg = false,
 	.pa_type = IWL_PA_SYSTEM,
+	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
+	.shadow_ram_support = true,
 };
 
 struct iwl_cfg iwl6050_3agn_cfg = {
@@ -232,7 +240,7 @@ struct iwl_cfg iwl6050_3agn_cfg = {
 	.ucode_api_min = IWL6050_UCODE_API_MIN,
 	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
 	.ops = &iwl6000_ops,
-	.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+	.eeprom_size = OTP_LOW_IMAGE_SIZE,
 	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
 	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
 	.mod_params = &iwl50_mod_params,
@@ -240,6 +248,8 @@ struct iwl_cfg iwl6050_3agn_cfg = {
 	.valid_rx_ant = ANT_ABC,
 	.need_pll_cfg = false,
 	.pa_type = IWL_PA_SYSTEM,
+	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
+	.shadow_ram_support = true,
 };
 
 MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX));
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 32750f4..5096834 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -209,6 +209,8 @@ struct iwl_mod_params {
  * @ucode_api_max: Highest version of uCode API supported by driver.
  * @ucode_api_min: Lowest version of uCode API supported by driver.
  * @pa_type: used by 6000 series only to identify the type of Power Amplifier
+ * @max_ll_items: max number of OTP blocks
+ * @shadow_ram_support: shadow support for OTP memory
  *
  * We enable the driver to be backward compatible wrt API version. The
  * driver specifies which APIs it supports (with @ucode_api_max being the
@@ -247,6 +249,8 @@ struct iwl_cfg {
 	bool need_pll_cfg;
 	bool use_isr_legacy;
 	enum iwl_pa_type pa_type;
+	const u16 max_ll_items;
+	const bool shadow_ram_support;
 };
 
 /***************************
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index c34f9d7..0b19a6f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -887,6 +887,17 @@ enum iwl_nvm_type {
 	NVM_DEVICE_TYPE_OTP,
 };
 
+/*
+ * Two types of OTP memory access modes
+ *   IWL_OTP_ACCESS_ABSOLUTE - absolute address mode,
+ * 			        based on physical memory addressing
+ *   IWL_OTP_ACCESS_RELATIVE - relative address mode,
+ * 			       based on logical memory addressing
+ */
+enum iwl_access_mode {
+	IWL_OTP_ACCESS_ABSOLUTE,
+	IWL_OTP_ACCESS_RELATIVE,
+};
 
 /**
  * enum iwl_pa_type - Power Amplifier type
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
index ded6332..01b95e8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -152,6 +152,19 @@ int iwlcore_eeprom_verify_signature(struct iwl_priv *priv)
 }
 EXPORT_SYMBOL(iwlcore_eeprom_verify_signature);
 
+static void iwl_set_otp_access(struct iwl_priv *priv, enum iwl_access_mode mode)
+{
+	u32 otpgp;
+
+	otpgp = iwl_read32(priv, CSR_OTP_GP_REG);
+	if (mode == IWL_OTP_ACCESS_ABSOLUTE)
+		iwl_clear_bit(priv, CSR_OTP_GP_REG,
+				CSR_OTP_GP_REG_OTP_ACCESS_MODE);
+	else
+		iwl_set_bit(priv, CSR_OTP_GP_REG,
+				CSR_OTP_GP_REG_OTP_ACCESS_MODE);
+}
+
 static int iwlcore_get_nvm_type(struct iwl_priv *priv)
 {
 	u32 otpgp;
@@ -252,6 +265,124 @@ static int iwl_init_otp_access(struct iwl_priv *priv)
 	return ret;
 }
 
+static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, u16 *eeprom_data)
+{
+	int ret = 0;
+	u32 r;
+	u32 otpgp;
+
+	_iwl_write32(priv, CSR_EEPROM_REG,
+		     CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
+	ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG,
+				  CSR_EEPROM_REG_READ_VALID_MSK,
+				  IWL_EEPROM_ACCESS_TIMEOUT);
+	if (ret < 0) {
+		IWL_ERR(priv, "Time out reading OTP[%d]\n", addr);
+		return ret;
+	}
+	r = _iwl_read_direct32(priv, CSR_EEPROM_REG);
+	/* check for ECC errors: */
+	otpgp = iwl_read32(priv, CSR_OTP_GP_REG);
+	if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) {
+		/* stop in this case */
+		/* set the uncorrectable OTP ECC bit for acknowledgement */
+		iwl_set_bit(priv, CSR_OTP_GP_REG,
+			CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK);
+		IWL_ERR(priv, "Uncorrectable OTP ECC error, abort OTP read\n");
+		return -EINVAL;
+	}
+	if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) {
+		/* continue in this case */
+		/* set the correctable OTP ECC bit for acknowledgement */
+		iwl_set_bit(priv, CSR_OTP_GP_REG,
+				CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK);
+		IWL_ERR(priv, "Correctable OTP ECC error, continue read\n");
+	}
+	*eeprom_data = le16_to_cpu((__force __le16)(r >> 16));
+	return 0;
+}
+
+/*
+ * iwl_is_otp_empty: check for empty OTP
+ */
+static bool iwl_is_otp_empty(struct iwl_priv *priv)
+{
+	u16 next_link_addr = 0, link_value;
+	bool is_empty = false;
+
+	/* locate the beginning of OTP link list */
+	if (!iwl_read_otp_word(priv, next_link_addr, &link_value)) {
+		if (!link_value) {
+			IWL_ERR(priv, "OTP is empty\n");
+			is_empty = true;
+		}
+	} else {
+		IWL_ERR(priv, "Unable to read first block of OTP list.\n");
+		is_empty = true;
+	}
+
+	return is_empty;
+}
+
+
+/*
+ * iwl_find_otp_image: find EEPROM image in OTP
+ *   finding the OTP block that contains the EEPROM image.
+ *   the last valid block on the link list (the block _before_ the last block)
+ *   is the block we should read and used to configure the device.
+ *   If all the available OTP blocks are full, the last block will be the block
+ *   we should read and used to configure the device.
+ *   only perform this operation if shadow RAM is disabled
+ */
+static int iwl_find_otp_image(struct iwl_priv *priv,
+					u16 *validblockaddr)
+{
+	u16 next_link_addr = 0, link_value = 0, valid_addr;
+	int ret = 0;
+	int usedblocks = 0;
+
+	/* set addressing mode to absolute to traverse the link list */
+	iwl_set_otp_access(priv, IWL_OTP_ACCESS_ABSOLUTE);
+
+	/* checking for empty OTP or error */
+	if (iwl_is_otp_empty(priv))
+		return -EINVAL;
+
+	/*
+	 * start traverse link list
+	 * until reach the max number of OTP blocks
+	 * different devices have different number of OTP blocks
+	 */
+	do {
+		/* save current valid block address
+		 * check for more block on the link list
+		 */
+		valid_addr = next_link_addr;
+		next_link_addr = link_value;
+		IWL_DEBUG_INFO(priv, "OTP blocks %d addr 0x%x\n",
+			       usedblocks, next_link_addr);
+		if (iwl_read_otp_word(priv, next_link_addr, &link_value))
+			return -EINVAL;
+		if (!link_value) {
+			/*
+			 * reach the end of link list,
+			 * set address point to the starting address
+			 * of the image
+			 */
+			goto done;
+		}
+		/* more in the link list, continue */
+		usedblocks++;
+	} while (usedblocks < priv->cfg->max_ll_items);
+	/* OTP full, use last block */
+	IWL_DEBUG_INFO(priv, "OTP is full, use last block\n");
+done:
+	*validblockaddr = valid_addr;
+	/* skip first 2 bytes (link list pointer) */
+	*validblockaddr += 2;
+	return ret;
+}
+
 /**
  * iwl_eeprom_init - read EEPROM contents
  *
@@ -266,15 +397,14 @@ int iwl_eeprom_init(struct iwl_priv *priv)
 	int sz;
 	int ret;
 	u16 addr;
-	u32 otpgp;
+	u16 validblockaddr = 0;
+	u16 cache_addr = 0;
 
 	priv->nvm_device_type = iwlcore_get_nvm_type(priv);
 	if (priv->nvm_device_type == -ENOENT)
 		return -ENOENT;
 	/* allocate eeprom */
-	if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP)
-		priv->cfg->eeprom_size =
-			OTP_BLOCK_SIZE * OTP_LOWER_BLOCKS_TOTAL;
+	IWL_DEBUG_INFO(priv, "NVM size = %d\n", priv->cfg->eeprom_size);
 	sz = priv->cfg->eeprom_size;
 	priv->eeprom = kzalloc(sz, GFP_KERNEL);
 	if (!priv->eeprom) {
@@ -302,46 +432,31 @@ int iwl_eeprom_init(struct iwl_priv *priv)
 		if (ret) {
 			IWL_ERR(priv, "Failed to initialize OTP access.\n");
 			ret = -ENOENT;
-			goto err;
+			goto done;
 		}
 		_iwl_write32(priv, CSR_EEPROM_GP,
 			     iwl_read32(priv, CSR_EEPROM_GP) &
 			     ~CSR_EEPROM_GP_IF_OWNER_MSK);
-		/* clear */
-		_iwl_write32(priv, CSR_OTP_GP_REG,
-			     iwl_read32(priv, CSR_OTP_GP_REG) |
+
+		iwl_set_bit(priv, CSR_OTP_GP_REG,
 			     CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK |
 			     CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK);
-
-		for (addr = 0; addr < sz; addr += sizeof(u16)) {
-			u32 r;
-
-			_iwl_write32(priv, CSR_EEPROM_REG,
-				     CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
-
-			ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG,
-						  CSR_EEPROM_REG_READ_VALID_MSK,
-						  IWL_EEPROM_ACCESS_TIMEOUT);
-			if (ret < 0) {
-				IWL_ERR(priv, "Time out reading OTP[%d]\n", addr);
+		/* traversing the linked list if no shadow ram supported */
+		if (!priv->cfg->shadow_ram_support) {
+			if (iwl_find_otp_image(priv, &validblockaddr)) {
+				ret = -ENOENT;
 				goto done;
 			}
-			r = _iwl_read_direct32(priv, CSR_EEPROM_REG);
-			/* check for ECC errors: */
-			otpgp = iwl_read32(priv, CSR_OTP_GP_REG);
-			if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) {
-				/* stop in this case */
-				IWL_ERR(priv, "Uncorrectable OTP ECC error, Abort OTP read\n");
+		}
+		for (addr = validblockaddr; addr < validblockaddr + sz;
+		     addr += sizeof(u16)) {
+			u16 eeprom_data;
+
+			ret = iwl_read_otp_word(priv, addr, &eeprom_data);
+			if (ret)
 				goto done;
-			}
-			if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) {
-				/* continue in this case */
-				_iwl_write32(priv, CSR_OTP_GP_REG,
-					     iwl_read32(priv, CSR_OTP_GP_REG) |
-					     CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK);
-				IWL_ERR(priv, "Correctable OTP ECC error, continue read\n");
-			}
-			e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16));
+			e[cache_addr / 2] = eeprom_data;
+			cache_addr += sizeof(u16);
 		}
 	} else {
 		/* eeprom is an array of 16bit values */
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
index 05d4fc4..ca7920a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
@@ -180,8 +180,14 @@ struct iwl_eeprom_channel {
 #define EEPROM_5050_EEPROM_VERSION	(0x21E)
 
 /* OTP */
-#define OTP_LOWER_BLOCKS_TOTAL		(3)
-#define OTP_BLOCK_SIZE			(0x400)
+/* lower blocks contain EEPROM image and calibration data */
+#define OTP_LOW_IMAGE_SIZE		(2 * 512 * sizeof(u16)) /* 2 KB */
+/* high blocks contain PAPD data */
+#define OTP_HIGH_IMAGE_SIZE_6x00        (6 * 512 * sizeof(u16)) /* 6 KB */
+#define OTP_HIGH_IMAGE_SIZE_1000        (0x200 * sizeof(u16)) /* 1024 bytes */
+#define OTP_MAX_LL_ITEMS_1000		(3)	/* OTP blocks for 1000 */
+#define OTP_MAX_LL_ITEMS_6x00		(4)	/* OTP blocks for 6x00 */
+#define OTP_MAX_LL_ITEMS_6x50		(7)	/* OTP blocks for 6x50 */
 
 /* 2.4 GHz */
 extern const u8 iwl_eeprom_band_1[14];
-- 
1.5.6.3


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

* [PATCH 06/13] iwlwifi: remove unused members of iwl_ht_info
  2009-08-13 20:30 [PATCH 0/13] iwlwifi driver updates 08/13/2009 Reinette Chatre
                   ` (4 preceding siblings ...)
  2009-08-13 20:30 ` [PATCH 05/13] iwlwifi: traverse linklist to find the valid OTP block Reinette Chatre
@ 2009-08-13 20:30 ` Reinette Chatre
  2009-08-13 20:30 ` [PATCH 07/13] iwlwifi: refactor packet reception code Reinette Chatre
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Reinette Chatre @ 2009-08-13 20:30 UTC (permalink / raw)
  To: linville
  Cc: linux-wireless, ipw3945-devel, Johannes Berg, Daniel C Halperin,
	Reinette Chatre

From: Johannes Berg <johannes@sipsolutions.net>

Some members of iwl_ht_info are unused, and one of
them is write-only, so we can remove these three:
max_amsdu_size, ampdu_factor and mpdu_density.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Daniel C Halperin <daniel.c.halperin@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-core.c |    2 --
 drivers/net/wireless/iwlwifi/iwl-dev.h  |    3 ---
 2 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 479b7e1..08345b9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -2397,8 +2397,6 @@ static void iwl_ht_conf(struct iwl_priv *priv,
 		iwl_conf->sgf |= HT_SHORT_GI_40MHZ;
 
 	iwl_conf->is_green_field = !!(ht_conf->cap & IEEE80211_HT_CAP_GRN_FLD);
-	iwl_conf->max_amsdu_size =
-		!!(ht_conf->cap & IEEE80211_HT_CAP_MAX_AMSDU);
 
 	iwl_conf->supported_chan_width =
 		!!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 0b19a6f..db74534 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -509,9 +509,6 @@ struct iwl_ht_info {
 	u8 sm_ps;
 	u8 is_green_field;
 	u8 sgf;			/* HT_SHORT_GI_* short guard interval */
-	u8 max_amsdu_size;
-	u8 ampdu_factor;
-	u8 mpdu_density;
 	struct ieee80211_mcs_info mcs;
 	/* BSS related data */
 	u8 extension_chan_offset;
-- 
1.5.6.3


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

* [PATCH 07/13] iwlwifi: refactor packet reception code
  2009-08-13 20:30 [PATCH 0/13] iwlwifi driver updates 08/13/2009 Reinette Chatre
                   ` (5 preceding siblings ...)
  2009-08-13 20:30 ` [PATCH 06/13] iwlwifi: remove unused members of iwl_ht_info Reinette Chatre
@ 2009-08-13 20:30 ` Reinette Chatre
  2009-08-13 20:30 ` [PATCH 08/13] iwlwifi: configure HT40 channels in iwl_mac_config Reinette Chatre
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Reinette Chatre @ 2009-08-13 20:30 UTC (permalink / raw)
  To: linville
  Cc: linux-wireless, ipw3945-devel, Daniel C Halperin, Reinette Chatre

From: Daniel C Halperin <daniel.c.halperin@intel.com>

This patch fixes a number of issues in iwl_rx_reply_rx and
iwl_pass_packet_to_mac80211.  These issues stem from the complexities of
managing two different types of packet commands for different hardware.

- Unify code handling rx_phy_res in SKB or cached to eliminate redundancy and
remove potential NULL pointer accesses
- Replace magic number with proper constant
- Optimize functions by moving early exit conditions before computation
- Comment code and improve some variable names
- Remove redundant computation in iwl_pass_packet_to_mac80211 by passing in the
correct, already-computed arguments.

Signed-off-by: Daniel C Halperin <daniel.c.halperin@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-commands.h |    1 +
 drivers/net/wireless/iwlwifi/iwl-rx.c       |  204 ++++++++++-----------------
 2 files changed, 78 insertions(+), 127 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 68d7719..9398ad7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -1156,6 +1156,7 @@ struct iwl_wep_cmd {
 #define RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK	cpu_to_le16(1 << 2)
 #define RX_RES_PHY_FLAGS_NARROW_BAND_MSK	cpu_to_le16(1 << 3)
 #define RX_RES_PHY_FLAGS_ANTENNA_MSK		cpu_to_le16(0xf0)
+#define RX_RES_PHY_FLAGS_ANTENNA_POS		4
 
 #define RX_RES_STATUS_SEC_TYPE_MSK	(0x7 << 8)
 #define RX_RES_STATUS_SEC_TYPE_NONE	(0x0 << 8)
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index 43b2fce..092d327 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -853,61 +853,12 @@ static u32 iwl_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in)
 }
 
 static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
-				       int include_phy,
-				       struct iwl_rx_mem_buffer *rxb,
-				       struct ieee80211_rx_status *stats)
+					struct ieee80211_hdr *hdr,
+					u16 len,
+					u32 ampdu_status,
+					struct iwl_rx_mem_buffer *rxb,
+					struct ieee80211_rx_status *stats)
 {
-	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
-	struct iwl_rx_phy_res *rx_start = (include_phy) ?
-	    (struct iwl_rx_phy_res *)&(pkt->u.raw[0]) : NULL;
-	struct ieee80211_hdr *hdr;
-	u16 len;
-	__le32 *rx_end;
-	unsigned int skblen;
-	u32 ampdu_status;
-	u32 ampdu_status_legacy;
-
-	if (!include_phy && priv->last_phy_res[0])
-		rx_start = (struct iwl_rx_phy_res *)&priv->last_phy_res[1];
-
-	if (!rx_start) {
-		IWL_ERR(priv, "MPDU frame without a PHY data\n");
-		return;
-	}
-	if (include_phy) {
-		hdr = (struct ieee80211_hdr *)((u8 *) &rx_start[1] +
-					       rx_start->cfg_phy_cnt);
-
-		len = le16_to_cpu(rx_start->byte_count);
-
-		rx_end = (__le32 *)((u8 *) &pkt->u.raw[0] +
-				  sizeof(struct iwl_rx_phy_res) +
-				  rx_start->cfg_phy_cnt + len);
-
-	} else {
-		struct iwl4965_rx_mpdu_res_start *amsdu =
-		    (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw;
-
-		hdr = (struct ieee80211_hdr *)(pkt->u.raw +
-			       sizeof(struct iwl4965_rx_mpdu_res_start));
-		len =  le16_to_cpu(amsdu->byte_count);
-		rx_start->byte_count = amsdu->byte_count;
-		rx_end = (__le32 *) (((u8 *) hdr) + len);
-	}
-
-	ampdu_status = le32_to_cpu(*rx_end);
-	skblen = ((u8 *) rx_end - (u8 *) &pkt->u.raw[0]) + sizeof(u32);
-
-	if (!include_phy) {
-		/* New status scheme, need to translate */
-		ampdu_status_legacy = ampdu_status;
-		ampdu_status = iwl_translate_rx_status(priv, ampdu_status);
-	}
-
-	/* start from MAC */
-	skb_reserve(rxb->skb, (void *)hdr - (void *)pkt);
-	skb_put(rxb->skb, len);	/* end where data ends */
-
 	/* We only process data packets if the interface is open */
 	if (unlikely(!priv->is_open)) {
 		IWL_DEBUG_DROP_LIMIT(priv,
@@ -915,13 +866,15 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
 		return;
 	}
 
-	hdr = (struct ieee80211_hdr *)rxb->skb->data;
-
-	/*  in case of HW accelerated crypto and bad decryption, drop */
+	/* In case of HW accelerated crypto and bad decryption, drop */
 	if (!priv->cfg->mod_params->sw_crypto &&
 	    iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats))
 		return;
 
+	/* Resize SKB from mac header to end of packet */
+	skb_reserve(rxb->skb, (void *)hdr - (void *)rxb->skb->data);
+	skb_put(rxb->skb, len);
+
 	iwl_update_stats(priv, false, hdr->frame_control, len);
 	memcpy(IEEE80211_SKB_RXCB(rxb->skb), stats, sizeof(*stats));
 	ieee80211_rx_irqsafe(priv->hw, rxb->skb);
@@ -955,25 +908,66 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
 	struct ieee80211_hdr *header;
 	struct ieee80211_rx_status rx_status;
 	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
-	/* Use phy data (Rx signal strength, etc.) contained within
-	 *   this rx packet for legacy frames,
-	 *   or phy data cached from REPLY_RX_PHY_CMD for HT frames. */
-	int include_phy = (pkt->hdr.cmd == REPLY_RX);
-	struct iwl_rx_phy_res *rx_start = (include_phy) ?
-		(struct iwl_rx_phy_res *)&(pkt->u.raw[0]) :
-		(struct iwl_rx_phy_res *)&priv->last_phy_res[1];
-	__le32 *rx_end;
-	unsigned int len = 0;
+	struct iwl_rx_phy_res *phy_res;
+	__le32 rx_pkt_status;
+	struct iwl4965_rx_mpdu_res_start *amsdu;
+	u32 len;
+	u32 ampdu_status;
 	u16 fc;
-	u8 network_packet;
 
-	rx_status.mactime = le64_to_cpu(rx_start->timestamp);
+	/**
+	 * REPLY_RX and REPLY_RX_MPDU_CMD are handled differently.
+	 *	REPLY_RX: physical layer info is in this buffer
+	 *	REPLY_RX_MPDU_CMD: physical layer info was sent in separate
+	 *		command and cached in priv->last_phy_res
+	 *
+	 * Here we set up local variables depending on which command is
+	 * received.
+	 */
+	if (pkt->hdr.cmd == REPLY_RX) {
+		phy_res = (struct iwl_rx_phy_res *)pkt->u.raw;
+		header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*phy_res)
+				+ phy_res->cfg_phy_cnt);
+
+		len = le16_to_cpu(phy_res->byte_count);
+		rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*phy_res) +
+				phy_res->cfg_phy_cnt + len);
+		ampdu_status = le32_to_cpu(rx_pkt_status);
+	} else {
+		if (!priv->last_phy_res[0]) {
+			IWL_ERR(priv, "MPDU frame without cached PHY data\n");
+			return;
+		}
+		phy_res = (struct iwl_rx_phy_res *)&priv->last_phy_res[1];
+		amsdu = (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw;
+		header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu));
+		len = le16_to_cpu(amsdu->byte_count);
+		rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*amsdu) + len);
+		ampdu_status = iwl_translate_rx_status(priv,
+				le32_to_cpu(rx_pkt_status));
+	}
+
+	if ((unlikely(phy_res->cfg_phy_cnt > 20))) {
+		IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n",
+				phy_res->cfg_phy_cnt);
+		return;
+	}
+
+	if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) ||
+	    !(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) {
+		IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n",
+				le32_to_cpu(rx_pkt_status));
+		return;
+	}
+
+	/* rx_status carries information about the packet to mac80211 */
+	rx_status.mactime = le64_to_cpu(phy_res->timestamp);
 	rx_status.freq =
-		ieee80211_channel_to_frequency(le16_to_cpu(rx_start->channel));
-	rx_status.band = (rx_start->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
+		ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel));
+	rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
 				IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
 	rx_status.rate_idx =
-		iwl_hwrate_to_plcp_idx(le32_to_cpu(rx_start->rate_n_flags));
+		iwl_hwrate_to_plcp_idx(le32_to_cpu(phy_res->rate_n_flags));
 	if (rx_status.band == IEEE80211_BAND_5GHZ)
 		rx_status.rate_idx -= IWL_FIRST_OFDM_RATE;
 
@@ -983,54 +977,10 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
 	 * this W/A doesn't propagate it to the mac80211 */
 	/*rx_status.flag |= RX_FLAG_TSFT;*/
 
-	if ((unlikely(rx_start->cfg_phy_cnt > 20))) {
-		IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n",
-				rx_start->cfg_phy_cnt);
-		return;
-	}
-
-	if (!include_phy) {
-		if (priv->last_phy_res[0])
-			rx_start = (struct iwl_rx_phy_res *)
-				&priv->last_phy_res[1];
-		else
-			rx_start = NULL;
-	}
-
-	if (!rx_start) {
-		IWL_ERR(priv, "MPDU frame without a PHY data\n");
-		return;
-	}
-
-	if (include_phy) {
-		header = (struct ieee80211_hdr *)((u8 *) &rx_start[1]
-						  + rx_start->cfg_phy_cnt);
-
-		len = le16_to_cpu(rx_start->byte_count);
-		rx_end = (__le32 *)(pkt->u.raw + rx_start->cfg_phy_cnt +
-				  sizeof(struct iwl_rx_phy_res) + len);
-	} else {
-		struct iwl4965_rx_mpdu_res_start *amsdu =
-			(struct iwl4965_rx_mpdu_res_start *)pkt->u.raw;
-
-		header = (void *)(pkt->u.raw +
-			sizeof(struct iwl4965_rx_mpdu_res_start));
-		len = le16_to_cpu(amsdu->byte_count);
-		rx_end = (__le32 *) (pkt->u.raw +
-			sizeof(struct iwl4965_rx_mpdu_res_start) + len);
-	}
-
-	if (!(*rx_end & RX_RES_STATUS_NO_CRC32_ERROR) ||
-	    !(*rx_end & RX_RES_STATUS_NO_RXE_OVERFLOW)) {
-		IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n",
-				le32_to_cpu(*rx_end));
-		return;
-	}
-
-	priv->ucode_beacon_time = le32_to_cpu(rx_start->beacon_time_stamp);
+	priv->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp);
 
 	/* Find max signal strength (dBm) among 3 antenna/receiver chains */
-	rx_status.signal = iwl_calc_rssi(priv, rx_start);
+	rx_status.signal = iwl_calc_rssi(priv, phy_res);
 
 	/* Meaningful noise values are available only from beacon statistics,
 	 *   which are gathered only when associated, and indicate noise
@@ -1050,10 +1000,10 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
 	if (!iwl_is_associated(priv))
 		priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
 
-	/* Set "1" to report good data frames in groups of 100 */
 #ifdef CONFIG_IWLWIFI_DEBUG
+	/* Set "1" to report good data frames in groups of 100 */
 	if (unlikely(iwl_get_debug_level(priv) & IWL_DL_RX))
-		iwl_dbg_report_frame(priv, rx_start, len, header, 1);
+		iwl_dbg_report_frame(priv, phy_res, len, header, 1);
 #endif
 	iwl_dbg_log_rx_data_frame(priv, len, header);
 	IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, qual %d, TSF %llu\n",
@@ -1073,18 +1023,18 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
 	 * new 802.11n radiotap field "RX chains" that is defined
 	 * as a bitmask.
 	 */
-	rx_status.antenna = le16_to_cpu(rx_start->phy_flags &
-					RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4;
+	rx_status.antenna =
+		le16_to_cpu(phy_res->phy_flags & RX_RES_PHY_FLAGS_ANTENNA_MSK)
+		>> RX_RES_PHY_FLAGS_ANTENNA_POS;
 
 	/* set the preamble flag if appropriate */
-	if (rx_start->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
+	if (phy_res->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
 		rx_status.flag |= RX_FLAG_SHORTPRE;
 
-	network_packet = iwl_is_network_packet(priv, header);
-	if (network_packet) {
+	if (iwl_is_network_packet(priv, header)) {
 		priv->last_rx_rssi = rx_status.signal;
 		priv->last_beacon_time =  priv->ucode_beacon_time;
-		priv->last_tsf = le64_to_cpu(rx_start->timestamp);
+		priv->last_tsf = le64_to_cpu(phy_res->timestamp);
 	}
 
 	fc = le16_to_cpu(header->frame_control);
@@ -1096,8 +1046,8 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
 						header->addr2);
 		/* fall through */
 	default:
-			iwl_pass_packet_to_mac80211(priv, include_phy, rxb,
-				   &rx_status);
+		iwl_pass_packet_to_mac80211(priv, header, len, ampdu_status,
+				rxb, &rx_status);
 		break;
 
 	}
-- 
1.5.6.3


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

* [PATCH 08/13] iwlwifi: configure HT40 channels in iwl_mac_config
  2009-08-13 20:30 [PATCH 0/13] iwlwifi driver updates 08/13/2009 Reinette Chatre
                   ` (6 preceding siblings ...)
  2009-08-13 20:30 ` [PATCH 07/13] iwlwifi: refactor packet reception code Reinette Chatre
@ 2009-08-13 20:30 ` Reinette Chatre
  2009-08-13 20:30 ` [PATCH 09/13] iwlwifi: check short GI support per-station rather than globally Reinette Chatre
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Reinette Chatre @ 2009-08-13 20:30 UTC (permalink / raw)
  To: linville
  Cc: linux-wireless, ipw3945-devel, Daniel C Halperin, Reinette Chatre

From: Daniel C Halperin <daniel.c.halperin@intel.com>

As indicated by note in iwl_ht_conf, some HT parameters are set on association
(e.g., channel width) and some vary over time (HT protection mode) and per
station (e.g., short GI support).  The global parameters should be set in
iwl_mac_config and the local/varying parameters in iwl_ht_conf.

This patch moves the channel width configuration from iwl_ht_conf to
iwl_mac_config, and defers further cleanup of the local/global conflation for a
later patch.

This fixes a bug in using HT40 channels in some modes.

Signed-off-by: Daniel C Halperin <daniel.c.halperin@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-core.c |   46 +++++++++++++++++--------------
 1 files changed, 25 insertions(+), 21 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 08345b9..104fd95 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -2398,25 +2398,6 @@ static void iwl_ht_conf(struct iwl_priv *priv,
 
 	iwl_conf->is_green_field = !!(ht_conf->cap & IEEE80211_HT_CAP_GRN_FLD);
 
-	iwl_conf->supported_chan_width =
-		!!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40);
-
-	/*
-	 * XXX: The HT configuration needs to be moved into iwl_mac_config()
-	 *	to be done there correctly.
-	 */
-
-	iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
-	if (conf_is_ht40_minus(&priv->hw->conf))
-		iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
-	else if (conf_is_ht40_plus(&priv->hw->conf))
-		iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
-
-	/* If no above or below channel supplied disable HT40 channel */
-	if (iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_ABOVE &&
-	    iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_BELOW)
-		iwl_conf->supported_chan_width = 0;
-
 	iwl_conf->sm_ps = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2);
 
 	memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16);
@@ -2733,6 +2714,7 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
 	struct iwl_priv *priv = hw->priv;
 	const struct iwl_channel_info *ch_info;
 	struct ieee80211_conf *conf = &hw->conf;
+	struct iwl_ht_info *ht_conf = &priv->current_ht_config;
 	unsigned long flags = 0;
 	int ret = 0;
 	u16 ch;
@@ -2774,10 +2756,32 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
 			goto set_ch_out;
 		}
 
-		priv->current_ht_config.is_ht = conf_is_ht(conf);
-
 		spin_lock_irqsave(&priv->lock, flags);
 
+		/* Configure HT40 channels */
+		ht_conf->is_ht = conf_is_ht(conf);
+		if (ht_conf->is_ht) {
+			if (conf_is_ht40_minus(conf)) {
+				ht_conf->extension_chan_offset =
+					IEEE80211_HT_PARAM_CHA_SEC_BELOW;
+				ht_conf->supported_chan_width =
+					IWL_CHANNEL_WIDTH_40MHZ;
+			} else if (conf_is_ht40_plus(conf)) {
+				ht_conf->extension_chan_offset =
+					IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+				ht_conf->supported_chan_width =
+					IWL_CHANNEL_WIDTH_40MHZ;
+			} else {
+				ht_conf->extension_chan_offset =
+					IEEE80211_HT_PARAM_CHA_SEC_NONE;
+				ht_conf->supported_chan_width =
+					IWL_CHANNEL_WIDTH_20MHZ;
+			}
+		} else
+			ht_conf->supported_chan_width = IWL_CHANNEL_WIDTH_20MHZ;
+		/* Default to no protection. Protection mode will later be set
+		 * from BSS config in iwl_ht_conf */
+		ht_conf->ht_protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE;
 
 		/* if we are switching from ht to 2.4 clear flags
 		 * from any ht related info since 2.4 does not
-- 
1.5.6.3


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

* [PATCH 09/13] iwlwifi: check short GI support per-station rather than globally
  2009-08-13 20:30 [PATCH 0/13] iwlwifi driver updates 08/13/2009 Reinette Chatre
                   ` (7 preceding siblings ...)
  2009-08-13 20:30 ` [PATCH 08/13] iwlwifi: configure HT40 channels in iwl_mac_config Reinette Chatre
@ 2009-08-13 20:30 ` Reinette Chatre
  2009-08-13 20:30 ` [PATCH 10/13] iwlwifi: use station HT capabilities and BSS operating mode for Green-field Reinette Chatre
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Reinette Chatre @ 2009-08-13 20:30 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Daniel C Halperin

From: Daniel C Halperin <daniel.c.halperin@intel.com>

Short guard interval support is a local per-station parameter not a global
per-NIC parameter.  (mac80211 will correctly remove SGI support from station
capabilities if the BSS does not permit it).  This patch removes the short GI
support bitfield from the global iwl_ht_info struct and properly uses
per-station HT capabilities during rate selection.

Signed-off-by: Daniel C Halperin <daniel.c.halperin@intel.com>
Acked-by: Johannes Berg <johannes@sipsolutions.net>
---
 drivers/net/wireless/iwlwifi/iwl-agn-rs.c |   69 ++++++----------------------
 drivers/net/wireless/iwlwifi/iwl-core.c   |    5 --
 drivers/net/wireless/iwlwifi/iwl-dev.h    |    4 --
 3 files changed, 15 insertions(+), 63 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 551c4ba..3b1bbc3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -1225,18 +1225,6 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
 	else
 		tbl->is_ht40 = 0;
 
-	/* FIXME: - don't toggle SGI here
-	if (tbl->is_ht40) {
-		if (priv->current_ht_config.sgf & HT_SHORT_GI_40MHZ_ONLY)
-			tbl->is_SGI = 1;
-		else
-			tbl->is_SGI = 0;
-	} else if (priv->current_ht_config.sgf & HT_SHORT_GI_20MHZ_ONLY)
-		tbl->is_SGI = 1;
-	else
-		tbl->is_SGI = 0;
-	*/
-
 	rs_set_expected_tpt_table(lq_sta, tbl);
 
 	rate = rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index);
@@ -1291,18 +1279,6 @@ static int rs_switch_to_mimo3(struct iwl_priv *priv,
 	else
 		tbl->is_ht40 = 0;
 
-	/* FIXME: - don't toggle SGI here
-	if (tbl->is_ht40) {
-		if (priv->current_ht_config.sgf & HT_SHORT_GI_40MHZ_ONLY)
-			tbl->is_SGI = 1;
-		else
-			tbl->is_SGI = 0;
-	} else if (priv->current_ht_config.sgf & HT_SHORT_GI_20MHZ_ONLY)
-		tbl->is_SGI = 1;
-	else
-		tbl->is_SGI = 0;
-	*/
-
 	rs_set_expected_tpt_table(lq_sta, tbl);
 
 	rate = rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index);
@@ -1350,18 +1326,6 @@ static int rs_switch_to_siso(struct iwl_priv *priv,
 	else
 		tbl->is_ht40 = 0;
 
-	/* FIXME: - don't toggle SGI here
-	if (tbl->is_ht40) {
-		if (priv->current_ht_config.sgf & HT_SHORT_GI_40MHZ_ONLY)
-			tbl->is_SGI = 1;
-		else
-			tbl->is_SGI = 0;
-	} else if (priv->current_ht_config.sgf & HT_SHORT_GI_20MHZ_ONLY)
-		tbl->is_SGI = 1;
-	else
-		tbl->is_SGI = 0;
-	*/
-
 	if (is_green)
 		tbl->is_SGI = 0; /*11n spec: no SGI in SISO+Greenfield*/
 
@@ -1530,6 +1494,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
 	struct iwl_scale_tbl_info *search_tbl =
 				&(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
 	struct iwl_rate_scale_data *window = &(tbl->win[index]);
+	struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
 	u32 sz = (sizeof(struct iwl_scale_tbl_info) -
 		  (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
 	u8 start_action = tbl->action;
@@ -1589,13 +1554,11 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
 				goto out;
 			break;
 		case IWL_SISO_SWITCH_GI:
-			if (!tbl->is_ht40 &&
-				!(priv->current_ht_config.sgf &
-						HT_SHORT_GI_20MHZ))
+			if (!tbl->is_ht40 && !(ht_cap->cap &
+						IEEE80211_HT_CAP_SGI_20))
 				break;
-			if (tbl->is_ht40 &&
-				!(priv->current_ht_config.sgf &
-						HT_SHORT_GI_40MHZ))
+			if (tbl->is_ht40 && !(ht_cap->cap &
+						IEEE80211_HT_CAP_SGI_40))
 				break;
 
 			IWL_DEBUG_RATE(priv, "LQ: SISO toggle SGI/NGI\n");
@@ -1669,6 +1632,7 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv,
 	struct iwl_scale_tbl_info *search_tbl =
 				&(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
 	struct iwl_rate_scale_data *window = &(tbl->win[index]);
+	struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
 	u32 sz = (sizeof(struct iwl_scale_tbl_info) -
 		  (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
 	u8 start_action = tbl->action;
@@ -1729,13 +1693,11 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv,
 			break;
 
 		case IWL_MIMO2_SWITCH_GI:
-			if (!tbl->is_ht40 &&
-				!(priv->current_ht_config.sgf &
-						HT_SHORT_GI_20MHZ))
+			if (!tbl->is_ht40 && !(ht_cap->cap &
+						IEEE80211_HT_CAP_SGI_20))
 				break;
-			if (tbl->is_ht40 &&
-				!(priv->current_ht_config.sgf &
-						HT_SHORT_GI_40MHZ))
+			if (tbl->is_ht40 && !(ht_cap->cap &
+						IEEE80211_HT_CAP_SGI_40))
 				break;
 
 			IWL_DEBUG_RATE(priv, "LQ: MIMO2 toggle SGI/NGI\n");
@@ -1811,6 +1773,7 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv,
 	struct iwl_scale_tbl_info *search_tbl =
 				&(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
 	struct iwl_rate_scale_data *window = &(tbl->win[index]);
+	struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
 	u32 sz = (sizeof(struct iwl_scale_tbl_info) -
 		  (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
 	u8 start_action = tbl->action;
@@ -1893,13 +1856,11 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv,
 			break;
 
 		case IWL_MIMO3_SWITCH_GI:
-			if (!tbl->is_ht40 &&
-				!(priv->current_ht_config.sgf &
-						HT_SHORT_GI_20MHZ))
+			if (!tbl->is_ht40 && !(ht_cap->cap &
+						IEEE80211_HT_CAP_SGI_20))
 				break;
-			if (tbl->is_ht40 &&
-				!(priv->current_ht_config.sgf &
-						HT_SHORT_GI_40MHZ))
+			if (tbl->is_ht40 && !(ht_cap->cap &
+						IEEE80211_HT_CAP_SGI_40))
 				break;
 
 			IWL_DEBUG_RATE(priv, "LQ: MIMO3 toggle SGI/NGI\n");
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 104fd95..b845cf3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -2391,11 +2391,6 @@ static void iwl_ht_conf(struct iwl_priv *priv,
 	}
 	ht_conf = &sta->ht_cap;
 
-	if (ht_conf->cap & IEEE80211_HT_CAP_SGI_20)
-		iwl_conf->sgf |= HT_SHORT_GI_20MHZ;
-	if (ht_conf->cap & IEEE80211_HT_CAP_SGI_40)
-		iwl_conf->sgf |= HT_SHORT_GI_40MHZ;
-
 	iwl_conf->is_green_field = !!(ht_conf->cap & IEEE80211_HT_CAP_GRN_FLD);
 
 	iwl_conf->sm_ps = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index db74534..e6a1c6f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -508,7 +508,6 @@ struct iwl_ht_info {
 	u8 supported_chan_width;
 	u8 sm_ps;
 	u8 is_green_field;
-	u8 sgf;			/* HT_SHORT_GI_* short guard interval */
 	struct ieee80211_mcs_info mcs;
 	/* BSS related data */
 	u8 extension_chan_offset;
@@ -728,9 +727,6 @@ struct iwl_dma_ptr {
 	size_t size;
 };
 
-#define HT_SHORT_GI_20MHZ	(1 << 0)
-#define HT_SHORT_GI_40MHZ	(1 << 1)
-
 #define IWL_CHANNEL_WIDTH_20MHZ   0
 #define IWL_CHANNEL_WIDTH_40MHZ   1
 
-- 
1.5.6.3


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

* [PATCH 10/13] iwlwifi: use station HT capabilities and BSS operating mode for Green-field
  2009-08-13 20:30 [PATCH 0/13] iwlwifi driver updates 08/13/2009 Reinette Chatre
                   ` (8 preceding siblings ...)
  2009-08-13 20:30 ` [PATCH 09/13] iwlwifi: check short GI support per-station rather than globally Reinette Chatre
@ 2009-08-13 20:30 ` Reinette Chatre
  2009-08-13 20:31 ` [PATCH 11/13] iwlwifi: add thermal throttling support to 5150 Reinette Chatre
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Reinette Chatre @ 2009-08-13 20:30 UTC (permalink / raw)
  To: linville
  Cc: linux-wireless, ipw3945-devel, Daniel C Halperin, Reinette Chatre

From: Daniel C Halperin <daniel.c.halperin@intel.com>

Green-field mode should be configured in the HT station table.  This patch uses
both the per-station GF support flag as well as the current BSS HT operation
mode (non-GF stations present flag).

Added the "ht_greenfield_support" field to struct iwl_cfg to replace the
device-specific check in rs_use_green().  That check has been moved to
iwlcore_init_ht_hw_capab().

Signed-off-by: Daniel C Halperin <daniel.c.halperin@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-1000.c   |    1 +
 drivers/net/wireless/iwlwifi/iwl-3945.c   |    6 ++++--
 drivers/net/wireless/iwlwifi/iwl-4965.c   |    3 ++-
 drivers/net/wireless/iwlwifi/iwl-5000.c   |    6 ++++++
 drivers/net/wireless/iwlwifi/iwl-6000.c   |    5 +++++
 drivers/net/wireless/iwlwifi/iwl-agn-rs.c |   26 +++++++++++---------------
 drivers/net/wireless/iwlwifi/iwl-core.c   |    5 ++---
 drivers/net/wireless/iwlwifi/iwl-core.h   |    1 +
 drivers/net/wireless/iwlwifi/iwl-dev.h    |    1 -
 9 files changed, 32 insertions(+), 22 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c
index 9bb6a28..a95caa0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-1000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-1000.c
@@ -158,5 +158,6 @@ struct iwl_cfg iwl1000_bgn_cfg = {
 	.need_pll_cfg = true,
 	.max_ll_items = OTP_MAX_LL_ITEMS_1000,
 	.shadow_ram_support = false,
+	.ht_greenfield_support = true,
 };
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index ba5ef83..b5a4d2e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -2889,7 +2889,8 @@ static struct iwl_cfg iwl3945_bg_cfg = {
 	.eeprom_ver = EEPROM_3945_EEPROM_VERSION,
 	.ops = &iwl3945_ops,
 	.mod_params = &iwl3945_mod_params,
-	.use_isr_legacy = true
+	.use_isr_legacy = true,
+	.ht_greenfield_support = false,
 };
 
 static struct iwl_cfg iwl3945_abg_cfg = {
@@ -2902,7 +2903,8 @@ static struct iwl_cfg iwl3945_abg_cfg = {
 	.eeprom_ver = EEPROM_3945_EEPROM_VERSION,
 	.ops = &iwl3945_ops,
 	.mod_params = &iwl3945_mod_params,
-	.use_isr_legacy = true
+	.use_isr_legacy = true,
+	.ht_greenfield_support = false,
 };
 
 struct pci_device_id iwl3945_hw_card_ids[] = {
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index e427a89..6a13bfb 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -2344,7 +2344,8 @@ struct iwl_cfg iwl4965_agn_cfg = {
 	.eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION,
 	.ops = &iwl4965_ops,
 	.mod_params = &iwl4965_mod_params,
-	.use_isr_legacy = true
+	.use_isr_legacy = true,
+	.ht_greenfield_support = false,
 };
 
 /* Module firmware */
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index 755c184..e1e862e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -1652,6 +1652,7 @@ struct iwl_cfg iwl5300_agn_cfg = {
 	.valid_tx_ant = ANT_ABC,
 	.valid_rx_ant = ANT_ABC,
 	.need_pll_cfg = true,
+	.ht_greenfield_support = true,
 };
 
 struct iwl_cfg iwl5100_bg_cfg = {
@@ -1668,6 +1669,7 @@ struct iwl_cfg iwl5100_bg_cfg = {
 	.valid_tx_ant = ANT_B,
 	.valid_rx_ant = ANT_AB,
 	.need_pll_cfg = true,
+	.ht_greenfield_support = true,
 };
 
 struct iwl_cfg iwl5100_abg_cfg = {
@@ -1684,6 +1686,7 @@ struct iwl_cfg iwl5100_abg_cfg = {
 	.valid_tx_ant = ANT_B,
 	.valid_rx_ant = ANT_AB,
 	.need_pll_cfg = true,
+	.ht_greenfield_support = true,
 };
 
 struct iwl_cfg iwl5100_agn_cfg = {
@@ -1700,6 +1703,7 @@ struct iwl_cfg iwl5100_agn_cfg = {
 	.valid_tx_ant = ANT_B,
 	.valid_rx_ant = ANT_AB,
 	.need_pll_cfg = true,
+	.ht_greenfield_support = true,
 };
 
 struct iwl_cfg iwl5350_agn_cfg = {
@@ -1716,6 +1720,7 @@ struct iwl_cfg iwl5350_agn_cfg = {
 	.valid_tx_ant = ANT_ABC,
 	.valid_rx_ant = ANT_ABC,
 	.need_pll_cfg = true,
+	.ht_greenfield_support = true,
 };
 
 struct iwl_cfg iwl5150_agn_cfg = {
@@ -1732,6 +1737,7 @@ struct iwl_cfg iwl5150_agn_cfg = {
 	.valid_tx_ant = ANT_A,
 	.valid_rx_ant = ANT_AB,
 	.need_pll_cfg = true,
+	.ht_greenfield_support = true,
 };
 
 MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX));
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index 0b731fd..383177d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -171,6 +171,7 @@ struct iwl_cfg iwl6000h_2agn_cfg = {
 	.pa_type = IWL_PA_HYBRID,
 	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
 	.shadow_ram_support = true,
+	.ht_greenfield_support = true,
 };
 
 /*
@@ -193,6 +194,7 @@ struct iwl_cfg iwl6000i_2agn_cfg = {
 	.pa_type = IWL_PA_INTERNAL,
 	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
 	.shadow_ram_support = true,
+	.ht_greenfield_support = true,
 };
 
 struct iwl_cfg iwl6050_2agn_cfg = {
@@ -212,6 +214,7 @@ struct iwl_cfg iwl6050_2agn_cfg = {
 	.pa_type = IWL_PA_SYSTEM,
 	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
 	.shadow_ram_support = true,
+	.ht_greenfield_support = true,
 };
 
 struct iwl_cfg iwl6000_3agn_cfg = {
@@ -231,6 +234,7 @@ struct iwl_cfg iwl6000_3agn_cfg = {
 	.pa_type = IWL_PA_SYSTEM,
 	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
 	.shadow_ram_support = true,
+	.ht_greenfield_support = true,
 };
 
 struct iwl_cfg iwl6050_3agn_cfg = {
@@ -250,6 +254,7 @@ struct iwl_cfg iwl6050_3agn_cfg = {
 	.pa_type = IWL_PA_SYSTEM,
 	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
 	.shadow_ram_support = true,
+	.ht_greenfield_support = true,
 };
 
 MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX));
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 3b1bbc3..fee110d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -657,19 +657,15 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags,
 	return 1;
 }
 
-/* in 4965 we don't use greenfield at all */
-static inline u8 rs_use_green(struct iwl_priv *priv,
-			      struct ieee80211_conf *conf)
+/**
+ * Green-field mode is valid if the station supports it and
+ * there are no non-GF stations present in the BSS.
+ */
+static inline u8 rs_use_green(struct ieee80211_sta *sta,
+			      struct iwl_ht_info *ht_conf)
 {
-	u8 is_green;
-
-	if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965)
-		is_green = 0;
-	else
-		is_green = (conf_is_ht(conf) &&
-			   priv->current_ht_config.is_green_field &&
-			   !priv->current_ht_config.non_GF_STA_present);
-	return is_green;
+	return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) &&
+		!(ht_conf->non_GF_STA_present);
 }
 
 /**
@@ -2072,7 +2068,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
 	if (is_legacy(tbl->lq_type))
 		lq_sta->is_green = 0;
 	else
-		lq_sta->is_green = rs_use_green(priv, conf);
+		lq_sta->is_green = rs_use_green(sta, &priv->current_ht_config);
 	is_green = lq_sta->is_green;
 
 	/* current tx rate */
@@ -2430,7 +2426,7 @@ static void rs_initialize_lq(struct iwl_priv *priv,
 	int rate_idx;
 	int i;
 	u32 rate;
-	u8 use_green = rs_use_green(priv, conf);
+	u8 use_green = rs_use_green(sta, &priv->current_ht_config);
 	u8 active_tbl = 0;
 	u8 valid_tx_ant;
 
@@ -2627,7 +2623,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
 	lq_sta->is_dup = 0;
 	lq_sta->max_rate_idx = -1;
 	lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX;
-	lq_sta->is_green = rs_use_green(priv, conf);
+	lq_sta->is_green = rs_use_green(sta, &priv->current_ht_config);
 	lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000);
 	lq_sta->active_rate_basic = priv->active_rate_basic;
 	lq_sta->band = priv->band;
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index b845cf3..62aa87b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -394,7 +394,8 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
 
 	ht_info->ht_supported = true;
 
-	ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD;
+	if (priv->cfg->ht_greenfield_support)
+		ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD;
 	ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
 	ht_info->cap |= (IEEE80211_HT_CAP_SM_PS &
 			     (WLAN_HT_CAP_SM_PS_DISABLED << 2));
@@ -2391,8 +2392,6 @@ static void iwl_ht_conf(struct iwl_priv *priv,
 	}
 	ht_conf = &sta->ht_cap;
 
-	iwl_conf->is_green_field = !!(ht_conf->cap & IEEE80211_HT_CAP_GRN_FLD);
-
 	iwl_conf->sm_ps = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2);
 
 	memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16);
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 5096834..4ca025a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -251,6 +251,7 @@ struct iwl_cfg {
 	enum iwl_pa_type pa_type;
 	const u16 max_ll_items;
 	const bool shadow_ram_support;
+	const bool ht_greenfield_support;
 };
 
 /***************************
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index e6a1c6f..0178734 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -507,7 +507,6 @@ struct iwl_ht_info {
 	u8 is_ht;
 	u8 supported_chan_width;
 	u8 sm_ps;
-	u8 is_green_field;
 	struct ieee80211_mcs_info mcs;
 	/* BSS related data */
 	u8 extension_chan_offset;
-- 
1.5.6.3


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

* [PATCH 11/13] iwlwifi: add thermal throttling support to 5150
  2009-08-13 20:30 [PATCH 0/13] iwlwifi driver updates 08/13/2009 Reinette Chatre
                   ` (9 preceding siblings ...)
  2009-08-13 20:30 ` [PATCH 10/13] iwlwifi: use station HT capabilities and BSS operating mode for Green-field Reinette Chatre
@ 2009-08-13 20:31 ` Reinette Chatre
  2009-08-13 20:31 ` [PATCH 12/13] iwlwifi: fix erroneous use of iwl_rx_packet.len as a length Reinette Chatre
  2009-08-13 20:31 ` [PATCH 13/13] iwlwifi: disable PS by default Reinette Chatre
  12 siblings, 0 replies; 14+ messages in thread
From: Reinette Chatre @ 2009-08-13 20:31 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy, Reinette Chatre

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

Adding legacy thermal throttling management support to 5150 NIC

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

diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index e1e862e..720d234 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -1411,6 +1411,7 @@ static void iwl5150_temperature(struct iwl_priv *priv)
 	vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset;
 	/* now vt hold the temperature in Kelvin */
 	priv->temperature = KELVIN_TO_CELSIUS(vt);
+	iwl_tt_handler(priv);
 }
 
 /* Calc max signal level (dBm) among 3 possible receivers */
-- 
1.5.6.3


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

* [PATCH 12/13] iwlwifi: fix erroneous use of iwl_rx_packet.len as a length
  2009-08-13 20:30 [PATCH 0/13] iwlwifi driver updates 08/13/2009 Reinette Chatre
                   ` (10 preceding siblings ...)
  2009-08-13 20:31 ` [PATCH 11/13] iwlwifi: add thermal throttling support to 5150 Reinette Chatre
@ 2009-08-13 20:31 ` Reinette Chatre
  2009-08-13 20:31 ` [PATCH 13/13] iwlwifi: disable PS by default Reinette Chatre
  12 siblings, 0 replies; 14+ messages in thread
From: Reinette Chatre @ 2009-08-13 20:31 UTC (permalink / raw)
  To: linville
  Cc: linux-wireless, ipw3945-devel, Daniel C Halperin, Reinette Chatre

From: Daniel C Halperin <daniel.c.halperin@intel.com>

The field called 'len' in struct iwl_rx_packet is in fact not just a length
field but also includes some flags from the flow handler.  In several places
throughout the driver, this causes incorrect values to be interpreted as
lengths when the field is improperly masked.

In most situations the improper use is for debugging output, and simply results
in an erroneous message, such as:

[551933.070224] ieee80211 phy0: I iwl_rx_statistics Statistics notification received (480 vs -1367342620).

which should read '(480 vs 484)'.

In at least one case this could case bad things to happen:

void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
                                      struct iwl_rx_mem_buffer *rxb)
{
        struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
        IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled "
                        "notification for %s:\n",
                        le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd));
        iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len)
);
}
EXPORT_SYMBOL(iwl_rx_pm_debug_statistics_notif);

Given the rampant misuse of this field without proper masking throughout the
driver (every use but one), this patch renames the field from 'len' to
'len_n_flags' to reduce confusion.  It also adds the proper masking when
this field is used as a length value.

Signed-off-by: Daniel C Halperin <daniel.c.halperin@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-3945.c     |    5 +++--
 drivers/net/wireless/iwlwifi/iwl-5000.c     |    2 +-
 drivers/net/wireless/iwlwifi/iwl-commands.h |    2 +-
 drivers/net/wireless/iwlwifi/iwl-core.c     |    7 ++++---
 drivers/net/wireless/iwlwifi/iwl-rx.c       |    3 ++-
 5 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index b5a4d2e..e9a685d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -349,12 +349,13 @@ static void iwl3945_rx_reply_tx(struct iwl_priv *priv,
  *
  *****************************************************************************/
 
-void iwl3945_hw_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
+void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
+		struct iwl_rx_mem_buffer *rxb)
 {
 	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
 	IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
 		     (int)sizeof(struct iwl3945_notif_statistics),
-		     le32_to_cpu(pkt->len));
+		     le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
 
 	memcpy(&priv->statistics_39, pkt->u.raw, sizeof(priv->statistics_39));
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index 720d234..1d539e3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -494,7 +494,7 @@ static void iwl5000_rx_calib_result(struct iwl_priv *priv,
 {
 	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
 	struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw;
-	int len = le32_to_cpu(pkt->len) & FH_RSCSR_FRAME_SIZE_MSK;
+	int len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
 	int index;
 
 	/* reduce the size of the length field itself */
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 9398ad7..f430384 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -3482,7 +3482,7 @@ struct iwl_wimax_coex_cmd {
  *****************************************************************************/
 
 struct iwl_rx_packet {
-	__le32 len;
+	__le32 len_n_flags;
 	struct iwl_cmd_header hdr;
 	union {
 		struct iwl3945_rx_frame rx_frame;
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 62aa87b..f4c2431 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -2294,10 +2294,11 @@ void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
 				      struct iwl_rx_mem_buffer *rxb)
 {
 	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
+	u32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
 	IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled "
-			"notification for %s:\n",
-			le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd));
-	iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len));
+			"notification for %s:\n", len,
+			get_cmd_string(pkt->hdr.cmd));
+	iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, len);
 }
 EXPORT_SYMBOL(iwl_rx_pm_debug_statistics_notif);
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index 092d327..353d9a2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -539,7 +539,8 @@ void iwl_rx_statistics(struct iwl_priv *priv,
 	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
 
 	IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
-		     (int)sizeof(priv->statistics), pkt->len);
+		     (int)sizeof(priv->statistics),
+		     le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
 
 	change = ((priv->statistics.general.temperature !=
 		   pkt->u.stats.general.temperature) ||
-- 
1.5.6.3


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

* [PATCH 13/13] iwlwifi: disable PS by default
  2009-08-13 20:30 [PATCH 0/13] iwlwifi driver updates 08/13/2009 Reinette Chatre
                   ` (11 preceding siblings ...)
  2009-08-13 20:31 ` [PATCH 12/13] iwlwifi: fix erroneous use of iwl_rx_packet.len as a length Reinette Chatre
@ 2009-08-13 20:31 ` Reinette Chatre
  12 siblings, 0 replies; 14+ messages in thread
From: Reinette Chatre @ 2009-08-13 20:31 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Johannes Berg, Reinette Chatre

From: Johannes Berg <johannes@sipsolutions.net>

Unfortunately, PS currently affects RX performance
significantly enough to warrant disabling it by
default, but give the user the choice to enable it
again with iwconfig.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-core.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index f4c2431..c0efa66 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1580,6 +1580,12 @@ int iwl_setup_mac(struct iwl_priv *priv)
 	/* Firmware does not support this */
 	hw->wiphy->disable_beacon_hints = true;
 
+	/*
+	 * For now, disable PS by default because it affects
+	 * RX performance significantly.
+	 */
+	hw->wiphy->ps_default = false;
+
 	hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX;
 	/* we create the 802.11 header and a zero-length SSID element */
 	hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2;
-- 
1.5.6.3


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

end of thread, other threads:[~2009-08-13 20:31 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-08-13 20:30 [PATCH 0/13] iwlwifi driver updates 08/13/2009 Reinette Chatre
2009-08-13 20:30 ` [PATCH 01/13] iwlwifi: prevent read outside array bounds Reinette Chatre
2009-08-13 20:30 ` [PATCH 02/13] iwlwifi: remove unused HT configuration entry tx_chan_width Reinette Chatre
2009-08-13 20:30 ` [PATCH 03/13] iwlwifi: include HT configuration when adding stations through rs_rate_init Reinette Chatre
2009-08-13 20:30 ` [PATCH 04/13] iwlwifi: cleanup HT40 extension channels setup Reinette Chatre
2009-08-13 20:30 ` [PATCH 05/13] iwlwifi: traverse linklist to find the valid OTP block Reinette Chatre
2009-08-13 20:30 ` [PATCH 06/13] iwlwifi: remove unused members of iwl_ht_info Reinette Chatre
2009-08-13 20:30 ` [PATCH 07/13] iwlwifi: refactor packet reception code Reinette Chatre
2009-08-13 20:30 ` [PATCH 08/13] iwlwifi: configure HT40 channels in iwl_mac_config Reinette Chatre
2009-08-13 20:30 ` [PATCH 09/13] iwlwifi: check short GI support per-station rather than globally Reinette Chatre
2009-08-13 20:30 ` [PATCH 10/13] iwlwifi: use station HT capabilities and BSS operating mode for Green-field Reinette Chatre
2009-08-13 20:31 ` [PATCH 11/13] iwlwifi: add thermal throttling support to 5150 Reinette Chatre
2009-08-13 20:31 ` [PATCH 12/13] iwlwifi: fix erroneous use of iwl_rx_packet.len as a length Reinette Chatre
2009-08-13 20:31 ` [PATCH 13/13] iwlwifi: disable PS by default Reinette Chatre

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).