Commit 520f03ea authored by Shahar S Matityahu's avatar Shahar S Matityahu Committed by Luca Coelho

iwlwifi: allow masking out memory areas from the fw dump

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: default avatarShahar S Matityahu <shahar.s.matityahu@intel.com>
Signed-off-by: default avatarGolan Ben Ami <golan.ben.ami@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent 92536c96
...@@ -243,39 +243,47 @@ static void iwl_fw_dump_fifos(struct iwl_fw_runtime *fwrt, ...@@ -243,39 +243,47 @@ static void iwl_fw_dump_fifos(struct iwl_fw_runtime *fwrt,
if (!iwl_trans_grab_nic_access(fwrt->trans, &flags)) if (!iwl_trans_grab_nic_access(fwrt->trans, &flags))
return; return;
if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_RXF)) {
/* Pull RXF1 */ /* Pull RXF1 */
iwl_fwrt_dump_rxf(fwrt, dump_data, cfg->lmac[0].rxfifo1_size, 0, 0); iwl_fwrt_dump_rxf(fwrt, dump_data,
cfg->lmac[0].rxfifo1_size, 0, 0);
/* Pull RXF2 */ /* Pull RXF2 */
iwl_fwrt_dump_rxf(fwrt, dump_data, cfg->rxfifo2_size, iwl_fwrt_dump_rxf(fwrt, dump_data, cfg->rxfifo2_size,
RXF_DIFF_FROM_PREV, 1); RXF_DIFF_FROM_PREV, 1);
/* Pull LMAC2 RXF1 */ /* Pull LMAC2 RXF1 */
if (fwrt->smem_cfg.num_lmacs > 1) if (fwrt->smem_cfg.num_lmacs > 1)
iwl_fwrt_dump_rxf(fwrt, dump_data, cfg->lmac[1].rxfifo1_size, iwl_fwrt_dump_rxf(fwrt, dump_data,
cfg->lmac[1].rxfifo1_size,
LMAC2_PRPH_OFFSET, 2); LMAC2_PRPH_OFFSET, 2);
}
if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_TXF)) {
/* Pull TXF data from LMAC1 */ /* Pull TXF data from LMAC1 */
for (i = 0; i < fwrt->smem_cfg.num_txfifo_entries; i++) { for (i = 0; i < fwrt->smem_cfg.num_txfifo_entries; i++) {
/* Mark the number of TXF we're pulling now */ /* Mark the number of TXF we're pulling now */
iwl_trans_write_prph(fwrt->trans, TXF_LARC_NUM, i); iwl_trans_write_prph(fwrt->trans, TXF_LARC_NUM, i);
iwl_fwrt_dump_txf(fwrt, dump_data, cfg->lmac[0].txfifo_size[i], iwl_fwrt_dump_txf(fwrt, dump_data,
0, i); cfg->lmac[0].txfifo_size[i], 0, i);
} }
/* Pull TXF data from LMAC2 */ /* Pull TXF data from LMAC2 */
if (fwrt->smem_cfg.num_lmacs > 1) { if (fwrt->smem_cfg.num_lmacs > 1) {
for (i = 0; i < fwrt->smem_cfg.num_txfifo_entries; i++) { for (i = 0; i < fwrt->smem_cfg.num_txfifo_entries;
i++) {
/* Mark the number of TXF we're pulling now */ /* Mark the number of TXF we're pulling now */
iwl_trans_write_prph(fwrt->trans, iwl_trans_write_prph(fwrt->trans,
TXF_LARC_NUM + LMAC2_PRPH_OFFSET, TXF_LARC_NUM +
i); LMAC2_PRPH_OFFSET, i);
iwl_fwrt_dump_txf(fwrt, dump_data, iwl_fwrt_dump_txf(fwrt, dump_data,
cfg->lmac[1].txfifo_size[i], cfg->lmac[1].txfifo_size[i],
LMAC2_PRPH_OFFSET, LMAC2_PRPH_OFFSET,
i + cfg->num_txfifo_entries); 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)) { IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG)) {
/* Pull UMAC internal TXF data from all TXFs */ /* Pull UMAC internal TXF data from all TXFs */
for (i = 0; for (i = 0;
...@@ -600,10 +608,13 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) ...@@ -600,10 +608,13 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
if (test_bit(STATUS_FW_ERROR, &fwrt->trans->status)) { if (test_bit(STATUS_FW_ERROR, &fwrt->trans->status)) {
fifo_data_len = 0; fifo_data_len = 0;
if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_RXF)) {
/* Count RXF2 size */ /* Count RXF2 size */
if (mem_cfg->rxfifo2_size) { if (mem_cfg->rxfifo2_size) {
/* Add header info */ /* Add header info */
fifo_data_len += mem_cfg->rxfifo2_size + fifo_data_len +=
mem_cfg->rxfifo2_size +
sizeof(*dump_data) + sizeof(*dump_data) +
sizeof(struct iwl_fw_error_dump_fifo); sizeof(struct iwl_fw_error_dump_fifo);
} }
...@@ -614,28 +625,37 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) ...@@ -614,28 +625,37 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
continue; continue;
/* Add header info */ /* Add header info */
fifo_data_len += mem_cfg->lmac[i].rxfifo1_size + fifo_data_len +=
mem_cfg->lmac[i].rxfifo1_size +
sizeof(*dump_data) + sizeof(*dump_data) +
sizeof(struct iwl_fw_error_dump_fifo); sizeof(struct iwl_fw_error_dump_fifo);
} }
}
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 */ /* Count TXF sizes */
for (i = 0; i < mem_cfg->num_lmacs; i++) { for (i = 0; i < mem_cfg->num_lmacs; i++) {
int j; int j;
for (j = 0; j < mem_cfg->num_txfifo_entries; j++) { for (j = 0; j < mem_cfg->num_txfifo_entries;
j++) {
if (!mem_cfg->lmac[i].txfifo_size[j]) if (!mem_cfg->lmac[i].txfifo_size[j])
continue; continue;
/* Add header info */ /* Add header info */
fifo_data_len += fifo_data_len +=
mem_cfg->lmac[i].txfifo_size[j] + fifo_const_len +
sizeof(*dump_data) + mem_cfg->lmac[i].txfifo_size[j];
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_INTERNAL_TXF)) &&
fw_has_capa(&fwrt->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG)) { IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG)) {
for (i = 0; for (i = 0;
i < ARRAY_SIZE(mem_cfg->internal_txfifo_size); i < ARRAY_SIZE(mem_cfg->internal_txfifo_size);
...@@ -652,7 +672,8 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) ...@@ -652,7 +672,8 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
} }
/* Make room for PRPH registers */ /* 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); for (i = 0; i < ARRAY_SIZE(iwl_prph_dump_addr_comm);
i++) { i++) {
/* The range includes both boundaries */ /* The range includes both boundaries */
...@@ -667,7 +688,8 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) ...@@ -667,7 +688,8 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
} }
if (!fwrt->trans->cfg->gen2 && 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 < for (i = 0; i <
ARRAY_SIZE(iwl_prph_dump_addr_9000); i++) { ARRAY_SIZE(iwl_prph_dump_addr_9000); i++) {
/* The range includes both boundaries */ /* The range includes both boundaries */
...@@ -681,34 +703,42 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) ...@@ -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; radio_len = sizeof(*dump_data) + RADIO_REG_MAX_READ;
} }
file_len = sizeof(*dump_file) + file_len = sizeof(*dump_file) +
sizeof(*dump_data) * 3 +
sizeof(*dump_smem_cfg) +
fifo_data_len + fifo_data_len +
prph_len + prph_len +
radio_len + radio_len;
sizeof(*dump_info);
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 */ /* Make room for the SMEM, if it exists */
if (smem_len) if (smem_len)
file_len += sizeof(*dump_data) + sizeof(*dump_mem) + smem_len; file_len += sizeof(*dump_data) + sizeof(*dump_mem) +
smem_len;
/* Make room for the secondary SRAM, if it exists */ /* Make room for the secondary SRAM, if it exists */
if (sram2_len) if (sram2_len)
file_len += sizeof(*dump_data) + sizeof(*dump_mem) + sram2_len; file_len += sizeof(*dump_data) + sizeof(*dump_mem) +
sram2_len;
/* Make room for MEM segments */ /* Make room for MEM segments */
for (i = 0; i < fwrt->fw->n_dbg_mem_tlv; i++) { for (i = 0; i < fwrt->fw->n_dbg_mem_tlv; i++) {
file_len += sizeof(*dump_data) + sizeof(*dump_mem) + file_len += sizeof(*dump_data) + sizeof(*dump_mem) +
le32_to_cpu(fw_dbg_mem[i].len); le32_to_cpu(fw_dbg_mem[i].len);
} }
}
/* Make room for fw's virtual image pages, if it exists */ /* 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->img[fwrt->cur_fw_img].paging_mem_size &&
fwrt->fw_paging_db[0].fw_paging_block) fwrt->fw_paging_db[0].fw_paging_block)
file_len += fwrt->num_of_paging_blk * file_len += fwrt->num_of_paging_blk *
...@@ -722,12 +752,14 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) ...@@ -722,12 +752,14 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
sizeof(*dump_info) + sizeof(*dump_smem_cfg); 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) + file_len += sizeof(*dump_data) + sizeof(*dump_trig) +
fwrt->dump.desc->len; fwrt->dump.desc->len;
if (!fwrt->fw->n_dbg_mem_tlv) if (fwrt->fw->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_MEM) &&
file_len += sram_len + sizeof(*dump_mem); !fwrt->fw->n_dbg_mem_tlv)
file_len += sizeof(*dump_data) + sram_len + sizeof(*dump_mem);
dump_file = vzalloc(file_len); dump_file = vzalloc(file_len);
if (!dump_file) { if (!dump_file) {
...@@ -740,23 +772,28 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) ...@@ -740,23 +772,28 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
dump_file->barker = cpu_to_le32(IWL_FW_ERROR_DUMP_BARKER); dump_file->barker = cpu_to_le32(IWL_FW_ERROR_DUMP_BARKER);
dump_data = (void *)dump_file->data; dump_data = (void *)dump_file->data;
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->type = cpu_to_le32(IWL_FW_ERROR_DUMP_DEV_FW_INFO);
dump_data->len = cpu_to_le32(sizeof(*dump_info)); dump_data->len = cpu_to_le32(sizeof(*dump_info));
dump_info = (void *)dump_data->data; dump_info = (void *)dump_data->data;
dump_info->device_family = dump_info->device_family =
fwrt->trans->cfg->device_family == IWL_DEVICE_FAMILY_7000 ? 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_7) :
cpu_to_le32(IWL_FW_ERROR_DUMP_FAMILY_8); cpu_to_le32(IWL_FW_ERROR_DUMP_FAMILY_8);
dump_info->hw_step = cpu_to_le32(CSR_HW_REV_STEP(fwrt->trans->hw_rev)); 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, memcpy(dump_info->fw_human_readable, fwrt->fw->human_readable,
sizeof(dump_info->fw_human_readable)); sizeof(dump_info->fw_human_readable));
strncpy(dump_info->dev_human_readable, fwrt->trans->cfg->name, strncpy(dump_info->dev_human_readable, fwrt->trans->cfg->name,
sizeof(dump_info->dev_human_readable)); sizeof(dump_info->dev_human_readable) - 1);
strncpy(dump_info->bus_human_readable, fwrt->dev->bus->name, strncpy(dump_info->bus_human_readable, fwrt->dev->bus->name,
sizeof(dump_info->bus_human_readable)); 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 shared memory configuration */
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_CFG); dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_CFG);
dump_data->len = cpu_to_le32(sizeof(*dump_smem_cfg)); dump_data->len = cpu_to_le32(sizeof(*dump_smem_cfg));
...@@ -766,14 +803,16 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) ...@@ -766,14 +803,16 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
cpu_to_le32(mem_cfg->num_txfifo_entries); cpu_to_le32(mem_cfg->num_txfifo_entries);
for (i = 0; i < MAX_NUM_LMAC; i++) { for (i = 0; i < MAX_NUM_LMAC; i++) {
int j; int j;
u32 *txf_size = mem_cfg->lmac[i].txfifo_size;
for (j = 0; j < TX_FIFO_MAX_NUM; j++) for (j = 0; j < TX_FIFO_MAX_NUM; j++)
dump_smem_cfg->lmac[i].txfifo_size[j] = dump_smem_cfg->lmac[i].txfifo_size[j] =
cpu_to_le32(mem_cfg->lmac[i].txfifo_size[j]); cpu_to_le32(txf_size[j]);
dump_smem_cfg->lmac[i].rxfifo1_size = dump_smem_cfg->lmac[i].rxfifo1_size =
cpu_to_le32(mem_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->rxfifo2_size =
cpu_to_le32(mem_cfg->rxfifo2_size);
dump_smem_cfg->internal_txfifo_addr = dump_smem_cfg->internal_txfifo_addr =
cpu_to_le32(mem_cfg->internal_txfifo_addr); cpu_to_le32(mem_cfg->internal_txfifo_addr);
for (i = 0; i < TX_FIFO_INTERNAL_MAX_NUM; i++) { for (i = 0; i < TX_FIFO_INTERNAL_MAX_NUM; i++) {
...@@ -782,6 +821,7 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) ...@@ -782,6 +821,7 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
} }
dump_data = iwl_fw_error_next_data(dump_data); dump_data = iwl_fw_error_next_data(dump_data);
}
/* We only dump the FIFOs if the FW is in error state */ /* We only dump the FIFOs if the FW is in error state */
if (test_bit(STATUS_FW_ERROR, &fwrt->trans->status)) { if (test_bit(STATUS_FW_ERROR, &fwrt->trans->status)) {
...@@ -790,7 +830,8 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) ...@@ -790,7 +830,8 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
iwl_read_radio_regs(fwrt, &dump_data); 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->type = cpu_to_le32(IWL_FW_ERROR_DUMP_ERROR_INFO);
dump_data->len = cpu_to_le32(sizeof(*dump_trig) + dump_data->len = cpu_to_le32(sizeof(*dump_trig) +
fwrt->dump.desc->len); fwrt->dump.desc->len);
...@@ -805,7 +846,8 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) ...@@ -805,7 +846,8 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
if (monitor_dump_only) if (monitor_dump_only)
goto dump_trans_data; 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->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
dump_data->len = cpu_to_le32(sram_len + sizeof(*dump_mem)); dump_data->len = cpu_to_le32(sram_len + sizeof(*dump_mem));
dump_mem = (void *)dump_data->data; dump_mem = (void *)dump_data->data;
...@@ -821,6 +863,9 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) ...@@ -821,6 +863,9 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
u32 ofs = le32_to_cpu(fw_dbg_mem[i].ofs); u32 ofs = le32_to_cpu(fw_dbg_mem[i].ofs);
bool success; 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->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
dump_data->len = cpu_to_le32(len + sizeof(*dump_mem)); dump_data->len = cpu_to_le32(len + sizeof(*dump_mem));
dump_mem = (void *)dump_data->data; dump_mem = (void *)dump_data->data;
...@@ -854,7 +899,7 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) ...@@ -854,7 +899,7 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
dump_data = iwl_fw_error_next_data(dump_data); 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"); IWL_DEBUG_INFO(fwrt, "WRT SMEM dump\n");
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM); dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
dump_data->len = cpu_to_le32(smem_len + sizeof(*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) ...@@ -867,7 +912,7 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
dump_data = iwl_fw_error_next_data(dump_data); 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"); IWL_DEBUG_INFO(fwrt, "WRT SRAM dump\n");
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM); dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
dump_data->len = cpu_to_le32(sram2_len + sizeof(*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) ...@@ -881,7 +926,8 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
} }
/* Dump fw's virtual image */ /* 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->img[fwrt->cur_fw_img].paging_mem_size &&
fwrt->fw_paging_db[0].fw_paging_block) { fwrt->fw_paging_db[0].fw_paging_block) {
IWL_DEBUG_INFO(fwrt, "WRT paging dump\n"); IWL_DEBUG_INFO(fwrt, "WRT paging dump\n");
......
...@@ -146,6 +146,9 @@ enum iwl_ucode_tlv_type { ...@@ -146,6 +146,9 @@ enum iwl_ucode_tlv_type {
IWL_UCODE_TLV_FW_GSCAN_CAPA = 50, IWL_UCODE_TLV_FW_GSCAN_CAPA = 50,
IWL_UCODE_TLV_FW_MEM_SEG = 51, IWL_UCODE_TLV_FW_MEM_SEG = 51,
IWL_UCODE_TLV_IML = 52, 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 { struct iwl_ucode_tlv {
......
...@@ -299,6 +299,7 @@ struct iwl_fw { ...@@ -299,6 +299,7 @@ struct iwl_fw {
size_t dbg_trigger_tlv_len[FW_DBG_TRIGGER_MAX]; size_t dbg_trigger_tlv_len[FW_DBG_TRIGGER_MAX];
u8 dbg_dest_reg_num; u8 dbg_dest_reg_num;
struct iwl_gscan_capabilities gscan_capa; struct iwl_gscan_capabilities gscan_capa;
u32 dbg_dump_mask;
}; };
static inline const char *get_fw_dbg_mode_string(int mode) static inline const char *get_fw_dbg_mode_string(int mode)
......
...@@ -1043,6 +1043,17 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, ...@@ -1043,6 +1043,17 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
pieces->dbg_trigger_tlv_len[trigger_id] = tlv_len; pieces->dbg_trigger_tlv_len[trigger_id] = tlv_len;
break; 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: case IWL_UCODE_TLV_SEC_RT_USNIFFER:
*usniffer_images = true; *usniffer_images = true;
iwl_store_ucode_sec(pieces, tlv_data, iwl_store_ucode_sec(pieces, tlv_data,
...@@ -1316,6 +1327,8 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context) ...@@ -1316,6 +1327,8 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
fw->ucode_capa.standard_phy_calibration_size = fw->ucode_capa.standard_phy_calibration_size =
IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE; IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE;
fw->ucode_capa.n_scan_channels = IWL_DEFAULT_SCAN_CHANNELS; 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); pieces = kzalloc(sizeof(*pieces), GFP_KERNEL);
if (!pieces) if (!pieces)
......
...@@ -771,6 +771,7 @@ struct iwl_trans { ...@@ -771,6 +771,7 @@ struct iwl_trans {
const struct iwl_fw_dbg_dest_tlv_v1 *dbg_dest_tlv; 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]; const struct iwl_fw_dbg_conf_tlv *dbg_conf_tlv[FW_DBG_CONF_MAX];
struct iwl_fw_dbg_trigger_tlv * const *dbg_trigger_tlv; struct iwl_fw_dbg_trigger_tlv * const *dbg_trigger_tlv;
u32 dbg_dump_mask;
u8 dbg_dest_reg_num; u8 dbg_dest_reg_num;
enum iwl_plat_pm_mode system_pm_mode; enum iwl_plat_pm_mode system_pm_mode;
......
...@@ -746,6 +746,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, ...@@ -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, memcpy(trans->dbg_conf_tlv, mvm->fw->dbg_conf_tlv,
sizeof(trans->dbg_conf_tlv)); sizeof(trans->dbg_conf_tlv));
trans->dbg_trigger_tlv = mvm->fw->dbg_trigger_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 = mvm->fw->iml;
trans->iml_len = mvm->fw->iml_len; trans->iml_len = mvm->fw->iml_len;
......
...@@ -84,6 +84,7 @@ ...@@ -84,6 +84,7 @@
#include "iwl-scd.h" #include "iwl-scd.h"
#include "iwl-agn-hw.h" #include "iwl-agn-hw.h"
#include "fw/error-dump.h" #include "fw/error-dump.h"
#include "fw/dbg.h"
#include "internal.h" #include "internal.h"
#include "iwl-fh.h" #include "iwl-fh.h"
...@@ -2978,7 +2979,8 @@ static struct iwl_trans_dump_data ...@@ -2978,7 +2979,8 @@ static struct iwl_trans_dump_data
u32 monitor_len; u32 monitor_len;
int i, ptr; int i, ptr;
bool dump_rbs = test_bit(STATUS_FW_ERROR, &trans->status) && 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 */ /* transport dump header */
len = sizeof(*dump_data); len = sizeof(*dump_data);
...@@ -3030,6 +3032,10 @@ static struct iwl_trans_dump_data ...@@ -3030,6 +3032,10 @@ static struct iwl_trans_dump_data
} }
if (trigger && (trigger->mode & IWL_FW_DBG_TRIGGER_MONITOR_ONLY)) { 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); dump_data = vzalloc(len);
if (!dump_data) if (!dump_data)
return NULL; return NULL;
...@@ -3042,15 +3048,20 @@ static struct iwl_trans_dump_data ...@@ -3042,15 +3048,20 @@ static struct iwl_trans_dump_data
} }
/* CSR registers */ /* CSR registers */
if (trans->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_CSR))
len += sizeof(*data) + IWL_CSR_TO_DUMP; len += sizeof(*data) + IWL_CSR_TO_DUMP;
/* FH registers */ /* FH registers */
if (trans->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_FH_REGS)) {
if (trans->cfg->gen2) if (trans->cfg->gen2)
len += sizeof(*data) + len += sizeof(*data) +
(FH_MEM_UPPER_BOUND_GEN2 - FH_MEM_LOWER_BOUND_GEN2); (FH_MEM_UPPER_BOUND_GEN2 -
FH_MEM_LOWER_BOUND_GEN2);
else else
len += sizeof(*data) + len += sizeof(*data) +
(FH_MEM_UPPER_BOUND - FH_MEM_LOWER_BOUND); (FH_MEM_UPPER_BOUND -
FH_MEM_LOWER_BOUND);
}
if (dump_rbs) { if (dump_rbs) {
/* Dump RBs is supported only for pre-9000 devices (1 queue) */ /* Dump RBs is supported only for pre-9000 devices (1 queue) */
...@@ -3066,7 +3077,8 @@ static struct iwl_trans_dump_data ...@@ -3066,7 +3077,8 @@ static struct iwl_trans_dump_data
} }
/* Paged memory for gen2 HW */ /* 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++) for (i = 0; i < trans_pcie->init_dram.paging_cnt; i++)
len += sizeof(*data) + len += sizeof(*data) +
sizeof(struct iwl_fw_error_dump_paging) + sizeof(struct iwl_fw_error_dump_paging) +
...@@ -3078,6 +3090,10 @@ static struct iwl_trans_dump_data ...@@ -3078,6 +3090,10 @@ static struct iwl_trans_dump_data
len = 0; len = 0;
data = (void *)dump_data->data; data = (void *)dump_data->data;
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); data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_TXCMD);
txcmd = (void *)data->data; txcmd = (void *)data->data;
spin_lock_bh(&cmdq->lock); spin_lock_bh(&cmdq->lock);
...@@ -3086,15 +3102,17 @@ static struct iwl_trans_dump_data ...@@ -3086,15 +3102,17 @@ static struct iwl_trans_dump_data
u8 idx = iwl_pcie_get_cmd_index(cmdq, ptr); u8 idx = iwl_pcie_get_cmd_index(cmdq, ptr);
u32 caplen, cmdlen; u32 caplen, cmdlen;
cmdlen = iwl_trans_pcie_get_cmdlen(trans, cmdq->tfds + cmdlen = iwl_trans_pcie_get_cmdlen(trans,
trans_pcie->tfd_size * ptr); cmdq->tfds +
tfd_size * ptr);
caplen = min_t(u32, TFD_MAX_PAYLOAD_SIZE, cmdlen); caplen = min_t(u32, TFD_MAX_PAYLOAD_SIZE, cmdlen);
if (cmdlen) { if (cmdlen) {
len += sizeof(*txcmd) + caplen; len += sizeof(*txcmd) + caplen;
txcmd->cmdlen = cpu_to_le32(cmdlen); txcmd->cmdlen = cpu_to_le32(cmdlen);
txcmd->caplen = cpu_to_le32(caplen); txcmd->caplen = cpu_to_le32(caplen);
memcpy(txcmd->data, cmdq->entries[idx].cmd, caplen); memcpy(txcmd->data, cmdq->entries[idx].cmd,
caplen);
txcmd = (void *)((u8 *)txcmd->data + caplen); txcmd = (void *)((u8 *)txcmd->data + caplen);
} }
...@@ -3105,14 +3123,18 @@ static struct iwl_trans_dump_data ...@@ -3105,14 +3123,18 @@ static struct iwl_trans_dump_data
data->len = cpu_to_le32(len); data->len = cpu_to_le32(len);
len += sizeof(*data); len += sizeof(*data);
data = iwl_fw_error_next_data(data); data = iwl_fw_error_next_data(data);
}
if (trans->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_CSR))
len += iwl_trans_pcie_dump_csr(trans, &data); 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); len += iwl_trans_pcie_fh_regs_dump(trans, &data);
if (dump_rbs) if (dump_rbs)
len += iwl_trans_pcie_dump_rbs(trans, &data, num_rbs); len += iwl_trans_pcie_dump_rbs(trans, &data, num_rbs);
/* Paged memory for gen2 HW */ /* 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++) { for (i = 0; i < trans_pcie->init_dram.paging_cnt; i++) {
struct iwl_fw_error_dump_paging *paging; struct iwl_fw_error_dump_paging *paging;
dma_addr_t addr = dma_addr_t addr =
...@@ -3132,7 +3154,7 @@ static struct iwl_trans_dump_data ...@@ -3132,7 +3154,7 @@ static struct iwl_trans_dump_data
len += sizeof(*data) + sizeof(*paging) + page_len; len += sizeof(*data) + sizeof(*paging) + page_len;
} }
} }
if (trans->dbg_dump_mask & BIT(IWL_FW_ERROR_DUMP_FW_MONITOR))
len += iwl_trans_pcie_dump_monitor(trans, &data, monitor_len); len += iwl_trans_pcie_dump_monitor(trans, &data, monitor_len);
dump_data->len = len; dump_data->len = len;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment