Skip to contentSkip to conversation

pull request: iwlwifi 2014-04-13

PATCH New Emmanuel Grumbach 2 participants 50 messages Apr 13, 2014 – Apr 22, 2014 Networking drivers (wireless)

lore
Share & tools
lore
#0 lore raw

Hi John,

This is for 3.16.

I have here a bunch of unrelated things. I disabled support for -7.ucode which means that I can removed a lot of code. Eliad has a brand new feature: we reduce the Tx power when the link allows - this reduces our power consumption. The regular changes in power and scan area. One interesting thing though is the patches from Johannes, we have now GRO which allows to increase our throughput in TCP Rx. The main advantage is that it reduces the number of TCP Acks - these TCP Acks are completely useless when we are using A-MPDU since the first packet of the A-MPDU generates a TCP Ack which is made obsolete by the next packets.

Same footer as previous pull request, I won't be available this week, so let's hope I am not causing any problem here.

Thanks!

The following changes since commit a31267c30880ebdc73e6815f58c69a665052fab8:

rtl8187: fix use after free on failure path in rtl8187_probe() (2014-03-31 13:47:41 -0400)

are available in the git repository at:

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

for you to fetch changes up to 3cd5279b021de6501a8012dd856d7a78ee58ead9:

iwlwifi: don't disable SCD chain extension on newer devices (2014-04-13 22:02:44 +0300)

----------------------------------------------------------------
Alexander Bondar (2):
iwlwifi: mvm: Change scan fragmentation condition
iwlwifi: mvm: Fix scan parameters units

Avri Altman (2):
iwlwifi: mvm: Handle power management constraints for additional use-cases
iwlwifi: mvm: Re-factor enabling uAPSD logic

Eliad Peller (4):
iwlwifi: mvm: add lq_cmd/tx_resp reduced_tpc field
iwlwifi: mvm: add ATPC implementation
iwlwifi: mvm: add debugfs file for fixed reduced tx power
iwlwifi: mvm: don't use d3 fw if d0i3 is used

Emmanuel Grumbach (27):
iwlwifi: pcie: don't leave the new NICs awake for commands
iwlwifi: pcie: unify iwl_rx_replenish and iwl_rx_replenish_now
iwlwifi: mvm: remove redundant empty line
iwlwifi: mvm: propagate the beamforming status from firmware
iwlwifi: mvm: don't set AP STA to EINVAL
iwlwifi: allow to wait for a subset of the queues
iwlwifi: pcie: WARN upon traffic while flushing TX queues
iwlwifi: mvm: dump Rx FIFO when the firmware asserts
iwlwifi: mvm: don't enable bcast filtering on P2P client
iwlwifi: mvm: replace BUG_ON by WARN_ON in scan.c
iwlwifi: mvm: deprecate -7 firmware
iwlwifi: remove IWL_UCODE_TLV_FLAGS_NEWBT_COEX TLV flag
iwlwifi: remove IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT flag
iwlwifi: remove IWL_UCODE_TLV_FLAGS_RX_ENERGY_API flag
iwlwifi: remove IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2 flag
iwlwifi: remove IWL_UCODE_TLV_FLAGS_BF_UPDATED flag
iwlwifi: remove IWL_UCODE_TLV_FLAGS_D3_CONTINUITY_API flag
iwlwifi: remove IWL_UCODE_TLV_FLAGS_SCHED_SCAN flag
iwlwifi: remove IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT flag
iwlwifi: remove IWL_UCODE_TLV_FLAGS_STA_KEY_CMD flag
iwlwifi: remove IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD flag
iwlwifi: mvm: BT Coex - don't use comma operator
iwlwifi: mvm: BT Coex - minor API change
iwlwifi: mvm: BT Coex - send priority tables from iwl_send_bt_init_conf
iwlwifi: 7000: bump firmware API version to 9
iwlwifi: mvm: replace leading spaces by tabs
iwlwifi: don't disable SCD chain extension on newer devices

Eran Harary (2):
iwlwifi: mvm: fix the number of channels in family 8000
iwlwifi: move CPU1_CPU2_SEPARATOR_SECTION to iwl-fw.h

Eyal Shapira (1):
iwlwifi: mvm: add per rate tx stats

Eytan Lifshitz (2):
iwlwifi: mvm: Fix warning message when exit thermal throttling
iwlwifi: mvm: Fix tx-backoff when NIC exit thermal throttling

Haim Dreyfuss (1):
iwlwifi: mvm: Add support for Energy based scan (EBS)

Johannes Berg (5):
iwlwifi: pcie: implement GRO without NAPI
iwlwifi: pcie: clarify RX queue need_update handling and locking
iwlwifi: pcie: use bool for TX queue where appropriate
iwlwifi: pcie: fix TX queue locking
iwlwifi: pcie: clarify TX queue need_update handling

Monam Agarwal (1):
iwlwifi: mvm: Use RCU_INIT_POINTER(x, NULL)

 drivers/net/wireless/iwlwifi/dvm/lib.c           |   2 +-
 drivers/net/wireless/iwlwifi/dvm/mac80211.c      |   2 +-
 drivers/net/wireless/iwlwifi/dvm/main.c          |  12 ++
 drivers/net/wireless/iwlwifi/iwl-1000.c          |   1 +
 drivers/net/wireless/iwlwifi/iwl-2000.c          |   2 +
 drivers/net/wireless/iwlwifi/iwl-5000.c          |   1 +
 drivers/net/wireless/iwlwifi/iwl-6000.c          |   3 +
 drivers/net/wireless/iwlwifi/iwl-7000.c          |  13 +-
 drivers/net/wireless/iwlwifi/iwl-config.h        |   5 +
 drivers/net/wireless/iwlwifi/iwl-fw.h            |  27 ++--
 drivers/net/wireless/iwlwifi/iwl-nvm-parse.c     |  25 ++--
 drivers/net/wireless/iwlwifi/iwl-op-mode.h       |  25 +++-
 drivers/net/wireless/iwlwifi/iwl-prph.h          |   8 ++
 drivers/net/wireless/iwlwifi/iwl-trans.h         |  10 +-
 drivers/net/wireless/iwlwifi/mvm/coex.c          |  34 +++--
 drivers/net/wireless/iwlwifi/mvm/d3.c            |  94 ++++++-------
 drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c   |  13 +-
 drivers/net/wireless/iwlwifi/mvm/debugfs.c       |  15 +--
 drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h   |  38 +++---
 drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h     |  17 +--
 drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h     |   2 +-
 drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h   |  34 +++--
 drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h    |  46 +------
 drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h     |   3 +-
 drivers/net/wireless/iwlwifi/mvm/fw-api.h        |  54 +-------
 drivers/net/wireless/iwlwifi/mvm/fw-error-dump.h |   6 +-
 drivers/net/wireless/iwlwifi/mvm/fw.c            |  12 +-
 drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c      |   5 +-
 drivers/net/wireless/iwlwifi/mvm/mac80211.c      |  49 ++++---
 drivers/net/wireless/iwlwifi/mvm/mvm.h           |  26 +++-
 drivers/net/wireless/iwlwifi/mvm/ops.c           |  56 +++++++-
 drivers/net/wireless/iwlwifi/mvm/power.c         | 272 ++++++++++++++++++-------------------
 drivers/net/wireless/iwlwifi/mvm/rs.c            | 330 ++++++++++++++++++++++++++++++++++++++++++++-
 drivers/net/wireless/iwlwifi/mvm/rs.h            |  24 ++++
 drivers/net/wireless/iwlwifi/mvm/rx.c            |  45 +------
 drivers/net/wireless/iwlwifi/mvm/scan.c          |  75 +++++++----
 drivers/net/wireless/iwlwifi/mvm/sf.c            |   3 -
 drivers/net/wireless/iwlwifi/mvm/sta.c           | 177 +++++-------------------
 drivers/net/wireless/iwlwifi/mvm/sta.h           |   3 +
 drivers/net/wireless/iwlwifi/mvm/time-event.c    |  71 ++--------
 drivers/net/wireless/iwlwifi/mvm/tt.c            |  10 +-
 drivers/net/wireless/iwlwifi/mvm/tx.c            |  11 +-
 drivers/net/wireless/iwlwifi/mvm/utils.c         |  46 ++++++-
 drivers/net/wireless/iwlwifi/pcie/internal.h     |   9 +-
 drivers/net/wireless/iwlwifi/pcie/rx.c           |  84 ++++++------
 drivers/net/wireless/iwlwifi/pcie/trans.c        |  47 ++++++-
 drivers/net/wireless/iwlwifi/pcie/tx.c           |  62 +++++----
 47 files changed, 1092 insertions(+), 817 deletions(-)
#1 lore raw

PATCH 1/47 iwlwifi: mvm: Handle power management constraints for additional use-cases

From: Avri Altman <[email protected]>

Today, the driver logic looks for the conditions to disable power management albeit power management should be enabled in a very few distinct cases.
This patch changes the driver logic to enable power management once the required conditions met.
While at it, make some housekeeping and support a few additional use cases:

a) Add support for a standalone p2p client:
Power management should be enabled for a P2P client MAC only if the firmware supports it (TLV flag is set). Instead we used the DCM flag, therefore we didn't cover use cases that did not include the DCM flag.

b) Add support to Same-Channel-Mode (SCM):
If both clients share the same channel (SCM), and there are no other active vifs in the system, power management should be enabled only if the firmware supports this (TLV flag is set).

c) Fix power management logic for GO/AP:
Today, when we detect an active GO / AP MAC - we disable power management for all the vifs altogether. Actually, the correct behavior is to enable power management on a client if on a different channel (based on the firmware capabilities).

d) Housekeeping - Along with that, this patch includes some
code-reorganizing: Today the logic of disabling power is scattered across several functions, specifically in the iterator. For the sake of both readability and scalability, we moved this logic to its applicable function, leaving the iterator gather information only. Furthermore, as power management is a MAC-related attribute, we moved the power management member to the iwl_mvm_vif structure.

---
 drivers/net/wireless/iwlwifi/iwl-fw.h    |   5 +
 drivers/net/wireless/iwlwifi/mvm/mvm.h   |   4 +-
 drivers/net/wireless/iwlwifi/mvm/power.c | 193 ++++++++++++++++++-------------
 3 files changed, 117 insertions(+), 85 deletions(-)
drivers/net/wireless/iwlwifi/iwl-fw.h +5 -0
index d14f193..de70919 100644
@@ -92,8 +92,11 @@
  * @IWL_UCODE_TLV_FLAGS_STA_KEY_CMD: new ADD_STA and ADD_STA_KEY command API
  * @IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD: support device wide power command
  *	containing CAM (Continuous Active Mode) indication.
+ * @IWL_UCODE_TLV_FLAGS_P2P_PM: P2P client supports PM as a stand alone MAC
  * @IWL_UCODE_TLV_FLAGS_P2P_BSS_PS_DCM: support power save on BSS station and
  *	P2P client interfaces simultaneously if they are in different bindings.
+ * @IWL_UCODE_TLV_FLAGS_P2P_BSS_PS_SCM: support power save on BSS station and
+ *	P2P client interfaces simultaneously if they are in same bindings.
  * @IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD: P2P client supports uAPSD power save
  * @IWL_UCODE_TLV_FLAGS_BCAST_FILTERING: uCode supports broadcast filtering.
  * @IWL_UCODE_TLV_FLAGS_GO_UAPSD: AP/GO interfaces support uAPSD clients
