forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-02-19 1c055e55a242a33e574e48be530e06770a210dcd
kernel/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
....@@ -5,10 +5,9 @@
55 *
66 * GPL LICENSE SUMMARY
77 *
8
- * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
98 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
109 * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
11
- * Copyright(c) 2018 Intel Corporation
10
+ * Copyright(c) 2012 - 2014, 2018 - 2020 Intel Corporation
1211 *
1312 * This program is free software; you can redistribute it and/or modify
1413 * it under the terms of version 2 of the GNU General Public License as
....@@ -19,11 +18,6 @@
1918 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2019 * General Public License for more details.
2120 *
22
- * You should have received a copy of the GNU General Public License
23
- * along with this program; if not, write to the Free Software
24
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
25
- * USA
26
- *
2721 * The full GNU General Public License is included in this distribution
2822 * in the file called COPYING.
2923 *
....@@ -33,10 +27,9 @@
3327 *
3428 * BSD LICENSE
3529 *
36
- * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
3730 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
3831 * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
39
- * Copyright(c) 2018 Intel Corporation
32
+ * Copyright(c) 2012 - 2014, 2018 - 2020 Intel Corporation
4033 * All rights reserved.
4134 *
4235 * Redistribution and use in source and binary forms, with or without
....@@ -77,6 +70,7 @@
7770 #include "iwl-io.h" /* for iwl_mvm_rx_card_state_notif */
7871 #include "iwl-prph.h"
7972 #include "fw/acpi.h"
73
+#include "fw/pnvm.h"
8074
8175 #include "mvm.h"
8276 #include "fw/dbg.h"
....@@ -84,8 +78,8 @@
8478 #include "iwl-modparams.h"
8579 #include "iwl-nvm-parse.h"
8680
87
-#define MVM_UCODE_ALIVE_TIMEOUT HZ
88
-#define MVM_UCODE_CALIB_TIMEOUT (2*HZ)
81
+#define MVM_UCODE_ALIVE_TIMEOUT (HZ)
82
+#define MVM_UCODE_CALIB_TIMEOUT (2 * HZ)
8983
9084 #define UCODE_VALID_OK cpu_to_le32(0x1)
9185
....@@ -139,7 +133,14 @@
139133 .dataflags[0] = IWL_HCMD_DFL_NOCOPY,
140134 };
141135
142
- /* Do not configure default queue, it is configured via context info */
136
+ /*
137
+ * The default queue is configured via context info, so if we
138
+ * have a single queue, there's nothing to do here.
139
+ */
140
+ if (mvm->trans->num_rx_queues == 1)
141
+ return 0;
142
+
143
+ /* skip the default queue */
143144 num_queues = mvm->trans->num_rx_queues - 1;
144145
145146 size = struct_size(cmd, data, num_queues);
....@@ -217,51 +218,82 @@
217218 struct iwl_mvm *mvm =
218219 container_of(notif_wait, struct iwl_mvm, notif_wait);
219220 struct iwl_mvm_alive_data *alive_data = data;
220
- struct mvm_alive_resp_v3 *palive3;
221
- struct mvm_alive_resp *palive;
222221 struct iwl_umac_alive *umac;
223222 struct iwl_lmac_alive *lmac1;
224223 struct iwl_lmac_alive *lmac2 = NULL;
225224 u16 status;
226
- u32 umac_error_event_table;
225
+ u32 lmac_error_event_table, umac_error_table;
227226
228
- if (iwl_rx_packet_payload_len(pkt) == sizeof(*palive)) {
227
+ /*
228
+ * For v5 and above, we can check the version, for older
229
+ * versions we need to check the size.
230
+ */
231
+ if (iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
232
+ UCODE_ALIVE_NTFY, 0) == 5) {
233
+ struct iwl_alive_ntf_v5 *palive;
234
+
229235 palive = (void *)pkt->data;
230236 umac = &palive->umac_data;
231237 lmac1 = &palive->lmac_data[0];
232238 lmac2 = &palive->lmac_data[1];
233239 status = le16_to_cpu(palive->status);
234
- } else {
240
+
241
+ mvm->trans->sku_id[0] = le32_to_cpu(palive->sku_id.data[0]);
242
+ mvm->trans->sku_id[1] = le32_to_cpu(palive->sku_id.data[1]);
243
+ mvm->trans->sku_id[2] = le32_to_cpu(palive->sku_id.data[2]);
244
+
245
+ IWL_DEBUG_FW(mvm, "Got sku_id: 0x0%x 0x0%x 0x0%x\n",
246
+ mvm->trans->sku_id[0],
247
+ mvm->trans->sku_id[1],
248
+ mvm->trans->sku_id[2]);
249
+ } else if (iwl_rx_packet_payload_len(pkt) == sizeof(struct iwl_alive_ntf_v4)) {
250
+ struct iwl_alive_ntf_v4 *palive;
251
+
252
+ palive = (void *)pkt->data;
253
+ umac = &palive->umac_data;
254
+ lmac1 = &palive->lmac_data[0];
255
+ lmac2 = &palive->lmac_data[1];
256
+ status = le16_to_cpu(palive->status);
257
+ } else if (iwl_rx_packet_payload_len(pkt) ==
258
+ sizeof(struct iwl_alive_ntf_v3)) {
259
+ struct iwl_alive_ntf_v3 *palive3;
260
+
235261 palive3 = (void *)pkt->data;
236262 umac = &palive3->umac_data;
237263 lmac1 = &palive3->lmac_data;
238264 status = le16_to_cpu(palive3->status);
239
- }
240
-
241
- mvm->error_event_table[0] = le32_to_cpu(lmac1->error_event_table_ptr);
242
- if (lmac2)
243
- mvm->error_event_table[1] =
244
- le32_to_cpu(lmac2->error_event_table_ptr);
245
- mvm->log_event_table = le32_to_cpu(lmac1->log_event_table_ptr);
246
-
247
- umac_error_event_table = le32_to_cpu(umac->error_info_addr);
248
-
249
- if (!umac_error_event_table) {
250
- mvm->support_umac_log = false;
251
- } else if (umac_error_event_table >=
252
- mvm->trans->cfg->min_umac_error_event_table) {
253
- mvm->support_umac_log = true;
254
- mvm->umac_error_event_table = umac_error_event_table;
255265 } else {
256
- IWL_ERR(mvm,
257
- "Not valid error log pointer 0x%08X for %s uCode\n",
258
- mvm->umac_error_event_table,
259
- (mvm->fwrt.cur_fw_img == IWL_UCODE_INIT) ?
260
- "Init" : "RT");
261
- mvm->support_umac_log = false;
266
+ WARN(1, "unsupported alive notification (size %d)\n",
267
+ iwl_rx_packet_payload_len(pkt));
268
+ /* get timeout later */
269
+ return false;
262270 }
263271
264
- alive_data->scd_base_addr = le32_to_cpu(lmac1->scd_base_ptr);
272
+ lmac_error_event_table =
273
+ le32_to_cpu(lmac1->dbg_ptrs.error_event_table_ptr);
274
+ iwl_fw_lmac1_set_alive_err_table(mvm->trans, lmac_error_event_table);
275
+
276
+ if (lmac2)
277
+ mvm->trans->dbg.lmac_error_event_table[1] =
278
+ le32_to_cpu(lmac2->dbg_ptrs.error_event_table_ptr);
279
+
280
+ umac_error_table = le32_to_cpu(umac->dbg_ptrs.error_info_addr);
281
+
282
+ if (umac_error_table) {
283
+ if (umac_error_table >=
284
+ mvm->trans->cfg->min_umac_error_event_table) {
285
+ iwl_fw_umac_set_alive_err_table(mvm->trans,
286
+ umac_error_table);
287
+ } else {
288
+ IWL_ERR(mvm,
289
+ "Not valid error log pointer 0x%08X for %s uCode\n",
290
+ umac_error_table,
291
+ (mvm->fwrt.cur_fw_img == IWL_UCODE_INIT) ?
292
+ "Init" : "RT");
293
+ }
294
+ }
295
+
296
+ alive_data->scd_base_addr = le32_to_cpu(lmac1->dbg_ptrs.scd_base_ptr);
265297 alive_data->valid = status == IWL_ALIVE_STATUS_OK;
266298
267299 IWL_DEBUG_FW(mvm,
....@@ -275,6 +307,8 @@
275307 "UMAC version: Major - 0x%x, Minor - 0x%x\n",
276308 le32_to_cpu(umac->umac_major),
277309 le32_to_cpu(umac->umac_minor));
310
+
311
+ iwl_fwrt_update_fw_versions(&mvm->fwrt, lmac1, umac);
278312
279313 return true;
280314 }
....@@ -306,11 +340,13 @@
306340 enum iwl_ucode_type ucode_type)
307341 {
308342 struct iwl_notification_wait alive_wait;
309
- struct iwl_mvm_alive_data alive_data;
343
+ struct iwl_mvm_alive_data alive_data = {};
310344 const struct fw_img *fw;
311
- int ret, i;
345
+ int ret;
312346 enum iwl_ucode_type old_type = mvm->fwrt.cur_fw_img;
313
- static const u16 alive_cmd[] = { MVM_ALIVE };
347
+ static const u16 alive_cmd[] = { UCODE_ALIVE_NTFY };
348
+ bool run_in_rfkill =
349
+ ucode_type == IWL_UCODE_INIT || iwl_mvm_has_unified_ucode(mvm);
314350
315351 if (ucode_type == IWL_UCODE_REGULAR &&
316352 iwl_fw_dbg_conf_usniffer(mvm->fw, FW_DBG_START_FROM_ALIVE) &&
....@@ -328,7 +364,12 @@
328364 alive_cmd, ARRAY_SIZE(alive_cmd),
329365 iwl_alive_fn, &alive_data);
330366
331
- ret = iwl_trans_start_fw(mvm->trans, fw, ucode_type == IWL_UCODE_INIT);
367
+ /*
368
+ * We want to load the INIT firmware even in RFKILL
369
+ * For the unified firmware case, the ucode_type is not
370
+ * INIT, but we still need to run it.
371
+ */
372
+ ret = iwl_trans_start_fw(mvm->trans, fw, run_in_rfkill);
332373 if (ret) {
333374 iwl_fw_set_current_image(&mvm->fwrt, old_type);
334375 iwl_remove_notification(&mvm->notif_wait, &alive_wait);
....@@ -344,16 +385,35 @@
344385 if (ret) {
345386 struct iwl_trans *trans = mvm->trans;
346387
347
- if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000)
388
+ if (trans->trans_cfg->device_family >=
389
+ IWL_DEVICE_FAMILY_22000) {
348390 IWL_ERR(mvm,
349391 "SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n",
350
- iwl_read_prph(trans, UMAG_SB_CPU_1_STATUS),
351
- iwl_read_prph(trans, UMAG_SB_CPU_2_STATUS));
352
- else if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000)
392
+ iwl_read_umac_prph(trans, UMAG_SB_CPU_1_STATUS),
393
+ iwl_read_umac_prph(trans,
394
+ UMAG_SB_CPU_2_STATUS));
395
+ IWL_ERR(mvm, "UMAC PC: 0x%x\n",
396
+ iwl_read_umac_prph(trans,
397
+ UREG_UMAC_CURRENT_PC));
398
+ IWL_ERR(mvm, "LMAC PC: 0x%x\n",
399
+ iwl_read_umac_prph(trans,
400
+ UREG_LMAC1_CURRENT_PC));
401
+ if (iwl_mvm_is_cdb_supported(mvm))
402
+ IWL_ERR(mvm, "LMAC2 PC: 0x%x\n",
403
+ iwl_read_umac_prph(trans,
404
+ UREG_LMAC2_CURRENT_PC));
405
+ } else if (trans->trans_cfg->device_family >=
406
+ IWL_DEVICE_FAMILY_8000) {
353407 IWL_ERR(mvm,
354408 "SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n",
355409 iwl_read_prph(trans, SB_CPU_1_STATUS),
356410 iwl_read_prph(trans, SB_CPU_2_STATUS));
411
+ }
412
+
413
+ if (ret == -ETIMEDOUT)
414
+ iwl_fw_dbg_error_collect(&mvm->fwrt,
415
+ FW_DBG_TRIGGER_ALIVE_TIMEOUT);
416
+
357417 iwl_fw_set_current_image(&mvm->fwrt, old_type);
358418 return ret;
359419 }
....@@ -362,6 +422,13 @@
362422 IWL_ERR(mvm, "Loaded ucode is not valid!\n");
363423 iwl_fw_set_current_image(&mvm->fwrt, old_type);
364424 return -EIO;
425
+ }
426
+
427
+ ret = iwl_pnvm_load(mvm->trans, &mvm->notif_wait);
428
+ if (ret) {
429
+ IWL_ERR(mvm, "Timeout waiting for PNVM load!\n");
430
+ iwl_fw_set_current_image(&mvm->fwrt, old_type);
431
+ return ret;
365432 }
366433
367434 iwl_trans_fw_alive(mvm->trans, alive_data.scd_base_addr);
....@@ -376,12 +443,19 @@
376443 */
377444
378445 memset(&mvm->queue_info, 0, sizeof(mvm->queue_info));
379
- mvm->queue_info[IWL_MVM_DQA_CMD_QUEUE].hw_queue_refcount = 1;
380
-
381
- for (i = 0; i < IEEE80211_MAX_QUEUES; i++)
382
- atomic_set(&mvm->mac80211_queue_stop_count[i], 0);
446
+ /*
447
+ * Set a 'fake' TID for the command queue, since we use the
448
+ * hweight() of the tid_bitmap as a refcount now. Not that
449
+ * we ever even consider the command queue as one we might
450
+ * want to reuse, but be safe nevertheless.
451
+ */
452
+ mvm->queue_info[IWL_MVM_DQA_CMD_QUEUE].tid_bitmap =
453
+ BIT(IWL_MAX_TID_COUNT + 2);
383454
384455 set_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status);
456
+#ifdef CONFIG_IWLWIFI_DEBUGFS
457
+ iwl_fw_set_dbg_rec_on(&mvm->fwrt);
458
+#endif
385459
386460 return 0;
387461 }
....@@ -398,7 +472,12 @@
398472 };
399473 int ret;
400474
475
+ if (mvm->trans->cfg->tx_with_siso_diversity)
476
+ init_cfg.init_flags |= cpu_to_le32(BIT(IWL_INIT_PHY));
477
+
401478 lockdep_assert_held(&mvm->mutex);
479
+
480
+ mvm->rfkill_safe_init_done = false;
402481
403482 iwl_init_notification_wait(&mvm->notif_wait,
404483 &init_wait,
....@@ -407,18 +486,23 @@
407486 iwl_wait_init_complete,
408487 NULL);
409488
489
+ iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_POINT_EARLY, NULL);
490
+
410491 /* Will also start the device */
411492 ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_REGULAR);
412493 if (ret) {
413494 IWL_ERR(mvm, "Failed to start RT ucode: %d\n", ret);
414495 goto error;
415496 }
497
+ iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_POINT_AFTER_ALIVE,
498
+ NULL);
416499
417500 /* Send init config command to mark that we are sending NVM access
418501 * commands
419502 */
420503 ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(SYSTEM_GROUP,
421
- INIT_EXTENDED_CFG_CMD), 0,
504
+ INIT_EXTENDED_CFG_CMD),
505
+ CMD_SEND_IN_RFKILL,
422506 sizeof(init_cfg), &init_cfg);
423507 if (ret) {
424508 IWL_ERR(mvm, "Failed to run init config command: %d\n",
....@@ -442,7 +526,8 @@
442526 }
443527
444528 ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(REGULATORY_AND_NVM_GROUP,
445
- NVM_ACCESS_COMPLETE), 0,
529
+ NVM_ACCESS_COMPLETE),
530
+ CMD_SEND_IN_RFKILL,
446531 sizeof(nvm_complete), &nvm_complete);
447532 if (ret) {
448533 IWL_ERR(mvm, "Failed to run complete NVM access: %d\n",
....@@ -467,6 +552,8 @@
467552 }
468553 }
469554
555
+ mvm->rfkill_safe_init_done = true;
556
+
470557 return 0;
471558
472559 error:
....@@ -474,27 +561,90 @@
474561 return ret;
475562 }
476563
564
+#ifdef CONFIG_ACPI
565
+static void iwl_mvm_phy_filter_init(struct iwl_mvm *mvm,
566
+ struct iwl_phy_specific_cfg *phy_filters)
567
+{
568
+ /*
569
+ * TODO: read specific phy config from BIOS
570
+ * ACPI table for this feature has not been defined yet,
571
+ * so for now we use hardcoded values.
572
+ */
573
+
574
+ if (IWL_MVM_PHY_FILTER_CHAIN_A) {
575
+ phy_filters->filter_cfg_chain_a =
576
+ cpu_to_le32(IWL_MVM_PHY_FILTER_CHAIN_A);
577
+ }
578
+ if (IWL_MVM_PHY_FILTER_CHAIN_B) {
579
+ phy_filters->filter_cfg_chain_b =
580
+ cpu_to_le32(IWL_MVM_PHY_FILTER_CHAIN_B);
581
+ }
582
+ if (IWL_MVM_PHY_FILTER_CHAIN_C) {
583
+ phy_filters->filter_cfg_chain_c =
584
+ cpu_to_le32(IWL_MVM_PHY_FILTER_CHAIN_C);
585
+ }
586
+ if (IWL_MVM_PHY_FILTER_CHAIN_D) {
587
+ phy_filters->filter_cfg_chain_d =
588
+ cpu_to_le32(IWL_MVM_PHY_FILTER_CHAIN_D);
589
+ }
590
+}
591
+
592
+#else /* CONFIG_ACPI */
593
+
594
+static void iwl_mvm_phy_filter_init(struct iwl_mvm *mvm,
595
+ struct iwl_phy_specific_cfg *phy_filters)
596
+{
597
+}
598
+#endif /* CONFIG_ACPI */
599
+
477600 static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
478601 {
479
- struct iwl_phy_cfg_cmd phy_cfg_cmd;
602
+ struct iwl_phy_cfg_cmd_v3 phy_cfg_cmd;
480603 enum iwl_ucode_type ucode_type = mvm->fwrt.cur_fw_img;
604
+ struct iwl_phy_specific_cfg phy_filters = {};
605
+ u8 cmd_ver;
606
+ size_t cmd_size;
607
+
608
+ if (iwl_mvm_has_unified_ucode(mvm) &&
609
+ !mvm->trans->cfg->tx_with_siso_diversity)
610
+ return 0;
611
+
612
+ if (mvm->trans->cfg->tx_with_siso_diversity) {
613
+ /*
614
+ * TODO: currently we don't set the antenna but letting the NIC
615
+ * to decide which antenna to use. This should come from BIOS.
616
+ */
617
+ phy_cfg_cmd.phy_cfg =
618
+ cpu_to_le32(FW_PHY_CFG_CHAIN_SAD_ENABLED);
619
+ }
481620
482621 /* Set parameters */
483622 phy_cfg_cmd.phy_cfg = cpu_to_le32(iwl_mvm_get_phy_config(mvm));
484623
485624 /* set flags extra PHY configuration flags from the device's cfg */
486
- phy_cfg_cmd.phy_cfg |= cpu_to_le32(mvm->cfg->extra_phy_cfg_flags);
625
+ phy_cfg_cmd.phy_cfg |=
626
+ cpu_to_le32(mvm->trans->trans_cfg->extra_phy_cfg_flags);
487627
488628 phy_cfg_cmd.calib_control.event_trigger =
489629 mvm->fw->default_calib[ucode_type].event_trigger;
490630 phy_cfg_cmd.calib_control.flow_trigger =
491631 mvm->fw->default_calib[ucode_type].flow_trigger;
492632
633
+ cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, IWL_ALWAYS_LONG_GROUP,
634
+ PHY_CONFIGURATION_CMD,
635
+ IWL_FW_CMD_VER_UNKNOWN);
636
+ if (cmd_ver == 3) {
637
+ iwl_mvm_phy_filter_init(mvm, &phy_filters);
638
+ memcpy(&phy_cfg_cmd.phy_specific_cfg, &phy_filters,
639
+ sizeof(struct iwl_phy_specific_cfg));
640
+ }
641
+
493642 IWL_DEBUG_INFO(mvm, "Sending Phy CFG command: 0x%x\n",
494643 phy_cfg_cmd.phy_cfg);
495
-
644
+ cmd_size = (cmd_ver == 3) ? sizeof(struct iwl_phy_cfg_cmd_v3) :
645
+ sizeof(struct iwl_phy_cfg_cmd_v1);
496646 return iwl_mvm_send_cmd_pdu(mvm, PHY_CONFIGURATION_CMD, 0,
497
- sizeof(phy_cfg_cmd), &phy_cfg_cmd);
647
+ cmd_size, &phy_cfg_cmd);
498648 }
499649
500650 int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
....@@ -511,8 +661,7 @@
511661
512662 lockdep_assert_held(&mvm->mutex);
513663
514
- if (WARN_ON_ONCE(mvm->calibrating))
515
- return 0;
664
+ mvm->rfkill_safe_init_done = false;
516665
517666 iwl_init_notification_wait(&mvm->notif_wait,
518667 &calib_wait,
....@@ -528,7 +677,7 @@
528677 goto remove_notif;
529678 }
530679
531
- if (mvm->cfg->device_family < IWL_DEVICE_FAMILY_8000) {
680
+ if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_8000) {
532681 ret = iwl_mvm_send_bt_init_conf(mvm);
533682 if (ret)
534683 goto remove_notif;
....@@ -561,7 +710,7 @@
561710 goto remove_notif;
562711 }
563712
564
- mvm->calibrating = true;
713
+ mvm->rfkill_safe_init_done = true;
565714
566715 /* Send TX valid antennas before triggering calibrations */
567716 ret = iwl_send_tx_ant_cfg(mvm, iwl_mvm_get_valid_tx_ant(mvm));
....@@ -597,7 +746,7 @@
597746 remove_notif:
598747 iwl_remove_notification(&mvm->notif_wait, &calib_wait);
599748 out:
600
- mvm->calibrating = false;
749
+ mvm->rfkill_safe_init_done = false;
601750 if (iwlmvm_mod_params.init_dbg && !mvm->nvm_data) {
602751 /* we want to debug INIT and we have no NVM - fake */
603752 mvm->nvm_data = kzalloc(sizeof(struct iwl_nvm_data) +
....@@ -631,250 +780,85 @@
631780 }
632781
633782 #ifdef CONFIG_ACPI
634
-static int iwl_mvm_sar_set_profile(struct iwl_mvm *mvm,
635
- union acpi_object *table,
636
- struct iwl_mvm_sar_profile *profile,
637
- bool enabled)
638
-{
639
- int i;
640
-
641
- profile->enabled = enabled;
642
-
643
- for (i = 0; i < ACPI_SAR_TABLE_SIZE; i++) {
644
- if ((table[i].type != ACPI_TYPE_INTEGER) ||
645
- (table[i].integer.value > U8_MAX))
646
- return -EINVAL;
647
-
648
- profile->table[i] = table[i].integer.value;
649
- }
650
-
651
- return 0;
652
-}
653
-
654
-static int iwl_mvm_sar_get_wrds_table(struct iwl_mvm *mvm)
655
-{
656
- union acpi_object *wifi_pkg, *table, *data;
657
- bool enabled;
658
- int ret;
659
-
660
- data = iwl_acpi_get_object(mvm->dev, ACPI_WRDS_METHOD);
661
- if (IS_ERR(data))
662
- return PTR_ERR(data);
663
-
664
- wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data,
665
- ACPI_WRDS_WIFI_DATA_SIZE);
666
- if (IS_ERR(wifi_pkg)) {
667
- ret = PTR_ERR(wifi_pkg);
668
- goto out_free;
669
- }
670
-
671
- if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER) {
672
- ret = -EINVAL;
673
- goto out_free;
674
- }
675
-
676
- enabled = !!(wifi_pkg->package.elements[1].integer.value);
677
-
678
- /* position of the actual table */
679
- table = &wifi_pkg->package.elements[2];
680
-
681
- /* The profile from WRDS is officially profile 1, but goes
682
- * into sar_profiles[0] (because we don't have a profile 0).
683
- */
684
- ret = iwl_mvm_sar_set_profile(mvm, table, &mvm->sar_profiles[0],
685
- enabled);
686
-out_free:
687
- kfree(data);
688
- return ret;
689
-}
690
-
691
-static int iwl_mvm_sar_get_ewrd_table(struct iwl_mvm *mvm)
692
-{
693
- union acpi_object *wifi_pkg, *data;
694
- bool enabled;
695
- int i, n_profiles, ret;
696
-
697
- data = iwl_acpi_get_object(mvm->dev, ACPI_EWRD_METHOD);
698
- if (IS_ERR(data))
699
- return PTR_ERR(data);
700
-
701
- wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data,
702
- ACPI_EWRD_WIFI_DATA_SIZE);
703
- if (IS_ERR(wifi_pkg)) {
704
- ret = PTR_ERR(wifi_pkg);
705
- goto out_free;
706
- }
707
-
708
- if ((wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER) ||
709
- (wifi_pkg->package.elements[2].type != ACPI_TYPE_INTEGER)) {
710
- ret = -EINVAL;
711
- goto out_free;
712
- }
713
-
714
- enabled = !!(wifi_pkg->package.elements[1].integer.value);
715
- n_profiles = wifi_pkg->package.elements[2].integer.value;
716
-
717
- /*
718
- * Check the validity of n_profiles. The EWRD profiles start
719
- * from index 1, so the maximum value allowed here is
720
- * ACPI_SAR_PROFILES_NUM - 1.
721
- */
722
- if (n_profiles <= 0 || n_profiles >= ACPI_SAR_PROFILE_NUM) {
723
- ret = -EINVAL;
724
- goto out_free;
725
- }
726
-
727
- for (i = 0; i < n_profiles; i++) {
728
- /* the tables start at element 3 */
729
- int pos = 3;
730
-
731
- /* The EWRD profiles officially go from 2 to 4, but we
732
- * save them in sar_profiles[1-3] (because we don't
733
- * have profile 0). So in the array we start from 1.
734
- */
735
- ret = iwl_mvm_sar_set_profile(mvm,
736
- &wifi_pkg->package.elements[pos],
737
- &mvm->sar_profiles[i + 1],
738
- enabled);
739
- if (ret < 0)
740
- break;
741
-
742
- /* go to the next table */
743
- pos += ACPI_SAR_TABLE_SIZE;
744
- }
745
-
746
-out_free:
747
- kfree(data);
748
- return ret;
749
-}
750
-
751
-static int iwl_mvm_sar_get_wgds_table(struct iwl_mvm *mvm)
752
-{
753
- union acpi_object *wifi_pkg, *data;
754
- int i, j, ret;
755
- int idx = 1;
756
-
757
- data = iwl_acpi_get_object(mvm->dev, ACPI_WGDS_METHOD);
758
- if (IS_ERR(data))
759
- return PTR_ERR(data);
760
-
761
- wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data,
762
- ACPI_WGDS_WIFI_DATA_SIZE);
763
- if (IS_ERR(wifi_pkg)) {
764
- ret = PTR_ERR(wifi_pkg);
765
- goto out_free;
766
- }
767
-
768
- for (i = 0; i < ACPI_NUM_GEO_PROFILES; i++) {
769
- for (j = 0; j < ACPI_GEO_TABLE_SIZE; j++) {
770
- union acpi_object *entry;
771
-
772
- entry = &wifi_pkg->package.elements[idx++];
773
- if ((entry->type != ACPI_TYPE_INTEGER) ||
774
- (entry->integer.value > U8_MAX)) {
775
- ret = -EINVAL;
776
- goto out_free;
777
- }
778
-
779
- mvm->geo_profiles[i].values[j] = entry->integer.value;
780
- }
781
- }
782
- ret = 0;
783
-out_free:
784
- kfree(data);
785
- return ret;
786
-}
787
-
788783 int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
789784 {
790785 struct iwl_dev_tx_power_cmd cmd = {
791
- .v3.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_CHAINS),
786
+ .common.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_CHAINS),
792787 };
793
- int i, j, idx;
794
- int profs[ACPI_SAR_NUM_CHAIN_LIMITS] = { prof_a, prof_b };
795
- int len = sizeof(cmd);
788
+ __le16 *per_chain;
789
+ int ret;
790
+ u16 len = 0;
791
+ u32 n_subbands;
792
+ u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, LONG_GROUP,
793
+ REDUCE_TX_POWER_CMD,
794
+ IWL_FW_CMD_VER_UNKNOWN);
796795
797
- BUILD_BUG_ON(ACPI_SAR_NUM_CHAIN_LIMITS < 2);
798
- BUILD_BUG_ON(ACPI_SAR_NUM_CHAIN_LIMITS * ACPI_SAR_NUM_SUB_BANDS !=
799
- ACPI_SAR_TABLE_SIZE);
800
-
801
- if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TX_POWER_ACK))
796
+ if (cmd_ver == 6) {
797
+ len = sizeof(cmd.v6);
798
+ n_subbands = IWL_NUM_SUB_BANDS_V2;
799
+ per_chain = cmd.v6.per_chain[0][0];
800
+ } else if (fw_has_api(&mvm->fw->ucode_capa,
801
+ IWL_UCODE_TLV_API_REDUCE_TX_POWER)) {
802
+ len = sizeof(cmd.v5);
803
+ n_subbands = IWL_NUM_SUB_BANDS;
804
+ per_chain = cmd.v5.per_chain[0][0];
805
+ } else if (fw_has_capa(&mvm->fw->ucode_capa,
806
+ IWL_UCODE_TLV_CAPA_TX_POWER_ACK)) {
807
+ len = sizeof(cmd.v4);
808
+ n_subbands = IWL_NUM_SUB_BANDS;
809
+ per_chain = cmd.v4.per_chain[0][0];
810
+ } else {
802811 len = sizeof(cmd.v3);
803
-
804
- for (i = 0; i < ACPI_SAR_NUM_CHAIN_LIMITS; i++) {
805
- struct iwl_mvm_sar_profile *prof;
806
-
807
- /* don't allow SAR to be disabled (profile 0 means disable) */
808
- if (profs[i] == 0)
809
- return -EPERM;
810
-
811
- /* we are off by one, so allow up to ACPI_SAR_PROFILE_NUM */
812
- if (profs[i] > ACPI_SAR_PROFILE_NUM)
813
- return -EINVAL;
814
-
815
- /* profiles go from 1 to 4, so decrement to access the array */
816
- prof = &mvm->sar_profiles[profs[i] - 1];
817
-
818
- /* if the profile is disabled, do nothing */
819
- if (!prof->enabled) {
820
- IWL_DEBUG_RADIO(mvm, "SAR profile %d is disabled.\n",
821
- profs[i]);
822
- /* if one of the profiles is disabled, we fail all */
823
- return -ENOENT;
824
- }
825
-
826
- IWL_DEBUG_RADIO(mvm, " Chain[%d]:\n", i);
827
- for (j = 0; j < ACPI_SAR_NUM_SUB_BANDS; j++) {
828
- idx = (i * ACPI_SAR_NUM_SUB_BANDS) + j;
829
- cmd.v3.per_chain_restriction[i][j] =
830
- cpu_to_le16(prof->table[idx]);
831
- IWL_DEBUG_RADIO(mvm, " Band[%d] = %d * .125dBm\n",
832
- j, prof->table[idx]);
833
- }
812
+ n_subbands = IWL_NUM_SUB_BANDS;
813
+ per_chain = cmd.v3.per_chain[0][0];
834814 }
835815
816
+ /* all structs have the same common part, add it */
817
+ len += sizeof(cmd.common);
818
+
819
+ ret = iwl_sar_select_profile(&mvm->fwrt, per_chain, ACPI_SAR_NUM_TABLES,
820
+ n_subbands, prof_a, prof_b);
821
+
822
+ /* return on error or if the profile is disabled (positive number) */
823
+ if (ret)
824
+ return ret;
825
+
836826 IWL_DEBUG_RADIO(mvm, "Sending REDUCE_TX_POWER_CMD per chain\n");
837
-
838827 return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, 0, len, &cmd);
839
-}
840
-
841
-static bool iwl_mvm_sar_geo_support(struct iwl_mvm *mvm)
842
-{
843
- /*
844
- * The GEO_TX_POWER_LIMIT command is not supported on earlier
845
- * firmware versions. Unfortunately, we don't have a TLV API
846
- * flag to rely on, so rely on the major version which is in
847
- * the first byte of ucode_ver. This was implemented
848
- * initially on version 38 and then backported to 17. It was
849
- * also backported to 29, but only for 7265D devices. The
850
- * intention was to have it in 36 as well, but not all 8000
851
- * family got this feature enabled. The 8000 family is the
852
- * only one using version 36, so skip this version entirely.
853
- */
854
- return IWL_UCODE_SERIAL(mvm->fw->ucode_ver) >= 38 ||
855
- IWL_UCODE_SERIAL(mvm->fw->ucode_ver) == 17 ||
856
- (IWL_UCODE_SERIAL(mvm->fw->ucode_ver) == 29 &&
857
- ((mvm->trans->hw_rev & CSR_HW_REV_TYPE_MSK) ==
858
- CSR_HW_REV_TYPE_7265D));
859828 }
860829
861830 int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
862831 {
832
+ union iwl_geo_tx_power_profiles_cmd geo_tx_cmd;
863833 struct iwl_geo_tx_power_profiles_resp *resp;
834
+ u16 len;
864835 int ret;
836
+ struct iwl_host_cmd cmd;
837
+ u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, PHY_OPS_GROUP,
838
+ GEO_TX_POWER_LIMIT,
839
+ IWL_FW_CMD_VER_UNKNOWN);
865840
866
- struct iwl_geo_tx_power_profiles_cmd geo_cmd = {
867
- .ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_GET_CURRENT_TABLE),
868
- };
869
- struct iwl_host_cmd cmd = {
870
- .id = WIDE_ID(PHY_OPS_GROUP, GEO_TX_POWER_LIMIT),
871
- .len = { sizeof(geo_cmd), },
872
- .flags = CMD_WANT_SKB,
873
- .data = { &geo_cmd },
874
- };
841
+ /* the ops field is at the same spot for all versions, so set in v1 */
842
+ geo_tx_cmd.v1.ops =
843
+ cpu_to_le32(IWL_PER_CHAIN_OFFSET_GET_CURRENT_TABLE);
875844
876
- if (!iwl_mvm_sar_geo_support(mvm))
845
+ if (cmd_ver == 3)
846
+ len = sizeof(geo_tx_cmd.v3);
847
+ else if (fw_has_api(&mvm->fwrt.fw->ucode_capa,
848
+ IWL_UCODE_TLV_API_SAR_TABLE_VER))
849
+ len = sizeof(geo_tx_cmd.v2);
850
+ else
851
+ len = sizeof(geo_tx_cmd.v1);
852
+
853
+ if (!iwl_sar_geo_support(&mvm->fwrt))
877854 return -EOPNOTSUPP;
855
+
856
+ cmd = (struct iwl_host_cmd){
857
+ .id = WIDE_ID(PHY_OPS_GROUP, GEO_TX_POWER_LIMIT),
858
+ .len = { len, },
859
+ .flags = CMD_WANT_SKB,
860
+ .data = { &geo_tx_cmd },
861
+ };
878862
879863 ret = iwl_mvm_send_cmd(mvm, &cmd);
880864 if (ret) {
....@@ -884,10 +868,9 @@
884868
885869 resp = (void *)cmd.resp_pkt->data;
886870 ret = le32_to_cpu(resp->profile_idx);
887
- if (WARN_ON(ret > ACPI_NUM_GEO_PROFILES)) {
871
+
872
+ if (WARN_ON(ret > ACPI_NUM_GEO_PROFILES))
888873 ret = -EIO;
889
- IWL_WARN(mvm, "Invalid geographic profile idx (%d)\n", ret);
890
- }
891874
892875 iwl_free_resp(&cmd);
893876 return ret;
....@@ -895,63 +878,361 @@
895878
896879 static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
897880 {
898
- struct iwl_geo_tx_power_profiles_cmd cmd = {
899
- .ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_SET_TABLES),
900
- };
901
- int ret, i, j;
902
- u16 cmd_wide_id = WIDE_ID(PHY_OPS_GROUP, GEO_TX_POWER_LIMIT);
881
+ union iwl_geo_tx_power_profiles_cmd cmd;
882
+ u16 len;
883
+ u32 n_bands;
884
+ int ret;
885
+ u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, PHY_OPS_GROUP,
886
+ GEO_TX_POWER_LIMIT,
887
+ IWL_FW_CMD_VER_UNKNOWN);
903888
904
- if (!iwl_mvm_sar_geo_support(mvm))
905
- return 0;
889
+ BUILD_BUG_ON(offsetof(struct iwl_geo_tx_power_profiles_cmd_v1, ops) !=
890
+ offsetof(struct iwl_geo_tx_power_profiles_cmd_v2, ops) ||
891
+ offsetof(struct iwl_geo_tx_power_profiles_cmd_v2, ops) !=
892
+ offsetof(struct iwl_geo_tx_power_profiles_cmd_v3, ops));
893
+ /* the ops field is at the same spot for all versions, so set in v1 */
894
+ cmd.v1.ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_SET_TABLES);
906895
907
- ret = iwl_mvm_sar_get_wgds_table(mvm);
908
- if (ret < 0) {
909
- IWL_DEBUG_RADIO(mvm,
910
- "Geo SAR BIOS table invalid or unavailable. (%d)\n",
911
- ret);
912
- /* we don't fail if the table is not available */
913
- return 0;
896
+ if (cmd_ver == 3) {
897
+ len = sizeof(cmd.v3);
898
+ n_bands = ARRAY_SIZE(cmd.v3.table[0]);
899
+ } else if (fw_has_api(&mvm->fwrt.fw->ucode_capa,
900
+ IWL_UCODE_TLV_API_SAR_TABLE_VER)) {
901
+ len = sizeof(cmd.v2);
902
+ n_bands = ARRAY_SIZE(cmd.v2.table[0]);
903
+ } else {
904
+ len = sizeof(cmd.v1);
905
+ n_bands = ARRAY_SIZE(cmd.v1.table[0]);
914906 }
915907
916
- IWL_DEBUG_RADIO(mvm, "Sending GEO_TX_POWER_LIMIT\n");
908
+ BUILD_BUG_ON(offsetof(struct iwl_geo_tx_power_profiles_cmd_v1, table) !=
909
+ offsetof(struct iwl_geo_tx_power_profiles_cmd_v2, table) ||
910
+ offsetof(struct iwl_geo_tx_power_profiles_cmd_v2, table) !=
911
+ offsetof(struct iwl_geo_tx_power_profiles_cmd_v3, table));
912
+ /* the table is at the same position for all versions, so set use v1 */
913
+ ret = iwl_sar_geo_init(&mvm->fwrt, &cmd.v1.table[0][0], n_bands);
917914
918
- BUILD_BUG_ON(ACPI_NUM_GEO_PROFILES * ACPI_WGDS_NUM_BANDS *
919
- ACPI_WGDS_TABLE_SIZE + 1 != ACPI_WGDS_WIFI_DATA_SIZE);
915
+ /*
916
+ * It is a valid scenario to not support SAR, or miss wgds table,
917
+ * but in that case there is no need to send the command.
918
+ */
919
+ if (ret)
920
+ return 0;
920921
921
- BUILD_BUG_ON(ACPI_NUM_GEO_PROFILES > IWL_NUM_GEO_PROFILES);
922
+ /*
923
+ * Set the revision on versions that contain it.
924
+ * This must be done after calling iwl_sar_geo_init().
925
+ */
926
+ if (cmd_ver == 3)
927
+ cmd.v3.table_revision = cpu_to_le32(mvm->fwrt.geo_rev);
928
+ else if (fw_has_api(&mvm->fwrt.fw->ucode_capa,
929
+ IWL_UCODE_TLV_API_SAR_TABLE_VER))
930
+ cmd.v2.table_revision = cpu_to_le32(mvm->fwrt.geo_rev);
922931
923
- for (i = 0; i < ACPI_NUM_GEO_PROFILES; i++) {
924
- struct iwl_per_chain_offset *chain =
925
- (struct iwl_per_chain_offset *)&cmd.table[i];
932
+ return iwl_mvm_send_cmd_pdu(mvm,
933
+ WIDE_ID(PHY_OPS_GROUP, GEO_TX_POWER_LIMIT),
934
+ 0, len, &cmd);
935
+}
926936
927
- for (j = 0; j < ACPI_WGDS_NUM_BANDS; j++) {
928
- u8 *value;
937
+static int iwl_mvm_get_ppag_table(struct iwl_mvm *mvm)
938
+{
939
+ union acpi_object *wifi_pkg, *data, *enabled;
940
+ int i, j, ret, tbl_rev, num_sub_bands;
941
+ int idx = 2;
942
+ s8 *gain;
929943
930
- value = &mvm->geo_profiles[i].values[j *
931
- ACPI_GEO_PER_CHAIN_SIZE];
932
- chain[j].max_tx_power = cpu_to_le16(value[0]);
933
- chain[j].chain_a = value[1];
934
- chain[j].chain_b = value[2];
935
- IWL_DEBUG_RADIO(mvm,
936
- "SAR geographic profile[%d] Band[%d]: chain A = %d chain B = %d max_tx_power = %d\n",
937
- i, j, value[1], value[2], value[0]);
944
+ /*
945
+ * The 'enabled' field is the same in v1 and v2 so we can just
946
+ * use v1 to access it.
947
+ */
948
+ mvm->fwrt.ppag_table.v1.enabled = cpu_to_le32(0);
949
+ data = iwl_acpi_get_object(mvm->dev, ACPI_PPAG_METHOD);
950
+ if (IS_ERR(data))
951
+ return PTR_ERR(data);
952
+
953
+ /* try to read ppag table revision 1 */
954
+ wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data,
955
+ ACPI_PPAG_WIFI_DATA_SIZE_V2, &tbl_rev);
956
+ if (!IS_ERR(wifi_pkg)) {
957
+ if (tbl_rev != 1) {
958
+ ret = -EINVAL;
959
+ goto out_free;
960
+ }
961
+ num_sub_bands = IWL_NUM_SUB_BANDS_V2;
962
+ gain = mvm->fwrt.ppag_table.v2.gain[0];
963
+ mvm->fwrt.ppag_ver = 2;
964
+ IWL_DEBUG_RADIO(mvm, "Reading PPAG table v2 (tbl_rev=1)\n");
965
+ goto read_table;
966
+ }
967
+
968
+ /* try to read ppag table revision 0 */
969
+ wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data,
970
+ ACPI_PPAG_WIFI_DATA_SIZE, &tbl_rev);
971
+ if (!IS_ERR(wifi_pkg)) {
972
+ if (tbl_rev != 0) {
973
+ ret = -EINVAL;
974
+ goto out_free;
975
+ }
976
+ num_sub_bands = IWL_NUM_SUB_BANDS;
977
+ gain = mvm->fwrt.ppag_table.v1.gain[0];
978
+ mvm->fwrt.ppag_ver = 1;
979
+ IWL_DEBUG_RADIO(mvm, "Reading PPAG table v1 (tbl_rev=0)\n");
980
+ goto read_table;
981
+ }
982
+ ret = PTR_ERR(wifi_pkg);
983
+ goto out_free;
984
+
985
+read_table:
986
+ enabled = &wifi_pkg->package.elements[1];
987
+ if (enabled->type != ACPI_TYPE_INTEGER ||
988
+ (enabled->integer.value != 0 && enabled->integer.value != 1)) {
989
+ ret = -EINVAL;
990
+ goto out_free;
991
+ }
992
+
993
+ mvm->fwrt.ppag_table.v1.enabled = cpu_to_le32(enabled->integer.value);
994
+ if (!mvm->fwrt.ppag_table.v1.enabled) {
995
+ ret = 0;
996
+ goto out_free;
997
+ }
998
+
999
+ /*
1000
+ * read, verify gain values and save them into the PPAG table.
1001
+ * first sub-band (j=0) corresponds to Low-Band (2.4GHz), and the
1002
+ * following sub-bands to High-Band (5GHz).
1003
+ */
1004
+ for (i = 0; i < IWL_NUM_CHAIN_LIMITS; i++) {
1005
+ for (j = 0; j < num_sub_bands; j++) {
1006
+ union acpi_object *ent;
1007
+
1008
+ ent = &wifi_pkg->package.elements[idx++];
1009
+ if (ent->type != ACPI_TYPE_INTEGER) {
1010
+ ret = -EINVAL;
1011
+ goto out_free;
1012
+ }
1013
+
1014
+ gain[i * num_sub_bands + j] = ent->integer.value;
1015
+
1016
+ if ((j == 0 &&
1017
+ (gain[i * num_sub_bands + j] > ACPI_PPAG_MAX_LB ||
1018
+ gain[i * num_sub_bands + j] < ACPI_PPAG_MIN_LB)) ||
1019
+ (j != 0 &&
1020
+ (gain[i * num_sub_bands + j] > ACPI_PPAG_MAX_HB ||
1021
+ gain[i * num_sub_bands + j] < ACPI_PPAG_MIN_HB))) {
1022
+ mvm->fwrt.ppag_table.v1.enabled = cpu_to_le32(0);
1023
+ ret = -EINVAL;
1024
+ goto out_free;
1025
+ }
9381026 }
9391027 }
940
- return iwl_mvm_send_cmd_pdu(mvm, cmd_wide_id, 0, sizeof(cmd), &cmd);
1028
+ ret = 0;
1029
+out_free:
1030
+ kfree(data);
1031
+ return ret;
9411032 }
9421033
1034
+int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm)
1035
+{
1036
+ u8 cmd_ver;
1037
+ int i, j, ret, num_sub_bands, cmd_size;
1038
+ s8 *gain;
1039
+
1040
+ if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_SET_PPAG)) {
1041
+ IWL_DEBUG_RADIO(mvm,
1042
+ "PPAG capability not supported by FW, command not sent.\n");
1043
+ return 0;
1044
+ }
1045
+ if (!mvm->fwrt.ppag_table.v1.enabled) {
1046
+ IWL_DEBUG_RADIO(mvm, "PPAG not enabled, command not sent.\n");
1047
+ return 0;
1048
+ }
1049
+
1050
+ cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, PHY_OPS_GROUP,
1051
+ PER_PLATFORM_ANT_GAIN_CMD,
1052
+ IWL_FW_CMD_VER_UNKNOWN);
1053
+ if (cmd_ver == 1) {
1054
+ num_sub_bands = IWL_NUM_SUB_BANDS;
1055
+ gain = mvm->fwrt.ppag_table.v1.gain[0];
1056
+ cmd_size = sizeof(mvm->fwrt.ppag_table.v1);
1057
+ if (mvm->fwrt.ppag_ver == 2) {
1058
+ IWL_DEBUG_RADIO(mvm,
1059
+ "PPAG table is v2 but FW supports v1, sending truncated table\n");
1060
+ }
1061
+ } else if (cmd_ver == 2) {
1062
+ num_sub_bands = IWL_NUM_SUB_BANDS_V2;
1063
+ gain = mvm->fwrt.ppag_table.v2.gain[0];
1064
+ cmd_size = sizeof(mvm->fwrt.ppag_table.v2);
1065
+ if (mvm->fwrt.ppag_ver == 1) {
1066
+ IWL_DEBUG_RADIO(mvm,
1067
+ "PPAG table is v1 but FW supports v2, sending padded table\n");
1068
+ }
1069
+ } else {
1070
+ IWL_DEBUG_RADIO(mvm, "Unsupported PPAG command version\n");
1071
+ return 0;
1072
+ }
1073
+
1074
+ for (i = 0; i < IWL_NUM_CHAIN_LIMITS; i++) {
1075
+ for (j = 0; j < num_sub_bands; j++) {
1076
+ IWL_DEBUG_RADIO(mvm,
1077
+ "PPAG table: chain[%d] band[%d]: gain = %d\n",
1078
+ i, j, gain[i * num_sub_bands + j]);
1079
+ }
1080
+ }
1081
+ IWL_DEBUG_RADIO(mvm, "Sending PER_PLATFORM_ANT_GAIN_CMD\n");
1082
+ ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(PHY_OPS_GROUP,
1083
+ PER_PLATFORM_ANT_GAIN_CMD),
1084
+ 0, cmd_size, &mvm->fwrt.ppag_table);
1085
+ if (ret < 0)
1086
+ IWL_ERR(mvm, "failed to send PER_PLATFORM_ANT_GAIN_CMD (%d)\n",
1087
+ ret);
1088
+
1089
+ return ret;
1090
+}
1091
+
1092
+static int iwl_mvm_ppag_init(struct iwl_mvm *mvm)
1093
+{
1094
+ int ret;
1095
+
1096
+ ret = iwl_mvm_get_ppag_table(mvm);
1097
+ if (ret < 0) {
1098
+ IWL_DEBUG_RADIO(mvm,
1099
+ "PPAG BIOS table invalid or unavailable. (%d)\n",
1100
+ ret);
1101
+ return 0;
1102
+ }
1103
+ return iwl_mvm_ppag_send_cmd(mvm);
1104
+}
1105
+
1106
+static void iwl_mvm_tas_init(struct iwl_mvm *mvm)
1107
+{
1108
+ int ret;
1109
+ struct iwl_tas_config_cmd cmd = {};
1110
+ int list_size;
1111
+
1112
+ BUILD_BUG_ON(ARRAY_SIZE(cmd.block_list_array) <
1113
+ APCI_WTAS_BLACK_LIST_MAX);
1114
+
1115
+ if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TAS_CFG)) {
1116
+ IWL_DEBUG_RADIO(mvm, "TAS not enabled in FW\n");
1117
+ return;
1118
+ }
1119
+
1120
+ ret = iwl_acpi_get_tas(&mvm->fwrt, cmd.block_list_array, &list_size);
1121
+ if (ret < 0) {
1122
+ IWL_DEBUG_RADIO(mvm,
1123
+ "TAS table invalid or unavailable. (%d)\n",
1124
+ ret);
1125
+ return;
1126
+ }
1127
+
1128
+ if (list_size < 0)
1129
+ return;
1130
+
1131
+ /* list size if TAS enabled can only be non-negative */
1132
+ cmd.block_list_size = cpu_to_le32((u32)list_size);
1133
+
1134
+ ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(REGULATORY_AND_NVM_GROUP,
1135
+ TAS_CONFIG),
1136
+ 0, sizeof(cmd), &cmd);
1137
+ if (ret < 0)
1138
+ IWL_DEBUG_RADIO(mvm, "failed to send TAS_CONFIG (%d)\n", ret);
1139
+}
1140
+
1141
+static u8 iwl_mvm_eval_dsm_indonesia_5g2(struct iwl_mvm *mvm)
1142
+{
1143
+ int ret = iwl_acpi_get_dsm_u8((&mvm->fwrt)->dev, 0,
1144
+ DSM_FUNC_ENABLE_INDONESIA_5G2);
1145
+
1146
+ if (ret < 0)
1147
+ IWL_DEBUG_RADIO(mvm,
1148
+ "Failed to evaluate DSM function ENABLE_INDONESIA_5G2, ret=%d\n",
1149
+ ret);
1150
+
1151
+ else if (ret >= DSM_VALUE_INDONESIA_MAX)
1152
+ IWL_DEBUG_RADIO(mvm,
1153
+ "DSM function ENABLE_INDONESIA_5G2 return invalid value, ret=%d\n",
1154
+ ret);
1155
+
1156
+ else if (ret == DSM_VALUE_INDONESIA_ENABLE) {
1157
+ IWL_DEBUG_RADIO(mvm,
1158
+ "Evaluated DSM function ENABLE_INDONESIA_5G2: Enabling 5g2\n");
1159
+ return DSM_VALUE_INDONESIA_ENABLE;
1160
+ }
1161
+ /* default behaviour is disabled */
1162
+ return DSM_VALUE_INDONESIA_DISABLE;
1163
+}
1164
+
1165
+static u8 iwl_mvm_eval_dsm_disable_srd(struct iwl_mvm *mvm)
1166
+{
1167
+ int ret = iwl_acpi_get_dsm_u8((&mvm->fwrt)->dev, 0,
1168
+ DSM_FUNC_DISABLE_SRD);
1169
+
1170
+ if (ret < 0)
1171
+ IWL_DEBUG_RADIO(mvm,
1172
+ "Failed to evaluate DSM function DISABLE_SRD, ret=%d\n",
1173
+ ret);
1174
+
1175
+ else if (ret >= DSM_VALUE_SRD_MAX)
1176
+ IWL_DEBUG_RADIO(mvm,
1177
+ "DSM function DISABLE_SRD return invalid value, ret=%d\n",
1178
+ ret);
1179
+
1180
+ else if (ret == DSM_VALUE_SRD_PASSIVE) {
1181
+ IWL_DEBUG_RADIO(mvm,
1182
+ "Evaluated DSM function DISABLE_SRD: setting SRD to passive\n");
1183
+ return DSM_VALUE_SRD_PASSIVE;
1184
+
1185
+ } else if (ret == DSM_VALUE_SRD_DISABLE) {
1186
+ IWL_DEBUG_RADIO(mvm,
1187
+ "Evaluated DSM function DISABLE_SRD: disabling SRD\n");
1188
+ return DSM_VALUE_SRD_DISABLE;
1189
+ }
1190
+ /* default behaviour is active */
1191
+ return DSM_VALUE_SRD_ACTIVE;
1192
+}
1193
+
1194
+static void iwl_mvm_lari_cfg(struct iwl_mvm *mvm)
1195
+{
1196
+ u8 ret;
1197
+ int cmd_ret;
1198
+ struct iwl_lari_config_change_cmd cmd = {};
1199
+
1200
+ if (iwl_mvm_eval_dsm_indonesia_5g2(mvm) == DSM_VALUE_INDONESIA_ENABLE)
1201
+ cmd.config_bitmap |=
1202
+ cpu_to_le32(LARI_CONFIG_ENABLE_5G2_IN_INDONESIA_MSK);
1203
+
1204
+ ret = iwl_mvm_eval_dsm_disable_srd(mvm);
1205
+ if (ret == DSM_VALUE_SRD_PASSIVE)
1206
+ cmd.config_bitmap |=
1207
+ cpu_to_le32(LARI_CONFIG_CHANGE_ETSI_TO_PASSIVE_MSK);
1208
+
1209
+ else if (ret == DSM_VALUE_SRD_DISABLE)
1210
+ cmd.config_bitmap |=
1211
+ cpu_to_le32(LARI_CONFIG_CHANGE_ETSI_TO_DISABLED_MSK);
1212
+
1213
+ /* apply more config masks here */
1214
+
1215
+ if (cmd.config_bitmap) {
1216
+ IWL_DEBUG_RADIO(mvm, "sending LARI_CONFIG_CHANGE\n");
1217
+ cmd_ret = iwl_mvm_send_cmd_pdu(mvm,
1218
+ WIDE_ID(REGULATORY_AND_NVM_GROUP,
1219
+ LARI_CONFIG_CHANGE),
1220
+ 0, sizeof(cmd), &cmd);
1221
+ if (cmd_ret < 0)
1222
+ IWL_DEBUG_RADIO(mvm,
1223
+ "Failed to send LARI_CONFIG_CHANGE (%d)\n",
1224
+ cmd_ret);
1225
+ }
1226
+}
9431227 #else /* CONFIG_ACPI */
944
-static int iwl_mvm_sar_get_wrds_table(struct iwl_mvm *mvm)
1228
+
1229
+inline int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm,
1230
+ int prof_a, int prof_b)
9451231 {
9461232 return -ENOENT;
9471233 }
9481234
949
-static int iwl_mvm_sar_get_ewrd_table(struct iwl_mvm *mvm)
950
-{
951
- return -ENOENT;
952
-}
953
-
954
-static int iwl_mvm_sar_get_wgds_table(struct iwl_mvm *mvm)
1235
+inline int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
9551236 {
9561237 return -ENOENT;
9571238 }
....@@ -961,23 +1242,81 @@
9611242 return 0;
9621243 }
9631244
964
-int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a,
965
- int prof_b)
1245
+int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm)
9661246 {
9671247 return -ENOENT;
9681248 }
9691249
970
-int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
1250
+static int iwl_mvm_ppag_init(struct iwl_mvm *mvm)
9711251 {
972
- return -ENOENT;
1252
+ return 0;
1253
+}
1254
+
1255
+static void iwl_mvm_tas_init(struct iwl_mvm *mvm)
1256
+{
1257
+}
1258
+
1259
+static void iwl_mvm_lari_cfg(struct iwl_mvm *mvm)
1260
+{
9731261 }
9741262 #endif /* CONFIG_ACPI */
1263
+
1264
+void iwl_mvm_send_recovery_cmd(struct iwl_mvm *mvm, u32 flags)
1265
+{
1266
+ u32 error_log_size = mvm->fw->ucode_capa.error_log_size;
1267
+ int ret;
1268
+ u32 resp;
1269
+
1270
+ struct iwl_fw_error_recovery_cmd recovery_cmd = {
1271
+ .flags = cpu_to_le32(flags),
1272
+ .buf_size = 0,
1273
+ };
1274
+ struct iwl_host_cmd host_cmd = {
1275
+ .id = WIDE_ID(SYSTEM_GROUP, FW_ERROR_RECOVERY_CMD),
1276
+ .flags = CMD_WANT_SKB,
1277
+ .data = {&recovery_cmd, },
1278
+ .len = {sizeof(recovery_cmd), },
1279
+ };
1280
+
1281
+ /* no error log was defined in TLV */
1282
+ if (!error_log_size)
1283
+ return;
1284
+
1285
+ if (flags & ERROR_RECOVERY_UPDATE_DB) {
1286
+ /* no buf was allocated while HW reset */
1287
+ if (!mvm->error_recovery_buf)
1288
+ return;
1289
+
1290
+ host_cmd.data[1] = mvm->error_recovery_buf;
1291
+ host_cmd.len[1] = error_log_size;
1292
+ host_cmd.dataflags[1] = IWL_HCMD_DFL_NOCOPY;
1293
+ recovery_cmd.buf_size = cpu_to_le32(error_log_size);
1294
+ }
1295
+
1296
+ ret = iwl_mvm_send_cmd(mvm, &host_cmd);
1297
+ kfree(mvm->error_recovery_buf);
1298
+ mvm->error_recovery_buf = NULL;
1299
+
1300
+ if (ret) {
1301
+ IWL_ERR(mvm, "Failed to send recovery cmd %d\n", ret);
1302
+ return;
1303
+ }
1304
+
1305
+ /* skb respond is only relevant in ERROR_RECOVERY_UPDATE_DB */
1306
+ if (flags & ERROR_RECOVERY_UPDATE_DB) {
1307
+ resp = le32_to_cpu(*(__le32 *)host_cmd.resp_pkt->data);
1308
+ if (resp)
1309
+ IWL_ERR(mvm,
1310
+ "Failed to send recovery cmd blob was invalid %d\n",
1311
+ resp);
1312
+ }
1313
+}
9751314
9761315 static int iwl_mvm_sar_init(struct iwl_mvm *mvm)
9771316 {
9781317 int ret;
9791318
980
- ret = iwl_mvm_sar_get_wrds_table(mvm);
1319
+ ret = iwl_sar_get_wrds_table(&mvm->fwrt);
9811320 if (ret < 0) {
9821321 IWL_DEBUG_RADIO(mvm,
9831322 "WRDS SAR BIOS table invalid or unavailable. (%d)\n",
....@@ -989,25 +1328,14 @@
9891328 return 1;
9901329 }
9911330
992
- ret = iwl_mvm_sar_get_ewrd_table(mvm);
1331
+ ret = iwl_sar_get_ewrd_table(&mvm->fwrt);
9931332 /* if EWRD is not available, we can still use WRDS, so don't fail */
9941333 if (ret < 0)
9951334 IWL_DEBUG_RADIO(mvm,
9961335 "EWRD SAR BIOS table invalid or unavailable. (%d)\n",
9971336 ret);
9981337
999
- /* choose profile 1 (WRDS) as default for both chains */
1000
- ret = iwl_mvm_sar_select_profile(mvm, 1, 1);
1001
-
1002
- /*
1003
- * If we don't have profile 0 from BIOS, just skip it. This
1004
- * means that SAR Geo will not be enabled either, even if we
1005
- * have other valid profiles.
1006
- */
1007
- if (ret == -ENOENT)
1008
- return 1;
1009
-
1010
- return ret;
1338
+ return iwl_mvm_sar_select_profile(mvm, 1, 1);
10111339 }
10121340
10131341 static int iwl_mvm_load_rt_fw(struct iwl_mvm *mvm)
....@@ -1027,19 +1355,23 @@
10271355 return ret;
10281356 }
10291357
1030
- /*
1031
- * Stop and start the transport without entering low power
1032
- * mode. This will save the state of other components on the
1033
- * device that are triggered by the INIT firwmare (MFUART).
1034
- */
1035
- _iwl_trans_stop_device(mvm->trans, false);
1036
- ret = _iwl_trans_start_hw(mvm->trans, false);
1358
+ iwl_fw_dbg_stop_sync(&mvm->fwrt);
1359
+ iwl_trans_stop_device(mvm->trans);
1360
+ ret = iwl_trans_start_hw(mvm->trans);
10371361 if (ret)
10381362 return ret;
10391363
1364
+ iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_POINT_EARLY, NULL);
1365
+
1366
+ mvm->rfkill_safe_init_done = false;
10401367 ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_REGULAR);
10411368 if (ret)
10421369 return ret;
1370
+
1371
+ mvm->rfkill_safe_init_done = true;
1372
+
1373
+ iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_POINT_AFTER_ALIVE,
1374
+ NULL);
10431375
10441376 return iwl_init_paging(&mvm->fwrt, mvm->fwrt.cur_fw_img);
10451377 }
....@@ -1049,6 +1381,7 @@
10491381 int ret, i;
10501382 struct ieee80211_channel *chan;
10511383 struct cfg80211_chan_def chandef;
1384
+ struct ieee80211_supported_band *sband = NULL;
10521385
10531386 lockdep_assert_held(&mvm->mutex);
10541387
....@@ -1059,6 +1392,9 @@
10591392 ret = iwl_mvm_load_rt_fw(mvm);
10601393 if (ret) {
10611394 IWL_ERR(mvm, "Failed to start RT ucode: %d\n", ret);
1395
+ if (ret != -ERFKILL)
1396
+ iwl_fw_dbg_error_collect(&mvm->fwrt,
1397
+ FW_DBG_TRIGGER_DRIVER);
10621398 goto error;
10631399 }
10641400
....@@ -1068,11 +1404,13 @@
10681404 if (ret)
10691405 IWL_ERR(mvm, "Failed to initialize Smart Fifo\n");
10701406
1071
- mvm->fwrt.dump.conf = FW_DBG_INVALID;
1072
- /* if we have a destination, assume EARLY START */
1073
- if (mvm->fw->dbg_dest_tlv)
1074
- mvm->fwrt.dump.conf = FW_DBG_START_FROM_ALIVE;
1075
- iwl_fw_start_dbg_conf(&mvm->fwrt, FW_DBG_START_FROM_ALIVE);
1407
+ if (!iwl_trans_dbg_ini_valid(mvm->trans)) {
1408
+ mvm->fwrt.dump.conf = FW_DBG_INVALID;
1409
+ /* if we have a destination, assume EARLY START */
1410
+ if (mvm->fw->dbg.dest_tlv)
1411
+ mvm->fwrt.dump.conf = FW_DBG_START_FROM_ALIVE;
1412
+ iwl_fw_start_dbg_conf(&mvm->fwrt, FW_DBG_START_FROM_ALIVE);
1413
+ }
10761414
10771415 ret = iwl_send_tx_ant_cfg(mvm, iwl_mvm_get_valid_tx_ant(mvm));
10781416 if (ret)
....@@ -1083,18 +1421,25 @@
10831421 ret = iwl_send_phy_db_data(mvm->phy_db);
10841422 if (ret)
10851423 goto error;
1086
-
1087
- ret = iwl_send_phy_cfg_cmd(mvm);
1088
- if (ret)
1089
- goto error;
10901424 }
1425
+
1426
+ ret = iwl_send_phy_cfg_cmd(mvm);
1427
+ if (ret)
1428
+ goto error;
10911429
10921430 ret = iwl_mvm_send_bt_init_conf(mvm);
10931431 if (ret)
10941432 goto error;
10951433
1434
+ if (fw_has_capa(&mvm->fw->ucode_capa,
1435
+ IWL_UCODE_TLV_CAPA_SOC_LATENCY_SUPPORT)) {
1436
+ ret = iwl_set_soc_latency(&mvm->fwrt);
1437
+ if (ret)
1438
+ goto error;
1439
+ }
1440
+
10961441 /* Init RSS configuration */
1097
- if (mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
1442
+ if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
10981443 ret = iwl_configure_rxq(mvm);
10991444 if (ret) {
11001445 IWL_ERR(mvm, "Failed to configure RX queues: %d\n",
....@@ -1113,7 +1458,7 @@
11131458 }
11141459
11151460 /* init the fw <-> mac80211 STA mapping */
1116
- for (i = 0; i < ARRAY_SIZE(mvm->fw_id_to_mac_id); i++)
1461
+ for (i = 0; i < mvm->fw->ucode_capa.num_stations; i++)
11171462 RCU_INIT_POINTER(mvm->fw_id_to_mac_id[i], NULL);
11181463
11191464 mvm->tdls_cs.peer.sta_id = IWL_MVM_INVALID_STA;
....@@ -1121,17 +1466,42 @@
11211466 /* reset quota debouncing buffer - 0xff will yield invalid data */
11221467 memset(&mvm->last_quota_cmd, 0xff, sizeof(mvm->last_quota_cmd));
11231468
1124
- ret = iwl_mvm_send_dqa_cmd(mvm);
1125
- if (ret)
1126
- goto error;
1469
+ if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_DQA_SUPPORT)) {
1470
+ ret = iwl_mvm_send_dqa_cmd(mvm);
1471
+ if (ret)
1472
+ goto error;
1473
+ }
11271474
1128
- /* Add auxiliary station for scanning */
1129
- ret = iwl_mvm_add_aux_sta(mvm);
1130
- if (ret)
1131
- goto error;
1475
+ /*
1476
+ * Add auxiliary station for scanning.
1477
+ * Newer versions of this command implies that the fw uses
1478
+ * internal aux station for all aux activities that don't
1479
+ * requires a dedicated data queue.
1480
+ */
1481
+ if (iwl_fw_lookup_cmd_ver(mvm->fw, LONG_GROUP,
1482
+ ADD_STA,
1483
+ 0) < 12) {
1484
+ /*
1485
+ * In old version the aux station uses mac id like other
1486
+ * station and not lmac id
1487
+ */
1488
+ ret = iwl_mvm_add_aux_sta(mvm, MAC_INDEX_AUX);
1489
+ if (ret)
1490
+ goto error;
1491
+ }
11321492
11331493 /* Add all the PHY contexts */
1134
- chan = &mvm->hw->wiphy->bands[NL80211_BAND_2GHZ]->channels[0];
1494
+ i = 0;
1495
+ while (!sband && i < NUM_NL80211_BANDS)
1496
+ sband = mvm->hw->wiphy->bands[i++];
1497
+
1498
+ if (WARN_ON_ONCE(!sband)) {
1499
+ ret = -ENODEV;
1500
+ goto error;
1501
+ }
1502
+
1503
+ chan = &sband->channels[0];
1504
+
11351505 cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT);
11361506 for (i = 0; i < NUM_PHY_CTX; i++) {
11371507 /*
....@@ -1145,7 +1515,6 @@
11451515 goto error;
11461516 }
11471517
1148
-#ifdef CONFIG_THERMAL
11491518 if (iwl_mvm_is_tt_in_fw(mvm)) {
11501519 /* in order to give the responsibility of ct-kill and
11511520 * TX backoff to FW we need to send empty temperature reporting
....@@ -1157,6 +1526,7 @@
11571526 iwl_mvm_tt_tx_backoff(mvm, 0);
11581527 }
11591528
1529
+#ifdef CONFIG_THERMAL
11601530 /* TODO: read the budget from BIOS / Platform NVM */
11611531
11621532 /*
....@@ -1169,17 +1539,16 @@
11691539 if (ret)
11701540 goto error;
11711541 }
1172
-#else
1173
- /* Initialize tx backoffs to the minimal possible */
1174
- iwl_mvm_tt_tx_backoff(mvm, 0);
11751542 #endif
11761543
1177
- WARN_ON(iwl_mvm_config_ltr(mvm));
1544
+ if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_SET_LTR_GEN2))
1545
+ WARN_ON(iwl_mvm_config_ltr(mvm));
11781546
11791547 ret = iwl_mvm_power_update_device(mvm);
11801548 if (ret)
11811549 goto error;
11821550
1551
+ iwl_mvm_lari_cfg(mvm);
11831552 /*
11841553 * RTNL is not taken during Ct-kill, but we don't need to scan/Tx
11851554 * anyway, so don't init MCC.
....@@ -1198,14 +1567,20 @@
11981567 goto error;
11991568 }
12001569
1201
- /* allow FW/transport low power modes if not during restart */
1202
- if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
1203
- iwl_mvm_unref(mvm, IWL_MVM_REF_UCODE_DOWN);
1570
+ if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
1571
+ iwl_mvm_send_recovery_cmd(mvm, ERROR_RECOVERY_UPDATE_DB);
1572
+
1573
+ if (iwl_acpi_get_eckv(mvm->dev, &mvm->ext_clock_valid))
1574
+ IWL_DEBUG_INFO(mvm, "ECKV table doesn't exist in BIOS\n");
1575
+
1576
+ ret = iwl_mvm_ppag_init(mvm);
1577
+ if (ret)
1578
+ goto error;
12041579
12051580 ret = iwl_mvm_sar_init(mvm);
12061581 if (ret == 0) {
12071582 ret = iwl_mvm_sar_geo_init(mvm);
1208
- } else if (ret > 0 && !iwl_mvm_sar_get_wgds_table(mvm)) {
1583
+ } else if (ret == -ENOENT && !iwl_sar_get_wgds_table(&mvm->fwrt)) {
12091584 /*
12101585 * If basic SAR is not available, we check for WGDS,
12111586 * which should *not* be available either. If it is
....@@ -1218,7 +1593,10 @@
12181593 if (ret < 0)
12191594 goto error;
12201595
1596
+ iwl_mvm_tas_init(mvm);
12211597 iwl_mvm_leds_sync(mvm);
1598
+
1599
+ iwl_mvm_ftm_initiator_smooth_config(mvm);
12221600
12231601 IWL_DEBUG_INFO(mvm, "RT uCode started.\n");
12241602 return 0;
....@@ -1258,13 +1636,24 @@
12581636 goto error;
12591637
12601638 /* init the fw <-> mac80211 STA mapping */
1261
- for (i = 0; i < ARRAY_SIZE(mvm->fw_id_to_mac_id); i++)
1639
+ for (i = 0; i < mvm->fw->ucode_capa.num_stations; i++)
12621640 RCU_INIT_POINTER(mvm->fw_id_to_mac_id[i], NULL);
12631641
1264
- /* Add auxiliary station for scanning */
1265
- ret = iwl_mvm_add_aux_sta(mvm);
1266
- if (ret)
1267
- goto error;
1642
+ if (iwl_fw_lookup_cmd_ver(mvm->fw, LONG_GROUP,
1643
+ ADD_STA,
1644
+ 0) < 12) {
1645
+ /*
1646
+ * Add auxiliary station for scanning.
1647
+ * Newer versions of this command implies that the fw uses
1648
+ * internal aux station for all aux activities that don't
1649
+ * requires a dedicated data queue.
1650
+ * In old version the aux station uses mac id like other
1651
+ * station and not lmac id
1652
+ */
1653
+ ret = iwl_mvm_add_aux_sta(mvm, MAC_INDEX_AUX);
1654
+ if (ret)
1655
+ goto error;
1656
+ }
12681657
12691658 return 0;
12701659 error: