iwlwifi: allow masking out memory areas from the fw dump
authorShahar S Matityahu <shahar.s.matityahu@intel.com>
Tue, 20 Feb 2018 15:20:32 +0000 (17:20 +0200)
committerLuca Coelho <luciano.coelho@intel.com>
Thu, 2 Aug 2018 07:50:06 +0000 (10:50 +0300)
Reading and dumping memory areas takes time, and sometimes
dumping all of the areas isn't necessary.

Allow choosing the memory areas which should be dumped.

Signed-off-by: Shahar S Matityahu <shahar.s.matityahu@intel.com>
Signed-off-by: Golan Ben Ami <golan.ben.ami@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
drivers/net/wireless/intel/iwlwifi/fw/dbg.c
drivers/net/wireless/intel/iwlwifi/fw/file.h
drivers/net/wireless/intel/iwlwifi/fw/img.h
drivers/net/wireless/intel/iwlwifi/iwl-drv.c
drivers/net/wireless/intel/iwlwifi/iwl-trans.h
drivers/net/wireless/intel/iwlwifi/mvm/ops.c
drivers/net/wireless/intel/iwlwifi/pcie/trans.c

index fa28328..a31a42e 100644 (file)
@@ -243,39 +243,47 @@ static void iwl_fw_dump_fifos(struct iwl_fw_runtime *fwrt,
        if (!iwl_trans_grab_nic_access(fwrt->trans, &flags))
                return;
 
-       /* Pull RXF1 */
-       iwl_fwrt_dump_rxf(fwrt, dump_data, cfg->lmac[0].rxfifo1_size, 0, 0);
-       /* Pull RXF2 */
-       iwl_fwrt_dump_rxf(fwrt, dump_data, cfg->rxfifo2_size,
-                         RXF_DIFF_FROM_PREV, 1);
-       /* Pull LMAC2 RXF1 */
-       if (fwrt->smem_cfg.num_lmacs > 1)
-               iwl_fwrt_dump_rxf(fwrt, dump_data, cfg->lmac[1].rxfifo1_size,
-                                 LMAC2_PRPH_OFFSET, 2);
-
-       /* Pull TXF data from LMAC1 */
-       for (i = 0; i < fwrt->smem_cfg.num_txfifo_entries; i++) {
-               /* Mark the number of TXF we're pulling now */
-               iwl_trans_write_prph(fwrt->trans, TXF_LARC_NUM, i);
-               iwl_fwrt_dump_txf(fwrt, dump_data, cfg->lmac[0].txfifo_size[i],
-                                 0, i);
+       if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_RXF)) {
+               /* Pull RXF1 */
+               iwl_fwrt_dump_rxf(fwrt, dump_data,
+                                 cfg->lmac[0].rxfifo1_size, 0, 0);
+               /* Pull RXF2 */
+               iwl_fwrt_dump_rxf(fwrt, dump_data, cfg->rxfifo2_size,
+                                 RXF_DIFF_FROM_PREV, 1);
+               /* Pull LMAC2 RXF1 */
+               if (fwrt->smem_cfg.num_lmacs > 1)
+                       iwl_fwrt_dump_rxf(fwrt, dump_data,
+                                         cfg->lmac[1].rxfifo1_size,
+                                         LMAC2_PRPH_OFFSET, 2);
        }
 