@@ -118,7 +121,9 @@ enum iwl_ucode_tlv_flag {
 	IWL_UCODE_TLV_FLAGS_SCHED_SCAN		= BIT(17),
 	IWL_UCODE_TLV_FLAGS_STA_KEY_CMD		= BIT(19),
 	IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD	= BIT(20),
+	IWL_UCODE_TLV_FLAGS_P2P_PM		= BIT(21),
 	IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM	= BIT(22),
+	IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_SCM	= BIT(23),
 	IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT	= BIT(24),
 	IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD	= BIT(26),
 	IWL_UCODE_TLV_FLAGS_BCAST_FILTERING	= BIT(29),
drivers/net/wireless/iwlwifi/mvm/mvm.h +2 -2
index d564233..b032511 100644
@@ -265,6 +265,7 @@ struct iwl_mvm_vif_bf_data {
  * @uploaded: indicates the MAC context has been added to the device
  * @ap_ibss_active: indicates that AP/IBSS is configured and that the interface
  *	should get quota etc.
+ * @pm_enabled - Indicate if MAC power management is allowed
  * @monitor_active: indicates that monitor context is configured, and that the
  *	interface should get quota etc.
  * @low_latency: indicates that this interface is in low-latency mode
@@ -283,6 +284,7 @@ struct iwl_mvm_vif {
 
 	bool uploaded;
 	bool ap_ibss_active;
+	bool pm_enabled;
 	bool monitor_active;
 	bool low_latency;
 	struct iwl_mvm_vif_bf_data bf_data;
@@ -629,8 +631,6 @@ struct iwl_mvm {
 
 	/* Indicate if device power save is allowed */
 	bool ps_disabled;
-	/* Indicate if device power management is allowed */
-	bool pm_disabled;
 };
 
 /* Extract MVM priv from op_mode and _hw */
drivers/net/wireless/iwlwifi/mvm/power.c +110 -83

284 lines not on this page · raw message

Signature · 1 line
1.8.3.2
#2 lore raw

PATCH 2/47 iwlwifi: mvm: fix the number of channels in family 8000

In reply to Emmanuel Grumbach

From: Eran Harary <[email protected]>

Number of channels changed from 40 to 50

---
 drivers/net/wireless/iwlwifi/iwl-nvm-parse.c   | 25 ++++++++++++++-----------
 drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h |  8 ++++++--
 2 files changed, 20 insertions(+), 13 deletions(-)
drivers/net/wireless/iwlwifi/iwl-nvm-parse.c +14 -11
index 6be30c6..4049c0d 100644
@@ -134,12 +134,13 @@ static const u8 iwl_nvm_channels_family_8000[] = {
 	149, 153, 157, 161, 165, 169, 173, 177, 181
 };
 
-#define IWL_NUM_CHANNELS	ARRAY_SIZE(iwl_nvm_channels)
+#define IWL_NUM_CHANNELS		ARRAY_SIZE(iwl_nvm_channels)
 #define IWL_NUM_CHANNELS_FAMILY_8000	ARRAY_SIZE(iwl_nvm_channels_family_8000)
-#define NUM_2GHZ_CHANNELS	14
-#define FIRST_2GHZ_HT_MINUS	5
-#define LAST_2GHZ_HT_PLUS	9
-#define LAST_5GHZ_HT		161
+#define NUM_2GHZ_CHANNELS		14
+#define NUM_2GHZ_CHANNELS_FAMILY_8000	13
+#define FIRST_2GHZ_HT_MINUS		5
+#define LAST_2GHZ_HT_PLUS		9
+#define LAST_5GHZ_HT			161
 
 #define DEFAULT_MAX_TX_POWER 16
 
@@ -202,21 +203,23 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
 	struct ieee80211_channel *channel;
 	u16 ch_flags;
 	bool is_5ghz;
-	int num_of_ch;
+	int num_of_ch, num_2ghz_channels;
 	const u8 *nvm_chan;
 
 	if (cfg->device_family != IWL_DEVICE_FAMILY_8000) {
 		num_of_ch = IWL_NUM_CHANNELS;
 		nvm_chan = &iwl_nvm_channels[0];
+		num_2ghz_channels = NUM_2GHZ_CHANNELS;
 	} else {
 		num_of_ch = IWL_NUM_CHANNELS_FAMILY_8000;
 		nvm_chan = &iwl_nvm_channels_family_8000[0];
+		num_2ghz_channels = NUM_2GHZ_CHANNELS_FAMILY_8000;
 	}
 
 	for (ch_idx = 0; ch_idx < num_of_ch; ch_idx++) {
 		ch_flags = __le16_to_cpup(nvm_ch_flags + ch_idx);
 
-		if (ch_idx >= NUM_2GHZ_CHANNELS &&
+		if (ch_idx >= num_2ghz_channels &&
 		    !data->sku_cap_band_52GHz_enable)
 			ch_flags &= ~NVM_CHANNEL_VALID;
 
@@ -225,7 +228,7 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
 					 "Ch. %d Flags %x [%sGHz] - No traffic\n",
 					 nvm_chan[ch_idx],
 					 ch_flags,
-					 (ch_idx >= NUM_2GHZ_CHANNELS) ?
+					 (ch_idx >= num_2ghz_channels) ?
 					 "5.2" : "2.4");
 			continue;
 		}
@@ -234,7 +237,7 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
 		n_channels++;
 
 		channel->hw_value = nvm_chan[ch_idx];
-		channel->band = (ch_idx < NUM_2GHZ_CHANNELS) ?
+		channel->band = (ch_idx < num_2ghz_channels) ?
 				IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
 		channel->center_freq =
 			ieee80211_channel_to_frequency(
@@ -242,7 +245,7 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
 
 		/* TODO: Need to be dependent to the NVM */
 		channel->flags = IEEE80211_CHAN_NO_HT40;
-		if (ch_idx < NUM_2GHZ_CHANNELS &&
+		if (ch_idx < num_2ghz_channels &&
 		    (ch_flags & NVM_CHANNEL_40MHZ)) {
 			if (nvm_chan[ch_idx] <= LAST_2GHZ_HT_PLUS)
 				channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS;
@@ -250,7 +253,7 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
 				channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS;
 		} else if (nvm_chan[ch_idx] <= LAST_5GHZ_HT &&
 			   (ch_flags & NVM_CHANNEL_40MHZ)) {
-			if ((ch_idx - NUM_2GHZ_CHANNELS) % 2 == 0)
+			if ((ch_idx - num_2ghz_channels) % 2 == 0)
 				channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS;
 			else
 				channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS;
drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h +6 -2
index 9426905..02856e0 100644
@@ -169,8 +169,12 @@ enum iwl_scan_type {
 	SCAN_TYPE_DISCOVERY_FORCED	= 6,
 }; /* SCAN_ACTIVITY_TYPE_E_VER_1 */
 
-/* Maximal number of channels to scan */
-#define MAX_NUM_SCAN_CHANNELS 0x24
+/**
+ * Maximal number of channels to scan
+ * it should be equal to:
+ * max(IWL_NUM_CHANNELS, IWL_NUM_CHANNELS_FAMILY_8000)
+ */
+#define MAX_NUM_SCAN_CHANNELS 50
 
 /**
  * struct iwl_scan_cmd - scan request command
Signature · 1 line
1.8.3.2
#3 lore raw

PATCH 3/47 iwlwifi: pcie: don't leave the new NICs awake for commands

In reply to Emmanuel Grumbach

From: Emmanuel Grumbach <[email protected]>

A hardware bug had been discovered on 7260 / 3160 and 7265 and the workaround for this bug is to force the NIC to stay awake as long as we have host commands in flight. This workaround has been introduced for all NICs in a previous patch:

b9439491055a ("iwlwifi: pcie: keep the NIC awake when commands are in flight")

In newer NICs, this bug is solved, so we can let the NIC go to sleep even when we send commands. The hardware will wake up when we increment the scheduler write pointer. Make the workaround conditional to only use it on affected hardware.

---
 drivers/net/wireless/iwlwifi/iwl-7000.c   | 1 +
 drivers/net/wireless/iwlwifi/iwl-config.h | 3 +++
 drivers/net/wireless/iwlwifi/pcie/tx.c    | 9 ++++++---
 3 files changed, 10 insertions(+), 3 deletions(-)
drivers/net/wireless/iwlwifi/iwl-7000.c +1 -0
index 003a546..c42d80c 100644
@@ -107,6 +107,7 @@ static const struct iwl_base_params iwl7000_base_params = {
 	.max_event_log_size = 512,
 	.shadow_reg_enable = true,
 	.pcie_l1_allowed = true,
+	.apmg_wake_up_wa = true,
 };
 
 static const struct iwl_ht_params iwl7000_ht_params = {
drivers/net/wireless/iwlwifi/iwl-config.h +3 -0
index 3f17dc3..8c16730 100644
@@ -146,6 +146,8 @@ static inline u8 num_of_ant(u8 mask)
  * @wd_timeout: TX queues watchdog timeout
  * @max_event_log_size: size of event log buffer size for ucode event logging
  * @shadow_reg_enable: HW shadow register support
+ * @apmg_wake_up_wa: should the MAC access REQ be asserted when a command
+ *	is in flight. This is due to a HW bug in 7260, 3160 and 7265.
  */
 struct iwl_base_params {
 	int eeprom_size;
@@ -160,6 +162,7 @@ struct iwl_base_params {
 	u32 max_event_log_size;
 	const bool shadow_reg_enable;
 	const bool pcie_l1_allowed;
+	const bool apmg_wake_up_wa;
 };
 
 /*
drivers/net/wireless/iwlwifi/pcie/tx.c +6 -3
index 3b0c72c..0368609 100644
@@ -1028,7 +1028,8 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx)
 		}
 	}
 
-	if (q->read_ptr == q->write_ptr) {
+	if (trans->cfg->base_params->apmg_wake_up_wa &&
+	    q->read_ptr == q->write_ptr) {
 		spin_lock_irqsave(&trans_pcie->reg_lock, flags);
 		WARN_ON(!trans_pcie->cmd_in_flight);
 		trans_pcie->cmd_in_flight = false;
@@ -1405,9 +1406,11 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
 	/*
 	 * wake up the NIC to make sure that the firmware will see the host
 	 * command - we will let the NIC sleep once all the host commands
-	 * returned.
+	 * returned. This needs to be done only on NICs that have
+	 * apmg_wake_up_wa set.
 	 */
-	if (!trans_pcie->cmd_in_flight) {
+	if (trans->cfg->base_params->apmg_wake_up_wa &&
+	    !trans_pcie->cmd_in_flight) {
 		trans_pcie->cmd_in_flight = true;
 		__iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL,
 					 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
Signature · 1 line
1.8.3.2
#4 lore raw

PATCH 4/47 iwlwifi: mvm: add lq_cmd/tx_resp reduced_tpc field

In reply to Emmanuel Grumbach

From: Eliad Peller <[email protected]>

The fw recently added an option to set tx power reduction per station (in the lq_cmd command), and get the tx power reduction used (in the tx_resp struct).

Use them and propogate this value up to mac80211's tx response (in order to use it later in the rate-scaling algorithm).

---
 drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h | 2 +-
 drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h | 3 ++-
 drivers/net/wireless/iwlwifi/mvm/sta.h       | 3 +++
 drivers/net/wireless/iwlwifi/mvm/tx.c        | 7 +++++++
 4 files changed, 13 insertions(+), 2 deletions(-)
drivers/net/wireless/iwlwifi/mvm/fw-api-rs.h +1 -1
index 39148b5..8bb5b94 100644
@@ -334,7 +334,7 @@ enum {
  */
 struct iwl_lq_cmd {
 	u8 sta_id;
-	u8 reserved1;
+	u8 reduced_tpc;
 	u16 control;
 	/* LINK_QUAL_GENERAL_PARAMS_API_S_VER_1 */
 	u8 flags;
drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h +2 -1
index 8e122f3..6cc5f52 100644
@@ -482,7 +482,8 @@ struct iwl_mvm_tx_resp {
 	u8 pa_integ_res_b[3];
 	u8 pa_integ_res_c[3];
 	__le16 measurement_req_id;
-	__le16 reserved;
+	u8 reduced_tpc;
+	u8 reserved;
 
 	__le32 tfd_info;
 	__le16 seq_ctl;
drivers/net/wireless/iwlwifi/mvm/sta.h +3 -0
index 2ed84c4..e5e3071 100644
@@ -253,6 +253,8 @@ enum iwl_mvm_agg_state {
  *	This is basically (last acked packet++).
  * @rate_n_flags: Rate at which Tx was attempted. Holds the data between the
  *	Tx response (TX_CMD), and the block ack notification (COMPRESSED_BA).
+ * @reduced_tpc: Reduced tx power. Holds the data between the
+ *	Tx response (TX_CMD), and the block ack notification (COMPRESSED_BA).
  * @state: state of the BA agreement establishment / tear down.
  * @txq_id: Tx queue used by the BA session
  * @ssn: the first packet to be sent in AGG HW queue in Tx AGG start flow, or
@@ -265,6 +267,7 @@ struct iwl_mvm_tid_data {
 	u16 next_reclaimed;
 	/* The rest is Tx AGG related */
 	u32 rate_n_flags;
+	u8 reduced_tpc;
 	enum iwl_mvm_agg_state state;
 	u16 txq_id;
 	u16 ssn;
drivers/net/wireless/iwlwifi/mvm/tx.c +7 -0
index 879aeac..0a4ad45 100644
@@ -636,6 +636,10 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
 			seq_ctl = le16_to_cpu(hdr->seq_ctrl);
 		}
 
+		BUILD_BUG_ON(ARRAY_SIZE(info->status.status_driver_data) < 1);
+		info->status.status_driver_data[0] =
+				(void *)(uintptr_t)tx_resp->reduced_tpc;
+
 		ieee80211_tx_status_ni(mvm->hw, skb);
 	}
 
@@ -815,6 +819,7 @@ static void iwl_mvm_rx_tx_cmd_agg(struct iwl_mvm *mvm,
 		struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
 		mvmsta->tid_data[tid].rate_n_flags =
 			le32_to_cpu(tx_resp->initial_rate);
+		mvmsta->tid_data[tid].reduced_tpc = tx_resp->reduced_tpc;
 	}
 
 	rcu_read_unlock();
@@ -928,6 +933,8 @@ int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
 			info->status.ampdu_len = ba_notif->txed;
 			iwl_mvm_hwrate_to_tx_status(tid_data->rate_n_flags,
 						    info);
+			info->status.status_driver_data[0] =
+				(void *)(uintptr_t)tid_data->reduced_tpc;
 		}
 	}
 
Signature · 1 line
1.8.3.2
#5 lore raw

PATCH 5/47 iwlwifi: mvm: add ATPC implementation

In reply to Emmanuel Grumbach

From: Eliad Peller <[email protected]>

Implement Adaptive Tx Power Control algorithm.

ATPC basically tries to decrease the tx power as much as possible while the throughput is not being hurt.

---
 drivers/net/wireless/iwlwifi/mvm/coex.c |  11 ++
 drivers/net/wireless/iwlwifi/mvm/mvm.h  |   2 +
 drivers/net/wireless/iwlwifi/mvm/rs.c   | 211 +++++++++++++++++++++++++++++++-
 drivers/net/wireless/iwlwifi/mvm/rs.h   |  12 ++
 4 files changed, 233 insertions(+), 3 deletions(-)
drivers/net/wireless/iwlwifi/mvm/coex.c +11 -0
index 685f7e8..4bd47c9 100644
@@ -1215,6 +1215,17 @@ bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm,
 	return iwl_get_coex_type(mvm, mvmsta->vif) == BT_COEX_TIGHT_LUT;
 }
 
+bool iwl_mvm_bt_coex_is_tpc_allowed(struct iwl_mvm *mvm,
+				    enum ieee80211_band band)
+{
+	u32 bt_activity = le32_to_cpu(mvm->last_bt_notif.bt_activity_grading);
+
+	if (band != IEEE80211_BAND_2GHZ)
+		return false;
+
+	return bt_activity >= BT_LOW_TRAFFIC;
+}
+
 u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr,
 			   struct ieee80211_tx_info *info, u8 ac)
 {
drivers/net/wireless/iwlwifi/mvm/mvm.h +2 -0
index b032511..5420700 100644
@@ -936,6 +936,8 @@ u16 iwl_mvm_coex_agg_time_limit(struct iwl_mvm *mvm,
 				struct ieee80211_sta *sta);
 bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm,
 				     struct ieee80211_sta *sta);
+bool iwl_mvm_bt_coex_is_tpc_allowed(struct iwl_mvm *mvm,
+				    enum ieee80211_band band);
 u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr,
 			   struct ieee80211_tx_info *info, u8 ac);
 int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, bool enable);
drivers/net/wireless/iwlwifi/mvm/rs.c +208 -3

279 lines not on this page · raw message

drivers/net/wireless/iwlwifi/mvm/rs.h +12 -0
index 3332b39..d8b0345 100644
@@ -157,6 +157,13 @@ enum {
 #define IWL_RATE_INCREASE_TH		6400	/*  50% */
 #define RS_SR_FORCE_DECREASE		1920	/*  15% */
 
+#define TPC_SR_FORCE_INCREASE		9600	/* 75% */
+#define TPC_SR_NO_INCREASE		10880	/* 85% */
+#define TPC_TX_POWER_STEP		3
+#define TPC_MAX_REDUCTION		15
+#define TPC_NO_REDUCTION		0
+#define TPC_INVALID			0xff
+
 #define LINK_QUAL_AGG_TIME_LIMIT_DEF	(4000) /* 4 milliseconds */
 #define LINK_QUAL_AGG_TIME_LIMIT_MAX	(8000)
 #define LINK_QUAL_AGG_TIME_LIMIT_MIN	(100)
@@ -279,6 +286,8 @@ struct iwl_scale_tbl_info {
 	enum rs_column column;
 	const u16 *expected_tpt;	/* throughput metrics; expected_tpt_G, etc. */
 	struct iwl_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */
+	/* per txpower-reduction history */
+	struct iwl_rate_scale_data tpc_win[TPC_MAX_REDUCTION + 1];
 };
 
 enum {
@@ -337,6 +346,9 @@ struct iwl_lq_sta {
 	u32 last_rate_n_flags;
 	/* packets destined for this STA are aggregated */
 	u8 is_agg;
+
+	/* tx power reduce for this sta */
+	int tpc_reduce;
 };
 
 /* Initialize station's rate scaling information after adding station */
Signature · 1 line
1.8.3.2
#6 lore raw

PATCH 6/47 iwlwifi: mvm: add debugfs file for fixed reduced tx power

In reply to Emmanuel Grumbach

From: Eliad Peller <[email protected]>

Allow fixing the tx power reduction through debugfs file.

The change doesn't take affect immediately, but will be considered the next time tpc is evaluated.

---
 drivers/net/wireless/iwlwifi/mvm/rs.c | 14 ++++++++++++++
 drivers/net/wireless/iwlwifi/mvm/rs.h |  2 ++
 2 files changed, 16 insertions(+)
drivers/net/wireless/iwlwifi/mvm/rs.c +14 -0
index fd090bc..50fd460 100644
@@ -1863,6 +1863,15 @@ static bool rs_tpc_perform(struct iwl_mvm *mvm,
 	int weak, strong;
 	int weak_tpt = IWL_INVALID_VALUE, strong_tpt = IWL_INVALID_VALUE;
 
+#ifdef CONFIG_MAC80211_DEBUGFS
+	if (lq_sta->dbg_fixed_txp_reduction <= TPC_MAX_REDUCTION) {
+		IWL_DEBUG_RATE(mvm, "fixed tpc: %d",
+			       lq_sta->dbg_fixed_txp_reduction);
+		lq_sta->lq.reduced_tpc = lq_sta->dbg_fixed_txp_reduction;
+		return cur != lq_sta->dbg_fixed_txp_reduction;
+	}
+#endif
+
 	rcu_read_lock();
 	chanctx_conf = rcu_dereference(vif->chanctx_conf);
 	if (WARN_ON(!chanctx_conf))
@@ -2613,6 +2622,7 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
 	lq_sta->is_agg = 0;
 #ifdef CONFIG_MAC80211_DEBUGFS
 	lq_sta->dbg_fixed_rate = 0;
+	lq_sta->dbg_fixed_txp_reduction = TPC_INVALID;
 #endif
 #ifdef CONFIG_IWLWIFI_DEBUGFS
 	iwl_mvm_reset_frame_stats(mvm, &mvm->drv_rx_stats);
@@ -3076,6 +3086,9 @@ static void rs_add_debugfs(void *mvm, void *mvm_sta, struct dentry *dir)
 	lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file =
 		debugfs_create_u8("tx_agg_tid_enable", S_IRUSR | S_IWUSR, dir,
 				  &lq_sta->tx_agg_tid_en);
+	lq_sta->rs_sta_dbgfs_reduced_txp_file =
+		debugfs_create_u8("reduced_tpc", S_IRUSR | S_IWUSR, dir,
+				  &lq_sta->dbg_fixed_txp_reduction);
 }
 
 static void rs_remove_debugfs(void *mvm, void *mvm_sta)
@@ -3084,6 +3097,7 @@ static void rs_remove_debugfs(void *mvm, void *mvm_sta)
 	debugfs_remove(lq_sta->rs_sta_dbgfs_scale_table_file);
 	debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file);
 	debugfs_remove(lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file);
+	debugfs_remove(lq_sta->rs_sta_dbgfs_reduced_txp_file);
 }
 #endif
 
drivers/net/wireless/iwlwifi/mvm/rs.h +2 -0
index d8b0345..fcc056d 100644
@@ -336,7 +336,9 @@ struct iwl_lq_sta {
 	struct dentry *rs_sta_dbgfs_scale_table_file;
 	struct dentry *rs_sta_dbgfs_stats_table_file;
 	struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file;
+	struct dentry *rs_sta_dbgfs_reduced_txp_file;
 	u32 dbg_fixed_rate;
+	u8 dbg_fixed_txp_reduction;
 #endif
 	struct iwl_mvm *drv;
 
Signature · 1 line
1.8.3.2
#7 lore raw

PATCH 7/47 iwlwifi: pcie: implement GRO without NAPI

In reply to Emmanuel Grumbach

From: Johannes Berg <[email protected]>

Use the new NAPI infrastructure added to mac80211 to get GRO. We don't really implement NAPI since we don't have a real poll function and we never schedule a NAPI poll. Instead of this, we collect all the packets we got from a single interrupt and then call napi_gro_flush().

This allows us to benefit from GRO. In half duplex medium like WiFi, its main advantage is that it reduces the number of TCP Acks, hence improving the TCP Rx performance.

Since we call the Rx path with a spinlock held, remove the might_sleep mention from the op_mode's API.

[Squash different patches and rewrite the commit message]
---
 drivers/net/wireless/iwlwifi/dvm/main.c      | 12 ++++++++++++
 drivers/net/wireless/iwlwifi/iwl-op-mode.h   | 25 ++++++++++++++++++++++---
 drivers/net/wireless/iwlwifi/mvm/ops.c       | 12 ++++++++++++
 drivers/net/wireless/iwlwifi/mvm/rx.c        |  2 +-
 drivers/net/wireless/iwlwifi/mvm/tx.c        |  4 ++--
 drivers/net/wireless/iwlwifi/pcie/internal.h |  3 +++
 drivers/net/wireless/iwlwifi/pcie/rx.c       | 17 +++++++++++++----
 drivers/net/wireless/iwlwifi/pcie/trans.c    | 21 +++++++++++++++++++++
 8 files changed, 86 insertions(+), 10 deletions(-)
drivers/net/wireless/iwlwifi/dvm/main.c +12 -0
index 6a6df71..6a00353 100644
@@ -2053,6 +2053,17 @@ static bool iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
 	return false;
 }
 
+static void iwl_napi_add(struct iwl_op_mode *op_mode,
+			 struct napi_struct *napi,
+			 struct net_device *napi_dev,
+			 int (*poll)(struct napi_struct *, int),
+			 int weight)
+{
+	struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
+
+	ieee80211_napi_add(priv->hw, napi, napi_dev, poll, weight);
+}
+
 static const struct iwl_op_mode_ops iwl_dvm_ops = {
 	.start = iwl_op_mode_dvm_start,
 	.stop = iwl_op_mode_dvm_stop,
@@ -2065,6 +2076,7 @@ static const struct iwl_op_mode_ops iwl_dvm_ops = {
 	.cmd_queue_full = iwl_cmd_queue_full,
 	.nic_config = iwl_nic_config,
 	.wimax_active = iwl_wimax_active,
+	.napi_add = iwl_napi_add,
 };
 
 /*****************************************************************************
drivers/net/wireless/iwlwifi/iwl-op-mode.h +22 -3
index ea29504..99785c8 100644
@@ -63,6 +63,7 @@
 #ifndef __iwl_op_mode_h__
 #define __iwl_op_mode_h__
 
+#include <linux/netdevice.h>
 #include <linux/debugfs.h>
 
 struct iwl_op_mode;
@@ -112,8 +113,11 @@ struct iwl_cfg;
  * @stop: stop the op_mode. Must free all the memory allocated.
  *	May sleep
  * @rx: Rx notification to the op_mode. rxb is the Rx buffer itself. Cmd is the
- *	HCMD this Rx responds to.
- *	This callback may sleep, it is called from a threaded IRQ handler.
+ *	HCMD this Rx responds to. Can't sleep.
+ * @napi_add: NAPI initialisation. The transport is fully responsible for NAPI,
+ *	but the higher layers need to know about it (in particular mac80211 to
+ *	to able to call the right NAPI RX functions); this function is needed
+ *	to eventually call netif_napi_add() with higher layer involvement.
  * @queue_full: notifies that a HW queue is full.
  *	Must be atomic and called with BH disabled.
  * @queue_not_full: notifies that a HW queue is not full any more.
@@ -143,6 +147,11 @@ struct iwl_op_mode_ops {
 	void (*stop)(struct iwl_op_mode *op_mode);
 	int (*rx)(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb,
 		  struct iwl_device_cmd *cmd);
+	void (*napi_add)(struct iwl_op_mode *op_mode,
+			 struct napi_struct *napi,
+			 struct net_device *napi_dev,
+			 int (*poll)(struct napi_struct *, int),
+			 int weight);
 	void (*queue_full)(struct iwl_op_mode *op_mode, int queue);
 	void (*queue_not_full)(struct iwl_op_mode *op_mode, int queue);
 	bool (*hw_rf_kill)(struct iwl_op_mode *op_mode, bool state);
@@ -180,7 +189,6 @@ static inline int iwl_op_mode_rx(struct iwl_op_mode *op_mode,
 				  struct iwl_rx_cmd_buffer *rxb,
 				  struct iwl_device_cmd *cmd)
 {
-	might_sleep();
 	return op_mode->ops->rx(op_mode, rxb, cmd);
 }
 
@@ -249,4 +257,15 @@ static inline int iwl_op_mode_exit_d0i3(struct iwl_op_mode *op_mode)
 	return op_mode->ops->exit_d0i3(op_mode);
 }
 
+static inline void iwl_op_mode_napi_add(struct iwl_op_mode *op_mode,
+					struct napi_struct *napi,
+					struct net_device *napi_dev,
+					int (*poll)(struct napi_struct *, int),
+					int weight)
+{
+	if (!op_mode->ops->napi_add)
+		return;
+	op_mode->ops->napi_add(op_mode, napi, napi_dev, poll, weight);
+}
+
 #endif /* __iwl_op_mode_h__ */
drivers/net/wireless/iwlwifi/mvm/ops.c +12 -0
index 9545d7f..e436c04 100644
@@ -1183,6 +1183,17 @@ out:
 	return ret;
 }
 
+static void iwl_mvm_napi_add(struct iwl_op_mode *op_mode,
+			     struct napi_struct *napi,
+			     struct net_device *napi_dev,
+			     int (*poll)(struct napi_struct *, int),
+			     int weight)
+{
+	struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
+
+	ieee80211_napi_add(mvm->hw, napi, napi_dev, poll, weight);
+}
+
 static const struct iwl_op_mode_ops iwl_mvm_ops = {
 	.start = iwl_op_mode_mvm_start,
 	.stop = iwl_op_mode_mvm_stop,
@@ -1196,4 +1207,5 @@ static const struct iwl_op_mode_ops iwl_mvm_ops = {
 	.nic_config = iwl_mvm_nic_config,
 	.enter_d0i3 = iwl_mvm_enter_d0i3,
 	.exit_d0i3 = iwl_mvm_exit_d0i3,
+	.napi_add = iwl_mvm_napi_add,
 };
drivers/net/wireless/iwlwifi/mvm/rx.c +1 -1
index 6061553..69f6aa6 100644
@@ -130,7 +130,7 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
 
 	memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
 
-	ieee80211_rx_ni(mvm->hw, skb);
+	ieee80211_rx(mvm->hw, skb);
 }
 
 static void iwl_mvm_calc_rssi(struct iwl_mvm *mvm,
drivers/net/wireless/iwlwifi/mvm/tx.c +2 -2
index 0a4ad45..ff1b630 100644
@@ -640,7 +640,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
 		info->status.status_driver_data[0] =
 				(void *)(uintptr_t)tx_resp->reduced_tpc;
 
-		ieee80211_tx_status_ni(mvm->hw, skb);
+		ieee80211_tx_status(mvm->hw, skb);
 	}
 
 	if (txq_id >= mvm->first_agg_queue) {
@@ -944,7 +944,7 @@ int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
 
 	while (!skb_queue_empty(&reclaimed_skbs)) {
 		skb = __skb_dequeue(&reclaimed_skbs);
-		ieee80211_tx_status_ni(mvm->hw, skb);
+		ieee80211_tx_status(mvm->hw, skb);
 	}
 
 	return 0;
drivers/net/wireless/iwlwifi/pcie/internal.h +3 -0
index 9091513..e269468 100644
@@ -270,6 +270,9 @@ struct iwl_trans_pcie {
 	struct iwl_trans *trans;
 	struct iwl_drv *drv;
 
+	struct net_device napi_dev;
+	struct napi_struct napi;
+
 	/* INT ICT Table */
 	__le32 *ict_tbl;
 	dma_addr_t ict_tbl_dma;
drivers/net/wireless/iwlwifi/pcie/rx.c +13 -4
index fdfa396..e8e5afc 100644
@@ -673,7 +673,6 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
 	/* Reuse the page if possible. For notification packets and
 	 * SKBs that fail to Rx correctly, add them back into the
 	 * rx_free list for reuse later. */
-	spin_lock(&rxq->lock);
 	if (rxb->page != NULL) {
 		rxb->page_dma =
 			dma_map_page(trans->dev, rxb->page, 0,
@@ -694,7 +693,6 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
 		}
 	} else
 		list_add_tail(&rxb->list, &rxq->rx_used);
-	spin_unlock(&rxq->lock);
 }
 
 /*
@@ -709,6 +707,8 @@ static void iwl_pcie_rx_handle(struct iwl_trans *trans)
 	u32 count = 8;
 	int total_empty;
 
+restart:
+	spin_lock(&rxq->lock);
 	/* uCode's read index (stored in shared DRAM) indicates the last Rx
 	 * buffer that the driver may process (last buffer filled by ucode). */
 	r = le16_to_cpu(ACCESS_ONCE(rxq->rb_stts->closed_rb_num)) & 0x0FFF;
@@ -743,18 +743,25 @@ static void iwl_pcie_rx_handle(struct iwl_trans *trans)
 			count++;
 			if (count >= 8) {
 				rxq->read = i;
+				spin_unlock(&rxq->lock);
 				iwl_pcie_rx_replenish_now(trans);
 				count = 0;
+				goto restart;
 			}
 		}
 	}
 
 	/* Backtrack one entry */
 	rxq->read = i;
+	spin_unlock(&rxq->lock);
+
 	if (fill_rx)
 		iwl_pcie_rx_replenish_now(trans);
 	else
 		iwl_pcie_rxq_restock(trans);
+
+	if (trans_pcie->napi.poll)
+		napi_gro_flush(&trans_pcie->napi, false);
 }
 
 /*
@@ -1068,8 +1075,6 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
 		iwl_write8(trans, CSR_INT_PERIODIC_REG,
 			    CSR_INT_PERIODIC_DIS);
 
-		iwl_pcie_rx_handle(trans);
-
 		/*
 		 * Enable periodic interrupt in 8 msec only if we received
 		 * real RX interrupt (instead of just periodic int), to catch
@@ -1082,6 +1087,10 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
 				   CSR_INT_PERIODIC_ENA);
 
 		isr_stats->rx++;
+
+		local_bh_disable();
+		iwl_pcie_rx_handle(trans);
+		local_bh_enable();
 	}
 
 	/* This "Tx" DMA channel is used only for loading uCode */
drivers/net/wireless/iwlwifi/pcie/trans.c +21 -0
index dcfd6d8..97e6bd8 100644
@@ -1053,6 +1053,12 @@ static void iwl_trans_pcie_write_prph(struct iwl_trans *trans, u32 addr,
 	iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_WDAT, val);
 }
 
+static int iwl_pcie_dummy_napi_poll(struct napi_struct *napi, int budget)
+{
+	WARN_ON(1);
+	return 0;
+}
+
 static void iwl_trans_pcie_configure(struct iwl_trans *trans,
 				     const struct iwl_trans_config *trans_cfg)
 {
@@ -1079,6 +1085,18 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans,
 
 	trans_pcie->command_names = trans_cfg->command_names;
 	trans_pcie->bc_table_dword = trans_cfg->bc_table_dword;
+
+	/* Initialize NAPI here - it should be before registering to mac80211
+	 * in the opmode but after the HW struct is allocated.
+	 * As this function may be called again in some corner cases don't
+	 * do anything if NAPI was already initialized.
+	 */
+	if (!trans_pcie->napi.poll && trans->op_mode->ops->napi_add) {
+		init_dummy_netdev(&trans_pcie->napi_dev);
+		iwl_op_mode_napi_add(trans->op_mode, &trans_pcie->napi,
+				     &trans_pcie->napi_dev,
+				     iwl_pcie_dummy_napi_poll, 64);
+	}
 }
 
 void iwl_trans_pcie_free(struct iwl_trans *trans)
@@ -1099,6 +1117,9 @@ void iwl_trans_pcie_free(struct iwl_trans *trans)
 	pci_disable_device(trans_pcie->pci_dev);
 	kmem_cache_destroy(trans->dev_cmd_pool);
 
+	if (trans_pcie->napi.poll)
+		netif_napi_del(&trans_pcie->napi);
+
 	kfree(trans);
 }
 
Signature · 1 line
1.8.3.2
#8 lore raw

PATCH 8/47 iwlwifi: pcie: clarify RX queue need_update handling and locking

In reply to Emmanuel Grumbach

From: Johannes Berg <[email protected]>

When shadow registers are enabled, then need_update never needs to be set, so move the need_update handling into the function that really needs to do it (iwl_pcie_rxq_inc_wr_ptr) and also separate the check when it woke up. While at it, convert it to bool.

This also clarifies the locking and means the irq_lock needs to no longer be held for any such updates.

The irq_lock also doesn't have to be held for restocking since everything else locks the RX queue properly, so remove that and finally disentangle the two locks entirely so there aren't any dependencies between the two left.

---
 drivers/net/wireless/iwlwifi/pcie/internal.h |  2 +-
 drivers/net/wireless/iwlwifi/pcie/rx.c       | 44 ++++++++++++++++------------
 2 files changed, 26 insertions(+), 20 deletions(-)
drivers/net/wireless/iwlwifi/pcie/internal.h +1 -1
index e269468..477ac36 100644
@@ -102,7 +102,7 @@ struct iwl_rxq {
 	u32 write_actual;
 	struct list_head rx_free;
 	struct list_head rx_used;
-	int need_update;
+	bool need_update;
 	struct iwl_rb_status *rb_stts;
 	dma_addr_t rb_stts_dma;
 	spinlock_t lock;
drivers/net/wireless/iwlwifi/pcie/rx.c +25 -19

92 lines not on this page · raw message

Signature · 1 line
1.8.3.2
#9 lore raw

PATCH 9/47 iwlwifi: pcie: use bool for TX queue where appropriate

In reply to Emmanuel Grumbach

From: Johannes Berg <[email protected]>

Instead of using u8 to hold logic values, use bool.

Also fix a comment, the return value is no longer relevant.

---
 drivers/net/wireless/iwlwifi/pcie/internal.h |  2 +-
 drivers/net/wireless/iwlwifi/pcie/tx.c       | 22 ++++++++++------------
 2 files changed, 11 insertions(+), 13 deletions(-)
drivers/net/wireless/iwlwifi/pcie/internal.h +1 -1
index 477ac36..1261a41 100644
@@ -231,7 +231,7 @@ struct iwl_txq {
 	spinlock_t lock;
 	struct timer_list stuck_timer;
 	struct iwl_trans_pcie *trans_pcie;
-	u8 need_update;
+	bool need_update;
 	u8 active;
 	bool ampdu;
 };
drivers/net/wireless/iwlwifi/pcie/tx.c +10 -12
index 0368609..6c7dca1 100644
@@ -293,7 +293,7 @@ void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_txq *txq)
 	u32 reg = 0;
 	int txq_id = txq->q.id;
 
-	if (txq->need_update == 0)
+	if (!txq->need_update)
 		return;
 
 	/*
@@ -328,7 +328,7 @@ void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_txq *txq)
 	IWL_DEBUG_TX(trans, "Q:%d WR: 0x%x\n", txq_id, txq->q.write_ptr);
 	iwl_write32(trans, HBUS_TARG_WRPTR, txq->q.write_ptr | (txq_id << 8));
 
-	txq->need_update = 0;
+	txq->need_update = false;
 }
 
 static inline dma_addr_t iwl_pcie_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx)
@@ -542,7 +542,7 @@ static int iwl_pcie_txq_init(struct iwl_trans *trans, struct iwl_txq *txq,
 {
 	int ret;
 
-	txq->need_update = 0;
+	txq->need_update = false;
 
 	/* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
 	 * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */
@@ -1393,7 +1393,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
 		kfree(txq->entries[idx].free_buf);
 	txq->entries[idx].free_buf = dup_buf;
 
-	txq->need_update = 1;
+	txq->need_update = true;
 
 	trace_iwlwifi_dev_hcmd(trans->dev, cmd, cmd_size, &out_cmd->hdr);
 
@@ -1664,7 +1664,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
 	dma_addr_t tb0_phys, tb1_phys, scratch_phys;
 	void *tb1_addr;
 	u16 len, tb1_len, tb2_len;
-	u8 wait_write_ptr = 0;
+	bool wait_write_ptr = false;
 	__le16 fc = hdr->frame_control;
 	u8 hdr_len = ieee80211_hdrlen(fc);
 	u16 wifi_seq;
@@ -1766,10 +1766,10 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
 				  skb->data + hdr_len, tb2_len);
 
 	if (!ieee80211_has_morefrags(fc)) {
-		txq->need_update = 1;
+		txq->need_update = true;
 	} else {
-		wait_write_ptr = 1;
-		txq->need_update = 0;
+		wait_write_ptr = true;
+		txq->need_update = false;
 	}
 
 	/* start timer if queue currently empty */
@@ -1783,13 +1783,11 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
 
 	/*
 	 * At this point the frame is "transmitted" successfully
-	 * and we will get a TX status notification eventually,
-	 * regardless of the value of ret. "ret" only indicates
-	 * whether or not we should update the write pointer.
+	 * and we will get a TX status notification eventually.
 	 */
 	if (iwl_queue_space(q) < q->high_mark) {
 		if (wait_write_ptr) {
-			txq->need_update = 1;
+			txq->need_update = true;
 			iwl_pcie_txq_inc_wr_ptr(trans, txq);
 		} else {
 			iwl_stop_queue(trans, txq);
Signature · 1 line
1.8.3.2
#10 lore raw

PATCH 10/47 iwlwifi: pcie: fix TX queue locking

In reply to Emmanuel Grumbach

From: Johannes Berg <[email protected]>

When updating the write pointer, the TX queue should be locked to get consistent state, fix that in the interrupt handler.

---
 drivers/net/wireless/iwlwifi/pcie/rx.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/net/wireless/iwlwifi/pcie/rx.c +4 -1
index 57e98cc..152c763 100644
@@ -1042,8 +1042,11 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
 	if (inta & CSR_INT_BIT_WAKEUP) {
 		IWL_DEBUG_ISR(trans, "Wakeup interrupt\n");
 		iwl_pcie_rxq_check_wrptr(trans);
-		for (i = 0; i < trans->cfg->base_params->num_of_queues; i++)
+		for (i = 0; i < trans->cfg->base_params->num_of_queues; i++) {
+			spin_lock(&trans_pcie->txq[i].lock);
 			iwl_pcie_txq_inc_wr_ptr(trans, &trans_pcie->txq[i]);
+			spin_unlock(&trans_pcie->txq[i].lock);
+		}
 
 		isr_stats->wakeup++;
 
Signature · 1 line
1.8.3.2
#11 lore raw

PATCH 11/47 iwlwifi: pcie: clarify TX queue need_update handling

In reply to Emmanuel Grumbach

From: Johannes Berg <[email protected]>

Similar to the recent RX queue patch, this changes the need_update handling for the TX queues to be clearer and only done when needed.

---
 drivers/net/wireless/iwlwifi/pcie/internal.h |  2 +-
 drivers/net/wireless/iwlwifi/pcie/rx.c       |  7 +----
 drivers/net/wireless/iwlwifi/pcie/tx.c       | 44 ++++++++++++++++------------
 3 files changed, 28 insertions(+), 25 deletions(-)
drivers/net/wireless/iwlwifi/pcie/internal.h +1 -1
index 1261a41..1b95d85 100644
@@ -365,7 +365,7 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo,
 void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int queue);
 int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
 		      struct iwl_device_cmd *dev_cmd, int txq_id);
-void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_txq *txq);
+void iwl_pcie_txq_check_wrptrs(struct iwl_trans *trans);
 int iwl_trans_pcie_send_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
 void iwl_pcie_hcmd_complete(struct iwl_trans *trans,
 			    struct iwl_rx_cmd_buffer *rxb, int handler_status);
drivers/net/wireless/iwlwifi/pcie/rx.c +1 -6
index 152c763..0937f84 100644
@@ -889,7 +889,6 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
 	struct isr_statistics *isr_stats = &trans_pcie->isr_stats;
 	u32 inta = 0;
 	u32 handled = 0;
-	u32 i;
 
 	lock_map_acquire(&trans->sync_cmd_lockdep_map);
 
@@ -1042,11 +1041,7 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
 	if (inta & CSR_INT_BIT_WAKEUP) {
 		IWL_DEBUG_ISR(trans, "Wakeup interrupt\n");
 		iwl_pcie_rxq_check_wrptr(trans);
-		for (i = 0; i < trans->cfg->base_params->num_of_queues; i++) {
-			spin_lock(&trans_pcie->txq[i].lock);
-			iwl_pcie_txq_inc_wr_ptr(trans, &trans_pcie->txq[i]);
-			spin_unlock(&trans_pcie->txq[i].lock);
-		}
+		iwl_pcie_txq_check_wrptrs(trans);
 
 		isr_stats->wakeup++;
 
drivers/net/wireless/iwlwifi/pcie/tx.c +26 -18

100 lines not on this page · raw message

Signature · 1 line
1.8.3.2
#12 lore raw

PATCH 12/47 iwlwifi: pcie: unify iwl_rx_replenish and iwl_rx_replenish_now

In reply to Emmanuel Grumbach

From: Emmanuel Grumbach <[email protected]>

Besides the different allocation flags, they are really the same. Pass the gfp_t flags as a parameter, and unify them.

---
 drivers/net/wireless/iwlwifi/pcie/rx.c | 19 ++++++-------------
 1 file changed, 6 insertions(+), 13 deletions(-)
drivers/net/wireless/iwlwifi/pcie/rx.c +6 -13
index 0937f84..4a26a08 100644
@@ -373,16 +373,9 @@ static void iwl_pcie_rxq_free_rbs(struct iwl_trans *trans)
  * Also restock the Rx queue via iwl_pcie_rxq_restock.
  * This is called as a scheduled work item (except for during initialization)
  */
-static void iwl_pcie_rx_replenish(struct iwl_trans *trans)
+static void iwl_pcie_rx_replenish(struct iwl_trans *trans, gfp_t gfp)
 {
-	iwl_pcie_rxq_alloc_rbs(trans, GFP_KERNEL);
-
-	iwl_pcie_rxq_restock(trans);
-}
-
-static void iwl_pcie_rx_replenish_now(struct iwl_trans *trans)
-{
-	iwl_pcie_rxq_alloc_rbs(trans, GFP_ATOMIC);
+	iwl_pcie_rxq_alloc_rbs(trans, gfp);
 
 	iwl_pcie_rxq_restock(trans);
 }
@@ -392,7 +385,7 @@ static void iwl_pcie_rx_replenish_work(struct work_struct *data)
 	struct iwl_trans_pcie *trans_pcie =
 	    container_of(data, struct iwl_trans_pcie, rx_replenish);
 
-	iwl_pcie_rx_replenish(trans_pcie->trans);
+	iwl_pcie_rx_replenish(trans_pcie->trans, GFP_KERNEL);
 }
 
 static int iwl_pcie_rx_alloc(struct iwl_trans *trans)
@@ -528,7 +521,7 @@ int iwl_pcie_rx_init(struct iwl_trans *trans)
 	memset(rxq->rb_stts, 0, sizeof(*rxq->rb_stts));
 	spin_unlock(&rxq->lock);
 
-	iwl_pcie_rx_replenish(trans);
+	iwl_pcie_rx_replenish(trans, GFP_KERNEL);
 
 	iwl_pcie_rx_hw_init(trans, rxq);
 
@@ -750,7 +743,7 @@ restart:
 			if (count >= 8) {
 				rxq->read = i;
 				spin_unlock(&rxq->lock);
-				iwl_pcie_rx_replenish_now(trans);
+				iwl_pcie_rx_replenish(trans, GFP_ATOMIC);
 				count = 0;
 				goto restart;
 			}
@@ -762,7 +755,7 @@ restart:
 	spin_unlock(&rxq->lock);
 
 	if (fill_rx)
-		iwl_pcie_rx_replenish_now(trans);
+		iwl_pcie_rx_replenish(trans, GFP_ATOMIC);
 	else
 		iwl_pcie_rxq_restock(trans);
 
Signature · 1 line
1.8.3.2
#13 lore raw

PATCH 13/47 iwlwifi: move CPU1_CPU2_SEPARATOR_SECTION to iwl-fw.h

In reply to Emmanuel Grumbach

From: Eran Harary <[email protected]>

This define is related to the firmware packaging and is needed by more than one transport.

---
 drivers/net/wireless/iwlwifi/iwl-fw.h     | 1 +
 drivers/net/wireless/iwlwifi/pcie/trans.c | 1 -
 2 files changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/iwlwifi/iwl-fw.h +1 -0
index de70919..f7ea9c0 100644
@@ -188,6 +188,7 @@ enum iwl_ucode_sec {
 #define IWL_UCODE_SECTION_MAX 12
 #define IWL_API_ARRAY_SIZE	1
 #define IWL_CAPABILITIES_ARRAY_SIZE	1
+#define CPU1_CPU2_SEPARATOR_SECTION	0xFFFFCCCC
 
 struct iwl_ucode_capabilities {
 	u32 max_probe_length;
drivers/net/wireless/iwlwifi/pcie/trans.c +0 -1
index 97e6bd8..2548f49 100644
@@ -103,7 +103,6 @@ static void iwl_pcie_set_pwr(struct iwl_trans *trans, bool vaux)
 
 /* PCI registers */
 #define PCI_CFG_RETRY_TIMEOUT	0x041
-#define CPU1_CPU2_SEPARATOR_SECTION	0xFFFFCCCC
 
 static void iwl_pcie_apm_config(struct iwl_trans *trans)
 {
Signature · 1 line
1.8.3.2
#14 lore raw

PATCH 14/47 iwlwifi: mvm: remove redundant empty line

In reply to Emmanuel Grumbach

From: Emmanuel Grumbach <[email protected]>

---
 drivers/net/wireless/iwlwifi/mvm/rx.c | 1 -
 1 file changed, 1 deletion(-)
drivers/net/wireless/iwlwifi/mvm/rx.c +0 -1
index 69f6aa6..ac9a84e 100644
@@ -60,7 +60,6 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *****************************************************************************/
 #include "iwl-trans.h"
-
 #include "mvm.h"
 #include "fw-api.h"
 
Signature · 1 line
1.8.3.2
#15 lore raw

PATCH 15/47 iwlwifi: mvm: propagate the beamforming status from firmware

In reply to Emmanuel Grumbach

From: Emmanuel Grumbach <[email protected]>

The firmware tells us if an Rx packet was beamformed or not. Propagate this data to mac80211's rx_status.vht_flags. The main user of this data is the radiotap header.

---
 drivers/net/wireless/iwlwifi/mvm/rx.c | 2 ++
 1 file changed, 2 insertions(+)
drivers/net/wireless/iwlwifi/mvm/rx.c +2 -0
index ac9a84e..40fd5dc 100644
@@ -393,6 +393,8 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
 		rx_status.rate_idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK;
 		rx_status.flag |= RX_FLAG_VHT;
 		rx_status.flag |= stbc << RX_FLAG_STBC_SHIFT;
+		if (rate_n_flags & RATE_MCS_BF_MSK)
+			rx_status.vht_flag |= RX_VHT_FLAG_BF;
 	} else {
 		rx_status.rate_idx =
 			iwl_mvm_legacy_rate_to_mac80211_idx(rate_n_flags,
Signature · 1 line
1.8.3.2
#16 lore raw

PATCH 16/47 iwlwifi: mvm: don't set AP STA to EINVAL

In reply to Emmanuel Grumbach

From: Emmanuel Grumbach <[email protected]>

Now that mac80211 calls pre_rcu_remove and we set the fw_id_to_mac_id pointer to -ENOENT before the station is removed, we don't need to set fw_id_to_mac_id to -EINVAL when the station is really removed.
Leave fw_id_to_mac_id to be -ENOENT which will let the drain worker (iwl_mvm_sta_drained_wk) know that this station is not to be drained.
We don't need to drain this station since it is our AP in managed mode and we flush all its frames synchronously anyway.

Setting the AP station to -EINVAL could lead to confusion since internal stations are also reserved with -EINVAL, this confusion showed up in the logs as:

Drained sta 0, but it is internal?

---
 drivers/net/wireless/iwlwifi/mvm/sta.c | 8 --------
 1 file changed, 8 deletions(-)
drivers/net/wireless/iwlwifi/mvm/sta.c +0 -8
index f339ef8..eb3e4bc 100644
@@ -520,14 +520,6 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
 		/* flush its queues here since we are freeing mvm_sta */
 		ret = iwl_mvm_flush_tx_path(mvm, mvm_sta->tfd_queue_msk, true);
 
-		/*
-		 * Put a non-NULL since the fw station isn't removed.
-		 * It will be removed after the MAC will be set as
-		 * unassoc.
-		 */
-		rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id],
-				   ERR_PTR(-EINVAL));
-
 		/* if we are associated - we can't remove the AP STA now */
 		if (vif->bss_conf.assoc)
 			return ret;
Signature · 1 line
1.8.3.2
#17 lore raw

PATCH 17/47 iwlwifi: allow to wait for a subset of the queues

In reply to Emmanuel Grumbach

From: Emmanuel Grumbach <[email protected]>

This will be used later to flush / wait for queues that are related to a specific vif.

---
 drivers/net/wireless/iwlwifi/dvm/lib.c      |  2 +-
 drivers/net/wireless/iwlwifi/dvm/mac80211.c |  2 +-
 drivers/net/wireless/iwlwifi/iwl-trans.h    | 10 +++++-----
 drivers/net/wireless/iwlwifi/pcie/trans.c   |  6 +++++-
 4 files changed, 12 insertions(+), 8 deletions(-)
drivers/net/wireless/iwlwifi/dvm/lib.c +1 -1
index 576f7ee..d169228 100644
@@ -180,7 +180,7 @@ void iwlagn_dev_txfifo_flush(struct iwl_priv *priv)
 		goto done;
 	}
 	IWL_DEBUG_INFO(priv, "wait transmit/flush all frames\n");
-	iwl_trans_wait_tx_queue_empty(priv->trans);
+	iwl_trans_wait_tx_queue_empty(priv->trans, 0xffffffff);
 done:
 	ieee80211_wake_queues(priv->hw);
 	mutex_unlock(&priv->mutex);
drivers/net/wireless/iwlwifi/dvm/mac80211.c +1 -1
index dd55c9c..d3abc15 100644
@@ -1119,7 +1119,7 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
 		}
 	}
 	IWL_DEBUG_MAC80211(priv, "wait transmit/flush all frames\n");
