aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/mvm/fw.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm/fw.c')
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw.c160
1 files changed, 143 insertions, 17 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c
index ca38e9817374..bc5eac4960e1 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/iwlwifi/mvm/fw.c
@@ -112,25 +112,27 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
112 struct iwl_mvm *mvm = 112 struct iwl_mvm *mvm =
113 container_of(notif_wait, struct iwl_mvm, notif_wait); 113 container_of(notif_wait, struct iwl_mvm, notif_wait);
114 struct iwl_mvm_alive_data *alive_data = data; 114 struct iwl_mvm_alive_data *alive_data = data;
115 struct mvm_alive_resp *palive; 115 struct mvm_alive_resp_ver1 *palive1;
116 struct mvm_alive_resp_ver2 *palive2; 116 struct mvm_alive_resp_ver2 *palive2;
117 struct mvm_alive_resp *palive;
117 118
118 if (iwl_rx_packet_payload_len(pkt) == sizeof(*palive)) { 119 if (iwl_rx_packet_payload_len(pkt) == sizeof(*palive1)) {
119 palive = (void *)pkt->data; 120 palive1 = (void *)pkt->data;
120 121
121 mvm->support_umac_log = false; 122 mvm->support_umac_log = false;
122 mvm->error_event_table = 123 mvm->error_event_table =
123 le32_to_cpu(palive->error_event_table_ptr); 124 le32_to_cpu(palive1->error_event_table_ptr);
124 mvm->log_event_table = le32_to_cpu(palive->log_event_table_ptr); 125 mvm->log_event_table =
125 alive_data->scd_base_addr = le32_to_cpu(palive->scd_base_ptr); 126 le32_to_cpu(palive1->log_event_table_ptr);
127 alive_data->scd_base_addr = le32_to_cpu(palive1->scd_base_ptr);
126 128
127 alive_data->valid = le16_to_cpu(palive->status) == 129 alive_data->valid = le16_to_cpu(palive1->status) ==
128 IWL_ALIVE_STATUS_OK; 130 IWL_ALIVE_STATUS_OK;
129 IWL_DEBUG_FW(mvm, 131 IWL_DEBUG_FW(mvm,
130 "Alive VER1 ucode status 0x%04x revision 0x%01X 0x%01X flags 0x%01X\n", 132 "Alive VER1 ucode status 0x%04x revision 0x%01X 0x%01X flags 0x%01X\n",
131 le16_to_cpu(palive->status), palive->ver_type, 133 le16_to_cpu(palive1->status), palive1->ver_type,
132 palive->ver_subtype, palive->flags); 134 palive1->ver_subtype, palive1->flags);
133 } else { 135 } else if (iwl_rx_packet_payload_len(pkt) == sizeof(*palive2)) {
134 palive2 = (void *)pkt->data; 136 palive2 = (void *)pkt->data;
135 137
136 mvm->error_event_table = 138 mvm->error_event_table =
@@ -156,6 +158,33 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
156 IWL_DEBUG_FW(mvm, 158 IWL_DEBUG_FW(mvm,
157 "UMAC version: Major - 0x%x, Minor - 0x%x\n", 159 "UMAC version: Major - 0x%x, Minor - 0x%x\n",
158 palive2->umac_major, palive2->umac_minor); 160 palive2->umac_major, palive2->umac_minor);
161 } else if (iwl_rx_packet_payload_len(pkt) == sizeof(*palive)) {
162 palive = (void *)pkt->data;
163
164 mvm->error_event_table =
165 le32_to_cpu(palive->error_event_table_ptr);
166 mvm->log_event_table =
167 le32_to_cpu(palive->log_event_table_ptr);
168 alive_data->scd_base_addr = le32_to_cpu(palive->scd_base_ptr);
169 mvm->umac_error_event_table =
170 le32_to_cpu(palive->error_info_addr);
171 mvm->sf_space.addr = le32_to_cpu(palive->st_fwrd_addr);
172 mvm->sf_space.size = le32_to_cpu(palive->st_fwrd_size);
173
174 alive_data->valid = le16_to_cpu(palive->status) ==
175 IWL_ALIVE_STATUS_OK;
176 if (mvm->umac_error_event_table)
177 mvm->support_umac_log = true;
178
179 IWL_DEBUG_FW(mvm,
180 "Alive VER3 ucode status 0x%04x revision 0x%01X 0x%01X flags 0x%01X\n",
181 le16_to_cpu(palive->status), palive->ver_type,
182 palive->ver_subtype, palive->flags);
183
184 IWL_DEBUG_FW(mvm,
185 "UMAC version: Major - 0x%x, Minor - 0x%x\n",
186 le32_to_cpu(palive->umac_major),
187 le32_to_cpu(palive->umac_minor));
159 } 188 }
160 189
161 return true; 190 return true;
@@ -188,8 +217,7 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
188 struct iwl_sf_region st_fwrd_space; 217 struct iwl_sf_region st_fwrd_space;
189 218
190 if (ucode_type == IWL_UCODE_REGULAR && 219 if (ucode_type == IWL_UCODE_REGULAR &&
191 iwl_fw_dbg_conf_usniffer(mvm->fw, FW_DBG_CUSTOM) && 220 iwl_fw_dbg_conf_usniffer(mvm->fw, FW_DBG_START_FROM_ALIVE))
192 iwl_fw_dbg_conf_enabled(mvm->fw, FW_DBG_CUSTOM))
193 fw = iwl_get_ucode_image(mvm, IWL_UCODE_REGULAR_USNIFFER); 221 fw = iwl_get_ucode_image(mvm, IWL_UCODE_REGULAR_USNIFFER);
194 else 222 else
195 fw = iwl_get_ucode_image(mvm, ucode_type); 223 fw = iwl_get_ucode_image(mvm, ucode_type);
@@ -451,20 +479,97 @@ exit:
451 iwl_free_resp(&cmd); 479 iwl_free_resp(&cmd);
452} 480}
453 481
454void iwl_mvm_fw_dbg_collect(struct iwl_mvm *mvm) 482int iwl_mvm_fw_dbg_collect_desc(struct iwl_mvm *mvm,
483 struct iwl_mvm_dump_desc *desc,
484 unsigned int delay)
455{ 485{
486 if (test_and_set_bit(IWL_MVM_STATUS_DUMPING_FW_LOG, &mvm->status))
487 return -EBUSY;
488
489 if (WARN_ON(mvm->fw_dump_desc))
490 iwl_mvm_free_fw_dump_desc(mvm);
491
492 IWL_WARN(mvm, "Collecting data: trigger %d fired.\n",
493 le32_to_cpu(desc->trig_desc.type));
494
495 mvm->fw_dump_desc = desc;
496
456 /* stop recording */ 497 /* stop recording */
457 if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) { 498 if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
458 iwl_set_bits_prph(mvm->trans, MON_BUFF_SAMPLE_CTL, 0x100); 499 iwl_set_bits_prph(mvm->trans, MON_BUFF_SAMPLE_CTL, 0x100);
459 } else { 500 } else {
460 iwl_write_prph(mvm->trans, DBGC_IN_SAMPLE, 0); 501 iwl_write_prph(mvm->trans, DBGC_IN_SAMPLE, 0);
461 iwl_write_prph(mvm->trans, DBGC_OUT_CTRL, 0); 502 /* wait before we collect the data till the DBGC stop */
503 udelay(100);
504 }
505
506 queue_delayed_work(system_wq, &mvm->fw_dump_wk, delay);
507
508 return 0;
509}
510
511int iwl_mvm_fw_dbg_collect(struct iwl_mvm *mvm, enum iwl_fw_dbg_trigger trig,
512 const char *str, size_t len, unsigned int delay)
513{
514 struct iwl_mvm_dump_desc *desc;
515
516 desc = kzalloc(sizeof(*desc) + len, GFP_ATOMIC);
517 if (!desc)
518 return -ENOMEM;
519
520 desc->len = len;
521 desc->trig_desc.type = cpu_to_le32(trig);
522 memcpy(desc->trig_desc.data, str, len);
523
524 return iwl_mvm_fw_dbg_collect_desc(mvm, desc, delay);
525}
526
527int iwl_mvm_fw_dbg_collect_trig(struct iwl_mvm *mvm,
528 struct iwl_fw_dbg_trigger_tlv *trigger,
529 const char *fmt, ...)
530{
531 unsigned int delay = msecs_to_jiffies(le32_to_cpu(trigger->stop_delay));
532 u16 occurrences = le16_to_cpu(trigger->occurrences);
533 int ret, len = 0;
534 char buf[64];
535
536 if (!occurrences)
537 return 0;
538
539 if (fmt) {
540 va_list ap;
541
542 buf[sizeof(buf) - 1] = '\0';
543
544 va_start(ap, fmt);
545 vsnprintf(buf, sizeof(buf), fmt, ap);
546 va_end(ap);
547
548 /* check for truncation */
549 if (WARN_ON_ONCE(buf[sizeof(buf) - 1]))
550 buf[sizeof(buf) - 1] = '\0';
551
552 len = strlen(buf) + 1;
462 } 553 }
463 554
464 schedule_work(&mvm->fw_error_dump_wk); 555 ret = iwl_mvm_fw_dbg_collect(mvm, le32_to_cpu(trigger->id), buf,
556 len, delay);
557 if (ret)
558 return ret;
559
560 trigger->occurrences = cpu_to_le16(occurrences - 1);
561 return 0;
465} 562}
466 563
467int iwl_mvm_start_fw_dbg_conf(struct iwl_mvm *mvm, enum iwl_fw_dbg_conf conf_id) 564static inline void iwl_mvm_restart_early_start(struct iwl_mvm *mvm)
565{
566 if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000)
567 iwl_clear_bits_prph(mvm->trans, MON_BUFF_SAMPLE_CTL, 0x100);
568 else
569 iwl_write_prph(mvm->trans, DBGC_IN_SAMPLE, 1);
570}
571
572int iwl_mvm_start_fw_dbg_conf(struct iwl_mvm *mvm, u8 conf_id)
468{ 573{
469 u8 *ptr; 574 u8 *ptr;
470 int ret; 575 int ret;
@@ -474,6 +579,14 @@ int iwl_mvm_start_fw_dbg_conf(struct iwl_mvm *mvm, enum iwl_fw_dbg_conf conf_id)
474 "Invalid configuration %d\n", conf_id)) 579 "Invalid configuration %d\n", conf_id))
475 return -EINVAL; 580 return -EINVAL;
476 581
582 /* EARLY START - firmware's configuration is hard coded */
583 if ((!mvm->fw->dbg_conf_tlv[conf_id] ||
584 !mvm->fw->dbg_conf_tlv[conf_id]->num_of_hcmds) &&
585 conf_id == FW_DBG_START_FROM_ALIVE) {
586 iwl_mvm_restart_early_start(mvm);
587 return 0;
588 }
589
477 if (!mvm->fw->dbg_conf_tlv[conf_id]) 590 if (!mvm->fw->dbg_conf_tlv[conf_id])
478 return -EINVAL; 591 return -EINVAL;
479 592
@@ -583,7 +696,10 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
583 IWL_ERR(mvm, "Failed to initialize Smart Fifo\n"); 696 IWL_ERR(mvm, "Failed to initialize Smart Fifo\n");
584 697
585 mvm->fw_dbg_conf = FW_DBG_INVALID; 698 mvm->fw_dbg_conf = FW_DBG_INVALID;
586 iwl_mvm_start_fw_dbg_conf(mvm, FW_DBG_CUSTOM); 699 /* if we have a destination, assume EARLY START */
700 if (mvm->fw->dbg_dest_tlv)
701 mvm->fw_dbg_conf = FW_DBG_START_FROM_ALIVE;
702 iwl_mvm_start_fw_dbg_conf(mvm, FW_DBG_START_FROM_ALIVE);
587 703
588 ret = iwl_send_tx_ant_cfg(mvm, iwl_mvm_get_valid_tx_ant(mvm)); 704 ret = iwl_send_tx_ant_cfg(mvm, iwl_mvm_get_valid_tx_ant(mvm));
589 if (ret) 705 if (ret)
@@ -640,6 +756,16 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
640 if (ret) 756 if (ret)
641 goto error; 757 goto error;
642 758
759 /*
760 * RTNL is not taken during Ct-kill, but we don't need to scan/Tx
761 * anyway, so don't init MCC.
762 */
763 if (!test_bit(IWL_MVM_STATUS_HW_CTKILL, &mvm->status)) {
764 ret = iwl_mvm_init_mcc(mvm);
765 if (ret)
766 goto error;
767 }
768
643 if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN) { 769 if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN) {
644 ret = iwl_mvm_config_scan(mvm); 770 ret = iwl_mvm_config_scan(mvm);
645 if (ret) 771 if (ret)