-       /* Pull TXF data from LMAC2 */
-       if (fwrt->smem_cfg.num_lmacs > 1) {
+       if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_TXF)) {
+               /* Pull TXF data from LMAC1 */
                for (i = 0; i < fwrt->smem_cfg.num_txfifo_entries; i++) {
                        /* Mark the number of TXF we're pulling now */
-                       iwl_trans_write_prph(fwrt->trans,
-                                            TXF_LARC_NUM + LMAC2_PRPH_OFFSET,
-                                            i);
+                       iwl_trans_write_prph(fwrt->trans, TXF_LARC_NUM, i);
                        iwl_fwrt_dump_txf(fwrt, dump_data,
-                                         cfg->lmac[1].txfifo_size[i],
-                                         LMAC2_PRPH_OFFSET,
-                                         i + cfg->num_txfifo_entries);
+                                         cfg->lmac[0].txfifo_size[i], 0, i);
+               }
+
+               /* Pull TXF data from LMAC2 */
+               if (fwrt->smem_cfg.num_lmacs > 1) {
+                       for (i = 0; i < fwrt->smem_cfg.num_txfifo_entries;
+                            i++) {
+                               /* Mark the number of TXF we're pulling now */
+                               iwl_trans_write_prph(fwrt->trans,
+                                                    TXF_LARC_NUM +
+                                                    LMAC2_PRPH_OFFSET, i);
+                               iwl_fwrt_dump_txf(fwrt, dump_data,
+                                                 cfg->lmac[1].txfifo_size[i],
+                                                 LMAC2_PRPH_OFFSET,
+                                                 i + cfg->num_txfifo_entries);
+                       }
                }
        }
 