-	iwl_trans_wait_tx_queue_empty(priv->trans);
+	iwl_trans_wait_tx_queue_empty(priv->trans, 0xffffffff);
 done:
 	mutex_unlock(&priv->mutex);
 	IWL_DEBUG_MAC80211(priv, "leave\n");
drivers/net/wireless/iwlwifi/iwl-trans.h +5 -5
index 8cdb0dd..22fd94e 100644
@@ -437,8 +437,7 @@ struct iwl_trans;
  *	this one. The op_mode must not configure the HCMD queue. May sleep.
  * @txq_disable: de-configure a Tx queue to send AMPDUs
  *	Must be atomic
- * @wait_tx_queue_empty: wait until all tx queues are empty
- *	May sleep
+ * @wait_tx_queue_empty: wait until tx queues are empty. May sleep.
  * @dbgfs_register: add the dbgfs files under this directory. Files will be
  *	automatically deleted.
  * @write8: write a u8 to a register at offset ofs from the BAR
@@ -490,7 +489,7 @@ struct iwl_trans_ops {
 	void (*txq_disable)(struct iwl_trans *trans, int queue);
 
 	int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir);
-	int (*wait_tx_queue_empty)(struct iwl_trans *trans);
+	int (*wait_tx_queue_empty)(struct iwl_trans *trans, u32 txq_bm);
 
 	void (*write8)(struct iwl_trans *trans, u32 ofs, u8 val);
 	void (*write32)(struct iwl_trans *trans, u32 ofs, u32 val);
@@ -759,12 +758,13 @@ static inline void iwl_trans_ac_txq_enable(struct iwl_trans *trans, int queue,
 			     IWL_MAX_TID_COUNT, IWL_FRAME_LIMIT, 0);
 }
 
