aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/mvm
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-09-05 17:54:29 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-05 17:54:29 -0400
commitcc998ff8811530be521f6b316f37ab7676a07938 (patch)
treea054b3bf4b2ef406bf756a6cfc9be2f9115f17ae /drivers/net/wireless/iwlwifi/mvm
parent57d730924d5cc2c3e280af16a9306587c3a511db (diff)
parent0d40f75bdab241868c0eb6f97aef9f8b3a66f7b3 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking changes from David Miller: "Noteworthy changes this time around: 1) Multicast rejoin support for team driver, from Jiri Pirko. 2) Centralize and simplify TCP RTT measurement handling in order to reduce the impact of bad RTO seeding from SYN/ACKs. Also, when both timestamps and local RTT measurements are available prefer the later because there are broken middleware devices which scramble the timestamp. From Yuchung Cheng. 3) Add TCP_NOTSENT_LOWAT socket option to limit the amount of kernel memory consumed to queue up unsend user data. From Eric Dumazet. 4) Add a "physical port ID" abstraction for network devices, from Jiri Pirko. 5) Add a "suppress" operation to influence fib_rules lookups, from Stefan Tomanek. 6) Add a networking development FAQ, from Paul Gortmaker. 7) Extend the information provided by tcp_probe and add ipv6 support, from Daniel Borkmann. 8) Use RCU locking more extensively in openvswitch data paths, from Pravin B Shelar. 9) Add SCTP support to openvswitch, from Joe Stringer. 10) Add EF10 chip support to SFC driver, from Ben Hutchings. 11) Add new SYNPROXY netfilter target, from Patrick McHardy. 12) Compute a rate approximation for sending in TCP sockets, and use this to more intelligently coalesce TSO frames. Furthermore, add a new packet scheduler which takes advantage of this estimate when available. From Eric Dumazet. 13) Allow AF_PACKET fanouts with random selection, from Daniel Borkmann. 14) Add ipv6 support to vxlan driver, from Cong Wang" Resolved conflicts as per discussion. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1218 commits) openvswitch: Fix alignment of struct sw_flow_key. netfilter: Fix build errors with xt_socket.c tcp: Add missing braces to do_tcp_setsockopt caif: Add missing braces to multiline if in cfctrl_linkup_request bnx2x: Add missing braces in bnx2x:bnx2x_link_initialize vxlan: Fix kernel panic on device delete. net: mvneta: implement ->ndo_do_ioctl() to support PHY ioctls net: mvneta: properly disable HW PHY polling and ensure adjust_link() works icplus: Use netif_running to determine device state ethernet/arc/arc_emac: Fix huge delays in large file copies tuntap: orphan frags before trying to set tx timestamp tuntap: purge socket error queue on detach qlcnic: use standard NAPI weights ipv6:introduce function to find route for redirect bnx2x: VF RSS support - VF side bnx2x: VF RSS support - PF side vxlan: Notify drivers for listening UDP port changes net: usbnet: update addr_assign_type if appropriate driver/net: enic: update enic maintainers and driver driver/net: enic: Exposing symbols for Cisco's low latency driver ...
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm')
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/Makefile2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/bt-coex.c162
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/constants.h80
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/d3.c217
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/debugfs.c271
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h49
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api-power.h147
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h5
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api.h255
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw.c55
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c3
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac80211.c82
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mvm.h112
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/ops.c58
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/power.c383
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/power_legacy.c319
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/quota.c27
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/rs.c653
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/rs.h80
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/rx.c158
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/scan.c2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/sta.c3
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/time-event.c103
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/tt.c32
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/tx.c13
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/utils.c23
27 files changed, 2117 insertions, 1179 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/Makefile b/drivers/net/wireless/iwlwifi/mvm/Makefile
index ff856e543ae8..6d73817850ce 100644
--- a/drivers/net/wireless/iwlwifi/mvm/Makefile
+++ b/drivers/net/wireless/iwlwifi/mvm/Makefile
@@ -2,7 +2,7 @@ obj-$(CONFIG_IWLMVM) += iwlmvm.o
2iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o 2iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o
3iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o 3iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o
4iwlmvm-y += scan.o time-event.o rs.o 4iwlmvm-y += scan.o time-event.o rs.o
5iwlmvm-y += power.o bt-coex.o 5iwlmvm-y += power.o power_legacy.o bt-coex.o
6iwlmvm-y += led.o tt.o 6iwlmvm-y += led.o tt.o
7iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o 7iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o
8iwlmvm-$(CONFIG_PM_SLEEP) += d3.o 8iwlmvm-$(CONFIG_PM_SLEEP) += d3.o
diff --git a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c
index dbd622a3929c..0fad98b85f60 100644
--- a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c
+++ b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c
@@ -220,66 +220,87 @@ static const __le32 iwl_single_shared_ant_lookup[BT_COEX_LUT_SIZE] = {
220 220
221int iwl_send_bt_init_conf(struct iwl_mvm *mvm) 221int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
222{ 222{
223 struct iwl_bt_coex_cmd cmd = { 223 struct iwl_bt_coex_cmd *bt_cmd;
224 .max_kill = 5, 224 struct iwl_host_cmd cmd = {
225 .bt3_time_t7_value = 1, 225 .id = BT_CONFIG,
226 .bt3_prio_sample_time = 2, 226 .len = { sizeof(*bt_cmd), },
227 .bt3_timer_t2_value = 0xc, 227 .dataflags = { IWL_HCMD_DFL_NOCOPY, },
228 .flags = CMD_SYNC,
228 }; 229 };
229 int ret; 230 int ret;
230 231
231 cmd.flags = iwlwifi_mod_params.bt_coex_active ? 232 /* go to CALIB state in internal BT-Coex state machine */
233 ret = iwl_send_bt_env(mvm, BT_COEX_ENV_OPEN,
234 BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
235 if (ret)
236 return ret;
237
238 ret = iwl_send_bt_env(mvm, BT_COEX_ENV_CLOSE,
239 BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
240 if (ret)
241 return ret;
242
243 bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL);
244 if (!bt_cmd)
245 return -ENOMEM;
246 cmd.data[0] = bt_cmd;
247
248 bt_cmd->max_kill = 5;
249 bt_cmd->bt3_time_t7_value = 1;
250 bt_cmd->bt3_prio_sample_time = 2;
251 bt_cmd->bt3_timer_t2_value = 0xc;
252
253 bt_cmd->flags = iwlwifi_mod_params.bt_coex_active ?
232 BT_COEX_NW : BT_COEX_DISABLE; 254 BT_COEX_NW : BT_COEX_DISABLE;
233 cmd.flags |= BT_CH_PRIMARY_EN | BT_SYNC_2_BT_DISABLE; 255 bt_cmd->flags |= BT_CH_PRIMARY_EN | BT_SYNC_2_BT_DISABLE;
234 256
235 cmd.valid_bit_msk = cpu_to_le16(BT_VALID_ENABLE | 257 bt_cmd->valid_bit_msk = cpu_to_le16(BT_VALID_ENABLE |
236 BT_VALID_BT_PRIO_BOOST | 258 BT_VALID_BT_PRIO_BOOST |
237 BT_VALID_MAX_KILL | 259 BT_VALID_MAX_KILL |
238 BT_VALID_3W_TMRS | 260 BT_VALID_3W_TMRS |
239 BT_VALID_KILL_ACK | 261 BT_VALID_KILL_ACK |
240 BT_VALID_KILL_CTS | 262 BT_VALID_KILL_CTS |
241 BT_VALID_REDUCED_TX_POWER | 263 BT_VALID_REDUCED_TX_POWER |
242 BT_VALID_LUT); 264 BT_VALID_LUT);
243 265
244 if (mvm->cfg->bt_shared_single_ant) 266 if (mvm->cfg->bt_shared_single_ant)
245 memcpy(&cmd.decision_lut, iwl_single_shared_ant_lookup, 267 memcpy(&bt_cmd->decision_lut, iwl_single_shared_ant_lookup,
246 sizeof(iwl_single_shared_ant_lookup)); 268 sizeof(iwl_single_shared_ant_lookup));
247 else if (is_loose_coex()) 269 else if (is_loose_coex())
248 memcpy(&cmd.decision_lut, iwl_loose_lookup, 270 memcpy(&bt_cmd->decision_lut, iwl_loose_lookup,
249 sizeof(iwl_tight_lookup)); 271 sizeof(iwl_tight_lookup));
250 else 272 else
251 memcpy(&cmd.decision_lut, iwl_tight_lookup, 273 memcpy(&bt_cmd->decision_lut, iwl_tight_lookup,
252 sizeof(iwl_tight_lookup)); 274 sizeof(iwl_tight_lookup));
253 275
254 cmd.bt_prio_boost = cpu_to_le32(IWL_BT_DEFAULT_BOOST); 276 bt_cmd->bt_prio_boost = cpu_to_le32(IWL_BT_DEFAULT_BOOST);
255 cmd.kill_ack_msk = 277 bt_cmd->kill_ack_msk =
256 cpu_to_le32(iwl_bt_ack_kill_msk[BT_KILL_MSK_DEFAULT]); 278 cpu_to_le32(iwl_bt_ack_kill_msk[BT_KILL_MSK_DEFAULT]);
257 cmd.kill_cts_msk = 279 bt_cmd->kill_cts_msk =
258 cpu_to_le32(iwl_bt_cts_kill_msk[BT_KILL_MSK_DEFAULT]); 280 cpu_to_le32(iwl_bt_cts_kill_msk[BT_KILL_MSK_DEFAULT]);
259 281
260 memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif)); 282 memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
261 283
262 /* go to CALIB state in internal BT-Coex state machine */ 284 ret = iwl_mvm_send_cmd(mvm, &cmd);
263 ret = iwl_send_bt_env(mvm, BT_COEX_ENV_OPEN,
264 BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
265 if (ret)
266 return ret;
267
268 ret = iwl_send_bt_env(mvm, BT_COEX_ENV_CLOSE,
269 BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
270 if (ret)
271 return ret;
272 285
273 return iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, CMD_SYNC, 286 kfree(bt_cmd);
274 sizeof(cmd), &cmd); 287 return ret;
275} 288}
276 289
277static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm, 290static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm,
278 bool reduced_tx_power) 291 bool reduced_tx_power)
279{ 292{
280 enum iwl_bt_kill_msk bt_kill_msk; 293 enum iwl_bt_kill_msk bt_kill_msk;
281 struct iwl_bt_coex_cmd cmd = {}; 294 struct iwl_bt_coex_cmd *bt_cmd;
282 struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif; 295 struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif;
296 struct iwl_host_cmd cmd = {
297 .id = BT_CONFIG,
298 .data[0] = &bt_cmd,
299 .len = { sizeof(*bt_cmd), },
300 .dataflags = { IWL_HCMD_DFL_NOCOPY, },
301 .flags = CMD_SYNC,
302 };
303 int ret = 0;
283 304
284 lockdep_assert_held(&mvm->mutex); 305 lockdep_assert_held(&mvm->mutex);
285 306
@@ -308,24 +329,40 @@ static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm,
308 return 0; 329 return 0;
309 330
310 mvm->bt_kill_msk = bt_kill_msk; 331 mvm->bt_kill_msk = bt_kill_msk;
311 cmd.kill_ack_msk = cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]); 332
312 cmd.kill_cts_msk = cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]); 333 bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL);
313 cmd.valid_bit_msk = cpu_to_le16(BT_VALID_KILL_ACK | BT_VALID_KILL_CTS); 334 if (!bt_cmd)
335 return -ENOMEM;
336 cmd.data[0] = bt_cmd;
337
338 bt_cmd->kill_ack_msk = cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]);
339 bt_cmd->kill_cts_msk = cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]);
340 bt_cmd->valid_bit_msk =
341 cpu_to_le16(BT_VALID_KILL_ACK | BT_VALID_KILL_CTS);
314 342
315 IWL_DEBUG_COEX(mvm, "bt_kill_msk = %d\n", bt_kill_msk); 343 IWL_DEBUG_COEX(mvm, "bt_kill_msk = %d\n", bt_kill_msk);
316 return iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, CMD_SYNC, 344
317 sizeof(cmd), &cmd); 345 ret = iwl_mvm_send_cmd(mvm, &cmd);
346
347 kfree(bt_cmd);
348 return ret;
318} 349}
319 350
320static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, 351static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
321 bool enable) 352 bool enable)
322{ 353{
323 struct iwl_bt_coex_cmd cmd = { 354 struct iwl_bt_coex_cmd *bt_cmd;
324 .valid_bit_msk = cpu_to_le16(BT_VALID_REDUCED_TX_POWER), 355 /* Send ASYNC since this can be sent from an atomic context */
325 .bt_reduced_tx_power = sta_id, 356 struct iwl_host_cmd cmd = {
357 .id = BT_CONFIG,
358 .len = { sizeof(*bt_cmd), },
359 .dataflags = { IWL_HCMD_DFL_DUP, },
360 .flags = CMD_ASYNC,
326 }; 361 };
362
327 struct ieee80211_sta *sta; 363 struct ieee80211_sta *sta;
328 struct iwl_mvm_sta *mvmsta; 364 struct iwl_mvm_sta *mvmsta;
365 int ret;
329 366
330 /* This can happen if the station has been removed right now */ 367 /* This can happen if the station has been removed right now */
331 if (sta_id == IWL_MVM_STATION_COUNT) 368 if (sta_id == IWL_MVM_STATION_COUNT)
@@ -339,17 +376,26 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
339 if (mvmsta->bt_reduced_txpower == enable) 376 if (mvmsta->bt_reduced_txpower == enable)
340 return 0; 377 return 0;
341 378
379 bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_ATOMIC);
380 if (!bt_cmd)
381 return -ENOMEM;
382 cmd.data[0] = bt_cmd;
383
384 bt_cmd->valid_bit_msk = cpu_to_le16(BT_VALID_REDUCED_TX_POWER),
385 bt_cmd->bt_reduced_tx_power = sta_id;
386
342 if (enable) 387 if (enable)
343 cmd.bt_reduced_tx_power |= BT_REDUCED_TX_POWER_BIT; 388 bt_cmd->bt_reduced_tx_power |= BT_REDUCED_TX_POWER_BIT;
344 389
345 IWL_DEBUG_COEX(mvm, "%sable reduced Tx Power for sta %d\n", 390 IWL_DEBUG_COEX(mvm, "%sable reduced Tx Power for sta %d\n",
346 enable ? "en" : "dis", sta_id); 391 enable ? "en" : "dis", sta_id);
347 392
348 mvmsta->bt_reduced_txpower = enable; 393 mvmsta->bt_reduced_txpower = enable;
349 394
350 /* Send ASYNC since this can be sent from an atomic context */ 395 ret = iwl_mvm_send_cmd(mvm, &cmd);
351 return iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, CMD_ASYNC, 396
352 sizeof(cmd), &cmd); 397 kfree(bt_cmd);
398 return ret;
353} 399}
354 400
355struct iwl_bt_iterator_data { 401struct iwl_bt_iterator_data {
@@ -384,6 +430,10 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
384 430
385 smps_mode = IEEE80211_SMPS_AUTOMATIC; 431 smps_mode = IEEE80211_SMPS_AUTOMATIC;
386 432
433 /* non associated BSSes aren't to be considered */
434 if (!vif->bss_conf.assoc)
435 return;
436
387 if (band != IEEE80211_BAND_2GHZ) { 437 if (band != IEEE80211_BAND_2GHZ) {
388 iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, 438 iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
389 smps_mode); 439 smps_mode);
@@ -523,6 +573,8 @@ static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac,
523 lockdep_is_held(&mvm->mutex)); 573 lockdep_is_held(&mvm->mutex));
524 mvmsta = (void *)sta->drv_priv; 574 mvmsta = (void *)sta->drv_priv;
525 575
576 data->num_bss_ifaces++;
577
526 /* 578 /*
527 * This interface doesn't support reduced Tx power (because of low 579 * This interface doesn't support reduced Tx power (because of low
528 * RSSI probably), then set bt_kill_msk to default values. 580 * RSSI probably), then set bt_kill_msk to default values.
@@ -588,23 +640,5 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
588 640
589void iwl_mvm_bt_coex_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif) 641void iwl_mvm_bt_coex_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
590{ 642{
591 struct ieee80211_chanctx_conf *chanctx_conf;
592 enum ieee80211_band band;
593
594 rcu_read_lock();
595 chanctx_conf = rcu_dereference(vif->chanctx_conf);
596 if (chanctx_conf && chanctx_conf->def.chan)
597 band = chanctx_conf->def.chan->band;
598 else
599 band = -1;
600 rcu_read_unlock();
601
602 /* if we are in 2GHz we will get a notification from the fw */
603 if (band == IEEE80211_BAND_2GHZ)
604 return;
605
606 /* else, we can remove all the constraints */
607 memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
608
609 iwl_mvm_bt_coex_notif_handle(mvm); 643 iwl_mvm_bt_coex_notif_handle(mvm);
610} 644}
diff --git a/drivers/net/wireless/iwlwifi/mvm/constants.h b/drivers/net/wireless/iwlwifi/mvm/constants.h
new file mode 100644
index 000000000000..2bf29f7992ee
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/mvm/constants.h
@@ -0,0 +1,80 @@
1/******************************************************************************
2 *
3 * This file is provided under a dual BSD/GPLv2 license. When using or
4 * redistributing this file, you may do so under either license.
5 *
6 * GPL LICENSE SUMMARY
7 *
8 * Copyright(c) 2013 Intel Corporation. All rights reserved.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of version 2 of the GNU General Public License as
12 * published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
22 * USA
23 *
24 * The full GNU General Public License is included in this distribution
25 * in the file called COPYING.
26 *
27 * Contact Information:
28 * Intel Linux Wireless <ilw@linux.intel.com>
29 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
30 *
31 * BSD LICENSE
32 *
33 * Copyright(c) 2013 Intel Corporation. All rights reserved.
34 * All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 *
40 * * Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * * Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in
44 * the documentation and/or other materials provided with the
45 * distribution.
46 * * Neither the name Intel Corporation nor the names of its
47 * contributors may be used to endorse or promote products derived
48 * from this software without specific prior written permission.
49 *
50 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
51 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
52 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
53 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
54 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
56 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
57 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
58 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
59 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
60 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61 *
62 *****************************************************************************/
63#ifndef __MVM_CONSTANTS_H
64#define __MVM_CONSTANTS_H
65
66#define IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT (100 * USEC_PER_MSEC)
67#define IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT (100 * USEC_PER_MSEC)
68#define IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT (10 * USEC_PER_MSEC)
69#define IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT (10 * USEC_PER_MSEC)
70#define IWL_MVM_UAPSD_RX_DATA_TIMEOUT (50 * USEC_PER_MSEC)
71#define IWL_MVM_UAPSD_TX_DATA_TIMEOUT (50 * USEC_PER_MSEC)
72#define IWL_MVM_PS_HEAVY_TX_THLD_PACKETS 20
73#define IWL_MVM_PS_HEAVY_RX_THLD_PACKETS 20
74#define IWL_MVM_PS_HEAVY_TX_THLD_PERCENT 50
75#define IWL_MVM_PS_HEAVY_RX_THLD_PERCENT 50
76#define IWL_MVM_PS_SNOOZE_INTERVAL 25
77#define IWL_MVM_PS_SNOOZE_WINDOW 50
78#define IWL_MVM_WOWLAN_PS_SNOOZE_WINDOW 25
79
80#endif /* __MVM_CONSTANTS_H */
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c
index 83da884cf303..417639f77b01 100644
--- a/drivers/net/wireless/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/iwlwifi/mvm/d3.c
@@ -105,7 +105,7 @@ void iwl_mvm_ipv6_addr_change(struct ieee80211_hw *hw,
105 list_for_each_entry(ifa, &idev->addr_list, if_list) { 105 list_for_each_entry(ifa, &idev->addr_list, if_list) {
106 mvmvif->target_ipv6_addrs[idx] = ifa->addr; 106 mvmvif->target_ipv6_addrs[idx] = ifa->addr;
107 idx++; 107 idx++;
108 if (idx >= IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS) 108 if (idx >= IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_MAX)
109 break; 109 break;
110 } 110 }
111 read_unlock_bh(&idev->lock); 111 read_unlock_bh(&idev->lock);
@@ -378,36 +378,68 @@ static int iwl_mvm_send_patterns(struct iwl_mvm *mvm,
378static int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm, 378static int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm,
379 struct ieee80211_vif *vif) 379 struct ieee80211_vif *vif)
380{ 380{
381 struct iwl_proto_offload_cmd cmd = {}; 381 union {
382 struct iwl_proto_offload_cmd_v1 v1;
383 struct iwl_proto_offload_cmd_v2 v2;
384 } cmd = {};
385 struct iwl_proto_offload_cmd_common *common;
386 u32 enabled = 0, size;
382#if IS_ENABLED(CONFIG_IPV6) 387#if IS_ENABLED(CONFIG_IPV6)
383 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 388 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
384 int i; 389 int i;
385 390
386 if (mvmvif->num_target_ipv6_addrs) { 391 if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS) {
387 cmd.enabled |= cpu_to_le32(IWL_D3_PROTO_OFFLOAD_NS); 392 if (mvmvif->num_target_ipv6_addrs) {
388 memcpy(cmd.ndp_mac_addr, vif->addr, ETH_ALEN); 393 enabled |= IWL_D3_PROTO_OFFLOAD_NS;
389 } 394 memcpy(cmd.v2.ndp_mac_addr, vif->addr, ETH_ALEN);
395 }
396
397 BUILD_BUG_ON(sizeof(cmd.v2.target_ipv6_addr[0]) !=
398 sizeof(mvmvif->target_ipv6_addrs[0]));
390 399
391 BUILD_BUG_ON(sizeof(cmd.target_ipv6_addr[i]) != 400 for (i = 0; i < min(mvmvif->num_target_ipv6_addrs,
392 sizeof(mvmvif->target_ipv6_addrs[i])); 401 IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V2); i++)
402 memcpy(cmd.v2.target_ipv6_addr[i],
403 &mvmvif->target_ipv6_addrs[i],
404 sizeof(cmd.v2.target_ipv6_addr[i]));
405 } else {
406 if (mvmvif->num_target_ipv6_addrs) {
407 enabled |= IWL_D3_PROTO_OFFLOAD_NS;
408 memcpy(cmd.v1.ndp_mac_addr, vif->addr, ETH_ALEN);
409 }
393 410
394 for (i = 0; i < mvmvif->num_target_ipv6_addrs; i++) 411 BUILD_BUG_ON(sizeof(cmd.v1.target_ipv6_addr[0]) !=
395 memcpy(cmd.target_ipv6_addr[i], 412 sizeof(mvmvif->target_ipv6_addrs[0]));
396 &mvmvif->target_ipv6_addrs[i], 413
397 sizeof(cmd.target_ipv6_addr[i])); 414 for (i = 0; i < min(mvmvif->num_target_ipv6_addrs,
415 IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V1); i++)
416 memcpy(cmd.v1.target_ipv6_addr[i],
417 &mvmvif->target_ipv6_addrs[i],
418 sizeof(cmd.v1.target_ipv6_addr[i]));
419 }
398#endif 420#endif
399 421
422 if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS) {
423 common = &cmd.v2.common;
424 size = sizeof(cmd.v2);
425 } else {
426 common = &cmd.v1.common;
427 size = sizeof(cmd.v1);
428 }
429
400 if (vif->bss_conf.arp_addr_cnt) { 430 if (vif->bss_conf.arp_addr_cnt) {
401 cmd.enabled |= cpu_to_le32(IWL_D3_PROTO_OFFLOAD_ARP); 431 enabled |= IWL_D3_PROTO_OFFLOAD_ARP;
402 cmd.host_ipv4_addr = vif->bss_conf.arp_addr_list[0]; 432 common->host_ipv4_addr = vif->bss_conf.arp_addr_list[0];
403 memcpy(cmd.arp_mac_addr, vif->addr, ETH_ALEN); 433 memcpy(common->arp_mac_addr, vif->addr, ETH_ALEN);
404 } 434 }
405 435
406 if (!cmd.enabled) 436 if (!enabled)
407 return 0; 437 return 0;
408 438
439 common->enabled = cpu_to_le32(enabled);
440
409 return iwl_mvm_send_cmd_pdu(mvm, PROT_OFFLOAD_CONFIG_CMD, CMD_SYNC, 441 return iwl_mvm_send_cmd_pdu(mvm, PROT_OFFLOAD_CONFIG_CMD, CMD_SYNC,
410 sizeof(cmd), &cmd); 442 size, &cmd);
411} 443}
412 444
413enum iwl_mvm_tcp_packet_type { 445enum iwl_mvm_tcp_packet_type {
@@ -1077,73 +1109,16 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
1077 return __iwl_mvm_suspend(hw, wowlan, false); 1109 return __iwl_mvm_suspend(hw, wowlan, false);
1078} 1110}
1079 1111
1080static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, 1112static void iwl_mvm_report_wakeup_reasons(struct iwl_mvm *mvm,
1081 struct ieee80211_vif *vif) 1113 struct ieee80211_vif *vif,
1114 struct iwl_wowlan_status *status)
1082{ 1115{
1083 u32 base = mvm->error_event_table; 1116 struct sk_buff *pkt = NULL;
1084 struct error_table_start {
1085 /* cf. struct iwl_error_event_table */
1086 u32 valid;
1087 u32 error_id;
1088 } err_info;
1089 struct cfg80211_wowlan_wakeup wakeup = { 1117 struct cfg80211_wowlan_wakeup wakeup = {
1090 .pattern_idx = -1, 1118 .pattern_idx = -1,
1091 }; 1119 };
1092 struct cfg80211_wowlan_wakeup *wakeup_report = &wakeup; 1120 struct cfg80211_wowlan_wakeup *wakeup_report = &wakeup;
1093 struct iwl_host_cmd cmd = { 1121 u32 reasons = le32_to_cpu(status->wakeup_reasons);
1094 .id = WOWLAN_GET_STATUSES,
1095 .flags = CMD_SYNC | CMD_WANT_SKB,
1096 };
1097 struct iwl_wowlan_status *status;
1098 u32 reasons;
1099 int ret, len;
1100 struct sk_buff *pkt = NULL;
1101
1102 iwl_trans_read_mem_bytes(mvm->trans, base,
1103 &err_info, sizeof(err_info));
1104
1105 if (err_info.valid) {
1106 IWL_INFO(mvm, "error table is valid (%d)\n",
1107 err_info.valid);
1108 if (err_info.error_id == RF_KILL_INDICATOR_FOR_WOWLAN) {
1109 wakeup.rfkill_release = true;
1110 ieee80211_report_wowlan_wakeup(vif, &wakeup,
1111 GFP_KERNEL);
1112 }
1113 return;
1114 }
1115
1116 /* only for tracing for now */
1117 ret = iwl_mvm_send_cmd_pdu(mvm, OFFLOADS_QUERY_CMD, CMD_SYNC, 0, NULL);
1118 if (ret)
1119 IWL_ERR(mvm, "failed to query offload statistics (%d)\n", ret);
1120
1121 ret = iwl_mvm_send_cmd(mvm, &cmd);
1122 if (ret) {
1123 IWL_ERR(mvm, "failed to query status (%d)\n", ret);
1124 return;
1125 }
1126
1127 /* RF-kill already asserted again... */
1128 if (!cmd.resp_pkt)
1129 return;
1130
1131 len = le32_to_cpu(cmd.resp_pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
1132 if (len - sizeof(struct iwl_cmd_header) < sizeof(*status)) {
1133 IWL_ERR(mvm, "Invalid WoWLAN status response!\n");
1134 goto out;
1135 }
1136
1137 status = (void *)cmd.resp_pkt->data;
1138
1139 if (len - sizeof(struct iwl_cmd_header) !=
1140 sizeof(*status) +
1141 ALIGN(le32_to_cpu(status->wake_packet_bufsize), 4)) {
1142 IWL_ERR(mvm, "Invalid WoWLAN status response!\n");
1143 goto out;
1144 }
1145
1146 reasons = le32_to_cpu(status->wakeup_reasons);
1147 1122
1148 if (reasons == IWL_WOWLAN_WAKEUP_BY_NON_WIRELESS) { 1123 if (reasons == IWL_WOWLAN_WAKEUP_BY_NON_WIRELESS) {
1149 wakeup_report = NULL; 1124 wakeup_report = NULL;
@@ -1206,6 +1181,12 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
1206 pktsize -= hdrlen; 1181 pktsize -= hdrlen;
1207 1182
1208 if (ieee80211_has_protected(hdr->frame_control)) { 1183 if (ieee80211_has_protected(hdr->frame_control)) {
1184 /*
1185 * This is unlocked and using gtk_i(c)vlen,
1186 * but since everything is under RTNL still
1187 * that's not really a problem - changing
1188 * it would be difficult.
1189 */
1209 if (is_multicast_ether_addr(hdr->addr1)) { 1190 if (is_multicast_ether_addr(hdr->addr1)) {
1210 ivlen = mvm->gtk_ivlen; 1191 ivlen = mvm->gtk_ivlen;
1211 icvlen += mvm->gtk_icvlen; 1192 icvlen += mvm->gtk_icvlen;
@@ -1256,9 +1237,82 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
1256 report: 1237 report:
1257 ieee80211_report_wowlan_wakeup(vif, wakeup_report, GFP_KERNEL); 1238 ieee80211_report_wowlan_wakeup(vif, wakeup_report, GFP_KERNEL);
1258 kfree_skb(pkt); 1239 kfree_skb(pkt);
1240}
1259 1241
1260 out: 1242/* releases the MVM mutex */
1243static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
1244 struct ieee80211_vif *vif)
1245{
1246 u32 base = mvm->error_event_table;
1247 struct error_table_start {
1248 /* cf. struct iwl_error_event_table */
1249 u32 valid;
1250 u32 error_id;
1251 } err_info;
1252 struct iwl_host_cmd cmd = {
1253 .id = WOWLAN_GET_STATUSES,
1254 .flags = CMD_SYNC | CMD_WANT_SKB,
1255 };
1256 struct iwl_wowlan_status *status;
1257 int ret, len;
1258
1259 iwl_trans_read_mem_bytes(mvm->trans, base,
1260 &err_info, sizeof(err_info));
1261
1262 if (err_info.valid) {
1263 IWL_INFO(mvm, "error table is valid (%d)\n",
1264 err_info.valid);
1265 if (err_info.error_id == RF_KILL_INDICATOR_FOR_WOWLAN) {
1266 struct cfg80211_wowlan_wakeup wakeup = {
1267 .rfkill_release = true,
1268 };
1269 ieee80211_report_wowlan_wakeup(vif, &wakeup,
1270 GFP_KERNEL);
1271 }
1272 goto out_unlock;
1273 }
1274
1275 /* only for tracing for now */
1276 ret = iwl_mvm_send_cmd_pdu(mvm, OFFLOADS_QUERY_CMD, CMD_SYNC, 0, NULL);
1277 if (ret)
1278 IWL_ERR(mvm, "failed to query offload statistics (%d)\n", ret);
1279
1280 ret = iwl_mvm_send_cmd(mvm, &cmd);
1281 if (ret) {
1282 IWL_ERR(mvm, "failed to query status (%d)\n", ret);
1283 goto out_unlock;
1284 }
1285
1286 /* RF-kill already asserted again... */
1287 if (!cmd.resp_pkt)
1288 goto out_unlock;
1289
1290 len = le32_to_cpu(cmd.resp_pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
1291 if (len - sizeof(struct iwl_cmd_header) < sizeof(*status)) {
1292 IWL_ERR(mvm, "Invalid WoWLAN status response!\n");
1293 goto out_free_resp;
1294 }
1295
1296 status = (void *)cmd.resp_pkt->data;
1297
1298 if (len - sizeof(struct iwl_cmd_header) !=
1299 sizeof(*status) +
1300 ALIGN(le32_to_cpu(status->wake_packet_bufsize), 4)) {
1301 IWL_ERR(mvm, "Invalid WoWLAN status response!\n");
1302 goto out_free_resp;
1303 }
1304
1305 /* now we have all the data we need, unlock to avoid mac80211 issues */
1306 mutex_unlock(&mvm->mutex);
1307
1308 iwl_mvm_report_wakeup_reasons(mvm, vif, status);
1309 iwl_free_resp(&cmd);
1310 return;
1311
1312 out_free_resp:
1261 iwl_free_resp(&cmd); 1313 iwl_free_resp(&cmd);
1314 out_unlock:
1315 mutex_unlock(&mvm->mutex);
1262} 1316}
1263 1317
1264static void iwl_mvm_read_d3_sram(struct iwl_mvm *mvm) 1318static void iwl_mvm_read_d3_sram(struct iwl_mvm *mvm)
@@ -1315,10 +1369,13 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
1315 iwl_mvm_read_d3_sram(mvm); 1369 iwl_mvm_read_d3_sram(mvm);
1316 1370
1317 iwl_mvm_query_wakeup_reasons(mvm, vif); 1371 iwl_mvm_query_wakeup_reasons(mvm, vif);
1372 /* has unlocked the mutex, so skip that */
1373 goto out;
1318 1374
1319 out_unlock: 1375 out_unlock:
1320 mutex_unlock(&mvm->mutex); 1376 mutex_unlock(&mvm->mutex);
1321 1377
1378 out:
1322 if (!test && vif) 1379 if (!test && vif)
1323 ieee80211_resume_disconnect(vif); 1380 ieee80211_resume_disconnect(vif);
1324 1381
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
index c24a744910ac..aac81b8984b0 100644
--- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
@@ -352,6 +352,10 @@ static void iwl_dbgfs_update_pm(struct iwl_mvm *mvm,
352 IWL_DEBUG_POWER(mvm, "lprx_rssi_threshold=%d\n", val); 352 IWL_DEBUG_POWER(mvm, "lprx_rssi_threshold=%d\n", val);
353 dbgfs_pm->lprx_rssi_threshold = val; 353 dbgfs_pm->lprx_rssi_threshold = val;
354 break; 354 break;
355 case MVM_DEBUGFS_PM_SNOOZE_ENABLE:
356 IWL_DEBUG_POWER(mvm, "snooze_enable=%d\n", val);
357 dbgfs_pm->snooze_ena = val;
358 break;
355 } 359 }
356} 360}
357 361
@@ -405,6 +409,10 @@ static ssize_t iwl_dbgfs_pm_params_write(struct file *file,
405 POWER_LPRX_RSSI_THRESHOLD_MIN) 409 POWER_LPRX_RSSI_THRESHOLD_MIN)
406 return -EINVAL; 410 return -EINVAL;
407 param = MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD; 411 param = MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD;
412 } else if (!strncmp("snooze_enable=", buf, 14)) {
413 if (sscanf(buf + 14, "%d", &val) != 1)
414 return -EINVAL;
415 param = MVM_DEBUGFS_PM_SNOOZE_ENABLE;
408 } else { 416 } else {
409 return -EINVAL; 417 return -EINVAL;
410 } 418 }
@@ -424,40 +432,11 @@ static ssize_t iwl_dbgfs_pm_params_read(struct file *file,
424 struct ieee80211_vif *vif = file->private_data; 432 struct ieee80211_vif *vif = file->private_data;
425 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 433 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
426 struct iwl_mvm *mvm = mvmvif->dbgfs_data; 434 struct iwl_mvm *mvm = mvmvif->dbgfs_data;
427 struct iwl_powertable_cmd cmd = {}; 435 char buf[512];
428 char buf[256];
429 int bufsz = sizeof(buf); 436 int bufsz = sizeof(buf);
430 int pos = 0; 437 int pos;
431 438
432 iwl_mvm_power_build_cmd(mvm, vif, &cmd); 439 pos = iwl_mvm_power_dbgfs_read(mvm, vif, buf, bufsz);
433
434 pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off = %d\n",
435 (cmd.flags &
436 cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK)) ?
437 0 : 1);
438 pos += scnprintf(buf+pos, bufsz-pos, "skip_dtim_periods = %d\n",
439 le32_to_cpu(cmd.skip_dtim_periods));
440 pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n",
441 iwlmvm_mod_params.power_scheme);
442 pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n",
443 le16_to_cpu(cmd.flags));
444 pos += scnprintf(buf+pos, bufsz-pos, "keep_alive = %d\n",
445 cmd.keep_alive_seconds);
446
447 if (cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) {
448 pos += scnprintf(buf+pos, bufsz-pos, "skip_over_dtim = %d\n",
449 (cmd.flags &
450 cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) ?
451 1 : 0);
452 pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout = %d\n",
453 le32_to_cpu(cmd.rx_data_timeout));
454 pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout = %d\n",
455 le32_to_cpu(cmd.tx_data_timeout));
456 if (cmd.flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
457 pos += scnprintf(buf+pos, bufsz-pos,
458 "lprx_rssi_threshold = %d\n",
459 le32_to_cpu(cmd.lprx_rssi_threshold));
460 }
461 440
462 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 441 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
463} 442}
@@ -621,25 +600,160 @@ static ssize_t iwl_dbgfs_bt_notif_read(struct file *file, char __user *user_buf,
621} 600}
622#undef BT_MBOX_PRINT 601#undef BT_MBOX_PRINT
623 602
603#define PRINT_STATS_LE32(_str, _val) \
604 pos += scnprintf(buf + pos, bufsz - pos, \
605 fmt_table, _str, \
606 le32_to_cpu(_val))
607
608static ssize_t iwl_dbgfs_fw_rx_stats_read(struct file *file,
609 char __user *user_buf, size_t count,
610 loff_t *ppos)
611{
612 struct iwl_mvm *mvm = file->private_data;
613 static const char *fmt_table = "\t%-30s %10u\n";
614 static const char *fmt_header = "%-32s\n";
615 int pos = 0;
616 char *buf;
617 int ret;
618 int bufsz = sizeof(struct mvm_statistics_rx_phy) * 20 +
619 sizeof(struct mvm_statistics_rx_non_phy) * 10 +
620 sizeof(struct mvm_statistics_rx_ht_phy) * 10 + 200;
621 struct mvm_statistics_rx_phy *ofdm;
622 struct mvm_statistics_rx_phy *cck;
623 struct mvm_statistics_rx_non_phy *general;
624 struct mvm_statistics_rx_ht_phy *ht;
625
626 buf = kzalloc(bufsz, GFP_KERNEL);
627 if (!buf)
628 return -ENOMEM;
629
630 mutex_lock(&mvm->mutex);
631
632 ofdm = &mvm->rx_stats.ofdm;
633 cck = &mvm->rx_stats.cck;
634 general = &mvm->rx_stats.general;
635 ht = &mvm->rx_stats.ofdm_ht;
636
637 pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
638 "Statistics_Rx - OFDM");
639 PRINT_STATS_LE32("ina_cnt", ofdm->ina_cnt);
640 PRINT_STATS_LE32("fina_cnt", ofdm->fina_cnt);
641 PRINT_STATS_LE32("plcp_err", ofdm->plcp_err);
642 PRINT_STATS_LE32("crc32_err", ofdm->crc32_err);
643 PRINT_STATS_LE32("overrun_err", ofdm->overrun_err);
644 PRINT_STATS_LE32("early_overrun_err", ofdm->early_overrun_err);
645 PRINT_STATS_LE32("crc32_good", ofdm->crc32_good);
646 PRINT_STATS_LE32("false_alarm_cnt", ofdm->false_alarm_cnt);
647 PRINT_STATS_LE32("fina_sync_err_cnt", ofdm->fina_sync_err_cnt);
648 PRINT_STATS_LE32("sfd_timeout", ofdm->sfd_timeout);
649 PRINT_STATS_LE32("fina_timeout", ofdm->fina_timeout);
650 PRINT_STATS_LE32("unresponded_rts", ofdm->unresponded_rts);
651 PRINT_STATS_LE32("rxe_frame_lmt_overrun",
652 ofdm->rxe_frame_limit_overrun);
653 PRINT_STATS_LE32("sent_ack_cnt", ofdm->sent_ack_cnt);
654 PRINT_STATS_LE32("sent_cts_cnt", ofdm->sent_cts_cnt);
655 PRINT_STATS_LE32("sent_ba_rsp_cnt", ofdm->sent_ba_rsp_cnt);
656 PRINT_STATS_LE32("dsp_self_kill", ofdm->dsp_self_kill);
657 PRINT_STATS_LE32("mh_format_err", ofdm->mh_format_err);
658 PRINT_STATS_LE32("re_acq_main_rssi_sum", ofdm->re_acq_main_rssi_sum);
659 PRINT_STATS_LE32("reserved", ofdm->reserved);
660
661 pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
662 "Statistics_Rx - CCK");
663 PRINT_STATS_LE32("ina_cnt", cck->ina_cnt);
664 PRINT_STATS_LE32("fina_cnt", cck->fina_cnt);
665 PRINT_STATS_LE32("plcp_err", cck->plcp_err);
666 PRINT_STATS_LE32("crc32_err", cck->crc32_err);
667 PRINT_STATS_LE32("overrun_err", cck->overrun_err);
668 PRINT_STATS_LE32("early_overrun_err", cck->early_overrun_err);
669 PRINT_STATS_LE32("crc32_good", cck->crc32_good);
670 PRINT_STATS_LE32("false_alarm_cnt", cck->false_alarm_cnt);
671 PRINT_STATS_LE32("fina_sync_err_cnt", cck->fina_sync_err_cnt);
672 PRINT_STATS_LE32("sfd_timeout", cck->sfd_timeout);
673 PRINT_STATS_LE32("fina_timeout", cck->fina_timeout);
674 PRINT_STATS_LE32("unresponded_rts", cck->unresponded_rts);
675 PRINT_STATS_LE32("rxe_frame_lmt_overrun",
676 cck->rxe_frame_limit_overrun);
677 PRINT_STATS_LE32("sent_ack_cnt", cck->sent_ack_cnt);
678 PRINT_STATS_LE32("sent_cts_cnt", cck->sent_cts_cnt);
679 PRINT_STATS_LE32("sent_ba_rsp_cnt", cck->sent_ba_rsp_cnt);
680 PRINT_STATS_LE32("dsp_self_kill", cck->dsp_self_kill);
681 PRINT_STATS_LE32("mh_format_err", cck->mh_format_err);
682 PRINT_STATS_LE32("re_acq_main_rssi_sum", cck->re_acq_main_rssi_sum);
683 PRINT_STATS_LE32("reserved", cck->reserved);
684
685 pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
686 "Statistics_Rx - GENERAL");
687 PRINT_STATS_LE32("bogus_cts", general->bogus_cts);
688 PRINT_STATS_LE32("bogus_ack", general->bogus_ack);
689 PRINT_STATS_LE32("non_bssid_frames", general->non_bssid_frames);
690 PRINT_STATS_LE32("filtered_frames", general->filtered_frames);
691 PRINT_STATS_LE32("non_channel_beacons", general->non_channel_beacons);
692 PRINT_STATS_LE32("channel_beacons", general->channel_beacons);
693 PRINT_STATS_LE32("num_missed_bcon", general->num_missed_bcon);
694 PRINT_STATS_LE32("adc_rx_saturation_time",
695 general->adc_rx_saturation_time);
696 PRINT_STATS_LE32("ina_detection_search_time",
697 general->ina_detection_search_time);
698 PRINT_STATS_LE32("beacon_silence_rssi_a",
699 general->beacon_silence_rssi_a);
700 PRINT_STATS_LE32("beacon_silence_rssi_b",
701 general->beacon_silence_rssi_b);
702 PRINT_STATS_LE32("beacon_silence_rssi_c",
703 general->beacon_silence_rssi_c);
704 PRINT_STATS_LE32("interference_data_flag",
705 general->interference_data_flag);
706 PRINT_STATS_LE32("channel_load", general->channel_load);
707 PRINT_STATS_LE32("dsp_false_alarms", general->dsp_false_alarms);
708 PRINT_STATS_LE32("beacon_rssi_a", general->beacon_rssi_a);
709 PRINT_STATS_LE32("beacon_rssi_b", general->beacon_rssi_b);
710 PRINT_STATS_LE32("beacon_rssi_c", general->beacon_rssi_c);
711 PRINT_STATS_LE32("beacon_energy_a", general->beacon_energy_a);
712 PRINT_STATS_LE32("beacon_energy_b", general->beacon_energy_b);
713 PRINT_STATS_LE32("beacon_energy_c", general->beacon_energy_c);
714 PRINT_STATS_LE32("num_bt_kills", general->num_bt_kills);
715 PRINT_STATS_LE32("directed_data_mpdu", general->directed_data_mpdu);
716
717 pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
718 "Statistics_Rx - HT");
719 PRINT_STATS_LE32("plcp_err", ht->plcp_err);
720 PRINT_STATS_LE32("overrun_err", ht->overrun_err);
721 PRINT_STATS_LE32("early_overrun_err", ht->early_overrun_err);
722 PRINT_STATS_LE32("crc32_good", ht->crc32_good);
723 PRINT_STATS_LE32("crc32_err", ht->crc32_err);
724 PRINT_STATS_LE32("mh_format_err", ht->mh_format_err);
725 PRINT_STATS_LE32("agg_crc32_good", ht->agg_crc32_good);
726 PRINT_STATS_LE32("agg_mpdu_cnt", ht->agg_mpdu_cnt);
727 PRINT_STATS_LE32("agg_cnt", ht->agg_cnt);
728 PRINT_STATS_LE32("unsupport_mcs", ht->unsupport_mcs);
729
730 mutex_unlock(&mvm->mutex);
731
732 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
733 kfree(buf);
734
735 return ret;
736}
737#undef PRINT_STAT_LE32
738
624static ssize_t iwl_dbgfs_fw_restart_write(struct file *file, 739static ssize_t iwl_dbgfs_fw_restart_write(struct file *file,
625 const char __user *user_buf, 740 const char __user *user_buf,
626 size_t count, loff_t *ppos) 741 size_t count, loff_t *ppos)
627{ 742{
628 struct iwl_mvm *mvm = file->private_data; 743 struct iwl_mvm *mvm = file->private_data;
629 bool restart_fw = iwlwifi_mod_params.restart_fw;
630 int ret; 744 int ret;
631 745
632 iwlwifi_mod_params.restart_fw = true;
633
634 mutex_lock(&mvm->mutex); 746 mutex_lock(&mvm->mutex);
635 747
748 /* allow one more restart that we're provoking here */
749 if (mvm->restart_fw >= 0)
750 mvm->restart_fw++;
751
636 /* take the return value to make compiler happy - it will fail anyway */ 752 /* take the return value to make compiler happy - it will fail anyway */
637 ret = iwl_mvm_send_cmd_pdu(mvm, REPLY_ERROR, CMD_SYNC, 0, NULL); 753 ret = iwl_mvm_send_cmd_pdu(mvm, REPLY_ERROR, CMD_SYNC, 0, NULL);
638 754
639 mutex_unlock(&mvm->mutex); 755 mutex_unlock(&mvm->mutex);
640 756
641 iwlwifi_mod_params.restart_fw = restart_fw;
642
643 return count; 757 return count;
644} 758}
645 759
@@ -661,8 +775,14 @@ static void iwl_dbgfs_update_bf(struct ieee80211_vif *vif,
661 case MVM_DEBUGFS_BF_ROAMING_STATE: 775 case MVM_DEBUGFS_BF_ROAMING_STATE:
662 dbgfs_bf->bf_roaming_state = value; 776 dbgfs_bf->bf_roaming_state = value;
663 break; 777 break;
664 case MVM_DEBUGFS_BF_TEMPERATURE_DELTA: 778 case MVM_DEBUGFS_BF_TEMP_THRESHOLD:
665 dbgfs_bf->bf_temperature_delta = value; 779 dbgfs_bf->bf_temp_threshold = value;
780 break;
781 case MVM_DEBUGFS_BF_TEMP_FAST_FILTER:
782 dbgfs_bf->bf_temp_fast_filter = value;
783 break;
784 case MVM_DEBUGFS_BF_TEMP_SLOW_FILTER:
785 dbgfs_bf->bf_temp_slow_filter = value;
666 break; 786 break;
667 case MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER: 787 case MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER:
668 dbgfs_bf->bf_enable_beacon_filter = value; 788 dbgfs_bf->bf_enable_beacon_filter = value;
@@ -721,13 +841,27 @@ static ssize_t iwl_dbgfs_bf_params_write(struct file *file,
721 value > IWL_BF_ROAMING_STATE_MAX) 841 value > IWL_BF_ROAMING_STATE_MAX)
722 return -EINVAL; 842 return -EINVAL;
723 param = MVM_DEBUGFS_BF_ROAMING_STATE; 843 param = MVM_DEBUGFS_BF_ROAMING_STATE;
724 } else if (!strncmp("bf_temperature_delta=", buf, 21)) { 844 } else if (!strncmp("bf_temp_threshold=", buf, 18)) {
725 if (sscanf(buf+21, "%d", &value) != 1) 845 if (sscanf(buf+18, "%d", &value) != 1)
846 return -EINVAL;
847 if (value < IWL_BF_TEMP_THRESHOLD_MIN ||
848 value > IWL_BF_TEMP_THRESHOLD_MAX)
726 return -EINVAL; 849 return -EINVAL;
727 if (value < IWL_BF_TEMPERATURE_DELTA_MIN || 850 param = MVM_DEBUGFS_BF_TEMP_THRESHOLD;
728 value > IWL_BF_TEMPERATURE_DELTA_MAX) 851 } else if (!strncmp("bf_temp_fast_filter=", buf, 20)) {
852 if (sscanf(buf+20, "%d", &value) != 1)
729 return -EINVAL; 853 return -EINVAL;
730 param = MVM_DEBUGFS_BF_TEMPERATURE_DELTA; 854 if (value < IWL_BF_TEMP_FAST_FILTER_MIN ||
855 value > IWL_BF_TEMP_FAST_FILTER_MAX)
856 return -EINVAL;
857 param = MVM_DEBUGFS_BF_TEMP_FAST_FILTER;
858 } else if (!strncmp("bf_temp_slow_filter=", buf, 20)) {
859 if (sscanf(buf+20, "%d", &value) != 1)
860 return -EINVAL;
861 if (value < IWL_BF_TEMP_SLOW_FILTER_MIN ||
862 value > IWL_BF_TEMP_SLOW_FILTER_MAX)
863 return -EINVAL;
864 param = MVM_DEBUGFS_BF_TEMP_SLOW_FILTER;
731 } else if (!strncmp("bf_enable_beacon_filter=", buf, 24)) { 865 } else if (!strncmp("bf_enable_beacon_filter=", buf, 24)) {
732 if (sscanf(buf+24, "%d", &value) != 1) 866 if (sscanf(buf+24, "%d", &value) != 1)
733 return -EINVAL; 867 return -EINVAL;
@@ -769,10 +903,7 @@ static ssize_t iwl_dbgfs_bf_params_write(struct file *file,
769 if (param == MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER && !value) { 903 if (param == MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER && !value) {
770 ret = iwl_mvm_disable_beacon_filter(mvm, vif); 904 ret = iwl_mvm_disable_beacon_filter(mvm, vif);
771 } else { 905 } else {
772 if (mvmvif->bf_enabled) 906 ret = iwl_mvm_enable_beacon_filter(mvm, vif);
773 ret = iwl_mvm_enable_beacon_filter(mvm, vif);
774 else
775 ret = iwl_mvm_disable_beacon_filter(mvm, vif);
776 } 907 }
777 mutex_unlock(&mvm->mutex); 908 mutex_unlock(&mvm->mutex);
778 909
@@ -789,41 +920,41 @@ static ssize_t iwl_dbgfs_bf_params_read(struct file *file,
789 int pos = 0; 920 int pos = 0;
790 const size_t bufsz = sizeof(buf); 921 const size_t bufsz = sizeof(buf);
791 struct iwl_beacon_filter_cmd cmd = { 922 struct iwl_beacon_filter_cmd cmd = {
792 .bf_energy_delta = IWL_BF_ENERGY_DELTA_DEFAULT, 923 IWL_BF_CMD_CONFIG_DEFAULTS,
793 .bf_roaming_energy_delta = IWL_BF_ROAMING_ENERGY_DELTA_DEFAULT, 924 .bf_enable_beacon_filter =
794 .bf_roaming_state = IWL_BF_ROAMING_STATE_DEFAULT, 925 cpu_to_le32(IWL_BF_ENABLE_BEACON_FILTER_DEFAULT),
795 .bf_temperature_delta = IWL_BF_TEMPERATURE_DELTA_DEFAULT, 926 .ba_enable_beacon_abort =
796 .bf_enable_beacon_filter = IWL_BF_ENABLE_BEACON_FILTER_DEFAULT, 927 cpu_to_le32(IWL_BA_ENABLE_BEACON_ABORT_DEFAULT),
797 .bf_debug_flag = IWL_BF_DEBUG_FLAG_DEFAULT,
798 .bf_escape_timer = cpu_to_le32(IWL_BF_ESCAPE_TIMER_DEFAULT),
799 .ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_DEFAULT),
800 .ba_enable_beacon_abort = IWL_BA_ENABLE_BEACON_ABORT_DEFAULT,
801 }; 928 };
802 929
803 iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd); 930 iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd);
804 if (mvmvif->bf_enabled) 931 if (mvmvif->bf_data.bf_enabled)
805 cmd.bf_enable_beacon_filter = 1; 932 cmd.bf_enable_beacon_filter = cpu_to_le32(1);
806 else 933 else
807 cmd.bf_enable_beacon_filter = 0; 934 cmd.bf_enable_beacon_filter = 0;
808 935
809 pos += scnprintf(buf+pos, bufsz-pos, "bf_energy_delta = %d\n", 936 pos += scnprintf(buf+pos, bufsz-pos, "bf_energy_delta = %d\n",
810 cmd.bf_energy_delta); 937 le32_to_cpu(cmd.bf_energy_delta));
811 pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_energy_delta = %d\n", 938 pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_energy_delta = %d\n",
812 cmd.bf_roaming_energy_delta); 939 le32_to_cpu(cmd.bf_roaming_energy_delta));
813 pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_state = %d\n", 940 pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_state = %d\n",
814 cmd.bf_roaming_state); 941 le32_to_cpu(cmd.bf_roaming_state));
815 pos += scnprintf(buf+pos, bufsz-pos, "bf_temperature_delta = %d\n", 942 pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_threshold = %d\n",
816 cmd.bf_temperature_delta); 943 le32_to_cpu(cmd.bf_temp_threshold));
944 pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_fast_filter = %d\n",
945 le32_to_cpu(cmd.bf_temp_fast_filter));
946 pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_slow_filter = %d\n",
947 le32_to_cpu(cmd.bf_temp_slow_filter));
817 pos += scnprintf(buf+pos, bufsz-pos, "bf_enable_beacon_filter = %d\n", 948 pos += scnprintf(buf+pos, bufsz-pos, "bf_enable_beacon_filter = %d\n",
818 cmd.bf_enable_beacon_filter); 949 le32_to_cpu(cmd.bf_enable_beacon_filter));
819 pos += scnprintf(buf+pos, bufsz-pos, "bf_debug_flag = %d\n", 950 pos += scnprintf(buf+pos, bufsz-pos, "bf_debug_flag = %d\n",
820 cmd.bf_debug_flag); 951 le32_to_cpu(cmd.bf_debug_flag));
821 pos += scnprintf(buf+pos, bufsz-pos, "bf_escape_timer = %d\n", 952 pos += scnprintf(buf+pos, bufsz-pos, "bf_escape_timer = %d\n",
822 cmd.bf_escape_timer); 953 le32_to_cpu(cmd.bf_escape_timer));
823 pos += scnprintf(buf+pos, bufsz-pos, "ba_escape_timer = %d\n", 954 pos += scnprintf(buf+pos, bufsz-pos, "ba_escape_timer = %d\n",
824 cmd.ba_escape_timer); 955 le32_to_cpu(cmd.ba_escape_timer));
825 pos += scnprintf(buf+pos, bufsz-pos, "ba_enable_beacon_abort = %d\n", 956 pos += scnprintf(buf+pos, bufsz-pos, "ba_enable_beacon_abort = %d\n",
826 cmd.ba_enable_beacon_abort); 957 le32_to_cpu(cmd.ba_enable_beacon_abort));
827 958
828 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 959 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
829} 960}
@@ -934,6 +1065,7 @@ MVM_DEBUGFS_READ_FILE_OPS(stations);
934MVM_DEBUGFS_READ_FILE_OPS(bt_notif); 1065MVM_DEBUGFS_READ_FILE_OPS(bt_notif);
935MVM_DEBUGFS_WRITE_FILE_OPS(power_down_allow); 1066MVM_DEBUGFS_WRITE_FILE_OPS(power_down_allow);
936MVM_DEBUGFS_WRITE_FILE_OPS(power_down_d3_allow); 1067MVM_DEBUGFS_WRITE_FILE_OPS(power_down_d3_allow);
1068MVM_DEBUGFS_READ_FILE_OPS(fw_rx_stats);
937MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart); 1069MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart);
938#ifdef CONFIG_PM_SLEEP 1070#ifdef CONFIG_PM_SLEEP
939MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram); 1071MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram);
@@ -957,6 +1089,7 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
957 MVM_DEBUGFS_ADD_FILE(bt_notif, dbgfs_dir, S_IRUSR); 1089 MVM_DEBUGFS_ADD_FILE(bt_notif, dbgfs_dir, S_IRUSR);
958 MVM_DEBUGFS_ADD_FILE(power_down_allow, mvm->debugfs_dir, S_IWUSR); 1090 MVM_DEBUGFS_ADD_FILE(power_down_allow, mvm->debugfs_dir, S_IWUSR);
959 MVM_DEBUGFS_ADD_FILE(power_down_d3_allow, mvm->debugfs_dir, S_IWUSR); 1091 MVM_DEBUGFS_ADD_FILE(power_down_d3_allow, mvm->debugfs_dir, S_IWUSR);
1092 MVM_DEBUGFS_ADD_FILE(fw_rx_stats, mvm->debugfs_dir, S_IRUSR);
960 MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR); 1093 MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR);
961#ifdef CONFIG_PM_SLEEP 1094#ifdef CONFIG_PM_SLEEP
962 MVM_DEBUGFS_ADD_FILE(d3_sram, mvm->debugfs_dir, S_IRUSR | S_IWUSR); 1095 MVM_DEBUGFS_ADD_FILE(d3_sram, mvm->debugfs_dir, S_IRUSR | S_IWUSR);
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h
index 6f8b2c16ae17..df72fcdf8170 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h
@@ -98,34 +98,63 @@ enum iwl_proto_offloads {
98 IWL_D3_PROTO_OFFLOAD_NS = BIT(1), 98 IWL_D3_PROTO_OFFLOAD_NS = BIT(1),
99}; 99};
100 100
101#define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS 2 101#define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V1 2
102#define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V2 6
103#define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_MAX 6
102 104
103/** 105/**
104 * struct iwl_proto_offload_cmd - ARP/NS offload configuration 106 * struct iwl_proto_offload_cmd_common - ARP/NS offload common part
105 * @enabled: enable flags 107 * @enabled: enable flags
106 * @remote_ipv4_addr: remote address to answer to (or zero if all) 108 * @remote_ipv4_addr: remote address to answer to (or zero if all)
107 * @host_ipv4_addr: our IPv4 address to respond to queries for 109 * @host_ipv4_addr: our IPv4 address to respond to queries for
108 * @arp_mac_addr: our MAC address for ARP responses 110 * @arp_mac_addr: our MAC address for ARP responses
109 * @remote_ipv6_addr: remote address to answer to (or zero if all) 111 * @reserved: unused
110 * @solicited_node_ipv6_addr: broken -- solicited node address exists
111 * for each target address
112 * @target_ipv6_addr: our target addresses
113 * @ndp_mac_addr: neighbor soliciation response MAC address
114 */ 112 */
115struct iwl_proto_offload_cmd { 113struct iwl_proto_offload_cmd_common {
116 __le32 enabled; 114 __le32 enabled;
117 __be32 remote_ipv4_addr; 115 __be32 remote_ipv4_addr;
118 __be32 host_ipv4_addr; 116 __be32 host_ipv4_addr;
119 u8 arp_mac_addr[ETH_ALEN]; 117 u8 arp_mac_addr[ETH_ALEN];
120 __le16 reserved1; 118 __le16 reserved;
119} __packed;
121 120
121/**
122 * struct iwl_proto_offload_cmd_v1 - ARP/NS offload configuration
123 * @common: common/IPv4 configuration
124 * @remote_ipv6_addr: remote address to answer to (or zero if all)
125 * @solicited_node_ipv6_addr: broken -- solicited node address exists
126 * for each target address
127 * @target_ipv6_addr: our target addresses
128 * @ndp_mac_addr: neighbor soliciation response MAC address
129 */
130struct iwl_proto_offload_cmd_v1 {
131 struct iwl_proto_offload_cmd_common common;
122 u8 remote_ipv6_addr[16]; 132 u8 remote_ipv6_addr[16];
123 u8 solicited_node_ipv6_addr[16]; 133 u8 solicited_node_ipv6_addr[16];
124 u8 target_ipv6_addr[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS][16]; 134 u8 target_ipv6_addr[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V1][16];
125 u8 ndp_mac_addr[ETH_ALEN]; 135 u8 ndp_mac_addr[ETH_ALEN];
126 __le16 reserved2; 136 __le16 reserved2;
127} __packed; /* PROT_OFFLOAD_CONFIG_CMD_DB_S_VER_1 */ 137} __packed; /* PROT_OFFLOAD_CONFIG_CMD_DB_S_VER_1 */
128 138
139/**
140 * struct iwl_proto_offload_cmd_v2 - ARP/NS offload configuration
141 * @common: common/IPv4 configuration
142 * @remote_ipv6_addr: remote address to answer to (or zero if all)
143 * @solicited_node_ipv6_addr: broken -- solicited node address exists
144 * for each target address
145 * @target_ipv6_addr: our target addresses
146 * @ndp_mac_addr: neighbor soliciation response MAC address
147 */
148struct iwl_proto_offload_cmd_v2 {
149 struct iwl_proto_offload_cmd_common common;
150 u8 remote_ipv6_addr[16];
151 u8 solicited_node_ipv6_addr[16];
152 u8 target_ipv6_addr[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V2][16];
153 u8 ndp_mac_addr[ETH_ALEN];
154 u8 numValidIPv6Addresses;
155 u8 reserved2[3];
156} __packed; /* PROT_OFFLOAD_CONFIG_CMD_DB_S_VER_2 */
157
129 158
130/* 159/*
131 * WOWLAN_PATTERNS 160 * WOWLAN_PATTERNS
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
index a6da359a80c3..8e7ab41079ca 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
@@ -79,6 +79,10 @@
79 * '1' Driver enables PM (use rest of parameters) 79 * '1' Driver enables PM (use rest of parameters)
80 * @POWER_FLAGS_SKIP_OVER_DTIM_MSK: '0' PM have to walk up every DTIM, 80 * @POWER_FLAGS_SKIP_OVER_DTIM_MSK: '0' PM have to walk up every DTIM,
81 * '1' PM could sleep over DTIM till listen Interval. 81 * '1' PM could sleep over DTIM till listen Interval.
82 * @POWER_FLAGS_SNOOZE_ENA_MSK: Enable snoozing only if uAPSD is enabled and all
83 * access categories are both delivery and trigger enabled.
84 * @POWER_FLAGS_BT_SCO_ENA: Enable BT SCO coex only if uAPSD and
85 * PBW Snoozing enabled
82 * @POWER_FLAGS_ADVANCE_PM_ENA_MSK: Advanced PM (uAPSD) enable mask 86 * @POWER_FLAGS_ADVANCE_PM_ENA_MSK: Advanced PM (uAPSD) enable mask
83 * @POWER_FLAGS_LPRX_ENA_MSK: Low Power RX enable. 87 * @POWER_FLAGS_LPRX_ENA_MSK: Low Power RX enable.
84*/ 88*/
@@ -86,6 +90,8 @@ enum iwl_power_flags {
86 POWER_FLAGS_POWER_SAVE_ENA_MSK = BIT(0), 90 POWER_FLAGS_POWER_SAVE_ENA_MSK = BIT(0),
87 POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK = BIT(1), 91 POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK = BIT(1),
88 POWER_FLAGS_SKIP_OVER_DTIM_MSK = BIT(2), 92 POWER_FLAGS_SKIP_OVER_DTIM_MSK = BIT(2),
93 POWER_FLAGS_SNOOZE_ENA_MSK = BIT(5),
94 POWER_FLAGS_BT_SCO_ENA = BIT(8),
89 POWER_FLAGS_ADVANCE_PM_ENA_MSK = BIT(9), 95 POWER_FLAGS_ADVANCE_PM_ENA_MSK = BIT(9),
90 POWER_FLAGS_LPRX_ENA_MSK = BIT(11), 96 POWER_FLAGS_LPRX_ENA_MSK = BIT(11),
91}; 97};
@@ -93,7 +99,8 @@ enum iwl_power_flags {
93#define IWL_POWER_VEC_SIZE 5 99#define IWL_POWER_VEC_SIZE 5
94 100
95/** 101/**
96 * struct iwl_powertable_cmd - Power Table Command 102 * struct iwl_powertable_cmd - legacy power command. Beside old API support this
103 * is used also with a new power API for device wide power settings.
97 * POWER_TABLE_CMD = 0x77 (command, has simple generic response) 104 * POWER_TABLE_CMD = 0x77 (command, has simple generic response)
98 * 105 *
99 * @flags: Power table command flags from POWER_FLAGS_* 106 * @flags: Power table command flags from POWER_FLAGS_*
@@ -125,6 +132,76 @@ struct iwl_powertable_cmd {
125} __packed; 132} __packed;
126 133
127/** 134/**
135 * struct iwl_mac_power_cmd - New power command containing uAPSD support
136 * MAC_PM_POWER_TABLE = 0xA9 (command, has simple generic response)
137 * @id_and_color: MAC contex identifier
138 * @flags: Power table command flags from POWER_FLAGS_*
139 * @keep_alive_seconds: Keep alive period in seconds. Default - 25 sec.
140 * Minimum allowed:- 3 * DTIM. Keep alive period must be
141 * set regardless of power scheme or current power state.
142 * FW use this value also when PM is disabled.
143 * @rx_data_timeout: Minimum time (usec) from last Rx packet for AM to
144 * PSM transition - legacy PM
145 * @tx_data_timeout: Minimum time (usec) from last Tx packet for AM to
146 * PSM transition - legacy PM
147 * @sleep_interval: not in use
148 * @skip_dtim_periods: Number of DTIM periods to skip if Skip over DTIM flag
149 * is set. For example, if it is required to skip over
150 * one DTIM, this value need to be set to 2 (DTIM periods).
151 * @rx_data_timeout_uapsd: Minimum time (usec) from last Rx packet for AM to
152 * PSM transition - uAPSD
153 * @tx_data_timeout_uapsd: Minimum time (usec) from last Tx packet for AM to
154 * PSM transition - uAPSD
155 * @lprx_rssi_threshold: Signal strength up to which LP RX can be enabled.
156 * Default: 80dbm
157 * @num_skip_dtim: Number of DTIMs to skip if Skip over DTIM flag is set
158 * @snooze_interval: Maximum time between attempts to retrieve buffered data
159 * from the AP [msec]
160 * @snooze_window: A window of time in which PBW snoozing insures that all
161 * packets received. It is also the minimum time from last
162 * received unicast RX packet, before client stops snoozing
163 * for data. [msec]
164 * @snooze_step: TBD
165 * @qndp_tid: TID client shall use for uAPSD QNDP triggers
166 * @uapsd_ac_flags: Set trigger-enabled and delivery-enabled indication for
167 * each corresponding AC.
168 * Use IEEE80211_WMM_IE_STA_QOSINFO_AC* for correct values.
169 * @uapsd_max_sp: Use IEEE80211_WMM_IE_STA_QOSINFO_SP_* for correct
170 * values.
171 * @heavy_tx_thld_packets: TX threshold measured in number of packets
172 * @heavy_rx_thld_packets: RX threshold measured in number of packets
173 * @heavy_tx_thld_percentage: TX threshold measured in load's percentage
174 * @heavy_rx_thld_percentage: RX threshold measured in load's percentage
175 * @limited_ps_threshold:
176*/
177struct iwl_mac_power_cmd {
178 /* CONTEXT_DESC_API_T_VER_1 */
179 __le32 id_and_color;
180
181 /* CLIENT_PM_POWER_TABLE_S_VER_1 */
182 __le16 flags;
183 __le16 keep_alive_seconds;
184 __le32 rx_data_timeout;
185 __le32 tx_data_timeout;
186 __le32 rx_data_timeout_uapsd;
187 __le32 tx_data_timeout_uapsd;
188 u8 lprx_rssi_threshold;
189 u8 skip_dtim_periods;
190 __le16 snooze_interval;
191 __le16 snooze_window;
192 u8 snooze_step;
193 u8 qndp_tid;
194 u8 uapsd_ac_flags;
195 u8 uapsd_max_sp;
196 u8 heavy_tx_thld_packets;
197 u8 heavy_rx_thld_packets;
198 u8 heavy_tx_thld_percentage;
199 u8 heavy_rx_thld_percentage;
200 u8 limited_ps_threshold;
201 u8 reserved;
202} __packed;
203
204/**
128 * struct iwl_beacon_filter_cmd 205 * struct iwl_beacon_filter_cmd
129 * REPLY_BEACON_FILTERING_CMD = 0xd2 (command) 206 * REPLY_BEACON_FILTERING_CMD = 0xd2 (command)
130 * @id_and_color: MAC contex identifier 207 * @id_and_color: MAC contex identifier
@@ -143,11 +220,21 @@ struct iwl_powertable_cmd {
143 * calculated for current beacon is less than the threshold, use 220 * calculated for current beacon is less than the threshold, use
144 * Roaming Energy Delta Threshold, otherwise use normal Energy Delta 221 * Roaming Energy Delta Threshold, otherwise use normal Energy Delta
145 * Threshold. Typical energy threshold is -72dBm. 222 * Threshold. Typical energy threshold is -72dBm.
146 * @bf_temperature_delta: Send Beacon to driver if delta in temperature values 223 * @bf_temp_threshold: This threshold determines the type of temperature
147 * calculated for this and the last passed beacon is greater than this 224 * filtering (Slow or Fast) that is selected (Units are in Celsuis):
148 * threshold. Zero value means that the temperature changeis ignored for 225 * If the current temperature is above this threshold - Fast filter
226 * will be used, If the current temperature is below this threshold -
227 * Slow filter will be used.
228 * @bf_temp_fast_filter: Send Beacon to driver if delta in temperature values
229 * calculated for this and the last passed beacon is greater than this
230 * threshold. Zero value means that the temperature change is ignored for
149 * beacon filtering; beacons will not be forced to be sent to driver 231 * beacon filtering; beacons will not be forced to be sent to driver
150 * regardless of whether its temerature has been changed. 232 * regardless of whether its temerature has been changed.
233 * @bf_temp_slow_filter: Send Beacon to driver if delta in temperature values
234 * calculated for this and the last passed beacon is greater than this
235 * threshold. Zero value means that the temperature change is ignored for
236 * beacon filtering; beacons will not be forced to be sent to driver
237 * regardless of whether its temerature has been changed.
151 * @bf_enable_beacon_filter: 1, beacon filtering is enabled; 0, disabled. 238 * @bf_enable_beacon_filter: 1, beacon filtering is enabled; 0, disabled.
152 * @bf_filter_escape_timer: Send beacons to to driver if no beacons were passed 239 * @bf_filter_escape_timer: Send beacons to to driver if no beacons were passed
153 * for a specific period of time. Units: Beacons. 240 * for a specific period of time. Units: Beacons.
@@ -156,17 +243,17 @@ struct iwl_powertable_cmd {
156 * @ba_enable_beacon_abort: 1, beacon abort is enabled; 0, disabled. 243 * @ba_enable_beacon_abort: 1, beacon abort is enabled; 0, disabled.
157 */ 244 */
158struct iwl_beacon_filter_cmd { 245struct iwl_beacon_filter_cmd {
159 u8 bf_energy_delta; 246 __le32 bf_energy_delta;
160 u8 bf_roaming_energy_delta; 247 __le32 bf_roaming_energy_delta;
161 u8 bf_roaming_state; 248 __le32 bf_roaming_state;
162 u8 bf_temperature_delta; 249 __le32 bf_temp_threshold;
163 u8 bf_enable_beacon_filter; 250 __le32 bf_temp_fast_filter;
164 u8 bf_debug_flag; 251 __le32 bf_temp_slow_filter;
165 __le16 reserved1; 252 __le32 bf_enable_beacon_filter;
253 __le32 bf_debug_flag;
166 __le32 bf_escape_timer; 254 __le32 bf_escape_timer;
167 __le32 ba_escape_timer; 255 __le32 ba_escape_timer;
168 u8 ba_enable_beacon_abort; 256 __le32 ba_enable_beacon_abort;
169 u8 reserved2[3];
170} __packed; 257} __packed;
171 258
172/* Beacon filtering and beacon abort */ 259/* Beacon filtering and beacon abort */
@@ -182,9 +269,17 @@ struct iwl_beacon_filter_cmd {
182#define IWL_BF_ROAMING_STATE_MAX 255 269#define IWL_BF_ROAMING_STATE_MAX 255
183#define IWL_BF_ROAMING_STATE_MIN 0 270#define IWL_BF_ROAMING_STATE_MIN 0
184 271
185#define IWL_BF_TEMPERATURE_DELTA_DEFAULT 5 272#define IWL_BF_TEMP_THRESHOLD_DEFAULT 112
186#define IWL_BF_TEMPERATURE_DELTA_MAX 255 273#define IWL_BF_TEMP_THRESHOLD_MAX 255
187#define IWL_BF_TEMPERATURE_DELTA_MIN 0 274#define IWL_BF_TEMP_THRESHOLD_MIN 0
275
276#define IWL_BF_TEMP_FAST_FILTER_DEFAULT 1
277#define IWL_BF_TEMP_FAST_FILTER_MAX 255
278#define IWL_BF_TEMP_FAST_FILTER_MIN 0
279
280#define IWL_BF_TEMP_SLOW_FILTER_DEFAULT 5
281#define IWL_BF_TEMP_SLOW_FILTER_MAX 255
282#define IWL_BF_TEMP_SLOW_FILTER_MIN 0
188 283
189#define IWL_BF_ENABLE_BEACON_FILTER_DEFAULT 1 284#define IWL_BF_ENABLE_BEACON_FILTER_DEFAULT 1
190 285
@@ -194,19 +289,23 @@ struct iwl_beacon_filter_cmd {
194#define IWL_BF_ESCAPE_TIMER_MAX 1024 289#define IWL_BF_ESCAPE_TIMER_MAX 1024
195#define IWL_BF_ESCAPE_TIMER_MIN 0 290#define IWL_BF_ESCAPE_TIMER_MIN 0
196 291
197#define IWL_BA_ESCAPE_TIMER_DEFAULT 3 292#define IWL_BA_ESCAPE_TIMER_DEFAULT 6
293#define IWL_BA_ESCAPE_TIMER_D3 6
198#define IWL_BA_ESCAPE_TIMER_MAX 1024 294#define IWL_BA_ESCAPE_TIMER_MAX 1024
199#define IWL_BA_ESCAPE_TIMER_MIN 0 295#define IWL_BA_ESCAPE_TIMER_MIN 0
200 296
201#define IWL_BA_ENABLE_BEACON_ABORT_DEFAULT 1 297#define IWL_BA_ENABLE_BEACON_ABORT_DEFAULT 1
202 298
203#define IWL_BF_CMD_CONFIG_DEFAULTS \ 299#define IWL_BF_CMD_CONFIG_DEFAULTS \
204 .bf_energy_delta = IWL_BF_ENERGY_DELTA_DEFAULT, \ 300 .bf_energy_delta = cpu_to_le32(IWL_BF_ENERGY_DELTA_DEFAULT), \
205 .bf_roaming_energy_delta = IWL_BF_ROAMING_ENERGY_DELTA_DEFAULT, \ 301 .bf_roaming_energy_delta = \
206 .bf_roaming_state = IWL_BF_ROAMING_STATE_DEFAULT, \ 302 cpu_to_le32(IWL_BF_ROAMING_ENERGY_DELTA_DEFAULT), \
207 .bf_temperature_delta = IWL_BF_TEMPERATURE_DELTA_DEFAULT, \ 303 .bf_roaming_state = cpu_to_le32(IWL_BF_ROAMING_STATE_DEFAULT), \
208 .bf_debug_flag = IWL_BF_DEBUG_FLAG_DEFAULT, \ 304 .bf_temp_threshold = cpu_to_le32(IWL_BF_TEMP_THRESHOLD_DEFAULT), \
209 .bf_escape_timer = cpu_to_le32(IWL_BF_ESCAPE_TIMER_DEFAULT), \ 305 .bf_temp_fast_filter = cpu_to_le32(IWL_BF_TEMP_FAST_FILTER_DEFAULT), \
306 .bf_temp_slow_filter = cpu_to_le32(IWL_BF_TEMP_SLOW_FILTER_DEFAULT), \
307 .bf_debug_flag = cpu_to_le32(IWL_BF_DEBUG_FLAG_DEFAULT), \
308 .bf_escape_timer = cpu_to_le32(IWL_BF_ESCAPE_TIMER_DEFAULT), \
210 .ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_DEFAULT) 309 .ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_DEFAULT)
211 310
212#endif 311#endif
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
index 365095a0c3b3..83cb9b992ea4 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
@@ -137,6 +137,8 @@ struct iwl_ssid_ie {
137 *@SCAN_FLAGS_DELAYED_SCAN_LOWBAND: 137 *@SCAN_FLAGS_DELAYED_SCAN_LOWBAND:
138 *@SCAN_FLAGS_DELAYED_SCAN_HIGHBAND: 138 *@SCAN_FLAGS_DELAYED_SCAN_HIGHBAND:
139 *@SCAN_FLAGS_FRAGMENTED_SCAN: 139 *@SCAN_FLAGS_FRAGMENTED_SCAN:
140 *@SCAN_FLAGS_PASSIVE2ACTIVE: use active scan on channels that was active
141 * in the past hour, even if they are marked as passive.
140 */ 142 */
141enum iwl_scan_flags { 143enum iwl_scan_flags {
142 SCAN_FLAGS_PERIODIC_SCAN = BIT(0), 144 SCAN_FLAGS_PERIODIC_SCAN = BIT(0),
@@ -144,6 +146,7 @@ enum iwl_scan_flags {
144 SCAN_FLAGS_DELAYED_SCAN_LOWBAND = BIT(2), 146 SCAN_FLAGS_DELAYED_SCAN_LOWBAND = BIT(2),
145 SCAN_FLAGS_DELAYED_SCAN_HIGHBAND = BIT(3), 147 SCAN_FLAGS_DELAYED_SCAN_HIGHBAND = BIT(3),
146 SCAN_FLAGS_FRAGMENTED_SCAN = BIT(4), 148 SCAN_FLAGS_FRAGMENTED_SCAN = BIT(4),
149 SCAN_FLAGS_PASSIVE2ACTIVE = BIT(5),
147}; 150};
148 151
149/** 152/**
@@ -178,7 +181,7 @@ enum iwl_scan_type {
178 * @quiet_time: in msecs, dwell this time for active scan on quiet channels 181 * @quiet_time: in msecs, dwell this time for active scan on quiet channels
179 * @quiet_plcp_th: quiet PLCP threshold (channel is quiet if less than 182 * @quiet_plcp_th: quiet PLCP threshold (channel is quiet if less than
180 * this number of packets were received (typically 1) 183 * this number of packets were received (typically 1)
181 * @passive2active: is auto switching from passive to active allowed (0 or 1) 184 * @passive2active: is auto switching from passive to active during scan allowed
182 * @rxchain_sel_flags: RXON_RX_CHAIN_* 185 * @rxchain_sel_flags: RXON_RX_CHAIN_*
183 * @max_out_time: in usecs, max out of serving channel time 186 * @max_out_time: in usecs, max out of serving channel time
184 * @suspend_time: how long to pause scan when returning to service channel: 187 * @suspend_time: how long to pause scan when returning to service channel:
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h
index 700cce731770..d606197bde8f 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-tx.h
@@ -91,7 +91,6 @@
91 * @TX_CMD_FLG_RESP_TO_DRV: zero this if the response should go only to FW 91 * @TX_CMD_FLG_RESP_TO_DRV: zero this if the response should go only to FW
92 * @TX_CMD_FLG_CCMP_AGG: this frame uses CCMP for aggregation acceleration 92 * @TX_CMD_FLG_CCMP_AGG: this frame uses CCMP for aggregation acceleration
93 * @TX_CMD_FLG_TKIP_MIC_DONE: FW already performed TKIP MIC calculation 93 * @TX_CMD_FLG_TKIP_MIC_DONE: FW already performed TKIP MIC calculation
94 * @TX_CMD_FLG_CTS_ONLY: send CTS only, no data after that
95 * @TX_CMD_FLG_DUR: disable duration overwriting used in PS-Poll Assoc-id 94 * @TX_CMD_FLG_DUR: disable duration overwriting used in PS-Poll Assoc-id
96 * @TX_CMD_FLG_FW_DROP: FW should mark frame to be dropped 95 * @TX_CMD_FLG_FW_DROP: FW should mark frame to be dropped
97 * @TX_CMD_FLG_EXEC_PAPD: execute PAPD 96 * @TX_CMD_FLG_EXEC_PAPD: execute PAPD
@@ -120,7 +119,6 @@ enum iwl_tx_flags {
120 TX_CMD_FLG_RESP_TO_DRV = BIT(21), 119 TX_CMD_FLG_RESP_TO_DRV = BIT(21),
121 TX_CMD_FLG_CCMP_AGG = BIT(22), 120 TX_CMD_FLG_CCMP_AGG = BIT(22),
122 TX_CMD_FLG_TKIP_MIC_DONE = BIT(23), 121 TX_CMD_FLG_TKIP_MIC_DONE = BIT(23),
123 TX_CMD_FLG_CTS_ONLY = BIT(24),
124 TX_CMD_FLG_DUR = BIT(25), 122 TX_CMD_FLG_DUR = BIT(25),
125 TX_CMD_FLG_FW_DROP = BIT(26), 123 TX_CMD_FLG_FW_DROP = BIT(26),
126 TX_CMD_FLG_EXEC_PAPD = BIT(27), 124 TX_CMD_FLG_EXEC_PAPD = BIT(27),
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
index cbfb3beae783..66264cc5a016 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
@@ -136,7 +136,7 @@ enum {
136 CALIB_RES_NOTIF_PHY_DB = 0x6b, 136 CALIB_RES_NOTIF_PHY_DB = 0x6b,
137 /* PHY_DB_CMD = 0x6c, */ 137 /* PHY_DB_CMD = 0x6c, */
138 138
139 /* Power */ 139 /* Power - legacy power table command */
140 POWER_TABLE_CMD = 0x77, 140 POWER_TABLE_CMD = 0x77,
141 141
142 /* Thermal Throttling*/ 142 /* Thermal Throttling*/
@@ -159,6 +159,7 @@ enum {
159 TX_ANT_CONFIGURATION_CMD = 0x98, 159 TX_ANT_CONFIGURATION_CMD = 0x98,
160 BT_CONFIG = 0x9b, 160 BT_CONFIG = 0x9b,
161 STATISTICS_NOTIFICATION = 0x9d, 161 STATISTICS_NOTIFICATION = 0x9d,
162 REDUCE_TX_POWER_CMD = 0x9f,
162 163
163 /* RF-KILL commands and notifications */ 164 /* RF-KILL commands and notifications */
164 CARD_STATE_CMD = 0xa0, 165 CARD_STATE_CMD = 0xa0,
@@ -166,6 +167,9 @@ enum {
166 167
167 MISSED_BEACONS_NOTIFICATION = 0xa2, 168 MISSED_BEACONS_NOTIFICATION = 0xa2,
168 169
170 /* Power - new power table command */
171 MAC_PM_POWER_TABLE = 0xa9,
172
169 REPLY_RX_PHY_CMD = 0xc0, 173 REPLY_RX_PHY_CMD = 0xc0,
170 REPLY_RX_MPDU_CMD = 0xc1, 174 REPLY_RX_MPDU_CMD = 0xc1,
171 BA_NOTIF = 0xc5, 175 BA_NOTIF = 0xc5,
@@ -223,6 +227,19 @@ struct iwl_tx_ant_cfg_cmd {
223 __le32 valid; 227 __le32 valid;
224} __packed; 228} __packed;
225 229
230/**
231 * struct iwl_reduce_tx_power_cmd - TX power reduction command
232 * REDUCE_TX_POWER_CMD = 0x9f
233 * @flags: (reserved for future implementation)
234 * @mac_context_id: id of the mac ctx for which we are reducing TX power.
235 * @pwr_restriction: TX power restriction in dBms.
236 */
237struct iwl_reduce_tx_power_cmd {
238 u8 flags;
239 u8 mac_context_id;
240 __le16 pwr_restriction;
241} __packed; /* TX_REDUCED_POWER_API_S_VER_1 */
242
226/* 243/*
227 * Calibration control struct. 244 * Calibration control struct.
228 * Sent as part of the phy configuration command. 245 * Sent as part of the phy configuration command.
@@ -482,71 +499,199 @@ enum iwl_time_event_type {
482 TE_MAX 499 TE_MAX
483}; /* MAC_EVENT_TYPE_API_E_VER_1 */ 500}; /* MAC_EVENT_TYPE_API_E_VER_1 */
484 501
502
503
504/* Time event - defines for command API v1 */
505
506/*
507 * @TE_V1_FRAG_NONE: fragmentation of the time event is NOT allowed.
508 * @TE_V1_FRAG_SINGLE: fragmentation of the time event is allowed, but only
509 * the first fragment is scheduled.
510 * @TE_V1_FRAG_DUAL: fragmentation of the time event is allowed, but only
511 * the first 2 fragments are scheduled.
512 * @TE_V1_FRAG_ENDLESS: fragmentation of the time event is allowed, and any
513 * number of fragments are valid.
514 *
515 * Other than the constant defined above, specifying a fragmentation value 'x'
516 * means that the event can be fragmented but only the first 'x' will be
517 * scheduled.
518 */
519enum {
520 TE_V1_FRAG_NONE = 0,
521 TE_V1_FRAG_SINGLE = 1,
522 TE_V1_FRAG_DUAL = 2,
523 TE_V1_FRAG_ENDLESS = 0xffffffff
524};
525
526/* If a Time Event can be fragmented, this is the max number of fragments */
527#define TE_V1_FRAG_MAX_MSK 0x0fffffff
528/* Repeat the time event endlessly (until removed) */
529#define TE_V1_REPEAT_ENDLESS 0xffffffff
530/* If a Time Event has bounded repetitions, this is the maximal value */
531#define TE_V1_REPEAT_MAX_MSK_V1 0x0fffffff
532
485/* Time Event dependencies: none, on another TE, or in a specific time */ 533/* Time Event dependencies: none, on another TE, or in a specific time */
486enum { 534enum {
487 TE_INDEPENDENT = 0, 535 TE_V1_INDEPENDENT = 0,
488 TE_DEP_OTHER = 1, 536 TE_V1_DEP_OTHER = BIT(0),
489 TE_DEP_TSF = 2, 537 TE_V1_DEP_TSF = BIT(1),
490 TE_EVENT_SOCIOPATHIC = 4, 538 TE_V1_EVENT_SOCIOPATHIC = BIT(2),
491}; /* MAC_EVENT_DEPENDENCY_POLICY_API_E_VER_2 */ 539}; /* MAC_EVENT_DEPENDENCY_POLICY_API_E_VER_2 */
540
492/* 541/*
542 * @TE_V1_NOTIF_NONE: no notifications
543 * @TE_V1_NOTIF_HOST_EVENT_START: request/receive notification on event start
544 * @TE_V1_NOTIF_HOST_EVENT_END:request/receive notification on event end
545 * @TE_V1_NOTIF_INTERNAL_EVENT_START: internal FW use
546 * @TE_V1_NOTIF_INTERNAL_EVENT_END: internal FW use.
547 * @TE_V1_NOTIF_HOST_FRAG_START: request/receive notification on frag start
548 * @TE_V1_NOTIF_HOST_FRAG_END:request/receive notification on frag end
549 * @TE_V1_NOTIF_INTERNAL_FRAG_START: internal FW use.
550 * @TE_V1_NOTIF_INTERNAL_FRAG_END: internal FW use.
551 *
493 * Supported Time event notifications configuration. 552 * Supported Time event notifications configuration.
494 * A notification (both event and fragment) includes a status indicating weather 553 * A notification (both event and fragment) includes a status indicating weather
495 * the FW was able to schedule the event or not. For fragment start/end 554 * the FW was able to schedule the event or not. For fragment start/end
496 * notification the status is always success. There is no start/end fragment 555 * notification the status is always success. There is no start/end fragment
497 * notification for monolithic events. 556 * notification for monolithic events.
498 *
499 * @TE_NOTIF_NONE: no notifications
500 * @TE_NOTIF_HOST_EVENT_START: request/receive notification on event start
501 * @TE_NOTIF_HOST_EVENT_END:request/receive notification on event end
502 * @TE_NOTIF_INTERNAL_EVENT_START: internal FW use
503 * @TE_NOTIF_INTERNAL_EVENT_END: internal FW use.
504 * @TE_NOTIF_HOST_FRAG_START: request/receive notification on frag start
505 * @TE_NOTIF_HOST_FRAG_END:request/receive notification on frag end
506 * @TE_NOTIF_INTERNAL_FRAG_START: internal FW use.
507 * @TE_NOTIF_INTERNAL_FRAG_END: internal FW use.
508 */ 557 */
509enum { 558enum {
510 TE_NOTIF_NONE = 0, 559 TE_V1_NOTIF_NONE = 0,
511 TE_NOTIF_HOST_EVENT_START = 0x1, 560 TE_V1_NOTIF_HOST_EVENT_START = BIT(0),
512 TE_NOTIF_HOST_EVENT_END = 0x2, 561 TE_V1_NOTIF_HOST_EVENT_END = BIT(1),
513 TE_NOTIF_INTERNAL_EVENT_START = 0x4, 562 TE_V1_NOTIF_INTERNAL_EVENT_START = BIT(2),
514 TE_NOTIF_INTERNAL_EVENT_END = 0x8, 563 TE_V1_NOTIF_INTERNAL_EVENT_END = BIT(3),
515 TE_NOTIF_HOST_FRAG_START = 0x10, 564 TE_V1_NOTIF_HOST_FRAG_START = BIT(4),
516 TE_NOTIF_HOST_FRAG_END = 0x20, 565 TE_V1_NOTIF_HOST_FRAG_END = BIT(5),
517 TE_NOTIF_INTERNAL_FRAG_START = 0x40, 566 TE_V1_NOTIF_INTERNAL_FRAG_START = BIT(6),
518 TE_NOTIF_INTERNAL_FRAG_END = 0x80 567 TE_V1_NOTIF_INTERNAL_FRAG_END = BIT(7),
519}; /* MAC_EVENT_ACTION_API_E_VER_2 */ 568}; /* MAC_EVENT_ACTION_API_E_VER_2 */
520 569
570
571/**
572 * struct iwl_time_event_cmd_api_v1 - configuring Time Events
573 * with struct MAC_TIME_EVENT_DATA_API_S_VER_1 (see also
574 * with version 2. determined by IWL_UCODE_TLV_FLAGS)
575 * ( TIME_EVENT_CMD = 0x29 )
576 * @id_and_color: ID and color of the relevant MAC
577 * @action: action to perform, one of FW_CTXT_ACTION_*
578 * @id: this field has two meanings, depending on the action:
579 * If the action is ADD, then it means the type of event to add.
580 * For all other actions it is the unique event ID assigned when the
581 * event was added by the FW.
582 * @apply_time: When to start the Time Event (in GP2)
583 * @max_delay: maximum delay to event's start (apply time), in TU
584 * @depends_on: the unique ID of the event we depend on (if any)
585 * @interval: interval between repetitions, in TU
586 * @interval_reciprocal: 2^32 / interval
587 * @duration: duration of event in TU
588 * @repeat: how many repetitions to do, can be TE_REPEAT_ENDLESS
589 * @dep_policy: one of TE_V1_INDEPENDENT, TE_V1_DEP_OTHER, TE_V1_DEP_TSF
590 * and TE_V1_EVENT_SOCIOPATHIC
591 * @is_present: 0 or 1, are we present or absent during the Time Event
592 * @max_frags: maximal number of fragments the Time Event can be divided to
593 * @notify: notifications using TE_V1_NOTIF_* (whom to notify when)
594 */
595struct iwl_time_event_cmd_v1 {
596 /* COMMON_INDEX_HDR_API_S_VER_1 */
597 __le32 id_and_color;
598 __le32 action;
599 __le32 id;
600 /* MAC_TIME_EVENT_DATA_API_S_VER_1 */
601 __le32 apply_time;
602 __le32 max_delay;
603 __le32 dep_policy;
604 __le32 depends_on;
605 __le32 is_present;
606 __le32 max_frags;
607 __le32 interval;
608 __le32 interval_reciprocal;
609 __le32 duration;
610 __le32 repeat;
611 __le32 notify;
612} __packed; /* MAC_TIME_EVENT_CMD_API_S_VER_1 */
613
614
615/* Time event - defines for command API v2 */
616
521/* 617/*
522 * @TE_FRAG_NONE: fragmentation of the time event is NOT allowed. 618 * @TE_V2_FRAG_NONE: fragmentation of the time event is NOT allowed.
523 * @TE_FRAG_SINGLE: fragmentation of the time event is allowed, but only 619 * @TE_V2_FRAG_SINGLE: fragmentation of the time event is allowed, but only
524 * the first fragment is scheduled. 620 * the first fragment is scheduled.
525 * @TE_FRAG_DUAL: fragmentation of the time event is allowed, but only 621 * @TE_V2_FRAG_DUAL: fragmentation of the time event is allowed, but only
526 * the first 2 fragments are scheduled. 622 * the first 2 fragments are scheduled.
527 * @TE_FRAG_ENDLESS: fragmentation of the time event is allowed, and any number 623 * @TE_V2_FRAG_ENDLESS: fragmentation of the time event is allowed, and any
528 * of fragments are valid. 624 * number of fragments are valid.
529 * 625 *
530 * Other than the constant defined above, specifying a fragmentation value 'x' 626 * Other than the constant defined above, specifying a fragmentation value 'x'
531 * means that the event can be fragmented but only the first 'x' will be 627 * means that the event can be fragmented but only the first 'x' will be
532 * scheduled. 628 * scheduled.
533 */ 629 */
534enum { 630enum {
535 TE_FRAG_NONE = 0, 631 TE_V2_FRAG_NONE = 0,
536 TE_FRAG_SINGLE = 1, 632 TE_V2_FRAG_SINGLE = 1,
537 TE_FRAG_DUAL = 2, 633 TE_V2_FRAG_DUAL = 2,
538 TE_FRAG_ENDLESS = 0xffffffff 634 TE_V2_FRAG_MAX = 0xfe,
635 TE_V2_FRAG_ENDLESS = 0xff
539}; 636};
540 637
541/* Repeat the time event endlessly (until removed) */ 638/* Repeat the time event endlessly (until removed) */
542#define TE_REPEAT_ENDLESS (0xffffffff) 639#define TE_V2_REPEAT_ENDLESS 0xff
543/* If a Time Event has bounded repetitions, this is the maximal value */ 640/* If a Time Event has bounded repetitions, this is the maximal value */
544#define TE_REPEAT_MAX_MSK (0x0fffffff) 641#define TE_V2_REPEAT_MAX 0xfe
545/* If a Time Event can be fragmented, this is the max number of fragments */ 642
546#define TE_FRAG_MAX_MSK (0x0fffffff) 643#define TE_V2_PLACEMENT_POS 12
644#define TE_V2_ABSENCE_POS 15
645
646/* Time event policy values (for time event cmd api v2)
647 * A notification (both event and fragment) includes a status indicating weather
648 * the FW was able to schedule the event or not. For fragment start/end
649 * notification the status is always success. There is no start/end fragment
650 * notification for monolithic events.
651 *
652 * @TE_V2_DEFAULT_POLICY: independent, social, present, unoticable
653 * @TE_V2_NOTIF_HOST_EVENT_START: request/receive notification on event start
654 * @TE_V2_NOTIF_HOST_EVENT_END:request/receive notification on event end
655 * @TE_V2_NOTIF_INTERNAL_EVENT_START: internal FW use
656 * @TE_V2_NOTIF_INTERNAL_EVENT_END: internal FW use.
657 * @TE_V2_NOTIF_HOST_FRAG_START: request/receive notification on frag start
658 * @TE_V2_NOTIF_HOST_FRAG_END:request/receive notification on frag end
659 * @TE_V2_NOTIF_INTERNAL_FRAG_START: internal FW use.
660 * @TE_V2_NOTIF_INTERNAL_FRAG_END: internal FW use.
661 * @TE_V2_DEP_OTHER: depends on another time event
662 * @TE_V2_DEP_TSF: depends on a specific time
663 * @TE_V2_EVENT_SOCIOPATHIC: can't co-exist with other events of tha same MAC
664 * @TE_V2_ABSENCE: are we present or absent during the Time Event.
665 */
666enum {
667 TE_V2_DEFAULT_POLICY = 0x0,
668
669 /* notifications (event start/stop, fragment start/stop) */
670 TE_V2_NOTIF_HOST_EVENT_START = BIT(0),
671 TE_V2_NOTIF_HOST_EVENT_END = BIT(1),
672 TE_V2_NOTIF_INTERNAL_EVENT_START = BIT(2),
673 TE_V2_NOTIF_INTERNAL_EVENT_END = BIT(3),
674
675 TE_V2_NOTIF_HOST_FRAG_START = BIT(4),
676 TE_V2_NOTIF_HOST_FRAG_END = BIT(5),
677 TE_V2_NOTIF_INTERNAL_FRAG_START = BIT(6),
678 TE_V2_NOTIF_INTERNAL_FRAG_END = BIT(7),
679
680 TE_V2_NOTIF_MSK = 0xff,
681
682 /* placement characteristics */
683 TE_V2_DEP_OTHER = BIT(TE_V2_PLACEMENT_POS),
684 TE_V2_DEP_TSF = BIT(TE_V2_PLACEMENT_POS + 1),
685 TE_V2_EVENT_SOCIOPATHIC = BIT(TE_V2_PLACEMENT_POS + 2),
686
687 /* are we present or absent during the Time Event. */
688 TE_V2_ABSENCE = BIT(TE_V2_ABSENCE_POS),
689};
547 690
548/** 691/**
549 * struct iwl_time_event_cmd - configuring Time Events 692 * struct iwl_time_event_cmd_api_v2 - configuring Time Events
693 * with struct MAC_TIME_EVENT_DATA_API_S_VER_2 (see also
694 * with version 1. determined by IWL_UCODE_TLV_FLAGS)
550 * ( TIME_EVENT_CMD = 0x29 ) 695 * ( TIME_EVENT_CMD = 0x29 )
551 * @id_and_color: ID and color of the relevant MAC 696 * @id_and_color: ID and color of the relevant MAC
552 * @action: action to perform, one of FW_CTXT_ACTION_* 697 * @action: action to perform, one of FW_CTXT_ACTION_*
@@ -558,32 +703,30 @@ enum {
558 * @max_delay: maximum delay to event's start (apply time), in TU 703 * @max_delay: maximum delay to event's start (apply time), in TU
559 * @depends_on: the unique ID of the event we depend on (if any) 704 * @depends_on: the unique ID of the event we depend on (if any)
560 * @interval: interval between repetitions, in TU 705 * @interval: interval between repetitions, in TU
561 * @interval_reciprocal: 2^32 / interval
562 * @duration: duration of event in TU 706 * @duration: duration of event in TU
563 * @repeat: how many repetitions to do, can be TE_REPEAT_ENDLESS 707 * @repeat: how many repetitions to do, can be TE_REPEAT_ENDLESS
564 * @dep_policy: one of TE_INDEPENDENT, TE_DEP_OTHER, TE_DEP_TSF
565 * @is_present: 0 or 1, are we present or absent during the Time Event
566 * @max_frags: maximal number of fragments the Time Event can be divided to 708 * @max_frags: maximal number of fragments the Time Event can be divided to
567 * @notify: notifications using TE_NOTIF_* (whom to notify when) 709 * @policy: defines whether uCode shall notify the host or other uCode modules
710 * on event and/or fragment start and/or end
711 * using one of TE_INDEPENDENT, TE_DEP_OTHER, TE_DEP_TSF
712 * TE_EVENT_SOCIOPATHIC
713 * using TE_ABSENCE and using TE_NOTIF_*
568 */ 714 */
569struct iwl_time_event_cmd { 715struct iwl_time_event_cmd_v2 {
570 /* COMMON_INDEX_HDR_API_S_VER_1 */ 716 /* COMMON_INDEX_HDR_API_S_VER_1 */
571 __le32 id_and_color; 717 __le32 id_and_color;
572 __le32 action; 718 __le32 action;
573 __le32 id; 719 __le32 id;
574 /* MAC_TIME_EVENT_DATA_API_S_VER_1 */ 720 /* MAC_TIME_EVENT_DATA_API_S_VER_2 */
575 __le32 apply_time; 721 __le32 apply_time;
576 __le32 max_delay; 722 __le32 max_delay;
577 __le32 dep_policy;
578 __le32 depends_on; 723 __le32 depends_on;
579 __le32 is_present;
580 __le32 max_frags;
581 __le32 interval; 724 __le32 interval;
582 __le32 interval_reciprocal;
583 __le32 duration; 725 __le32 duration;
584 __le32 repeat; 726 u8 repeat;
585 __le32 notify; 727 u8 max_frags;
586} __packed; /* MAC_TIME_EVENT_CMD_API_S_VER_1 */ 728 __le16 policy;
729} __packed; /* MAC_TIME_EVENT_CMD_API_S_VER_2 */
587 730
588/** 731/**
589 * struct iwl_time_event_resp - response structure to iwl_time_event_cmd 732 * struct iwl_time_event_resp - response structure to iwl_time_event_cmd
@@ -765,6 +908,14 @@ struct iwl_phy_context_cmd {
765} __packed; /* PHY_CONTEXT_CMD_API_VER_1 */ 908} __packed; /* PHY_CONTEXT_CMD_API_VER_1 */
766 909
767#define IWL_RX_INFO_PHY_CNT 8 910#define IWL_RX_INFO_PHY_CNT 8
911#define IWL_RX_INFO_ENERGY_ANT_ABC_IDX 1
912#define IWL_RX_INFO_ENERGY_ANT_A_MSK 0x000000ff
913#define IWL_RX_INFO_ENERGY_ANT_B_MSK 0x0000ff00
914#define IWL_RX_INFO_ENERGY_ANT_C_MSK 0x00ff0000
915#define IWL_RX_INFO_ENERGY_ANT_A_POS 0
916#define IWL_RX_INFO_ENERGY_ANT_B_POS 8
917#define IWL_RX_INFO_ENERGY_ANT_C_POS 16
918
768#define IWL_RX_INFO_AGC_IDX 1 919#define IWL_RX_INFO_AGC_IDX 1
769#define IWL_RX_INFO_RSSI_AB_IDX 2 920#define IWL_RX_INFO_RSSI_AB_IDX 2
770#define IWL_OFDM_AGC_A_MSK 0x0000007f 921#define IWL_OFDM_AGC_A_MSK 0x0000007f
@@ -1170,7 +1321,7 @@ struct mvm_statistics_general {
1170 struct mvm_statistics_general_common common; 1321 struct mvm_statistics_general_common common;
1171 __le32 beacon_filtered; 1322 __le32 beacon_filtered;
1172 __le32 missed_beacons; 1323 __le32 missed_beacons;
1173 __s8 beacon_filter_everage_energy; 1324 __s8 beacon_filter_average_energy;
1174 __s8 beacon_filter_reason; 1325 __s8 beacon_filter_reason;
1175 __s8 beacon_filter_current_energy; 1326 __s8 beacon_filter_current_energy;
1176 __s8 beacon_filter_reserved; 1327 __s8 beacon_filter_reserved;
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c
index cd7c0032cc58..c76299a3a1e0 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/iwlwifi/mvm/fw.c
@@ -78,22 +78,6 @@
78 78
79#define UCODE_VALID_OK cpu_to_le32(0x1) 79#define UCODE_VALID_OK cpu_to_le32(0x1)
80 80
81/* Default calibration values for WkP - set to INIT image w/o running */
82static const u8 wkp_calib_values_rx_iq_skew[] = { 0x00, 0x00, 0x01, 0x00 };
83static const u8 wkp_calib_values_tx_iq_skew[] = { 0x01, 0x00, 0x00, 0x00 };
84
85struct iwl_calib_default_data {
86 u16 size;
87 void *data;
88};
89
90#define CALIB_SIZE_N_DATA(_buf) {.size = sizeof(_buf), .data = &_buf}
91
92static const struct iwl_calib_default_data wkp_calib_default_data[12] = {
93 [9] = CALIB_SIZE_N_DATA(wkp_calib_values_tx_iq_skew),
94 [11] = CALIB_SIZE_N_DATA(wkp_calib_values_rx_iq_skew),
95};
96
97struct iwl_mvm_alive_data { 81struct iwl_mvm_alive_data {
98 bool valid; 82 bool valid;
99 u32 scd_base_addr; 83 u32 scd_base_addr;
@@ -248,40 +232,6 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
248 sizeof(phy_cfg_cmd), &phy_cfg_cmd); 232 sizeof(phy_cfg_cmd), &phy_cfg_cmd);
249} 233}
250 234
251static int iwl_set_default_calibrations(struct iwl_mvm *mvm)
252{
253 u8 cmd_raw[16]; /* holds the variable size commands */
254 struct iwl_set_calib_default_cmd *cmd =
255 (struct iwl_set_calib_default_cmd *)cmd_raw;
256 int ret, i;
257
258 /* Setting default values for calibrations we don't run */
259 for (i = 0; i < ARRAY_SIZE(wkp_calib_default_data); i++) {
260 u16 cmd_len;
261
262 if (wkp_calib_default_data[i].size == 0)
263 continue;
264
265 memset(cmd_raw, 0, sizeof(cmd_raw));
266 cmd_len = wkp_calib_default_data[i].size + sizeof(cmd);
267 cmd->calib_index = cpu_to_le16(i);
268 cmd->length = cpu_to_le16(wkp_calib_default_data[i].size);
269 if (WARN_ONCE(cmd_len > sizeof(cmd_raw),
270 "Need to enlarge cmd_raw to %d\n", cmd_len))
271 break;
272 memcpy(cmd->data, wkp_calib_default_data[i].data,
273 wkp_calib_default_data[i].size);
274 ret = iwl_mvm_send_cmd_pdu(mvm, SET_CALIB_DEFAULT_CMD, 0,
275 sizeof(*cmd) +
276 wkp_calib_default_data[i].size,
277 cmd);
278 if (ret)
279 return ret;
280 }
281
282 return 0;
283}
284
285int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) 235int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
286{ 236{
287 struct iwl_notification_wait calib_wait; 237 struct iwl_notification_wait calib_wait;
@@ -342,11 +292,6 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
342 if (ret) 292 if (ret)
343 goto error; 293 goto error;
344 294
345 /* need to set default values */
346 ret = iwl_set_default_calibrations(mvm);
347 if (ret)
348 goto error;
349
350 /* 295 /*
351 * Send phy configurations command to init uCode 296 * Send phy configurations command to init uCode
352 * to start the 16.0 uCode init image internal calibrations. 297 * to start the 16.0 uCode init image internal calibrations.
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
index 94aae9c8562c..5fe23a5ea9b6 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
@@ -264,7 +264,8 @@ static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm,
264 return 0; 264 return 0;
265 265
266 /* Therefore, in recovery, we can't get here */ 266 /* Therefore, in recovery, we can't get here */
267 WARN_ON_ONCE(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)); 267 if (WARN_ON_ONCE(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)))
268 return -EBUSY;
268 269
269 mvmvif->id = find_first_bit(data.available_mac_ids, 270 mvmvif->id = find_first_bit(data.available_mac_ids,
270 NUM_MAC_INDEX_DRIVER); 271 NUM_MAC_INDEX_DRIVER);
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index f19baf0dea6b..9833cdf6177c 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -153,7 +153,10 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
153 IEEE80211_HW_SUPPORTS_DYNAMIC_PS | 153 IEEE80211_HW_SUPPORTS_DYNAMIC_PS |
154 IEEE80211_HW_AMPDU_AGGREGATION | 154 IEEE80211_HW_AMPDU_AGGREGATION |
155 IEEE80211_HW_TIMING_BEACON_ONLY | 155 IEEE80211_HW_TIMING_BEACON_ONLY |
156 IEEE80211_HW_CONNECTION_MONITOR; 156 IEEE80211_HW_CONNECTION_MONITOR |
157 IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
158 IEEE80211_HW_SUPPORTS_STATIC_SMPS |
159 IEEE80211_HW_SUPPORTS_UAPSD;
157 160
158 hw->queues = IWL_MVM_FIRST_AGG_QUEUE; 161 hw->queues = IWL_MVM_FIRST_AGG_QUEUE;
159 hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE; 162 hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE;
@@ -188,6 +191,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
188 191
189 hw->wiphy->max_remain_on_channel_duration = 10000; 192 hw->wiphy->max_remain_on_channel_duration = 10000;
190 hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL; 193 hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL;
194 hw->uapsd_queues = IWL_UAPSD_AC_INFO;
195 hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP;
191 196
192 /* Extract MAC address */ 197 /* Extract MAC address */
193 memcpy(mvm->addresses[0].addr, mvm->nvm_data->hw_addr, ETH_ALEN); 198 memcpy(mvm->addresses[0].addr, mvm->nvm_data->hw_addr, ETH_ALEN);
@@ -506,7 +511,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
506 511
507 mutex_lock(&mvm->mutex); 512 mutex_lock(&mvm->mutex);
508 513
509 /* Allocate resources for the MAC context, and add it the the fw */ 514 /* Allocate resources for the MAC context, and add it to the fw */
510 ret = iwl_mvm_mac_ctxt_init(mvm, vif); 515 ret = iwl_mvm_mac_ctxt_init(mvm, vif);
511 if (ret) 516 if (ret)
512 goto out_unlock; 517 goto out_unlock;
@@ -552,6 +557,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
552 goto out_release; 557 goto out_release;
553 } 558 }
554 559
560 iwl_mvm_vif_dbgfs_register(mvm, vif);
555 goto out_unlock; 561 goto out_unlock;
556 } 562 }
557 563
@@ -566,16 +572,18 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
566 iwl_mvm_power_update_mode(mvm, vif); 572 iwl_mvm_power_update_mode(mvm, vif);
567 573
568 /* beacon filtering */ 574 /* beacon filtering */
575 ret = iwl_mvm_disable_beacon_filter(mvm, vif);
576 if (ret)
577 goto out_remove_mac;
578
569 if (!mvm->bf_allowed_vif && 579 if (!mvm->bf_allowed_vif &&
570 vif->type == NL80211_IFTYPE_STATION && !vif->p2p){ 580 vif->type == NL80211_IFTYPE_STATION && !vif->p2p &&
581 mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BF_UPDATED){
571 mvm->bf_allowed_vif = mvmvif; 582 mvm->bf_allowed_vif = mvmvif;
572 vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER; 583 vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER |
584 IEEE80211_VIF_SUPPORTS_CQM_RSSI;
573 } 585 }
574 586
575 ret = iwl_mvm_disable_beacon_filter(mvm, vif);
576 if (ret)
577 goto out_release;
578
579 /* 587 /*
580 * P2P_DEVICE interface does not have a channel context assigned to it, 588 * P2P_DEVICE interface does not have a channel context assigned to it,
581 * so a dedicated PHY context is allocated to it and the corresponding 589 * so a dedicated PHY context is allocated to it and the corresponding
@@ -586,7 +594,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
586 mvmvif->phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm); 594 mvmvif->phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm);
587 if (!mvmvif->phy_ctxt) { 595 if (!mvmvif->phy_ctxt) {
588 ret = -ENOSPC; 596 ret = -ENOSPC;
589 goto out_remove_mac; 597 goto out_free_bf;
590 } 598 }
591 599
592 iwl_mvm_phy_ctxt_ref(mvm, mvmvif->phy_ctxt); 600 iwl_mvm_phy_ctxt_ref(mvm, mvmvif->phy_ctxt);
@@ -610,6 +618,12 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
610 iwl_mvm_binding_remove_vif(mvm, vif); 618 iwl_mvm_binding_remove_vif(mvm, vif);
611 out_unref_phy: 619 out_unref_phy:
612 iwl_mvm_phy_ctxt_unref(mvm, mvmvif->phy_ctxt); 620 iwl_mvm_phy_ctxt_unref(mvm, mvmvif->phy_ctxt);
621 out_free_bf:
622 if (mvm->bf_allowed_vif == mvmvif) {
623 mvm->bf_allowed_vif = NULL;
624 vif->driver_flags &= ~(IEEE80211_VIF_BEACON_FILTER |
625 IEEE80211_VIF_SUPPORTS_CQM_RSSI);
626 }
613 out_remove_mac: 627 out_remove_mac:
614 mvmvif->phy_ctxt = NULL; 628 mvmvif->phy_ctxt = NULL;
615 iwl_mvm_mac_ctxt_remove(mvm, vif); 629 iwl_mvm_mac_ctxt_remove(mvm, vif);
@@ -674,7 +688,8 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
674 688
675 if (mvm->bf_allowed_vif == mvmvif) { 689 if (mvm->bf_allowed_vif == mvmvif) {
676 mvm->bf_allowed_vif = NULL; 690 mvm->bf_allowed_vif = NULL;
677 vif->driver_flags &= ~IEEE80211_VIF_BEACON_FILTER; 691 vif->driver_flags &= ~(IEEE80211_VIF_BEACON_FILTER |
692 IEEE80211_VIF_SUPPORTS_CQM_RSSI);
678 } 693 }
679 694
680 iwl_mvm_vif_dbgfs_clean(mvm, vif); 695 iwl_mvm_vif_dbgfs_clean(mvm, vif);
@@ -719,6 +734,20 @@ out_release:
719 mutex_unlock(&mvm->mutex); 734 mutex_unlock(&mvm->mutex);
720} 735}
721 736
737static int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
738 s8 tx_power)
739{
740 /* FW is in charge of regulatory enforcement */
741 struct iwl_reduce_tx_power_cmd reduce_txpwr_cmd = {
742 .mac_context_id = iwl_mvm_vif_from_mac80211(vif)->id,
743 .pwr_restriction = cpu_to_le16(tx_power),
744 };
745
746 return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, CMD_SYNC,
747 sizeof(reduce_txpwr_cmd),
748 &reduce_txpwr_cmd);
749}
750
722static int iwl_mvm_mac_config(struct ieee80211_hw *hw, u32 changed) 751static int iwl_mvm_mac_config(struct ieee80211_hw *hw, u32 changed)
723{ 752{
724 return 0; 753 return 0;
@@ -766,7 +795,6 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
766 IWL_ERR(mvm, "failed to update quotas\n"); 795 IWL_ERR(mvm, "failed to update quotas\n");
767 return; 796 return;
768 } 797 }
769 iwl_mvm_bt_coex_vif_assoc(mvm, vif);
770 iwl_mvm_configure_mcast_filter(mvm, vif); 798 iwl_mvm_configure_mcast_filter(mvm, vif);
771 } else if (mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) { 799 } else if (mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) {
772 /* remove AP station now that the MAC is unassoc */ 800 /* remove AP station now that the MAC is unassoc */
@@ -779,9 +807,19 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
779 if (ret) 807 if (ret)
780 IWL_ERR(mvm, "failed to update quotas\n"); 808 IWL_ERR(mvm, "failed to update quotas\n");
781 } 809 }
782 ret = iwl_mvm_power_update_mode(mvm, vif); 810
783 if (ret) 811 /* reset rssi values */
784 IWL_ERR(mvm, "failed to update power mode\n"); 812 mvmvif->bf_data.ave_beacon_signal = 0;
813
814 if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD)) {
815 /* Workaround for FW bug, otherwise FW disables device
816 * power save upon disassociation
817 */
818 ret = iwl_mvm_power_update_mode(mvm, vif);
819 if (ret)
820 IWL_ERR(mvm, "failed to update power mode\n");
821 }
822 iwl_mvm_bt_coex_vif_assoc(mvm, vif);
785 } else if (changes & BSS_CHANGED_BEACON_INFO) { 823 } else if (changes & BSS_CHANGED_BEACON_INFO) {
786 /* 824 /*
787 * We received a beacon _after_ association so 825 * We received a beacon _after_ association so
@@ -789,11 +827,25 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
789 */ 827 */
790 iwl_mvm_remove_time_event(mvm, mvmvif, 828 iwl_mvm_remove_time_event(mvm, mvmvif,
791 &mvmvif->time_event_data); 829 &mvmvif->time_event_data);
792 } else if (changes & BSS_CHANGED_PS) { 830 } else if (changes & (BSS_CHANGED_PS | BSS_CHANGED_QOS)) {
793 ret = iwl_mvm_power_update_mode(mvm, vif); 831 ret = iwl_mvm_power_update_mode(mvm, vif);
794 if (ret) 832 if (ret)
795 IWL_ERR(mvm, "failed to update power mode\n"); 833 IWL_ERR(mvm, "failed to update power mode\n");
796 } 834 }
835 if (changes & BSS_CHANGED_TXPOWER) {
836 IWL_DEBUG_CALIB(mvm, "Changing TX Power to %d\n",
837 bss_conf->txpower);
838 iwl_mvm_set_tx_power(mvm, vif, bss_conf->txpower);
839 }
840
841 if (changes & BSS_CHANGED_CQM) {
842 IWL_DEBUG_MAC80211(mvm, "cqm info_changed");
843 /* reset cqm events tracking */
844 mvmvif->bf_data.last_cqm_event = 0;
845 ret = iwl_mvm_update_beacon_filter(mvm, vif);
846 if (ret)
847 IWL_ERR(mvm, "failed to update CQM thresholds\n");
848 }
797} 849}
798 850
799static int iwl_mvm_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif) 851static int iwl_mvm_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index 420e82d379d9..b0389279cc1e 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -76,6 +76,7 @@
76#include "iwl-trans.h" 76#include "iwl-trans.h"
77#include "sta.h" 77#include "sta.h"
78#include "fw-api.h" 78#include "fw-api.h"
79#include "constants.h"
79 80
80#define IWL_INVALID_MAC80211_QUEUE 0xff 81#define IWL_INVALID_MAC80211_QUEUE 0xff
81#define IWL_MVM_MAX_ADDRESSES 5 82#define IWL_MVM_MAX_ADDRESSES 5
@@ -91,6 +92,9 @@ enum iwl_mvm_tx_fifo {
91}; 92};
92 93
93extern struct ieee80211_ops iwl_mvm_hw_ops; 94extern struct ieee80211_ops iwl_mvm_hw_ops;
95extern const struct iwl_mvm_power_ops pm_legacy_ops;
96extern const struct iwl_mvm_power_ops pm_mac_ops;
97
94/** 98/**
95 * struct iwl_mvm_mod_params - module parameters for iwlmvm 99 * struct iwl_mvm_mod_params - module parameters for iwlmvm
96 * @init_dbg: if true, then the NIC won't be stopped if the INIT fw asserted. 100 * @init_dbg: if true, then the NIC won't be stopped if the INIT fw asserted.
@@ -149,6 +153,22 @@ enum iwl_power_scheme {
149}; 153};
150 154
151#define IWL_CONN_MAX_LISTEN_INTERVAL 70 155#define IWL_CONN_MAX_LISTEN_INTERVAL 70
156#define IWL_UAPSD_AC_INFO (IEEE80211_WMM_IE_STA_QOSINFO_AC_VO |\
157 IEEE80211_WMM_IE_STA_QOSINFO_AC_VI |\
158 IEEE80211_WMM_IE_STA_QOSINFO_AC_BK |\
159 IEEE80211_WMM_IE_STA_QOSINFO_AC_BE)
160#define IWL_UAPSD_MAX_SP IEEE80211_WMM_IE_STA_QOSINFO_SP_2
161
162struct iwl_mvm_power_ops {
163 int (*power_update_mode)(struct iwl_mvm *mvm,
164 struct ieee80211_vif *vif);
165 int (*power_disable)(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
166#ifdef CONFIG_IWLWIFI_DEBUGFS
167 int (*power_dbgfs_read)(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
168 char *buf, int bufsz);
169#endif
170};
171
152 172
153#ifdef CONFIG_IWLWIFI_DEBUGFS 173#ifdef CONFIG_IWLWIFI_DEBUGFS
154enum iwl_dbgfs_pm_mask { 174enum iwl_dbgfs_pm_mask {
@@ -160,10 +180,11 @@ enum iwl_dbgfs_pm_mask {
160 MVM_DEBUGFS_PM_DISABLE_POWER_OFF = BIT(5), 180 MVM_DEBUGFS_PM_DISABLE_POWER_OFF = BIT(5),
161 MVM_DEBUGFS_PM_LPRX_ENA = BIT(6), 181 MVM_DEBUGFS_PM_LPRX_ENA = BIT(6),
162 MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD = BIT(7), 182 MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD = BIT(7),
183 MVM_DEBUGFS_PM_SNOOZE_ENABLE = BIT(8),
163}; 184};
164 185
165struct iwl_dbgfs_pm { 186struct iwl_dbgfs_pm {
166 u8 keep_alive_seconds; 187 u16 keep_alive_seconds;
167 u32 rx_data_timeout; 188 u32 rx_data_timeout;
168 u32 tx_data_timeout; 189 u32 tx_data_timeout;
169 bool skip_over_dtim; 190 bool skip_over_dtim;
@@ -171,6 +192,7 @@ struct iwl_dbgfs_pm {
171 bool disable_power_off; 192 bool disable_power_off;
172 bool lprx_ena; 193 bool lprx_ena;
173 u32 lprx_rssi_threshold; 194 u32 lprx_rssi_threshold;
195 bool snooze_ena;
174 int mask; 196 int mask;
175}; 197};
176 198
@@ -180,24 +202,28 @@ enum iwl_dbgfs_bf_mask {
180 MVM_DEBUGFS_BF_ENERGY_DELTA = BIT(0), 202 MVM_DEBUGFS_BF_ENERGY_DELTA = BIT(0),
181 MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA = BIT(1), 203 MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA = BIT(1),
182 MVM_DEBUGFS_BF_ROAMING_STATE = BIT(2), 204 MVM_DEBUGFS_BF_ROAMING_STATE = BIT(2),
183 MVM_DEBUGFS_BF_TEMPERATURE_DELTA = BIT(3), 205 MVM_DEBUGFS_BF_TEMP_THRESHOLD = BIT(3),
184 MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER = BIT(4), 206 MVM_DEBUGFS_BF_TEMP_FAST_FILTER = BIT(4),
185 MVM_DEBUGFS_BF_DEBUG_FLAG = BIT(5), 207 MVM_DEBUGFS_BF_TEMP_SLOW_FILTER = BIT(5),
186 MVM_DEBUGFS_BF_ESCAPE_TIMER = BIT(6), 208 MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER = BIT(6),
187 MVM_DEBUGFS_BA_ESCAPE_TIMER = BIT(7), 209 MVM_DEBUGFS_BF_DEBUG_FLAG = BIT(7),
188 MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT = BIT(8), 210 MVM_DEBUGFS_BF_ESCAPE_TIMER = BIT(8),
211 MVM_DEBUGFS_BA_ESCAPE_TIMER = BIT(9),
212 MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT = BIT(10),
189}; 213};
190 214
191struct iwl_dbgfs_bf { 215struct iwl_dbgfs_bf {
192 u8 bf_energy_delta; 216 u32 bf_energy_delta;
193 u8 bf_roaming_energy_delta; 217 u32 bf_roaming_energy_delta;
194 u8 bf_roaming_state; 218 u32 bf_roaming_state;
195 u8 bf_temperature_delta; 219 u32 bf_temp_threshold;
196 u8 bf_enable_beacon_filter; 220 u32 bf_temp_fast_filter;
197 u8 bf_debug_flag; 221 u32 bf_temp_slow_filter;
222 u32 bf_enable_beacon_filter;
223 u32 bf_debug_flag;
198 u32 bf_escape_timer; 224 u32 bf_escape_timer;
199 u32 ba_escape_timer; 225 u32 ba_escape_timer;
200 u8 ba_enable_beacon_abort; 226 u32 ba_enable_beacon_abort;
201 int mask; 227 int mask;
202}; 228};
203#endif 229#endif
@@ -209,6 +235,21 @@ enum iwl_mvm_smps_type_request {
209}; 235};
210 236
211/** 237/**
238* struct iwl_mvm_vif_bf_data - beacon filtering related data
239* @bf_enabled: indicates if beacon filtering is enabled
240* @ba_enabled: indicated if beacon abort is enabled
241* @last_beacon_signal: last beacon rssi signal in dbm
242* @ave_beacon_signal: average beacon signal
243* @last_cqm_event: rssi of the last cqm event
244*/
245struct iwl_mvm_vif_bf_data {
246 bool bf_enabled;
247 bool ba_enabled;
248 s8 ave_beacon_signal;
249 s8 last_cqm_event;
250};
251
252/**
212 * struct iwl_mvm_vif - data per Virtual Interface, it is a MAC context 253 * struct iwl_mvm_vif - data per Virtual Interface, it is a MAC context
213 * @id: between 0 and 3 254 * @id: between 0 and 3
214 * @color: to solve races upon MAC addition and removal 255 * @color: to solve races upon MAC addition and removal
@@ -233,8 +274,7 @@ struct iwl_mvm_vif {
233 bool uploaded; 274 bool uploaded;
234 bool ap_active; 275 bool ap_active;
235 bool monitor_active; 276 bool monitor_active;
236 /* indicate whether beacon filtering is enabled */ 277 struct iwl_mvm_vif_bf_data bf_data;
237 bool bf_enabled;
238 278
239 u32 ap_beacon_time; 279 u32 ap_beacon_time;
240 280
@@ -268,7 +308,7 @@ struct iwl_mvm_vif {
268 308
269#if IS_ENABLED(CONFIG_IPV6) 309#if IS_ENABLED(CONFIG_IPV6)
270 /* IPv6 addresses for WoWLAN */ 310 /* IPv6 addresses for WoWLAN */
271 struct in6_addr target_ipv6_addrs[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS]; 311 struct in6_addr target_ipv6_addrs[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_MAX];
272 int num_target_ipv6_addrs; 312 int num_target_ipv6_addrs;
273#endif 313#endif
274#endif 314#endif
@@ -402,6 +442,8 @@ struct iwl_mvm {
402 442
403 struct iwl_notif_wait_data notif_wait; 443 struct iwl_notif_wait_data notif_wait;
404 444
445 struct mvm_statistics_rx rx_stats;
446
405 unsigned long transport_queue_stop; 447 unsigned long transport_queue_stop;
406 u8 queue_to_mac80211[IWL_MAX_HW_QUEUES]; 448 u8 queue_to_mac80211[IWL_MAX_HW_QUEUES];
407 atomic_t queue_stop_count[IWL_MAX_HW_QUEUES]; 449 atomic_t queue_stop_count[IWL_MAX_HW_QUEUES];
@@ -459,6 +501,9 @@ struct iwl_mvm {
459 */ 501 */
460 u8 vif_count; 502 u8 vif_count;
461 503
504 /* -1 for always, 0 for never, >0 for that many times */
505 s8 restart_fw;
506
462 struct led_classdev led; 507 struct led_classdev led;
463 508
464 struct ieee80211_vif *p2p_device_vif; 509 struct ieee80211_vif *p2p_device_vif;
@@ -482,6 +527,8 @@ struct iwl_mvm {
482 /* Thermal Throttling and CTkill */ 527 /* Thermal Throttling and CTkill */
483 struct iwl_mvm_tt_mgmt thermal_throttle; 528 struct iwl_mvm_tt_mgmt thermal_throttle;
484 s32 temperature; /* Celsius */ 529 s32 temperature; /* Celsius */
530
531 const struct iwl_mvm_power_ops *pm_ops;
485}; 532};
486 533
487/* Extract MVM priv from op_mode and _hw */ 534/* Extract MVM priv from op_mode and _hw */
@@ -525,6 +572,7 @@ int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags,
525 enum ieee80211_band band); 572 enum ieee80211_band band);
526u8 iwl_mvm_mac80211_idx_to_hwrate(int rate_idx); 573u8 iwl_mvm_mac80211_idx_to_hwrate(int rate_idx);
527void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm); 574void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm);
575void iwl_mvm_dump_sram(struct iwl_mvm *mvm);
528u8 first_antenna(u8 mask); 576u8 first_antenna(u8 mask);
529u8 iwl_mvm_next_antenna(struct iwl_mvm *mvm, u8 valid, u8 last_idx); 577u8 iwl_mvm_next_antenna(struct iwl_mvm *mvm, u8 valid, u8 last_idx);
530 578
@@ -660,10 +708,26 @@ int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq,
660 u8 flags, bool init); 708 u8 flags, bool init);
661 709
662/* power managment */ 710/* power managment */
663int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif); 711static inline int iwl_mvm_power_update_mode(struct iwl_mvm *mvm,
664int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif); 712 struct ieee80211_vif *vif)
665void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 713{
666 struct iwl_powertable_cmd *cmd); 714 return mvm->pm_ops->power_update_mode(mvm, vif);
715}
716
717static inline int iwl_mvm_power_disable(struct iwl_mvm *mvm,
718 struct ieee80211_vif *vif)
719{
720 return mvm->pm_ops->power_disable(mvm, vif);
721}
722
723#ifdef CONFIG_IWLWIFI_DEBUGFS
724static inline int iwl_mvm_power_dbgfs_read(struct iwl_mvm *mvm,
725 struct ieee80211_vif *vif,
726 char *buf, int bufsz)
727{
728 return mvm->pm_ops->power_dbgfs_read(mvm, vif, buf, bufsz);
729}
730#endif
667 731
668int iwl_mvm_leds_init(struct iwl_mvm *mvm); 732int iwl_mvm_leds_init(struct iwl_mvm *mvm);
669void iwl_mvm_leds_exit(struct iwl_mvm *mvm); 733void iwl_mvm_leds_exit(struct iwl_mvm *mvm);
@@ -707,6 +771,12 @@ int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
707 struct ieee80211_vif *vif); 771 struct ieee80211_vif *vif);
708int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm, 772int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
709 struct ieee80211_vif *vif); 773 struct ieee80211_vif *vif);
774int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm,
775 struct iwl_beacon_filter_cmd *cmd);
776int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm,
777 struct ieee80211_vif *vif, bool enable);
778int iwl_mvm_update_beacon_filter(struct iwl_mvm *mvm,
779 struct ieee80211_vif *vif);
710 780
711/* SMPS */ 781/* SMPS */
712void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 782void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c
index af79a14063a9..2fcc8ef88a68 100644
--- a/drivers/net/wireless/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/iwlwifi/mvm/ops.c
@@ -275,6 +275,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = {
275 CMD(BEACON_NOTIFICATION), 275 CMD(BEACON_NOTIFICATION),
276 CMD(BEACON_TEMPLATE_CMD), 276 CMD(BEACON_TEMPLATE_CMD),
277 CMD(STATISTICS_NOTIFICATION), 277 CMD(STATISTICS_NOTIFICATION),
278 CMD(REDUCE_TX_POWER_CMD),
278 CMD(TX_ANT_CONFIGURATION_CMD), 279 CMD(TX_ANT_CONFIGURATION_CMD),
279 CMD(D3_CONFIG_CMD), 280 CMD(D3_CONFIG_CMD),
280 CMD(PROT_OFFLOAD_CONFIG_CMD), 281 CMD(PROT_OFFLOAD_CONFIG_CMD),
@@ -301,6 +302,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = {
301 CMD(MCAST_FILTER_CMD), 302 CMD(MCAST_FILTER_CMD),
302 CMD(REPLY_BEACON_FILTERING_CMD), 303 CMD(REPLY_BEACON_FILTERING_CMD),
303 CMD(REPLY_THERMAL_MNG_BACKOFF), 304 CMD(REPLY_THERMAL_MNG_BACKOFF),
305 CMD(MAC_PM_POWER_TABLE),
304}; 306};
305#undef CMD 307#undef CMD
306 308
@@ -340,6 +342,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
340 mvm->fw = fw; 342 mvm->fw = fw;
341 mvm->hw = hw; 343 mvm->hw = hw;
342 344
345 mvm->restart_fw = iwlwifi_mod_params.restart_fw ? -1 : 0;
346
343 mutex_init(&mvm->mutex); 347 mutex_init(&mvm->mutex);
344 spin_lock_init(&mvm->async_handlers_lock); 348 spin_lock_init(&mvm->async_handlers_lock);
345 INIT_LIST_HEAD(&mvm->time_event_list); 349 INIT_LIST_HEAD(&mvm->time_event_list);
@@ -431,6 +435,13 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
431 if (err) 435 if (err)
432 goto out_unregister; 436 goto out_unregister;
433 437
438 if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD)
439 mvm->pm_ops = &pm_mac_ops;
440 else
441 mvm->pm_ops = &pm_legacy_ops;
442
443 memset(&mvm->rx_stats, 0, sizeof(struct mvm_statistics_rx));
444
434 return op_mode; 445 return op_mode;
435 446
436 out_unregister: 447 out_unregister:
@@ -638,6 +649,22 @@ static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
638 ieee80211_free_txskb(mvm->hw, skb); 649 ieee80211_free_txskb(mvm->hw, skb);
639} 650}
640 651
652struct iwl_mvm_reprobe {
653 struct device *dev;
654 struct work_struct work;
655};
656
657static void iwl_mvm_reprobe_wk(struct work_struct *wk)
658{
659 struct iwl_mvm_reprobe *reprobe;
660
661 reprobe = container_of(wk, struct iwl_mvm_reprobe, work);
662 if (device_reprobe(reprobe->dev))
663 dev_err(reprobe->dev, "reprobe failed!\n");
664 kfree(reprobe);
665 module_put(THIS_MODULE);
666}
667
641static void iwl_mvm_nic_restart(struct iwl_mvm *mvm) 668static void iwl_mvm_nic_restart(struct iwl_mvm *mvm)
642{ 669{
643 iwl_abort_notification_waits(&mvm->notif_wait); 670 iwl_abort_notification_waits(&mvm->notif_wait);
@@ -649,9 +676,30 @@ static void iwl_mvm_nic_restart(struct iwl_mvm *mvm)
649 * can't recover this since we're already half suspended. 676 * can't recover this since we're already half suspended.
650 */ 677 */
651 if (test_and_set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { 678 if (test_and_set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
652 IWL_ERR(mvm, "Firmware error during reconfiguration! Abort.\n"); 679 struct iwl_mvm_reprobe *reprobe;
653 } else if (mvm->cur_ucode == IWL_UCODE_REGULAR && 680
654 iwlwifi_mod_params.restart_fw) { 681 IWL_ERR(mvm,
682 "Firmware error during reconfiguration - reprobe!\n");
683
684 /*
685 * get a module reference to avoid doing this while unloading
686 * anyway and to avoid scheduling a work with code that's
687 * being removed.
688 */
689 if (!try_module_get(THIS_MODULE)) {
690 IWL_ERR(mvm, "Module is being unloaded - abort\n");
691 return;
692 }
693
694 reprobe = kzalloc(sizeof(*reprobe), GFP_ATOMIC);
695 if (!reprobe) {
696 module_put(THIS_MODULE);
697 return;
698 }
699 reprobe->dev = mvm->trans->dev;
700 INIT_WORK(&reprobe->work, iwl_mvm_reprobe_wk);
701 schedule_work(&reprobe->work);
702 } else if (mvm->cur_ucode == IWL_UCODE_REGULAR && mvm->restart_fw) {
655 /* 703 /*
656 * This is a bit racy, but worst case we tell mac80211 about 704 * This is a bit racy, but worst case we tell mac80211 about
657 * a stopped/aborted (sched) scan when that was already done 705 * a stopped/aborted (sched) scan when that was already done
@@ -669,6 +717,8 @@ static void iwl_mvm_nic_restart(struct iwl_mvm *mvm)
669 break; 717 break;
670 } 718 }
671 719
720 if (mvm->restart_fw > 0)
721 mvm->restart_fw--;
672 ieee80211_restart_hw(mvm->hw); 722 ieee80211_restart_hw(mvm->hw);
673 } 723 }
674} 724}
@@ -678,6 +728,8 @@ static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode)
678 struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); 728 struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
679 729
680 iwl_mvm_dump_nic_error_log(mvm); 730 iwl_mvm_dump_nic_error_log(mvm);
731 if (!mvm->restart_fw)
732 iwl_mvm_dump_sram(mvm);
681 733
682 iwl_mvm_nic_restart(mvm); 734 iwl_mvm_nic_restart(mvm);
683} 735}
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c
index e7ca965a89b8..21407a353a3b 100644
--- a/drivers/net/wireless/iwlwifi/mvm/power.c
+++ b/drivers/net/wireless/iwlwifi/mvm/power.c
@@ -75,8 +75,8 @@
75 75
76#define POWER_KEEP_ALIVE_PERIOD_SEC 25 76#define POWER_KEEP_ALIVE_PERIOD_SEC 25
77 77
78static int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm, 78int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm,
79 struct iwl_beacon_filter_cmd *cmd) 79 struct iwl_beacon_filter_cmd *cmd)
80{ 80{
81 int ret; 81 int ret;
82 82
@@ -85,69 +85,110 @@ static int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm,
85 85
86 if (!ret) { 86 if (!ret) {
87 IWL_DEBUG_POWER(mvm, "ba_enable_beacon_abort is: %d\n", 87 IWL_DEBUG_POWER(mvm, "ba_enable_beacon_abort is: %d\n",
88 cmd->ba_enable_beacon_abort); 88 le32_to_cpu(cmd->ba_enable_beacon_abort));
89 IWL_DEBUG_POWER(mvm, "ba_escape_timer is: %d\n", 89 IWL_DEBUG_POWER(mvm, "ba_escape_timer is: %d\n",
90 cmd->ba_escape_timer); 90 le32_to_cpu(cmd->ba_escape_timer));
91 IWL_DEBUG_POWER(mvm, "bf_debug_flag is: %d\n", 91 IWL_DEBUG_POWER(mvm, "bf_debug_flag is: %d\n",
92 cmd->bf_debug_flag); 92 le32_to_cpu(cmd->bf_debug_flag));
93 IWL_DEBUG_POWER(mvm, "bf_enable_beacon_filter is: %d\n", 93 IWL_DEBUG_POWER(mvm, "bf_enable_beacon_filter is: %d\n",
94 cmd->bf_enable_beacon_filter); 94 le32_to_cpu(cmd->bf_enable_beacon_filter));
95 IWL_DEBUG_POWER(mvm, "bf_energy_delta is: %d\n", 95 IWL_DEBUG_POWER(mvm, "bf_energy_delta is: %d\n",
96 cmd->bf_energy_delta); 96 le32_to_cpu(cmd->bf_energy_delta));
97 IWL_DEBUG_POWER(mvm, "bf_escape_timer is: %d\n", 97 IWL_DEBUG_POWER(mvm, "bf_escape_timer is: %d\n",
98 cmd->bf_escape_timer); 98 le32_to_cpu(cmd->bf_escape_timer));
99 IWL_DEBUG_POWER(mvm, "bf_roaming_energy_delta is: %d\n", 99 IWL_DEBUG_POWER(mvm, "bf_roaming_energy_delta is: %d\n",
100 cmd->bf_roaming_energy_delta); 100 le32_to_cpu(cmd->bf_roaming_energy_delta));
101 IWL_DEBUG_POWER(mvm, "bf_roaming_state is: %d\n", 101 IWL_DEBUG_POWER(mvm, "bf_roaming_state is: %d\n",
102 cmd->bf_roaming_state); 102 le32_to_cpu(cmd->bf_roaming_state));
103 IWL_DEBUG_POWER(mvm, "bf_temperature_delta is: %d\n", 103 IWL_DEBUG_POWER(mvm, "bf_temp_threshold is: %d\n",
104 cmd->bf_temperature_delta); 104 le32_to_cpu(cmd->bf_temp_threshold));
105 IWL_DEBUG_POWER(mvm, "bf_temp_fast_filter is: %d\n",
106 le32_to_cpu(cmd->bf_temp_fast_filter));
107 IWL_DEBUG_POWER(mvm, "bf_temp_slow_filter is: %d\n",
108 le32_to_cpu(cmd->bf_temp_slow_filter));
105 } 109 }
106 return ret; 110 return ret;
107} 111}
108 112
109static int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm, 113static
110 struct ieee80211_vif *vif, bool enable) 114void iwl_mvm_beacon_filter_set_cqm_params(struct iwl_mvm *mvm,
115 struct ieee80211_vif *vif,
116 struct iwl_beacon_filter_cmd *cmd)
117{
118 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
119
120 if (vif->bss_conf.cqm_rssi_thold) {
121 cmd->bf_energy_delta =
122 cpu_to_le32(vif->bss_conf.cqm_rssi_hyst);
123 /* fw uses an absolute value for this */
124 cmd->bf_roaming_state =
125 cpu_to_le32(-vif->bss_conf.cqm_rssi_thold);
126 }
127 cmd->ba_enable_beacon_abort = cpu_to_le32(mvmvif->bf_data.ba_enabled);
128}
129
130int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm,
131 struct ieee80211_vif *vif, bool enable)
111{ 132{
112 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 133 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
113 struct iwl_beacon_filter_cmd cmd = { 134 struct iwl_beacon_filter_cmd cmd = {
114 IWL_BF_CMD_CONFIG_DEFAULTS, 135 IWL_BF_CMD_CONFIG_DEFAULTS,
115 .bf_enable_beacon_filter = 1, 136 .bf_enable_beacon_filter = cpu_to_le32(1),
116 .ba_enable_beacon_abort = enable, 137 .ba_enable_beacon_abort = cpu_to_le32(enable),
117 }; 138 };
118 139
119 if (!mvmvif->bf_enabled) 140 if (!mvmvif->bf_data.bf_enabled)
120 return 0; 141 return 0;
121 142
143 if (mvm->cur_ucode == IWL_UCODE_WOWLAN)
144 cmd.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_D3);
145
146 mvmvif->bf_data.ba_enabled = enable;
147 iwl_mvm_beacon_filter_set_cqm_params(mvm, vif, &cmd);
122 iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd); 148 iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd);
123 return iwl_mvm_beacon_filter_send_cmd(mvm, &cmd); 149 return iwl_mvm_beacon_filter_send_cmd(mvm, &cmd);
124} 150}
125 151
126static void iwl_mvm_power_log(struct iwl_mvm *mvm, 152static void iwl_mvm_power_log(struct iwl_mvm *mvm,
127 struct iwl_powertable_cmd *cmd) 153 struct iwl_mac_power_cmd *cmd)
128{ 154{
129 IWL_DEBUG_POWER(mvm, 155 IWL_DEBUG_POWER(mvm,
130 "Sending power table command for power level %d, flags = 0x%X\n", 156 "Sending power table command on mac id 0x%X for power level %d, flags = 0x%X\n",
131 iwlmvm_mod_params.power_scheme, 157 cmd->id_and_color, iwlmvm_mod_params.power_scheme,
132 le16_to_cpu(cmd->flags)); 158 le16_to_cpu(cmd->flags));
133 IWL_DEBUG_POWER(mvm, "Keep alive = %u sec\n", cmd->keep_alive_seconds); 159 IWL_DEBUG_POWER(mvm, "Keep alive = %u sec\n",
134 160 le16_to_cpu(cmd->keep_alive_seconds));
135 if (cmd->flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) { 161
136 IWL_DEBUG_POWER(mvm, "Rx timeout = %u usec\n", 162 if (!(cmd->flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK))) {
137 le32_to_cpu(cmd->rx_data_timeout)); 163 IWL_DEBUG_POWER(mvm, "Disable power management\n");
138 IWL_DEBUG_POWER(mvm, "Tx timeout = %u usec\n", 164 return;
139 le32_to_cpu(cmd->tx_data_timeout)); 165 }
140 if (cmd->flags & cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) 166
141 IWL_DEBUG_POWER(mvm, "DTIM periods to skip = %u\n", 167 IWL_DEBUG_POWER(mvm, "Rx timeout = %u usec\n",
142 le32_to_cpu(cmd->skip_dtim_periods)); 168 le32_to_cpu(cmd->rx_data_timeout));
143 if (cmd->flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK)) 169 IWL_DEBUG_POWER(mvm, "Tx timeout = %u usec\n",
144 IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n", 170 le32_to_cpu(cmd->tx_data_timeout));
145 le32_to_cpu(cmd->lprx_rssi_threshold)); 171 if (cmd->flags & cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK))
172 IWL_DEBUG_POWER(mvm, "DTIM periods to skip = %u\n",
173 cmd->skip_dtim_periods);
174 if (cmd->flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
175 IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n",
176 cmd->lprx_rssi_threshold);
177 if (cmd->flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK)) {
178 IWL_DEBUG_POWER(mvm, "uAPSD enabled\n");
179 IWL_DEBUG_POWER(mvm, "Rx timeout (uAPSD) = %u usec\n",
180 le32_to_cpu(cmd->rx_data_timeout_uapsd));
181 IWL_DEBUG_POWER(mvm, "Tx timeout (uAPSD) = %u usec\n",
182 le32_to_cpu(cmd->tx_data_timeout_uapsd));
183 IWL_DEBUG_POWER(mvm, "QNDP TID = %d\n", cmd->qndp_tid);
184 IWL_DEBUG_POWER(mvm, "ACs flags = 0x%x\n", cmd->uapsd_ac_flags);
185 IWL_DEBUG_POWER(mvm, "Max SP = %d\n", cmd->uapsd_max_sp);
146 } 186 }
147} 187}
148 188
149void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 189static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
150 struct iwl_powertable_cmd *cmd) 190 struct ieee80211_vif *vif,
191 struct iwl_mac_power_cmd *cmd)
151{ 192{
152 struct ieee80211_hw *hw = mvm->hw; 193 struct ieee80211_hw *hw = mvm->hw;
153 struct ieee80211_chanctx_conf *chanctx_conf; 194 struct ieee80211_chanctx_conf *chanctx_conf;
@@ -157,20 +198,29 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
157 bool radar_detect = false; 198 bool radar_detect = false;
158 struct iwl_mvm_vif *mvmvif __maybe_unused = 199 struct iwl_mvm_vif *mvmvif __maybe_unused =
159 iwl_mvm_vif_from_mac80211(vif); 200 iwl_mvm_vif_from_mac80211(vif);
201 enum ieee80211_ac_numbers ac;
202 bool tid_found = false;
203
204 cmd->id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
205 mvmvif->color));
206 dtimper = hw->conf.ps_dtim_period ?: 1;
160 207
161 /* 208 /*
162 * Regardless of power management state the driver must set 209 * Regardless of power management state the driver must set
163 * keep alive period. FW will use it for sending keep alive NDPs 210 * keep alive period. FW will use it for sending keep alive NDPs
164 * immediately after association. 211 * immediately after association. Check that keep alive period
212 * is at least 3 * DTIM
165 */ 213 */
166 cmd->keep_alive_seconds = POWER_KEEP_ALIVE_PERIOD_SEC; 214 dtimper_msec = dtimper * vif->bss_conf.beacon_int;
215 keep_alive = max_t(int, 3 * dtimper_msec,
216 MSEC_PER_SEC * POWER_KEEP_ALIVE_PERIOD_SEC);
217 keep_alive = DIV_ROUND_UP(keep_alive, MSEC_PER_SEC);
218 cmd->keep_alive_seconds = cpu_to_le16(keep_alive);
167 219
168 if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM) 220 if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM)
169 return; 221 return;
170 222
171 cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK); 223 cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
172 if (!vif->bss_conf.assoc)
173 cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
174 224
175#ifdef CONFIG_IWLWIFI_DEBUGFS 225#ifdef CONFIG_IWLWIFI_DEBUGFS
176 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_DISABLE_POWER_OFF && 226 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_DISABLE_POWER_OFF &&
@@ -186,12 +236,9 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
186 (vif->bss_conf.beacon_rate->bitrate == 10 || 236 (vif->bss_conf.beacon_rate->bitrate == 10 ||
187 vif->bss_conf.beacon_rate->bitrate == 60)) { 237 vif->bss_conf.beacon_rate->bitrate == 60)) {
188 cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK); 238 cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
189 cmd->lprx_rssi_threshold = 239 cmd->lprx_rssi_threshold = POWER_LPRX_RSSI_THRESHOLD;
190 cpu_to_le32(POWER_LPRX_RSSI_THRESHOLD);
191 } 240 }
192 241
193 dtimper = hw->conf.ps_dtim_period ?: 1;
194
195 /* Check if radar detection is required on current channel */ 242 /* Check if radar detection is required on current channel */
196 rcu_read_lock(); 243 rcu_read_lock();
197 chanctx_conf = rcu_dereference(vif->chanctx_conf); 244 chanctx_conf = rcu_dereference(vif->chanctx_conf);
@@ -207,27 +254,82 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
207 (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP || 254 (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP ||
208 mvm->cur_ucode == IWL_UCODE_WOWLAN)) { 255 mvm->cur_ucode == IWL_UCODE_WOWLAN)) {
209 cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK); 256 cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
210 cmd->skip_dtim_periods = cpu_to_le32(3); 257 cmd->skip_dtim_periods = 3;
211 } 258 }
212 259
213 /* Check that keep alive period is at least 3 * DTIM */
214 dtimper_msec = dtimper * vif->bss_conf.beacon_int;
215 keep_alive = max_t(int, 3 * dtimper_msec,
216 MSEC_PER_SEC * cmd->keep_alive_seconds);
217 keep_alive = DIV_ROUND_UP(keep_alive, MSEC_PER_SEC);
218 cmd->keep_alive_seconds = keep_alive;
219
220 if (mvm->cur_ucode != IWL_UCODE_WOWLAN) { 260 if (mvm->cur_ucode != IWL_UCODE_WOWLAN) {
221 cmd->rx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC); 261 cmd->rx_data_timeout =
222 cmd->tx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC); 262 cpu_to_le32(IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT);
263 cmd->tx_data_timeout =
264 cpu_to_le32(IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT);
223 } else { 265 } else {
224 cmd->rx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC); 266 cmd->rx_data_timeout =
225 cmd->tx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC); 267 cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT);
268 cmd->tx_data_timeout =
269 cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT);
270 }
271
272 for (ac = IEEE80211_AC_VO; ac <= IEEE80211_AC_BK; ac++) {
273 if (!mvmvif->queue_params[ac].uapsd)
274 continue;
275
276 cmd->flags |= cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK);
277 cmd->uapsd_ac_flags |= BIT(ac);
278
279 /* QNDP TID - the highest TID with no admission control */
280 if (!tid_found && !mvmvif->queue_params[ac].acm) {
281 tid_found = true;
282 switch (ac) {
283 case IEEE80211_AC_VO:
284 cmd->qndp_tid = 6;
285 break;
286 case IEEE80211_AC_VI:
287 cmd->qndp_tid = 5;
288 break;
289 case IEEE80211_AC_BE:
290 cmd->qndp_tid = 0;
291 break;
292 case IEEE80211_AC_BK:
293 cmd->qndp_tid = 1;
294 break;
295 }
296 }
297 }
298
299 if (cmd->flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK)) {
300 cmd->rx_data_timeout_uapsd =
301 cpu_to_le32(IWL_MVM_UAPSD_RX_DATA_TIMEOUT);
302 cmd->tx_data_timeout_uapsd =
303 cpu_to_le32(IWL_MVM_UAPSD_TX_DATA_TIMEOUT);
304
305 if (cmd->uapsd_ac_flags == (BIT(IEEE80211_AC_VO) |
306 BIT(IEEE80211_AC_VI) |
307 BIT(IEEE80211_AC_BE) |
308 BIT(IEEE80211_AC_BK))) {
309 cmd->flags |= cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK);
310 cmd->snooze_interval =
311 cpu_to_le16(IWL_MVM_PS_SNOOZE_INTERVAL);
312 cmd->snooze_window =
313 (mvm->cur_ucode == IWL_UCODE_WOWLAN) ?
314 cpu_to_le16(IWL_MVM_WOWLAN_PS_SNOOZE_WINDOW) :
315 cpu_to_le16(IWL_MVM_PS_SNOOZE_WINDOW);
316 }
317
318 cmd->uapsd_max_sp = IWL_UAPSD_MAX_SP;
319 cmd->heavy_tx_thld_packets =
320 IWL_MVM_PS_HEAVY_TX_THLD_PACKETS;
321 cmd->heavy_rx_thld_packets =
322 IWL_MVM_PS_HEAVY_RX_THLD_PACKETS;
323 cmd->heavy_tx_thld_percentage =
324 IWL_MVM_PS_HEAVY_TX_THLD_PERCENT;
325 cmd->heavy_rx_thld_percentage =
326 IWL_MVM_PS_HEAVY_RX_THLD_PERCENT;
226 } 327 }
227 328
228#ifdef CONFIG_IWLWIFI_DEBUGFS 329#ifdef CONFIG_IWLWIFI_DEBUGFS
229 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_KEEP_ALIVE) 330 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_KEEP_ALIVE)
230 cmd->keep_alive_seconds = mvmvif->dbgfs_pm.keep_alive_seconds; 331 cmd->keep_alive_seconds =
332 cpu_to_le16(mvmvif->dbgfs_pm.keep_alive_seconds);
231 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_OVER_DTIM) { 333 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_OVER_DTIM) {
232 if (mvmvif->dbgfs_pm.skip_over_dtim) 334 if (mvmvif->dbgfs_pm.skip_over_dtim)
233 cmd->flags |= 335 cmd->flags |=
@@ -243,8 +345,7 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
243 cmd->tx_data_timeout = 345 cmd->tx_data_timeout =
244 cpu_to_le32(mvmvif->dbgfs_pm.tx_data_timeout); 346 cpu_to_le32(mvmvif->dbgfs_pm.tx_data_timeout);
245 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS) 347 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS)
246 cmd->skip_dtim_periods = 348 cmd->skip_dtim_periods = mvmvif->dbgfs_pm.skip_dtim_periods;
247 cpu_to_le32(mvmvif->dbgfs_pm.skip_dtim_periods);
248 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_ENA) { 349 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_ENA) {
249 if (mvmvif->dbgfs_pm.lprx_ena) 350 if (mvmvif->dbgfs_pm.lprx_ena)
250 cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK); 351 cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
@@ -252,16 +353,24 @@ void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
252 cmd->flags &= cpu_to_le16(~POWER_FLAGS_LPRX_ENA_MSK); 353 cmd->flags &= cpu_to_le16(~POWER_FLAGS_LPRX_ENA_MSK);
253 } 354 }
254 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD) 355 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD)
255 cmd->lprx_rssi_threshold = 356 cmd->lprx_rssi_threshold = mvmvif->dbgfs_pm.lprx_rssi_threshold;
256 cpu_to_le32(mvmvif->dbgfs_pm.lprx_rssi_threshold); 357 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SNOOZE_ENABLE) {
358 if (mvmvif->dbgfs_pm.snooze_ena)
359 cmd->flags |=
360 cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK);
361 else
362 cmd->flags &=
363 cpu_to_le16(~POWER_FLAGS_SNOOZE_ENA_MSK);
364 }
257#endif /* CONFIG_IWLWIFI_DEBUGFS */ 365#endif /* CONFIG_IWLWIFI_DEBUGFS */
258} 366}
259 367
260int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif) 368static int iwl_mvm_power_mac_update_mode(struct iwl_mvm *mvm,
369 struct ieee80211_vif *vif)
261{ 370{
262 int ret; 371 int ret;
263 bool ba_enable; 372 bool ba_enable;
264 struct iwl_powertable_cmd cmd = {}; 373 struct iwl_mac_power_cmd cmd = {};
265 374
266 if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) 375 if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
267 return 0; 376 return 0;
@@ -280,7 +389,7 @@ int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
280 iwl_mvm_power_build_cmd(mvm, vif, &cmd); 389 iwl_mvm_power_build_cmd(mvm, vif, &cmd);
281 iwl_mvm_power_log(mvm, &cmd); 390 iwl_mvm_power_log(mvm, &cmd);
282 391
283 ret = iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_SYNC, 392 ret = iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, CMD_SYNC,
284 sizeof(cmd), &cmd); 393 sizeof(cmd), &cmd);
285 if (ret) 394 if (ret)
286 return ret; 395 return ret;
@@ -291,15 +400,19 @@ int iwl_mvm_power_update_mode(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
291 return iwl_mvm_update_beacon_abort(mvm, vif, ba_enable); 400 return iwl_mvm_update_beacon_abort(mvm, vif, ba_enable);
292} 401}
293 402
294int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif) 403static int iwl_mvm_power_mac_disable(struct iwl_mvm *mvm,
404 struct ieee80211_vif *vif)
295{ 405{
296 struct iwl_powertable_cmd cmd = {}; 406 struct iwl_mac_power_cmd cmd = {};
297 struct iwl_mvm_vif *mvmvif __maybe_unused = 407 struct iwl_mvm_vif *mvmvif __maybe_unused =
298 iwl_mvm_vif_from_mac80211(vif); 408 iwl_mvm_vif_from_mac80211(vif);
299 409
300 if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) 410 if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
301 return 0; 411 return 0;
302 412
413 cmd.id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
414 mvmvif->color));
415
303 if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM) 416 if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM)
304 cmd.flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK); 417 cmd.flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
305 418
@@ -310,11 +423,98 @@ int iwl_mvm_power_disable(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
310#endif 423#endif
311 iwl_mvm_power_log(mvm, &cmd); 424 iwl_mvm_power_log(mvm, &cmd);
312 425
313 return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_ASYNC, 426 return iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, CMD_ASYNC,
314 sizeof(cmd), &cmd); 427 sizeof(cmd), &cmd);
315} 428}
316 429
317#ifdef CONFIG_IWLWIFI_DEBUGFS 430#ifdef CONFIG_IWLWIFI_DEBUGFS
431static int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm,
432 struct ieee80211_vif *vif, char *buf,
433 int bufsz)
434{
435 struct iwl_mac_power_cmd cmd = {};
436 int pos = 0;
437
438 iwl_mvm_power_build_cmd(mvm, vif, &cmd);
439
440 pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off = %d\n",
441 (cmd.flags &
442 cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK)) ?
443 0 : 1);
444 pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n",
445 iwlmvm_mod_params.power_scheme);
446 pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n",
447 le16_to_cpu(cmd.flags));
448 pos += scnprintf(buf+pos, bufsz-pos, "keep_alive = %d\n",
449 le16_to_cpu(cmd.keep_alive_seconds));
450
451 if (cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) {
452 pos += scnprintf(buf+pos, bufsz-pos, "skip_over_dtim = %d\n",
453 (cmd.flags &
454 cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) ?
455 1 : 0);
456 pos += scnprintf(buf+pos, bufsz-pos, "skip_dtim_periods = %d\n",
457 cmd.skip_dtim_periods);
458 if (!(cmd.flags &
459 cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK))) {
460 pos += scnprintf(buf+pos, bufsz-pos,
461 "rx_data_timeout = %d\n",
462 le32_to_cpu(cmd.rx_data_timeout));
463 pos += scnprintf(buf+pos, bufsz-pos,
464 "tx_data_timeout = %d\n",
465 le32_to_cpu(cmd.tx_data_timeout));
466 }
467 if (cmd.flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
468 pos += scnprintf(buf+pos, bufsz-pos,
469 "lprx_rssi_threshold = %d\n",
470 cmd.lprx_rssi_threshold);
471 if (cmd.flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK)) {
472 pos +=
473 scnprintf(buf+pos, bufsz-pos,
474 "rx_data_timeout_uapsd = %d\n",
475 le32_to_cpu(cmd.rx_data_timeout_uapsd));
476 pos +=
477 scnprintf(buf+pos, bufsz-pos,
478 "tx_data_timeout_uapsd = %d\n",
479 le32_to_cpu(cmd.tx_data_timeout_uapsd));
480 pos += scnprintf(buf+pos, bufsz-pos, "qndp_tid = %d\n",
481 cmd.qndp_tid);
482 pos += scnprintf(buf+pos, bufsz-pos,
483 "uapsd_ac_flags = 0x%x\n",
484 cmd.uapsd_ac_flags);
485 pos += scnprintf(buf+pos, bufsz-pos,
486 "uapsd_max_sp = %d\n",
487 cmd.uapsd_max_sp);
488 pos += scnprintf(buf+pos, bufsz-pos,
489 "heavy_tx_thld_packets = %d\n",
490 cmd.heavy_tx_thld_packets);
491 pos += scnprintf(buf+pos, bufsz-pos,
492 "heavy_rx_thld_packets = %d\n",
493 cmd.heavy_rx_thld_packets);
494 pos += scnprintf(buf+pos, bufsz-pos,
495 "heavy_tx_thld_percentage = %d\n",
496 cmd.heavy_tx_thld_percentage);
497 pos += scnprintf(buf+pos, bufsz-pos,
498 "heavy_rx_thld_percentage = %d\n",
499 cmd.heavy_rx_thld_percentage);
500 pos +=
501 scnprintf(buf+pos, bufsz-pos, "snooze_enable = %d\n",
502 (cmd.flags &
503 cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) ?
504 1 : 0);
505 }
506 if (cmd.flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) {
507 pos += scnprintf(buf+pos, bufsz-pos,
508 "snooze_interval = %d\n",
509 cmd.snooze_interval);
510 pos += scnprintf(buf+pos, bufsz-pos,
511 "snooze_window = %d\n",
512 cmd.snooze_window);
513 }
514 }
515 return pos;
516}
517
318void 518void
319iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif, 519iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif,
320 struct iwl_beacon_filter_cmd *cmd) 520 struct iwl_beacon_filter_cmd *cmd)
@@ -323,22 +523,30 @@ iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif,
323 struct iwl_dbgfs_bf *dbgfs_bf = &mvmvif->dbgfs_bf; 523 struct iwl_dbgfs_bf *dbgfs_bf = &mvmvif->dbgfs_bf;
324 524
325 if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ENERGY_DELTA) 525 if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ENERGY_DELTA)
326 cmd->bf_energy_delta = dbgfs_bf->bf_energy_delta; 526 cmd->bf_energy_delta = cpu_to_le32(dbgfs_bf->bf_energy_delta);
327 if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA) 527 if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA)
328 cmd->bf_roaming_energy_delta = 528 cmd->bf_roaming_energy_delta =
329 dbgfs_bf->bf_roaming_energy_delta; 529 cpu_to_le32(dbgfs_bf->bf_roaming_energy_delta);
330 if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_STATE) 530 if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_STATE)
331 cmd->bf_roaming_state = dbgfs_bf->bf_roaming_state; 531 cmd->bf_roaming_state = cpu_to_le32(dbgfs_bf->bf_roaming_state);
332 if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMPERATURE_DELTA) 532 if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_THRESHOLD)
333 cmd->bf_temperature_delta = dbgfs_bf->bf_temperature_delta; 533 cmd->bf_temp_threshold =
534 cpu_to_le32(dbgfs_bf->bf_temp_threshold);
535 if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_FAST_FILTER)
536 cmd->bf_temp_fast_filter =
537 cpu_to_le32(dbgfs_bf->bf_temp_fast_filter);
538 if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_SLOW_FILTER)
539 cmd->bf_temp_slow_filter =
540 cpu_to_le32(dbgfs_bf->bf_temp_slow_filter);
334 if (dbgfs_bf->mask & MVM_DEBUGFS_BF_DEBUG_FLAG) 541 if (dbgfs_bf->mask & MVM_DEBUGFS_BF_DEBUG_FLAG)
335 cmd->bf_debug_flag = dbgfs_bf->bf_debug_flag; 542 cmd->bf_debug_flag = cpu_to_le32(dbgfs_bf->bf_debug_flag);
336 if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ESCAPE_TIMER) 543 if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ESCAPE_TIMER)
337 cmd->bf_escape_timer = cpu_to_le32(dbgfs_bf->bf_escape_timer); 544 cmd->bf_escape_timer = cpu_to_le32(dbgfs_bf->bf_escape_timer);
338 if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ESCAPE_TIMER) 545 if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ESCAPE_TIMER)
339 cmd->ba_escape_timer = cpu_to_le32(dbgfs_bf->ba_escape_timer); 546 cmd->ba_escape_timer = cpu_to_le32(dbgfs_bf->ba_escape_timer);
340 if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT) 547 if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT)
341 cmd->ba_enable_beacon_abort = dbgfs_bf->ba_enable_beacon_abort; 548 cmd->ba_enable_beacon_abort =
549 cpu_to_le32(dbgfs_bf->ba_enable_beacon_abort);
342} 550}
343#endif 551#endif
344 552
@@ -348,7 +556,7 @@ int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
348 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 556 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
349 struct iwl_beacon_filter_cmd cmd = { 557 struct iwl_beacon_filter_cmd cmd = {
350 IWL_BF_CMD_CONFIG_DEFAULTS, 558 IWL_BF_CMD_CONFIG_DEFAULTS,
351 .bf_enable_beacon_filter = 1, 559 .bf_enable_beacon_filter = cpu_to_le32(1),
352 }; 560 };
353 int ret; 561 int ret;
354 562
@@ -356,11 +564,12 @@ int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
356 vif->type != NL80211_IFTYPE_STATION || vif->p2p) 564 vif->type != NL80211_IFTYPE_STATION || vif->p2p)
357 return 0; 565 return 0;
358 566
567 iwl_mvm_beacon_filter_set_cqm_params(mvm, vif, &cmd);
359 iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd); 568 iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd);
360 ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd); 569 ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd);
361 570
362 if (!ret) 571 if (!ret)
363 mvmvif->bf_enabled = true; 572 mvmvif->bf_data.bf_enabled = true;
364 573
365 return ret; 574 return ret;
366} 575}
@@ -372,13 +581,33 @@ int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
372 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 581 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
373 int ret; 582 int ret;
374 583
375 if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) 584 if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BF_UPDATED) ||
585 vif->type != NL80211_IFTYPE_STATION || vif->p2p)
376 return 0; 586 return 0;
377 587
378 ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd); 588 ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd);
379 589
380 if (!ret) 590 if (!ret)
381 mvmvif->bf_enabled = false; 591 mvmvif->bf_data.bf_enabled = false;
382 592
383 return ret; 593 return ret;
384} 594}
595
596int iwl_mvm_update_beacon_filter(struct iwl_mvm *mvm,
597 struct ieee80211_vif *vif)
598{
599 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
600
601 if (!mvmvif->bf_data.bf_enabled)
602 return 0;
603
604 return iwl_mvm_enable_beacon_filter(mvm, vif);
605}
606
607const struct iwl_mvm_power_ops pm_mac_ops = {
608 .power_update_mode = iwl_mvm_power_mac_update_mode,
609 .power_disable = iwl_mvm_power_mac_disable,
610#ifdef CONFIG_IWLWIFI_DEBUGFS
611 .power_dbgfs_read = iwl_mvm_power_mac_dbgfs_read,
612#endif
613};
diff --git a/drivers/net/wireless/iwlwifi/mvm/power_legacy.c b/drivers/net/wireless/iwlwifi/mvm/power_legacy.c
new file mode 100644
index 000000000000..2ce79bad5845
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/mvm/power_legacy.c
@@ -0,0 +1,319 @@
1/******************************************************************************
2 *
3 * This file is provided under a dual BSD/GPLv2 license. When using or
4 * redistributing this file, you may do so under either license.
5 *
6 * GPL LICENSE SUMMARY
7 *
8 * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of version 2 of the GNU General Public License as
12 * published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
22 * USA
23 *
24 * The full GNU General Public License is included in this distribution
25 * in the file called COPYING.
26 *
27 * Contact Information:
28 * Intel Linux Wireless <ilw@linux.intel.com>
29 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
30 *
31 * BSD LICENSE
32 *
33 * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
34 * All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 *
40 * * Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * * Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in
44 * the documentation and/or other materials provided with the
45 * distribution.
46 * * Neither the name Intel Corporation nor the names of its
47 * contributors may be used to endorse or promote products derived
48 * from this software without specific prior written permission.
49 *
50 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
51 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
52 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
53 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
54 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
56 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
57 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
58 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
59 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
60 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61 *
62 *****************************************************************************/
63
64#include <linux/kernel.h>
65#include <linux/module.h>
66#include <linux/slab.h>
67#include <linux/init.h>
68
69#include <net/mac80211.h>
70
71#include "iwl-debug.h"
72#include "mvm.h"
73#include "iwl-modparams.h"
74#include "fw-api-power.h"
75
76#define POWER_KEEP_ALIVE_PERIOD_SEC 25
77
78static void iwl_mvm_power_log(struct iwl_mvm *mvm,
79 struct iwl_powertable_cmd *cmd)
80{
81 IWL_DEBUG_POWER(mvm,
82 "Sending power table command for power level %d, flags = 0x%X\n",
83 iwlmvm_mod_params.power_scheme,
84 le16_to_cpu(cmd->flags));
85 IWL_DEBUG_POWER(mvm, "Keep alive = %u sec\n", cmd->keep_alive_seconds);
86
87 if (cmd->flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) {
88 IWL_DEBUG_POWER(mvm, "Rx timeout = %u usec\n",
89 le32_to_cpu(cmd->rx_data_timeout));
90 IWL_DEBUG_POWER(mvm, "Tx timeout = %u usec\n",
91 le32_to_cpu(cmd->tx_data_timeout));
92 if (cmd->flags & cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK))
93 IWL_DEBUG_POWER(mvm, "DTIM periods to skip = %u\n",
94 le32_to_cpu(cmd->skip_dtim_periods));
95 if (cmd->flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
96 IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n",
97 le32_to_cpu(cmd->lprx_rssi_threshold));
98 }
99}
100
101static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
102 struct ieee80211_vif *vif,
103 struct iwl_powertable_cmd *cmd)
104{
105 struct ieee80211_hw *hw = mvm->hw;
106 struct ieee80211_chanctx_conf *chanctx_conf;
107 struct ieee80211_channel *chan;
108 int dtimper, dtimper_msec;
109 int keep_alive;
110 bool radar_detect = false;
111 struct iwl_mvm_vif *mvmvif __maybe_unused =
112 iwl_mvm_vif_from_mac80211(vif);
113
114 /*
115 * Regardless of power management state the driver must set
116 * keep alive period. FW will use it for sending keep alive NDPs
117 * immediately after association.
118 */
119 cmd->keep_alive_seconds = POWER_KEEP_ALIVE_PERIOD_SEC;
120
121 if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM)
122 return;
123
124 cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
125 if (!vif->bss_conf.assoc)
126 cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
127
128#ifdef CONFIG_IWLWIFI_DEBUGFS
129 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_DISABLE_POWER_OFF &&
130 mvmvif->dbgfs_pm.disable_power_off)
131 cmd->flags &= cpu_to_le16(~POWER_FLAGS_POWER_SAVE_ENA_MSK);
132#endif
133 if (!vif->bss_conf.ps)
134 return;
135
136 cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
137
138 if (vif->bss_conf.beacon_rate &&
139 (vif->bss_conf.beacon_rate->bitrate == 10 ||
140 vif->bss_conf.beacon_rate->bitrate == 60)) {
141 cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
142 cmd->lprx_rssi_threshold =
143 cpu_to_le32(POWER_LPRX_RSSI_THRESHOLD);
144 }
145
146 dtimper = hw->conf.ps_dtim_period ?: 1;
147
148 /* Check if radar detection is required on current channel */
149 rcu_read_lock();
150 chanctx_conf = rcu_dereference(vif->chanctx_conf);
151 WARN_ON(!chanctx_conf);
152 if (chanctx_conf) {
153 chan = chanctx_conf->def.chan;
154 radar_detect = chan->flags & IEEE80211_CHAN_RADAR;
155 }
156 rcu_read_unlock();
157
158 /* Check skip over DTIM conditions */
159 if (!radar_detect && (dtimper <= 10) &&
160 (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP ||
161 mvm->cur_ucode == IWL_UCODE_WOWLAN)) {
162 cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
163 cmd->skip_dtim_periods = cpu_to_le32(3);
164 }
165
166 /* Check that keep alive period is at least 3 * DTIM */
167 dtimper_msec = dtimper * vif->bss_conf.beacon_int;
168 keep_alive = max_t(int, 3 * dtimper_msec,
169 MSEC_PER_SEC * cmd->keep_alive_seconds);
170 keep_alive = DIV_ROUND_UP(keep_alive, MSEC_PER_SEC);
171 cmd->keep_alive_seconds = keep_alive;
172
173 if (mvm->cur_ucode != IWL_UCODE_WOWLAN) {
174 cmd->rx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC);
175 cmd->tx_data_timeout = cpu_to_le32(100 * USEC_PER_MSEC);
176 } else {
177 cmd->rx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC);
178 cmd->tx_data_timeout = cpu_to_le32(10 * USEC_PER_MSEC);
179 }
180
181#ifdef CONFIG_IWLWIFI_DEBUGFS
182 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_KEEP_ALIVE)
183 cmd->keep_alive_seconds = mvmvif->dbgfs_pm.keep_alive_seconds;
184 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_OVER_DTIM) {
185 if (mvmvif->dbgfs_pm.skip_over_dtim)
186 cmd->flags |=
187 cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
188 else
189 cmd->flags &=
190 cpu_to_le16(~POWER_FLAGS_SKIP_OVER_DTIM_MSK);
191 }
192 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_RX_DATA_TIMEOUT)
193 cmd->rx_data_timeout =
194 cpu_to_le32(mvmvif->dbgfs_pm.rx_data_timeout);
195 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_TX_DATA_TIMEOUT)
196 cmd->tx_data_timeout =
197 cpu_to_le32(mvmvif->dbgfs_pm.tx_data_timeout);
198 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS)
199 cmd->skip_dtim_periods =
200 cpu_to_le32(mvmvif->dbgfs_pm.skip_dtim_periods);
201 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_ENA) {
202 if (mvmvif->dbgfs_pm.lprx_ena)
203 cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
204 else
205 cmd->flags &= cpu_to_le16(~POWER_FLAGS_LPRX_ENA_MSK);
206 }
207 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD)
208 cmd->lprx_rssi_threshold =
209 cpu_to_le32(mvmvif->dbgfs_pm.lprx_rssi_threshold);
210#endif /* CONFIG_IWLWIFI_DEBUGFS */
211}
212
213static int iwl_mvm_power_legacy_update_mode(struct iwl_mvm *mvm,
214 struct ieee80211_vif *vif)
215{
216 int ret;
217 bool ba_enable;
218 struct iwl_powertable_cmd cmd = {};
219
220 if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
221 return 0;
222
223 /*
224 * TODO: The following vif_count verification is temporary condition.
225 * Avoid power mode update if more than one interface is currently
226 * active. Remove this condition when FW will support power management
227 * on multiple MACs.
228 */
229 IWL_DEBUG_POWER(mvm, "Currently %d interfaces active\n",
230 mvm->vif_count);
231 if (mvm->vif_count > 1)
232 return 0;
233
234 iwl_mvm_power_build_cmd(mvm, vif, &cmd);
235 iwl_mvm_power_log(mvm, &cmd);
236
237 ret = iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_SYNC,
238 sizeof(cmd), &cmd);
239 if (ret)
240 return ret;
241
242 ba_enable = !!(cmd.flags &
243 cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK));
244
245 return iwl_mvm_update_beacon_abort(mvm, vif, ba_enable);
246}
247
248static int iwl_mvm_power_legacy_disable(struct iwl_mvm *mvm,
249 struct ieee80211_vif *vif)
250{
251 struct iwl_powertable_cmd cmd = {};
252 struct iwl_mvm_vif *mvmvif __maybe_unused =
253 iwl_mvm_vif_from_mac80211(vif);
254
255 if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
256 return 0;
257
258 if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM)
259 cmd.flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
260
261#ifdef CONFIG_IWLWIFI_DEBUGFS
262 if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_DISABLE_POWER_OFF &&
263 mvmvif->dbgfs_pm.disable_power_off)
264 cmd.flags &= cpu_to_le16(~POWER_FLAGS_POWER_SAVE_ENA_MSK);
265#endif
266 iwl_mvm_power_log(mvm, &cmd);
267
268 return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_ASYNC,
269 sizeof(cmd), &cmd);
270}
271
272#ifdef CONFIG_IWLWIFI_DEBUGFS
273static int iwl_mvm_power_legacy_dbgfs_read(struct iwl_mvm *mvm,
274 struct ieee80211_vif *vif, char *buf,
275 int bufsz)
276{
277 struct iwl_powertable_cmd cmd = {};
278 int pos = 0;
279
280 iwl_mvm_power_build_cmd(mvm, vif, &cmd);
281
282 pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off = %d\n",
283 (cmd.flags &
284 cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK)) ?
285 0 : 1);
286 pos += scnprintf(buf+pos, bufsz-pos, "skip_dtim_periods = %d\n",
287 le32_to_cpu(cmd.skip_dtim_periods));
288 pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n",
289 iwlmvm_mod_params.power_scheme);
290 pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n",
291 le16_to_cpu(cmd.flags));
292 pos += scnprintf(buf+pos, bufsz-pos, "keep_alive = %d\n",
293 cmd.keep_alive_seconds);
294
295 if (cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)) {
296 pos += scnprintf(buf+pos, bufsz-pos, "skip_over_dtim = %d\n",
297 (cmd.flags &
298 cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) ?
299 1 : 0);
300 pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout = %d\n",
301 le32_to_cpu(cmd.rx_data_timeout));
302 pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout = %d\n",
303 le32_to_cpu(cmd.tx_data_timeout));
304 if (cmd.flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
305 pos += scnprintf(buf+pos, bufsz-pos,
306 "lprx_rssi_threshold = %d\n",
307 le32_to_cpu(cmd.lprx_rssi_threshold));
308 }
309 return pos;
310}
311#endif
312
313const struct iwl_mvm_power_ops pm_legacy_ops = {
314 .power_update_mode = iwl_mvm_power_legacy_update_mode,
315 .power_disable = iwl_mvm_power_legacy_disable,
316#ifdef CONFIG_IWLWIFI_DEBUGFS
317 .power_dbgfs_read = iwl_mvm_power_legacy_dbgfs_read,
318#endif
319};
diff --git a/drivers/net/wireless/iwlwifi/mvm/quota.c b/drivers/net/wireless/iwlwifi/mvm/quota.c
index 29d49cf0fdb2..5c6ae16ec52b 100644
--- a/drivers/net/wireless/iwlwifi/mvm/quota.c
+++ b/drivers/net/wireless/iwlwifi/mvm/quota.c
@@ -131,23 +131,22 @@ static void iwl_mvm_quota_iterator(void *_data, u8 *mac,
131 131
132int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif) 132int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif)
133{ 133{
134 struct iwl_time_quota_cmd cmd; 134 struct iwl_time_quota_cmd cmd = {};
135 int i, idx, ret, num_active_bindings, quota, quota_rem; 135 int i, idx, ret, num_active_macs, quota, quota_rem;
136 struct iwl_mvm_quota_iterator_data data = { 136 struct iwl_mvm_quota_iterator_data data = {
137 .n_interfaces = {}, 137 .n_interfaces = {},
138 .colors = { -1, -1, -1, -1 }, 138 .colors = { -1, -1, -1, -1 },
139 .new_vif = newvif, 139 .new_vif = newvif,
140 }; 140 };
141 141
142 lockdep_assert_held(&mvm->mutex);
143
142 /* update all upon completion */ 144 /* update all upon completion */
143 if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) 145 if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
144 return 0; 146 return 0;
145 147
146 BUILD_BUG_ON(data.colors[MAX_BINDINGS - 1] != -1); 148 /* iterator data above must match */
147 149 BUILD_BUG_ON(MAX_BINDINGS != 4);
148 lockdep_assert_held(&mvm->mutex);
149
150 memset(&cmd, 0, sizeof(cmd));
151 150
152 ieee80211_iterate_active_interfaces_atomic( 151 ieee80211_iterate_active_interfaces_atomic(
153 mvm->hw, IEEE80211_IFACE_ITER_NORMAL, 152 mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
@@ -162,18 +161,17 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif)
162 * IWL_MVM_MAX_QUOTA fragments. Divide these fragments 161 * IWL_MVM_MAX_QUOTA fragments. Divide these fragments
163 * equally between all the bindings that require quota 162 * equally between all the bindings that require quota
164 */ 163 */
165 num_active_bindings = 0; 164 num_active_macs = 0;
166 for (i = 0; i < MAX_BINDINGS; i++) { 165 for (i = 0; i < MAX_BINDINGS; i++) {
167 cmd.quotas[i].id_and_color = cpu_to_le32(FW_CTXT_INVALID); 166 cmd.quotas[i].id_and_color = cpu_to_le32(FW_CTXT_INVALID);
168 if (data.n_interfaces[i] > 0) 167 num_active_macs += data.n_interfaces[i];
169 num_active_bindings++;
170 } 168 }
171 169
172 quota = 0; 170 quota = 0;
173 quota_rem = 0; 171 quota_rem = 0;
174 if (num_active_bindings) { 172 if (num_active_macs) {
175 quota = IWL_MVM_MAX_QUOTA / num_active_bindings; 173 quota = IWL_MVM_MAX_QUOTA / num_active_macs;
176 quota_rem = IWL_MVM_MAX_QUOTA % num_active_bindings; 174 quota_rem = IWL_MVM_MAX_QUOTA % num_active_macs;
177 } 175 }
178 176
179 for (idx = 0, i = 0; i < MAX_BINDINGS; i++) { 177 for (idx = 0, i = 0; i < MAX_BINDINGS; i++) {
@@ -187,7 +185,8 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif)
187 cmd.quotas[idx].quota = cpu_to_le32(0); 185 cmd.quotas[idx].quota = cpu_to_le32(0);
188 cmd.quotas[idx].max_duration = cpu_to_le32(0); 186 cmd.quotas[idx].max_duration = cpu_to_le32(0);
189 } else { 187 } else {
190 cmd.quotas[idx].quota = cpu_to_le32(quota); 188 cmd.quotas[idx].quota =
189 cpu_to_le32(quota * data.n_interfaces[i]);
191 cmd.quotas[idx].max_duration = 190 cmd.quotas[idx].max_duration =
192 cpu_to_le32(IWL_MVM_MAX_QUOTA); 191 cpu_to_le32(IWL_MVM_MAX_QUOTA);
193 } 192 }
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c
index b328a988c130..4ffaa3fa153f 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rs.c
@@ -56,61 +56,61 @@
56#define IWL_RATE_SCALE_FLUSH_INTVL (3*HZ) 56#define IWL_RATE_SCALE_FLUSH_INTVL (3*HZ)
57 57
58static u8 rs_ht_to_legacy[] = { 58static u8 rs_ht_to_legacy[] = {
59 IWL_RATE_6M_INDEX, IWL_RATE_6M_INDEX, 59 [IWL_RATE_1M_INDEX] = IWL_RATE_6M_INDEX,
60 IWL_RATE_6M_INDEX, IWL_RATE_6M_INDEX, 60 [IWL_RATE_2M_INDEX] = IWL_RATE_6M_INDEX,
61 IWL_RATE_6M_INDEX, 61 [IWL_RATE_5M_INDEX] = IWL_RATE_6M_INDEX,
62 IWL_RATE_6M_INDEX, IWL_RATE_9M_INDEX, 62 [IWL_RATE_11M_INDEX] = IWL_RATE_6M_INDEX,
63 IWL_RATE_12M_INDEX, IWL_RATE_18M_INDEX, 63 [IWL_RATE_6M_INDEX] = IWL_RATE_6M_INDEX,
64 IWL_RATE_24M_INDEX, IWL_RATE_36M_INDEX, 64 [IWL_RATE_9M_INDEX] = IWL_RATE_6M_INDEX,
65 IWL_RATE_48M_INDEX, IWL_RATE_54M_INDEX 65 [IWL_RATE_12M_INDEX] = IWL_RATE_9M_INDEX,
66 [IWL_RATE_18M_INDEX] = IWL_RATE_12M_INDEX,
67 [IWL_RATE_24M_INDEX] = IWL_RATE_18M_INDEX,
68 [IWL_RATE_36M_INDEX] = IWL_RATE_24M_INDEX,
69 [IWL_RATE_48M_INDEX] = IWL_RATE_36M_INDEX,
70 [IWL_RATE_54M_INDEX] = IWL_RATE_48M_INDEX,
71 [IWL_RATE_60M_INDEX] = IWL_RATE_54M_INDEX,
66}; 72};
67 73
68static const u8 ant_toggle_lookup[] = { 74static const u8 ant_toggle_lookup[] = {
69 /*ANT_NONE -> */ ANT_NONE, 75 [ANT_NONE] = ANT_NONE,
70 /*ANT_A -> */ ANT_B, 76 [ANT_A] = ANT_B,
71 /*ANT_B -> */ ANT_C, 77 [ANT_B] = ANT_C,
72 /*ANT_AB -> */ ANT_BC, 78 [ANT_AB] = ANT_BC,
73 /*ANT_C -> */ ANT_A, 79 [ANT_C] = ANT_A,
74 /*ANT_AC -> */ ANT_AB, 80 [ANT_AC] = ANT_AB,
75 /*ANT_BC -> */ ANT_AC, 81 [ANT_BC] = ANT_AC,
76 /*ANT_ABC -> */ ANT_ABC, 82 [ANT_ABC] = ANT_ABC,
77}; 83};
78 84
79#define IWL_DECLARE_RATE_INFO(r, s, ip, in, rp, rn, pp, np) \ 85#define IWL_DECLARE_RATE_INFO(r, s, rp, rn) \
80 [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \ 86 [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \
81 IWL_RATE_SISO_##s##M_PLCP, \ 87 IWL_RATE_SISO_##s##M_PLCP, \
82 IWL_RATE_MIMO2_##s##M_PLCP,\ 88 IWL_RATE_MIMO2_##s##M_PLCP,\
83 IWL_RATE_MIMO3_##s##M_PLCP,\
84 IWL_RATE_##r##M_IEEE, \
85 IWL_RATE_##ip##M_INDEX, \
86 IWL_RATE_##in##M_INDEX, \
87 IWL_RATE_##rp##M_INDEX, \ 89 IWL_RATE_##rp##M_INDEX, \
88 IWL_RATE_##rn##M_INDEX, \ 90 IWL_RATE_##rn##M_INDEX }
89 IWL_RATE_##pp##M_INDEX, \
90 IWL_RATE_##np##M_INDEX }
91 91
92/* 92/*
93 * Parameter order: 93 * Parameter order:
94 * rate, ht rate, prev rate, next rate, prev tgg rate, next tgg rate 94 * rate, ht rate, prev rate, next rate
95 * 95 *
96 * If there isn't a valid next or previous rate then INV is used which 96 * If there isn't a valid next or previous rate then INV is used which
97 * maps to IWL_RATE_INVALID 97 * maps to IWL_RATE_INVALID
98 * 98 *
99 */ 99 */
100static const struct iwl_rs_rate_info iwl_rates[IWL_RATE_COUNT] = { 100static const struct iwl_rs_rate_info iwl_rates[IWL_RATE_COUNT] = {
101 IWL_DECLARE_RATE_INFO(1, INV, INV, 2, INV, 2, INV, 2), /* 1mbps */ 101 IWL_DECLARE_RATE_INFO(1, INV, INV, 2), /* 1mbps */
102 IWL_DECLARE_RATE_INFO(2, INV, 1, 5, 1, 5, 1, 5), /* 2mbps */ 102 IWL_DECLARE_RATE_INFO(2, INV, 1, 5), /* 2mbps */
103 IWL_DECLARE_RATE_INFO(5, INV, 2, 6, 2, 11, 2, 11), /*5.5mbps */ 103 IWL_DECLARE_RATE_INFO(5, INV, 2, 11), /*5.5mbps */
104 IWL_DECLARE_RATE_INFO(11, INV, 9, 12, 9, 12, 5, 18), /* 11mbps */ 104 IWL_DECLARE_RATE_INFO(11, INV, 9, 12), /* 11mbps */
105 IWL_DECLARE_RATE_INFO(6, 6, 5, 9, 5, 11, 5, 11), /* 6mbps */ 105 IWL_DECLARE_RATE_INFO(6, 6, 5, 11), /* 6mbps */
106 IWL_DECLARE_RATE_INFO(9, 6, 6, 11, 6, 11, 5, 11), /* 9mbps */ 106 IWL_DECLARE_RATE_INFO(9, 6, 6, 11), /* 9mbps */
107 IWL_DECLARE_RATE_INFO(12, 12, 11, 18, 11, 18, 11, 18), /* 12mbps */ 107 IWL_DECLARE_RATE_INFO(12, 12, 11, 18), /* 12mbps */
108 IWL_DECLARE_RATE_INFO(18, 18, 12, 24, 12, 24, 11, 24), /* 18mbps */ 108 IWL_DECLARE_RATE_INFO(18, 18, 12, 24), /* 18mbps */
109 IWL_DECLARE_RATE_INFO(24, 24, 18, 36, 18, 36, 18, 36), /* 24mbps */ 109 IWL_DECLARE_RATE_INFO(24, 24, 18, 36), /* 24mbps */
110 IWL_DECLARE_RATE_INFO(36, 36, 24, 48, 24, 48, 24, 48), /* 36mbps */ 110 IWL_DECLARE_RATE_INFO(36, 36, 24, 48), /* 36mbps */
111 IWL_DECLARE_RATE_INFO(48, 48, 36, 54, 36, 54, 36, 54), /* 48mbps */ 111 IWL_DECLARE_RATE_INFO(48, 48, 36, 54), /* 48mbps */
112 IWL_DECLARE_RATE_INFO(54, 54, 48, INV, 48, INV, 48, INV),/* 54mbps */ 112 IWL_DECLARE_RATE_INFO(54, 54, 48, INV), /* 54mbps */
113 IWL_DECLARE_RATE_INFO(60, 60, 48, INV, 48, INV, 48, INV),/* 60mbps */ 113 IWL_DECLARE_RATE_INFO(60, 60, 48, INV), /* 60mbps */
114 /* FIXME:RS: ^^ should be INV (legacy) */ 114 /* FIXME:RS: ^^ should be INV (legacy) */
115}; 115};
116 116
@@ -128,9 +128,8 @@ static int iwl_hwrate_to_plcp_idx(u32 rate_n_flags)
128 if (rate_n_flags & RATE_MCS_HT_MSK) { 128 if (rate_n_flags & RATE_MCS_HT_MSK) {
129 idx = rs_extract_rate(rate_n_flags); 129 idx = rs_extract_rate(rate_n_flags);
130 130
131 if (idx >= IWL_RATE_MIMO3_6M_PLCP) 131 WARN_ON_ONCE(idx >= IWL_RATE_MIMO3_6M_PLCP);
132 idx = idx - IWL_RATE_MIMO3_6M_PLCP; 132 if (idx >= IWL_RATE_MIMO2_6M_PLCP)
133 else if (idx >= IWL_RATE_MIMO2_6M_PLCP)
134 idx = idx - IWL_RATE_MIMO2_6M_PLCP; 133 idx = idx - IWL_RATE_MIMO2_6M_PLCP;
135 134
136 idx += IWL_FIRST_OFDM_RATE; 135 idx += IWL_FIRST_OFDM_RATE;
@@ -162,10 +161,10 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search);
162 161
163#ifdef CONFIG_MAC80211_DEBUGFS 162#ifdef CONFIG_MAC80211_DEBUGFS
164static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, 163static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
165 u32 *rate_n_flags, int index); 164 u32 *rate_n_flags);
166#else 165#else
167static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, 166static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
168 u32 *rate_n_flags, int index) 167 u32 *rate_n_flags)
169{} 168{}
170#endif 169#endif
171 170
@@ -212,20 +211,6 @@ static s32 expected_tpt_mimo2_40MHz[4][IWL_RATE_COUNT] = {
212 {0, 0, 0, 0, 186, 0, 329, 439, 527, 667, 764, 803, 838}, /* AGG+SGI */ 211 {0, 0, 0, 0, 186, 0, 329, 439, 527, 667, 764, 803, 838}, /* AGG+SGI */
213}; 212};
214 213
215static s32 expected_tpt_mimo3_20MHz[4][IWL_RATE_COUNT] = {
216 {0, 0, 0, 0, 99, 0, 153, 186, 208, 239, 256, 263, 268}, /* Norm */
217 {0, 0, 0, 0, 106, 0, 162, 194, 215, 246, 262, 268, 273}, /* SGI */
218 {0, 0, 0, 0, 134, 0, 249, 346, 431, 574, 685, 732, 775}, /* AGG */
219 {0, 0, 0, 0, 148, 0, 272, 376, 465, 614, 727, 775, 818}, /* AGG+SGI */
220};
221
222static s32 expected_tpt_mimo3_40MHz[4][IWL_RATE_COUNT] = {
223 {0, 0, 0, 0, 152, 0, 211, 239, 255, 279, 290, 294, 297}, /* Norm */
224 {0, 0, 0, 0, 160, 0, 219, 245, 261, 284, 294, 297, 300}, /* SGI */
225 {0, 0, 0, 0, 254, 0, 443, 584, 695, 868, 984, 1030, 1070}, /* AGG */
226 {0, 0, 0, 0, 277, 0, 478, 624, 737, 911, 1026, 1070, 1109}, /* AGG+SGI */
227};
228
229/* mbps, mcs */ 214/* mbps, mcs */
230static const struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = { 215static const struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = {
231 { "1", "BPSK DSSS"}, 216 { "1", "BPSK DSSS"},
@@ -260,82 +245,6 @@ static inline u8 rs_is_valid_ant(u8 valid_antenna, u8 ant_type)
260 return (ant_type & valid_antenna) == ant_type; 245 return (ant_type & valid_antenna) == ant_type;
261} 246}
262 247
263/*
264 * removes the old data from the statistics. All data that is older than
265 * TID_MAX_TIME_DIFF, will be deleted.
266 */
267static void rs_tl_rm_old_stats(struct iwl_traffic_load *tl, u32 curr_time)
268{
269 /* The oldest age we want to keep */
270 u32 oldest_time = curr_time - TID_MAX_TIME_DIFF;
271
272 while (tl->queue_count &&
273 (tl->time_stamp < oldest_time)) {
274 tl->total -= tl->packet_count[tl->head];
275 tl->packet_count[tl->head] = 0;
276 tl->time_stamp += TID_QUEUE_CELL_SPACING;
277 tl->queue_count--;
278 tl->head++;
279 if (tl->head >= TID_QUEUE_MAX_SIZE)
280 tl->head = 0;
281 }
282}
283
284/*
285 * increment traffic load value for tid and also remove
286 * any old values if passed the certain time period
287 */
288static u8 rs_tl_add_packet(struct iwl_lq_sta *lq_data,
289 struct ieee80211_hdr *hdr)
290{
291 u32 curr_time = jiffies_to_msecs(jiffies);
292 u32 time_diff;
293 s32 index;
294 struct iwl_traffic_load *tl = NULL;
295 u8 tid;
296
297 if (ieee80211_is_data_qos(hdr->frame_control)) {
298 u8 *qc = ieee80211_get_qos_ctl(hdr);
299 tid = qc[0] & 0xf;
300 } else {
301 return IWL_MAX_TID_COUNT;
302 }
303
304 if (unlikely(tid >= IWL_MAX_TID_COUNT))
305 return IWL_MAX_TID_COUNT;
306
307 tl = &lq_data->load[tid];
308
309 curr_time -= curr_time % TID_ROUND_VALUE;
310
311 /* Happens only for the first packet. Initialize the data */
312 if (!(tl->queue_count)) {
313 tl->total = 1;
314 tl->time_stamp = curr_time;
315 tl->queue_count = 1;
316 tl->head = 0;
317 tl->packet_count[0] = 1;
318 return IWL_MAX_TID_COUNT;
319 }
320
321 time_diff = TIME_WRAP_AROUND(tl->time_stamp, curr_time);
322 index = time_diff / TID_QUEUE_CELL_SPACING;
323
324 /* The history is too long: remove data that is older than */
325 /* TID_MAX_TIME_DIFF */
326 if (index >= TID_QUEUE_MAX_SIZE)
327 rs_tl_rm_old_stats(tl, curr_time);
328
329 index = (tl->head + index) % TID_QUEUE_MAX_SIZE;
330 tl->packet_count[index] = tl->packet_count[index] + 1;
331 tl->total = tl->total + 1;
332
333 if ((index + 1) > tl->queue_count)
334 tl->queue_count = index + 1;
335
336 return tid;
337}
338
339#ifdef CONFIG_MAC80211_DEBUGFS 248#ifdef CONFIG_MAC80211_DEBUGFS
340/** 249/**
341 * Program the device to use fixed rate for frame transmit 250 * Program the device to use fixed rate for frame transmit
@@ -349,7 +258,6 @@ static void rs_program_fix_rate(struct iwl_mvm *mvm,
349 lq_sta->active_legacy_rate = 0x0FFF; /* 1 - 54 MBits, includes CCK */ 258 lq_sta->active_legacy_rate = 0x0FFF; /* 1 - 54 MBits, includes CCK */
350 lq_sta->active_siso_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ 259 lq_sta->active_siso_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */
351 lq_sta->active_mimo2_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ 260 lq_sta->active_mimo2_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */
352 lq_sta->active_mimo3_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */
353 261
354 IWL_DEBUG_RATE(mvm, "sta_id %d rate 0x%X\n", 262 IWL_DEBUG_RATE(mvm, "sta_id %d rate 0x%X\n",
355 lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate); 263 lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate);
@@ -361,45 +269,11 @@ static void rs_program_fix_rate(struct iwl_mvm *mvm,
361} 269}
362#endif 270#endif
363 271
364/*
365 get the traffic load value for tid
366*/
367static u32 rs_tl_get_load(struct iwl_lq_sta *lq_data, u8 tid)
368{
369 u32 curr_time = jiffies_to_msecs(jiffies);
370 u32 time_diff;
371 s32 index;
372 struct iwl_traffic_load *tl = NULL;
373
374 if (tid >= IWL_MAX_TID_COUNT)
375 return 0;
376
377 tl = &(lq_data->load[tid]);
378
379 curr_time -= curr_time % TID_ROUND_VALUE;
380
381 if (!(tl->queue_count))
382 return 0;
383
384 time_diff = TIME_WRAP_AROUND(tl->time_stamp, curr_time);
385 index = time_diff / TID_QUEUE_CELL_SPACING;
386
387 /* The history is too long: remove data that is older than */
388 /* TID_MAX_TIME_DIFF */
389 if (index >= TID_QUEUE_MAX_SIZE)
390 rs_tl_rm_old_stats(tl, curr_time);
391
392 return tl->total;
393}
394
395static int rs_tl_turn_on_agg_for_tid(struct iwl_mvm *mvm, 272static int rs_tl_turn_on_agg_for_tid(struct iwl_mvm *mvm,
396 struct iwl_lq_sta *lq_data, u8 tid, 273 struct iwl_lq_sta *lq_data, u8 tid,
397 struct ieee80211_sta *sta) 274 struct ieee80211_sta *sta)
398{ 275{
399 int ret = -EAGAIN; 276 int ret = -EAGAIN;
400 u32 load;
401
402 load = rs_tl_get_load(lq_data, tid);
403 277
404 /* 278 /*
405 * Don't create TX aggregation sessions when in high 279 * Don't create TX aggregation sessions when in high
@@ -563,7 +437,7 @@ static u32 rate_n_flags_from_tbl(struct iwl_mvm *mvm,
563 else if (is_mimo2(tbl->lq_type)) 437 else if (is_mimo2(tbl->lq_type))
564 rate_n_flags |= iwl_rates[index].plcp_mimo2; 438 rate_n_flags |= iwl_rates[index].plcp_mimo2;
565 else 439 else
566 rate_n_flags |= iwl_rates[index].plcp_mimo3; 440 WARN_ON_ONCE(1);
567 } else { 441 } else {
568 IWL_ERR(mvm, "Invalid tbl->lq_type %d\n", tbl->lq_type); 442 IWL_ERR(mvm, "Invalid tbl->lq_type %d\n", tbl->lq_type);
569 } 443 }
@@ -601,7 +475,7 @@ static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags,
601 u8 num_of_ant = get_num_of_ant_from_rate(rate_n_flags); 475 u8 num_of_ant = get_num_of_ant_from_rate(rate_n_flags);
602 u8 mcs; 476 u8 mcs;
603 477
604 memset(tbl, 0, sizeof(struct iwl_scale_tbl_info)); 478 memset(tbl, 0, offsetof(struct iwl_scale_tbl_info, win));
605 *rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags); 479 *rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags);
606 480
607 if (*rate_idx == IWL_RATE_INVALID) { 481 if (*rate_idx == IWL_RATE_INVALID) {
@@ -640,12 +514,8 @@ static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags,
640 } else if (mcs <= IWL_RATE_MIMO2_60M_PLCP) { 514 } else if (mcs <= IWL_RATE_MIMO2_60M_PLCP) {
641 if (num_of_ant == 2) 515 if (num_of_ant == 2)
642 tbl->lq_type = LQ_MIMO2; 516 tbl->lq_type = LQ_MIMO2;
643 /* MIMO3 */
644 } else { 517 } else {
645 if (num_of_ant == 3) { 518 WARN_ON_ONCE(num_of_ant == 3);
646 tbl->max_search = IWL_MAX_11N_MIMO3_SEARCH;
647 tbl->lq_type = LQ_MIMO3;
648 }
649 } 519 }
650 } 520 }
651 return 0; 521 return 0;
@@ -711,10 +581,10 @@ static u16 rs_get_supported_rates(struct iwl_lq_sta *lq_sta,
711 } else { 581 } else {
712 if (is_siso(rate_type)) 582 if (is_siso(rate_type))
713 return lq_sta->active_siso_rate; 583 return lq_sta->active_siso_rate;
714 else if (is_mimo2(rate_type)) 584 else {
585 WARN_ON_ONCE(!is_mimo2(rate_type));
715 return lq_sta->active_mimo2_rate; 586 return lq_sta->active_mimo2_rate;
716 else 587 }
717 return lq_sta->active_mimo3_rate;
718 } 588 }
719} 589}
720 590
@@ -1089,7 +959,7 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta,
1089 } 959 }
1090 960
1091 /* Choose among many HT tables depending on number of streams 961 /* Choose among many HT tables depending on number of streams
1092 * (SISO/MIMO2/MIMO3), channel width (20/40), SGI, and aggregation 962 * (SISO/MIMO2), channel width (20/40), SGI, and aggregation
1093 * status */ 963 * status */
1094 if (is_siso(tbl->lq_type) && !tbl->is_ht40) 964 if (is_siso(tbl->lq_type) && !tbl->is_ht40)
1095 ht_tbl_pointer = expected_tpt_siso20MHz; 965 ht_tbl_pointer = expected_tpt_siso20MHz;
@@ -1097,12 +967,10 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta,
1097 ht_tbl_pointer = expected_tpt_siso40MHz; 967 ht_tbl_pointer = expected_tpt_siso40MHz;
1098 else if (is_mimo2(tbl->lq_type) && !tbl->is_ht40) 968 else if (is_mimo2(tbl->lq_type) && !tbl->is_ht40)
1099 ht_tbl_pointer = expected_tpt_mimo2_20MHz; 969 ht_tbl_pointer = expected_tpt_mimo2_20MHz;
1100 else if (is_mimo2(tbl->lq_type)) 970 else {
971 WARN_ON_ONCE(!is_mimo2(tbl->lq_type));
1101 ht_tbl_pointer = expected_tpt_mimo2_40MHz; 972 ht_tbl_pointer = expected_tpt_mimo2_40MHz;
1102 else if (is_mimo3(tbl->lq_type) && !tbl->is_ht40) 973 }
1103 ht_tbl_pointer = expected_tpt_mimo3_20MHz;
1104 else /* if (is_mimo3(tbl->lq_type)) <-- must be true */
1105 ht_tbl_pointer = expected_tpt_mimo3_40MHz;
1106 974
1107 if (!tbl->is_SGI && !lq_sta->is_agg) /* Normal */ 975 if (!tbl->is_SGI && !lq_sta->is_agg) /* Normal */
1108 tbl->expected_tpt = ht_tbl_pointer[0]; 976 tbl->expected_tpt = ht_tbl_pointer[0];
@@ -1274,58 +1142,6 @@ static int rs_switch_to_mimo2(struct iwl_mvm *mvm,
1274} 1142}
1275 1143
1276/* 1144/*
1277 * Set up search table for MIMO3
1278 */
1279static int rs_switch_to_mimo3(struct iwl_mvm *mvm,
1280 struct iwl_lq_sta *lq_sta,
1281 struct ieee80211_sta *sta,
1282 struct iwl_scale_tbl_info *tbl, int index)
1283{
1284 u16 rate_mask;
1285 s32 rate;
1286 s8 is_green = lq_sta->is_green;
1287
1288 if (!sta->ht_cap.ht_supported)
1289 return -1;
1290
1291 if (sta->smps_mode == IEEE80211_SMPS_STATIC)
1292 return -1;
1293
1294 /* Need both Tx chains/antennas to support MIMO */
1295 if (num_of_ant(iwl_fw_valid_tx_ant(mvm->fw)) < 3)
1296 return -1;
1297
1298 IWL_DEBUG_RATE(mvm, "LQ: try to switch to MIMO3\n");
1299
1300 tbl->lq_type = LQ_MIMO3;
1301 tbl->action = 0;
1302 tbl->max_search = IWL_MAX_11N_MIMO3_SEARCH;
1303 rate_mask = lq_sta->active_mimo3_rate;
1304
1305 if (iwl_is_ht40_tx_allowed(sta))
1306 tbl->is_ht40 = 1;
1307 else
1308 tbl->is_ht40 = 0;
1309
1310 rs_set_expected_tpt_table(lq_sta, tbl);
1311
1312 rate = rs_get_best_rate(mvm, lq_sta, tbl, rate_mask, index);
1313
1314 IWL_DEBUG_RATE(mvm, "LQ: MIMO3 best rate %d mask %X\n",
1315 rate, rate_mask);
1316 if ((rate == IWL_RATE_INVALID) || !((1 << rate) & rate_mask)) {
1317 IWL_DEBUG_RATE(mvm, "Can't switch with index %d rate mask %x\n",
1318 rate, rate_mask);
1319 return -1;
1320 }
1321 tbl->current_rate = rate_n_flags_from_tbl(mvm, tbl, rate, is_green);
1322
1323 IWL_DEBUG_RATE(mvm, "LQ: Switch to new mcs %X index is green %X\n",
1324 tbl->current_rate, is_green);
1325 return 0;
1326}
1327
1328/*
1329 * Set up search table for SISO 1145 * Set up search table for SISO
1330 */ 1146 */
1331static int rs_switch_to_siso(struct iwl_mvm *mvm, 1147static int rs_switch_to_siso(struct iwl_mvm *mvm,
@@ -1434,21 +1250,14 @@ static int rs_move_legacy_other(struct iwl_mvm *mvm,
1434 } 1250 }
1435 1251
1436 break; 1252 break;
1437 case IWL_LEGACY_SWITCH_MIMO2_AB: 1253 case IWL_LEGACY_SWITCH_MIMO2:
1438 case IWL_LEGACY_SWITCH_MIMO2_AC:
1439 case IWL_LEGACY_SWITCH_MIMO2_BC:
1440 IWL_DEBUG_RATE(mvm, "LQ: Legacy switch to MIMO2\n"); 1254 IWL_DEBUG_RATE(mvm, "LQ: Legacy switch to MIMO2\n");
1441 1255
1442 /* Set up search table to try MIMO */ 1256 /* Set up search table to try MIMO */
1443 memcpy(search_tbl, tbl, sz); 1257 memcpy(search_tbl, tbl, sz);
1444 search_tbl->is_SGI = 0; 1258 search_tbl->is_SGI = 0;
1445 1259
1446 if (tbl->action == IWL_LEGACY_SWITCH_MIMO2_AB) 1260 search_tbl->ant_type = ANT_AB;
1447 search_tbl->ant_type = ANT_AB;
1448 else if (tbl->action == IWL_LEGACY_SWITCH_MIMO2_AC)
1449 search_tbl->ant_type = ANT_AC;
1450 else
1451 search_tbl->ant_type = ANT_BC;
1452 1261
1453 if (!rs_is_valid_ant(valid_tx_ant, 1262 if (!rs_is_valid_ant(valid_tx_ant,
1454 search_tbl->ant_type)) 1263 search_tbl->ant_type))
@@ -1461,30 +1270,11 @@ static int rs_move_legacy_other(struct iwl_mvm *mvm,
1461 goto out; 1270 goto out;
1462 } 1271 }
1463 break; 1272 break;
1464 1273 default:
1465 case IWL_LEGACY_SWITCH_MIMO3_ABC: 1274 WARN_ON_ONCE(1);
1466 IWL_DEBUG_RATE(mvm, "LQ: Legacy switch to MIMO3\n");
1467
1468 /* Set up search table to try MIMO3 */
1469 memcpy(search_tbl, tbl, sz);
1470 search_tbl->is_SGI = 0;
1471
1472 search_tbl->ant_type = ANT_ABC;
1473
1474 if (!rs_is_valid_ant(valid_tx_ant,
1475 search_tbl->ant_type))
1476 break;
1477
1478 ret = rs_switch_to_mimo3(mvm, lq_sta, sta,
1479 search_tbl, index);
1480 if (!ret) {
1481 lq_sta->action_counter = 0;
1482 goto out;
1483 }
1484 break;
1485 } 1275 }
1486 tbl->action++; 1276 tbl->action++;
1487 if (tbl->action > IWL_LEGACY_SWITCH_MIMO3_ABC) 1277 if (tbl->action > IWL_LEGACY_SWITCH_MIMO2)
1488 tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; 1278 tbl->action = IWL_LEGACY_SWITCH_ANTENNA1;
1489 1279
1490 if (tbl->action == start_action) 1280 if (tbl->action == start_action)
@@ -1496,7 +1286,7 @@ static int rs_move_legacy_other(struct iwl_mvm *mvm,
1496out: 1286out:
1497 lq_sta->search_better_tbl = 1; 1287 lq_sta->search_better_tbl = 1;
1498 tbl->action++; 1288 tbl->action++;
1499 if (tbl->action > IWL_LEGACY_SWITCH_MIMO3_ABC) 1289 if (tbl->action > IWL_LEGACY_SWITCH_MIMO2)
1500 tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; 1290 tbl->action = IWL_LEGACY_SWITCH_ANTENNA1;
1501 if (update_search_tbl_counter) 1291 if (update_search_tbl_counter)
1502 search_tbl->action = tbl->action; 1292 search_tbl->action = tbl->action;
@@ -1531,7 +1321,7 @@ static int rs_move_siso_to_other(struct iwl_mvm *mvm,
1531 case IWL_BT_COEX_TRAFFIC_LOAD_LOW: 1321 case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
1532 /* avoid antenna B unless MIMO */ 1322 /* avoid antenna B unless MIMO */
1533 if (tbl->action == IWL_SISO_SWITCH_ANTENNA2) 1323 if (tbl->action == IWL_SISO_SWITCH_ANTENNA2)
1534 tbl->action = IWL_SISO_SWITCH_MIMO2_AB; 1324 tbl->action = IWL_SISO_SWITCH_MIMO2;
1535 break; 1325 break;
1536 case IWL_BT_COEX_TRAFFIC_LOAD_HIGH: 1326 case IWL_BT_COEX_TRAFFIC_LOAD_HIGH:
1537 case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: 1327 case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS:
@@ -1573,19 +1363,12 @@ static int rs_move_siso_to_other(struct iwl_mvm *mvm,
1573 goto out; 1363 goto out;
1574 } 1364 }
1575 break; 1365 break;
1576 case IWL_SISO_SWITCH_MIMO2_AB: 1366 case IWL_SISO_SWITCH_MIMO2:
1577 case IWL_SISO_SWITCH_MIMO2_AC:
1578 case IWL_SISO_SWITCH_MIMO2_BC:
1579 IWL_DEBUG_RATE(mvm, "LQ: SISO switch to MIMO2\n"); 1367 IWL_DEBUG_RATE(mvm, "LQ: SISO switch to MIMO2\n");
1580 memcpy(search_tbl, tbl, sz); 1368 memcpy(search_tbl, tbl, sz);
1581 search_tbl->is_SGI = 0; 1369 search_tbl->is_SGI = 0;
1582 1370
1583 if (tbl->action == IWL_SISO_SWITCH_MIMO2_AB) 1371 search_tbl->ant_type = ANT_AB;
1584 search_tbl->ant_type = ANT_AB;
1585 else if (tbl->action == IWL_SISO_SWITCH_MIMO2_AC)
1586 search_tbl->ant_type = ANT_AC;
1587 else
1588 search_tbl->ant_type = ANT_BC;
1589 1372
1590 if (!rs_is_valid_ant(valid_tx_ant, 1373 if (!rs_is_valid_ant(valid_tx_ant,
1591 search_tbl->ant_type)) 1374 search_tbl->ant_type))
@@ -1626,24 +1409,11 @@ static int rs_move_siso_to_other(struct iwl_mvm *mvm,
1626 index, is_green); 1409 index, is_green);
1627 update_search_tbl_counter = 1; 1410 update_search_tbl_counter = 1;
1628 goto out; 1411 goto out;
1629 case IWL_SISO_SWITCH_MIMO3_ABC: 1412 default:
1630 IWL_DEBUG_RATE(mvm, "LQ: SISO switch to MIMO3\n"); 1413 WARN_ON_ONCE(1);
1631 memcpy(search_tbl, tbl, sz);
1632 search_tbl->is_SGI = 0;
1633 search_tbl->ant_type = ANT_ABC;
1634
1635 if (!rs_is_valid_ant(valid_tx_ant,
1636 search_tbl->ant_type))
1637 break;
1638
1639 ret = rs_switch_to_mimo3(mvm, lq_sta, sta,
1640 search_tbl, index);
1641 if (!ret)
1642 goto out;
1643 break;
1644 } 1414 }
1645 tbl->action++; 1415 tbl->action++;
1646 if (tbl->action > IWL_LEGACY_SWITCH_MIMO3_ABC) 1416 if (tbl->action > IWL_SISO_SWITCH_GI)
1647 tbl->action = IWL_SISO_SWITCH_ANTENNA1; 1417 tbl->action = IWL_SISO_SWITCH_ANTENNA1;
1648 1418
1649 if (tbl->action == start_action) 1419 if (tbl->action == start_action)
@@ -1655,7 +1425,7 @@ static int rs_move_siso_to_other(struct iwl_mvm *mvm,
1655 out: 1425 out:
1656 lq_sta->search_better_tbl = 1; 1426 lq_sta->search_better_tbl = 1;
1657 tbl->action++; 1427 tbl->action++;
1658 if (tbl->action > IWL_SISO_SWITCH_MIMO3_ABC) 1428 if (tbl->action > IWL_SISO_SWITCH_GI)
1659 tbl->action = IWL_SISO_SWITCH_ANTENNA1; 1429 tbl->action = IWL_SISO_SWITCH_ANTENNA1;
1660 if (update_search_tbl_counter) 1430 if (update_search_tbl_counter)
1661 search_tbl->action = tbl->action; 1431 search_tbl->action = tbl->action;
@@ -1696,8 +1466,7 @@ static int rs_move_mimo2_to_other(struct iwl_mvm *mvm,
1696 break; 1466 break;
1697 case IWL_BT_COEX_TRAFFIC_LOAD_LOW: 1467 case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
1698 /* avoid antenna B unless MIMO */ 1468 /* avoid antenna B unless MIMO */
1699 if (tbl->action == IWL_MIMO2_SWITCH_SISO_B || 1469 if (tbl->action == IWL_MIMO2_SWITCH_SISO_B)
1700 tbl->action == IWL_MIMO2_SWITCH_SISO_C)
1701 tbl->action = IWL_MIMO2_SWITCH_SISO_A; 1470 tbl->action = IWL_MIMO2_SWITCH_SISO_A;
1702 break; 1471 break;
1703 default: 1472 default:
@@ -1730,7 +1499,6 @@ static int rs_move_mimo2_to_other(struct iwl_mvm *mvm,
1730 break; 1499 break;
1731 case IWL_MIMO2_SWITCH_SISO_A: 1500 case IWL_MIMO2_SWITCH_SISO_A:
1732 case IWL_MIMO2_SWITCH_SISO_B: 1501 case IWL_MIMO2_SWITCH_SISO_B:
1733 case IWL_MIMO2_SWITCH_SISO_C:
1734 IWL_DEBUG_RATE(mvm, "LQ: MIMO2 switch to SISO\n"); 1502 IWL_DEBUG_RATE(mvm, "LQ: MIMO2 switch to SISO\n");
1735 1503
1736 /* Set up new search table for SISO */ 1504 /* Set up new search table for SISO */
@@ -1738,10 +1506,8 @@ static int rs_move_mimo2_to_other(struct iwl_mvm *mvm,
1738 1506
1739 if (tbl->action == IWL_MIMO2_SWITCH_SISO_A) 1507 if (tbl->action == IWL_MIMO2_SWITCH_SISO_A)
1740 search_tbl->ant_type = ANT_A; 1508 search_tbl->ant_type = ANT_A;
1741 else if (tbl->action == IWL_MIMO2_SWITCH_SISO_B) 1509 else /* tbl->action == IWL_MIMO2_SWITCH_SISO_B */
1742 search_tbl->ant_type = ANT_B; 1510 search_tbl->ant_type = ANT_B;
1743 else
1744 search_tbl->ant_type = ANT_C;
1745 1511
1746 if (!rs_is_valid_ant(valid_tx_ant, 1512 if (!rs_is_valid_ant(valid_tx_ant,
1747 search_tbl->ant_type)) 1513 search_tbl->ant_type))
@@ -1784,26 +1550,11 @@ static int rs_move_mimo2_to_other(struct iwl_mvm *mvm,
1784 index, is_green); 1550 index, is_green);
1785 update_search_tbl_counter = 1; 1551 update_search_tbl_counter = 1;
1786 goto out; 1552 goto out;
1787 1553 default:
1788 case IWL_MIMO2_SWITCH_MIMO3_ABC: 1554 WARN_ON_ONCE(1);
1789 IWL_DEBUG_RATE(mvm, "LQ: MIMO2 switch to MIMO3\n");
1790 memcpy(search_tbl, tbl, sz);
1791 search_tbl->is_SGI = 0;
1792 search_tbl->ant_type = ANT_ABC;
1793
1794 if (!rs_is_valid_ant(valid_tx_ant,
1795 search_tbl->ant_type))
1796 break;
1797
1798 ret = rs_switch_to_mimo3(mvm, lq_sta, sta,
1799 search_tbl, index);
1800 if (!ret)
1801 goto out;
1802
1803 break;
1804 } 1555 }
1805 tbl->action++; 1556 tbl->action++;
1806 if (tbl->action > IWL_MIMO2_SWITCH_MIMO3_ABC) 1557 if (tbl->action > IWL_MIMO2_SWITCH_GI)
1807 tbl->action = IWL_MIMO2_SWITCH_ANTENNA1; 1558 tbl->action = IWL_MIMO2_SWITCH_ANTENNA1;
1808 1559
1809 if (tbl->action == start_action) 1560 if (tbl->action == start_action)
@@ -1814,7 +1565,7 @@ static int rs_move_mimo2_to_other(struct iwl_mvm *mvm,
1814 out: 1565 out:
1815 lq_sta->search_better_tbl = 1; 1566 lq_sta->search_better_tbl = 1;
1816 tbl->action++; 1567 tbl->action++;
1817 if (tbl->action > IWL_MIMO2_SWITCH_MIMO3_ABC) 1568 if (tbl->action > IWL_MIMO2_SWITCH_GI)
1818 tbl->action = IWL_MIMO2_SWITCH_ANTENNA1; 1569 tbl->action = IWL_MIMO2_SWITCH_ANTENNA1;
1819 if (update_search_tbl_counter) 1570 if (update_search_tbl_counter)
1820 search_tbl->action = tbl->action; 1571 search_tbl->action = tbl->action;
@@ -1823,171 +1574,6 @@ static int rs_move_mimo2_to_other(struct iwl_mvm *mvm,
1823} 1574}
1824 1575
1825/* 1576/*
1826 * Try to switch to new modulation mode from MIMO3
1827 */
1828static int rs_move_mimo3_to_other(struct iwl_mvm *mvm,
1829 struct iwl_lq_sta *lq_sta,
1830 struct ieee80211_sta *sta, int index)
1831{
1832 s8 is_green = lq_sta->is_green;
1833 struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
1834 struct iwl_scale_tbl_info *search_tbl =
1835 &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
1836 struct iwl_rate_scale_data *window = &(tbl->win[index]);
1837 struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
1838 u32 sz = (sizeof(struct iwl_scale_tbl_info) -
1839 (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
1840 u8 start_action;
1841 u8 valid_tx_ant = iwl_fw_valid_tx_ant(mvm->fw);
1842 u8 tx_chains_num = num_of_ant(valid_tx_ant);
1843 int ret;
1844 u8 update_search_tbl_counter = 0;
1845
1846 switch (BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD)) {
1847 case IWL_BT_COEX_TRAFFIC_LOAD_NONE:
1848 /* nothing */
1849 break;
1850 case IWL_BT_COEX_TRAFFIC_LOAD_HIGH:
1851 case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS:
1852 /* avoid antenna B and MIMO */
1853 if (tbl->action != IWL_MIMO3_SWITCH_SISO_A)
1854 tbl->action = IWL_MIMO3_SWITCH_SISO_A;
1855 break;
1856 case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
1857 /* avoid antenna B unless MIMO */
1858 if (tbl->action == IWL_MIMO3_SWITCH_SISO_B ||
1859 tbl->action == IWL_MIMO3_SWITCH_SISO_C)
1860 tbl->action = IWL_MIMO3_SWITCH_SISO_A;
1861 break;
1862 default:
1863 IWL_ERR(mvm, "Invalid BT load %d",
1864 BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD));
1865 break;
1866 }
1867
1868 start_action = tbl->action;
1869 while (1) {
1870 lq_sta->action_counter++;
1871 switch (tbl->action) {
1872 case IWL_MIMO3_SWITCH_ANTENNA1:
1873 case IWL_MIMO3_SWITCH_ANTENNA2:
1874 IWL_DEBUG_RATE(mvm, "LQ: MIMO3 toggle Antennas\n");
1875
1876 if (tx_chains_num <= 3)
1877 break;
1878
1879 if (window->success_ratio >= IWL_RS_GOOD_RATIO)
1880 break;
1881
1882 memcpy(search_tbl, tbl, sz);
1883 if (rs_toggle_antenna(valid_tx_ant,
1884 &search_tbl->current_rate,
1885 search_tbl))
1886 goto out;
1887 break;
1888 case IWL_MIMO3_SWITCH_SISO_A:
1889 case IWL_MIMO3_SWITCH_SISO_B:
1890 case IWL_MIMO3_SWITCH_SISO_C:
1891 IWL_DEBUG_RATE(mvm, "LQ: MIMO3 switch to SISO\n");
1892
1893 /* Set up new search table for SISO */
1894 memcpy(search_tbl, tbl, sz);
1895
1896 if (tbl->action == IWL_MIMO3_SWITCH_SISO_A)
1897 search_tbl->ant_type = ANT_A;
1898 else if (tbl->action == IWL_MIMO3_SWITCH_SISO_B)
1899 search_tbl->ant_type = ANT_B;
1900 else
1901 search_tbl->ant_type = ANT_C;
1902
1903 if (!rs_is_valid_ant(valid_tx_ant,
1904 search_tbl->ant_type))
1905 break;
1906
1907 ret = rs_switch_to_siso(mvm, lq_sta, sta,
1908 search_tbl, index);
1909 if (!ret)
1910 goto out;
1911
1912 break;
1913
1914 case IWL_MIMO3_SWITCH_MIMO2_AB:
1915 case IWL_MIMO3_SWITCH_MIMO2_AC:
1916 case IWL_MIMO3_SWITCH_MIMO2_BC:
1917 IWL_DEBUG_RATE(mvm, "LQ: MIMO3 switch to MIMO2\n");
1918
1919 memcpy(search_tbl, tbl, sz);
1920 search_tbl->is_SGI = 0;
1921 if (tbl->action == IWL_MIMO3_SWITCH_MIMO2_AB)
1922 search_tbl->ant_type = ANT_AB;
1923 else if (tbl->action == IWL_MIMO3_SWITCH_MIMO2_AC)
1924 search_tbl->ant_type = ANT_AC;
1925 else
1926 search_tbl->ant_type = ANT_BC;
1927
1928 if (!rs_is_valid_ant(valid_tx_ant,
1929 search_tbl->ant_type))
1930 break;
1931
1932 ret = rs_switch_to_mimo2(mvm, lq_sta, sta,
1933 search_tbl, index);
1934 if (!ret)
1935 goto out;
1936
1937 break;
1938
1939 case IWL_MIMO3_SWITCH_GI:
1940 if (!tbl->is_ht40 && !(ht_cap->cap &
1941 IEEE80211_HT_CAP_SGI_20))
1942 break;
1943 if (tbl->is_ht40 && !(ht_cap->cap &
1944 IEEE80211_HT_CAP_SGI_40))
1945 break;
1946
1947 IWL_DEBUG_RATE(mvm, "LQ: MIMO3 toggle SGI/NGI\n");
1948
1949 /* Set up new search table for MIMO */
1950 memcpy(search_tbl, tbl, sz);
1951 search_tbl->is_SGI = !tbl->is_SGI;
1952 rs_set_expected_tpt_table(lq_sta, search_tbl);
1953 /*
1954 * If active table already uses the fastest possible
1955 * modulation (dual stream with short guard interval),
1956 * and it's working well, there's no need to look
1957 * for a better type of modulation!
1958 */
1959 if (tbl->is_SGI) {
1960 s32 tpt = lq_sta->last_tpt / 100;
1961 if (tpt >= search_tbl->expected_tpt[index])
1962 break;
1963 }
1964 search_tbl->current_rate =
1965 rate_n_flags_from_tbl(mvm, search_tbl,
1966 index, is_green);
1967 update_search_tbl_counter = 1;
1968 goto out;
1969 }
1970 tbl->action++;
1971 if (tbl->action > IWL_MIMO3_SWITCH_GI)
1972 tbl->action = IWL_MIMO3_SWITCH_ANTENNA1;
1973
1974 if (tbl->action == start_action)
1975 break;
1976 }
1977 search_tbl->lq_type = LQ_NONE;
1978 return 0;
1979 out:
1980 lq_sta->search_better_tbl = 1;
1981 tbl->action++;
1982 if (tbl->action > IWL_MIMO3_SWITCH_GI)
1983 tbl->action = IWL_MIMO3_SWITCH_ANTENNA1;
1984 if (update_search_tbl_counter)
1985 search_tbl->action = tbl->action;
1986
1987 return 0;
1988}
1989
1990/*
1991 * Check whether we should continue using same modulation mode, or 1577 * Check whether we should continue using same modulation mode, or
1992 * begin search for a new mode, based on: 1578 * begin search for a new mode, based on:
1993 * 1) # tx successes or failures while using this mode 1579 * 1) # tx successes or failures while using this mode
@@ -2086,6 +1672,22 @@ static void rs_update_rate_tbl(struct iwl_mvm *mvm,
2086 iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, CMD_ASYNC, false); 1672 iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, CMD_ASYNC, false);
2087} 1673}
2088 1674
1675static u8 rs_get_tid(struct iwl_lq_sta *lq_data,
1676 struct ieee80211_hdr *hdr)
1677{
1678 u8 tid = IWL_MAX_TID_COUNT;
1679
1680 if (ieee80211_is_data_qos(hdr->frame_control)) {
1681 u8 *qc = ieee80211_get_qos_ctl(hdr);
1682 tid = qc[0] & 0xf;
1683 }
1684
1685 if (unlikely(tid > IWL_MAX_TID_COUNT))
1686 tid = IWL_MAX_TID_COUNT;
1687
1688 return tid;
1689}
1690
2089/* 1691/*
2090 * Do rate scaling and search for new modulation mode. 1692 * Do rate scaling and search for new modulation mode.
2091 */ 1693 */
@@ -2129,7 +1731,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
2129 1731
2130 lq_sta->supp_rates = sta->supp_rates[lq_sta->band]; 1732 lq_sta->supp_rates = sta->supp_rates[lq_sta->band];
2131 1733
2132 tid = rs_tl_add_packet(lq_sta, hdr); 1734 tid = rs_get_tid(lq_sta, hdr);
2133 if ((tid != IWL_MAX_TID_COUNT) && 1735 if ((tid != IWL_MAX_TID_COUNT) &&
2134 (lq_sta->tx_agg_tid_en & (1 << tid))) { 1736 (lq_sta->tx_agg_tid_en & (1 << tid))) {
2135 tid_data = &sta_priv->tid_data[tid]; 1737 tid_data = &sta_priv->tid_data[tid];
@@ -2377,8 +1979,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
2377 scale_action = 0; 1979 scale_action = 0;
2378 1980
2379 if ((BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD) >= 1981 if ((BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD) >=
2380 IWL_BT_COEX_TRAFFIC_LOAD_HIGH) && 1982 IWL_BT_COEX_TRAFFIC_LOAD_HIGH) && (is_mimo(tbl->lq_type))) {
2381 (is_mimo2(tbl->lq_type) || is_mimo3(tbl->lq_type))) {
2382 if (lq_sta->last_bt_traffic > 1983 if (lq_sta->last_bt_traffic >
2383 BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD)) { 1984 BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD)) {
2384 /* 1985 /*
@@ -2395,8 +1996,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
2395 BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD); 1996 BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD);
2396 1997
2397 if ((BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD) >= 1998 if ((BT_MBOX_MSG(&mvm->last_bt_notif, 3, TRAFFIC_LOAD) >=
2398 IWL_BT_COEX_TRAFFIC_LOAD_HIGH) && 1999 IWL_BT_COEX_TRAFFIC_LOAD_HIGH) && is_mimo(tbl->lq_type)) {
2399 (is_mimo2(tbl->lq_type) || is_mimo3(tbl->lq_type))) {
2400 /* search for a new modulation */ 2000 /* search for a new modulation */
2401 rs_stay_in_table(lq_sta, true); 2001 rs_stay_in_table(lq_sta, true);
2402 goto lq_update; 2002 goto lq_update;
@@ -2456,7 +2056,7 @@ lq_update:
2456 else if (is_mimo2(tbl->lq_type)) 2056 else if (is_mimo2(tbl->lq_type))
2457 rs_move_mimo2_to_other(mvm, lq_sta, sta, index); 2057 rs_move_mimo2_to_other(mvm, lq_sta, sta, index);
2458 else 2058 else
2459 rs_move_mimo3_to_other(mvm, lq_sta, sta, index); 2059 WARN_ON_ONCE(1);
2460 2060
2461 /* If new "search" mode was selected, set up in uCode table */ 2061 /* If new "search" mode was selected, set up in uCode table */
2462 if (lq_sta->search_better_tbl) { 2062 if (lq_sta->search_better_tbl) {
@@ -2621,11 +2221,10 @@ static void rs_get_rate(void *mvm_r, struct ieee80211_sta *sta, void *mvm_sta,
2621 rate_idx -= IWL_FIRST_OFDM_RATE; 2221 rate_idx -= IWL_FIRST_OFDM_RATE;
2622 /* 6M and 9M shared same MCS index */ 2222 /* 6M and 9M shared same MCS index */
2623 rate_idx = (rate_idx > 0) ? (rate_idx - 1) : 0; 2223 rate_idx = (rate_idx > 0) ? (rate_idx - 1) : 0;
2224 WARN_ON_ONCE(rs_extract_rate(lq_sta->last_rate_n_flags) >=
2225 IWL_RATE_MIMO3_6M_PLCP);
2624 if (rs_extract_rate(lq_sta->last_rate_n_flags) >= 2226 if (rs_extract_rate(lq_sta->last_rate_n_flags) >=
2625 IWL_RATE_MIMO3_6M_PLCP) 2227 IWL_RATE_MIMO2_6M_PLCP)
2626 rate_idx = rate_idx + (2 * MCS_INDEX_PER_STREAM);
2627 else if (rs_extract_rate(lq_sta->last_rate_n_flags) >=
2628 IWL_RATE_MIMO2_6M_PLCP)
2629 rate_idx = rate_idx + MCS_INDEX_PER_STREAM; 2228 rate_idx = rate_idx + MCS_INDEX_PER_STREAM;
2630 info->control.rates[0].flags = IEEE80211_TX_RC_MCS; 2229 info->control.rates[0].flags = IEEE80211_TX_RC_MCS;
2631 if (lq_sta->last_rate_n_flags & RATE_MCS_SGI_MSK) 2230 if (lq_sta->last_rate_n_flags & RATE_MCS_SGI_MSK)
@@ -2688,9 +2287,6 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
2688 2287
2689 lq_sta->flush_timer = 0; 2288 lq_sta->flush_timer = 0;
2690 lq_sta->supp_rates = sta->supp_rates[sband->band]; 2289 lq_sta->supp_rates = sta->supp_rates[sband->band];
2691 for (j = 0; j < LQ_SIZE; j++)
2692 for (i = 0; i < IWL_RATE_COUNT; i++)
2693 rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]);
2694 2290
2695 IWL_DEBUG_RATE(mvm, 2291 IWL_DEBUG_RATE(mvm,
2696 "LQ: *** rate scale station global init for station %d ***\n", 2292 "LQ: *** rate scale station global init for station %d ***\n",
@@ -2727,16 +2323,10 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
2727 lq_sta->active_mimo2_rate &= ~((u16)0x2); 2323 lq_sta->active_mimo2_rate &= ~((u16)0x2);
2728 lq_sta->active_mimo2_rate <<= IWL_FIRST_OFDM_RATE; 2324 lq_sta->active_mimo2_rate <<= IWL_FIRST_OFDM_RATE;
2729 2325
2730 lq_sta->active_mimo3_rate = ht_cap->mcs.rx_mask[2] << 1;
2731 lq_sta->active_mimo3_rate |= ht_cap->mcs.rx_mask[2] & 0x1;
2732 lq_sta->active_mimo3_rate &= ~((u16)0x2);
2733 lq_sta->active_mimo3_rate <<= IWL_FIRST_OFDM_RATE;
2734
2735 IWL_DEBUG_RATE(mvm, 2326 IWL_DEBUG_RATE(mvm,
2736 "SISO-RATE=%X MIMO2-RATE=%X MIMO3-RATE=%X\n", 2327 "SISO-RATE=%X MIMO2-RATE=%X\n",
2737 lq_sta->active_siso_rate, 2328 lq_sta->active_siso_rate,
2738 lq_sta->active_mimo2_rate, 2329 lq_sta->active_mimo2_rate);
2739 lq_sta->active_mimo3_rate);
2740 2330
2741 /* These values will be overridden later */ 2331 /* These values will be overridden later */
2742 lq_sta->lq.single_stream_ant_msk = 2332 lq_sta->lq.single_stream_ant_msk =
@@ -2780,7 +2370,7 @@ static void rs_fill_link_cmd(struct iwl_mvm *mvm,
2780 struct iwl_lq_cmd *lq_cmd = &lq_sta->lq; 2370 struct iwl_lq_cmd *lq_cmd = &lq_sta->lq;
2781 2371
2782 /* Override starting rate (index 0) if needed for debug purposes */ 2372 /* Override starting rate (index 0) if needed for debug purposes */
2783 rs_dbgfs_set_mcs(lq_sta, &new_rate, index); 2373 rs_dbgfs_set_mcs(lq_sta, &new_rate);
2784 2374
2785 /* Interpret new_rate (rate_n_flags) */ 2375 /* Interpret new_rate (rate_n_flags) */
2786 rs_get_tbl_info_from_mcs(new_rate, lq_sta->band, 2376 rs_get_tbl_info_from_mcs(new_rate, lq_sta->band,
@@ -2827,7 +2417,7 @@ static void rs_fill_link_cmd(struct iwl_mvm *mvm,
2827 } 2417 }
2828 2418
2829 /* Override next rate if needed for debug purposes */ 2419 /* Override next rate if needed for debug purposes */
2830 rs_dbgfs_set_mcs(lq_sta, &new_rate, index); 2420 rs_dbgfs_set_mcs(lq_sta, &new_rate);
2831 2421
2832 /* Fill next table entry */ 2422 /* Fill next table entry */
2833 lq_cmd->rs_table[index] = 2423 lq_cmd->rs_table[index] =
@@ -2869,7 +2459,7 @@ static void rs_fill_link_cmd(struct iwl_mvm *mvm,
2869 use_ht_possible = 0; 2459 use_ht_possible = 0;
2870 2460
2871 /* Override next rate if needed for debug purposes */ 2461 /* Override next rate if needed for debug purposes */
2872 rs_dbgfs_set_mcs(lq_sta, &new_rate, index); 2462 rs_dbgfs_set_mcs(lq_sta, &new_rate);
2873 2463
2874 /* Fill next table entry */ 2464 /* Fill next table entry */
2875 lq_cmd->rs_table[index] = cpu_to_le32(new_rate); 2465 lq_cmd->rs_table[index] = cpu_to_le32(new_rate);
@@ -2914,7 +2504,7 @@ static void rs_free_sta(void *mvm_r, struct ieee80211_sta *sta,
2914 2504
2915#ifdef CONFIG_MAC80211_DEBUGFS 2505#ifdef CONFIG_MAC80211_DEBUGFS
2916static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, 2506static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
2917 u32 *rate_n_flags, int index) 2507 u32 *rate_n_flags)
2918{ 2508{
2919 struct iwl_mvm *mvm; 2509 struct iwl_mvm *mvm;
2920 u8 valid_tx_ant; 2510 u8 valid_tx_ant;
@@ -2999,8 +2589,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
2999 (is_legacy(tbl->lq_type)) ? "legacy" : "HT"); 2589 (is_legacy(tbl->lq_type)) ? "legacy" : "HT");
3000 if (is_Ht(tbl->lq_type)) { 2590 if (is_Ht(tbl->lq_type)) {
3001 desc += sprintf(buff+desc, " %s", 2591 desc += sprintf(buff+desc, " %s",
3002 (is_siso(tbl->lq_type)) ? "SISO" : 2592 (is_siso(tbl->lq_type)) ? "SISO" : "MIMO2");
3003 ((is_mimo2(tbl->lq_type)) ? "MIMO2" : "MIMO3"));
3004 desc += sprintf(buff+desc, " %s", 2593 desc += sprintf(buff+desc, " %s",
3005 (tbl->is_ht40) ? "40MHz" : "20MHz"); 2594 (tbl->is_ht40) ? "40MHz" : "20MHz");
3006 desc += sprintf(buff+desc, " %s %s %s\n", 2595 desc += sprintf(buff+desc, " %s %s %s\n",
@@ -3100,32 +2689,6 @@ static const struct file_operations rs_sta_dbgfs_stats_table_ops = {
3100 .llseek = default_llseek, 2689 .llseek = default_llseek,
3101}; 2690};
3102 2691
3103static ssize_t rs_sta_dbgfs_rate_scale_data_read(struct file *file,
3104 char __user *user_buf, size_t count, loff_t *ppos)
3105{
3106 struct iwl_lq_sta *lq_sta = file->private_data;
3107 struct iwl_scale_tbl_info *tbl = &lq_sta->lq_info[lq_sta->active_tbl];
3108 char buff[120];
3109 int desc = 0;
3110
3111 if (is_Ht(tbl->lq_type))
3112 desc += sprintf(buff+desc,
3113 "Bit Rate= %d Mb/s\n",
3114 tbl->expected_tpt[lq_sta->last_txrate_idx]);
3115 else
3116 desc += sprintf(buff+desc,
3117 "Bit Rate= %d Mb/s\n",
3118 iwl_rates[lq_sta->last_txrate_idx].ieee >> 1);
3119
3120 return simple_read_from_buffer(user_buf, count, ppos, buff, desc);
3121}
3122
3123static const struct file_operations rs_sta_dbgfs_rate_scale_data_ops = {
3124 .read = rs_sta_dbgfs_rate_scale_data_read,
3125 .open = simple_open,
3126 .llseek = default_llseek,
3127};
3128
3129static void rs_add_debugfs(void *mvm, void *mvm_sta, struct dentry *dir) 2692static void rs_add_debugfs(void *mvm, void *mvm_sta, struct dentry *dir)
3130{ 2693{
3131 struct iwl_lq_sta *lq_sta = mvm_sta; 2694 struct iwl_lq_sta *lq_sta = mvm_sta;
@@ -3135,9 +2698,6 @@ static void rs_add_debugfs(void *mvm, void *mvm_sta, struct dentry *dir)
3135 lq_sta->rs_sta_dbgfs_stats_table_file = 2698 lq_sta->rs_sta_dbgfs_stats_table_file =
3136 debugfs_create_file("rate_stats_table", S_IRUSR, dir, 2699 debugfs_create_file("rate_stats_table", S_IRUSR, dir,
3137 lq_sta, &rs_sta_dbgfs_stats_table_ops); 2700 lq_sta, &rs_sta_dbgfs_stats_table_ops);
3138 lq_sta->rs_sta_dbgfs_rate_scale_data_file =
3139 debugfs_create_file("rate_scale_data", S_IRUSR, dir,
3140 lq_sta, &rs_sta_dbgfs_rate_scale_data_ops);
3141 lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file = 2701 lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file =
3142 debugfs_create_u8("tx_agg_tid_enable", S_IRUSR | S_IWUSR, dir, 2702 debugfs_create_u8("tx_agg_tid_enable", S_IRUSR | S_IWUSR, dir,
3143 &lq_sta->tx_agg_tid_en); 2703 &lq_sta->tx_agg_tid_en);
@@ -3148,7 +2708,6 @@ static void rs_remove_debugfs(void *mvm, void *mvm_sta)
3148 struct iwl_lq_sta *lq_sta = mvm_sta; 2708 struct iwl_lq_sta *lq_sta = mvm_sta;
3149 debugfs_remove(lq_sta->rs_sta_dbgfs_scale_table_file); 2709 debugfs_remove(lq_sta->rs_sta_dbgfs_scale_table_file);
3150 debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file); 2710 debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file);
3151 debugfs_remove(lq_sta->rs_sta_dbgfs_rate_scale_data_file);
3152 debugfs_remove(lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file); 2711 debugfs_remove(lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file);
3153} 2712}
3154#endif 2713#endif
@@ -3159,8 +2718,9 @@ static void rs_remove_debugfs(void *mvm, void *mvm_sta)
3159 * station is added we ignore it. 2718 * station is added we ignore it.
3160 */ 2719 */
3161static void rs_rate_init_stub(void *mvm_r, 2720static void rs_rate_init_stub(void *mvm_r,
3162 struct ieee80211_supported_band *sband, 2721 struct ieee80211_supported_band *sband,
3163 struct ieee80211_sta *sta, void *mvm_sta) 2722 struct cfg80211_chan_def *chandef,
2723 struct ieee80211_sta *sta, void *mvm_sta)
3164{ 2724{
3165} 2725}
3166static struct rate_control_ops rs_mvm_ops = { 2726static struct rate_control_ops rs_mvm_ops = {
@@ -3193,13 +2753,14 @@ void iwl_mvm_rate_control_unregister(void)
3193 * iwl_mvm_tx_protection - Gets LQ command, change it to enable/disable 2753 * iwl_mvm_tx_protection - Gets LQ command, change it to enable/disable
3194 * Tx protection, according to this rquest and previous requests, 2754 * Tx protection, according to this rquest and previous requests,
3195 * and send the LQ command. 2755 * and send the LQ command.
3196 * @lq: The LQ command
3197 * @mvmsta: The station 2756 * @mvmsta: The station
3198 * @enable: Enable Tx protection? 2757 * @enable: Enable Tx protection?
3199 */ 2758 */
3200int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, 2759int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
3201 struct iwl_mvm_sta *mvmsta, bool enable) 2760 bool enable)
3202{ 2761{
2762 struct iwl_lq_cmd *lq = &mvmsta->lq_sta.lq;
2763
3203 lockdep_assert_held(&mvm->mutex); 2764 lockdep_assert_held(&mvm->mutex);
3204 2765
3205 if (enable) { 2766 if (enable) {
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h
index cff4f6da7733..335cf1682902 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rs.h
+++ b/drivers/net/wireless/iwlwifi/mvm/rs.h
@@ -38,14 +38,8 @@ struct iwl_rs_rate_info {
38 u8 plcp; /* uCode API: IWL_RATE_6M_PLCP, etc. */ 38 u8 plcp; /* uCode API: IWL_RATE_6M_PLCP, etc. */
39 u8 plcp_siso; /* uCode API: IWL_RATE_SISO_6M_PLCP, etc. */ 39 u8 plcp_siso; /* uCode API: IWL_RATE_SISO_6M_PLCP, etc. */
40 u8 plcp_mimo2; /* uCode API: IWL_RATE_MIMO2_6M_PLCP, etc. */ 40 u8 plcp_mimo2; /* uCode API: IWL_RATE_MIMO2_6M_PLCP, etc. */
41 u8 plcp_mimo3; /* uCode API: IWL_RATE_MIMO3_6M_PLCP, etc. */
42 u8 ieee; /* MAC header: IWL_RATE_6M_IEEE, etc. */
43 u8 prev_ieee; /* previous rate in IEEE speeds */
44 u8 next_ieee; /* next rate in IEEE speeds */
45 u8 prev_rs; /* previous rate used in rs algo */ 41 u8 prev_rs; /* previous rate used in rs algo */
46 u8 next_rs; /* next rate used in rs algo */ 42 u8 next_rs; /* next rate used in rs algo */
47 u8 prev_rs_tgg; /* previous rate used in TGG rs algo */
48 u8 next_rs_tgg; /* next rate used in TGG rs algo */
49}; 43};
50 44
51#define IWL_RATE_60M_PLCP 3 45#define IWL_RATE_60M_PLCP 3
@@ -120,23 +114,6 @@ enum {
120 IWL_RATE_MIMO3_INVM_PLCP = IWL_RATE_SISO_INVM_PLCP, 114 IWL_RATE_MIMO3_INVM_PLCP = IWL_RATE_SISO_INVM_PLCP,
121}; 115};
122 116
123/* MAC header values for bit rates */
124enum {
125 IWL_RATE_6M_IEEE = 12,
126 IWL_RATE_9M_IEEE = 18,
127 IWL_RATE_12M_IEEE = 24,
128 IWL_RATE_18M_IEEE = 36,
129 IWL_RATE_24M_IEEE = 48,
130 IWL_RATE_36M_IEEE = 72,
131 IWL_RATE_48M_IEEE = 96,
132 IWL_RATE_54M_IEEE = 108,
133 IWL_RATE_60M_IEEE = 120,
134 IWL_RATE_1M_IEEE = 2,
135 IWL_RATE_2M_IEEE = 4,
136 IWL_RATE_5M_IEEE = 11,
137 IWL_RATE_11M_IEEE = 22,
138};
139
140#define IWL_RATES_MASK ((1 << IWL_RATE_COUNT) - 1) 117#define IWL_RATES_MASK ((1 << IWL_RATE_COUNT) - 1)
141 118
142#define IWL_INVALID_VALUE -1 119#define IWL_INVALID_VALUE -1
@@ -165,47 +142,22 @@ enum {
165#define IWL_LEGACY_SWITCH_ANTENNA1 0 142#define IWL_LEGACY_SWITCH_ANTENNA1 0
166#define IWL_LEGACY_SWITCH_ANTENNA2 1 143#define IWL_LEGACY_SWITCH_ANTENNA2 1
167#define IWL_LEGACY_SWITCH_SISO 2 144#define IWL_LEGACY_SWITCH_SISO 2
168#define IWL_LEGACY_SWITCH_MIMO2_AB 3 145#define IWL_LEGACY_SWITCH_MIMO2 3
169#define IWL_LEGACY_SWITCH_MIMO2_AC 4
170#define IWL_LEGACY_SWITCH_MIMO2_BC 5
171#define IWL_LEGACY_SWITCH_MIMO3_ABC 6
172 146
173/* possible actions when in siso mode */ 147/* possible actions when in siso mode */
174#define IWL_SISO_SWITCH_ANTENNA1 0 148#define IWL_SISO_SWITCH_ANTENNA1 0
175#define IWL_SISO_SWITCH_ANTENNA2 1 149#define IWL_SISO_SWITCH_ANTENNA2 1
176#define IWL_SISO_SWITCH_MIMO2_AB 2 150#define IWL_SISO_SWITCH_MIMO2 2
177#define IWL_SISO_SWITCH_MIMO2_AC 3 151#define IWL_SISO_SWITCH_GI 3
178#define IWL_SISO_SWITCH_MIMO2_BC 4
179#define IWL_SISO_SWITCH_GI 5
180#define IWL_SISO_SWITCH_MIMO3_ABC 6
181
182 152
183/* possible actions when in mimo mode */ 153/* possible actions when in mimo mode */
184#define IWL_MIMO2_SWITCH_ANTENNA1 0 154#define IWL_MIMO2_SWITCH_ANTENNA1 0
185#define IWL_MIMO2_SWITCH_ANTENNA2 1 155#define IWL_MIMO2_SWITCH_ANTENNA2 1
186#define IWL_MIMO2_SWITCH_SISO_A 2 156#define IWL_MIMO2_SWITCH_SISO_A 2
187#define IWL_MIMO2_SWITCH_SISO_B 3 157#define IWL_MIMO2_SWITCH_SISO_B 3
188#define IWL_MIMO2_SWITCH_SISO_C 4 158#define IWL_MIMO2_SWITCH_GI 4
189#define IWL_MIMO2_SWITCH_GI 5
190#define IWL_MIMO2_SWITCH_MIMO3_ABC 6
191
192 159
193/* possible actions when in mimo3 mode */ 160#define IWL_MAX_SEARCH IWL_MIMO2_SWITCH_GI
194#define IWL_MIMO3_SWITCH_ANTENNA1 0
195#define IWL_MIMO3_SWITCH_ANTENNA2 1
196#define IWL_MIMO3_SWITCH_SISO_A 2
197#define IWL_MIMO3_SWITCH_SISO_B 3
198#define IWL_MIMO3_SWITCH_SISO_C 4
199#define IWL_MIMO3_SWITCH_MIMO2_AB 5
200#define IWL_MIMO3_SWITCH_MIMO2_AC 6
201#define IWL_MIMO3_SWITCH_MIMO2_BC 7
202#define IWL_MIMO3_SWITCH_GI 8
203
204
205#define IWL_MAX_11N_MIMO3_SEARCH IWL_MIMO3_SWITCH_GI
206#define IWL_MAX_SEARCH IWL_MIMO2_SWITCH_MIMO3_ABC
207
208/*FIXME:RS:add possible actions for MIMO3*/
209 161
210#define IWL_ACTION_LIMIT 3 /* # possible actions */ 162#define IWL_ACTION_LIMIT 3 /* # possible actions */
211 163
@@ -240,15 +192,13 @@ enum iwl_table_type {
240 LQ_A, 192 LQ_A,
241 LQ_SISO, /* high-throughput types */ 193 LQ_SISO, /* high-throughput types */
242 LQ_MIMO2, 194 LQ_MIMO2,
243 LQ_MIMO3,
244 LQ_MAX, 195 LQ_MAX,
245}; 196};
246 197
247#define is_legacy(tbl) (((tbl) == LQ_G) || ((tbl) == LQ_A)) 198#define is_legacy(tbl) (((tbl) == LQ_G) || ((tbl) == LQ_A))
248#define is_siso(tbl) ((tbl) == LQ_SISO) 199#define is_siso(tbl) ((tbl) == LQ_SISO)
249#define is_mimo2(tbl) ((tbl) == LQ_MIMO2) 200#define is_mimo2(tbl) ((tbl) == LQ_MIMO2)
250#define is_mimo3(tbl) ((tbl) == LQ_MIMO3) 201#define is_mimo(tbl) is_mimo2(tbl)
251#define is_mimo(tbl) (is_mimo2(tbl) || is_mimo3(tbl))
252#define is_Ht(tbl) (is_siso(tbl) || is_mimo(tbl)) 202#define is_Ht(tbl) (is_siso(tbl) || is_mimo(tbl))
253#define is_a_band(tbl) ((tbl) == LQ_A) 203#define is_a_band(tbl) ((tbl) == LQ_A)
254#define is_g_and(tbl) ((tbl) == LQ_G) 204#define is_g_and(tbl) ((tbl) == LQ_G)
@@ -290,17 +240,6 @@ struct iwl_scale_tbl_info {
290 struct iwl_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */ 240 struct iwl_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */
291}; 241};
292 242
293struct iwl_traffic_load {
294 unsigned long time_stamp; /* age of the oldest statistics */
295 u32 packet_count[TID_QUEUE_MAX_SIZE]; /* packet count in this time
296 * slice */
297 u32 total; /* total num of packets during the
298 * last TID_MAX_TIME_DIFF */
299 u8 queue_count; /* number of queues that has
300 * been used since the last cleanup */
301 u8 head; /* start of the circular buffer */
302};
303
304/** 243/**
305 * struct iwl_lq_sta -- driver's rate scaling private structure 244 * struct iwl_lq_sta -- driver's rate scaling private structure
306 * 245 *
@@ -331,18 +270,15 @@ struct iwl_lq_sta {
331 u16 active_legacy_rate; 270 u16 active_legacy_rate;
332 u16 active_siso_rate; 271 u16 active_siso_rate;
333 u16 active_mimo2_rate; 272 u16 active_mimo2_rate;
334 u16 active_mimo3_rate;
335 s8 max_rate_idx; /* Max rate set by user */ 273 s8 max_rate_idx; /* Max rate set by user */
336 u8 missed_rate_counter; 274 u8 missed_rate_counter;
337 275
338 struct iwl_lq_cmd lq; 276 struct iwl_lq_cmd lq;
339 struct iwl_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */ 277 struct iwl_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */
340 struct iwl_traffic_load load[IWL_MAX_TID_COUNT];
341 u8 tx_agg_tid_en; 278 u8 tx_agg_tid_en;
342#ifdef CONFIG_MAC80211_DEBUGFS 279#ifdef CONFIG_MAC80211_DEBUGFS
343 struct dentry *rs_sta_dbgfs_scale_table_file; 280 struct dentry *rs_sta_dbgfs_scale_table_file;
344 struct dentry *rs_sta_dbgfs_stats_table_file; 281 struct dentry *rs_sta_dbgfs_stats_table_file;
345 struct dentry *rs_sta_dbgfs_rate_scale_data_file;
346 struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file; 282 struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file;
347 u32 dbg_fixed_rate; 283 u32 dbg_fixed_rate;
348#endif 284#endif
@@ -404,7 +340,7 @@ extern void iwl_mvm_rate_control_unregister(void);
404 340
405struct iwl_mvm_sta; 341struct iwl_mvm_sta;
406 342
407int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, 343int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
408 struct iwl_mvm_sta *mvmsta, bool enable); 344 bool enable);
409 345
410#endif /* __rs__ */ 346#endif /* __rs__ */
diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c
index e4930d5027d2..2a8cb5a60535 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rx.c
@@ -124,24 +124,15 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
124 ieee80211_rx_ni(mvm->hw, skb); 124 ieee80211_rx_ni(mvm->hw, skb);
125} 125}
126 126
127/* 127static void iwl_mvm_calc_rssi(struct iwl_mvm *mvm,
128 * iwl_mvm_calc_rssi - calculate the rssi in dBm 128 struct iwl_rx_phy_info *phy_info,
129 * @phy_info: the phy information for the coming packet 129 struct ieee80211_rx_status *rx_status)
130 */
131static int iwl_mvm_calc_rssi(struct iwl_mvm *mvm,
132 struct iwl_rx_phy_info *phy_info)
133{ 130{
134 int rssi_a, rssi_b, rssi_a_dbm, rssi_b_dbm, max_rssi_dbm; 131 int rssi_a, rssi_b, rssi_a_dbm, rssi_b_dbm, max_rssi_dbm;
135 int rssi_all_band_a, rssi_all_band_b; 132 int rssi_all_band_a, rssi_all_band_b;
136 u32 agc_a, agc_b, max_agc; 133 u32 agc_a, agc_b, max_agc;
137 u32 val; 134 u32 val;
138 135
139 /* Find max rssi among 2 possible receivers.
140 * These values are measured by the Digital Signal Processor (DSP).
141 * They should stay fairly constant even as the signal strength varies,
142 * if the radio's Automatic Gain Control (AGC) is working right.
143 * AGC value (see below) will provide the "interesting" info.
144 */
145 val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_AGC_IDX]); 136 val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_AGC_IDX]);
146 agc_a = (val & IWL_OFDM_AGC_A_MSK) >> IWL_OFDM_AGC_A_POS; 137 agc_a = (val & IWL_OFDM_AGC_A_MSK) >> IWL_OFDM_AGC_A_POS;
147 agc_b = (val & IWL_OFDM_AGC_B_MSK) >> IWL_OFDM_AGC_B_POS; 138 agc_b = (val & IWL_OFDM_AGC_B_MSK) >> IWL_OFDM_AGC_B_POS;
@@ -166,7 +157,51 @@ static int iwl_mvm_calc_rssi(struct iwl_mvm *mvm,
166 IWL_DEBUG_STATS(mvm, "Rssi In A %d B %d Max %d AGCA %d AGCB %d\n", 157 IWL_DEBUG_STATS(mvm, "Rssi In A %d B %d Max %d AGCA %d AGCB %d\n",
167 rssi_a_dbm, rssi_b_dbm, max_rssi_dbm, agc_a, agc_b); 158 rssi_a_dbm, rssi_b_dbm, max_rssi_dbm, agc_a, agc_b);
168 159
169 return max_rssi_dbm; 160 rx_status->signal = max_rssi_dbm;
161 rx_status->chains = (le16_to_cpu(phy_info->phy_flags) &
162 RX_RES_PHY_FLAGS_ANTENNA)
163 >> RX_RES_PHY_FLAGS_ANTENNA_POS;
164 rx_status->chain_signal[0] = rssi_a_dbm;
165 rx_status->chain_signal[1] = rssi_b_dbm;
166}
167
168/*
169 * iwl_mvm_get_signal_strength - use new rx PHY INFO API
170 * values are reported by the fw as positive values - need to negate
171 * to obtain their dBM. Account for missing antennas by replacing 0
172 * values by -256dBm: practically 0 power and a non-feasible 8 bit value.
173 */
174static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm,
175 struct iwl_rx_phy_info *phy_info,
176 struct ieee80211_rx_status *rx_status)
177{
178 int energy_a, energy_b, energy_c, max_energy;
179 u32 val;
180
181 val =
182 le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_ENERGY_ANT_ABC_IDX]);
183 energy_a = (val & IWL_RX_INFO_ENERGY_ANT_A_MSK) >>
184 IWL_RX_INFO_ENERGY_ANT_A_POS;
185 energy_a = energy_a ? -energy_a : -256;
186 energy_b = (val & IWL_RX_INFO_ENERGY_ANT_B_MSK) >>
187 IWL_RX_INFO_ENERGY_ANT_B_POS;
188 energy_b = energy_b ? -energy_b : -256;
189 energy_c = (val & IWL_RX_INFO_ENERGY_ANT_C_MSK) >>
190 IWL_RX_INFO_ENERGY_ANT_C_POS;
191 energy_c = energy_c ? -energy_c : -256;
192 max_energy = max(energy_a, energy_b);
193 max_energy = max(max_energy, energy_c);
194
195 IWL_DEBUG_STATS(mvm, "energy In A %d B %d C %d , and max %d\n",
196 energy_a, energy_b, energy_c, max_energy);
197
198 rx_status->signal = max_energy;
199 rx_status->chains = (le16_to_cpu(phy_info->phy_flags) &
200 RX_RES_PHY_FLAGS_ANTENNA)
201 >> RX_RES_PHY_FLAGS_ANTENNA_POS;
202 rx_status->chain_signal[0] = energy_a;
203 rx_status->chain_signal[1] = energy_b;
204 rx_status->chain_signal[2] = energy_c;
170} 205}
171 206
172/* 207/*
@@ -289,29 +324,14 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
289 */ 324 */
290 /*rx_status.flag |= RX_FLAG_MACTIME_MPDU;*/ 325 /*rx_status.flag |= RX_FLAG_MACTIME_MPDU;*/
291 326
292 /* Find max signal strength (dBm) among 3 antenna/receiver chains */ 327 if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_RX_ENERGY_API)
293 rx_status.signal = iwl_mvm_calc_rssi(mvm, phy_info); 328 iwl_mvm_get_signal_strength(mvm, phy_info, &rx_status);
329 else
330 iwl_mvm_calc_rssi(mvm, phy_info, &rx_status);
294 331
295 IWL_DEBUG_STATS_LIMIT(mvm, "Rssi %d, TSF %llu\n", rx_status.signal, 332 IWL_DEBUG_STATS_LIMIT(mvm, "Rssi %d, TSF %llu\n", rx_status.signal,
296 (unsigned long long)rx_status.mactime); 333 (unsigned long long)rx_status.mactime);
297 334
298 /*
299 * "antenna number"
300 *
301 * It seems that the antenna field in the phy flags value
302 * is actually a bit field. This is undefined by radiotap,
303 * it wants an actual antenna number but I always get "7"
304 * for most legacy frames I receive indicating that the
305 * same frame was received on all three RX chains.
306 *
307 * I think this field should be removed in favor of a
308 * new 802.11n radiotap field "RX chains" that is defined
309 * as a bitmask.
310 */
311 rx_status.antenna = (le16_to_cpu(phy_info->phy_flags) &
312 RX_RES_PHY_FLAGS_ANTENNA)
313 >> RX_RES_PHY_FLAGS_ANTENNA_POS;
314
315 /* set the preamble flag if appropriate */ 335 /* set the preamble flag if appropriate */
316 if (phy_info->phy_flags & cpu_to_le16(RX_RES_PHY_FLAGS_SHORT_PREAMBLE)) 336 if (phy_info->phy_flags & cpu_to_le16(RX_RES_PHY_FLAGS_SHORT_PREAMBLE))
317 rx_status.flag |= RX_FLAG_SHORTPRE; 337 rx_status.flag |= RX_FLAG_SHORTPRE;
@@ -364,11 +384,74 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
364 return 0; 384 return 0;
365} 385}
366 386
387static void iwl_mvm_update_rx_statistics(struct iwl_mvm *mvm,
388 struct iwl_notif_statistics *stats)
389{
390 /*
391 * NOTE FW aggregates the statistics - BUT the statistics are cleared
392 * when the driver issues REPLY_STATISTICS_CMD 0x9c with CLEAR_STATS
393 * bit set.
394 */
395 lockdep_assert_held(&mvm->mutex);
396 memcpy(&mvm->rx_stats, &stats->rx, sizeof(struct mvm_statistics_rx));
397}
398
399struct iwl_mvm_stat_data {
400 struct iwl_notif_statistics *stats;
401 struct iwl_mvm *mvm;
402};
403
404static void iwl_mvm_stat_iterator(void *_data, u8 *mac,
405 struct ieee80211_vif *vif)
406{
407 struct iwl_mvm_stat_data *data = _data;
408 struct iwl_notif_statistics *stats = data->stats;
409 struct iwl_mvm *mvm = data->mvm;
410 int sig = -stats->general.beacon_filter_average_energy;
411 int last_event;
412 int thold = vif->bss_conf.cqm_rssi_thold;
413 int hyst = vif->bss_conf.cqm_rssi_hyst;
414 u16 id = le32_to_cpu(stats->rx.general.mac_id);
415 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
416
417 if (mvmvif->id != id)
418 return;
419
420 if (vif->type != NL80211_IFTYPE_STATION)
421 return;
422
423 mvmvif->bf_data.ave_beacon_signal = sig;
424
425 if (!(vif->driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI))
426 return;
427
428 /* CQM Notification */
429 last_event = mvmvif->bf_data.last_cqm_event;
430 if (thold && sig < thold && (last_event == 0 ||
431 sig < last_event - hyst)) {
432 mvmvif->bf_data.last_cqm_event = sig;
433 IWL_DEBUG_RX(mvm, "cqm_iterator cqm low %d\n",
434 sig);
435 ieee80211_cqm_rssi_notify(
436 vif,
437 NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
438 GFP_KERNEL);
439 } else if (sig > thold &&
440 (last_event == 0 || sig > last_event + hyst)) {
441 mvmvif->bf_data.last_cqm_event = sig;
442 IWL_DEBUG_RX(mvm, "cqm_iterator cqm high %d\n",
443 sig);
444 ieee80211_cqm_rssi_notify(
445 vif,
446 NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
447 GFP_KERNEL);
448 }
449}
450
367/* 451/*
368 * iwl_mvm_rx_statistics - STATISTICS_NOTIFICATION handler 452 * iwl_mvm_rx_statistics - STATISTICS_NOTIFICATION handler
369 * 453 *
370 * TODO: This handler is implemented partially. 454 * TODO: This handler is implemented partially.
371 * It only gets the NIC's temperature.
372 */ 455 */
373int iwl_mvm_rx_statistics(struct iwl_mvm *mvm, 456int iwl_mvm_rx_statistics(struct iwl_mvm *mvm,
374 struct iwl_rx_cmd_buffer *rxb, 457 struct iwl_rx_cmd_buffer *rxb,
@@ -377,11 +460,20 @@ int iwl_mvm_rx_statistics(struct iwl_mvm *mvm,
377 struct iwl_rx_packet *pkt = rxb_addr(rxb); 460 struct iwl_rx_packet *pkt = rxb_addr(rxb);
378 struct iwl_notif_statistics *stats = (void *)&pkt->data; 461 struct iwl_notif_statistics *stats = (void *)&pkt->data;
379 struct mvm_statistics_general_common *common = &stats->general.common; 462 struct mvm_statistics_general_common *common = &stats->general.common;
463 struct iwl_mvm_stat_data data = {
464 .stats = stats,
465 .mvm = mvm,
466 };
380 467
381 if (mvm->temperature != le32_to_cpu(common->temperature)) { 468 if (mvm->temperature != le32_to_cpu(common->temperature)) {
382 mvm->temperature = le32_to_cpu(common->temperature); 469 mvm->temperature = le32_to_cpu(common->temperature);
383 iwl_mvm_tt_handler(mvm); 470 iwl_mvm_tt_handler(mvm);
384 } 471 }
472 iwl_mvm_update_rx_statistics(mvm, stats);
385 473
474 ieee80211_iterate_active_interfaces(mvm->hw,
475 IEEE80211_IFACE_ITER_NORMAL,
476 iwl_mvm_stat_iterator,
477 &data);
386 return 0; 478 return 0;
387} 479}
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c
index acdff6b67e04..9a7ab8495300 100644
--- a/drivers/net/wireless/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/iwlwifi/mvm/scan.c
@@ -301,10 +301,12 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm,
301 */ 301 */
302 if (req->n_ssids > 0) { 302 if (req->n_ssids > 0) {
303 cmd->passive2active = cpu_to_le16(1); 303 cmd->passive2active = cpu_to_le16(1);
304 cmd->scan_flags |= SCAN_FLAGS_PASSIVE2ACTIVE;
304 ssid = req->ssids[0].ssid; 305 ssid = req->ssids[0].ssid;
305 ssid_len = req->ssids[0].ssid_len; 306 ssid_len = req->ssids[0].ssid_len;
306 } else { 307 } else {
307 cmd->passive2active = 0; 308 cmd->passive2active = 0;
309 cmd->scan_flags &= ~SCAN_FLAGS_PASSIVE2ACTIVE;
308 } 310 }
309 311
310 iwl_mvm_scan_fill_ssids(cmd, req); 312 iwl_mvm_scan_fill_ssids(cmd, req);
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c
index 563f559b902d..44add291531b 100644
--- a/drivers/net/wireless/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/iwlwifi/mvm/sta.c
@@ -826,8 +826,7 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
826 * method for HT traffic 826 * method for HT traffic
827 * this function also sends the LQ command 827 * this function also sends the LQ command
828 */ 828 */
829 return iwl_mvm_tx_protection(mvm, &mvmsta->lq_sta.lq, 829 return iwl_mvm_tx_protection(mvm, mvmsta, true);
830 mvmsta, true);
831 /* 830 /*
832 * TODO: remove the TLC_RTS flag when we tear down the last 831 * TODO: remove the TLC_RTS flag when we tear down the last
833 * AGG session (agg_tids_count in DVM) 832 * AGG session (agg_tids_count in DVM)
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c
index 7fd6fbfbc1b3..c17b74c31398 100644
--- a/drivers/net/wireless/iwlwifi/mvm/time-event.c
+++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c
@@ -73,7 +73,6 @@
73#include "iwl-prph.h" 73#include "iwl-prph.h"
74 74
75/* A TimeUnit is 1024 microsecond */ 75/* A TimeUnit is 1024 microsecond */
76#define TU_TO_JIFFIES(_tu) (usecs_to_jiffies((_tu) * 1024))
77#define MSEC_TO_TU(_msec) (_msec*1000/1024) 76#define MSEC_TO_TU(_msec) (_msec*1000/1024)
78 77
79/* 78/*
@@ -185,7 +184,7 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
185 } 184 }
186 } 185 }
187 186
188 if (le32_to_cpu(notif->action) & TE_NOTIF_HOST_EVENT_END) { 187 if (le32_to_cpu(notif->action) & TE_V2_NOTIF_HOST_EVENT_END) {
189 IWL_DEBUG_TE(mvm, 188 IWL_DEBUG_TE(mvm,
190 "TE ended - current time %lu, estimated end %lu\n", 189 "TE ended - current time %lu, estimated end %lu\n",
191 jiffies, te_data->end_jiffies); 190 jiffies, te_data->end_jiffies);
@@ -202,10 +201,9 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
202 iwl_mvm_te_check_disconnect(mvm, te_data->vif, 201 iwl_mvm_te_check_disconnect(mvm, te_data->vif,
203 "No assocation and the time event is over already..."); 202 "No assocation and the time event is over already...");
204 iwl_mvm_te_clear_data(mvm, te_data); 203 iwl_mvm_te_clear_data(mvm, te_data);
205 } else if (le32_to_cpu(notif->action) & TE_NOTIF_HOST_EVENT_START) { 204 } else if (le32_to_cpu(notif->action) & TE_V2_NOTIF_HOST_EVENT_START) {
206 te_data->running = true; 205 te_data->running = true;
207 te_data->end_jiffies = jiffies + 206 te_data->end_jiffies = TU_TO_EXP_TIME(te_data->duration);
208 TU_TO_JIFFIES(te_data->duration);
209 207
210 if (te_data->vif->type == NL80211_IFTYPE_P2P_DEVICE) { 208 if (te_data->vif->type == NL80211_IFTYPE_P2P_DEVICE) {
211 set_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status); 209 set_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status);
@@ -270,10 +268,67 @@ static bool iwl_mvm_time_event_response(struct iwl_notif_wait_data *notif_wait,
270 return true; 268 return true;
271} 269}
272 270
271/* used to convert from time event API v2 to v1 */
272#define TE_V2_DEP_POLICY_MSK (TE_V2_DEP_OTHER | TE_V2_DEP_TSF |\
273 TE_V2_EVENT_SOCIOPATHIC)
274static inline u16 te_v2_get_notify(__le16 policy)
275{
276 return le16_to_cpu(policy) & TE_V2_NOTIF_MSK;
277}
278
279static inline u16 te_v2_get_dep_policy(__le16 policy)
280{
281 return (le16_to_cpu(policy) & TE_V2_DEP_POLICY_MSK) >>
282 TE_V2_PLACEMENT_POS;
283}
284
285static inline u16 te_v2_get_absence(__le16 policy)
286{
287 return (le16_to_cpu(policy) & TE_V2_ABSENCE) >> TE_V2_ABSENCE_POS;
288}
289
290static void iwl_mvm_te_v2_to_v1(const struct iwl_time_event_cmd_v2 *cmd_v2,
291 struct iwl_time_event_cmd_v1 *cmd_v1)
292{
293 cmd_v1->id_and_color = cmd_v2->id_and_color;
294 cmd_v1->action = cmd_v2->action;
295 cmd_v1->id = cmd_v2->id;
296 cmd_v1->apply_time = cmd_v2->apply_time;
297 cmd_v1->max_delay = cmd_v2->max_delay;
298 cmd_v1->depends_on = cmd_v2->depends_on;
299 cmd_v1->interval = cmd_v2->interval;
300 cmd_v1->duration = cmd_v2->duration;
301 if (cmd_v2->repeat == TE_V2_REPEAT_ENDLESS)
302 cmd_v1->repeat = cpu_to_le32(TE_V1_REPEAT_ENDLESS);
303 else
304 cmd_v1->repeat = cpu_to_le32(cmd_v2->repeat);
305 cmd_v1->max_frags = cpu_to_le32(cmd_v2->max_frags);
306 cmd_v1->interval_reciprocal = 0; /* unused */
307
308 cmd_v1->dep_policy = cpu_to_le32(te_v2_get_dep_policy(cmd_v2->policy));
309 cmd_v1->is_present = cpu_to_le32(!te_v2_get_absence(cmd_v2->policy));
310 cmd_v1->notify = cpu_to_le32(te_v2_get_notify(cmd_v2->policy));
311}
312
313static int iwl_mvm_send_time_event_cmd(struct iwl_mvm *mvm,
314 const struct iwl_time_event_cmd_v2 *cmd)
315{
316 struct iwl_time_event_cmd_v1 cmd_v1;
317
318 if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2)
319 return iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, CMD_SYNC,
320 sizeof(*cmd), cmd);
321
322 iwl_mvm_te_v2_to_v1(cmd, &cmd_v1);
323 return iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, CMD_SYNC,
324 sizeof(cmd_v1), &cmd_v1);
325}
326
327
273static int iwl_mvm_time_event_send_add(struct iwl_mvm *mvm, 328static int iwl_mvm_time_event_send_add(struct iwl_mvm *mvm,
274 struct ieee80211_vif *vif, 329 struct ieee80211_vif *vif,
275 struct iwl_mvm_time_event_data *te_data, 330 struct iwl_mvm_time_event_data *te_data,
276 struct iwl_time_event_cmd *te_cmd) 331 struct iwl_time_event_cmd_v2 *te_cmd)
277{ 332{
278 static const u8 time_event_response[] = { TIME_EVENT_CMD }; 333 static const u8 time_event_response[] = { TIME_EVENT_CMD };
279 struct iwl_notification_wait wait_time_event; 334 struct iwl_notification_wait wait_time_event;
@@ -309,8 +364,7 @@ static int iwl_mvm_time_event_send_add(struct iwl_mvm *mvm,
309 ARRAY_SIZE(time_event_response), 364 ARRAY_SIZE(time_event_response),
310 iwl_mvm_time_event_response, te_data); 365 iwl_mvm_time_event_response, te_data);
311 366
312 ret = iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, CMD_SYNC, 367 ret = iwl_mvm_send_time_event_cmd(mvm, te_cmd);
313 sizeof(*te_cmd), te_cmd);
314 if (ret) { 368 if (ret) {
315 IWL_ERR(mvm, "Couldn't send TIME_EVENT_CMD: %d\n", ret); 369 IWL_ERR(mvm, "Couldn't send TIME_EVENT_CMD: %d\n", ret);
316 iwl_remove_notification(&mvm->notif_wait, &wait_time_event); 370 iwl_remove_notification(&mvm->notif_wait, &wait_time_event);
@@ -337,13 +391,12 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm,
337{ 391{
338 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 392 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
339 struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data; 393 struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data;
340 struct iwl_time_event_cmd time_cmd = {}; 394 struct iwl_time_event_cmd_v2 time_cmd = {};
341 395
342 lockdep_assert_held(&mvm->mutex); 396 lockdep_assert_held(&mvm->mutex);
343 397
344 if (te_data->running && 398 if (te_data->running &&
345 time_after(te_data->end_jiffies, 399 time_after(te_data->end_jiffies, TU_TO_EXP_TIME(min_duration))) {
346 jiffies + TU_TO_JIFFIES(min_duration))) {
347 IWL_DEBUG_TE(mvm, "We have enough time in the current TE: %u\n", 400 IWL_DEBUG_TE(mvm, "We have enough time in the current TE: %u\n",
348 jiffies_to_msecs(te_data->end_jiffies - jiffies)); 401 jiffies_to_msecs(te_data->end_jiffies - jiffies));
349 return; 402 return;
@@ -372,17 +425,14 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm,
372 time_cmd.apply_time = 425 time_cmd.apply_time =
373 cpu_to_le32(iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG)); 426 cpu_to_le32(iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG));
374 427
375 time_cmd.dep_policy = TE_INDEPENDENT; 428 time_cmd.max_frags = TE_V2_FRAG_NONE;
376 time_cmd.is_present = cpu_to_le32(1);
377 time_cmd.max_frags = cpu_to_le32(TE_FRAG_NONE);
378 time_cmd.max_delay = cpu_to_le32(500); 429 time_cmd.max_delay = cpu_to_le32(500);
379 /* TODO: why do we need to interval = bi if it is not periodic? */ 430 /* TODO: why do we need to interval = bi if it is not periodic? */
380 time_cmd.interval = cpu_to_le32(1); 431 time_cmd.interval = cpu_to_le32(1);
381 time_cmd.interval_reciprocal = cpu_to_le32(iwl_mvm_reciprocal(1));
382 time_cmd.duration = cpu_to_le32(duration); 432 time_cmd.duration = cpu_to_le32(duration);
383 time_cmd.repeat = cpu_to_le32(1); 433 time_cmd.repeat = 1;
384 time_cmd.notify = cpu_to_le32(TE_NOTIF_HOST_EVENT_START | 434 time_cmd.policy = cpu_to_le16(TE_V2_NOTIF_HOST_EVENT_START |
385 TE_NOTIF_HOST_EVENT_END); 435 TE_V2_NOTIF_HOST_EVENT_END);
386 436
387 iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd); 437 iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd);
388} 438}
@@ -396,7 +446,7 @@ void iwl_mvm_remove_time_event(struct iwl_mvm *mvm,
396 struct iwl_mvm_vif *mvmvif, 446 struct iwl_mvm_vif *mvmvif,
397 struct iwl_mvm_time_event_data *te_data) 447 struct iwl_mvm_time_event_data *te_data)
398{ 448{
399 struct iwl_time_event_cmd time_cmd = {}; 449 struct iwl_time_event_cmd_v2 time_cmd = {};
400 u32 id, uid; 450 u32 id, uid;
401 int ret; 451 int ret;
402 452
@@ -433,8 +483,7 @@ void iwl_mvm_remove_time_event(struct iwl_mvm *mvm,
433 cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color)); 483 cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color));
434 484
435 IWL_DEBUG_TE(mvm, "Removing TE 0x%x\n", le32_to_cpu(time_cmd.id)); 485 IWL_DEBUG_TE(mvm, "Removing TE 0x%x\n", le32_to_cpu(time_cmd.id));
436 ret = iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, CMD_SYNC, 486 ret = iwl_mvm_send_time_event_cmd(mvm, &time_cmd);
437 sizeof(time_cmd), &time_cmd);
438 if (WARN_ON(ret)) 487 if (WARN_ON(ret))
439 return; 488 return;
440} 489}
@@ -454,7 +503,7 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
454{ 503{
455 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 504 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
456 struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data; 505 struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data;
457 struct iwl_time_event_cmd time_cmd = {}; 506 struct iwl_time_event_cmd_v2 time_cmd = {};
458 507
459 lockdep_assert_held(&mvm->mutex); 508 lockdep_assert_held(&mvm->mutex);
460 if (te_data->running) { 509 if (te_data->running) {
@@ -485,8 +534,6 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
485 } 534 }
486 535
487 time_cmd.apply_time = cpu_to_le32(0); 536 time_cmd.apply_time = cpu_to_le32(0);
488 time_cmd.dep_policy = cpu_to_le32(TE_INDEPENDENT);
489 time_cmd.is_present = cpu_to_le32(1);
490 time_cmd.interval = cpu_to_le32(1); 537 time_cmd.interval = cpu_to_le32(1);
491 538
492 /* 539 /*
@@ -495,12 +542,12 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
495 * scheduled. To improve the chances of it being scheduled, allow them 542 * scheduled. To improve the chances of it being scheduled, allow them
496 * to be fragmented, and in addition allow them to be delayed. 543 * to be fragmented, and in addition allow them to be delayed.
497 */ 544 */
498 time_cmd.max_frags = cpu_to_le32(MSEC_TO_TU(duration)/20); 545 time_cmd.max_frags = min(MSEC_TO_TU(duration)/50, TE_V2_FRAG_ENDLESS);
499 time_cmd.max_delay = cpu_to_le32(MSEC_TO_TU(duration/2)); 546 time_cmd.max_delay = cpu_to_le32(MSEC_TO_TU(duration/2));
500 time_cmd.duration = cpu_to_le32(MSEC_TO_TU(duration)); 547 time_cmd.duration = cpu_to_le32(MSEC_TO_TU(duration));
501 time_cmd.repeat = cpu_to_le32(1); 548 time_cmd.repeat = 1;
502 time_cmd.notify = cpu_to_le32(TE_NOTIF_HOST_EVENT_START | 549 time_cmd.policy = cpu_to_le16(TE_V2_NOTIF_HOST_EVENT_START |
503 TE_NOTIF_HOST_EVENT_END); 550 TE_V2_NOTIF_HOST_EVENT_END);
504 551
505 return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd); 552 return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd);
506} 553}
diff --git a/drivers/net/wireless/iwlwifi/mvm/tt.c b/drivers/net/wireless/iwlwifi/mvm/tt.c
index d6ae7f16ac11..1f3282dff513 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tt.c
@@ -391,8 +391,7 @@ static void iwl_mvm_tt_tx_protection(struct iwl_mvm *mvm, bool enable)
391 mvmsta = (void *)sta->drv_priv; 391 mvmsta = (void *)sta->drv_priv;
392 if (enable == mvmsta->tt_tx_protection) 392 if (enable == mvmsta->tt_tx_protection)
393 continue; 393 continue;
394 err = iwl_mvm_tx_protection(mvm, &mvmsta->lq_sta.lq, 394 err = iwl_mvm_tx_protection(mvm, mvmsta, enable);
395 mvmsta, enable);
396 if (err) { 395 if (err) {
397 IWL_ERR(mvm, "Failed to %s Tx protection\n", 396 IWL_ERR(mvm, "Failed to %s Tx protection\n",
398 enable ? "enable" : "disable"); 397 enable ? "enable" : "disable");
@@ -513,12 +512,39 @@ static const struct iwl_tt_params iwl7000_tt_params = {
513 .support_tx_backoff = true, 512 .support_tx_backoff = true,
514}; 513};
515 514
515static const struct iwl_tt_params iwl7000_high_temp_tt_params = {
516 .ct_kill_entry = 118,
517 .ct_kill_exit = 96,
518 .ct_kill_duration = 5,
519 .dynamic_smps_entry = 114,
520 .dynamic_smps_exit = 110,
521 .tx_protection_entry = 114,
522 .tx_protection_exit = 108,
523 .tx_backoff = {
524 {.temperature = 112, .backoff = 300},
525 {.temperature = 113, .backoff = 800},
526 {.temperature = 114, .backoff = 1500},
527 {.temperature = 115, .backoff = 3000},
528 {.temperature = 116, .backoff = 5000},
529 {.temperature = 117, .backoff = 10000},
530 },
531 .support_ct_kill = true,
532 .support_dynamic_smps = true,
533 .support_tx_protection = true,
534 .support_tx_backoff = true,
535};
536
516void iwl_mvm_tt_initialize(struct iwl_mvm *mvm) 537void iwl_mvm_tt_initialize(struct iwl_mvm *mvm)
517{ 538{
518 struct iwl_mvm_tt_mgmt *tt = &mvm->thermal_throttle; 539 struct iwl_mvm_tt_mgmt *tt = &mvm->thermal_throttle;
519 540
520 IWL_DEBUG_TEMP(mvm, "Initialize Thermal Throttling\n"); 541 IWL_DEBUG_TEMP(mvm, "Initialize Thermal Throttling\n");
521 tt->params = &iwl7000_tt_params; 542
543 if (mvm->cfg->high_temp)
544 tt->params = &iwl7000_high_temp_tt_params;
545 else
546 tt->params = &iwl7000_tt_params;
547
522 tt->throttle = false; 548 tt->throttle = false;
523 INIT_DELAYED_WORK(&tt->ct_kill_exit, check_exit_ctkill); 549 INIT_DELAYED_WORK(&tt->ct_kill_exit, check_exit_ctkill);
524} 550}
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c
index f0e96a927407..e05440d90319 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tx.c
@@ -91,11 +91,10 @@ static void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
91 tx_flags |= TX_CMD_FLG_ACK | TX_CMD_FLG_BAR; 91 tx_flags |= TX_CMD_FLG_ACK | TX_CMD_FLG_BAR;
92 92
93 /* High prio packet (wrt. BT coex) if it is EAPOL, MCAST or MGMT */ 93 /* High prio packet (wrt. BT coex) if it is EAPOL, MCAST or MGMT */
94 if (info->band == IEEE80211_BAND_2GHZ && 94 if (info->band == IEEE80211_BAND_2GHZ &&
95 (skb->protocol == cpu_to_be16(ETH_P_PAE) || 95 (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO ||
96 is_multicast_ether_addr(hdr->addr1) || 96 is_multicast_ether_addr(hdr->addr1) ||
97 ieee80211_is_back_req(fc) || 97 ieee80211_is_back_req(fc) || ieee80211_is_mgmt(fc)))
98 ieee80211_is_mgmt(fc)))
99 tx_flags |= TX_CMD_FLG_BT_DIS; 98 tx_flags |= TX_CMD_FLG_BT_DIS;
100 99
101 if (ieee80211_has_morefrags(fc)) 100 if (ieee80211_has_morefrags(fc))
@@ -123,6 +122,8 @@ static void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
123 * it 122 * it
124 */ 123 */
125 WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_AMPDU); 124 WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_AMPDU);
125 } else if (skb->protocol == cpu_to_be16(ETH_P_PAE)) {
126 tx_cmd->pm_frame_timeout = cpu_to_le16(2);
126 } else { 127 } else {
127 tx_cmd->pm_frame_timeout = 0; 128 tx_cmd->pm_frame_timeout = 0;
128 } 129 }
@@ -171,7 +172,7 @@ static void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm,
171 } 172 }
172 173
173 /* 174 /*
174 * for data packets, rate info comes from the table inside he fw. This 175 * for data packets, rate info comes from the table inside the fw. This
175 * table is controlled by LINK_QUALITY commands 176 * table is controlled by LINK_QUALITY commands
176 */ 177 */
177 178
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c
index 1e1332839e4a..a9c357491434 100644
--- a/drivers/net/wireless/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/iwlwifi/mvm/utils.c
@@ -453,6 +453,29 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm)
453 IWL_ERR(mvm, "0x%08X | flow_handler\n", table.flow_handler); 453 IWL_ERR(mvm, "0x%08X | flow_handler\n", table.flow_handler);
454} 454}
455 455
456void iwl_mvm_dump_sram(struct iwl_mvm *mvm)
457{
458 const struct fw_img *img;
459 int ofs, len = 0;
460 u8 *buf;
461
462 if (!mvm->ucode_loaded)
463 return;
464
465 img = &mvm->fw->img[mvm->cur_ucode];
466 ofs = img->sec[IWL_UCODE_SECTION_DATA].offset;
467 len = img->sec[IWL_UCODE_SECTION_DATA].len;
468
469 buf = kzalloc(len, GFP_KERNEL);
470 if (!buf)
471 return;
472
473 iwl_trans_read_mem_bytes(mvm->trans, ofs, buf, len);
474 iwl_print_hex_error(mvm->trans, buf, len);
475
476 kfree(buf);
477}
478
456/** 479/**
457 * iwl_mvm_send_lq_cmd() - Send link quality command 480 * iwl_mvm_send_lq_cmd() - Send link quality command
458 * @init: This command is sent as part of station initialization right 481 * @init: This command is sent as part of station initialization right