Commit 7a99c877 authored by Shahar S Matityahu's avatar Shahar S Matityahu Committed by Luca Coelho

iwlwifi: dbg: support multiple dumps in legacy dump flow

Support multiple debug data collection triggers in legacy flow.
Utilize the already existing Yoyo infra so the change is rather simple.
Signed-off-by: default avatarShahar S Matityahu <shahar.s.matityahu@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/iwlwifi.20200417131727.5be6a1923cbe.I10701236b03f66328041f2a38f5f0f22a26fd40b@changeid
parent 4af11950
...@@ -818,7 +818,8 @@ static void iwl_dump_paging(struct iwl_fw_runtime *fwrt, ...@@ -818,7 +818,8 @@ static void iwl_dump_paging(struct iwl_fw_runtime *fwrt,
static struct iwl_fw_error_dump_file * static struct iwl_fw_error_dump_file *
iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt, iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt,
struct iwl_fw_dump_ptrs *fw_error_dump) struct iwl_fw_dump_ptrs *fw_error_dump,
struct iwl_fwrt_dump_data *data)
{ {
struct iwl_fw_error_dump_file *dump_file; struct iwl_fw_error_dump_file *dump_file;
struct iwl_fw_error_dump_data *dump_data; struct iwl_fw_error_dump_data *dump_data;
...@@ -900,15 +901,15 @@ iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt, ...@@ -900,15 +901,15 @@ iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt,
} }
/* If we only want a monitor dump, reset the file length */ /* If we only want a monitor dump, reset the file length */
if (fwrt->dump.monitor_only) { if (data->monitor_only) {
file_len = sizeof(*dump_file) + sizeof(*dump_data) * 2 + file_len = sizeof(*dump_file) + sizeof(*dump_data) * 2 +
sizeof(*dump_info) + sizeof(*dump_smem_cfg); sizeof(*dump_info) + sizeof(*dump_smem_cfg);
} }
if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_ERROR_INFO) && if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_ERROR_INFO) &&
fwrt->dump.desc) data->desc)
file_len += sizeof(*dump_data) + sizeof(*dump_trig) + file_len += sizeof(*dump_data) + sizeof(*dump_trig) +
fwrt->dump.desc->len; data->desc->len;
dump_file = vzalloc(file_len); dump_file = vzalloc(file_len);
if (!dump_file) if (!dump_file)
...@@ -984,19 +985,19 @@ iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt, ...@@ -984,19 +985,19 @@ iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt,
iwl_read_radio_regs(fwrt, &dump_data); iwl_read_radio_regs(fwrt, &dump_data);
if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_ERROR_INFO) && if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_ERROR_INFO) &&
fwrt->dump.desc) { data->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); data->desc->len);
dump_trig = (void *)dump_data->data; dump_trig = (void *)dump_data->data;
memcpy(dump_trig, &fwrt->dump.desc->trig_desc, memcpy(dump_trig, &data->desc->trig_desc,
sizeof(*dump_trig) + fwrt->dump.desc->len); sizeof(*dump_trig) + data->desc->len);
dump_data = iwl_fw_error_next_data(dump_data); dump_data = iwl_fw_error_next_data(dump_data);
} }
/* In case we only want monitor dump, skip to dump trasport data */ /* In case we only want monitor dump, skip to dump trasport data */
if (fwrt->dump.monitor_only) if (data->monitor_only)
goto out; goto out;
if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_MEM)) { if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_MEM)) {
...@@ -2172,7 +2173,21 @@ static u32 iwl_dump_ini_file_gen(struct iwl_fw_runtime *fwrt, ...@@ -2172,7 +2173,21 @@ static u32 iwl_dump_ini_file_gen(struct iwl_fw_runtime *fwrt,
return le32_to_cpu(hdr->file_len); return le32_to_cpu(hdr->file_len);
} }
static void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) static inline void iwl_fw_free_dump_desc(struct iwl_fw_runtime *fwrt,
const struct iwl_fw_dump_desc **desc)
{
if (desc && *desc != &iwl_dump_desc_assert)
kfree(*desc);
*desc = NULL;
fwrt->dump.lmac_err_id[0] = 0;
if (fwrt->smem_cfg.num_lmacs > 1)
fwrt->dump.lmac_err_id[1] = 0;
fwrt->dump.umac_err_id = 0;
}
static void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt,
struct iwl_fwrt_dump_data *dump_data)
{ {
struct iwl_fw_dump_ptrs fw_error_dump = {}; struct iwl_fw_dump_ptrs fw_error_dump = {};
struct iwl_fw_error_dump_file *dump_file; struct iwl_fw_error_dump_file *dump_file;
...@@ -2180,11 +2195,11 @@ static void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) ...@@ -2180,11 +2195,11 @@ static void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
u32 file_len; u32 file_len;
u32 dump_mask = fwrt->fw->dbg.dump_mask; u32 dump_mask = fwrt->fw->dbg.dump_mask;
dump_file = iwl_fw_error_dump_file(fwrt, &fw_error_dump); dump_file = iwl_fw_error_dump_file(fwrt, &fw_error_dump, dump_data);
if (!dump_file) if (!dump_file)
goto out; return;
if (fwrt->dump.monitor_only) if (dump_data->monitor_only)
dump_mask &= IWL_FW_ERROR_DUMP_FW_MONITOR; dump_mask &= IWL_FW_ERROR_DUMP_FW_MONITOR;
fw_error_dump.trans_ptr = iwl_trans_dump_data(fwrt->trans, dump_mask); fw_error_dump.trans_ptr = iwl_trans_dump_data(fwrt->trans, dump_mask);
...@@ -2213,9 +2228,6 @@ static void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) ...@@ -2213,9 +2228,6 @@ static void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
} }
vfree(fw_error_dump.fwrt_ptr); vfree(fw_error_dump.fwrt_ptr);
vfree(fw_error_dump.trans_ptr); vfree(fw_error_dump.trans_ptr);
out:
iwl_fw_free_dump_desc(fwrt);
} }
static void iwl_dump_ini_list_free(struct list_head *list) static void iwl_dump_ini_list_free(struct list_head *list)
...@@ -2244,7 +2256,7 @@ static void iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt, ...@@ -2244,7 +2256,7 @@ static void iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt,
u32 file_len = iwl_dump_ini_file_gen(fwrt, dump_data, &dump_list); u32 file_len = iwl_dump_ini_file_gen(fwrt, dump_data, &dump_list);
if (!file_len) if (!file_len)
goto out; return;
sg_dump_data = alloc_sgtable(file_len); sg_dump_data = alloc_sgtable(file_len);
if (sg_dump_data) { if (sg_dump_data) {
...@@ -2261,9 +2273,6 @@ static void iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt, ...@@ -2261,9 +2273,6 @@ static void iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt,
GFP_KERNEL); GFP_KERNEL);
} }
iwl_dump_ini_list_free(&dump_list); iwl_dump_ini_list_free(&dump_list);
out:
iwl_fw_error_dump_data_free(dump_data);
} }
const struct iwl_fw_dump_desc iwl_dump_desc_assert = { const struct iwl_fw_dump_desc iwl_dump_desc_assert = {
...@@ -2278,27 +2287,40 @@ int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt, ...@@ -2278,27 +2287,40 @@ int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt,
bool monitor_only, bool monitor_only,
unsigned int delay) unsigned int delay)
{ {
struct iwl_fwrt_wk_data *wk_data;
unsigned long idx;
if (iwl_trans_dbg_ini_valid(fwrt->trans)) { if (iwl_trans_dbg_ini_valid(fwrt->trans)) {
iwl_fw_free_dump_desc(fwrt); iwl_fw_free_dump_desc(fwrt, &desc);
return 0; return 0;
} }
/* use wks[0] since dump flow prior to ini does not need to support /*
* consecutive triggers collection * Check there is an available worker.
* ffz return value is undefined if no zero exists,
* so check against ~0UL first.
*/ */
if (test_and_set_bit(fwrt->dump.wks[0].idx, &fwrt->dump.active_wks)) if (fwrt->dump.active_wks == ~0UL)
return -EBUSY; return -EBUSY;
if (WARN_ON(fwrt->dump.desc)) idx = ffz(fwrt->dump.active_wks);
iwl_fw_free_dump_desc(fwrt);
if (idx >= IWL_FW_RUNTIME_DUMP_WK_NUM ||
test_and_set_bit(fwrt->dump.wks[idx].idx, &fwrt->dump.active_wks))
return -EBUSY;
wk_data = &fwrt->dump.wks[idx];
if (WARN_ON(wk_data->dump_data.desc))
iwl_fw_free_dump_desc(fwrt, &wk_data->dump_data.desc);
wk_data->dump_data.desc = desc;
wk_data->dump_data.monitor_only = monitor_only;
IWL_WARN(fwrt, "Collecting data: trigger %d fired.\n", IWL_WARN(fwrt, "Collecting data: trigger %d fired.\n",
le32_to_cpu(desc->trig_desc.type)); le32_to_cpu(desc->trig_desc.type));
fwrt->dump.desc = desc; schedule_delayed_work(&wk_data->wk, usecs_to_jiffies(delay));
fwrt->dump.monitor_only = monitor_only;
schedule_delayed_work(&fwrt->dump.wks[0].wk, usecs_to_jiffies(delay));
return 0; return 0;
} }
...@@ -2504,14 +2526,14 @@ IWL_EXPORT_SYMBOL(iwl_fw_start_dbg_conf); ...@@ -2504,14 +2526,14 @@ IWL_EXPORT_SYMBOL(iwl_fw_start_dbg_conf);
static void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt, u8 wk_idx) static void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt, u8 wk_idx)
{ {
struct iwl_fw_dbg_params params = {0}; struct iwl_fw_dbg_params params = {0};
struct iwl_fwrt_dump_data *dump_data =
&fwrt->dump.wks[wk_idx].dump_data;
if (!test_bit(wk_idx, &fwrt->dump.active_wks)) if (!test_bit(wk_idx, &fwrt->dump.active_wks))
return; return;
if (fwrt->ops && fwrt->ops->fw_running && if (!test_bit(STATUS_DEVICE_ENABLED, &fwrt->trans->status)) {
!fwrt->ops->fw_running(fwrt->ops_ctx)) { IWL_ERR(fwrt, "Device is not enabled - cannot dump error\n");
IWL_ERR(fwrt, "Firmware not running - cannot dump error\n");
iwl_fw_free_dump_desc(fwrt);
goto out; goto out;
} }
...@@ -2527,12 +2549,17 @@ static void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt, u8 wk_idx) ...@@ -2527,12 +2549,17 @@ static void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt, u8 wk_idx)
if (iwl_trans_dbg_ini_valid(fwrt->trans)) if (iwl_trans_dbg_ini_valid(fwrt->trans))
iwl_fw_error_ini_dump(fwrt, &fwrt->dump.wks[wk_idx].dump_data); iwl_fw_error_ini_dump(fwrt, &fwrt->dump.wks[wk_idx].dump_data);
else else
iwl_fw_error_dump(fwrt); iwl_fw_error_dump(fwrt, &fwrt->dump.wks[wk_idx].dump_data);
IWL_DEBUG_FW_INFO(fwrt, "WRT: Data collection done\n"); IWL_DEBUG_FW_INFO(fwrt, "WRT: Data collection done\n");
iwl_fw_dbg_stop_restart_recording(fwrt, &params, false); iwl_fw_dbg_stop_restart_recording(fwrt, &params, false);
out: out:
if (iwl_trans_dbg_ini_valid(fwrt->trans))
iwl_fw_error_dump_data_free(dump_data);
else
iwl_fw_free_dump_desc(fwrt, &dump_data->desc);
clear_bit(wk_idx, &fwrt->dump.active_wks); clear_bit(wk_idx, &fwrt->dump.active_wks);
} }
......
...@@ -98,17 +98,6 @@ struct iwl_fw_dbg_params { ...@@ -98,17 +98,6 @@ struct iwl_fw_dbg_params {
extern const struct iwl_fw_dump_desc iwl_dump_desc_assert; extern const struct iwl_fw_dump_desc iwl_dump_desc_assert;
static inline void iwl_fw_free_dump_desc(struct iwl_fw_runtime *fwrt)
{
if (fwrt->dump.desc != &iwl_dump_desc_assert)
kfree(fwrt->dump.desc);
fwrt->dump.desc = NULL;
fwrt->dump.lmac_err_id[0] = 0;
if (fwrt->smem_cfg.num_lmacs > 1)
fwrt->dump.lmac_err_id[1] = 0;
fwrt->dump.umac_err_id = 0;
}
int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt, int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt,
const struct iwl_fw_dump_desc *desc, const struct iwl_fw_dump_desc *desc,
bool monitor_only, unsigned int delay); bool monitor_only, unsigned int delay);
......
...@@ -98,8 +98,16 @@ struct iwl_fwrt_shared_mem_cfg { ...@@ -98,8 +98,16 @@ struct iwl_fwrt_shared_mem_cfg {
* @fw_pkt: packet received from FW * @fw_pkt: packet received from FW
*/ */
struct iwl_fwrt_dump_data { struct iwl_fwrt_dump_data {
union {
struct {
struct iwl_fw_ini_trigger_tlv *trig; struct iwl_fw_ini_trigger_tlv *trig;
struct iwl_rx_packet *fw_pkt; struct iwl_rx_packet *fw_pkt;
};
struct {
const struct iwl_fw_dump_desc *desc;
bool monitor_only;
};
};
}; };
/** /**
...@@ -162,8 +170,6 @@ struct iwl_fw_runtime { ...@@ -162,8 +170,6 @@ struct iwl_fw_runtime {
/* debug */ /* debug */
struct { struct {
const struct iwl_fw_dump_desc *desc;
bool monitor_only;
struct iwl_fwrt_wk_data wks[IWL_FW_RUNTIME_DUMP_WK_NUM]; struct iwl_fwrt_wk_data wks[IWL_FW_RUNTIME_DUMP_WK_NUM];
unsigned long active_wks; unsigned long active_wks;
......
...@@ -1264,7 +1264,6 @@ static void iwl_mvm_mac_stop(struct ieee80211_hw *hw) ...@@ -1264,7 +1264,6 @@ static void iwl_mvm_mac_stop(struct ieee80211_hw *hw)
cancel_delayed_work_sync(&mvm->cs_tx_unblock_dwork); cancel_delayed_work_sync(&mvm->cs_tx_unblock_dwork);
cancel_delayed_work_sync(&mvm->scan_timeout_dwork); cancel_delayed_work_sync(&mvm->scan_timeout_dwork);
iwl_fw_free_dump_desc(&mvm->fwrt);
mutex_lock(&mvm->mutex); mutex_lock(&mvm->mutex);
__iwl_mvm_mac_stop(mvm); __iwl_mvm_mac_stop(mvm);
......
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