-static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans)
+static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans,
+						u32 txq_bm)
 {
 	if (unlikely(trans->state != IWL_TRANS_FW_ALIVE))
 		IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
 
-	return trans->ops->wait_tx_queue_empty(trans);
+	return trans->ops->wait_tx_queue_empty(trans, txq_bm);
 }
 
 static inline int iwl_trans_dbgfs_register(struct iwl_trans *trans,
drivers/net/wireless/iwlwifi/pcie/trans.c +5 -1
index 2548f49..0f20e73 100644
@@ -1257,7 +1257,7 @@ static int iwl_trans_pcie_write_mem(struct iwl_trans *trans, u32 addr,
 
 #define IWL_FLUSH_WAIT_MS	2000
 
-static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans)
+static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, u32 txq_bm)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	struct iwl_txq *txq;
@@ -1272,6 +1272,10 @@ static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans)
 	for (cnt = 0; cnt < trans->cfg->base_params->num_of_queues; cnt++) {
 		if (cnt == trans_pcie->cmd_queue)
 			continue;
+		if (!test_bit(cnt, trans_pcie->queue_used))
+			continue;
+		if (!(BIT(cnt) & txq_bm))
+			continue;
 		txq = &trans_pcie->txq[cnt];
 		q = &txq->q;
 		while (q->read_ptr != q->write_ptr && !time_after(jiffies,
Signature · 1 line
1.8.3.2
#18 lore raw

PATCH 18/47 iwlwifi: pcie: WARN upon traffic while flushing TX queues

In reply to Emmanuel Grumbach

From: Emmanuel Grumbach <[email protected]>

This must not happen - otherwise we might keep flushing forever.

---
 drivers/net/wireless/iwlwifi/pcie/trans.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)
drivers/net/wireless/iwlwifi/pcie/trans.c +14 -2
index 0f20e73..4845d50 100644
@@ -1270,6 +1270,8 @@ static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, u32 txq_bm)
 
 	/* waiting for all the tx frames complete might take a while */
 	for (cnt = 0; cnt < trans->cfg->base_params->num_of_queues; cnt++) {
+		u8 wr_ptr;
+
 		if (cnt == trans_pcie->cmd_queue)
 			continue;
 		if (!test_bit(cnt, trans_pcie->queue_used))
@@ -1278,9 +1280,19 @@ static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, u32 txq_bm)
 			continue;
 		txq = &trans_pcie->txq[cnt];
 		q = &txq->q;
-		while (q->read_ptr != q->write_ptr && !time_after(jiffies,
-		       now + msecs_to_jiffies(IWL_FLUSH_WAIT_MS)))
+		wr_ptr = ACCESS_ONCE(q->write_ptr);
+
+		while (q->read_ptr != ACCESS_ONCE(q->write_ptr) &&
+		       !time_after(jiffies,
+				   now + msecs_to_jiffies(IWL_FLUSH_WAIT_MS))) {
+			u8 write_ptr = ACCESS_ONCE(q->write_ptr);
+
+			if (WARN_ONCE(wr_ptr != write_ptr,
+				      "WR pointer moved while flushing %d -> %d\n",
+				      wr_ptr, write_ptr))
+				return -ETIMEDOUT;
 			msleep(1);
+		}
 
 		if (q->read_ptr != q->write_ptr) {
 			IWL_ERR(trans,
Signature · 1 line
1.8.3.2
#19 lore raw

PATCH 19/47 iwlwifi: mvm: dump Rx FIFO when the firmware asserts

In reply to Emmanuel Grumbach

From: Emmanuel Grumbach <[email protected]>

The Rx FIFO includes valuable data - dump it when the FW asserts. Also - free the SRAM and Rx FIFO when we create the file, and don't collect new SRAM / Rx FIFO if the previous file hasn't been collected through debugfs yet.

Also - add a comment to saying that the ASSERT output should not be modified since we have automatic scripts that monitor this output.

---
 drivers/net/wireless/iwlwifi/iwl-prph.h          |  8 +++++
 drivers/net/wireless/iwlwifi/mvm/debugfs.c       |  3 --
 drivers/net/wireless/iwlwifi/mvm/fw-error-dump.h |  6 ++--
 drivers/net/wireless/iwlwifi/mvm/mvm.h           |  3 ++
 drivers/net/wireless/iwlwifi/mvm/ops.c           | 20 +++++++++--
 drivers/net/wireless/iwlwifi/mvm/utils.c         | 46 +++++++++++++++++++++++-
 6 files changed, 78 insertions(+), 8 deletions(-)
drivers/net/wireless/iwlwifi/iwl-prph.h +8 -0
index 5f657c5..7793110 100644
@@ -348,4 +348,12 @@ enum secure_load_status_reg {
 
 #define LMPM_SECURE_TIME_OUT	(100)
 
+/* Rx FIFO */
+#define RXF_SIZE_ADDR			(0xa00c88)
+#define RXF_SIZE_BYTE_CND_POS		(7)
+#define RXF_SIZE_BYTE_CNT_MSK		(0x3ff << RXF_SIZE_BYTE_CND_POS)
+
+#define RXF_LD_FENCE_OFFSET_ADDR	(0xa00c10)
+#define RXF_FIFO_RD_FENCE_ADDR		(0xa00c0c)
+
 #endif				/* __iwl_prph_h__ */
drivers/net/wireless/iwlwifi/mvm/debugfs.c +0 -3
index 1b52dee..d727572 100644
@@ -136,9 +136,6 @@ static int iwl_dbgfs_fw_error_dump_open(struct inode *inode, struct file *file)
 
 	file->private_data = mvm->fw_error_dump;
 	mvm->fw_error_dump = NULL;
-	kfree(mvm->fw_error_sram);
-	mvm->fw_error_sram = NULL;
-	mvm->fw_error_sram_len = 0;
 	ret = 0;
 
 out:
drivers/net/wireless/iwlwifi/mvm/fw-error-dump.h +4 -2
index 58c8941..f381908 100644
@@ -71,10 +71,12 @@
  * 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:
  */
 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_MAX,
 };
@@ -89,7 +91,7 @@ struct iwl_fw_error_dump_data {
 	__le32 type;
 	__le32 len;
 	__u8 data[];
-} __packed __aligned(4);
+} __packed;
 
 /**
  * struct iwl_fw_error_dump_file - the layout of the header of the file
@@ -101,6 +103,6 @@ struct iwl_fw_error_dump_file {
 	__le32 barker;
 	__le32 file_len;
 	u8 data[0];
-} __packed __aligned(4);
+} __packed;
 
 #endif /* __fw_error_dump_h__ */
drivers/net/wireless/iwlwifi/mvm/mvm.h +3 -0
index 5420700..9f2ecf2 100644
@@ -580,6 +580,8 @@ struct iwl_mvm {
 	void *fw_error_dump;
 	void *fw_error_sram;
 	u32 fw_error_sram_len;
+	u32 *fw_error_rxf;
+	u32 fw_error_rxf_len;
 
 	struct led_classdev led;
 
@@ -705,6 +707,7 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm);
 #ifdef CONFIG_IWLWIFI_DEBUGFS
 void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm);
 void iwl_mvm_fw_error_sram_dump(struct iwl_mvm *mvm);
+void iwl_mvm_fw_error_rxf_dump(struct iwl_mvm *mvm);
 #endif
 u8 first_antenna(u8 mask);
 u8 iwl_mvm_next_antenna(struct iwl_mvm *mvm, u8 valid, u8 last_idx);
drivers/net/wireless/iwlwifi/mvm/ops.c +18 -2
index e436c04..7cb401b 100644
@@ -538,6 +538,7 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
 	kfree(mvm->scan_cmd);
 	vfree(mvm->fw_error_dump);
 	kfree(mvm->fw_error_sram);
+	kfree(mvm->fw_error_rxf);
 	kfree(mvm->mcast_filter_cmd);
 	mvm->mcast_filter_cmd = NULL;
 
@@ -821,8 +822,9 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
 		return;
 
 	file_len = mvm->fw_error_sram_len +
+		   mvm->fw_error_rxf_len +
 		   sizeof(*dump_file) +
-		   sizeof(*dump_data);
+		   sizeof(*dump_data) * 2;
 
 	dump_file = vmalloc(file_len);
 	if (!dump_file)
@@ -833,7 +835,12 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
 	dump_file->barker = cpu_to_le32(IWL_FW_ERROR_DUMP_BARKER);
 	dump_file->file_len = cpu_to_le32(file_len);
 	dump_data = (void *)dump_file->data;
-	dump_data->type = IWL_FW_ERROR_DUMP_SRAM;
+	dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_RXF);
+	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->type = cpu_to_le32(IWL_FW_ERROR_DUMP_SRAM);
 	dump_data->len = cpu_to_le32(mvm->fw_error_sram_len);
 
 	/*
@@ -842,6 +849,14 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
 	 * mvm->fw_error_sram right now.
 	 */
 	memcpy(dump_data->data, mvm->fw_error_sram, mvm->fw_error_sram_len);
+
+	kfree(mvm->fw_error_rxf);
+	mvm->fw_error_rxf = NULL;
+	mvm->fw_error_rxf_len = 0;
+
+	kfree(mvm->fw_error_sram);
+	mvm->fw_error_sram = NULL;
+	mvm->fw_error_sram_len = 0;
 }
 #endif
 
@@ -853,6 +868,7 @@ static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode)
 
 #ifdef CONFIG_IWLWIFI_DEBUGFS
 	iwl_mvm_fw_error_sram_dump(mvm);
+	iwl_mvm_fw_error_rxf_dump(mvm);
 #endif
 
 	iwl_mvm_nic_restart(mvm);
drivers/net/wireless/iwlwifi/mvm/utils.c +45 -1

70 lines not on this page · raw message

Signature · 1 line
1.8.3.2
#20 lore raw

PATCH 20/47 iwlwifi: mvm: Fix warning message when exit thermal throttling

In reply to Emmanuel Grumbach

From: Eytan Lifshitz <[email protected]>

When NIC exit thermal throttling while having minimal tx-backoff restriction, the warning message that indicate about that state won't show up. Fixed.

---
 drivers/net/wireless/iwlwifi/mvm/tt.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/wireless/iwlwifi/mvm/tt.c +2 -1
index 7a99fa3..cee4e72 100644
@@ -484,7 +484,8 @@ void iwl_mvm_tt_handler(struct iwl_mvm *mvm)
 		IWL_WARN(mvm,
 			 "Due to high temperature thermal throttling initiated\n");
 		tt->throttle = true;
-	} else if (tt->throttle && !tt->dynamic_smps && tt->tx_backoff == 0 &&
+	} else if (tt->throttle && !tt->dynamic_smps &&
+		   tt->tx_backoff == tt->min_backoff &&
 		   temperature <= params->tx_protection_exit) {
 		IWL_WARN(mvm,
 			 "Temperature is back to normal thermal throttling stopped\n");
Signature · 1 line
1.8.3.2
#21 lore raw

PATCH 21/47 iwlwifi: mvm: Fix tx-backoff when NIC exit thermal throttling

In reply to Emmanuel Grumbach

From: Eytan Lifshitz <[email protected]>

When NIC is exiting from thermal throttling state (i.e. after heating and then cooling down), tx-backoff values are assigned to be zero, instead of being restored to the minimal value. Fixed.

---
 drivers/net/wireless/iwlwifi/mvm/tt.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/net/wireless/iwlwifi/mvm/tt.c +4 -3
index cee4e72..39a3e03 100644
@@ -468,13 +468,14 @@ void iwl_mvm_tt_handler(struct iwl_mvm *mvm)
 	}
 
 	if (params->support_tx_backoff) {
-		tx_backoff = 0;
+		tx_backoff = tt->min_backoff;
 		for (i = 0; i < TT_TX_BACKOFF_SIZE; i++) {
 			if (temperature < params->tx_backoff[i].temperature)
 				break;
-			tx_backoff = params->tx_backoff[i].backoff;
+			tx_backoff = max(tt->min_backoff,
+					 params->tx_backoff[i].backoff);
 		}
-		if (tx_backoff != 0)
+		if (tx_backoff != tt->min_backoff)
 			throttle_enable = true;
 		if (tt->tx_backoff != tx_backoff)
 			iwl_mvm_tt_tx_backoff(mvm, tx_backoff);
Signature · 1 line
1.8.3.2
#22 lore raw

PATCH 22/47 iwlwifi: mvm: don't enable bcast filtering on P2P client

In reply to Emmanuel Grumbach

From: Emmanuel Grumbach <[email protected]>

The firmware doesn't support broadcast filtering on P2P client. Trying to enable it makes the firmware assert.

---
 drivers/net/wireless/iwlwifi/mvm/mac80211.c | 4 ++++
 1 file changed, 4 insertions(+)
drivers/net/wireless/iwlwifi/mvm/mac80211.c +4 -0
index 4dd9ff4..01b4228 100644
@@ -1223,6 +1223,10 @@ static int iwl_mvm_configure_bcast_filter(struct iwl_mvm *mvm,
 	if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BCAST_FILTERING))
 		return 0;
 
+	/* bcast filtering isn't supported for P2P client */
+	if (vif->p2p)
+		return 0;
+
 	if (!iwl_mvm_bcast_filter_build_cmd(mvm, &cmd))
 		return 0;
 
Signature · 1 line
1.8.3.2
#23 lore raw

PATCH 23/47 iwlwifi: mvm: Use RCU_INIT_POINTER(x, NULL)

In reply to Emmanuel Grumbach

From: Monam Agarwal <[email protected]>

rcu_assign_pointer() ensures that the initialization of a structure is carried out before storing a pointer to that structure. However, in the case that NULL is assigned there's no structure to initialize so using RCU_INIT_POINTER instead is safe and more efficient.

[rewrite commit log]
---
 drivers/net/wireless/iwlwifi/mvm/sta.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/net/wireless/iwlwifi/mvm/sta.c +4 -4
index eb3e4bc..075500c 100644
@@ -498,7 +498,7 @@ void iwl_mvm_sta_drained_wk(struct work_struct *wk)
 				sta_id);
 			continue;
 		}
-		rcu_assign_pointer(mvm->fw_id_to_mac_id[sta_id], NULL);
+		RCU_INIT_POINTER(mvm->fw_id_to_mac_id[sta_id], NULL);
 		clear_bit(sta_id, mvm->sta_drained);
 	}
 
@@ -549,7 +549,7 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
 	} else {
 		spin_unlock_bh(&mvm_sta->lock);
 		ret = iwl_mvm_rm_sta_common(mvm, mvm_sta->sta_id);
-		rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id], NULL);
+		RCU_INIT_POINTER(mvm->fw_id_to_mac_id[mvm_sta->sta_id], NULL);
 	}
 
 	return ret;
@@ -563,7 +563,7 @@ int iwl_mvm_rm_sta_id(struct iwl_mvm *mvm,
 
 	lockdep_assert_held(&mvm->mutex);
 
-	rcu_assign_pointer(mvm->fw_id_to_mac_id[sta_id], NULL);
+	RCU_INIT_POINTER(mvm->fw_id_to_mac_id[sta_id], NULL);
 	return ret;
 }
 
@@ -585,7 +585,7 @@ int iwl_mvm_allocate_int_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *sta,
 
 void iwl_mvm_dealloc_int_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *sta)
 {
-	rcu_assign_pointer(mvm->fw_id_to_mac_id[sta->sta_id], NULL);
+	RCU_INIT_POINTER(mvm->fw_id_to_mac_id[sta->sta_id], NULL);
 	memset(sta, 0, sizeof(struct iwl_mvm_int_sta));
 	sta->sta_id = IWL_MVM_STATION_COUNT;
 }
Signature · 1 line
1.8.3.2
#24 lore raw

PATCH 24/47 iwlwifi: mvm: add per rate tx stats

In reply to Emmanuel Grumbach

From: Eyal Shapira <[email protected]>

Collect accumulated stats of tx attempts and successes per rate and column for debugging purposes. These stats can be read via debugfs file drv_tx_stats and can also be reset by writing to this file.

---
 drivers/net/wireless/iwlwifi/mvm/rs.c | 105 ++++++++++++++++++++++++++++++++--
 drivers/net/wireless/iwlwifi/mvm/rs.h |  10 ++++
 2 files changed, 111 insertions(+), 4 deletions(-)
drivers/net/wireless/iwlwifi/mvm/rs.c +101 -4
index 50fd460..7a332cb 100644
@@ -641,7 +641,8 @@ static int _rs_collect_tx_data(struct iwl_scale_tbl_info *tbl,
 	return 0;
 }
 
-static int rs_collect_tx_data(struct iwl_scale_tbl_info *tbl,
+static int rs_collect_tx_data(struct iwl_lq_sta *lq_sta,
+			      struct iwl_scale_tbl_info *tbl,
 			      int scale_index, int attempts, int successes,
 			      u8 reduced_txp)
 {
@@ -651,6 +652,11 @@ static int rs_collect_tx_data(struct iwl_scale_tbl_info *tbl,
 	if (scale_index < 0 || scale_index >= IWL_RATE_COUNT)
 		return -EINVAL;
 
+	if (tbl->column != RS_COLUMN_INVALID) {
+		lq_sta->tx_stats[tbl->column][scale_index].total += attempts;
+		lq_sta->tx_stats[tbl->column][scale_index].success += successes;
+	}
+
 	/* Select window for current tx bit rate */
 	window = &(tbl->win[scale_index]);
 
@@ -1119,7 +1125,7 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband,
 	if (info->flags & IEEE80211_TX_STAT_AMPDU) {
 		ucode_rate = le32_to_cpu(table->rs_table[0]);
 		rs_rate_from_ucode_rate(ucode_rate, info->band, &rate);
-		rs_collect_tx_data(curr_tbl, rate.index,
+		rs_collect_tx_data(lq_sta, curr_tbl, rate.index,
 				   info->status.ampdu_len,
 				   info->status.ampdu_ack_len,
 				   reduced_txp);
@@ -1155,7 +1161,7 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband,
 			else
 				continue;
 
-			rs_collect_tx_data(tmp_tbl, rate.index, 1,
+			rs_collect_tx_data(lq_sta, tmp_tbl, rate.index, 1,
 					   i < retries ? 0 : legacy_success,
 					   reduced_txp);
 		}
@@ -2928,7 +2934,6 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file,
 	size_t buf_size;
 	u32 parsed_rate;
 
-
 	mvm = lq_sta->drv;
 	memset(buf, 0, sizeof(buf));
 	buf_size = min(count, sizeof(buf) -  1);
@@ -3074,6 +3079,94 @@ static const struct file_operations rs_sta_dbgfs_stats_table_ops = {
 	.llseek = default_llseek,
 };
 
+static ssize_t rs_sta_dbgfs_drv_tx_stats_read(struct file *file,
+					      char __user *user_buf,
+					      size_t count, loff_t *ppos)
+{
+	static const char * const column_name[] = {
+		[RS_COLUMN_LEGACY_ANT_A] = "LEGACY_ANT_A",
+		[RS_COLUMN_LEGACY_ANT_B] = "LEGACY_ANT_B",
+		[RS_COLUMN_SISO_ANT_A] = "SISO_ANT_A",
+		[RS_COLUMN_SISO_ANT_B] = "SISO_ANT_B",
+		[RS_COLUMN_SISO_ANT_A_SGI] = "SISO_ANT_A_SGI",
+		[RS_COLUMN_SISO_ANT_B_SGI] = "SISO_ANT_B_SGI",
+		[RS_COLUMN_MIMO2] = "MIMO2",
+		[RS_COLUMN_MIMO2_SGI] = "MIMO2_SGI",
+	};
+
+	static const char * const rate_name[] = {
+		[IWL_RATE_1M_INDEX] = "1M",
+		[IWL_RATE_2M_INDEX] = "2M",
+		[IWL_RATE_5M_INDEX] = "5.5M",
+		[IWL_RATE_11M_INDEX] = "11M",
+		[IWL_RATE_6M_INDEX] = "6M|MCS0",
+		[IWL_RATE_9M_INDEX] = "9M",
+		[IWL_RATE_12M_INDEX] = "12M|MCS1",
+		[IWL_RATE_18M_INDEX] = "18M|MCS2",
+		[IWL_RATE_24M_INDEX] = "24M|MCS3",
+		[IWL_RATE_36M_INDEX] = "36M|MCS4",
+		[IWL_RATE_48M_INDEX] = "48M|MCS5",
+		[IWL_RATE_54M_INDEX] = "54M|MCS6",
+		[IWL_RATE_MCS_7_INDEX] = "MCS7",
+		[IWL_RATE_MCS_8_INDEX] = "MCS8",
+		[IWL_RATE_MCS_9_INDEX] = "MCS9",
+	};
+
+	char *buff, *pos, *endpos;
+	int col, rate;
+	ssize_t ret;
+	struct iwl_lq_sta *lq_sta = file->private_data;
+	struct rs_rate_stats *stats;
+	static const size_t bufsz = 1024;
+
+	buff = kmalloc(bufsz, GFP_KERNEL);
+	if (!buff)
+		return -ENOMEM;
+
+	pos = buff;
+	endpos = pos + bufsz;
+
+	pos += scnprintf(pos, endpos - pos, "COLUMN,");
+	for (rate = 0; rate < IWL_RATE_COUNT; rate++)
+		pos += scnprintf(pos, endpos - pos, "%s,", rate_name[rate]);
+	pos += scnprintf(pos, endpos - pos, "\n");
+
+	for (col = 0; col < RS_COLUMN_COUNT; col++) {
+		pos += scnprintf(pos, endpos - pos,
+				 "%s,", column_name[col]);
+
+		for (rate = 0; rate < IWL_RATE_COUNT; rate++) {
+			stats = &(lq_sta->tx_stats[col][rate]);
+			pos += scnprintf(pos, endpos - pos,
+					 "%llu/%llu,",
+					 stats->success,
+					 stats->total);
+		}
+		pos += scnprintf(pos, endpos - pos, "\n");
+	}
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buff, pos - buff);
+	kfree(buff);
+	return ret;
+}
+
+static ssize_t rs_sta_dbgfs_drv_tx_stats_write(struct file *file,
+					       const char __user *user_buf,
+					       size_t count, loff_t *ppos)
+{
+	struct iwl_lq_sta *lq_sta = file->private_data;
+	memset(lq_sta->tx_stats, 0, sizeof(lq_sta->tx_stats));
+
+	return count;
+}
+
+static const struct file_operations rs_sta_dbgfs_drv_tx_stats_ops = {
+	.read = rs_sta_dbgfs_drv_tx_stats_read,
+	.write = rs_sta_dbgfs_drv_tx_stats_write,
+	.open = simple_open,
+	.llseek = default_llseek,
+};
+
 static void rs_add_debugfs(void *mvm, void *mvm_sta, struct dentry *dir)
 {
 	struct iwl_lq_sta *lq_sta = mvm_sta;
@@ -3083,6 +3176,9 @@ static void rs_add_debugfs(void *mvm, void *mvm_sta, struct dentry *dir)
 	lq_sta->rs_sta_dbgfs_stats_table_file =
 		debugfs_create_file("rate_stats_table", S_IRUSR, dir,
 				    lq_sta, &rs_sta_dbgfs_stats_table_ops);
+	lq_sta->rs_sta_dbgfs_drv_tx_stats_file =
+		debugfs_create_file("drv_tx_stats", S_IRUSR | S_IWUSR, dir,
+				    lq_sta, &rs_sta_dbgfs_drv_tx_stats_ops);
 	lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file =
 		debugfs_create_u8("tx_agg_tid_enable", S_IRUSR | S_IWUSR, dir,
 				  &lq_sta->tx_agg_tid_en);
@@ -3096,6 +3192,7 @@ static void rs_remove_debugfs(void *mvm, void *mvm_sta)
 	struct iwl_lq_sta *lq_sta = mvm_sta;
 	debugfs_remove(lq_sta->rs_sta_dbgfs_scale_table_file);
 	debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file);
+	debugfs_remove(lq_sta->rs_sta_dbgfs_drv_tx_stats_file);
 	debugfs_remove(lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file);
 	debugfs_remove(lq_sta->rs_sta_dbgfs_reduced_txp_file);
 }
drivers/net/wireless/iwlwifi/mvm/rs.h +10 -0
index fcc056d..958c99d 100644
@@ -272,9 +272,16 @@ enum rs_column {
 	RS_COLUMN_MIMO2_SGI,
 
 	RS_COLUMN_LAST = RS_COLUMN_MIMO2_SGI,
+	RS_COLUMN_COUNT = RS_COLUMN_LAST + 1,
 	RS_COLUMN_INVALID,
 };
 
+/* Packet stats per rate */
+struct rs_rate_stats {
+	u64 success;
+	u64 total;
+};
+
 /**
  * struct iwl_scale_tbl_info -- tx params and success history for all rates
  *
@@ -322,6 +329,8 @@ struct iwl_lq_sta {
 	bool is_vht;
 	enum ieee80211_band band;
 
+	struct rs_rate_stats tx_stats[RS_COLUMN_COUNT][IWL_RATE_COUNT];
+
 	/* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */
 	u16 active_legacy_rate;
 	u16 active_siso_rate;
@@ -335,6 +344,7 @@ struct iwl_lq_sta {
 #ifdef CONFIG_MAC80211_DEBUGFS
 	struct dentry *rs_sta_dbgfs_scale_table_file;
 	struct dentry *rs_sta_dbgfs_stats_table_file;
+	struct dentry *rs_sta_dbgfs_drv_tx_stats_file;
 	struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file;
 	struct dentry *rs_sta_dbgfs_reduced_txp_file;
 	u32 dbg_fixed_rate;
Signature · 1 line
1.8.3.2
#25 lore raw

PATCH 25/47 iwlwifi: mvm: replace BUG_ON by WARN_ON in scan.c

In reply to Emmanuel Grumbach

From: Emmanuel Grumbach <[email protected]>

While the scan_cmd should really be allocated in init (and we do fail init in case the allocation failed), it doesn't mean we should lock up the machine if something really bad happened.

---
 drivers/net/wireless/iwlwifi/mvm/scan.c   | 5 ++++-
 drivers/net/wireless/iwlwifi/pcie/trans.c | 3 +++
 2 files changed, 7 insertions(+), 1 deletion(-)
drivers/net/wireless/iwlwifi/mvm/scan.c +4 -1
index c91dc84..9e760d0 100644
@@ -348,7 +348,10 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm,
 	struct iwl_mvm_scan_params params = {};
 
 	lockdep_assert_held(&mvm->mutex);
-	BUG_ON(mvm->scan_cmd == NULL);
+
+	/* we should have failed registration if scan_cmd was NULL */
+	if (WARN_ON(mvm->scan_cmd == NULL))
+		return -ENOMEM;
 
 	IWL_DEBUG_SCAN(mvm, "Handling mac80211 scan request\n");
 	mvm->scan_status = IWL_MVM_SCAN_OS;
drivers/net/wireless/iwlwifi/pcie/trans.c +3 -0
index 4845d50..f98ef1e 100644
@@ -1278,6 +1278,8 @@ static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, u32 txq_bm)
 			continue;
 		if (!(BIT(cnt) & txq_bm))
 			continue;
+
+		IWL_DEBUG_TX_QUEUES(trans, "Emptying queue %d...\n", cnt);
 		txq = &trans_pcie->txq[cnt];
 		q = &txq->q;
 		wr_ptr = ACCESS_ONCE(q->write_ptr);
@@ -1300,6 +1302,7 @@ static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, u32 txq_bm)
 			ret = -ETIMEDOUT;
 			break;
 		}
+		IWL_DEBUG_TX_QUEUES(trans, "Queue %d is now empty.\n", cnt);
 	}
 
 	if (!ret)
