Skip to contentSkip to conversation

pull request: iwlwifi-next 2014-05-07

PATCH New Emmanuel Grumbach 2 participants 25 messages May 7, 2014 – May 8, 2014 Networking drivers (wireless)

lore
Share & tools
lore
#0 lore raw

Hi John,

I have here another pull request for 3.16.
I merged wireless-next.git because of dependencies on changes in mac80211. I merged iwlwifi-fixes.git (that feeds wireless.git) because of dependencies in the rate scaling changes that were sent to wireless.git.

Eran continues to work on new devices, Eyal is still digging in the rate control stuff, and Johannes added new functionality to the debug system we have in place now along with a few cleanups he made on the way. That's pretty much it.

Please pull.

The following changes since commit 48d11dc37977614a461bfedddc52d1c651bc279f:

rsi: Changing opcode for sta mode according to changes in firmware (2014-04-30 12:13:16 -0400)

are available in the git repository at:

git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next.git for-john

for you to fetch changes up to 017a64161f6d082f6e3ed85646217bd7217af15a:

iwlwifi: mvm: rs: enable MCS9 for Tx (2014-05-07 22:44:43 +0300)

----------------------------------------------------------------
Alexander Bondar (1):
iwlwifi: mvm: several fixes in scan

Andrei Otcheretianski (1):
iwlwifi:mvm: Add AP/GO channel switch support

Eliad Peller (1):
iwlwifi: mvm: wait for d0i3 exit in some more ampdu actions

Emmanuel Grumbach (6):
iwlwifi: mvm: BT Coex - fix validity flags during init
iwlwifi: mvm: rs - s/CPTCFG/CONFIG
Merge remote-tracking branch 'iwlwifi-fixes/master' into iwlwifi-next Merge remote-tracking branch 'wireless-next/master' into iwlwifi-next
iwlwifi: mvm: implement mac80211's flush callback
iwlwifi: mvm: fix sparse warning when _DEBUGFS isn't set

Eran Harary (5):
iwlwifi: mvm: fix bug with OTP memory size
iwlwifi: mvm: prevent nic to powered up at driver load
iwlwifi: mvm: Prioritize external nvm values on top of the OTP values
iwlwifi: mvm: select the MAC address according to priority
iwlwifi: mvm: fix bug in parse_nvm_sections

Eyal Shapira (6):
iwlwifi: mvm: rs: revert changes to search cycle rules
iwlwifi: mvm: rs: overhaul rs_get_best_rate
iwlwifi: mvm: rs: don't allow TPC when power save is disabled
iwlwifi: mvm: rs: avoid TPC while in search cycle
iwlwifi: mvm: rs: choose correct expected tpt table
iwlwifi: mvm: rs: enable MCS9 for Tx

Johannes Berg (5):
iwlwifi: mvm: remove useless variable
iwlwifi: make LED support optional
iwlwifi: pcie: use bool for iwl_pcie_txq_build_tfd() argument
iwlwifi: pcie: get rid of q->n_bd
iwlwifi: mvm/pcie: capture last commands on firmware error

 drivers/net/wireless/iwlwifi/Kconfig                                      |  12 ++++++---
 drivers/net/wireless/iwlwifi/dvm/Makefile                                 |   3 ++-
 drivers/net/wireless/iwlwifi/dvm/dev.h                                    |   2 ++
 drivers/net/wireless/iwlwifi/dvm/led.h                                    |  12 +++++++++
 drivers/net/wireless/iwlwifi/iwl-7000.c                                   |   2 +-
 drivers/net/wireless/iwlwifi/iwl-8000.c                                   |   2 +-
 drivers/net/wireless/iwlwifi/iwl-agn-hw.h                                 |   4 +--
 drivers/net/wireless/iwlwifi/iwl-config.h                                 |   6 +++++
 drivers/net/wireless/iwlwifi/{mvm/fw-error-dump.h => iwl-fw-error-dump.h} |  26 +++++++++++++++++++
 drivers/net/wireless/iwlwifi/iwl-fw.h                                     |   2 ++
 drivers/net/wireless/iwlwifi/iwl-nvm-parse.c                              |  46 +++++++++++++++++++++++++++------
 drivers/net/wireless/iwlwifi/iwl-trans.h                                  |  19 ++++++++++++++
 drivers/net/wireless/iwlwifi/mvm/Makefile                                 |   3 ++-
 drivers/net/wireless/iwlwifi/mvm/coex.c                                   |   6 ++---
 drivers/net/wireless/iwlwifi/mvm/debugfs.c                                |   2 +-
 drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h                            |   8 +++---
 drivers/net/wireless/iwlwifi/mvm/fw.c                                     |   2 +-
 drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c                               |  12 +++++++++
 drivers/net/wireless/iwlwifi/mvm/mac80211.c                               |  91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 drivers/net/wireless/iwlwifi/mvm/mvm.h                                    |  16 +++++++++++-
 drivers/net/wireless/iwlwifi/mvm/nvm.c                                    |  30 ++++++++++++++--------
 drivers/net/wireless/iwlwifi/mvm/ops.c                                    |  36 ++++++++++++++++++++------
 drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c                               |   9 +++----
 drivers/net/wireless/iwlwifi/mvm/rs.c                                     | 173 +++++++++++++++++++++++++++++++++++++++++----------------------------------------------------------------------------------
 drivers/net/wireless/iwlwifi/mvm/scan.c                                   |  53 +++++++++-----------------------------
 drivers/net/wireless/iwlwifi/mvm/utils.c                                  |   2 ++
 drivers/net/wireless/iwlwifi/pcie/internal.h                              |  24 +++++++++--------
 drivers/net/wireless/iwlwifi/pcie/rx.c                                    |   2 +-
 drivers/net/wireless/iwlwifi/pcie/trans.c                                 |  64 ++++++++++++++++++++++++++++++++++++++++++++--
 drivers/net/wireless/iwlwifi/pcie/tx.c                                    | 129 ++++++++++++++++++++++++++++++++++++++++++++++---------------------------------------------
 30 files changed, 507 insertions(+), 291 deletions(-)
 rename drivers/net/wireless/iwlwifi/{mvm/fw-error-dump.h => iwl-fw-error-dump.h} (84%)
#1 lore raw

PATCH 1/23 iwlwifi: mvm: several fixes in scan

From: Alexander Bondar <[email protected]>

The firmware doesn't handle properly the fragmented scan. Stop using it.
While at it change max_out_time and suspend_time units from usec to TUs as expected by firmware API.

---
 drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h |  8 ++--
 drivers/net/wireless/iwlwifi/mvm/scan.c        | 53 ++++++--------------------
 2 files changed, 16 insertions(+), 45 deletions(-)
drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h +4 -4
index 9426905..d73a89e 100644
@@ -183,9 +183,9 @@ enum iwl_scan_type {
  *	this number of packets were received (typically 1)
  * @passive2active: is auto switching from passive to active during scan allowed
  * @rxchain_sel_flags: RXON_RX_CHAIN_*
- * @max_out_time: in usecs, max out of serving channel time
+ * @max_out_time: in TUs, max out of serving channel time
  * @suspend_time: how long to pause scan when returning to service channel:
- *	bits 0-19: beacon interal in usecs (suspend before executing)
+ *	bits 0-19: beacon interal in TUs (suspend before executing)
  *	bits 20-23: reserved
  *	bits 24-31: number of beacons (suspend between channels)
  * @rxon_flags: RXON_FLG_*
@@ -383,8 +383,8 @@ enum scan_framework_client {
  * @quiet_plcp_th:	quiet channel num of packets threshold
  * @good_CRC_th:	passive to active promotion threshold
  * @rx_chain:		RXON rx chain.
- * @max_out_time:	max uSec to be out of assoceated channel
- * @suspend_time:	pause scan this long when returning to service channel
+ * @max_out_time:	max TUs to be out of assoceated channel
+ * @suspend_time:	pause scan this TUs when returning to service channel
  * @flags:		RXON flags
  * @filter_flags:	RXONfilter
  * @tx_cmd:		tx command for active scan; for 2GHz and for 5GHz.
drivers/net/wireless/iwlwifi/mvm/scan.c +12 -41

63 lines not on this page · raw message

Signature · 1 line
1.8.3.2
#2 lore raw

PATCH 2/23 iwlwifi: mvm: BT Coex - fix validity flags during init

In reply to Emmanuel Grumbach

From: Emmanuel Grumbach <[email protected]>

The commit below introduced a bug in the validity bits in init. Due to that, all the Coex mechanism stopped sending kills to the BT side. Fix that.

Fixes b9fae2d54c9f ("iwlwifi: mvm: BT Coex add support for Co-running block")
---
 drivers/net/wireless/iwlwifi/mvm/coex.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/net/wireless/iwlwifi/mvm/coex.c +3 -3
index fa858d54..0489314 100644
@@ -611,14 +611,14 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
 		bt_cmd->flags |= cpu_to_le32(BT_COEX_SYNC2SCO);
 
 	if (IWL_MVM_BT_COEX_CORUNNING) {
-		bt_cmd->valid_bit_msk = cpu_to_le32(BT_VALID_CORUN_LUT_20 |
-						    BT_VALID_CORUN_LUT_40);
+		bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_CORUN_LUT_20 |
+						     BT_VALID_CORUN_LUT_40);
 		bt_cmd->flags |= cpu_to_le32(BT_COEX_CORUNNING);
 	}
 
 	if (IWL_MVM_BT_COEX_MPLUT) {
 		bt_cmd->flags |= cpu_to_le32(BT_COEX_MPLUT);
-		bt_cmd->valid_bit_msk = cpu_to_le32(BT_VALID_MULTI_PRIO_LUT);
+		bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_MULTI_PRIO_LUT);
 	}
 
 	if (mvm->cfg->bt_shared_single_ant)
Signature · 1 line
1.8.3.2
#3 lore raw

PATCH 3/23 iwlwifi: mvm: rs - s/CPTCFG/CONFIG

In reply to Emmanuel Grumbach

From: Emmanuel Grumbach <[email protected]>

My bad - I forgot to update this when sending the patch upstream.

Fixes 87d5e4155c00 ("iwlwifi: mvm: rs: reinit rs if no tx for a long time")
---
 drivers/net/wireless/iwlwifi/mvm/rs.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/iwlwifi/mvm/rs.c +1 -1
index 9f52c5b..e1c8388 100644
@@ -1010,7 +1010,7 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband,
 		return;
 	}
 