-       if (fw_has_capa(&fwrt->fw->ucode_capa,
+       if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_INTERNAL_TXF) &&
+           fw_has_capa(&fwrt->fw->ucode_capa,
                        IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG)) {
                /* Pull UMAC internal TXF data from all TXFs */
                for (i = 0;
@@ -600,42 +608,54 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
        if (test_bit(STATUS_FW_ERROR, &fwrt->trans->status)) {
                fifo_data_len = 0;
 
-               /* Count RXF2 size */
-               if (mem_cfg->rxfifo2_size) {
-                       /* Add header info */
-                       fifo_data_len += mem_cfg->rxfifo2_size +
-                                        sizeof(*dump_data) +
-                                        sizeof(struct iwl_fw_error_dump_fifo);
-               }
-
-               /* Count RXF1 sizes */
-               for (i = 0; i < mem_cfg->num_lmacs; i++) {
-                       if (!mem_cfg->lmac[i].rxfifo1_size)
-                               continue;
-
-                       /* Add header info */
-                       fifo_data_len += mem_cfg->lmac[i].rxfifo1_size +
-                                        sizeof(*dump_data) +
-                                        sizeof(struct iwl_fw_error_dump_fifo);
-               }
+               if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_RXF)) {
 
-               /* Count TXF sizes */
-               for (i = 0; i < mem_cfg->num_lmacs; i++) {
-                       int j;
+                       /* Count RXF2 size */
+                       if (mem_cfg->rxfifo2_size) {
+                               /* Add header info */
+                               fifo_data_len +=
+                                       mem_cfg->rxfifo2_size +
+                                       sizeof(*dump_data) +
+                                       sizeof(struct iwl_fw_error_dump_fifo);
+                       }
 
-                       for (j = 0; j < mem_cfg->num_txfifo_entries; j++) {
-                               if (!mem_cfg->lmac[i].txfifo_size[j])
+                       /* Count RXF1 sizes */
+                       for (i = 0; i < mem_cfg->num_lmacs; i++) {
+                               if (!mem_cfg->lmac[i].rxfifo1_size)
                                        continue;
 
                                /* Add header info */
                                fifo_data_len +=
-                                       mem_cfg->lmac[i].txfifo_size[j] +
+                                       mem_cfg->lmac[i].rxfifo1_size +
                                        sizeof(*dump_data) +
                                        sizeof(struct iwl_fw_error_dump_fifo);
                        }
                }
 
-               if (fw_has_capa(&fwrt->fw->ucode_capa,
+               if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_TXF)) {
+                       size_t fifo_const_len = sizeof(*dump_data) +
+                               sizeof(struct iwl_fw_error_dump_fifo);
+
+                       /* Count TXF sizes */
+                       for (i = 0; i < mem_cfg->num_lmacs; i++) {
+                               int j;
+
+                               for (j = 0; j < mem_cfg->num_txfifo_entries;
+                                    j++) {
+                                       if (!mem_cfg->lmac[i].txfifo_size[j])
+                                               continue;
+
+                                       /* Add header info */
+                                       fifo_data_len +=
+                                               fifo_const_len +
+                                               mem_cfg->lmac[i].txfifo_size[j];
+                               }
+                       }
+               }
+
+               if ((fwrt->fw->dbg_dump_mask &
+                   BIT(IWL_FW_ERROR_DUMP_INTERNAL_TXF)) &&
+                   fw_has_capa(&fwrt->fw->ucode_capa,
                                IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG)) {
                        for (i = 0;
                             i < ARRAY_SIZE(mem_cfg->internal_txfifo_size);
@@ -652,7 +672,8 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
                }
 
                /* Make room for PRPH registers */
-               if (!fwrt->trans->cfg->gen2) {
+               if (!fwrt->trans->cfg->gen2 &&
+                   fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_PRPH)) {
                        for (i = 0; i < ARRAY_SIZE(iwl_prph_dump_addr_comm);
                             i++) {
                                /* The range includes both boundaries */
@@ -667,7 +688,8 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
                }
 
                if (!fwrt->trans->cfg->gen2 &&
-                   fwrt->trans->cfg->mq_rx_supported) {
+                   fwrt->trans->cfg->mq_rx_supported &&
+                   fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_PRPH)) {
                        for (i = 0; i <
                                ARRAY_SIZE(iwl_prph_dump_addr_9000); i++) {
                                /* The range includes both boundaries */
@@ -681,34 +703,42 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
                        }
                }
 
-               if (fwrt->trans->cfg->device_family == IWL_DEVICE_FAMILY_7000)
+               if (fwrt->trans->cfg->device_family == IWL_DEVICE_FAMILY_7000 &&
+                   fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_RADIO_REG))
                        radio_len = sizeof(*dump_data) + RADIO_REG_MAX_READ;
        }
 
        file_len = sizeof(*dump_file) +
-                  sizeof(*dump_data) * 3 +
-                  sizeof(*dump_smem_cfg) +
                   fifo_data_len +
                   prph_len +
-                  radio_len +
-                  sizeof(*dump_info);
-
-       /* Make room for the SMEM, if it exists */
-       if (smem_len)
-               file_len += sizeof(*dump_data) + sizeof(*dump_mem) + smem_len;
-
-       /* Make room for the secondary SRAM, if it exists */
-       if (sram2_len)
-               file_len += sizeof(*dump_data) + sizeof(*dump_mem) + sram2_len;
-
-       /* Make room for MEM segments */
-       for (i = 0; i < fwrt->fw->n_dbg_mem_tlv; i++) {
-               file_len += sizeof(*dump_data) + sizeof(*dump_mem) +
-                           le32_to_cpu(fw_dbg_mem[i].len);
+                  radio_len;
+
+       if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_DEV_FW_INFO))
+               file_len += sizeof(*dump_data) + sizeof(*dump_info);
+       if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_MEM_CFG))
+               file_len += sizeof(*dump_data) + sizeof(*dump_smem_cfg);
+
+       if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_MEM)) {
+               /* Make room for the SMEM, if it exists */
+               if (smem_len)
+                       file_len += sizeof(*dump_data) + sizeof(*dump_mem) +
+                               smem_len;
+
+               /* Make room for the secondary SRAM, if it exists */
+               if (sram2_len)
+                       file_len += sizeof(*dump_data) + sizeof(*dump_mem) +
+                               sram2_len;
+
+               /* Make room for MEM segments */
+               for (i = 0; i < fwrt->fw->n_dbg_mem_tlv; i++) {
+                       file_len += sizeof(*dump_data) + sizeof(*dump_mem) +
+                                   le32_to_cpu(fw_dbg_mem[i].len);
+               }
        }
 
        /* Make room for fw's virtual image pages, if it exists */