Signature · 1 line
1.8.3.2
#26 lore raw

PATCH 26/47 iwlwifi: mvm: deprecate -7 firmware

In reply to Emmanuel Grumbach

From: Emmanuel Grumbach <[email protected]>

This firmware is not supported any more.
A few code paths specific to old firmware can be removed. We can now assume that a few TLV flags are always set since we won't load firmware that didn't support the corresponding features. This will be done in a separate patch.

---
 drivers/net/wireless/iwlwifi/iwl-7000.c     | 4 ++--
 drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | 5 +----
 drivers/net/wireless/iwlwifi/mvm/mac80211.c | 7 ++-----
 drivers/net/wireless/iwlwifi/mvm/sf.c       | 3 ---
 4 files changed, 5 insertions(+), 14 deletions(-)
drivers/net/wireless/iwlwifi/iwl-7000.c +2 -2
index c42d80c..3ab21ef 100644
@@ -75,8 +75,8 @@
 #define IWL3160_UCODE_API_OK	8
 
 /* Lowest firmware API version supported */
-#define IWL7260_UCODE_API_MIN	7
-#define IWL3160_UCODE_API_MIN	7
+#define IWL7260_UCODE_API_MIN	8
+#define IWL3160_UCODE_API_MIN	8
 
 /* NVM versions */
 #define IWL7260_NVM_VERSION		0x0a1d
drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +1 -4
index 9ccec10..7110ec2 100644
@@ -667,12 +667,9 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
 	if (vif->bss_conf.qos)
 		cmd->qos_flags |= cpu_to_le32(MAC_QOS_FLG_UPDATE_EDCA);
 
-	/* Don't use cts to self as the fw doesn't support it currently. */
 	if (vif->bss_conf.use_cts_prot) {
 		cmd->protection_flags |= cpu_to_le32(MAC_PROT_FLG_TGG_PROTECT);
-		if (IWL_UCODE_API(mvm->fw->ucode_ver) >= 8)
-			cmd->protection_flags |=
-				cpu_to_le32(MAC_PROT_FLG_SELF_CTS_EN);
+		cmd->protection_flags |= cpu_to_le32(MAC_PROT_FLG_SELF_CTS_EN);
 	}
 	IWL_DEBUG_RATE(mvm, "use_cts_prot %d, ht_operation_mode %d\n",
 		       vif->bss_conf.use_cts_prot,
drivers/net/wireless/iwlwifi/mvm/mac80211.c +2 -5
index 01b4228..39e4ffe 100644
@@ -309,11 +309,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
 		BIT(NL80211_IFTYPE_P2P_CLIENT) |
 		BIT(NL80211_IFTYPE_AP) |
 		BIT(NL80211_IFTYPE_P2P_GO) |
-		BIT(NL80211_IFTYPE_P2P_DEVICE);
-
-	/* IBSS has bugs in older versions */
-	if (IWL_UCODE_API(mvm->fw->ucode_ver) >= 8)
-		hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);
+		BIT(NL80211_IFTYPE_P2P_DEVICE) |
+		BIT(NL80211_IFTYPE_ADHOC);
 
 	hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
 	hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG |
drivers/net/wireless/iwlwifi/mvm/sf.c +0 -3
index 8401627..aa819e6 100644
@@ -237,9 +237,6 @@ int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *changed_vif,
 		.sta_vif_ap_sta_id = IWL_MVM_STATION_COUNT,
 	};
 
-	if (IWL_UCODE_API(mvm->fw->ucode_ver) < 8)
-		return 0;
-
 	/*
 	 * Ignore the call if we are in HW Restart flow, or if the handled
 	 * vif is a p2p device.
Signature · 1 line
1.8.3.2
#27 lore raw

PATCH 27/47 iwlwifi: mvm: Change scan fragmentation condition

In reply to Emmanuel Grumbach

From: Alexander Bondar <[email protected]>

Do not allow passive scan fragmentation in case of P2P discovery scan. This is to avoid negative impact on P2P discoverability. Do some re-factoring to make existing code more clear.

---
 drivers/net/wireless/iwlwifi/mvm/scan.c | 54 ++++++++++++++++++---------------
 1 file changed, 30 insertions(+), 24 deletions(-)
drivers/net/wireless/iwlwifi/mvm/scan.c +30 -24
index 9e760d0..5481e09 100644
@@ -272,11 +272,16 @@ static void iwl_mvm_scan_calc_params(struct iwl_mvm *mvm,
 {
 	bool global_bound = false;
 	enum ieee80211_band band;
+	u8 frag_passive_dwell = 0;
 
 	ieee80211_iterate_active_interfaces_atomic(mvm->hw,
 					    IEEE80211_IFACE_ITER_NORMAL,
 					    iwl_mvm_scan_condition_iterator,
 					    &global_bound);
+
+	if (!global_bound)
+		goto not_bound;
+
 	/*
 	 * Under low latency traffic passive scan is fragmented meaning
 	 * that dwell on a particular channel will be fragmented. Each fragment
@@ -288,37 +293,38 @@ static void iwl_mvm_scan_calc_params(struct iwl_mvm *mvm,
 	 * 70ms, so for active scanning operating channel will be left for 70ms
 	 * while for passive still for 20ms (fragment dwell).
 	 */
-	if (global_bound) {
-		if (!iwl_mvm_low_latency(mvm)) {
-			params->suspend_time = ieee80211_tu_to_usec(100);
-			params->max_out_time = ieee80211_tu_to_usec(600);
-		} else {
-			params->suspend_time = ieee80211_tu_to_usec(105);
-			/* P2P doesn't support fragmented passive scan, so
-			 * configure max_out_time to be at least longest dwell
-			 * time for passive scan.
-			 */
-			if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p) {
-				params->max_out_time = ieee80211_tu_to_usec(70);
-				params->passive_fragmented = true;
-			} else {
-				u32 passive_dwell;
 
-				/*
-				 * Use band G so that passive channel dwell time
-				 * will be assigned with maximum value.
-				 */
-				band = IEEE80211_BAND_2GHZ;
-				passive_dwell = iwl_mvm_get_passive_dwell(band);
-				params->max_out_time =
+	if (iwl_mvm_low_latency(mvm)) {
+		params->suspend_time = ieee80211_tu_to_usec(105);
+		params->max_out_time = ieee80211_tu_to_usec(70);
+		frag_passive_dwell = 20;
+	} else {
+		params->suspend_time = ieee80211_tu_to_usec(100);
+		params->max_out_time = ieee80211_tu_to_usec(600);
+	}
+
+	if (frag_passive_dwell) {
+		/*
+		* P2P device scan should not be fragmented to avoid negative
+		* impact on P2P device discovery. Configure max_out_time to be
+		* equal to dwell time on passive channel. Take a longest
+		* possible value, one that corresponds to 2GHz band
+		*/
+		if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
+			u32 passive_dwell =
+				iwl_mvm_get_passive_dwell(IEEE80211_BAND_2GHZ);
+			params->max_out_time =
 					ieee80211_tu_to_usec(passive_dwell);
-			}
+		} else {
+			params->passive_fragmented = true;
 		}
 	}
 
+not_bound:
+
 	for (band = IEEE80211_BAND_2GHZ; band < IEEE80211_NUM_BANDS; band++) {
 		if (params->passive_fragmented)
-			params->dwell[band].passive = 20;
+			params->dwell[band].passive = frag_passive_dwell;
 		else
 			params->dwell[band].passive =
 				iwl_mvm_get_passive_dwell(band);
Signature · 1 line
1.8.3.2
#28 lore raw

PATCH 28/47 iwlwifi: mvm: Fix scan parameters units

In reply to Emmanuel Grumbach

From: Alexander Bondar <[email protected]>

Change max_out_time and suspend_time units from usec to TUs as expected by FW API.

---
 drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h |  8 ++++----
 drivers/net/wireless/iwlwifi/mvm/scan.c        | 11 +++++------
 2 files changed, 9 insertions(+), 10 deletions(-)
drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h +4 -4
index 02856e0..0373f44 100644
@@ -187,9 +187,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_*
@@ -387,8 +387,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 +5 -6
index 5481e09..ea17745 100644
@@ -295,12 +295,12 @@ static void iwl_mvm_scan_calc_params(struct iwl_mvm *mvm,
 	 */
 
 	if (iwl_mvm_low_latency(mvm)) {
-		params->suspend_time = ieee80211_tu_to_usec(105);
-		params->max_out_time = ieee80211_tu_to_usec(70);
+		params->suspend_time = 105;
+		params->max_out_time = 70;
 		frag_passive_dwell = 20;
 	} else {
-		params->suspend_time = ieee80211_tu_to_usec(100);
-		params->max_out_time = ieee80211_tu_to_usec(600);
+		params->suspend_time = 100;
+		params->max_out_time = 600;
 	}
 
 	if (frag_passive_dwell) {
@@ -313,8 +313,7 @@ static void iwl_mvm_scan_calc_params(struct iwl_mvm *mvm,
 		if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
 			u32 passive_dwell =
 				iwl_mvm_get_passive_dwell(IEEE80211_BAND_2GHZ);
-			params->max_out_time =
-					ieee80211_tu_to_usec(passive_dwell);
+			params->max_out_time = passive_dwell;
 		} else {
 			params->passive_fragmented = true;
 		}
Signature · 1 line
1.8.3.2
#29 lore raw

PATCH 29/47 iwlwifi: remove IWL_UCODE_TLV_FLAGS_NEWBT_COEX TLV flag

In reply to Emmanuel Grumbach

From: Emmanuel Grumbach <[email protected]>

All the supported firmwares have this flag set.

---
 drivers/net/wireless/iwlwifi/iwl-fw.h   | 1 -
 drivers/net/wireless/iwlwifi/mvm/coex.c | 9 ---------
 2 files changed, 10 deletions(-)
drivers/net/wireless/iwlwifi/iwl-fw.h +0 -1
index f7ea9c0..9cb4ad9 100644
@@ -107,7 +107,6 @@ enum iwl_ucode_tlv_flag {
 	IWL_UCODE_TLV_FLAGS_MFP			= BIT(2),
 	IWL_UCODE_TLV_FLAGS_P2P			= BIT(3),
 	IWL_UCODE_TLV_FLAGS_DW_BC_TABLE		= BIT(4),
-	IWL_UCODE_TLV_FLAGS_NEWBT_COEX		= BIT(5),
 	IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT	= BIT(6),
 	IWL_UCODE_TLV_FLAGS_SHORT_BL		= BIT(7),
 	IWL_UCODE_TLV_FLAGS_RX_ENERGY_API	= BIT(8),
drivers/net/wireless/iwlwifi/mvm/coex.c +0 -9
index 4bd47c9..92a005c 100644
@@ -106,9 +106,6 @@ static const u8 iwl_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = {
 
 int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm)
 {
-	if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWBT_COEX))
-		return 0;
-
 	return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_PRIO_TABLE, CMD_SYNC,
 				    sizeof(struct iwl_bt_coex_prio_tbl_cmd),
 				    &iwl_bt_prio_tbl);
@@ -573,9 +570,6 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
 	int ret;
 	u32 flags;
 
-	if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWBT_COEX))
-		return 0;
-
 	bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL);
 	if (!bt_cmd)
 		return -ENOMEM;
@@ -1260,9 +1254,6 @@ u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr,
 
 void iwl_mvm_bt_coex_vif_change(struct iwl_mvm *mvm)
 {
-	if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWBT_COEX))
-		return;
-
 	iwl_mvm_bt_coex_notif_handle(mvm);
 }
 
Signature · 1 line
1.8.3.2
#30 lore raw

PATCH 30/47 iwlwifi: remove IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT flag

In reply to Emmanuel Grumbach

From: Emmanuel Grumbach <[email protected]>

All the supported firmwares have this flag set.

---
 drivers/net/wireless/iwlwifi/iwl-fw.h          |  1 -
 drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c |  3 +--
 drivers/net/wireless/iwlwifi/mvm/fw.c          |  6 ------
 drivers/net/wireless/iwlwifi/mvm/mvm.h         |  2 --
 drivers/net/wireless/iwlwifi/mvm/power.c       | 20 --------------------
 5 files changed, 1 insertion(+), 31 deletions(-)
drivers/net/wireless/iwlwifi/iwl-fw.h +0 -1
index 9cb4ad9..c9a3ca6 100644
@@ -107,7 +107,6 @@ enum iwl_ucode_tlv_flag {
 	IWL_UCODE_TLV_FLAGS_MFP			= BIT(2),
 	IWL_UCODE_TLV_FLAGS_P2P			= BIT(3),
 	IWL_UCODE_TLV_FLAGS_DW_BC_TABLE		= BIT(4),
-	IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT	= BIT(6),
 	IWL_UCODE_TLV_FLAGS_SHORT_BL		= BIT(7),
 	IWL_UCODE_TLV_FLAGS_RX_ENERGY_API	= BIT(8),
 	IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2	= BIT(9),
drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c +1 -2
index 9b59e1d..d372ca6 100644
@@ -592,8 +592,7 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
 		return;
 	}
 
-	if ((mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT) &&
-	    iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM &&
+	if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM &&
 	    ((vif->type == NL80211_IFTYPE_STATION && !vif->p2p) ||
 	     (vif->type == NL80211_IFTYPE_STATION && vif->p2p &&
 	      mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM)))
drivers/net/wireless/iwlwifi/mvm/fw.c +0 -6
index 7ce2006..e7a2639 100644
@@ -468,12 +468,6 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
 	/* Initialize tx backoffs to the minimal possible */
 	iwl_mvm_tt_tx_backoff(mvm, 0);
 
-	if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT)) {
-		ret = iwl_power_legacy_set_cam_mode(mvm);
-		if (ret)
-			goto error;
-	}
-
 	ret = iwl_mvm_power_update_device(mvm);
 	if (ret)
 		goto error;
drivers/net/wireless/iwlwifi/mvm/mvm.h +0 -2
index 9f2ecf2..a0fb7b1 100644
@@ -877,8 +877,6 @@ void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm,
 int rs_pretty_print_rate(char *buf, const u32 rate);
 
 /* power management */
-int iwl_power_legacy_set_cam_mode(struct iwl_mvm *mvm);
-
 int iwl_mvm_power_update_device(struct iwl_mvm *mvm);
 int iwl_mvm_power_update_mac(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
 int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
drivers/net/wireless/iwlwifi/mvm/power.c +0 -20
index a1ce8d2..ab92a63 100644
@@ -437,9 +437,6 @@ int iwl_mvm_power_update_device(struct iwl_mvm *mvm)
 		.flags = cpu_to_le16(DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK),
 	};
 
-	if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT))
-		return 0;
-
 	if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD))
 		return 0;
 
@@ -646,9 +643,6 @@ int iwl_mvm_power_update_mac(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
 
 	lockdep_assert_held(&mvm->mutex);
 
-	if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT))
-		return 0;
-
 	iwl_mvm_power_set_pm(mvm, &vifs);
 
 	/* disable PS if CAM */
@@ -698,10 +692,6 @@ int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm,
 	struct iwl_mac_power_cmd cmd = {};
 	int pos = 0;
 
-	if (WARN_ON(!(mvm->fw->ucode_capa.flags &
-		      IWL_UCODE_TLV_FLAGS_PM_CMD_SUPPORT)))
-		return 0;
-
 	mutex_lock(&mvm->mutex);
 	memcpy(&cmd, &mvmvif->mac_pwr_cmd, sizeof(cmd));
 	mutex_unlock(&mvm->mutex);
@@ -941,13 +931,3 @@ int iwl_mvm_update_beacon_filter(struct iwl_mvm *mvm,
 
 	return iwl_mvm_enable_beacon_filter(mvm, vif, flags);
 }
-
-int iwl_power_legacy_set_cam_mode(struct iwl_mvm *mvm)
-{
-	struct iwl_powertable_cmd cmd = {
-		.keep_alive_seconds = POWER_KEEP_ALIVE_PERIOD_SEC,
-	};
-
-	return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_SYNC,
-				    sizeof(cmd), &cmd);
-}
Signature · 1 line
1.8.3.2
#31 lore raw

PATCH 31/47 iwlwifi: remove IWL_UCODE_TLV_FLAGS_RX_ENERGY_API flag

In reply to Emmanuel Grumbach

From: Emmanuel Grumbach <[email protected]>

All the supported firmwares have this flag set.

---
 drivers/net/wireless/iwlwifi/iwl-fw.h |  2 --
 drivers/net/wireless/iwlwifi/mvm/rx.c | 40 +----------------------------------
 2 files changed, 1 insertion(+), 41 deletions(-)
drivers/net/wireless/iwlwifi/iwl-fw.h +0 -2
index c9a3ca6..7d5e7ba 100644
@@ -77,7 +77,6 @@
  * @IWL_UCODE_TLV_FLAGS_UAPSD: This uCode image supports uAPSD
  * @IWL_UCODE_TLV_FLAGS_SHORT_BL: 16 entries of black list instead of 64 in scan
  *	offload profile config command.
- * @IWL_UCODE_TLV_FLAGS_RX_ENERGY_API: supports rx signal strength api
  * @IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2: using the new time event API.
  * @IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS: D3 image supports up to six
  *	(rather than two) IPv6 addresses