-#ifdef CPTCFG_MAC80211_DEBUGFS
+#ifdef CONFIG_MAC80211_DEBUGFS
 	/* Disable last tx check if we are debugging with fixed rate */
 	if (lq_sta->dbg_fixed_rate) {
 		IWL_DEBUG_RATE(mvm, "Fixed rate. avoid rate scaling\n");
Signature · 1 line
1.8.3.2
#4 lore raw

PATCH 4/23 iwlwifi: mvm: rs: revert changes to search cycle rules

In reply to Emmanuel Grumbach

From: Eyal Shapira <[email protected]>

Adding more options in the search cycle causes longer search cycles with additional wondering off to non optimal Tx configurations. Reduce the Tx configurations searched to improve throughput in non optimal attenuations.

---
 drivers/net/wireless/iwlwifi/mvm/rs.c | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)
drivers/net/wireless/iwlwifi/mvm/rs.c +14 -14
index 857ddaf..f9aab15 100644
@@ -211,7 +211,7 @@ static const struct rs_tx_column rs_tx_columns[] = {
 		.next_columns = {
 			RS_COLUMN_LEGACY_ANT_B,
 			RS_COLUMN_SISO_ANT_A,
-			RS_COLUMN_SISO_ANT_B,
+			RS_COLUMN_MIMO2,
 			RS_COLUMN_INVALID,
 			RS_COLUMN_INVALID,
 			RS_COLUMN_INVALID,
@@ -223,8 +223,8 @@ static const struct rs_tx_column rs_tx_columns[] = {
 		.ant = ANT_B,
 		.next_columns = {
 			RS_COLUMN_LEGACY_ANT_A,
-			RS_COLUMN_SISO_ANT_A,
 			RS_COLUMN_SISO_ANT_B,
+			RS_COLUMN_MIMO2,
 			RS_COLUMN_INVALID,
 			RS_COLUMN_INVALID,
 			RS_COLUMN_INVALID,
@@ -238,10 +238,10 @@ static const struct rs_tx_column rs_tx_columns[] = {
 			RS_COLUMN_SISO_ANT_B,
 			RS_COLUMN_MIMO2,
 			RS_COLUMN_SISO_ANT_A_SGI,
-			RS_COLUMN_SISO_ANT_B_SGI,
 			RS_COLUMN_LEGACY_ANT_A,
 			RS_COLUMN_LEGACY_ANT_B,
 			RS_COLUMN_INVALID,
+			RS_COLUMN_INVALID,
 		},
 		.checks = {
 			rs_siso_allow,
@@ -254,10 +254,10 @@ static const struct rs_tx_column rs_tx_columns[] = {
 			RS_COLUMN_SISO_ANT_A,
 			RS_COLUMN_MIMO2,
 			RS_COLUMN_SISO_ANT_B_SGI,
-			RS_COLUMN_SISO_ANT_A_SGI,
 			RS_COLUMN_LEGACY_ANT_A,
 			RS_COLUMN_LEGACY_ANT_B,
 			RS_COLUMN_INVALID,
+			RS_COLUMN_INVALID,
 		},
 		.checks = {
 			rs_siso_allow,
@@ -271,10 +271,10 @@ static const struct rs_tx_column rs_tx_columns[] = {
 			RS_COLUMN_SISO_ANT_B_SGI,
 			RS_COLUMN_MIMO2_SGI,
 			RS_COLUMN_SISO_ANT_A,
-			RS_COLUMN_SISO_ANT_B,
-			RS_COLUMN_MIMO2,
 			RS_COLUMN_LEGACY_ANT_A,
 			RS_COLUMN_LEGACY_ANT_B,
+			RS_COLUMN_INVALID,
+			RS_COLUMN_INVALID,
 		},
 		.checks = {
 			rs_siso_allow,
@@ -289,10 +289,10 @@ static const struct rs_tx_column rs_tx_columns[] = {
 			RS_COLUMN_SISO_ANT_A_SGI,
 			RS_COLUMN_MIMO2_SGI,
 			RS_COLUMN_SISO_ANT_B,
-			RS_COLUMN_SISO_ANT_A,
-			RS_COLUMN_MIMO2,
 			RS_COLUMN_LEGACY_ANT_A,
 			RS_COLUMN_LEGACY_ANT_B,
+			RS_COLUMN_INVALID,
+			RS_COLUMN_INVALID,
 		},
 		.checks = {
 			rs_siso_allow,
@@ -304,12 +304,12 @@ static const struct rs_tx_column rs_tx_columns[] = {
 		.ant = ANT_AB,
 		.next_columns = {
 			RS_COLUMN_SISO_ANT_A,
-			RS_COLUMN_SISO_ANT_B,
-			RS_COLUMN_SISO_ANT_A_SGI,
-			RS_COLUMN_SISO_ANT_B_SGI,
 			RS_COLUMN_MIMO2_SGI,
 			RS_COLUMN_LEGACY_ANT_A,
 			RS_COLUMN_LEGACY_ANT_B,
+			RS_COLUMN_INVALID,
+			RS_COLUMN_INVALID,
+			RS_COLUMN_INVALID,
 		},
 		.checks = {
 			rs_mimo_allow,
@@ -321,12 +321,12 @@ static const struct rs_tx_column rs_tx_columns[] = {
 		.sgi = true,
 		.next_columns = {
 			RS_COLUMN_SISO_ANT_A_SGI,
-			RS_COLUMN_SISO_ANT_B_SGI,
-			RS_COLUMN_SISO_ANT_A,
-			RS_COLUMN_SISO_ANT_B,
 			RS_COLUMN_MIMO2,
 			RS_COLUMN_LEGACY_ANT_A,
 			RS_COLUMN_LEGACY_ANT_B,
+			RS_COLUMN_INVALID,
+			RS_COLUMN_INVALID,
+			RS_COLUMN_INVALID,
 		},
 		.checks = {
 			rs_mimo_allow,
Signature · 1 line
1.8.3.2
#5 lore raw

PATCH 5/23 iwlwifi: mvm: rs: overhaul rs_get_best_rate

In reply to Emmanuel Grumbach

From: Eyal Shapira <[email protected]>

rs_get_best_rate determines the optimal rate to try in a new Tx column. Currently we were sometimes trying a too high rate which would lead us to fail and avoid switching to the new column despite it having a potential to be better. Change the logic to try and find the first rate which would exceed the current actual throughput or be more aggressive if the success ratio is good.

---
 drivers/net/wireless/iwlwifi/mvm/rs.c | 117 +++++++++-------------------------
 1 file changed, 31 insertions(+), 86 deletions(-)
drivers/net/wireless/iwlwifi/mvm/rs.c +31 -86
index f9aab15..a7ad532 100644
@@ -1335,105 +1335,50 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta,
 	tbl->expected_tpt = rs_get_expected_tpt_table(lq_sta, column, rate->bw);
 }
 
-/*
- * Find starting rate for new "search" high-throughput mode of modulation.
- * Goal is to find lowest expected rate (under perfect conditions) that is
- * above the current measured throughput of "active" mode, to give new mode
- * a fair chance to prove itself without too many challenges.
- *
- * This gets called when transitioning to more aggressive modulation
- * (i.e. legacy to SISO or MIMO, or SISO to MIMO), as well as less aggressive
- * (i.e. MIMO to SISO).  When moving to MIMO, bit rate will typically need
- * to decrease to match "active" throughput.  When moving from MIMO to SISO,
- * bit rate will typically need to increase, but not if performance was bad.
- */
 static s32 rs_get_best_rate(struct iwl_mvm *mvm,
 			    struct iwl_lq_sta *lq_sta,
 			    struct iwl_scale_tbl_info *tbl,	/* "search" */
-			    u16 rate_mask, s8 index)
+			    unsigned long rate_mask, s8 index)
 {
-	/* "active" values */
 	struct iwl_scale_tbl_info *active_tbl =
 	    &(lq_sta->lq_info[lq_sta->active_tbl]);
-	s32 active_sr = active_tbl->win[index].success_ratio;
-	s32 active_tpt = active_tbl->expected_tpt[index];
-	/* expected "search" throughput */
+	s32 success_ratio = active_tbl->win[index].success_ratio;
+	u16 expected_current_tpt = active_tbl->expected_tpt[index];
 	const u16 *tpt_tbl = tbl->expected_tpt;
-
-	s32 new_rate, high, low, start_hi;
 	u16 high_low;
-	s8 rate = index;
-
-	new_rate = high = low = start_hi = IWL_RATE_INVALID;
-
-	while (1) {
-		high_low = rs_get_adjacent_rate(mvm, rate, rate_mask,
-						tbl->rate.type);
-
-		low = high_low & 0xff;
-		high = (high_low >> 8) & 0xff;
-
-		/*
-		 * Lower the "search" bit rate, to give new "search" mode
-		 * approximately the same throughput as "active" if:
-		 *
-		 * 1) "Active" mode has been working modestly well (but not
-		 *    great), and expected "search" throughput (under perfect
-		 *    conditions) at candidate rate is above the actual
-		 *    measured "active" throughput (but less than expected
-		 *    "active" throughput under perfect conditions).
-		 * OR
-		 * 2) "Active" mode has been working perfectly or very well
-		 *    and expected "search" throughput (under perfect
-		 *    conditions) at candidate rate is above expected
-		 *    "active" throughput (under perfect conditions).
-		 */
-		if ((((100 * tpt_tbl[rate]) > lq_sta->last_tpt) &&
-		     ((active_sr > RS_SR_FORCE_DECREASE) &&
-		      (active_sr <= IWL_RATE_HIGH_TH) &&
-		      (tpt_tbl[rate] <= active_tpt))) ||
-		    ((active_sr >= IWL_RATE_SCALE_SWITCH) &&
-		     (tpt_tbl[rate] > active_tpt))) {
-			/* (2nd or later pass)
-			 * If we've already tried to raise the rate, and are
-			 * now trying to lower it, use the higher rate. */
-			if (start_hi != IWL_RATE_INVALID) {
-				new_rate = start_hi;
-				break;
-			}
-
-			new_rate = rate;
+	u32 target_tpt;
+	int rate_idx;
 
-			/* Loop again with lower rate */
-			if (low != IWL_RATE_INVALID)
-				rate = low;
+	if (success_ratio > RS_SR_NO_DECREASE) {
+		target_tpt = 100 * expected_current_tpt;
+		IWL_DEBUG_RATE(mvm,
+			       "SR %d high. Find rate exceeding EXPECTED_CURRENT %d\n",
+			       success_ratio, target_tpt);
+	} else {
+		target_tpt = lq_sta->last_tpt;
+		IWL_DEBUG_RATE(mvm,
+			       "SR %d not thag good. Find rate exceeding ACTUAL_TPT %d\n",
+			       success_ratio, target_tpt);
+	}
 
-			/* Lower rate not available, use the original */
-			else
-				break;
+	rate_idx = find_first_bit(&rate_mask, BITS_PER_LONG);
 
-		/* Else try to raise the "search" rate to match "active" */
-		} else {
-			/* (2nd or later pass)
-			 * If we've already tried to lower the rate, and are
-			 * now trying to raise it, use the lower rate. */
-			if (new_rate != IWL_RATE_INVALID)
-				break;
+	while (rate_idx != IWL_RATE_INVALID) {
+		if (target_tpt < (100 * tpt_tbl[rate_idx]))
+			break;
 
-			/* Loop again with higher rate */
-			else if (high != IWL_RATE_INVALID) {
-				start_hi = high;
-				rate = high;
+		high_low = rs_get_adjacent_rate(mvm, rate_idx, rate_mask,
+						tbl->rate.type);
 
-			/* Higher rate not available, use the original */
-			} else {
-				new_rate = rate;
-				break;
-			}
-		}
+		rate_idx = (high_low >> 8) & 0xff;
 	}
 
-	return new_rate;
+	IWL_DEBUG_RATE(mvm, "Best rate found %d target_tp %d expected_new %d\n",
+		       rate_idx, target_tpt,
+		       rate_idx != IWL_RATE_INVALID ?
+		       100 * tpt_tbl[rate_idx] : IWL_INVALID_VALUE);
+
+	return rate_idx;
 }
 
 static u32 rs_bw_from_sta_bw(struct ieee80211_sta *sta)
@@ -1649,7 +1594,7 @@ static int rs_switch_to_column(struct iwl_mvm *mvm,
 	const struct rs_tx_column *curr_column = &rs_tx_columns[tbl->column];
 	u32 sz = (sizeof(struct iwl_scale_tbl_info) -
 		  (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
-	u16 rate_mask = 0;
+	unsigned long rate_mask = 0;
 	u32 rate_idx = 0;
 
 	memcpy(search_tbl, tbl, sz);
@@ -1691,7 +1636,7 @@ static int rs_switch_to_column(struct iwl_mvm *mvm,
 		    !(BIT(rate_idx) & rate_mask)) {
 			IWL_DEBUG_RATE(mvm,
 				       "can not switch with index %d"
-				       " rate mask %x\n",
+				       " rate mask %lx\n",
 				       rate_idx, rate_mask);
 
 			goto err;
Signature · 1 line
1.8.3.2
#6 lore raw

PATCH 6/23 iwlwifi: mvm: rs: don't allow TPC when power save is disabled

In reply to Emmanuel Grumbach

From: Eyal Shapira <[email protected]>

Currently we were checking only if the driver power_scheme is set to CAM. TPC shouldn't be enabled also when disabling powersave on the interface (e.g. iw wlan0 set power_save off)
which may occur even if power_scheme wasn't set to CAM.

---
 drivers/net/wireless/iwlwifi/mvm/rs.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)
drivers/net/wireless/iwlwifi/mvm/rs.c +9 -4
index a7ad532..32ac66b 100644
@@ -1750,16 +1750,21 @@ static void rs_get_adjacent_txp(struct iwl_mvm *mvm, int index,
 		*stronger = TPC_INVALID;
 }
 
-static bool rs_tpc_allowed(struct iwl_mvm *mvm, struct rs_rate *rate,
-			   enum ieee80211_band band)
+static bool rs_tpc_allowed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+			   struct rs_rate *rate, enum ieee80211_band band)
 {
 	int index = rate->index;
+	bool cam = (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM);
+	bool sta_ps_disabled = (vif->type == NL80211_IFTYPE_STATION &&
+				!vif->bss_conf.ps);
 
+	IWL_DEBUG_RATE(mvm, "cam: %d sta_ps_disabled %d\n",
+		       cam, sta_ps_disabled);
 	/*
 	 * allow tpc only if power management is enabled, or bt coex
 	 * activity grade allows it and we are on 2.4Ghz.
 	 */
-	if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM &&
+	if ((cam || sta_ps_disabled) &&
 	    !iwl_mvm_bt_coex_is_tpc_allowed(mvm, band))
 		return false;
 
@@ -1876,7 +1881,7 @@ static bool rs_tpc_perform(struct iwl_mvm *mvm,
 		band = chanctx_conf->def.chan->band;
 	rcu_read_unlock();
 
-	if (!rs_tpc_allowed(mvm, rate, band)) {
+	if (!rs_tpc_allowed(mvm, vif, rate, band)) {
 		IWL_DEBUG_RATE(mvm,
 			       "tpc is not allowed. remove txp restrictions");
 		lq_sta->lq.reduced_tpc = TPC_NO_REDUCTION;
Signature · 1 line
1.8.3.2
#7 lore raw

PATCH 7/23 iwlwifi: mvm: rs: avoid TPC while in search cycle

In reply to Emmanuel Grumbach

From: Eyal Shapira <[email protected]>

TPC is a power optimization which should only be attempted when we're in the "stay in column" state after we've locked onto an optimal rate.

---
 drivers/net/wireless/iwlwifi/mvm/rs.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/wireless/iwlwifi/mvm/rs.c +2 -1
index 32ac66b..6216618 100644
@@ -2185,7 +2185,8 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
 		break;
 	case RS_ACTION_STAY:
 		/* No change */
-		update_lq = rs_tpc_perform(mvm, sta, lq_sta, tbl);
+		if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN)
+			update_lq = rs_tpc_perform(mvm, sta, lq_sta, tbl);
 		break;
 	default:
 		break;
Signature · 1 line
1.8.3.2
#8 lore raw

PATCH 8/23 iwlwifi: mvm: rs: choose correct expected tpt table

In reply to Emmanuel Grumbach

From: Eyal Shapira <[email protected]>

The expected throughput table used when estimating a new column depends on the channel bandwidth. When switching from legacy to siso or mimo the wrong expected throughput table was used as it was chosen based on the the channel bandwidth in legacy which is always 20Mhz. Instead it should be chosen based on the current sta bandwidth which could be also 40Mhz or 80Mhz.
When enabling MCS9 this bug leads to a problem where the max expected throughput of the siso or mimo column is 0 as MCS9 isn't supported in 20Mhz. This in turns prevents switching to siso or mimo.

Fix this by using the sta bandwidth when deciding which table to choose.

---
 drivers/net/wireless/iwlwifi/mvm/rs.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/iwlwifi/mvm/rs.c +1 -1
index 6216618..6d5af48 100644
@@ -1553,7 +1553,7 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm,
 
 		tpt = lq_sta->last_tpt / 100;
 		expected_tpt_tbl = rs_get_expected_tpt_table(lq_sta, next_col,
-							     tbl->rate.bw);
+						     rs_bw_from_sta_bw(sta));
 		if (WARN_ON_ONCE(!expected_tpt_tbl))
 			continue;
 
Signature · 1 line
1.8.3.2
#9 lore raw

PATCH 9/23 iwlwifi: mvm: remove useless variable

In reply to Emmanuel Grumbach

From: Johannes Berg <[email protected]>

There's no need to use a variable just to return the result of another function call at the end of a function, remove it.

---
 drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)
drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c +3 -6
index 237efe0..eafc517 100644
@@ -202,18 +202,15 @@ int iwl_mvm_phy_ctxt_add(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
 			 struct cfg80211_chan_def *chandef,
 			 u8 chains_static, u8 chains_dynamic)
 {
-	int ret;
-
 	WARN_ON(!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&
 		ctxt->ref);
 	lockdep_assert_held(&mvm->mutex);
 
 	ctxt->channel = chandef->chan;
-	ret = iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef,
-				     chains_static, chains_dynamic,
-				     FW_CTXT_ACTION_ADD, 0);
 
-	return ret;
+	return iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef,
+				      chains_static, chains_dynamic,
+				      FW_CTXT_ACTION_ADD, 0);
 }
 
 /*
Signature · 1 line
1.8.3.2
#10 lore raw

PATCH 10/23 iwlwifi: mvm: fix bug with OTP memory size

In reply to Emmanuel Grumbach

From: Eran Harary <[email protected]>

OTP size changed in family 7000 and in family 8000.

---
 drivers/net/wireless/iwlwifi/iwl-7000.c   | 2 +-
 drivers/net/wireless/iwlwifi/iwl-8000.c   | 2 +-
 drivers/net/wireless/iwlwifi/iwl-agn-hw.h | 4 +---
 drivers/net/wireless/iwlwifi/iwl-config.h | 5 +++++
 drivers/net/wireless/iwlwifi/mvm/nvm.c    | 1 -
 5 files changed, 8 insertions(+), 6 deletions(-)
drivers/net/wireless/iwlwifi/iwl-7000.c +1 -1
index f73de23..4873006 100644
@@ -98,7 +98,7 @@
 #define NVM_HW_SECTION_NUM_FAMILY_7000		0
 
 static const struct iwl_base_params iwl7000_base_params = {
-	.eeprom_size = OTP_LOW_IMAGE_SIZE,
+	.eeprom_size = OTP_LOW_IMAGE_SIZE_FAMILY_7000,
 	.num_of_queues = IWLAGN_NUM_QUEUES,
 	.pll_cfg_val = 0,
 	.shadow_ram_support = true,
drivers/net/wireless/iwlwifi/iwl-8000.c +1 -1
index f5bd82b..b26b68c 100644
@@ -85,7 +85,7 @@
 #define NVM_HW_SECTION_NUM_FAMILY_8000		10
 
 static const struct iwl_base_params iwl8000_base_params = {
-	.eeprom_size = OTP_LOW_IMAGE_SIZE,
+	.eeprom_size = OTP_LOW_IMAGE_SIZE_FAMILY_8000,
 	.num_of_queues = IWLAGN_NUM_QUEUES,
 	.pll_cfg_val = 0,
 	.shadow_ram_support = true,
drivers/net/wireless/iwlwifi/iwl-agn-hw.h +1 -3
index 7f37fb8..04a483d 100644
@@ -102,9 +102,7 @@
 
 /* EEPROM */
 #define IWLAGN_EEPROM_IMG_SIZE		2048
-/* OTP */
-/* 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 */
drivers/net/wireless/iwlwifi/iwl-config.h +5 -0
index 7ce82d9..b73eac9 100644
@@ -193,6 +193,11 @@ struct iwl_ht_params {
 #define EEPROM_6000_REG_BAND_24_HT40_CHANNELS	0x80
 #define EEPROM_REGULATORY_BAND_NO_HT40		0
 
+/* lower blocks contain EEPROM image and calibration data */
+#define OTP_LOW_IMAGE_SIZE		(2 * 512 * sizeof(u16)) /* 2 KB */
+#define OTP_LOW_IMAGE_SIZE_FAMILY_7000	(4 * 512 * sizeof(u16)) /* 4 KB */
+#define OTP_LOW_IMAGE_SIZE_FAMILY_8000	(32 * 512 * sizeof(u16)) /* 32 KB */
+
 struct iwl_eeprom_params {
 	const u8 regulatory_bands[7];
 	bool enhanced_txpower;
drivers/net/wireless/iwlwifi/mvm/nvm.c +0 -1
index cf2d09f..4092422 100644
@@ -463,7 +463,6 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
 		/* Read From FW NVM */
 		IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from NVM\n");
 
-		/* TODO: find correct NVM max size for a section */
 		nvm_buffer = kmalloc(mvm->cfg->base_params->eeprom_size,
 				     GFP_KERNEL);
 		if (!nvm_buffer)
Signature · 1 line
1.8.3.2
#11 lore raw

PATCH 11/23 iwlwifi: mvm: prevent nic to powered up at driver load

In reply to Emmanuel Grumbach

From: Eran Harary <[email protected]>

A few devices aren't allowed to be powered up at driver load time. Add "power_up_nic_in_init" flag to iwl_cfg structure to customize the load flow according to the device.

---
 drivers/net/wireless/iwlwifi/iwl-config.h |  1 +
 drivers/net/wireless/iwlwifi/mvm/fw.c     |  2 +-
 drivers/net/wireless/iwlwifi/mvm/mvm.h    |  2 +-
 drivers/net/wireless/iwlwifi/mvm/nvm.c    |  6 ++++--
 drivers/net/wireless/iwlwifi/mvm/ops.c    | 16 +++++++++++-----
 5 files changed, 18 insertions(+), 9 deletions(-)
drivers/net/wireless/iwlwifi/iwl-config.h +1 -0
index b73eac9..97f23d6 100644
@@ -274,6 +274,7 @@ struct iwl_cfg {
 	u8   nvm_hw_section_num;
 	bool lp_xtal_workaround;
 	const struct iwl_pwr_tx_backoff *pwr_tx_backoffs;
+	bool no_power_up_nic_in_init;
 };
 
 /*
drivers/net/wireless/iwlwifi/mvm/fw.c +1 -1
index 3d99cf5..34ae3f3 100644
@@ -295,7 +295,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
 	/* Read the NVM only at driver load time, no need to do this twice */
 	if (read_nvm) {
 		/* Read nvm */
-		ret = iwl_nvm_init(mvm);
+		ret = iwl_nvm_init(mvm, true);
 		if (ret) {
 			IWL_ERR(mvm, "Failed to read NVM: %d\n", ret);
 			goto error;
drivers/net/wireless/iwlwifi/mvm/mvm.h +1 -1
index 17c42da..b52d1c9 100644
@@ -757,7 +757,7 @@ int iwl_mvm_rx_statistics(struct iwl_mvm *mvm,
 			  struct iwl_device_cmd *cmd);
 
 /* NVM */
-int iwl_nvm_init(struct iwl_mvm *mvm);
+int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic);
 int iwl_mvm_load_nvm_to_nic(struct iwl_mvm *mvm);
 
 int iwl_mvm_up(struct iwl_mvm *mvm);
drivers/net/wireless/iwlwifi/mvm/nvm.c +4 -2
index 4092422..fe4c91e 100644
@@ -427,7 +427,7 @@ int iwl_mvm_load_nvm_to_nic(struct iwl_mvm *mvm)
 	return ret;
 }
 
-int iwl_nvm_init(struct iwl_mvm *mvm)
+int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic)
 {
 	int ret, i, section;
 	u8 *nvm_buffer, *temp;
@@ -443,7 +443,9 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
 		ret = iwl_mvm_read_external_nvm(mvm);
 		if (ret)
 			return ret;
-	} else {
+	}
+
+	if (read_nvm_from_nic) {
 		/* list of NVM sections we are allowed/need to read */
 		if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) {
 			nvm_to_read[0] = mvm->cfg->nvm_hw_section_num;
drivers/net/wireless/iwlwifi/mvm/ops.c +11 -5
index 7a5a8ba..3c14ea1 100644
@@ -467,12 +467,18 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
 	min_backoff = calc_min_backoff(trans, cfg);
 	iwl_mvm_tt_initialize(mvm, min_backoff);
 
+	if (WARN(cfg->no_power_up_nic_in_init && !iwlwifi_mod_params.nvm_file,
+		 "not allowing power-up and not having nvm_file\n"))
+		goto out_free;
+
 	/*
-	 * If the NVM exists in an external file,
-	 * there is no need to unnecessarily power up the NIC at driver load
+	 * Even if nvm exists in the nvm_file driver should read agin the nvm
+	 * from the nic because there might be entries that exist in the OTP
+	 * and not in the file.
+	 * for nics with no_power_up_nic_in_init: rely completley on nvm_file
 	 */
-	if (iwlwifi_mod_params.nvm_file) {
-		err = iwl_nvm_init(mvm);
+	if (cfg->no_power_up_nic_in_init && iwlwifi_mod_params.nvm_file) {
+		err = iwl_nvm_init(mvm, false);
 		if (err)
 			goto out_free;
 	} else {
@@ -519,7 +525,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
  out_free:
 	iwl_phy_db_free(mvm->phy_db);
 	kfree(mvm->scan_cmd);
-	if (!iwlwifi_mod_params.nvm_file)
+	if (!cfg->no_power_up_nic_in_init || !iwlwifi_mod_params.nvm_file)
 		iwl_trans_op_mode_leave(trans);
 	ieee80211_free_hw(mvm->hw);
 	return NULL;
Signature · 1 line
1.8.3.2
#12 lore raw

PATCH 12/23 iwlwifi: mvm: Prioritize external nvm values on top of the OTP values

In reply to Emmanuel Grumbach

From: Eran Harary <[email protected]>

Read first the nvm sections from the OTP, then read the nvm sections from the external file and override the OTP values (if there were any values in the OTP).

---
 drivers/net/wireless/iwlwifi/mvm/nvm.c | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)
drivers/net/wireless/iwlwifi/mvm/nvm.c +10 -8
index fe4c91e..2cb6c29 100644
@@ -437,14 +437,7 @@ int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic)
 	if (WARN_ON_ONCE(mvm->cfg->nvm_hw_section_num >= NVM_MAX_NUM_SECTIONS))
 		return -EINVAL;
 
-	/* load external NVM if configured */
-	if (iwlwifi_mod_params.nvm_file) {
-		/* move to External NVM flow */
-		ret = iwl_mvm_read_external_nvm(mvm);
-		if (ret)
-			return ret;
-	}
-
+	/* load NVM values from nic */
 	if (read_nvm_from_nic) {
 		/* list of NVM sections we are allowed/need to read */
 		if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) {
@@ -512,6 +505,15 @@ int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic)
 			return ret;
 	}
 
+	/* load external NVM if configured */
+	if (iwlwifi_mod_params.nvm_file) {
+		/* move to External NVM flow */
+		ret = iwl_mvm_read_external_nvm(mvm);
+		if (ret)
+			return ret;
+	}
+
+	/* parse the relevant nvm sections */
 	mvm->nvm_data = iwl_parse_nvm_sections(mvm);
 	if (!mvm->nvm_data)
 		return -ENODATA;
Signature · 1 line
1.8.3.2
#13 lore raw

PATCH 13/23 iwlwifi: mvm: select the MAC address according to priority

In reply to Emmanuel Grumbach

From: Eran Harary <[email protected]>

For family 8000 products, the driver should take the MAC address from the mac_override section and only if this section is empty it should take it from the HW section.

---
 drivers/net/wireless/iwlwifi/iwl-nvm-parse.c | 46 +++++++++++++++++++++++-----
 drivers/net/wireless/iwlwifi/mvm/nvm.c       |  9 +++++-
 2 files changed, 46 insertions(+), 9 deletions(-)
drivers/net/wireless/iwlwifi/iwl-nvm-parse.c +38 -8
index 4049c0d..49963e4 100644
@@ -62,6 +62,7 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/export.h>
+#include <linux/etherdevice.h>
 #include "iwl-drv.h"
 #include "iwl-modparams.h"
 #include "iwl-nvm-parse.h"
@@ -450,13 +451,7 @@ static void iwl_set_hw_address(const struct iwl_cfg *cfg,
 			       struct iwl_nvm_data *data,
 			       const __le16 *nvm_sec)
 {
-	u8 hw_addr[ETH_ALEN];
-
-	if (cfg->device_family != IWL_DEVICE_FAMILY_8000)
-		memcpy(hw_addr, nvm_sec + HW_ADDR, ETH_ALEN);
-	else
-		memcpy(hw_addr, nvm_sec + MAC_ADDRESS_OVERRIDE_FAMILY_8000,
-		       ETH_ALEN);
+	const u8 *hw_addr = (const u8 *)(nvm_sec + HW_ADDR);
 
 	/* The byte order is little endian 16 bit, meaning 214365 */
 	data->hw_addr[0] = hw_addr[1];
@@ -467,6 +462,41 @@ static void iwl_set_hw_address(const struct iwl_cfg *cfg,
 	data->hw_addr[5] = hw_addr[4];
 }
 
+static void iwl_set_hw_address_family_8000(const struct iwl_cfg *cfg,
+					   struct iwl_nvm_data *data,
+					   const __le16 *mac_override,
+					   const __le16 *nvm_hw)
+{
+	const u8 *hw_addr;
+
+	if (mac_override) {
+		hw_addr = (const u8 *)(mac_override +
+				 MAC_ADDRESS_OVERRIDE_FAMILY_8000);
+
+		/* The byte order is little endian 16 bit, meaning 214365 */
+		data->hw_addr[0] = hw_addr[1];
+		data->hw_addr[1] = hw_addr[0];
+		data->hw_addr[2] = hw_addr[3];
+		data->hw_addr[3] = hw_addr[2];
+		data->hw_addr[4] = hw_addr[5];
+		data->hw_addr[5] = hw_addr[4];
+
+		if (is_valid_ether_addr(hw_addr))
+			return;
+	}
+
+	/* take the MAC address from the OTP */
+	hw_addr = (const u8 *)(nvm_hw + HW_ADDR0_FAMILY_8000);
+	data->hw_addr[0] = hw_addr[3];
+	data->hw_addr[1] = hw_addr[2];
+	data->hw_addr[2] = hw_addr[1];
+	data->hw_addr[3] = hw_addr[0];
+
+	hw_addr = (const u8 *)(nvm_hw + HW_ADDR1_FAMILY_8000);
+	data->hw_addr[4] = hw_addr[1];
+	data->hw_addr[5] = hw_addr[0];
+}
+
 struct iwl_nvm_data *
 iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
 		   const __le16 *nvm_hw, const __le16 *nvm_sw,
@@ -526,7 +556,7 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
 				rx_chains);
 	} else {
 		/* MAC address in family 8000 */
-		iwl_set_hw_address(cfg, data, mac_override);
+		iwl_set_hw_address_family_8000(cfg, data, mac_override, nvm_hw);
 
 		iwl_init_sbands(dev, cfg, data, regulatory,
 				sku & NVM_SKU_CAP_11AC_ENABLE, tx_chains,
drivers/net/wireless/iwlwifi/mvm/nvm.c +8 -1
index 2cb6c29..6d0e659 100644
@@ -238,13 +238,20 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
 			return NULL;
 		}
 	} else {
+		/* SW and REGULATORY sections are mandatory */
 		if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data ||
-		    !mvm->nvm_sections[NVM_SECTION_TYPE_MAC_OVERRIDE].data ||
 		    !mvm->nvm_sections[NVM_SECTION_TYPE_REGULATORY].data) {
 			IWL_ERR(mvm,
 				"Can't parse empty family 8000 NVM sections\n");
 			return NULL;
 		}
+		/* MAC_OVERRIDE or at least HW section must exist */
+		if (!mvm->cfg->nvm_hw_section_num &&
+		    !mvm->nvm_sections[NVM_SECTION_TYPE_MAC_OVERRIDE].data) {
+			IWL_ERR(mvm,
+				"Can't parse mac_address, empty sections\n");
+			return NULL;
+		}
 	}
 
 	if (WARN_ON(!mvm->cfg))
Signature · 1 line
1.8.3.2
#14 lore raw

PATCH 14/23 iwlwifi: mvm: fix bug in parse_nvm_sections

In reply to Emmanuel Grumbach

From: Eran Harary <[email protected]>

The old code checks if hw_section_num is valid while the right thing to do is to check if section[hw_section_num].data is valid.

---
 drivers/net/wireless/iwlwifi/mvm/nvm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/iwlwifi/mvm/nvm.c +1 -1
index 6d0e659..6b88c29 100644
@@ -246,7 +246,7 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
 			return NULL;
 		}
 		/* MAC_OVERRIDE or at least HW section must exist */
-		if (!mvm->cfg->nvm_hw_section_num &&
+		if (!mvm->nvm_sections[mvm->cfg->nvm_hw_section_num].data &&
 		    !mvm->nvm_sections[NVM_SECTION_TYPE_MAC_OVERRIDE].data) {
 			IWL_ERR(mvm,
 				"Can't parse mac_address, empty sections\n");
Signature · 1 line
1.8.3.2
#15 lore raw

PATCH 15/23 iwlwifi: make LED support optional

In reply to Emmanuel Grumbach

From: Johannes Berg <[email protected]>

If there's no LED on the system, it doesn't make a lot of sense to include close to 4k of LED-related code (mostly in mac80211), so instead of forcing LED support into the kernel, don't build iwlwifi/mac80211 LED support if there's no LED class support.

---
 drivers/net/wireless/iwlwifi/Kconfig      | 12 ++++++++----
 drivers/net/wireless/iwlwifi/dvm/Makefile |  3 ++-
 drivers/net/wireless/iwlwifi/dvm/dev.h    |  2 ++
 drivers/net/wireless/iwlwifi/dvm/led.h    | 12 ++++++++++++
 drivers/net/wireless/iwlwifi/mvm/Makefile |  3 ++-
 drivers/net/wireless/iwlwifi/mvm/mvm.h    | 12 ++++++++++++
 6 files changed, 38 insertions(+), 6 deletions(-)
drivers/net/wireless/iwlwifi/Kconfig +8 -4
index 74b3b4d..b82d30c 100644
@@ -2,10 +2,6 @@ config IWLWIFI
 	tristate "Intel Wireless WiFi Next Gen AGN - Wireless-N/Advanced-N/Ultimate-N (iwlwifi) "
 	depends on PCI && MAC80211 && HAS_IOMEM
 	select FW_LOADER
-	select NEW_LEDS
-	select LEDS_CLASS
-	select LEDS_TRIGGERS
-	select MAC80211_LEDS
 	---help---
 	  Select to build the driver supporting the:
 
@@ -43,6 +39,14 @@ config IWLWIFI
 	  say M here and read <file:Documentation/kbuild/modules.txt>.  The
 	  module will be called iwlwifi.
 
+config IWLWIFI_LEDS
+	bool
+	depends on IWLWIFI
+	depends on LEDS_CLASS
+	select LEDS_TRIGGERS
+	select MAC80211_LEDS
+	default y
+
 config IWLDVM
 	tristate "Intel Wireless WiFi DVM Firmware support"
 	depends on IWLWIFI
drivers/net/wireless/iwlwifi/dvm/Makefile +2 -1
index dce7ab2..4d19685 100644
@@ -4,9 +4,10 @@ iwldvm-objs		+= main.o rs.o mac80211.o ucode.o tx.o
 iwldvm-objs		+= lib.o calib.o tt.o sta.o rx.o
 
 iwldvm-objs		+= power.o
-iwldvm-objs		+= scan.o led.o
+iwldvm-objs		+= scan.o
 iwldvm-objs		+= rxon.o devices.o
 
+iwldvm-$(CONFIG_IWLWIFI_LEDS) += led.o
 iwldvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o
 
 ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/../
drivers/net/wireless/iwlwifi/dvm/dev.h +2 -0
index 3441f70..a6f22c3 100644
@@ -888,9 +888,11 @@ struct iwl_priv {
 
 	struct iwl_event_log event_log;
 
+#ifdef CONFIG_IWLWIFI_LEDS
 	struct led_classdev led;
 	unsigned long blink_on, blink_off;
 	bool led_registered;
+#endif
 
 	/* WoWLAN GTK rekey data */
 	u8 kck[NL80211_KCK_LEN], kek[NL80211_KEK_LEN];
drivers/net/wireless/iwlwifi/dvm/led.h +12 -0
index 6a0817d..1c6b225 100644
@@ -36,8 +36,20 @@ struct iwl_priv;
 #define IWL_LED_ACTIVITY       (0<<1)
 #define IWL_LED_LINK           (1<<1)
 
+#ifdef CONFIG_IWLWIFI_LEDS
 void iwlagn_led_enable(struct iwl_priv *priv);
 void iwl_leds_init(struct iwl_priv *priv);
 void iwl_leds_exit(struct iwl_priv *priv);
+#else
+static inline void iwlagn_led_enable(struct iwl_priv *priv)
+{
+}
+static inline void iwl_leds_init(struct iwl_priv *priv)
+{
+}
+static inline void iwl_leds_exit(struct iwl_priv *priv)
+{
+}
+#endif
 
 #endif /* __iwl_leds_h__ */
drivers/net/wireless/iwlwifi/mvm/Makefile +2 -1
index ccdd3b7..c30d7f6 100644
@@ -3,8 +3,9 @@ iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o
 iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o sf.o
 iwlmvm-y += scan.o time-event.o rs.o
 iwlmvm-y += power.o coex.o
-iwlmvm-y += led.o tt.o offloading.o
+iwlmvm-y += tt.o offloading.o
 iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o
+iwlmvm-$(CONFIG_IWLWIFI_LEDS) += led.o
 iwlmvm-$(CONFIG_PM_SLEEP) += d3.o
 
 ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/../
drivers/net/wireless/iwlwifi/mvm/mvm.h +12 -0
index b52d1c9..1575ac7 100644
@@ -589,7 +589,9 @@ struct iwl_mvm {
 	u32 *fw_error_rxf;
 	u32 fw_error_rxf_len;
 
+#ifdef CONFIG_IWLWIFI_LEDS
 	struct led_classdev led;
+#endif
 
 	struct ieee80211_vif *p2p_device_vif;
 
@@ -896,8 +898,18 @@ int iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm,
 					     struct iwl_rx_cmd_buffer *rxb,
 					     struct iwl_device_cmd *cmd);
 
+#ifdef CONFIG_IWLWIFI_LEDS
 int iwl_mvm_leds_init(struct iwl_mvm *mvm);
 void iwl_mvm_leds_exit(struct iwl_mvm *mvm);
+#else
+static inline int iwl_mvm_leds_init(struct iwl_mvm *mvm)
+{
+	return 0;
+}
+static inline void iwl_mvm_leds_exit(struct iwl_mvm *mvm)
+{
+}
+#endif
 
 /* D3 (WoWLAN, NetDetect) */
 int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan);
Signature · 1 line
1.8.3.2
#16 lore raw

PATCH 16/23 iwlwifi: pcie: use bool for iwl_pcie_txq_build_tfd() argument

In reply to Emmanuel Grumbach

From: Johannes Berg <[email protected]>

The 'reset' argument is clearly a boolean, so use bool instead of u8 with 0/1 values.

---
 drivers/net/wireless/iwlwifi/pcie/tx.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)
drivers/net/wireless/iwlwifi/pcie/tx.c +7 -7
index dde6031..16ebc4a 100644
@@ -452,7 +452,7 @@ static void iwl_pcie_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq)
 }
 
 static int iwl_pcie_txq_build_tfd(struct iwl_trans *trans, struct iwl_txq *txq,
-				  dma_addr_t addr, u16 len, u8 reset)
+				  dma_addr_t addr, u16 len, bool reset)
 {
 	struct iwl_queue *q;
 	struct iwl_tfd *tfd, *tfd_tmp;
@@ -1363,7 +1363,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
 	memcpy(&txq->scratchbufs[q->write_ptr], &out_cmd->hdr, scratch_size);
 	iwl_pcie_txq_build_tfd(trans, txq,
 			       iwl_pcie_get_scratchbuf_dma(txq, q->write_ptr),
-			       scratch_size, 1);
+			       scratch_size, true);
 
 	/* map first command fragment, if any remains */
 	if (copy_size > scratch_size) {
@@ -1379,7 +1379,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
 		}
 
 		iwl_pcie_txq_build_tfd(trans, txq, phys_addr,
-				       copy_size - scratch_size, 0);
+				       copy_size - scratch_size, false);
 	}
 
 	/* map the remaining (adjusted) nocopy/dup fragments */
@@ -1402,7 +1402,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
 			goto out;
 		}
 
-		iwl_pcie_txq_build_tfd(trans, txq, phys_addr, cmdlen[i], 0);
+		iwl_pcie_txq_build_tfd(trans, txq, phys_addr, cmdlen[i], false);
 	}
 
 	out_meta->flags = cmd->flags;
@@ -1740,7 +1740,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
 	memcpy(&txq->scratchbufs[q->write_ptr], &dev_cmd->hdr,
 	       IWL_HCMD_SCRATCHBUF_SIZE);
 	iwl_pcie_txq_build_tfd(trans, txq, tb0_phys,
-			       IWL_HCMD_SCRATCHBUF_SIZE, 1);
+			       IWL_HCMD_SCRATCHBUF_SIZE, true);
 
 	/* there must be data left over for TB1 or this code must be changed */
 	BUILD_BUG_ON(sizeof(struct iwl_tx_cmd) < IWL_HCMD_SCRATCHBUF_SIZE);
@@ -1750,7 +1750,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
 	tb1_phys = dma_map_single(trans->dev, tb1_addr, tb1_len, DMA_TO_DEVICE);
 	if (unlikely(dma_mapping_error(trans->dev, tb1_phys)))
 		goto out_err;
-	iwl_pcie_txq_build_tfd(trans, txq, tb1_phys, tb1_len, 0);
+	iwl_pcie_txq_build_tfd(trans, txq, tb1_phys, tb1_len, false);
 
 	/*
 	 * Set up TFD's third entry to point directly to remainder
@@ -1766,7 +1766,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
 					   &txq->tfds[q->write_ptr]);
 			goto out_err;
 		}
-		iwl_pcie_txq_build_tfd(trans, txq, tb2_phys, tb2_len, 0);
+		iwl_pcie_txq_build_tfd(trans, txq, tb2_phys, tb2_len, false);
 	}
 
 	/* Set up entry for this TFD in Tx byte-count array */
Signature · 1 line
1.8.3.2
#17 lore raw

PATCH 17/23 iwlwifi: pcie: get rid of q->n_bd

In reply to Emmanuel Grumbach

From: Johannes Berg <[email protected]>

This variable always tracks a constant value (256) so there's no need to have it. Removing it simplifies code generation, reducing the .text size (by about 240 bytes on x86-64.)

---
 drivers/net/wireless/iwlwifi/pcie/internal.h | 17 +++----
 drivers/net/wireless/iwlwifi/pcie/rx.c       |  2 +-
 drivers/net/wireless/iwlwifi/pcie/trans.c    |  4 +-
 drivers/net/wireless/iwlwifi/pcie/tx.c       | 75 +++++++++++++---------------
 4 files changed, 45 insertions(+), 53 deletions(-)
drivers/net/wireless/iwlwifi/pcie/internal.h +7 -10
index 1b95d85..ab21aee 100644
@@ -117,21 +117,19 @@ struct iwl_dma_ptr {
 /**
  * iwl_queue_inc_wrap - increment queue index, wrap back to beginning
  * @index -- current index
- * @n_bd -- total number of entries in queue (must be power of 2)
  */
-static inline int iwl_queue_inc_wrap(int index, int n_bd)
+static inline int iwl_queue_inc_wrap(int index)
 {
-	return ++index & (n_bd - 1);
+	return ++index & (TFD_QUEUE_SIZE_MAX - 1);
 }
 
 /**
  * iwl_queue_dec_wrap - decrement queue index, wrap back to end
  * @index -- current index
- * @n_bd -- total number of entries in queue (must be power of 2)
  */
-static inline int iwl_queue_dec_wrap(int index, int n_bd)
+static inline int iwl_queue_dec_wrap(int index)
 {
-	return --index & (n_bd - 1);
+	return --index & (TFD_QUEUE_SIZE_MAX - 1);
 }
 
 struct iwl_cmd_meta {
@@ -145,13 +143,13 @@ struct iwl_cmd_meta {
  *
  * Contains common data for Rx and Tx queues.
  *
- * Note the difference between n_bd and n_window: the hardware
- * always assumes 256 descriptors, so n_bd is always 256 (unless
+ * Note the difference between TFD_QUEUE_SIZE_MAX and n_window: the hardware
+ * always assumes 256 descriptors, so TFD_QUEUE_SIZE_MAX is always 256 (unless
  * there might be HW changes in the future). For the normal TX
  * queues, n_window, which is the size of the software queue data
  * is also 256; however, for the command queue, n_window is only
  * 32 since we don't need so many commands pending. Since the HW
- * still uses 256 BDs for DMA though, n_bd stays 256. As a result,
+ * still uses 256 BDs for DMA though, TFD_QUEUE_SIZE_MAX stays 256. As a result,
  * the software buffers (in the variables @meta, @txb in struct
  * iwl_txq) only have 32 entries, while the HW buffers (@tfds in
  * the same struct) have 256.
@@ -162,7 +160,6 @@ struct iwl_cmd_meta {
  * data is a window overlayed over the HW queue.
  */
 struct iwl_queue {
-	int n_bd;              /* number of BDs in this queue */
 	int write_ptr;       /* 1-st empty entry (index) host_w*/
 	int read_ptr;         /* last used entry (index) host_r*/
 	/* use for monitoring and recovering the stuck queue */
drivers/net/wireless/iwlwifi/pcie/rx.c +1 -1
index 4a26a08..a2698e5 100644
@@ -850,7 +850,7 @@ static u32 iwl_pcie_int_cause_ict(struct iwl_trans *trans)
 				trans_pcie->ict_index, read);
 		trans_pcie->ict_tbl[trans_pcie->ict_index] = 0;
 		trans_pcie->ict_index =
-			iwl_queue_inc_wrap(trans_pcie->ict_index, ICT_COUNT);
+			((trans_pcie->ict_index + 1) & (ICT_COUNT - 1));
 
 		read = le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]);
 		trace_iwlwifi_dev_ict_read(trans->dev, trans_pcie->ict_index,
drivers/net/wireless/iwlwifi/pcie/trans.c +2 -2
index f98ef1e..a6f8622 100644
@@ -1337,8 +1337,8 @@ static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, u32 txq_bm)
 		IWL_ERR(trans,
 			"Q %d is %sactive and mapped to fifo %d ra_tid 0x%04x [%d,%d]\n",
 			cnt, active ? "" : "in", fifo, tbl_dw,
-			iwl_read_prph(trans,
-				      SCD_QUEUE_RDPTR(cnt)) & (txq->q.n_bd - 1),
+			iwl_read_prph(trans, SCD_QUEUE_RDPTR(cnt)) &
+				(TFD_QUEUE_SIZE_MAX - 1),
 			iwl_read_prph(trans, SCD_QUEUE_WRPTR(cnt)));
 	}
 
drivers/net/wireless/iwlwifi/pcie/tx.c +35 -40

188 lines not on this page · raw message

Signature · 1 line
1.8.3.2
#18 lore raw

PATCH 18/23 iwlwifi: mvm/pcie: capture last commands on firmware error

In reply to Emmanuel Grumbach

From: Johannes Berg <[email protected]>

When a firmware error occurs, capture the last 32 commands (which are still in memory) in the error dump debugfs file.

---
 drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h | 134 +++++++++++++++++++++++
 drivers/net/wireless/iwlwifi/iwl-trans.h         |  19 ++++
 drivers/net/wireless/iwlwifi/mvm/debugfs.c       |   2 +-
 drivers/net/wireless/iwlwifi/mvm/fw-error-dump.h | 108 ------------------
 drivers/net/wireless/iwlwifi/mvm/ops.c           |  18 ++-
 drivers/net/wireless/iwlwifi/pcie/internal.h     |   7 ++
 drivers/net/wireless/iwlwifi/pcie/trans.c        |  60 ++++++++++
 drivers/net/wireless/iwlwifi/pcie/tx.c           |  40 ++++---
 8 files changed, 259 insertions(+), 129 deletions(-)
 create mode 100644 drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h
 delete mode 100644 drivers/net/wireless/iwlwifi/mvm/fw-error-dump.h
drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h new file +134 -0
new file mode 100644
index 0000000..2953ffc
@@ -0,0 +1,134 @@
+/******************************************************************************
+ *
+ * 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) 2014 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 COPYING.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <[email protected]>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2014 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.
+ *****************************************************************************/
+
+#ifndef __fw_error_dump_h__
+#define __fw_error_dump_h__
+
+#include <linux/types.h>
+
+#define IWL_FW_ERROR_DUMP_BARKER	0x14789632
+
+/**
+ * enum iwl_fw_error_dump_type - types of data in the dump file
+ * @IWL_FW_ERROR_DUMP_SRAM:
+ * @IWL_FW_ERROR_DUMP_REG:
+ * @IWL_FW_ERROR_DUMP_RXF:
+ * @IWL_FW_ERROR_DUMP_TXCMD: last TX command data, structured as
+ *	&struct iwl_fw_error_dump_txcmd packets
+ */
+enum iwl_fw_error_dump_type {
+	IWL_FW_ERROR_DUMP_SRAM = 0,
+	IWL_FW_ERROR_DUMP_REG = 1,
+	IWL_FW_ERROR_DUMP_RXF = 2,
+	IWL_FW_ERROR_DUMP_TXCMD = 3,
+
+	IWL_FW_ERROR_DUMP_MAX,
+};
+
+/**
+ * struct iwl_fw_error_dump_data - data for one type
+ * @type: %enum iwl_fw_error_dump_type
+ * @len: the length starting from %data - must be a multiplier of 4.
+ * @data: the data itself padded to be a multiplier of 4.
+ */
+struct iwl_fw_error_dump_data {
+	__le32 type;
+	__le32 len;
+	__u8 data[];
+} __packed;
+
+/**
+ * struct iwl_fw_error_dump_file - the layout of the header of the file
+ * @barker: must be %IWL_FW_ERROR_DUMP_BARKER
+ * @file_len: the length of all the file starting from %barker
+ * @data: array of %struct iwl_fw_error_dump_data
+ */
+struct iwl_fw_error_dump_file {
+	__le32 barker;
+	__le32 file_len;
+	u8 data[0];
+} __packed;
+
+/**
+ * struct iwl_fw_error_dump_txcmd - TX command data
+ * @cmdlen: original length of command
+ * @caplen: captured length of command (may be less)
+ * @data: captured command data, @caplen bytes
+ */
+struct iwl_fw_error_dump_txcmd {
+	__le32 cmdlen;
+	__le32 caplen;
+	u8 data[];
+} __packed;
+
+/**
+ * iwl_mvm_fw_error_next_data - advance fw error dump data pointer
+ * @data: previous data block
+ * Returns: next data block
+ */
+static inline struct iwl_fw_error_dump_data *
+iwl_mvm_fw_error_next_data(struct iwl_fw_error_dump_data *data)
+{
+	return (void *)(data->data + le32_to_cpu(data->len));
+}
+
+#endif /* __fw_error_dump_h__ */
drivers/net/wireless/iwlwifi/iwl-trans.h +19 -0
index 22fd94e..84ad48d 100644
@@ -463,6 +463,11 @@ struct iwl_trans;
  * @unref: release a reference previously taken with @ref. Note that
  *	initially the reference count is 1, making an initial @unref
  *	necessary to allow low power states.
+ * @dump_data: fill a data dump with debug data, maybe containing last
+ *	TX'ed commands and similar. When called with a NULL buffer and
+ *	zero buffer length, provide only the (estimated) required buffer
+ *	length. Return the used buffer length.
+ *	Note that the transport must fill in the proper file headers.
  */
 struct iwl_trans_ops {
 
@@ -511,6 +516,10 @@ struct iwl_trans_ops {
 			      u32 value);
 	void (*ref)(struct iwl_trans *trans);
 	void (*unref)(struct iwl_trans *trans);
+
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+	u32 (*dump_data)(struct iwl_trans *trans, void *buf, u32 buflen);
+#endif
 };
 
 /**
@@ -664,6 +673,16 @@ static inline void iwl_trans_unref(struct iwl_trans *trans)
 		trans->ops->unref(trans);
 }
 
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+static inline u32 iwl_trans_dump_data(struct iwl_trans *trans,
+				      void *buf, u32 buflen)
+{
+	if (!trans->ops->dump_data)
+		return 0;
+	return trans->ops->dump_data(trans, buf, buflen);
+}
+#endif
+
 static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
 				     struct iwl_host_cmd *cmd)
 {
drivers/net/wireless/iwlwifi/mvm/debugfs.c +1 -1
index f462c9b..bef487b 100644
@@ -67,7 +67,7 @@
 #include "iwl-io.h"
 #include "iwl-prph.h"
 #include "debugfs.h"
-#include "fw-error-dump.h"
+#include "iwl-fw-error-dump.h"
 
 static ssize_t iwl_dbgfs_tx_flush_write(struct iwl_mvm *mvm, char *buf,
 					size_t count, loff_t *ppos)
drivers/net/wireless/iwlwifi/mvm/fw-error-dump.h deleted +0 -108

108 lines not on this page · raw message

drivers/net/wireless/iwlwifi/mvm/ops.c +16 -2
index 3c14ea1..cd526e1 100644
@@ -79,8 +79,8 @@
 #include "iwl-prph.h"
 #include "rs.h"
 #include "fw-api-scan.h"
-#include "fw-error-dump.h"
 #include "time-event.h"
+#include "iwl-fw-error-dump.h"
 
 /*
  * module name, copyright, version, etc.
@@ -822,6 +822,7 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
 	struct iwl_fw_error_dump_file *dump_file;
 	struct iwl_fw_error_dump_data *dump_data;
 	u32 file_len;
+	u32 trans_len;
 
 	lockdep_assert_held(&mvm->mutex);
 
@@ -833,6 +834,10 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
 		   sizeof(*dump_file) +
 		   sizeof(*dump_data) * 2;
 
+	trans_len = iwl_trans_dump_data(mvm->trans, NULL, 0);
+	if (trans_len)
+		file_len += trans_len;
+
 	dump_file = vmalloc(file_len);
 	if (!dump_file)
 		return;
@@ -846,7 +851,7 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
 	dump_data->len = cpu_to_le32(mvm->fw_error_rxf_len);
 	memcpy(dump_data->data, mvm->fw_error_rxf, mvm->fw_error_rxf_len);
 
-	dump_data = (void *)((u8 *)dump_data->data + mvm->fw_error_rxf_len);
+	dump_data = iwl_mvm_fw_error_next_data(dump_data);
 	dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_SRAM);
 	dump_data->len = cpu_to_le32(mvm->fw_error_sram_len);
 
@@ -864,6 +869,15 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
 	kfree(mvm->fw_error_sram);
 	mvm->fw_error_sram = NULL;
 	mvm->fw_error_sram_len = 0;
+
+	if (trans_len) {
+		void *buf = iwl_mvm_fw_error_next_data(dump_data);
+		u32 real_trans_len = iwl_trans_dump_data(mvm->trans, buf,
+							 trans_len);
+		dump_data = (void *)((u8 *)buf + real_trans_len);
+		dump_file->file_len =
+			cpu_to_le32(file_len - trans_len + real_trans_len);
+	}
 }
 #endif
 
drivers/net/wireless/iwlwifi/pcie/internal.h +7 -0
index ab21aee..6c22b23 100644
@@ -370,6 +370,13 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
 			    struct sk_buff_head *skbs);
 void iwl_trans_pcie_tx_reset(struct iwl_trans *trans);
 
+static inline u16 iwl_pcie_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx)
+{
+	struct iwl_tfd_tb *tb = &tfd->tbs[idx];
+
+	return le16_to_cpu(tb->hi_n_len) >> 4;
+}
+
 /*****************************************************
 * Error handling
 ******************************************************/
drivers/net/wireless/iwlwifi/pcie/trans.c +60 -0

78 lines not on this page · raw message

drivers/net/wireless/iwlwifi/pcie/tx.c +22 -18
index 93709fe..77a512a 100644
@@ -353,13 +353,6 @@ static inline dma_addr_t iwl_pcie_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx)
 	return addr;
 }
 
-static inline u16 iwl_pcie_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx)
-{
-	struct iwl_tfd_tb *tb = &tfd->tbs[idx];
-
-	return le16_to_cpu(tb->hi_n_len) >> 4;
-}
-
 static inline void iwl_pcie_tfd_set_tb(struct iwl_tfd *tfd, u8 idx,
 				       dma_addr_t addr, u16 len)
 {
@@ -1322,28 +1315,39 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
 	cmd_pos = offsetof(struct iwl_device_cmd, payload);
 	copy_size = sizeof(out_cmd->hdr);
 	for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) {
-		int copy = 0;
+		int copy;
 
 		if (!cmd->len[i])
 			continue;
 
-		/* need at least IWL_HCMD_SCRATCHBUF_SIZE copied */
-		if (copy_size < IWL_HCMD_SCRATCHBUF_SIZE) {
-			copy = IWL_HCMD_SCRATCHBUF_SIZE - copy_size;
-
-			if (copy > cmd->len[i])
-				copy = cmd->len[i];
-		}
-
 		/* copy everything if not nocopy/dup */
 		if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY |
-					   IWL_HCMD_DFL_DUP)))
+					   IWL_HCMD_DFL_DUP))) {
 			copy = cmd->len[i];
 
-		if (copy) {
 			memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], copy);
 			cmd_pos += copy;
 			copy_size += copy;