-       if (!fwrt->trans->cfg->gen2 &&
+       if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING) &&
+           !fwrt->trans->cfg->gen2 &&
            fwrt->fw->img[fwrt->cur_fw_img].paging_mem_size &&
            fwrt->fw_paging_db[0].fw_paging_block)
                file_len += fwrt->num_of_paging_blk *
@@ -722,12 +752,14 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
                           sizeof(*dump_info) + sizeof(*dump_smem_cfg);
        }
 
-       if (fwrt->dump.desc)
+       if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_ERROR_INFO) &&
+           fwrt->dump.desc)
                file_len += sizeof(*dump_data) + sizeof(*dump_trig) +
                            fwrt->dump.desc->len;
 
-       if (!fwrt->fw->n_dbg_mem_tlv)
-               file_len += sram_len + sizeof(*dump_mem);
+       if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_MEM) &&
+           !fwrt->fw->n_dbg_mem_tlv)
+               file_len += sizeof(*dump_data) + sram_len + sizeof(*dump_mem);
 
        dump_file = vzalloc(file_len);
        if (!dump_file) {
@@ -740,48 +772,56 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
        dump_file->barker = cpu_to_le32(IWL_FW_ERROR_DUMP_BARKER);
        dump_data = (void *)dump_file->data;
 
-       dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_DEV_FW_INFO);
-       dump_data->len = cpu_to_le32(sizeof(*dump_info));
-       dump_info = (void *)dump_data->data;
-       dump_info->device_family =
-               fwrt->trans->cfg->device_family == IWL_DEVICE_FAMILY_7000 ?
-                       cpu_to_le32(IWL_FW_ERROR_DUMP_FAMILY_7) :
-                       cpu_to_le32(IWL_FW_ERROR_DUMP_FAMILY_8);
-       dump_info->hw_step = cpu_to_le32(CSR_HW_REV_STEP(fwrt->trans->hw_rev));
-       memcpy(dump_info->fw_human_readable, fwrt->fw->human_readable,
-              sizeof(dump_info->fw_human_readable));
-       strncpy(dump_info->dev_human_readable, fwrt->trans->cfg->name,
-               sizeof(dump_info->dev_human_readable));
-       strncpy(dump_info->bus_human_readable, fwrt->dev->bus->name,
-               sizeof(dump_info->bus_human_readable));
-
-       dump_data = iwl_fw_error_next_data(dump_data);
-
-       /* Dump shared memory configuration */
-       dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_CFG);
-       dump_data->len = cpu_to_le32(sizeof(*dump_smem_cfg));
-       dump_smem_cfg = (void *)dump_data->data;
-       dump_smem_cfg->num_lmacs = cpu_to_le32(mem_cfg->num_lmacs);
-       dump_smem_cfg->num_txfifo_entries =
-               cpu_to_le32(mem_cfg->num_txfifo_entries);
-       for (i = 0; i < MAX_NUM_LMAC; i++) {
-               int j;
-
-               for (j = 0; j < TX_FIFO_MAX_NUM; j++)
-                       dump_smem_cfg->lmac[i].txfifo_size[j] =
-                               cpu_to_le32(mem_cfg->lmac[i].txfifo_size[j]);
-               dump_smem_cfg->lmac[i].rxfifo1_size =
-                       cpu_to_le32(mem_cfg->lmac[i].rxfifo1_size);
-       }
-       dump_smem_cfg->rxfifo2_size = cpu_to_le32(mem_cfg->rxfifo2_size);
-       dump_smem_cfg->internal_txfifo_addr =
-               cpu_to_le32(mem_cfg->internal_txfifo_addr);
-       for (i = 0; i < TX_FIFO_INTERNAL_MAX_NUM; i++) {
-               dump_smem_cfg->internal_txfifo_size[i] =
-                       cpu_to_le32(mem_cfg->internal_txfifo_size[i]);
+       if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_DEV_FW_INFO)) {
+               dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_DEV_FW_INFO);
+               dump_data->len = cpu_to_le32(sizeof(*dump_info));
+               dump_info = (void *)dump_data->data;
+               dump_info->device_family =
+                       fwrt->trans->cfg->device_family ==
+                       IWL_DEVICE_FAMILY_7000 ?
+                               cpu_to_le32(IWL_FW_ERROR_DUMP_FAMILY_7) :
+                               cpu_to_le32(IWL_FW_ERROR_DUMP_FAMILY_8);
+               dump_info->hw_step =
+                       cpu_to_le32(CSR_HW_REV_STEP(fwrt->trans->hw_rev));
+               memcpy(dump_info->fw_human_readable, fwrt->fw->human_readable,
+                      sizeof(dump_info->fw_human_readable));
+               strncpy(dump_info->dev_human_readable, fwrt->trans->cfg->name,
+                       sizeof(dump_info->dev_human_readable) - 1);
+               strncpy(dump_info->bus_human_readable, fwrt->dev->bus->name,
+                       sizeof(dump_info->bus_human_readable) - 1);
+
+               dump_data = iwl_fw_error_next_data(dump_data);
        }
 