@@ -108,7 +107,6 @@ enum iwl_ucode_tlv_flag {
 	IWL_UCODE_TLV_FLAGS_P2P			= BIT(3),
 	IWL_UCODE_TLV_FLAGS_DW_BC_TABLE		= BIT(4),
 	IWL_UCODE_TLV_FLAGS_SHORT_BL		= BIT(7),
-	IWL_UCODE_TLV_FLAGS_RX_ENERGY_API	= BIT(8),
 	IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2	= BIT(9),
 	IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS	= BIT(10),
 	IWL_UCODE_TLV_FLAGS_BF_UPDATED		= BIT(11),
drivers/net/wireless/iwlwifi/mvm/rx.c +1 -39
index 40fd5dc..cf72769 100644
@@ -132,41 +132,6 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
 	ieee80211_rx(mvm->hw, skb);
 }
 
-static void iwl_mvm_calc_rssi(struct iwl_mvm *mvm,
-			      struct iwl_rx_phy_info *phy_info,
-			      struct ieee80211_rx_status *rx_status)
-{
-	int rssi_a, rssi_b, rssi_a_dbm, rssi_b_dbm, max_rssi_dbm;
-	u32 agc_a, agc_b;
-	u32 val;
-
-	val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_AGC_IDX]);
-	agc_a = (val & IWL_OFDM_AGC_A_MSK) >> IWL_OFDM_AGC_A_POS;
-	agc_b = (val & IWL_OFDM_AGC_B_MSK) >> IWL_OFDM_AGC_B_POS;
-
-	val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_RSSI_AB_IDX]);
-	rssi_a = (val & IWL_OFDM_RSSI_INBAND_A_MSK) >> IWL_OFDM_RSSI_A_POS;
-	rssi_b = (val & IWL_OFDM_RSSI_INBAND_B_MSK) >> IWL_OFDM_RSSI_B_POS;
-
-	/*
-	 * dBm = rssi dB - agc dB - constant.
-	 * Higher AGC (higher radio gain) means lower signal.
-	 */
-	rssi_a_dbm = rssi_a - IWL_RSSI_OFFSET - agc_a;
-	rssi_b_dbm = rssi_b - IWL_RSSI_OFFSET - agc_b;
-	max_rssi_dbm = max_t(int, rssi_a_dbm, rssi_b_dbm);
-
-	IWL_DEBUG_STATS(mvm, "Rssi In A %d B %d Max %d AGCA %d AGCB %d\n",
-			rssi_a_dbm, rssi_b_dbm, max_rssi_dbm, agc_a, agc_b);
-
-	rx_status->signal = max_rssi_dbm;
-	rx_status->chains = (le16_to_cpu(phy_info->phy_flags) &
-				RX_RES_PHY_FLAGS_ANTENNA)
-					>> RX_RES_PHY_FLAGS_ANTENNA_POS;
-	rx_status->chain_signal[0] = rssi_a_dbm;
-	rx_status->chain_signal[1] = rssi_b_dbm;
-}
-
 /*
  * iwl_mvm_get_signal_strength - use new rx PHY INFO API
  * values are reported by the fw as positive values - need to negate
@@ -336,10 +301,7 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
 	 */
 	/*rx_status.flag |= RX_FLAG_MACTIME_MPDU;*/
 
-	if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_RX_ENERGY_API)
-		iwl_mvm_get_signal_strength(mvm, phy_info, &rx_status);
-	else
-		iwl_mvm_calc_rssi(mvm, phy_info, &rx_status);
+	iwl_mvm_get_signal_strength(mvm, phy_info, &rx_status);
 
 	IWL_DEBUG_STATS_LIMIT(mvm, "Rssi %d, TSF %llu\n", rx_status.signal,
 			      (unsigned long long)rx_status.mactime);
Signature · 1 line
1.8.3.2
#32 lore raw

PATCH 32/47 iwlwifi: remove IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2 flag

In reply to Emmanuel Grumbach

From: Emmanuel Grumbach <[email protected]>

All the supported firmwares have this flag set.

---
 drivers/net/wireless/iwlwifi/iwl-fw.h         |  2 -
 drivers/net/wireless/iwlwifi/mvm/fw-api.h     | 53 ++------------------
 drivers/net/wireless/iwlwifi/mvm/time-event.c | 71 +++------------------------
 3 files changed, 12 insertions(+), 114 deletions(-)
drivers/net/wireless/iwlwifi/iwl-fw.h +0 -2
index 7d5e7ba..04eac6e 100644
@@ -77,7 +77,6 @@
  * @IWL_UCODE_TLV_FLAGS_UAPSD: This uCode image supports uAPSD
  * @IWL_UCODE_TLV_FLAGS_SHORT_BL: 16 entries of black list instead of 64 in scan
  *	offload profile config command.
- * @IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2: using the new time event API.
  * @IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS: D3 image supports up to six
  *	(rather than two) IPv6 addresses
  * @IWL_UCODE_TLV_FLAGS_BF_UPDATED: new beacon filtering API
@@ -107,7 +106,6 @@ enum iwl_ucode_tlv_flag {
 	IWL_UCODE_TLV_FLAGS_P2P			= BIT(3),
 	IWL_UCODE_TLV_FLAGS_DW_BC_TABLE		= BIT(4),
 	IWL_UCODE_TLV_FLAGS_SHORT_BL		= BIT(7),
-	IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2	= BIT(9),
 	IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS	= BIT(10),
 	IWL_UCODE_TLV_FLAGS_BF_UPDATED		= BIT(11),
 	IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID	= BIT(12),
drivers/net/wireless/iwlwifi/mvm/fw-api.h +4 -49

77 lines not on this page · raw message

drivers/net/wireless/iwlwifi/mvm/time-event.c +8 -63

110 lines not on this page · raw message

Signature · 1 line
1.8.3.2
#33 lore raw

PATCH 33/47 iwlwifi: remove IWL_UCODE_TLV_FLAGS_BF_UPDATED flag

In reply to Emmanuel Grumbach

From: Emmanuel Grumbach <[email protected]>

All the supported firmwares have this flag set.

---
 drivers/net/wireless/iwlwifi/iwl-fw.h       | 2 --
 drivers/net/wireless/iwlwifi/mvm/mac80211.c | 3 +--
 drivers/net/wireless/iwlwifi/mvm/power.c    | 3 +--
 3 files changed, 2 insertions(+), 6 deletions(-)
drivers/net/wireless/iwlwifi/iwl-fw.h +0 -2
index 04eac6e..f87ab69 100644
@@ -79,7 +79,6 @@
  *	offload profile config command.
  * @IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS: D3 image supports up to six
  *	(rather than two) IPv6 addresses
- * @IWL_UCODE_TLV_FLAGS_BF_UPDATED: new beacon filtering API
  * @IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID: not sending a probe with the SSID element
  *	from the probe request template.
  * @IWL_UCODE_TLV_FLAGS_D3_CONTINUITY_API: modified D3 API to allow keeping
@@ -107,7 +106,6 @@ enum iwl_ucode_tlv_flag {
 	IWL_UCODE_TLV_FLAGS_DW_BC_TABLE		= BIT(4),
 	IWL_UCODE_TLV_FLAGS_SHORT_BL		= BIT(7),
 	IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS	= BIT(10),
-	IWL_UCODE_TLV_FLAGS_BF_UPDATED		= BIT(11),
 	IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID	= BIT(12),
 	IWL_UCODE_TLV_FLAGS_D3_CONTINUITY_API	= BIT(14),
 	IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL	= BIT(15),
drivers/net/wireless/iwlwifi/mvm/mac80211.c +1 -2
index 39e4ffe..c455722 100644
@@ -824,8 +824,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
 		goto out_remove_mac;
 
 	if (!mvm->bf_allowed_vif &&
-	    vif->type == NL80211_IFTYPE_STATION && !vif->p2p &&
-	    mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BF_UPDATED){
+	    vif->type == NL80211_IFTYPE_STATION && !vif->p2p) {
 		mvm->bf_allowed_vif = mvmvif;
 		vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER |
 				     IEEE80211_VIF_SUPPORTS_CQM_RSSI;
drivers/net/wireless/iwlwifi/mvm/power.c +1 -2
index ab92a63..dba760f 100644
@@ -843,8 +843,7 @@ int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 	int ret;
 
-	if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BF_UPDATED) ||
-	    vif->type != NL80211_IFTYPE_STATION || vif->p2p)
+	if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
 		return 0;
 
 	ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd, flags);
Signature · 1 line
1.8.3.2
#34 lore raw

PATCH 34/47 iwlwifi: remove IWL_UCODE_TLV_FLAGS_D3_CONTINUITY_API flag

In reply to Emmanuel Grumbach

From: Emmanuel Grumbach <[email protected]>

All the supported firmwares have this flag set.

---
 drivers/net/wireless/iwlwifi/iwl-fw.h        |  3 --
 drivers/net/wireless/iwlwifi/mvm/d3.c        | 72 +++++++++-------------------
 drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h | 17 +------
 drivers/net/wireless/iwlwifi/mvm/ops.c       |  2 +-
 4 files changed, 24 insertions(+), 70 deletions(-)
drivers/net/wireless/iwlwifi/iwl-fw.h +0 -3
index f87ab69..fbfdba7 100644
@@ -81,8 +81,6 @@
  *	(rather than two) IPv6 addresses
  * @IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID: not sending a probe with the SSID element
  *	from the probe request template.
- * @IWL_UCODE_TLV_FLAGS_D3_CONTINUITY_API: modified D3 API to allow keeping
- *	connection when going back to D0
  * @IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL: new NS offload (small version)
  * @IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE: new NS offload (large version)
  * @IWL_UCODE_TLV_FLAGS_SCHED_SCAN: this uCode image supports scheduled scan.
@@ -107,7 +105,6 @@ enum iwl_ucode_tlv_flag {
 	IWL_UCODE_TLV_FLAGS_SHORT_BL		= BIT(7),
 	IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS	= BIT(10),
 	IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID	= BIT(12),
-	IWL_UCODE_TLV_FLAGS_D3_CONTINUITY_API	= BIT(14),
 	IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL	= BIT(15),
 	IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE	= BIT(16),
 	IWL_UCODE_TLV_FLAGS_SCHED_SCAN		= BIT(17),
drivers/net/wireless/iwlwifi/mvm/d3.c +22 -50

132 lines not on this page · raw message

drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h +1 -16
index 10fcc1a..13696fe 100644
@@ -345,21 +345,6 @@ enum iwl_wowlan_wakeup_reason {
 	IWL_WOWLAN_WAKEUP_BY_REM_WAKE_WAKEUP_PACKET		= BIT(12),
 }; /* WOWLAN_WAKE_UP_REASON_API_E_VER_2 */
 
-struct iwl_wowlan_status_v4 {
-	__le64 replay_ctr;
-	__le16 pattern_number;
-	__le16 non_qos_seq_ctr;
-	__le16 qos_seq_ctr[8];
-	__le32 wakeup_reasons;
-	__le32 rekey_status;
-	__le32 num_of_gtk_rekeys;
-	__le32 transmitted_ndps;
-	__le32 received_beacons;
-	__le32 wake_packet_length;
-	__le32 wake_packet_bufsize;
-	u8 wake_packet[]; /* can be truncated from _length to _bufsize */
-} __packed; /* WOWLAN_STATUSES_API_S_VER_4 */
-
 struct iwl_wowlan_gtk_status {
 	u8 key_index;
 	u8 reserved[3];
@@ -368,7 +353,7 @@ struct iwl_wowlan_gtk_status {
 	struct iwl_wowlan_rsc_tsc_params_cmd rsc;
 } __packed;
 
-struct iwl_wowlan_status_v6 {
+struct iwl_wowlan_status {
 	struct iwl_wowlan_gtk_status gtk;
 	__le64 replay_ctr;
 	__le16 pattern_number;
drivers/net/wireless/iwlwifi/mvm/ops.c +1 -1
index 7cb401b..fd53128 100644
@@ -1144,7 +1144,7 @@ static void iwl_mvm_d0i3_exit_work(struct work_struct *wk)
 		.id = WOWLAN_GET_STATUSES,
 		.flags = CMD_SYNC | CMD_HIGH_PRIO | CMD_WANT_SKB,
 	};
-	struct iwl_wowlan_status_v6 *status;
+	struct iwl_wowlan_status *status;
 	int ret;
 	u32 disconnection_reasons, wakeup_reasons;
 	__le16 *qos_seq = NULL;
Signature · 1 line
1.8.3.2
#35 lore raw

PATCH 35/47 iwlwifi: remove IWL_UCODE_TLV_FLAGS_SCHED_SCAN flag

In reply to Emmanuel Grumbach

From: Emmanuel Grumbach <[email protected]>

All the supported firmwares have this flag set.

---
 drivers/net/wireless/iwlwifi/iwl-fw.h       |  2 --
 drivers/net/wireless/iwlwifi/mvm/mac80211.c | 13 +++++--------
 2 files changed, 5 insertions(+), 10 deletions(-)
drivers/net/wireless/iwlwifi/iwl-fw.h +0 -2
index fbfdba7..90d69a2 100644
@@ -83,7 +83,6 @@
  *	from the probe request template.
  * @IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL: new NS offload (small version)
  * @IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE: new NS offload (large version)
- * @IWL_UCODE_TLV_FLAGS_SCHED_SCAN: this uCode image supports scheduled scan.
  * @IWL_UCODE_TLV_FLAGS_STA_KEY_CMD: new ADD_STA and ADD_STA_KEY command API
  * @IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD: support device wide power command
  *	containing CAM (Continuous Active Mode) indication.
@@ -107,7 +106,6 @@ enum iwl_ucode_tlv_flag {
 	IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID	= BIT(12),
 	IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL	= BIT(15),
 	IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE	= BIT(16),
-	IWL_UCODE_TLV_FLAGS_SCHED_SCAN		= BIT(17),
 	IWL_UCODE_TLV_FLAGS_STA_KEY_CMD		= BIT(19),
 	IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD	= BIT(20),
 	IWL_UCODE_TLV_FLAGS_P2P_PM		= BIT(21),
drivers/net/wireless/iwlwifi/mvm/mac80211.c +5 -8
index c455722..8312c03 100644
@@ -362,14 +362,11 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
 	else
 		hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
 
-	if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_SCHED_SCAN) {
-		hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
-		hw->wiphy->max_sched_scan_ssids = PROBE_OPTION_MAX;
-		hw->wiphy->max_match_sets = IWL_SCAN_MAX_PROFILES;
-		/* we create the 802.11 header and zero length SSID IE. */
-		hw->wiphy->max_sched_scan_ie_len =
-					SCAN_OFFLOAD_PROBE_REQ_SIZE - 24 - 2;
-	}
+	hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
+	hw->wiphy->max_sched_scan_ssids = PROBE_OPTION_MAX;
+	hw->wiphy->max_match_sets = IWL_SCAN_MAX_PROFILES;
+	/* we create the 802.11 header and zero length SSID IE. */
+	hw->wiphy->max_sched_scan_ie_len = SCAN_OFFLOAD_PROBE_REQ_SIZE - 24 - 2;
 
 	hw->wiphy->features |= NL80211_FEATURE_P2P_GO_CTWIN |
 			       NL80211_FEATURE_P2P_GO_OPPPS;
Signature · 1 line
1.8.3.2
#36 lore raw

PATCH 36/47 iwlwifi: remove IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT flag

In reply to Emmanuel Grumbach

From: Emmanuel Grumbach <[email protected]>

All the supported firmwares have this flag set.

---
 drivers/net/wireless/iwlwifi/iwl-fw.h       |  1 -
 drivers/net/wireless/iwlwifi/mvm/mac80211.c | 11 ++++++-----
 2 files changed, 6 insertions(+), 6 deletions(-)
drivers/net/wireless/iwlwifi/iwl-fw.h +0 -1
index 90d69a2..ad65f68 100644
@@ -111,7 +111,6 @@ enum iwl_ucode_tlv_flag {
 	IWL_UCODE_TLV_FLAGS_P2P_PM		= BIT(21),
 	IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM	= BIT(22),
 	IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_SCM	= BIT(23),
-	IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT	= BIT(24),
 	IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD	= BIT(26),
 	IWL_UCODE_TLV_FLAGS_BCAST_FILTERING	= BIT(29),
 	IWL_UCODE_TLV_FLAGS_GO_UAPSD		= BIT(30),
drivers/net/wireless/iwlwifi/mvm/mac80211.c +6 -5
index 8312c03..dc9069b 100644
@@ -276,6 +276,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
 		    IEEE80211_HW_AMPDU_AGGREGATION |
 		    IEEE80211_HW_TIMING_BEACON_ONLY |
 		    IEEE80211_HW_CONNECTION_MONITOR |
+		    IEEE80211_HW_SUPPORTS_UAPSD |
 		    IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
 		    IEEE80211_HW_SUPPORTS_STATIC_SMPS;
 
@@ -285,6 +286,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
 				    IEEE80211_RADIOTAP_MCS_HAVE_STBC;
 	hw->radiotap_vht_details |= IEEE80211_RADIOTAP_VHT_KNOWN_STBC;
 	hw->rate_control_algorithm = "iwl-mvm-rs";
+	hw->uapsd_queues = IWL_UAPSD_AC_INFO;
+	hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP;
 
 	/*
 	 * Enable 11w if advertised by firmware and software crypto
@@ -295,11 +298,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
 	    !iwlwifi_mod_params.sw_crypto)
 		hw->flags |= IEEE80211_HW_MFP_CAPABLE;
 
-	if (0 && mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT) {
-		hw->flags |= IEEE80211_HW_SUPPORTS_UAPSD;
-		hw->uapsd_queues = IWL_UAPSD_AC_INFO;
-		hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP;
-	}
+	/* Disable uAPSD due to firmware issues */
+	if (true)
+		hw->flags &= ~IEEE80211_HW_SUPPORTS_UAPSD;
 
 	hw->sta_data_size = sizeof(struct iwl_mvm_sta);
 	hw->vif_data_size = sizeof(struct iwl_mvm_vif);
Signature · 1 line
1.8.3.2
#37 lore raw

PATCH 37/47 iwlwifi: remove IWL_UCODE_TLV_FLAGS_STA_KEY_CMD flag

In reply to Emmanuel Grumbach

From: Emmanuel Grumbach <[email protected]>

All the supported firmwares have this flag set.

---
 drivers/net/wireless/iwlwifi/iwl-fw.h         |   2 -
 drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h |  46 +-------
 drivers/net/wireless/iwlwifi/mvm/sta.c        | 161 +++++---------------------
 3 files changed, 32 insertions(+), 177 deletions(-)
drivers/net/wireless/iwlwifi/iwl-fw.h +0 -2
index ad65f68..77f02e1 100644
@@ -83,7 +83,6 @@
  *	from the probe request template.
  * @IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL: new NS offload (small version)
  * @IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE: new NS offload (large version)
- * @IWL_UCODE_TLV_FLAGS_STA_KEY_CMD: new ADD_STA and ADD_STA_KEY command API
  * @IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD: support device wide power command
  *	containing CAM (Continuous Active Mode) indication.
  * @IWL_UCODE_TLV_FLAGS_P2P_PM: P2P client supports PM as a stand alone MAC
@@ -106,7 +105,6 @@ enum iwl_ucode_tlv_flag {
 	IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID	= BIT(12),
 	IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL	= BIT(15),
 	IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE	= BIT(16),
-	IWL_UCODE_TLV_FLAGS_STA_KEY_CMD		= BIT(19),
 	IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD	= BIT(20),
 	IWL_UCODE_TLV_FLAGS_P2P_PM		= BIT(21),
 	IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM	= BIT(22),
drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h +5 -41

67 lines not on this page · raw message

drivers/net/wireless/iwlwifi/mvm/sta.c +27 -134

279 lines not on this page · raw message

Signature · 1 line
1.8.3.2
#38 lore raw

PATCH 38/47 iwlwifi: remove IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD flag

In reply to Emmanuel Grumbach

From: Emmanuel Grumbach <[email protected]>

All the supported firmwares have this flag set.

---
 drivers/net/wireless/iwlwifi/iwl-fw.h          |  3 ---
 drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c | 10 ----------
 drivers/net/wireless/iwlwifi/mvm/debugfs.c     |  5 ++---
 drivers/net/wireless/iwlwifi/mvm/mvm.h         |  2 --
 drivers/net/wireless/iwlwifi/mvm/power.c       | 13 -------------
 5 files changed, 2 insertions(+), 31 deletions(-)
drivers/net/wireless/iwlwifi/iwl-fw.h +0 -3
index 77f02e1..265d6f1 100644
@@ -83,8 +83,6 @@
  *	from the probe request template.
  * @IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL: new NS offload (small version)
  * @IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE: new NS offload (large version)
- * @IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD: support device wide power command
- *	containing CAM (Continuous Active Mode) indication.
  * @IWL_UCODE_TLV_FLAGS_P2P_PM: P2P client supports PM as a stand alone MAC
  * @IWL_UCODE_TLV_FLAGS_P2P_BSS_PS_DCM: support power save on BSS station and
  *	P2P client interfaces simultaneously if they are in different bindings.
@@ -105,7 +103,6 @@ enum iwl_ucode_tlv_flag {
 	IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID	= BIT(12),
 	IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL	= BIT(15),
 	IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE	= BIT(16),
-	IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD	= BIT(20),
 	IWL_UCODE_TLV_FLAGS_P2P_PM		= BIT(21),
 	IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM	= BIT(22),
 	IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_SCM	= BIT(23),
drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c +0 -10
index d372ca6..6047cfd 100644
@@ -103,10 +103,6 @@ static void iwl_dbgfs_update_pm(struct iwl_mvm *mvm,
 		IWL_DEBUG_POWER(mvm, "tx_data_timeout=%d\n", val);
 		dbgfs_pm->tx_data_timeout = val;
 		break;
-	case MVM_DEBUGFS_PM_DISABLE_POWER_OFF:
-		IWL_DEBUG_POWER(mvm, "disable_power_off=%d\n", val);
-		dbgfs_pm->disable_power_off = val;
-		break;
 	case MVM_DEBUGFS_PM_LPRX_ENA:
 		IWL_DEBUG_POWER(mvm, "lprx %s\n", val ? "enabled" : "disabled");
 		dbgfs_pm->lprx_ena = val;
@@ -154,12 +150,6 @@ static ssize_t iwl_dbgfs_pm_params_write(struct ieee80211_vif *vif, char *buf,
 		if (sscanf(buf + 16, "%d", &val) != 1)
 			return -EINVAL;
 		param = MVM_DEBUGFS_PM_TX_DATA_TIMEOUT;
-	} else if (!strncmp("disable_power_off=", buf, 18) &&
-		   !(mvm->fw->ucode_capa.flags &
-		     IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD)) {
-		if (sscanf(buf + 18, "%d", &val) != 1)
-			return -EINVAL;
-		param = MVM_DEBUGFS_PM_DISABLE_POWER_OFF;
 	} else if (!strncmp("lprx=", buf, 5)) {
 		if (sscanf(buf + 5, "%d", &val) != 1)
 			return -EINVAL;
drivers/net/wireless/iwlwifi/mvm/debugfs.c +2 -3
index d727572..db368cd 100644
@@ -1135,9 +1135,8 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
 	MVM_DEBUGFS_ADD_FILE(fw_error_dump, dbgfs_dir, S_IRUSR);
 	MVM_DEBUGFS_ADD_FILE(bt_notif, dbgfs_dir, S_IRUSR);
 	MVM_DEBUGFS_ADD_FILE(bt_cmd, dbgfs_dir, S_IRUSR);
-	if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD)
-		MVM_DEBUGFS_ADD_FILE(disable_power_off, mvm->debugfs_dir,
-				     S_IRUSR | S_IWUSR);
+	MVM_DEBUGFS_ADD_FILE(disable_power_off, mvm->debugfs_dir,
+			     S_IRUSR | S_IWUSR);
 	MVM_DEBUGFS_ADD_FILE(fw_rx_stats, mvm->debugfs_dir, S_IRUSR);
 	MVM_DEBUGFS_ADD_FILE(drv_rx_stats, mvm->debugfs_dir, S_IRUSR);
 	MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR);
drivers/net/wireless/iwlwifi/mvm/mvm.h +0 -2
index a0fb7b1..afca542 100644
@@ -164,7 +164,6 @@ enum iwl_dbgfs_pm_mask {
 	MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS = BIT(2),
 	MVM_DEBUGFS_PM_RX_DATA_TIMEOUT = BIT(3),
 	MVM_DEBUGFS_PM_TX_DATA_TIMEOUT = BIT(4),
-	MVM_DEBUGFS_PM_DISABLE_POWER_OFF = BIT(5),
 	MVM_DEBUGFS_PM_LPRX_ENA = BIT(6),
 	MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD = BIT(7),
 	MVM_DEBUGFS_PM_SNOOZE_ENABLE = BIT(8),
@@ -177,7 +176,6 @@ struct iwl_dbgfs_pm {
 	u32 tx_data_timeout;
 	bool skip_over_dtim;
 	u8 skip_dtim_periods;
-	bool disable_power_off;
 	bool lprx_ena;
 	u32 lprx_rssi_threshold;
 	bool snooze_ena;
drivers/net/wireless/iwlwifi/mvm/power.c +0 -13
index dba760f..2e6f477 100644
@@ -303,11 +303,6 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
 
 	cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
 
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-	if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_DISABLE_POWER_OFF &&
-	    mvmvif->dbgfs_pm.disable_power_off)
-		cmd->flags &= cpu_to_le16(~POWER_FLAGS_POWER_SAVE_ENA_MSK);
-#endif
 	if (!vif->bss_conf.ps || iwl_mvm_vif_low_latency(mvmvif) ||
 	    !mvmvif->pm_enabled)
 		return;
@@ -437,9 +432,6 @@ int iwl_mvm_power_update_device(struct iwl_mvm *mvm)
 		.flags = cpu_to_le16(DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK),
 	};
 
-	if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD))
-		return 0;
-
 	if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM)
 		mvm->ps_disabled = true;
 
@@ -696,11 +688,6 @@ int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm,
 	memcpy(&cmd, &mvmvif->mac_pwr_cmd, sizeof(cmd));
 	mutex_unlock(&mvm->mutex);
 
-	if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DEVICE_PS_CMD))
-		pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off = %d\n",
-				 (cmd.flags &
-				 cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK)) ?
-				 0 : 1);
 	pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n",
 			 iwlmvm_mod_params.power_scheme);
 	pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n",