+			continue;
+		}
+
+		/*
+		 * Otherwise we need at least IWL_HCMD_SCRATCHBUF_SIZE copied
+		 * in total (for the scratchbuf handling), but copy up to what
+		 * we can fit into the payload for debug dump purposes.
+		 */
+		copy = min_t(int, TFD_MAX_PAYLOAD_SIZE - cmd_pos, cmd->len[i]);
+
+		memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], copy);
+		cmd_pos += copy;
+
+		/* However, treat copy_size the proper way, we need it below */
+		if (copy_size < IWL_HCMD_SCRATCHBUF_SIZE) {
+			copy = IWL_HCMD_SCRATCHBUF_SIZE - copy_size;
+
+			if (copy > cmd->len[i])
+				copy = cmd->len[i];
+			copy_size += copy;
 		}
 	}
 
Signature · 1 line
1.8.3.2
#19 lore raw

PATCH 19/23 iwlwifi: mvm: wait for d0i3 exit in some more ampdu actions

In reply to Emmanuel Grumbach

From: Eliad Peller <[email protected]>

Some ampdu actions change queues by direct target access.

Since the bus is disabled in d0i3, make sure to exit d0i3 before handling these actions.

---
 drivers/net/wireless/iwlwifi/mvm/mac80211.c | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)