-       dump_data = iwl_fw_error_next_data(dump_data);
+       if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_MEM_CFG)) {
+               /* Dump shared memory configuration */
+               dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_CFG);
+               dump_data->len = cpu_to_le32(sizeof(*dump_smem_cfg));
+               dump_smem_cfg = (void *)dump_data->data;
+               dump_smem_cfg->num_lmacs = cpu_to_le32(mem_cfg->num_lmacs);
+               dump_smem_cfg->num_txfifo_entries =
+                       cpu_to_le32(mem_cfg->num_txfifo_entries);
+               for (i = 0; i < MAX_NUM_LMAC; i++) {
+                       int j;
+                       u32 *txf_size = mem_cfg->lmac[i].txfifo_size;
+
+                       for (j = 0; j < TX_FIFO_MAX_NUM; j++)
+                               dump_smem_cfg->lmac[i].txfifo_size[j] =
+                                       cpu_to_le32(txf_size[j]);
+                       dump_smem_cfg->lmac[i].rxfifo1_size =
+                               cpu_to_le32(mem_cfg->lmac[i].rxfifo1_size);
+               }
+               dump_smem_cfg->rxfifo2_size =
+                       cpu_to_le32(mem_cfg->rxfifo2_size);
+               dump_smem_cfg->internal_txfifo_addr =
+                       cpu_to_le32(mem_cfg->internal_txfifo_addr);
+               for (i = 0; i < TX_FIFO_INTERNAL_MAX_NUM; i++) {
+                       dump_smem_cfg->internal_txfifo_size[i] =
+                               cpu_to_le32(mem_cfg->internal_txfifo_size[i]);
+               }
+
+               dump_data = iwl_fw_error_next_data(dump_data);
+       }
 
        /* We only dump the FIFOs if the FW is in error state */
        if (test_bit(STATUS_FW_ERROR, &fwrt->trans->status)) {
@@ -790,7 +830,8 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
                        iwl_read_radio_regs(fwrt, &dump_data);
        }
 
-       if (fwrt->dump.desc) {
+       if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_ERROR_INFO) &&
+           fwrt->dump.desc) {
                dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_ERROR_INFO);
                dump_data->len = cpu_to_le32(sizeof(*dump_trig) +
                                             fwrt->dump.desc->len);
@@ -805,7 +846,8 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
        if (monitor_dump_only)
                goto dump_trans_data;
 
-       if (!fwrt->fw->n_dbg_mem_tlv) {
+       if (!fwrt->fw->n_dbg_mem_tlv &&
+           fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_MEM)) {
                dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
                dump_data->len = cpu_to_le32(sram_len + sizeof(*dump_mem));
                dump_mem = (void *)dump_data->data;
@@ -821,6 +863,9 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
                u32 ofs = le32_to_cpu(fw_dbg_mem[i].ofs);
                bool success;
 
+               if (!(fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_MEM)))
+                       break;
+
                dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
                dump_data->len = cpu_to_le32(len + sizeof(*dump_mem));
                dump_mem = (void *)dump_data->data;