Signature · 1 line
1.8.3.2
#39 lore raw

PATCH 39/47 iwlwifi: mvm: BT Coex - don't use comma operator

In reply to Emmanuel Grumbach

From: Emmanuel Grumbach <[email protected]>

This is really not needed. This is a remainder from a C99 initialiser.

---
 drivers/net/wireless/iwlwifi/mvm/coex.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/net/wireless/iwlwifi/mvm/coex.c +4 -4
index 92a005c..3755ad4 100644
@@ -576,10 +576,10 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
 	cmd.data[0] = bt_cmd;
 
 	bt_cmd->max_kill = 5;
-	bt_cmd->bt4_antenna_isolation_thr = BT_ANTENNA_COUPLING_THRESHOLD,
-	bt_cmd->bt4_antenna_isolation = iwlwifi_mod_params.ant_coupling,
-	bt_cmd->bt4_tx_tx_delta_freq_thr = 15,
-	bt_cmd->bt4_tx_rx_max_freq0 = 15,
+	bt_cmd->bt4_antenna_isolation_thr = BT_ANTENNA_COUPLING_THRESHOLD;
+	bt_cmd->bt4_antenna_isolation = iwlwifi_mod_params.ant_coupling;
+	bt_cmd->bt4_tx_tx_delta_freq_thr = 15;
+	bt_cmd->bt4_tx_rx_max_freq0 = 15;
 
 	flags = iwlwifi_mod_params.bt_coex_active ?
 			BT_COEX_NW : BT_COEX_DISABLE;
Signature · 1 line
1.8.3.2
#40 lore raw

PATCH 40/47 iwlwifi: mvm: BT Coex - minor API change

In reply to Emmanuel Grumbach

From: Emmanuel Grumbach <[email protected]>

The BT Coex API underwent a minor backward compatible API change.
We now need to set an invalid value in the override fields. While at it, add kerneldoc comments on the fields in the command.

---
 drivers/net/wireless/iwlwifi/mvm/coex.c        |  2 ++
 drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h | 38 +++++++++++++++-----------
 2 files changed, 24 insertions(+), 16 deletions(-)
drivers/net/wireless/iwlwifi/mvm/coex.c +2 -0
index 3755ad4..a1403d4 100644
@@ -580,6 +580,8 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
 	bt_cmd->bt4_antenna_isolation = iwlwifi_mod_params.ant_coupling;
 	bt_cmd->bt4_tx_tx_delta_freq_thr = 15;
 	bt_cmd->bt4_tx_rx_max_freq0 = 15;
+	bt_cmd->override_primary_lut = BT_COEX_INVALID_LUT;
+	bt_cmd->override_secondary_lut = BT_COEX_INVALID_LUT;
 
 	flags = iwlwifi_mod_params.bt_coex_active ?
 			BT_COEX_NW : BT_COEX_DISABLE;
drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h +22 -16
index 21877e5..5fe82c29 100644
@@ -141,7 +141,8 @@ enum iwl_bt_coex_lut_type {
 	BT_COEX_TX_DIS_LUT,
 
 	BT_COEX_MAX_LUT,
-};
+	BT_COEX_INVALID_LUT = 0xff,
+}; /* BT_COEX_DECISION_LUT_INDEX_API_E_VER_1 */
 
 #define BT_COEX_LUT_SIZE (12)
 #define BT_COEX_CORUN_LUT_SIZE (32)
@@ -154,19 +155,23 @@ enum iwl_bt_coex_lut_type {
  * @flags:&enum iwl_bt_coex_flags
  * @max_kill:
  * @bt_reduced_tx_power: enum %iwl_bt_reduced_tx_power
- * @bt4_antenna_isolation:
- * @bt4_antenna_isolation_thr:
- * @bt4_tx_tx_delta_freq_thr:
- * @bt4_tx_rx_max_freq0:
- * @bt_prio_boost:
+ * @override_primary_lut: enum %iwl_bt_coex_lut_type: BT_COEX_INVALID_LUT
+ *	should be set by default
+ * @override_secondary_lut: enum %iwl_bt_coex_lut_type: BT_COEX_INVALID_LUT
+ *	should be set by default
+ * @bt4_antenna_isolation: antenna isolation
+ * @bt4_antenna_isolation_thr: antenna threshold value
+ * @bt4_tx_tx_delta_freq_thr: TxTx delta frequency
+ * @bt4_tx_rx_max_freq0: TxRx max frequency
+ * @bt_prio_boost: BT priority boost registers
  * @wifi_tx_prio_boost: SW boost of wifi tx priority
  * @wifi_rx_prio_boost: SW boost of wifi rx priority
- * @kill_ack_msk:
- * @kill_cts_msk:
- * @decision_lut:
- * @bt4_multiprio_lut:
- * @bt4_corun_lut20:
- * @bt4_corun_lut40:
+ * @kill_ack_msk: kill ACK mask. 1 - Tx ACK, 0 - kill Tx of ACK.
+ * @kill_cts_msk: kill CTS mask. 1 - Tx CTS, 0 - kill Tx of CTS.
+ * @decision_lut: PTA decision LUT, per Prio-Ch
+ * @bt4_multiprio_lut: multi priority LUT configuration
+ * @bt4_corun_lut20: co-running 20 MHz LUT configuration
+ * @bt4_corun_lut40: co-running 40 MHz LUT configuration
  * @valid_bit_msk: enum %iwl_bt_coex_valid_bit_msk
  *
  * The structure is used for the BT_COEX command.
@@ -175,7 +180,8 @@ struct iwl_bt_coex_cmd {
 	__le32 flags;
 	u8 max_kill;
 	u8 bt_reduced_tx_power;
-	u8 reserved[2];
+	u8 override_primary_lut;
+	u8 override_secondary_lut;
 
 	u8 bt4_antenna_isolation;
 	u8 bt4_antenna_isolation_thr;
@@ -194,7 +200,7 @@ struct iwl_bt_coex_cmd {
 	__le32 bt4_corun_lut40[BT_COEX_CORUN_LUT_SIZE];
 
 	__le32 valid_bit_msk;
-} __packed; /* BT_COEX_CMD_API_S_VER_3 */
+} __packed; /* BT_COEX_CMD_API_S_VER_5 */
 
 /**
  * struct iwl_bt_coex_ci_cmd - bt coex channel inhibition command
@@ -282,7 +288,7 @@ enum iwl_bt_activity_grading {
 	BT_ON_NO_CONNECTION	= 1,
 	BT_LOW_TRAFFIC		= 2,
 	BT_HIGH_TRAFFIC		= 3,
-};
+}; /* BT_COEX_BT_ACTIVITY_GRADING_API_E_VER_1 */
 
 /**
  * struct iwl_bt_coex_profile_notif - notification about BT coex
@@ -310,7 +316,7 @@ struct iwl_bt_coex_profile_notif {
 	__le32 primary_ch_lut;
 	__le32 secondary_ch_lut;
 	__le32 bt_activity_grading;
-} __packed; /* BT_COEX_PROFILE_NTFY_API_S_VER_2 */
+} __packed; /* BT_COEX_PROFILE_NTFY_API_S_VER_3 */
 
 enum iwl_bt_coex_prio_table_event {
 	BT_COEX_PRIO_TBL_EVT_INIT_CALIB1		= 0,
Signature · 1 line
1.8.3.2
#41 lore raw

PATCH 41/47 iwlwifi: mvm: BT Coex - send priority tables from iwl_send_bt_init_conf

In reply to Emmanuel Grumbach

From: Emmanuel Grumbach <[email protected]>

Calling iwl_send_bt_init_conf for INIT firmware is not a problem, and calling iwl_send_bt_prio_tbl from iwl_send_bt_init_conf allows us to prepare for new API.

---
 drivers/net/wireless/iwlwifi/mvm/coex.c | 6 +++++-
 drivers/net/wireless/iwlwifi/mvm/fw.c   | 6 +-----
 drivers/net/wireless/iwlwifi/mvm/mvm.h  | 1 -
 3 files changed, 6 insertions(+), 7 deletions(-)
drivers/net/wireless/iwlwifi/mvm/coex.c +5 -1
index a1403d4..0918635 100644
@@ -104,7 +104,7 @@ static const u8 iwl_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = {
 #define BT_DISABLE_REDUCED_TXPOWER_THRESHOLD	(-65)
 #define BT_ANTENNA_COUPLING_THRESHOLD		(30)
 
-int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm)
+static int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm)
 {
 	return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_PRIO_TABLE, CMD_SYNC,
 				    sizeof(struct iwl_bt_coex_prio_tbl_cmd),
@@ -570,6 +570,10 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
 	int ret;
 	u32 flags;
 
+	ret = iwl_send_bt_prio_tbl(mvm);
+	if (ret)
+		return ret;
+
 	bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL);
 	if (!bt_cmd)
 		return -ENOMEM;
drivers/net/wireless/iwlwifi/mvm/fw.c +1 -5
index e7a2639..3d99cf5 100644
@@ -288,7 +288,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
 		goto error;
 	}
 
-	ret = iwl_send_bt_prio_tbl(mvm);
+	ret = iwl_send_bt_init_conf(mvm);
 	if (ret)
 		goto error;
 
@@ -424,10 +424,6 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
 	if (ret)
 		goto error;
 
-	ret = iwl_send_bt_prio_tbl(mvm);
-	if (ret)
-		goto error;
-
 	ret = iwl_send_bt_init_conf(mvm);
 	if (ret)
 		goto error;
drivers/net/wireless/iwlwifi/mvm/mvm.h +0 -1
index afca542..ed22201 100644
@@ -923,7 +923,6 @@ void iwl_mvm_unref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
 void iwl_mvm_d0i3_enable_tx(struct iwl_mvm *mvm, __le16 *qos_seq);
 
 /* BT Coex */
-int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm);
 int iwl_send_bt_init_conf(struct iwl_mvm *mvm);
 int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
 			     struct iwl_rx_cmd_buffer *rxb,
Signature · 1 line
1.8.3.2
#42 lore raw

PATCH 42/47 iwlwifi: mvm: Add support for Energy based scan (EBS)

In reply to Emmanuel Grumbach

From: Haim Dreyfuss <[email protected]>

This patch enables Energy Based Scan (EBS) - intended to detect energy on 5 GHz band channels. Passive scan on this band takes up to 2.64 sec assuming 110mSec per-channel * 24 channels. EBS is designed to detect energy on channels with intensive Wifi activity as well as those where only beacons are transmitted. EBS completes sampling all channels within shortest beacon frame transmission time. Total EBS duration is about 100 msec (typical beacon interval).
Detecting Wifi activity on 5 GHz band channels can significantly reduce scan duration thus saving time and power. EBS failure reported by FW disables EBS for current connection. It is re-enabled upon new connection attempt on any WLAN interface.

---
 drivers/net/wireless/iwlwifi/iwl-fw.h          |  2 ++
 drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h | 18 ++++++++++++++----
 drivers/net/wireless/iwlwifi/mvm/fw-api.h      |  1 +
 drivers/net/wireless/iwlwifi/mvm/mac80211.c    |  5 +++++
 drivers/net/wireless/iwlwifi/mvm/mvm.h         |  2 ++
 drivers/net/wireless/iwlwifi/mvm/scan.c        | 15 +++++++++++++--
 6 files changed, 37 insertions(+), 6 deletions(-)
drivers/net/wireless/iwlwifi/iwl-fw.h +2 -0
index 265d6f1..f5927d0c 100644
@@ -91,6 +91,7 @@
  * @IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD: P2P client supports uAPSD power save
  * @IWL_UCODE_TLV_FLAGS_BCAST_FILTERING: uCode supports broadcast filtering.
  * @IWL_UCODE_TLV_FLAGS_GO_UAPSD: AP/GO interfaces support uAPSD clients
+ * @IWL_UCODE_TLV_FLAGS_EBS_SUPPORT: this uCode image supports EBS.
  */
 enum iwl_ucode_tlv_flag {
 	IWL_UCODE_TLV_FLAGS_PAN			= BIT(0),
@@ -106,6 +107,7 @@ enum iwl_ucode_tlv_flag {
 	IWL_UCODE_TLV_FLAGS_P2P_PM		= BIT(21),
 	IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM	= BIT(22),
 	IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_SCM	= BIT(23),
+	IWL_UCODE_TLV_FLAGS_EBS_SUPPORT		= BIT(25),
 	IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD	= BIT(26),
 	IWL_UCODE_TLV_FLAGS_BCAST_FILTERING	= BIT(29),
 	IWL_UCODE_TLV_FLAGS_GO_UAPSD		= BIT(30),
drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h +14 -4
index 0373f44..6959fda 100644
@@ -538,13 +538,16 @@ struct iwl_scan_offload_schedule {
  *
  * IWL_SCAN_OFFLOAD_FLAG_PASS_ALL: pass all results - no filtering.
  * IWL_SCAN_OFFLOAD_FLAG_CACHED_CHANNEL: add cached channels to partial scan.
- * IWL_SCAN_OFFLOAD_FLAG_ENERGY_SCAN: use energy based scan before partial scan
- *	on A band.
+ * IWL_SCAN_OFFLOAD_FLAG_EBS_QUICK_MODE: EBS duration is 100mSec - typical
+ *	beacon period. Finding channel activity in this mode is not guaranteed.
+ * IWL_SCAN_OFFLOAD_FLAG_EBS_ACCURATE_MODE: EBS duration is 200mSec.
+ *	Assuming beacon period is 100ms finding channel activity is guaranteed.
  */
 enum iwl_scan_offload_flags {
 	IWL_SCAN_OFFLOAD_FLAG_PASS_ALL		= BIT(0),
 	IWL_SCAN_OFFLOAD_FLAG_CACHED_CHANNEL	= BIT(2),
-	IWL_SCAN_OFFLOAD_FLAG_ENERGY_SCAN	= BIT(3),
+	IWL_SCAN_OFFLOAD_FLAG_EBS_QUICK_MODE	= BIT(5),
+	IWL_SCAN_OFFLOAD_FLAG_EBS_ACCURATE_MODE	= BIT(6),
 };
 
 /**
@@ -567,17 +570,24 @@ enum iwl_scan_offload_compleate_status {
 	IWL_SCAN_OFFLOAD_ABORTED	= 2,
 };
 
+enum iwl_scan_ebs_status {
+	IWL_SCAN_EBS_SUCCESS,
+	IWL_SCAN_EBS_FAILED,
+	IWL_SCAN_EBS_CHAN_NOT_FOUND,
+};
+
 /**
  * iwl_scan_offload_complete - SCAN_OFFLOAD_COMPLETE_NTF_API_S_VER_1
  * @last_schedule_line:		last schedule line executed (fast or regular)
  * @last_schedule_iteration:	last scan iteration executed before scan abort
  * @status:			enum iwl_scan_offload_compleate_status
+ * @ebs_status: last EBS status, see IWL_SCAN_EBS_*
  */
 struct iwl_scan_offload_complete {
 	u8 last_schedule_line;
 	u8 last_schedule_iteration;
 	u8 status;
-	u8 reserved;
+	u8 ebs_status;
 } __packed;
 
 /**
drivers/net/wireless/iwlwifi/mvm/fw-api.h +1 -0
index 48554da..309a9b9 100644
@@ -71,6 +71,7 @@
 #include "fw-api-power.h"
 #include "fw-api-d3.h"
 #include "fw-api-coex.h"
+#include "fw-api-scan.h"
 
 /* maximal number of Tx queues in any platform */
 #define IWL_MVM_MAX_QUEUES	20
drivers/net/wireless/iwlwifi/mvm/mac80211.c +5 -0
index dc9069b..374ecd4 100644
@@ -1694,6 +1694,11 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
 		ret = iwl_mvm_add_sta(mvm, vif, sta);
 	} else if (old_state == IEEE80211_STA_NONE &&
 		   new_state == IEEE80211_STA_AUTH) {
+		/*
+		 * EBS may be disabled due to previous failures reported by FW.
+		 * Reset EBS status here assuming environment has been changed.
+		 */
+		mvm->last_ebs_successful = true;
 		ret = 0;
 	} else if (old_state == IEEE80211_STA_AUTH &&
 		   new_state == IEEE80211_STA_ASSOC) {
drivers/net/wireless/iwlwifi/mvm/mvm.h +2 -0
index ed22201..41184a4 100644
@@ -535,6 +535,8 @@ struct iwl_mvm {
 	/* Internal station */
 	struct iwl_mvm_int_sta aux_sta;
 
+	bool last_ebs_successful;
+
 	u8 scan_last_antenna_idx; /* to toggle TX between antennas */
 	u8 mgmt_last_antenna_idx;
 
drivers/net/wireless/iwlwifi/mvm/scan.c +13 -2
index ea17745..84e7c66 100644
@@ -575,9 +575,13 @@ int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm,
 	/* scan status must be locked for proper checking */
 	lockdep_assert_held(&mvm->mutex);
 
-	IWL_DEBUG_SCAN(mvm, "Scheduled scan completed, status %s\n",
+	IWL_DEBUG_SCAN(mvm,
+		       "Scheduled scan completed, status %s EBS status %s:%d\n",
 		       scan_notif->status == IWL_SCAN_OFFLOAD_COMPLETED ?
-		       "completed" : "aborted");
+		       "completed" : "aborted", scan_notif->ebs_status ==
+		       IWL_SCAN_EBS_SUCCESS ? "success" : "failed",
+		       scan_notif->ebs_status);
+
 
 	/* only call mac80211 completion if the stop was initiated by FW */
 	if (mvm->scan_status == IWL_MVM_SCAN_SCHED) {
@@ -585,6 +589,8 @@ int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm,
 		ieee80211_sched_scan_stopped(mvm->hw);
 	}
 
+	mvm->last_ebs_successful = !scan_notif->ebs_status;
+
 	return 0;
 }
 
@@ -921,6 +927,11 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
 		scan_req.flags |= cpu_to_le16(IWL_SCAN_OFFLOAD_FLAG_PASS_ALL);
 	}
 
+	if (mvm->last_ebs_successful &&
+	    mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_EBS_SUPPORT)
+		scan_req.flags |=
+			cpu_to_le16(IWL_SCAN_OFFLOAD_FLAG_EBS_ACCURATE_MODE);
+
 	return iwl_mvm_send_cmd_pdu(mvm, SCAN_OFFLOAD_REQUEST_CMD, CMD_SYNC,
 				    sizeof(scan_req), &scan_req);
 }
Signature · 1 line
1.8.3.2
#43 lore raw

PATCH 43/47 iwlwifi: 7000: bump firmware API version to 9

In reply to Emmanuel Grumbach

From: Emmanuel Grumbach <[email protected]>

Also warn if an older firmware is loaded.

---
 drivers/net/wireless/iwlwifi/iwl-7000.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/net/wireless/iwlwifi/iwl-7000.c +4 -4
index 3ab21ef..2c9b6fb 100644
@@ -67,12 +67,12 @@
 #include "iwl-agn-hw.h"
 
 /* Highest firmware API version supported */
-#define IWL7260_UCODE_API_MAX	8
-#define IWL3160_UCODE_API_MAX	8
+#define IWL7260_UCODE_API_MAX	9
+#define IWL3160_UCODE_API_MAX	9
 
 /* Oldest version we won't warn about */
-#define IWL7260_UCODE_API_OK	8
-#define IWL3160_UCODE_API_OK	8
+#define IWL7260_UCODE_API_OK	9
+#define IWL3160_UCODE_API_OK	9
 
 /* Lowest firmware API version supported */
 #define IWL7260_UCODE_API_MIN	8
Signature · 1 line
1.8.3.2
#44 lore raw

PATCH 44/47 iwlwifi: mvm: don't use d3 fw if d0i3 is used

In reply to Emmanuel Grumbach

From: Eliad Peller <[email protected]>

bail out from the suspend/resume callbacks if d0i3 is used.

declare support for ANY wowlan trigger (i.e. normal operation).

On resume, we shouldn't execute the d0i3 exit flow (which might disconnect stations, etc.) until mac80211 was resumed.
Add new flags to indicate we are in suspend, and call the pending exit work on resume.

Since the resume flow can take some time, add a new EXIT_WORK reference type to prevent going back to d0i3 at this stage.

---
 drivers/net/wireless/iwlwifi/mvm/d3.c       | 22 ++++++++++++++++++++++
 drivers/net/wireless/iwlwifi/mvm/debugfs.c  |  1 +
 drivers/net/wireless/iwlwifi/mvm/mac80211.c |  6 +++++-
 drivers/net/wireless/iwlwifi/mvm/mvm.h      | 10 ++++++++++
 drivers/net/wireless/iwlwifi/mvm/ops.c      | 22 ++++++++++++++++++++--
 5 files changed, 58 insertions(+), 3 deletions(-)
drivers/net/wireless/iwlwifi/mvm/d3.c +22 -0
index 5c9f14d..7694472 100644
@@ -1074,6 +1074,15 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
 
 int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
 {
+	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+
+	if (iwl_mvm_is_d0i3_supported(mvm)) {
+		mutex_lock(&mvm->d0i3_suspend_mutex);
+		__set_bit(D0I3_DEFER_WAKEUP, &mvm->d0i3_suspend_flags);
+		mutex_unlock(&mvm->d0i3_suspend_mutex);
+		return 0;
+	}
+
 	return __iwl_mvm_suspend(hw, wowlan, false);
 }
 
@@ -1646,6 +1655,19 @@ int iwl_mvm_resume(struct ieee80211_hw *hw)
 {
 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
 
+	if (iwl_mvm_is_d0i3_supported(mvm)) {
+		bool exit_now;
+
+		mutex_lock(&mvm->d0i3_suspend_mutex);
+		__clear_bit(D0I3_DEFER_WAKEUP, &mvm->d0i3_suspend_flags);
+		exit_now = __test_and_clear_bit(D0I3_PENDING_WAKEUP,
+						&mvm->d0i3_suspend_flags);
+		mutex_unlock(&mvm->d0i3_suspend_mutex);
+		if (exit_now)
+			_iwl_mvm_exit_d0i3(mvm);
+		return 0;
+	}
+
 	return __iwl_mvm_resume(mvm, false);
 }
 
drivers/net/wireless/iwlwifi/mvm/debugfs.c +1 -0
index db368cd..c152188 100644
@@ -1001,6 +1001,7 @@ static ssize_t iwl_dbgfs_d0i3_refs_read(struct file *file,
 	PRINT_MVM_REF(IWL_MVM_REF_P2P_CLIENT);
 	PRINT_MVM_REF(IWL_MVM_REF_AP_IBSS);
 	PRINT_MVM_REF(IWL_MVM_REF_USER);
+	PRINT_MVM_REF(IWL_MVM_REF_EXIT_WORK);
 
 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 }
drivers/net/wireless/iwlwifi/mvm/mac80211.c +5 -1
index 374ecd4..3e8437f 100644
@@ -381,7 +381,11 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
 	}
 
 #ifdef CONFIG_PM_SLEEP