drivers/net/wireless/iwlwifi/mvm/mac80211.c +15 -3
index 97c3dea..db55d67 100644
@@ -539,13 +539,22 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
 		return -EACCES;
 
 	/* return from D0i3 before starting a new Tx aggregation */
-	if (action == IEEE80211_AMPDU_TX_START) {
+	switch (action) {
+	case IEEE80211_AMPDU_TX_START:
+	case IEEE80211_AMPDU_TX_STOP_CONT:
+	case IEEE80211_AMPDU_TX_STOP_FLUSH:
+	case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
+	case IEEE80211_AMPDU_TX_OPERATIONAL:
 		iwl_mvm_ref(mvm, IWL_MVM_REF_TX_AGG);
 		tx_agg_ref = true;
 
 		/*
-		 * wait synchronously until D0i3 exit to get the correct
-		 * sequence number for the tid
+		 * for tx start, wait synchronously until D0i3 exit to
+		 * get the correct sequence number for the tid.
+		 * additionally, some other ampdu actions use direct
+		 * target access, which is not handled automatically
+		 * by the trans layer (unlike commands), so wait for
+		 * d0i3 exit in these cases as well.
 		 */
 		if (!wait_event_timeout(mvm->d0i3_exit_waitq,
 			  !test_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status), HZ)) {
@@ -553,6 +562,9 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
 			iwl_mvm_unref(mvm, IWL_MVM_REF_TX_AGG);
 			return -EIO;
 		}
+		break;
+	default:
+		break;
 	}
 
 	mutex_lock(&mvm->mutex);