@@ -854,7 +899,7 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
                        dump_data = iwl_fw_error_next_data(dump_data);
        }
 
-       if (smem_len) {
+       if (smem_len && fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_MEM)) {
                IWL_DEBUG_INFO(fwrt, "WRT SMEM dump\n");
                dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
                dump_data->len = cpu_to_le32(smem_len + sizeof(*dump_mem));
@@ -867,7 +912,7 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
                dump_data = iwl_fw_error_next_data(dump_data);
        }
 
-       if (sram2_len) {
+       if (sram2_len && fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_MEM)) {
                IWL_DEBUG_INFO(fwrt, "WRT SRAM dump\n");
                dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
                dump_data->len = cpu_to_le32(sram2_len + sizeof(*dump_mem));
@@ -881,7 +926,8 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
        }
 
        /* Dump fw's virtual image */
-       if (!fwrt->trans->cfg->gen2 &&
+       if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING) &&
+           !fwrt->trans->cfg->gen2 &&
            fwrt->fw->img[fwrt->cur_fw_img].paging_mem_size &&
            fwrt->fw_paging_db[0].fw_paging_block) {
                IWL_DEBUG_INFO(fwrt, "WRT paging dump\n");
index 9d939cb..c967dfb 100644 (file)
@@ -146,6 +146,9 @@ enum iwl_ucode_tlv_type {
        IWL_UCODE_TLV_FW_GSCAN_CAPA     = 50,
        IWL_UCODE_TLV_FW_MEM_SEG        = 51,
        IWL_UCODE_TLV_IML               = 52,
+
+       /* TLVs 0x1000-0x2000 are for internal driver usage */
+       IWL_UCODE_TLV_FW_DBG_DUMP_LST   = 0x1000,
 };
 
 struct iwl_ucode_tlv {
index f491238..6c5de68 100644 (file)
@@ -299,6 +299,7 @@ struct iwl_fw {
        size_t dbg_trigger_tlv_len[FW_DBG_TRIGGER_MAX];
        u8 dbg_dest_reg_num;
        struct iwl_gscan_capabilities gscan_capa;
+       u32 dbg_dump_mask;
 };
 
 static inline const char *get_fw_dbg_mode_string(int mode)
index 38fcc6a..370281e 100644 (file)
@@ -1043,6 +1043,17 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
                        pieces->dbg_trigger_tlv_len[trigger_id] = tlv_len;
                        break;
                        }
+               case IWL_UCODE_TLV_FW_DBG_DUMP_LST: {
+                       if (tlv_len != sizeof(u32)) {
+                               IWL_ERR(drv,
+                                       "dbg lst mask size incorrect, skip\n");
+                               break;
+                       }
+
+                       drv->fw.dbg_dump_mask =
+                               le32_to_cpup((__le32 *)tlv_data);
+                       break;
+                       }
                case IWL_UCODE_TLV_SEC_RT_USNIFFER:
                        *usniffer_images = true;
                        iwl_store_ucode_sec(pieces, tlv_data,
@@ -1316,6 +1327,8 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
        fw->ucode_capa.standard_phy_calibration_size =
                        IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE;
        fw->ucode_capa.n_scan_channels = IWL_DEFAULT_SCAN_CHANNELS;
+       /* dump all fw memory areas by default */
+       fw->dbg_dump_mask = 0xffffffff;
 
        pieces = kzalloc(sizeof(*pieces), GFP_KERNEL);
        if (!pieces)
index 9483f76..279dd7b 100644 (file)
@@ -771,6 +771,7 @@ struct iwl_trans {
        const struct iwl_fw_dbg_dest_tlv_v1 *dbg_dest_tlv;
        const struct iwl_fw_dbg_conf_tlv *dbg_conf_tlv[FW_DBG_CONF_MAX];
        struct iwl_fw_dbg_trigger_tlv * const *dbg_trigger_tlv;
+       u32 dbg_dump_mask;
        u8 dbg_dest_reg_num;
 
        enum iwl_plat_pm_mode system_pm_mode;
index f5b117d..99c0860 100644 (file)
@@ -746,6 +746,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
        memcpy(trans->dbg_conf_tlv, mvm->fw->dbg_conf_tlv,
               sizeof(trans->dbg_conf_tlv));
        trans->dbg_trigger_tlv = mvm->fw->dbg_trigger_tlv;
+       trans->dbg_dump_mask = mvm->fw->dbg_dump_mask;
 
        trans->iml = mvm->fw->iml;
        trans->iml_len = mvm->fw->iml_len;
index 603458a..7928e80 100644 (file)
@@ -84,6 +84,7 @@
 #include "iwl-scd.h"
 #include "iwl-agn-hw.h"
 #include "fw/error-dump.h"
+#include "fw/dbg.h"
 #include "internal.h"
 #include "iwl-fh.h"
 
@@ -2978,7 +2979,8 @@ static struct iwl_trans_dump_data
        u32 monitor_len;
        int i, ptr;
        bool dump_rbs = test_bit(STATUS_FW_ERROR, &trans->status) &&
-                       !trans->cfg->mq_rx_supported;
+                       !trans->cfg->mq_rx_supported &&
+                       trans->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_RB);
 
        /* transport dump header */
        len = sizeof(*dump_data);
@@ -3030,6 +3032,10 @@ static struct iwl_trans_dump_data
        }
 
        if (trigger && (trigger->mode & IWL_FW_DBG_TRIGGER_MONITOR_ONLY)) {
+               if (!(trans->dbg_dump_mask &
+                     BIT(IWL_FW_ERROR_DUMP_FW_MONITOR)))
+                       return NULL;
+
                dump_data = vzalloc(len);
                if (!dump_data)
                        return NULL;
@@ -3042,15 +3048,20 @@ static struct iwl_trans_dump_data
        }
 
        /* CSR registers */
-       len += sizeof(*data) + IWL_CSR_TO_DUMP;
+       if (trans->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_CSR))
+               len += sizeof(*data) + IWL_CSR_TO_DUMP;
 
        /* FH registers */