-	if (mvm->fw->img[IWL_UCODE_WOWLAN].sec[0].len &&
+	if (iwl_mvm_is_d0i3_supported(mvm) &&
+	    device_can_wakeup(mvm->trans->dev)) {
+		mvm->wowlan.flags = WIPHY_WOWLAN_ANY;
+		hw->wiphy->wowlan = &mvm->wowlan;
+	} else if (mvm->fw->img[IWL_UCODE_WOWLAN].sec[0].len &&
 	    mvm->trans->ops->d3_suspend &&
 	    mvm->trans->ops->d3_resume &&
 	    device_can_wakeup(mvm->trans->dev)) {
drivers/net/wireless/iwlwifi/mvm/mvm.h +10 -0
index 41184a4..17c42da 100644
@@ -230,6 +230,7 @@ enum iwl_mvm_ref_type {
 	IWL_MVM_REF_USER,
 	IWL_MVM_REF_TX,
 	IWL_MVM_REF_TX_AGG,
+	IWL_MVM_REF_EXIT_WORK,
 
 	IWL_MVM_REF_COUNT,
 };
@@ -451,6 +452,11 @@ struct iwl_mvm_frame_stats {
 	int last_frame_idx;
 };
 
+enum {
+	D0I3_DEFER_WAKEUP,
+	D0I3_PENDING_WAKEUP,
+};
+
 struct iwl_mvm {
 	/* for logger access */
 	struct device *dev;
@@ -605,6 +611,9 @@ struct iwl_mvm {
 	bool d0i3_offloading;
 	struct work_struct d0i3_exit_work;
 	struct sk_buff_head d0i3_tx;
+	/* protect d0i3_suspend_flags */
+	struct mutex d0i3_suspend_mutex;
+	unsigned long d0i3_suspend_flags;
 	/* sync d0i3_tx queue and IWL_MVM_STATUS_IN_D0I3 status flag */
 	spinlock_t d0i3_tx_lock;
 	wait_queue_head_t d0i3_exit_waitq;
@@ -923,6 +932,7 @@ int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm,
 void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
 void iwl_mvm_unref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
 void iwl_mvm_d0i3_enable_tx(struct iwl_mvm *mvm, __le16 *qos_seq);
+int _iwl_mvm_exit_d0i3(struct iwl_mvm *mvm);
 
 /* BT Coex */
 int iwl_send_bt_init_conf(struct iwl_mvm *mvm);
drivers/net/wireless/iwlwifi/mvm/ops.c +20 -2
index fd53128..7a5a8ba 100644
@@ -402,6 +402,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
 	mvm->sf_state = SF_UNINIT;
 
 	mutex_init(&mvm->mutex);
+	mutex_init(&mvm->d0i3_suspend_mutex);
 	spin_lock_init(&mvm->async_handlers_lock);
 	INIT_LIST_HEAD(&mvm->time_event_list);
 	INIT_LIST_HEAD(&mvm->async_handlers_list);
@@ -1174,18 +1175,27 @@ static void iwl_mvm_d0i3_exit_work(struct work_struct *wk)
 	iwl_free_resp(&get_status_cmd);
 out:
 	iwl_mvm_d0i3_enable_tx(mvm, qos_seq);
+	iwl_mvm_unref(mvm, IWL_MVM_REF_EXIT_WORK);
 	mutex_unlock(&mvm->mutex);
 }
 
-static int iwl_mvm_exit_d0i3(struct iwl_op_mode *op_mode)
+int _iwl_mvm_exit_d0i3(struct iwl_mvm *mvm)
 {
-	struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
 	u32 flags = CMD_ASYNC | CMD_HIGH_PRIO | CMD_SEND_IN_IDLE |
 		    CMD_WAKE_UP_TRANS;
 	int ret;
 
 	IWL_DEBUG_RPM(mvm, "MVM exiting D0i3\n");
 
+	mutex_lock(&mvm->d0i3_suspend_mutex);
+	if (test_bit(D0I3_DEFER_WAKEUP, &mvm->d0i3_suspend_flags)) {
+		IWL_DEBUG_RPM(mvm, "Deferring d0i3 exit until resume\n");
+		__set_bit(D0I3_PENDING_WAKEUP, &mvm->d0i3_suspend_flags);
+		mutex_unlock(&mvm->d0i3_suspend_mutex);
+		return 0;
+	}
+	mutex_unlock(&mvm->d0i3_suspend_mutex);
+
 	ret = iwl_mvm_send_cmd_pdu(mvm, D0I3_END_CMD, flags, 0, NULL);
 	if (ret)
 		goto out;
@@ -1199,6 +1209,14 @@ out:
 	return ret;
 }
 
+static int iwl_mvm_exit_d0i3(struct iwl_op_mode *op_mode)
+{
+	struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
+
+	iwl_mvm_ref(mvm, IWL_MVM_REF_EXIT_WORK);
+	return _iwl_mvm_exit_d0i3(mvm);
+}
+
 static void iwl_mvm_napi_add(struct iwl_op_mode *op_mode,
 			     struct napi_struct *napi,
 			     struct net_device *napi_dev,
Signature · 1 line
1.8.3.2
#45 lore raw

PATCH 45/47 iwlwifi: mvm: replace leading spaces by tabs

In reply to Emmanuel Grumbach

From: Emmanuel Grumbach <[email protected]>

Somehow I added spaces instead of tabs to a few lines in debugfs.c.

---
 drivers/net/wireless/iwlwifi/mvm/debugfs.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/net/wireless/iwlwifi/mvm/debugfs.c +3 -3
index c152188..f462c9b 100644
@@ -1106,9 +1106,9 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8);
 MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8);
 
 static const struct file_operations iwl_dbgfs_fw_error_dump_ops = {
-        .open = iwl_dbgfs_fw_error_dump_open,
-        .read = iwl_dbgfs_fw_error_dump_read,
-        .release = iwl_dbgfs_fw_error_dump_release,
+	.open = iwl_dbgfs_fw_error_dump_open,
+	.read = iwl_dbgfs_fw_error_dump_read,
+	.release = iwl_dbgfs_fw_error_dump_release,
 };
 
 #ifdef CONFIG_IWLWIFI_BCAST_FILTERING
Signature · 1 line
1.8.3.2
#46 lore raw

PATCH 46/47 iwlwifi: mvm: Re-factor enabling uAPSD logic

In reply to Emmanuel Grumbach

From: Avri Altman <[email protected]>

The driver can enable uAPSD and specify some of its related parameters. This patch organizes this logic in a separate function.

---
 drivers/net/wireless/iwlwifi/mvm/power.c | 43 +++++++++++++++++++-------------
 1 file changed, 25 insertions(+), 18 deletions(-)
drivers/net/wireless/iwlwifi/mvm/power.c +25 -18
index 2e6f477..78309f7 100644
@@ -268,6 +268,30 @@ static void iwl_mvm_power_configure_uapsd(struct iwl_mvm *mvm,
 		IWL_MVM_PS_HEAVY_RX_THLD_PERCENT;
 }
 
+static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm,
+				       struct ieee80211_vif *vif)
+{
+	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+
+	if (!memcmp(mvmvif->uapsd_misbehaving_bssid, vif->bss_conf.bssid,
+		    ETH_ALEN))
+		return false;
+
+	if (vif->p2p &&
+	    !(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD))
+		return false;
+	/*
+	 * Avoid using uAPSD if P2P client is associated to GO that uses
+	 * opportunistic power save. This is due to current FW limitation.
+	 */
+	if (vif->p2p &&
+	    (vif->bss_conf.p2p_noa_attr.oppps_ctwindow &
+	    IEEE80211_P2P_OPPPS_ENABLE_BIT))
+		return false;
+
+	return true;
+}
+
 static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
 				    struct ieee80211_vif *vif,
 				    struct iwl_mac_power_cmd *cmd)
@@ -280,7 +304,6 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
 	bool radar_detect = false;
 	struct iwl_mvm_vif *mvmvif __maybe_unused =
 		iwl_mvm_vif_from_mac80211(vif);
-	bool allow_uapsd = true;
 
 	cmd->id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
 							    mvmvif->color));
@@ -346,23 +369,7 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
 			cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT);
 	}
 
-	if (!memcmp(mvmvif->uapsd_misbehaving_bssid, vif->bss_conf.bssid,
-		    ETH_ALEN))
-		allow_uapsd = false;
-
-	if (vif->p2p &&
-	    !(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD))
-		allow_uapsd = false;
-	/*
-	 * Avoid using uAPSD if P2P client is associated to GO that uses
-	 * opportunistic power save. This is due to current FW limitation.
-	 */
-	if (vif->p2p &&
-	    vif->bss_conf.p2p_noa_attr.oppps_ctwindow &
-	    IEEE80211_P2P_OPPPS_ENABLE_BIT)
-		allow_uapsd = false;
-
-	if (allow_uapsd)
+	if (iwl_mvm_power_allow_uapsd(mvm, vif))
 		iwl_mvm_power_configure_uapsd(mvm, vif, cmd);
 
 #ifdef CONFIG_IWLWIFI_DEBUGFS
Signature · 1 line
1.8.3.2
#47 lore raw

PATCH 47/47 iwlwifi: don't disable SCD chain extension on newer devices

In reply to Emmanuel Grumbach

From: Emmanuel Grumbach <[email protected]>

7000 device series have a fix for this hardware feature. Stop disabling it, and get an improvement in Tx throughput. This feature allows the scheduler to fetch more frames on the fly while an A-MPDU is being built - which means that we can get larger A-MPDU. This, of course, give an improvement in the Tx throughput.

---
 drivers/net/wireless/iwlwifi/iwl-1000.c   | 1 +
 drivers/net/wireless/iwlwifi/iwl-2000.c   | 2 ++
 drivers/net/wireless/iwlwifi/iwl-5000.c   | 1 +
 drivers/net/wireless/iwlwifi/iwl-6000.c   | 3 +++
 drivers/net/wireless/iwlwifi/iwl-config.h | 2 ++
 drivers/net/wireless/iwlwifi/pcie/tx.c    | 3 ++-
 6 files changed, 11 insertions(+), 1 deletion(-)
drivers/net/wireless/iwlwifi/iwl-1000.c +1 -0
index 854ba84..c3817fa 100644
@@ -62,6 +62,7 @@ static const struct iwl_base_params iwl1000_base_params = {
 	.led_compensation = 51,
 	.wd_timeout = IWL_WATCHDOG_DISABLED,
 	.max_event_log_size = 128,
+	.scd_chain_ext_wa = true,
 };
 
 static const struct iwl_ht_params iwl1000_ht_params = {
drivers/net/wireless/iwlwifi/iwl-2000.c +2 -0
index 3e63323..21e5d08 100644
@@ -75,6 +75,7 @@ static const struct iwl_base_params iwl2000_base_params = {
 	.wd_timeout = IWL_DEF_WD_TIMEOUT,
 	.max_event_log_size = 512,
 	.shadow_reg_enable = false, /* TODO: fix bugs using this feature */
+	.scd_chain_ext_wa = true,
 };
 
 
@@ -88,6 +89,7 @@ static const struct iwl_base_params iwl2030_base_params = {
 	.wd_timeout = IWL_LONG_WD_TIMEOUT,
 	.max_event_log_size = 512,
 	.shadow_reg_enable = false, /* TODO: fix bugs using this feature */
+	.scd_chain_ext_wa = true,
 };
 
 static const struct iwl_ht_params iwl2000_ht_params = {
drivers/net/wireless/iwlwifi/iwl-5000.c +1 -0
index 6674f2c..332bbede 100644
@@ -61,6 +61,7 @@ static const struct iwl_base_params iwl5000_base_params = {
 	.led_compensation = 51,
 	.wd_timeout = IWL_WATCHDOG_DISABLED,
 	.max_event_log_size = 512,
+	.scd_chain_ext_wa = true,
 };
 
 static const struct iwl_ht_params iwl5000_ht_params = {
drivers/net/wireless/iwlwifi/iwl-6000.c +3 -0
index 8048de9..8f2c3c8 100644
@@ -85,6 +85,7 @@ static const struct iwl_base_params iwl6000_base_params = {
 	.wd_timeout = IWL_DEF_WD_TIMEOUT,
 	.max_event_log_size = 512,
 	.shadow_reg_enable = false, /* TODO: fix bugs using this feature */
+	.scd_chain_ext_wa = true,
 };
 
 static const struct iwl_base_params iwl6050_base_params = {
@@ -97,6 +98,7 @@ static const struct iwl_base_params iwl6050_base_params = {
 	.wd_timeout = IWL_DEF_WD_TIMEOUT,
 	.max_event_log_size = 1024,
 	.shadow_reg_enable = false, /* TODO: fix bugs using this feature */
+	.scd_chain_ext_wa = true,
 };
 
 static const struct iwl_base_params iwl6000_g2_base_params = {
@@ -109,6 +111,7 @@ static const struct iwl_base_params iwl6000_g2_base_params = {
 	.wd_timeout = IWL_LONG_WD_TIMEOUT,
 	.max_event_log_size = 512,
 	.shadow_reg_enable = false, /* TODO: fix bugs using this feature */
+	.scd_chain_ext_wa = true,
 };
 
 static const struct iwl_ht_params iwl6000_ht_params = {
drivers/net/wireless/iwlwifi/iwl-config.h +2 -0
index 8c16730..7ce82d9 100644
@@ -148,6 +148,7 @@ static inline u8 num_of_ant(u8 mask)
  * @shadow_reg_enable: HW shadow register support
  * @apmg_wake_up_wa: should the MAC access REQ be asserted when a command
  *	is in flight. This is due to a HW bug in 7260, 3160 and 7265.
+ * @scd_chain_ext_wa: should the chain extension feature in SCD be disabled.
  */
 struct iwl_base_params {
 	int eeprom_size;
@@ -163,6 +164,7 @@ struct iwl_base_params {
 	const bool shadow_reg_enable;
 	const bool pcie_l1_allowed;
 	const bool apmg_wake_up_wa;
+	const bool scd_chain_ext_wa;
 };
 
 /*
drivers/net/wireless/iwlwifi/pcie/tx.c +2 -1
index 78a6ff2..dde6031 100644
@@ -696,7 +696,8 @@ void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr)
 	/* The chain extension of the SCD doesn't work well. This feature is
 	 * enabled by default by the HW, so we need to disable it manually.
 	 */
-	iwl_write_prph(trans, SCD_CHAINEXT_EN, 0);
+	if (trans->cfg->base_params->scd_chain_ext_wa)
+		iwl_write_prph(trans, SCD_CHAINEXT_EN, 0);
 
 	iwl_trans_ac_txq_enable(trans, trans_pcie->cmd_queue,
 				trans_pcie->cmd_fifo);
Signature · 1 line
1.8.3.2
#48 lore raw
In reply to Emmanuel Grumbach
Quoted 12 lines · Emmanuel Grumbach

Hi John,

This is for 3.16.

I have here a bunch of unrelated things. I disabled support for -7.ucode which means that I can removed a lot of code. Eliad has a brand new feature: we reduce the Tx power when the link allows - this reduces our power consumption. The regular changes in power and scan area. One interesting thing though is the patches from Johannes, we have now GRO which allows to increase our throughput in TCP Rx. The main advantage is that it reduces the number of TCP Acks - these TCP Acks are completely useless when we are using A-MPDU since the first packet of the A-MPDU generates a TCP Ack which is made obsolete by the next packets.

Same footer as previous pull request, I won't be available this week, so let's hope I am not causing any problem here.

Thanks!

The following changes since commit a31267c30880ebdc73e6815f58c69a665052fab8:

Quoted 8 lines

rtl8187: fix use after free on failure path in rtl8187_probe() (2014-03-31 13:47:41 -0400)

are available in the git repository at:

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

for you to fetch changes up to 3cd5279b021de6501a8012dd856d7a78ee58ead9:

Apparently I can't get the rid of my tradition to fixup something after the mail goes out...

I dropped 2 patches that I queued up for 3.15 in my next pull request - new HEAD: e03bbb62cfdf539ae8110b297493c685f9d12774

#49 lore raw
Quoted 19 lines · Emmanuel Grumbach
Quoted 16 lines · Emmanuel Grumbach

Hi John,

This is for 3.16.

I have here a bunch of unrelated things. I disabled support for -7.ucode which means that I can removed a lot of code. Eliad has a brand new feature: we reduce the Tx power when the link allows - this reduces our power consumption. The regular changes in power and scan area. One interesting thing though is the patches from Johannes, we have now GRO which allows to increase our throughput in TCP Rx. The main advantage is that it reduces the number of TCP Acks - these TCP Acks are completely useless when we are using A-MPDU since the first packet of the A-MPDU generates a TCP Ack which is made obsolete by the next packets.

Same footer as previous pull request, I won't be available this week, so let's hope I am not causing any problem here.

Thanks!

The following changes since commit a31267c30880ebdc73e6815f58c69a665052fab8:

rtl8187: fix use after free on failure path in rtl8187_probe() (2014-03-31 13:47:41 -0400)

are available in the git repository at:

Quoted 7 lines
Quoted 4 lines

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

for you to fetch changes up to 3cd5279b021de6501a8012dd856d7a78ee58ead9:

Apparently I can't get the rid of my tradition to fixup something after the mail goes out...

I dropped 2 patches that I queued up for 3.15 in my next pull request - new HEAD: e03bbb62cfdf539ae8110b297493c685f9d12774

Pulled today...

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