Signature · 1 line
1.8.3.2
#20 lore raw

PATCH 20/23 iwlwifi:mvm: Add AP/GO channel switch support

In reply to Emmanuel Grumbach

From: Andrei Otcheretianski <[email protected]>

Publish WIPHY_FLAG_HAS_CHANNEL_SWITCH if the fw supports
newly introduced IWL_UCODE_TLV_API_CSA_FLOW.
When CSA starts, save the switching vif inside mvm and during the CSA period configure fw with a new beacon after each beacon transmission in order to update the csa counters.
Also, handle correctly the CSA unbind-bind flow which is triggered by mac80211 when the actual channel switch happens.

---
 drivers/net/wireless/iwlwifi/iwl-fw.h       |  2 ++
 drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | 12 ++++++++
 drivers/net/wireless/iwlwifi/mvm/mac80211.c | 44 ++++++++++++++++++++++++++++-
 drivers/net/wireless/iwlwifi/mvm/mvm.h      |  2 ++
 drivers/net/wireless/iwlwifi/mvm/ops.c      |  2 +-
 5 files changed, 60 insertions(+), 2 deletions(-)
drivers/net/wireless/iwlwifi/iwl-fw.h +2 -0
index f5927d0c..6fea27c 100644
@@ -116,9 +116,11 @@ enum iwl_ucode_tlv_flag {
 /**
  * enum iwl_ucode_tlv_api - ucode api
  * @IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID: wowlan config includes tid field.
+ * @IWL_UCODE_TLV_API_CSA_FLOW: ucode can do unbind-bind flow for CSA.
  */
 enum iwl_ucode_tlv_api {
 	IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID	= BIT(0),
+	IWL_UCODE_TLV_API_CSA_FLOW		= BIT(4),
 };
 
 /**
drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +12 -0
index 7110ec2..56cf58e 100644
@@ -1237,11 +1237,23 @@ int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
 	u32 rate __maybe_unused =
 		le32_to_cpu(beacon->beacon_notify_hdr.initial_rate);
 
+	lockdep_assert_held(&mvm->mutex);
+
 	IWL_DEBUG_RX(mvm, "beacon status %#x retries:%d tsf:0x%16llX rate:%d\n",
 		     status & TX_STATUS_MSK,
 		     beacon->beacon_notify_hdr.failure_frame,
 		     le64_to_cpu(beacon->tsf),
 		     rate);
+
+	if (unlikely(mvm->csa_vif && mvm->csa_vif->csa_active)) {
+		if (!ieee80211_csa_is_complete(mvm->csa_vif)) {
+			iwl_mvm_mac_ctxt_beacon_changed(mvm, mvm->csa_vif);
+		} else {
+			ieee80211_csa_finish(mvm->csa_vif);
+			mvm->csa_vif = NULL;
+		}
+	}
+
 	return 0;
 }
 
drivers/net/wireless/iwlwifi/mvm/mac80211.c +43 -1

86 lines not on this page · raw message

drivers/net/wireless/iwlwifi/mvm/mvm.h +2 -0
index 1575ac7..1e468c3 100644
@@ -644,6 +644,8 @@ struct iwl_mvm {
 
 	/* Indicate if device power save is allowed */
 	bool ps_disabled;
+
+	struct ieee80211_vif *csa_vif;
 };
 
 /* Extract MVM priv from op_mode and _hw */