-       if (trans->cfg->gen2)
-               len += sizeof(*data) +
-                      (FH_MEM_UPPER_BOUND_GEN2 - FH_MEM_LOWER_BOUND_GEN2);
-       else
-               len += sizeof(*data) +
-                      (FH_MEM_UPPER_BOUND - FH_MEM_LOWER_BOUND);
+       if (trans->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_FH_REGS)) {
+               if (trans->cfg->gen2)
+                       len += sizeof(*data) +
+                              (FH_MEM_UPPER_BOUND_GEN2 -
+                               FH_MEM_LOWER_BOUND_GEN2);
+               else
+                       len += sizeof(*data) +
+                              (FH_MEM_UPPER_BOUND -
+                               FH_MEM_LOWER_BOUND);
+       }
 
        if (dump_rbs) {
                /* Dump RBs is supported only for pre-9000 devices (1 queue) */
@@ -3066,7 +3077,8 @@ static struct iwl_trans_dump_data
        }
 
        /* Paged memory for gen2 HW */
-       if (trans->cfg->gen2)
+       if (trans->cfg->gen2 &&
+           trans->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING))
                for (i = 0; i < trans_pcie->init_dram.paging_cnt; i++)
                        len += sizeof(*data) +
                               sizeof(struct iwl_fw_error_dump_paging) +
@@ -3078,41 +3090,51 @@ static struct iwl_trans_dump_data
 
        len = 0;
        data = (void *)dump_data->data;
-       data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_TXCMD);
-       txcmd = (void *)data->data;
-       spin_lock_bh(&cmdq->lock);
-       ptr = cmdq->write_ptr;
-       for (i = 0; i < cmdq->n_window; i++) {
-               u8 idx = iwl_pcie_get_cmd_index(cmdq, ptr);
-               u32 caplen, cmdlen;
-
-               cmdlen = iwl_trans_pcie_get_cmdlen(trans, cmdq->tfds +
-                                                  trans_pcie->tfd_size * ptr);
-               caplen = min_t(u32, TFD_MAX_PAYLOAD_SIZE, cmdlen);
-
-               if (cmdlen) {
-                       len += sizeof(*txcmd) + caplen;
-                       txcmd->cmdlen = cpu_to_le32(cmdlen);
-                       txcmd->caplen = cpu_to_le32(caplen);
-                       memcpy(txcmd->data, cmdq->entries[idx].cmd, caplen);
-                       txcmd = (void *)((u8 *)txcmd->data + caplen);
+
+       if (trans->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_TXCMD)) {
+               u16 tfd_size = trans_pcie->tfd_size;
+
+               data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_TXCMD);
+               txcmd = (void *)data->data;
+               spin_lock_bh(&cmdq->lock);
+               ptr = cmdq->write_ptr;
+               for (i = 0; i < cmdq->n_window; i++) {
+                       u8 idx = iwl_pcie_get_cmd_index(cmdq, ptr);
+                       u32 caplen, cmdlen;
+
+                       cmdlen = iwl_trans_pcie_get_cmdlen(trans,
+                                                          cmdq->tfds +
+                                                          tfd_size * ptr);
+                       caplen = min_t(u32, TFD_MAX_PAYLOAD_SIZE, cmdlen);
+
+                       if (cmdlen) {
+                               len += sizeof(*txcmd) + caplen;
+                               txcmd->cmdlen = cpu_to_le32(cmdlen);
+                               txcmd->caplen = cpu_to_le32(caplen);
+                               memcpy(txcmd->data, cmdq->entries[idx].cmd,
+                                      caplen);
+                               txcmd = (void *)((u8 *)txcmd->data + caplen);
+                       }
+
+                       ptr = iwl_queue_dec_wrap(trans, ptr);
                }
+               spin_unlock_bh(&cmdq->lock);
 
-               ptr = iwl_queue_dec_wrap(trans, ptr);
+               data->len = cpu_to_le32(len);
+               len += sizeof(*data);
+               data = iwl_fw_error_next_data(data);
        }
-       spin_unlock_bh(&cmdq->lock);
-
-       data->len = cpu_to_le32(len);
-       len += sizeof(*data);
-       data = iwl_fw_error_next_data(data);
 
-       len += iwl_trans_pcie_dump_csr(trans, &data);
-       len += iwl_trans_pcie_fh_regs_dump(trans, &data);
+       if (trans->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_CSR))
+               len += iwl_trans_pcie_dump_csr(trans, &data);
+       if (trans->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_FH_REGS))
+               len += iwl_trans_pcie_fh_regs_dump(trans, &data);
        if (dump_rbs)
                len += iwl_trans_pcie_dump_rbs(trans, &data, num_rbs);
 
        /* Paged memory for gen2 HW */
-       if (trans->cfg->gen2) {
+       if (trans->cfg->gen2 &&
+           trans->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_PAGING)) {
                for (i = 0; i < trans_pcie->init_dram.paging_cnt; i++) {
                        struct iwl_fw_error_dump_paging *paging;
                        dma_addr_t addr =
@@ -3132,8 +3154,8 @@ static struct iwl_trans_dump_data
                        len += sizeof(*data) + sizeof(*paging) + page_len;
                }
        }
-
-       len += iwl_trans_pcie_dump_monitor(trans, &data, monitor_len);
+       if (trans->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_FW_MONITOR))
+               len += iwl_trans_pcie_dump_monitor(trans, &data, monitor_len);
 
        dump_data->len = len;