drivers/net/wireless/iwlwifi/mvm/ops.c +1 -1
index cd526e1..f8530b3 100644
@@ -220,7 +220,7 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
 	RX_HANDLER(BA_NOTIF, iwl_mvm_rx_ba_notif, false),
 
 	RX_HANDLER(BT_PROFILE_NOTIFICATION, iwl_mvm_rx_bt_coex_notif, true),
-	RX_HANDLER(BEACON_NOTIFICATION, iwl_mvm_rx_beacon_notif, false),
+	RX_HANDLER(BEACON_NOTIFICATION, iwl_mvm_rx_beacon_notif, true),
 	RX_HANDLER(STATISTICS_NOTIFICATION, iwl_mvm_rx_statistics, true),
 	RX_HANDLER(ANTENNA_COUPLING_NOTIFICATION,
 		   iwl_mvm_rx_ant_coupling_notif, true),
Signature · 1 line
1.8.3.2
#21 lore raw

PATCH 21/23 iwlwifi: mvm: implement mac80211's flush callback

In reply to Emmanuel Grumbach

From: Emmanuel Grumbach <[email protected]>

This allows mac80211 to flush the Tx queues before it sends critical management frames.

---
 drivers/net/wireless/iwlwifi/mvm/mac80211.c | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)
drivers/net/wireless/iwlwifi/mvm/mac80211.c +29 -0
index 3462624..6713b87 100644
@@ -2400,6 +2400,34 @@ out_unlock:
 	mutex_unlock(&mvm->mutex);
 }
 
+static void iwl_mvm_mac_flush(struct ieee80211_hw *hw,
+			      struct ieee80211_vif *vif, u32 queues, bool drop)
+{
+	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+	struct iwl_mvm_vif *mvmvif;
+	struct iwl_mvm_sta *mvmsta;
+
+	if (!vif || vif->type != NL80211_IFTYPE_STATION)
+		return;
+
+	mutex_lock(&mvm->mutex);
+	mvmvif = iwl_mvm_vif_from_mac80211(vif);
+	mvmsta = iwl_mvm_sta_from_staid_protected(mvm, mvmvif->ap_sta_id);
+
+	if (WARN_ON_ONCE(!mvmsta))
+		goto done;
+
+	if (drop) {
+		if (iwl_mvm_flush_tx_path(mvm, mvmsta->tfd_queue_msk, true))
+			IWL_ERR(mvm, "flush request fail\n");
+	} else {
+		iwl_trans_wait_tx_queue_empty(mvm->trans,
+					      mvmsta->tfd_queue_msk);
+	}
+done:
+	mutex_unlock(&mvm->mutex);
+}
+
 const struct ieee80211_ops iwl_mvm_hw_ops = {
 	.tx = iwl_mvm_mac_tx,
 	.ampdu_action = iwl_mvm_mac_ampdu_action,
@@ -2423,6 +2451,7 @@ const struct ieee80211_ops iwl_mvm_hw_ops = {
 	.sta_rc_update = iwl_mvm_sta_rc_update,
 	.conf_tx = iwl_mvm_mac_conf_tx,
 	.mgd_prepare_tx = iwl_mvm_mac_mgd_prepare_tx,
+	.flush = iwl_mvm_mac_flush,
 	.sched_scan_start = iwl_mvm_mac_sched_scan_start,
 	.sched_scan_stop = iwl_mvm_mac_sched_scan_stop,
 	.set_key = iwl_mvm_mac_set_key,
Signature · 1 line
1.8.3.2
#22 lore raw

PATCH 22/23 iwlwifi: mvm: fix sparse warning when _DEBUGFS isn't set

In reply to Emmanuel Grumbach

From: Emmanuel Grumbach <[email protected]>

Since the declaration of iwl_mvm_fw_error_rxf_dump and iwl_mvm_fw_error_sram_dump is under
ifdef CONFIG_IWLWIFI_DEBUGFS, do the same for their implementation.

---
 drivers/net/wireless/iwlwifi/mvm/utils.c | 2 ++
 1 file changed, 2 insertions(+)
drivers/net/wireless/iwlwifi/mvm/utils.c +2 -0
index c5f4532..4c3577e 100644
@@ -519,6 +519,7 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm)
 		iwl_mvm_dump_umac_error_log(mvm);
 }
 
+#ifdef CONFIG_IWLWIFI_DEBUGFS
 void iwl_mvm_fw_error_sram_dump(struct iwl_mvm *mvm)
 {
 	const struct fw_img *img;
@@ -581,6 +582,7 @@ void iwl_mvm_fw_error_rxf_dump(struct iwl_mvm *mvm)
 	}
 	iwl_trans_release_nic_access(mvm->trans, &flags);
 }
+#endif
 
 /**
  * iwl_mvm_send_lq_cmd() - Send link quality command
Signature · 1 line
1.8.3.2
#23 lore raw

PATCH 23/23 iwlwifi: mvm: rs: enable MCS9 for Tx

In reply to Emmanuel Grumbach

From: Eyal Shapira <[email protected]>

After fixes to the rs algorithm reenable MCS9.

---
 drivers/net/wireless/iwlwifi/mvm/rs.c | 8 --------
 1 file changed, 8 deletions(-)
drivers/net/wireless/iwlwifi/mvm/rs.c +0 -8
index 6d5af48..10ad1dc 100644
@@ -2440,10 +2440,6 @@ static void rs_vht_set_enabled_rates(struct ieee80211_sta *sta,
 			if (i == IWL_RATE_9M_INDEX)
 				continue;
 
-			/* Disable MCS9 as a workaround */
-			if (i == IWL_RATE_MCS_9_INDEX)
-				continue;
-
 			/* VHT MCS9 isn't valid for 20Mhz for NSS=1,2 */
 			if (i == IWL_RATE_MCS_9_INDEX &&
 			    sta->bandwidth == IEEE80211_STA_RX_BW_20)
@@ -2462,10 +2458,6 @@ static void rs_vht_set_enabled_rates(struct ieee80211_sta *sta,
 			if (i == IWL_RATE_9M_INDEX)
 				continue;
 
-			/* Disable MCS9 as a workaround */
-			if (i == IWL_RATE_MCS_9_INDEX)
-				continue;
-
 			/* VHT MCS9 isn't valid for 20Mhz for NSS=1,2 */
 			if (i == IWL_RATE_MCS_9_INDEX &&
 			    sta->bandwidth == IEEE80211_STA_RX_BW_20)
Signature · 1 line
1.8.3.2
#24 lore raw
In reply to Emmanuel Grumbach
Quoted 14 lines · Emmanuel Grumbach

Hi John,

I have here another pull request for 3.16.
I merged wireless-next.git because of dependencies on changes in mac80211. I merged iwlwifi-fixes.git (that feeds wireless.git) because of dependencies in the rate scaling changes that were sent to wireless.git.

Eran continues to work on new devices, Eyal is still digging in the rate control stuff, and Johannes added new functionality to the debug system we have in place now along with a few cleanups he made on the way. That's pretty much it.

Please pull.

The following changes since commit 48d11dc37977614a461bfedddc52d1c651bc279f:

rsi: Changing opcode for sta mode according to changes in firmware (2014-04-30 12:13:16 -0400)

Quoted 7 lines

are available in the git repository at:

git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next.git for-john

for you to fetch changes up to 017a64161f6d082f6e3ed85646217bd7217af15a:

iwlwifi: mvm: rs: enable MCS9 for Tx (2014-05-07 22:44:43 +0300)

Pulling now...

Signature · 2 lines
John W. Linville		Someday the world will need a hero, and you
[email protected]			might be all we have.  Be ready.