From 4b49e34e580c87ea84f8f57fd04a1165219eb3fc Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Tue, 12 Feb 2019 10:11:10 +0200 Subject: iwlwifi: dbg_ini: separate between ini and legacy dump flows Separate between ini and legacy dump flows to allow adding ini triggers that are not supported in the legacy flow and to increase readabilty. iwl_fw_dbg_ini_collect function is now called with legacy trigger id and _iwl_fw_dbg_ini_collect is called with ini trigger id. Also make the actual dumping function static so that any dump collection will go through iwl_fw_dbg_collect_sync. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 189 ++++++++++++++++------------ 1 file changed, 111 insertions(+), 78 deletions(-) (limited to 'drivers/net/wireless/intel/iwlwifi/fw/dbg.c') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index f119c49cd39c..65252481a306 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -804,8 +804,8 @@ static void iwl_dump_paging(struct iwl_fw_runtime *fwrt, } static struct iwl_fw_error_dump_file * -_iwl_fw_error_dump(struct iwl_fw_runtime *fwrt, - struct iwl_fw_dump_ptrs *fw_error_dump) +iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt, + struct iwl_fw_dump_ptrs *fw_error_dump) { struct iwl_fw_error_dump_file *dump_file; struct iwl_fw_error_dump_data *dump_data; @@ -1791,16 +1791,13 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, } static struct iwl_fw_error_dump_file * -_iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt, - struct iwl_fw_dump_ptrs *fw_error_dump) +iwl_fw_error_ini_dump_file(struct iwl_fw_runtime *fwrt) { - int size, id = le32_to_cpu(fwrt->dump.desc->trig_desc.type); + int size; struct iwl_fw_error_dump_data *dump_data; struct iwl_fw_error_dump_file *dump_file; struct iwl_fw_ini_trigger *trigger; - - if (id == FW_DBG_TRIGGER_FW_ASSERT) - id = IWL_FW_TRIGGER_ID_FW_ASSERT; + enum iwl_fw_ini_trigger_id id = fwrt->dump.ini_trig_id; if (!iwl_fw_ini_trigger_on(fwrt, id)) return NULL; @@ -1817,8 +1814,6 @@ _iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt, if (!dump_file) return NULL; - fw_error_dump->fwrt_ptr = dump_file; - dump_file->barker = cpu_to_le32(IWL_FW_ERROR_DUMP_BARKER); dump_data = (void *)dump_file->data; dump_file->file_len = cpu_to_le32(size); @@ -1828,47 +1823,27 @@ _iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt, return dump_file; } -void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) +static void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) { - 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 scatterlist *sg_dump_data; u32 file_len; u32 dump_mask = fwrt->fw->dbg.dump_mask; - IWL_DEBUG_INFO(fwrt, "WRT dump start\n"); - - /* there's no point in fw dump if the bus is dead */ - if (test_bit(STATUS_TRANS_DEAD, &fwrt->trans->status)) { - IWL_ERR(fwrt, "Skip fw error dump since bus is dead\n"); - goto out; - } - - fw_error_dump = kzalloc(sizeof(*fw_error_dump), GFP_KERNEL); - if (!fw_error_dump) - goto out; - - if (fwrt->trans->ini_valid) - dump_file = _iwl_fw_error_ini_dump(fwrt, fw_error_dump); - else - dump_file = _iwl_fw_error_dump(fwrt, fw_error_dump); - - if (!dump_file) { - kfree(fw_error_dump); + dump_file = iwl_fw_error_dump_file(fwrt, &fw_error_dump); + if (!dump_file) goto out; - } if (!fwrt->trans->ini_valid && fwrt->dump.monitor_only) dump_mask &= IWL_FW_ERROR_DUMP_FW_MONITOR; - if (!fwrt->trans->ini_valid) - 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); file_len = le32_to_cpu(dump_file->file_len); - fw_error_dump->fwrt_len = file_len; - if (fw_error_dump->trans_ptr) { - file_len += fw_error_dump->trans_ptr->len; + fw_error_dump.fwrt_len = file_len; + + if (fw_error_dump.trans_ptr) { + file_len += fw_error_dump.trans_ptr->len; dump_file->file_len = cpu_to_le32(file_len); } @@ -1876,27 +1851,49 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) if (sg_dump_data) { sg_pcopy_from_buffer(sg_dump_data, sg_nents(sg_dump_data), - fw_error_dump->fwrt_ptr, - fw_error_dump->fwrt_len, 0); - if (fw_error_dump->trans_ptr) + fw_error_dump.fwrt_ptr, + fw_error_dump.fwrt_len, 0); + if (fw_error_dump.trans_ptr) sg_pcopy_from_buffer(sg_dump_data, sg_nents(sg_dump_data), - fw_error_dump->trans_ptr->data, - fw_error_dump->trans_ptr->len, - fw_error_dump->fwrt_len); + fw_error_dump.trans_ptr->data, + fw_error_dump.trans_ptr->len, + fw_error_dump.fwrt_len); dev_coredumpsg(fwrt->trans->dev, sg_dump_data, file_len, GFP_KERNEL); } - vfree(fw_error_dump->fwrt_ptr); - vfree(fw_error_dump->trans_ptr); - kfree(fw_error_dump); + vfree(fw_error_dump.fwrt_ptr); + vfree(fw_error_dump.trans_ptr); out: iwl_fw_free_dump_desc(fwrt); clear_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status); - IWL_DEBUG_INFO(fwrt, "WRT dump done\n"); } -IWL_EXPORT_SYMBOL(iwl_fw_error_dump); + +static void iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt) +{ + struct iwl_fw_error_dump_file *dump_file; + struct scatterlist *sg_dump_data; + u32 file_len; + + dump_file = iwl_fw_error_ini_dump_file(fwrt); + if (!dump_file) + goto out; + + file_len = le32_to_cpu(dump_file->file_len); + + sg_dump_data = alloc_sgtable(file_len); + if (sg_dump_data) { + sg_pcopy_from_buffer(sg_dump_data, sg_nents(sg_dump_data), + dump_file, file_len, 0); + dev_coredumpsg(fwrt->trans->dev, sg_dump_data, file_len, + GFP_KERNEL); + } + vfree(dump_file); +out: + fwrt->dump.ini_trig_id = IWL_FW_TRIGGER_ID_INVALID; + clear_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status); +} const struct iwl_fw_dump_desc iwl_dump_desc_assert = { .trig_desc = { @@ -1910,6 +1907,17 @@ int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt, bool monitor_only, unsigned int delay) { + u32 trig_type = le32_to_cpu(desc->trig_desc.type); + int ret; + + if (fwrt->trans->ini_valid) { + ret = iwl_fw_dbg_ini_collect(fwrt, trig_type); + if (!ret) + iwl_fw_free_dump_desc(fwrt); + + return ret; + } + if (test_and_set_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status)) return -EBUSY; @@ -1955,10 +1963,10 @@ int iwl_fw_dbg_error_collect(struct iwl_fw_runtime *fwrt, } IWL_EXPORT_SYMBOL(iwl_fw_dbg_error_collect); -int _iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, - enum iwl_fw_dbg_trigger trig, - const char *str, size_t len, - struct iwl_fw_dbg_trigger_tlv *trigger) +int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, + enum iwl_fw_dbg_trigger trig, + const char *str, size_t len, + struct iwl_fw_dbg_trigger_tlv *trigger) { struct iwl_fw_dump_desc *desc; unsigned int delay = 0; @@ -1995,50 +2003,64 @@ int _iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, return iwl_fw_dbg_collect_desc(fwrt, desc, monitor_only, delay); } -IWL_EXPORT_SYMBOL(_iwl_fw_dbg_collect); +IWL_EXPORT_SYMBOL(iwl_fw_dbg_collect); -int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, - u32 id, const char *str, size_t len) +int _iwl_fw_dbg_ini_collect(struct iwl_fw_runtime *fwrt, + enum iwl_fw_ini_trigger_id id) { - struct iwl_fw_dump_desc *desc; struct iwl_fw_ini_active_triggers *active; u32 occur, delay; - if (!fwrt->trans->ini_valid) - return _iwl_fw_dbg_collect(fwrt, id, str, len, NULL); + if (WARN_ON(!iwl_fw_ini_trigger_on(fwrt, id))) + return -EINVAL; - if (id == FW_DBG_TRIGGER_USER) - id = IWL_FW_TRIGGER_ID_USER_TRIGGER; + if (test_and_set_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status)) + return -EBUSY; active = &fwrt->dump.active_trigs[id]; - - if (WARN_ON(!active->active)) - return -EINVAL; - delay = le32_to_cpu(active->trig->dump_delay); occur = le32_to_cpu(active->trig->occurrences); if (!occur) return 0; + active->trig->occurrences = cpu_to_le32(--occur); + if (le32_to_cpu(active->trig->force_restart)) { IWL_WARN(fwrt, "Force restart: trigger %d fired.\n", id); iwl_force_nmi(fwrt->trans); return 0; } - desc = kzalloc(sizeof(*desc) + len, GFP_ATOMIC); - if (!desc) - return -ENOMEM; + fwrt->dump.ini_trig_id = id; - active->trig->occurrences = cpu_to_le32(--occur); + IWL_WARN(fwrt, "Collecting data: ini trigger %d fired.\n", id); - desc->len = len; - desc->trig_desc.type = cpu_to_le32(id); - memcpy(desc->trig_desc.data, str, len); + schedule_delayed_work(&fwrt->dump.wk, usecs_to_jiffies(delay)); - return iwl_fw_dbg_collect_desc(fwrt, desc, true, delay); + return 0; } -IWL_EXPORT_SYMBOL(iwl_fw_dbg_collect); +IWL_EXPORT_SYMBOL(_iwl_fw_dbg_ini_collect); + +int iwl_fw_dbg_ini_collect(struct iwl_fw_runtime *fwrt, u32 legacy_trigger_id) +{ + int id; + + switch (legacy_trigger_id) { + case FW_DBG_TRIGGER_FW_ASSERT: + case FW_DBG_TRIGGER_ALIVE_TIMEOUT: + case FW_DBG_TRIGGER_DRIVER: + id = IWL_FW_TRIGGER_ID_FW_ASSERT; + break; + case FW_DBG_TRIGGER_USER: + id = IWL_FW_TRIGGER_ID_USER_TRIGGER; + break; + default: + return -EIO; + } + + return _iwl_fw_dbg_ini_collect(fwrt, id); +} +IWL_EXPORT_SYMBOL(iwl_fw_dbg_ini_collect); int iwl_fw_dbg_collect_trig(struct iwl_fw_runtime *fwrt, struct iwl_fw_dbg_trigger_tlv *trigger, @@ -2066,8 +2088,8 @@ int iwl_fw_dbg_collect_trig(struct iwl_fw_runtime *fwrt, len = strlen(buf) + 1; } - ret = _iwl_fw_dbg_collect(fwrt, le32_to_cpu(trigger->id), buf, len, - trigger); + ret = iwl_fw_dbg_collect(fwrt, le32_to_cpu(trigger->id), buf, len, + trigger); if (ret) return ret; @@ -2141,9 +2163,20 @@ void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt) return; } + /* there's no point in fw dump if the bus is dead */ + if (test_bit(STATUS_TRANS_DEAD, &fwrt->trans->status)) { + IWL_ERR(fwrt, "Skip fw error dump since bus is dead\n"); + return; + } + iwl_fw_dbg_stop_recording(fwrt, ¶ms); - iwl_fw_error_dump(fwrt); + IWL_DEBUG_INFO(fwrt, "WRT dump start\n"); + if (fwrt->trans->ini_valid) + iwl_fw_error_ini_dump(fwrt); + else + iwl_fw_error_dump(fwrt); + IWL_DEBUG_INFO(fwrt, "WRT dump done\n"); /* start recording again if the firmware is not crashed */ if (!test_bit(STATUS_FW_ERROR, &fwrt->trans->status) && -- cgit v1.2.3-59-g8ed1b From bfa34c332964e90f6222b2ff665990484c22f6f2 Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Mon, 11 Feb 2019 12:12:08 +0200 Subject: iwlwifi: dbg_ini: enforce always on domain checking Enforce domain checking before sending host commands and collecting memory regions. Currently the driver supports always on domain only. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/net/wireless/intel/iwlwifi/fw/dbg.c') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 65252481a306..caf860b7afff 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1711,6 +1711,10 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, if (!reg) continue; + /* currently the driver supports always on domain only */ + if (le32_to_cpu(reg->domain) != IWL_FW_INI_DBG_DOMAIN_ALWAYS_ON) + continue; + type = le32_to_cpu(reg->region_type); switch (type) { case IWL_FW_INI_REGION_DEVICE_MEMORY: @@ -2320,6 +2324,10 @@ static void iwl_fw_dbg_send_hcmd(struct iwl_fw_runtime *fwrt, .data = { data->data, }, }; + /* currently the driver supports always on domain only */ + if (le32_to_cpu(hcmd_tlv->domain) != IWL_FW_INI_DBG_DOMAIN_ALWAYS_ON) + return; + iwl_trans_send_cmd(fwrt->trans, &hcmd); } -- cgit v1.2.3-59-g8ed1b From 4bdb2676d8fdd48fadbb59a945792c0e1811c67e Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Sun, 17 Feb 2019 17:28:04 +0200 Subject: iwlwifi: dbg_ini: fix iwl_dump_ini_dev_mem_iter memory base address The driver is using range->start_addr before assigning it a value. Set value into range->start_addr and then use it. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless/intel/iwlwifi/fw/dbg.c') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index caf860b7afff..4beec863197e 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1090,10 +1090,10 @@ static int iwl_dump_ini_dev_mem_iter(struct iwl_fw_runtime *fwrt, void *range_ptr, int idx) { struct iwl_fw_ini_error_dump_range *range = range_ptr; - u32 addr = le32_to_cpu(range->start_addr); - u32 offset = le32_to_cpu(reg->offset); + u32 addr, offset = le32_to_cpu(reg->offset); range->start_addr = reg->start_addr[idx]; + addr = le32_to_cpu(range->start_addr); range->range_data_size = reg->internal.range_data_size; iwl_trans_read_mem_bytes(fwrt->trans, addr + offset, range->data, le32_to_cpu(reg->internal.range_data_size)); -- cgit v1.2.3-59-g8ed1b From 9802162f98b4e587bd5dbb11c352c04e204bf9f0 Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Sun, 17 Feb 2019 17:37:27 +0200 Subject: iwlwifi: dbg_ini: add memory offset to the base address of a memory region Add the offset to the base address of a memory region to show the actual addresses being read. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) (limited to 'drivers/net/wireless/intel/iwlwifi/fw/dbg.c') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 4beec863197e..78bca27b7809 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1049,14 +1049,14 @@ static int iwl_dump_ini_prph_iter(struct iwl_fw_runtime *fwrt, { struct iwl_fw_ini_error_dump_range *range = range_ptr; __le32 *val = range->data; - u32 addr, prph_val, offset = le32_to_cpu(reg->offset); + u32 prph_val; + u32 addr = le32_to_cpu(reg->start_addr[idx]) + le32_to_cpu(reg->offset); int i; - range->start_addr = reg->start_addr[idx]; + range->start_addr = cpu_to_le32(addr); range->range_data_size = reg->internal.range_data_size; for (i = 0; i < le32_to_cpu(reg->internal.range_data_size); i += 4) { - addr = le32_to_cpu(range->start_addr) + i; - prph_val = iwl_read_prph(fwrt->trans, addr + offset); + prph_val = iwl_read_prph(fwrt->trans, addr + i); if (prph_val == 0x5a5a5a5a) return -EBUSY; *val++ = cpu_to_le32(prph_val); @@ -1071,16 +1071,13 @@ static int iwl_dump_ini_csr_iter(struct iwl_fw_runtime *fwrt, { struct iwl_fw_ini_error_dump_range *range = range_ptr; __le32 *val = range->data; - u32 addr, offset = le32_to_cpu(reg->offset); + u32 addr = le32_to_cpu(reg->start_addr[idx]) + le32_to_cpu(reg->offset); int i; - range->start_addr = reg->start_addr[idx]; + range->start_addr = cpu_to_le32(addr); range->range_data_size = reg->internal.range_data_size; - for (i = 0; i < le32_to_cpu(reg->internal.range_data_size); i += 4) { - addr = le32_to_cpu(range->start_addr) + i; - *val++ = cpu_to_le32(iwl_trans_read32(fwrt->trans, - addr + offset)); - } + for (i = 0; i < le32_to_cpu(reg->internal.range_data_size); i += 4) + *val++ = cpu_to_le32(iwl_trans_read32(fwrt->trans, addr + i)); return sizeof(*range) + le32_to_cpu(range->range_data_size); } @@ -1090,12 +1087,11 @@ static int iwl_dump_ini_dev_mem_iter(struct iwl_fw_runtime *fwrt, void *range_ptr, int idx) { struct iwl_fw_ini_error_dump_range *range = range_ptr; - u32 addr, offset = le32_to_cpu(reg->offset); + u32 addr = le32_to_cpu(reg->start_addr[idx]) + le32_to_cpu(reg->offset); - range->start_addr = reg->start_addr[idx]; - addr = le32_to_cpu(range->start_addr); + range->start_addr = cpu_to_le32(addr); range->range_data_size = reg->internal.range_data_size; - iwl_trans_read_mem_bytes(fwrt->trans, addr + offset, range->data, + iwl_trans_read_mem_bytes(fwrt->trans, addr, range->data, le32_to_cpu(reg->internal.range_data_size)); return sizeof(*range) + le32_to_cpu(range->range_data_size); -- cgit v1.2.3-59-g8ed1b From 990ffe3e81962ff2428ca3d41621dfdd774c8d57 Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Sun, 17 Feb 2019 12:16:53 +0200 Subject: iwlwifi: dbg_ini: add version to dump header Add version to dump header to allow future changes of the dump struct, once the ini debug flow becomes operational, without breaking backwards compatibility. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 5 +++++ drivers/net/wireless/intel/iwlwifi/fw/error-dump.h | 6 ++++++ 2 files changed, 11 insertions(+) (limited to 'drivers/net/wireless/intel/iwlwifi/fw/dbg.c') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 78bca27b7809..81ce8a46ff11 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1380,6 +1380,8 @@ static void *iwl_dump_ini_mem_fill_header(struct iwl_fw_runtime *fwrt, { struct iwl_fw_ini_error_dump *dump = data; + dump->header.version = cpu_to_le32(IWL_INI_DUMP_MEM_VER); + return dump->ranges; } @@ -1402,6 +1404,7 @@ static void MON_BUFF_CYCLE_CNT_VER2); iwl_trans_release_nic_access(fwrt->trans, &flags); + mon_dump->header.version = cpu_to_le32(IWL_INI_DUMP_MONITOR_VER); mon_dump->write_ptr = cpu_to_le32(write_ptr); mon_dump->cycle_cnt = cpu_to_le32(cycle_cnt); @@ -1414,6 +1417,8 @@ static void *iwl_dump_ini_fifo_fill_header(struct iwl_fw_runtime *fwrt, { struct iwl_fw_ini_fifo_error_dump *dump = data; + dump->header.version = cpu_to_le32(IWL_INI_DUMP_FIFO_VER); + return dump->ranges; } diff --git a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h index ea5513050b56..a2339021153f 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h @@ -278,6 +278,10 @@ struct iwl_fw_error_dump_mem { u8 data[]; }; +#define IWL_INI_DUMP_MEM_VER 1 +#define IWL_INI_DUMP_MONITOR_VER 1 +#define IWL_INI_DUMP_FIFO_VER 1 + /** * struct iwl_fw_ini_error_dump_range - range of memory * @start_addr: the start address of this range @@ -292,11 +296,13 @@ struct iwl_fw_ini_error_dump_range { /** * struct iwl_fw_ini_error_dump_header - ini region dump header + * @version: dump version * @num_of_ranges: number of ranges in this region * @name_len: number of bytes allocated to the name string of this region * @name: name of the region */ struct iwl_fw_ini_error_dump_header { + __le32 version; __le32 num_of_ranges; __le32 name_len; u8 name[IWL_FW_INI_MAX_NAME]; -- cgit v1.2.3-59-g8ed1b From 1cdb4d8f2a4b682a5cd9f0138098cddae55dddc3 Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Sun, 17 Feb 2019 13:16:13 +0200 Subject: iwlwifi: dbg_ini: add region id to the region dump Add the region id of the collected memory to the header of the memory region. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 1 + drivers/net/wireless/intel/iwlwifi/fw/error-dump.h | 2 ++ 2 files changed, 3 insertions(+) (limited to 'drivers/net/wireless/intel/iwlwifi/fw/dbg.c') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 81ce8a46ff11..a014fb729f48 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1606,6 +1606,7 @@ iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt, (*data)->type = cpu_to_le32(type | INI_DUMP_BIT); (*data)->len = cpu_to_le32(ops->get_size(fwrt, reg)); + header->region_id = reg->region_id; header->num_of_ranges = cpu_to_le32(num_of_ranges); header->name_len = cpu_to_le32(min_t(int, IWL_FW_INI_MAX_NAME, le32_to_cpu(reg->name_len))); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h index a2339021153f..ac2589bfedb2 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h @@ -297,12 +297,14 @@ struct iwl_fw_ini_error_dump_range { /** * struct iwl_fw_ini_error_dump_header - ini region dump header * @version: dump version + * @region_id: id of the region * @num_of_ranges: number of ranges in this region * @name_len: number of bytes allocated to the name string of this region * @name: name of the region */ struct iwl_fw_ini_error_dump_header { __le32 version; + __le32 region_id; __le32 num_of_ranges; __le32 name_len; u8 name[IWL_FW_INI_MAX_NAME]; -- cgit v1.2.3-59-g8ed1b From 60eeaf572f3ed00e1ac01bfa43a70369eb32e40d Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Sun, 17 Feb 2019 14:08:50 +0200 Subject: iwlwifi: dbg_ini: add registers addresses in fifo dump Add to the fifo dump the registers addresses. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 46 +++++++++++++++------- drivers/net/wireless/intel/iwlwifi/fw/error-dump.h | 15 ++++++- 2 files changed, 45 insertions(+), 16 deletions(-) (limited to 'drivers/net/wireless/intel/iwlwifi/fw/dbg.c') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index a014fb729f48..a1d6765498a8 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1224,10 +1224,11 @@ static int iwl_dump_ini_txf_iter(struct iwl_fw_runtime *fwrt, { struct iwl_fw_ini_fifo_error_dump_range *range = range_ptr; struct iwl_ini_txf_iter_data *iter; + struct iwl_fw_ini_error_dump_register *reg_dump = (void *)range->data; u32 offs = le32_to_cpu(reg->offset), addr; u32 registers_size = - le32_to_cpu(reg->fifos.num_of_registers) * sizeof(__le32); - __le32 *val = range->data; + le32_to_cpu(reg->fifos.num_of_registers) * sizeof(*reg_dump); + __le32 *data; unsigned long flags; int i; @@ -1245,11 +1246,18 @@ static int iwl_dump_ini_txf_iter(struct iwl_fw_runtime *fwrt, iwl_write_prph_no_grab(fwrt->trans, TXF_LARC_NUM + offs, iter->fifo); - /* read txf registers */ + /* + * read txf registers. for each register, write to the dump the + * register address and its value + */ for (i = 0; i < le32_to_cpu(reg->fifos.num_of_registers); i++) { addr = le32_to_cpu(reg->start_addr[i]) + offs; - *val++ = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, addr)); + reg_dump->addr = cpu_to_le32(addr); + reg_dump->data = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, + addr)); + + reg_dump++; } if (reg->fifos.header_only) { @@ -1266,8 +1274,9 @@ static int iwl_dump_ini_txf_iter(struct iwl_fw_runtime *fwrt, /* Read FIFO */ addr = TXF_READ_MODIFY_DATA + offs; - for (i = 0; i < iter->fifo_size; i += sizeof(__le32)) - *val++ = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, addr)); + data = (void *)reg_dump; + for (i = 0; i < iter->fifo_size; i += sizeof(*data)) + *data++ = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, addr)); out: iwl_trans_release_nic_access(fwrt->trans, &flags); @@ -1323,10 +1332,11 @@ static int iwl_dump_ini_rxf_iter(struct iwl_fw_runtime *fwrt, { struct iwl_fw_ini_fifo_error_dump_range *range = range_ptr; struct iwl_ini_rxf_data rxf_data; + struct iwl_fw_ini_error_dump_register *reg_dump = (void *)range->data; u32 offs = le32_to_cpu(reg->offset), addr; u32 registers_size = - le32_to_cpu(reg->fifos.num_of_registers) * sizeof(__le32); - __le32 *val = range->data; + le32_to_cpu(reg->fifos.num_of_registers) * sizeof(*reg_dump); + __le32 *data; unsigned long flags; int i; @@ -1343,11 +1353,18 @@ static int iwl_dump_ini_rxf_iter(struct iwl_fw_runtime *fwrt, range->num_of_registers = reg->fifos.num_of_registers; range->range_data_size = cpu_to_le32(rxf_data.size + registers_size); - /* read rxf registers */ + /* + * read rxf registers. for each register, write to the dump the + * register address and its value + */ for (i = 0; i < le32_to_cpu(reg->fifos.num_of_registers); i++) { addr = le32_to_cpu(reg->start_addr[i]) + offs; - *val++ = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, addr)); + reg_dump->addr = cpu_to_le32(addr); + reg_dump->data = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, + addr)); + + reg_dump++; } if (reg->fifos.header_only) { @@ -1365,8 +1382,9 @@ static int iwl_dump_ini_rxf_iter(struct iwl_fw_runtime *fwrt, /* Read FIFO */ addr = RXF_FIFO_RD_FENCE_INC + offs; - for (i = 0; i < rxf_data.size; i += sizeof(__le32)) - *val++ = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, addr)); + data = (void *)reg_dump; + for (i = 0; i < rxf_data.size; i += sizeof(*data)) + *data++ = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, addr)); out: iwl_trans_release_nic_access(fwrt->trans, &flags); @@ -1525,7 +1543,7 @@ static u32 iwl_dump_ini_txf_get_size(struct iwl_fw_runtime *fwrt, void *fifo_iter = fwrt->dump.fifo_iter; u32 size = 0; u32 fifo_hdr = sizeof(struct iwl_fw_ini_fifo_error_dump_range) + - le32_to_cpu(reg->fifos.num_of_registers) * sizeof(__le32); + le32_to_cpu(reg->fifos.num_of_registers) * sizeof(__le32) * 2; fwrt->dump.fifo_iter = &iter; while (iwl_ini_txf_iter(fwrt, reg)) { @@ -1548,7 +1566,7 @@ static u32 iwl_dump_ini_rxf_get_size(struct iwl_fw_runtime *fwrt, struct iwl_ini_rxf_data rx_data; u32 size = sizeof(struct iwl_fw_ini_fifo_error_dump) + sizeof(struct iwl_fw_ini_fifo_error_dump_range) + - le32_to_cpu(reg->fifos.num_of_registers) * sizeof(__le32); + le32_to_cpu(reg->fifos.num_of_registers) * sizeof(__le32) * 2; if (reg->fifos.header_only) return size; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h index ac2589bfedb2..d6c67960dccd 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h @@ -323,13 +323,24 @@ struct iwl_fw_ini_error_dump { /* This bit is used to differentiate between lmac and umac rxf */ #define IWL_RXF_UMAC_BIT BIT(31) +/** + * struct iwl_fw_ini_error_dump_register - ini register dump + * @addr: address of the register + * @data: data of the register + */ +struct iwl_fw_ini_error_dump_register { + __le32 addr; + __le32 data; +} __packed; + /** * struct iwl_fw_ini_fifo_error_dump_range - ini fifo range dump * @fifo_num: the fifo num. In case of rxf and umac rxf, set BIT(31) to * distinguish between lmac and umac * @num_of_registers: num of registers to dump, dword size each - * @range_data_size: the size of the registers and fifo data - * @data: fifo data + * @range_data_size: the size of the data + * @data: consist of + * num_of_registers * (register address + register value) + fifo data */ struct iwl_fw_ini_fifo_error_dump_range { __le32 fifo_num; -- cgit v1.2.3-59-g8ed1b From f0e1e1c20d5fc9ff6d94193100ab90d5945a6d08 Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Sun, 17 Feb 2019 14:13:12 +0200 Subject: iwlwifi: dbg_ini: change memory range base address to u64 AX210 devices will use u64 for the base address to the DRAM monitor buffer. To support this, change the structure for all device families so both address sizes fit. Also move range_data_size to the top of the struct to ease the parsing of the memory range. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 12 ++++++------ drivers/net/wireless/intel/iwlwifi/fw/error-dump.h | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/net/wireless/intel/iwlwifi/fw/dbg.c') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index a1d6765498a8..1b6a850940cf 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1053,7 +1053,7 @@ static int iwl_dump_ini_prph_iter(struct iwl_fw_runtime *fwrt, u32 addr = le32_to_cpu(reg->start_addr[idx]) + le32_to_cpu(reg->offset); int i; - range->start_addr = cpu_to_le32(addr); + range->start_addr = cpu_to_le64(addr); range->range_data_size = reg->internal.range_data_size; for (i = 0; i < le32_to_cpu(reg->internal.range_data_size); i += 4) { prph_val = iwl_read_prph(fwrt->trans, addr + i); @@ -1074,7 +1074,7 @@ static int iwl_dump_ini_csr_iter(struct iwl_fw_runtime *fwrt, u32 addr = le32_to_cpu(reg->start_addr[idx]) + le32_to_cpu(reg->offset); int i; - range->start_addr = cpu_to_le32(addr); + range->start_addr = cpu_to_le64(addr); range->range_data_size = reg->internal.range_data_size; for (i = 0; i < le32_to_cpu(reg->internal.range_data_size); i += 4) *val++ = cpu_to_le32(iwl_trans_read32(fwrt->trans, addr + i)); @@ -1089,7 +1089,7 @@ static int iwl_dump_ini_dev_mem_iter(struct iwl_fw_runtime *fwrt, struct iwl_fw_ini_error_dump_range *range = range_ptr; u32 addr = le32_to_cpu(reg->start_addr[idx]) + le32_to_cpu(reg->offset); - range->start_addr = cpu_to_le32(addr); + range->start_addr = cpu_to_le64(addr); range->range_data_size = reg->internal.range_data_size; iwl_trans_read_mem_bytes(fwrt->trans, addr, range->data, le32_to_cpu(reg->internal.range_data_size)); @@ -1105,7 +1105,7 @@ iwl_dump_ini_paging_gen2_iter(struct iwl_fw_runtime *fwrt, struct iwl_fw_ini_error_dump_range *range = range_ptr; u32 page_size = fwrt->trans->init_dram.paging[idx].size; - range->start_addr = cpu_to_le32(idx); + range->start_addr = cpu_to_le64(idx); range->range_data_size = cpu_to_le32(page_size); memcpy(range->data, fwrt->trans->init_dram.paging[idx].block, page_size); @@ -1125,7 +1125,7 @@ static int iwl_dump_ini_paging_iter(struct iwl_fw_runtime *fwrt, dma_addr_t addr = fwrt->fw_paging_db[idx].fw_paging_phys; u32 page_size = fwrt->fw_paging_db[idx].fw_paging_size; - range->start_addr = cpu_to_le32(idx); + range->start_addr = cpu_to_le64(idx); range->range_data_size = cpu_to_le32(page_size); dma_sync_single_for_cpu(fwrt->trans->dev, addr, page_size, DMA_BIDIRECTIONAL); @@ -1148,7 +1148,7 @@ iwl_dump_ini_mon_dram_iter(struct iwl_fw_runtime *fwrt, if (start_addr == 0x5a5a5a5a) return -EBUSY; - range->start_addr = cpu_to_le32(start_addr); + range->start_addr = cpu_to_le64(start_addr); range->range_data_size = cpu_to_le32(fwrt->trans->fw_mon[idx].size); memcpy(range->data, fwrt->trans->fw_mon[idx].block, diff --git a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h index d6c67960dccd..0df72a99bf05 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h @@ -284,13 +284,13 @@ struct iwl_fw_error_dump_mem { /** * struct iwl_fw_ini_error_dump_range - range of memory - * @start_addr: the start address of this range * @range_data_size: the size of this range, in bytes + * @start_addr: the start address of this range * @data: the actual memory */ struct iwl_fw_ini_error_dump_range { - __le32 start_addr; __le32 range_data_size; + __le64 start_addr; __le32 data[]; } __packed; -- cgit v1.2.3-59-g8ed1b From d63916aeba5768a9aedcd3bfddf32ffff4dae076 Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Sun, 17 Feb 2019 14:46:22 +0200 Subject: iwlwifi: dbg_ini: fix the dram monitor header size Add sizeof(struct iwl_fw_ini_error_dump_range) to the header of the dram monitor. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless/intel/iwlwifi/fw/dbg.c') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 1b6a850940cf..6f681060245e 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1528,7 +1528,8 @@ static u32 iwl_dump_ini_paging_get_size(struct iwl_fw_runtime *fwrt, static u32 iwl_dump_ini_mon_dram_get_size(struct iwl_fw_runtime *fwrt, struct iwl_fw_ini_region_cfg *reg) { - u32 size = sizeof(struct iwl_fw_ini_monitor_dram_dump); + u32 size = sizeof(struct iwl_fw_ini_monitor_dram_dump) + + sizeof(struct iwl_fw_ini_error_dump_range); if (fwrt->trans->num_blocks) size += fwrt->trans->fw_mon[0].size; -- cgit v1.2.3-59-g8ed1b From 4c704534c38fb1125b111fd4ffc8a36d79dd7339 Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Sun, 17 Feb 2019 17:07:53 +0200 Subject: iwlwifi: dbg_ini: add monitor header to smem monitor Add write pointer and cycle count registers to smem monitor header. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/cfg/22000.c | 6 +- drivers/net/wireless/intel/iwlwifi/cfg/9000.c | 10 +- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 101 +++++++++++++++++---- drivers/net/wireless/intel/iwlwifi/fw/error-dump.h | 6 +- drivers/net/wireless/intel/iwlwifi/iwl-config.h | 4 + 5 files changed, 104 insertions(+), 23 deletions(-) (limited to 'drivers/net/wireless/intel/iwlwifi/fw/dbg.c') diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index 32c989eda3c4..33c95663914d 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -180,7 +180,11 @@ static const struct iwl_ht_params iwl_22000_ht_params = { .dbgc_supported = true, \ .min_umac_error_event_table = 0x400000, \ .d3_debug_data_base_addr = 0x401000, \ - .d3_debug_data_length = 60 * 1024 + .d3_debug_data_length = 60 * 1024, \ + .fw_mon_smem_write_ptr_addr = 0xa0c16c, \ + .fw_mon_smem_write_ptr_msk = 0xfffff, \ + .fw_mon_smem_cycle_cnt_ptr_addr = 0xa0c174, \ + .fw_mon_smem_cycle_cnt_ptr_msk = 0xfffff #define IWL_DEVICE_AX200_COMMON \ IWL_DEVICE_22000_COMMON, \ diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c index 3225b64eb845..41bdd0eaf62c 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c @@ -6,7 +6,7 @@ * GPL LICENSE SUMMARY * * Copyright(c) 2015-2017 Intel Deutschland GmbH - * Copyright (C) 2018 Intel Corporation + * Copyright (C) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -20,7 +20,7 @@ * BSD LICENSE * * Copyright(c) 2015-2017 Intel Deutschland GmbH - * Copyright (C) 2018 Intel Corporation + * Copyright (C) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -148,7 +148,11 @@ static const struct iwl_tt_params iwl9000_tt_params = { .d3_debug_data_length = 92 * 1024, \ .ht_params = &iwl9000_ht_params, \ .nvm_ver = IWL9000_NVM_VERSION, \ - .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K + .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \ + .fw_mon_smem_write_ptr_addr = 0xa0476c, \ + .fw_mon_smem_write_ptr_msk = 0xfffff, \ + .fw_mon_smem_cycle_cnt_ptr_addr = 0xa04774, \ + .fw_mon_smem_cycle_cnt_ptr_msk = 0xfffff const struct iwl_cfg iwl9160_2ac_cfg = { diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 6f681060245e..87da6125683a 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1404,29 +1404,80 @@ static void *iwl_dump_ini_mem_fill_header(struct iwl_fw_runtime *fwrt, } static void -*iwl_dump_ini_mon_dram_fill_header(struct iwl_fw_runtime *fwrt, - struct iwl_fw_ini_region_cfg *reg, - void *data) +*iwl_dump_ini_mon_fill_header(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_region_cfg *reg, + struct iwl_fw_ini_monitor_dump *data, + u32 write_ptr_addr, u32 write_ptr_msk, + u32 cycle_cnt_addr, u32 cycle_cnt_msk) { - struct iwl_fw_ini_monitor_dram_dump *mon_dump = (void *)data; u32 write_ptr, cycle_cnt; unsigned long flags; if (!iwl_trans_grab_nic_access(fwrt->trans, &flags)) { - IWL_ERR(fwrt, "Failed to get DRAM monitor header\n"); + IWL_ERR(fwrt, "Failed to get monitor header\n"); return NULL; } - write_ptr = iwl_read_umac_prph_no_grab(fwrt->trans, - MON_BUFF_WRPTR_VER2); - cycle_cnt = iwl_read_umac_prph_no_grab(fwrt->trans, - MON_BUFF_CYCLE_CNT_VER2); + + write_ptr = iwl_read_prph_no_grab(fwrt->trans, write_ptr_addr); + cycle_cnt = iwl_read_prph_no_grab(fwrt->trans, cycle_cnt_addr); + iwl_trans_release_nic_access(fwrt->trans, &flags); - mon_dump->header.version = cpu_to_le32(IWL_INI_DUMP_MONITOR_VER); - mon_dump->write_ptr = cpu_to_le32(write_ptr); - mon_dump->cycle_cnt = cpu_to_le32(cycle_cnt); + data->header.version = cpu_to_le32(IWL_INI_DUMP_MONITOR_VER); + data->write_ptr = cpu_to_le32(write_ptr & write_ptr_msk); + data->cycle_cnt = cpu_to_le32(cycle_cnt & cycle_cnt_msk); + + return data->ranges; +} + +static void +*iwl_dump_ini_mon_dram_fill_header(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_region_cfg *reg, + void *data) +{ + struct iwl_fw_ini_monitor_dump *mon_dump = (void *)data; + u32 write_ptr_addr, write_ptr_msk, cycle_cnt_addr, cycle_cnt_msk; + + switch (fwrt->trans->cfg->device_family) { + case IWL_DEVICE_FAMILY_9000: + case IWL_DEVICE_FAMILY_22000: + write_ptr_addr = MON_BUFF_WRPTR_VER2; + write_ptr_msk = -1; + cycle_cnt_addr = MON_BUFF_CYCLE_CNT_VER2; + cycle_cnt_msk = -1; + break; + default: + IWL_ERR(fwrt, "Unsupported device family %d\n", + fwrt->trans->cfg->device_family); + return NULL; + } + + return iwl_dump_ini_mon_fill_header(fwrt, reg, mon_dump, write_ptr_addr, + write_ptr_msk, cycle_cnt_addr, + cycle_cnt_msk); +} + +static void +*iwl_dump_ini_mon_smem_fill_header(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_region_cfg *reg, + void *data) +{ + struct iwl_fw_ini_monitor_dump *mon_dump = (void *)data; + const struct iwl_cfg *cfg = fwrt->trans->cfg; + + if (fwrt->trans->cfg->device_family != IWL_DEVICE_FAMILY_9000 && + fwrt->trans->cfg->device_family != IWL_DEVICE_FAMILY_22000) { + IWL_ERR(fwrt, "Unsupported device family %d\n", + fwrt->trans->cfg->device_family); + return NULL; + } + + return iwl_dump_ini_mon_fill_header(fwrt, reg, mon_dump, + cfg->fw_mon_smem_write_ptr_addr, + cfg->fw_mon_smem_write_ptr_msk, + cfg->fw_mon_smem_cycle_cnt_ptr_addr, + cfg->fw_mon_smem_cycle_cnt_ptr_msk); - return mon_dump->ranges; } static void *iwl_dump_ini_fifo_fill_header(struct iwl_fw_runtime *fwrt, @@ -1528,7 +1579,7 @@ static u32 iwl_dump_ini_paging_get_size(struct iwl_fw_runtime *fwrt, static u32 iwl_dump_ini_mon_dram_get_size(struct iwl_fw_runtime *fwrt, struct iwl_fw_ini_region_cfg *reg) { - u32 size = sizeof(struct iwl_fw_ini_monitor_dram_dump) + + u32 size = sizeof(struct iwl_fw_ini_monitor_dump) + sizeof(struct iwl_fw_ini_error_dump_range); if (fwrt->trans->num_blocks) @@ -1537,6 +1588,15 @@ static u32 iwl_dump_ini_mon_dram_get_size(struct iwl_fw_runtime *fwrt, return size; } +static u32 iwl_dump_ini_mon_smem_get_size(struct iwl_fw_runtime *fwrt, + struct iwl_fw_ini_region_cfg *reg) +{ + return sizeof(struct iwl_fw_ini_monitor_dump) + + iwl_dump_ini_mem_ranges(fwrt, reg) * + (sizeof(struct iwl_fw_ini_error_dump_range) + + le32_to_cpu(reg->internal.range_data_size)); +} + static u32 iwl_dump_ini_txf_get_size(struct iwl_fw_runtime *fwrt, struct iwl_fw_ini_region_cfg *reg) { @@ -1677,7 +1737,6 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, case IWL_FW_INI_REGION_PERIPHERY_MAC: case IWL_FW_INI_REGION_PERIPHERY_PHY: case IWL_FW_INI_REGION_PERIPHERY_AUX: - case IWL_FW_INI_REGION_INTERNAL_BUFFER: case IWL_FW_INI_REGION_CSR: size += hdr_len + iwl_dump_ini_mem_get_size(fwrt, reg); break; @@ -1703,6 +1762,10 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, size += hdr_len + iwl_dump_ini_mon_dram_get_size(fwrt, reg); break; + case IWL_FW_INI_REGION_INTERNAL_BUFFER: + size += hdr_len + + iwl_dump_ini_mon_smem_get_size(fwrt, reg); + break; case IWL_FW_INI_REGION_DRAM_IMR: /* Undefined yet */ default: @@ -1739,7 +1802,6 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, type = le32_to_cpu(reg->region_type); switch (type) { case IWL_FW_INI_REGION_DEVICE_MEMORY: - case IWL_FW_INI_REGION_INTERNAL_BUFFER: ops.get_num_of_ranges = iwl_dump_ini_mem_ranges; ops.get_size = iwl_dump_ini_mem_get_size; ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header; @@ -1762,6 +1824,13 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, ops.fill_range = iwl_dump_ini_mon_dram_iter; iwl_dump_ini_mem(fwrt, type, data, reg, &ops); break; + case IWL_FW_INI_REGION_INTERNAL_BUFFER: + ops.get_num_of_ranges = iwl_dump_ini_mem_ranges; + ops.get_size = iwl_dump_ini_mon_smem_get_size; + ops.fill_mem_hdr = iwl_dump_ini_mon_smem_fill_header; + ops.fill_range = iwl_dump_ini_dev_mem_iter; + iwl_dump_ini_mem(fwrt, type, data, reg, &ops); + break; case IWL_FW_INI_REGION_PAGING: { ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header; if (iwl_fw_dbg_is_paging_enabled(fwrt)) { diff --git a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h index 0df72a99bf05..260097c75427 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h @@ -374,13 +374,13 @@ struct iwl_fw_error_dump_rb { }; /** - * struct iwl_fw_ini_monitor_dram_dump - ini dram monitor dump + * struct iwl_fw_ini_monitor_dump - ini monitor dump * @header - header of the region - * @write_ptr - write pointer position in the dram + * @write_ptr - write pointer position in the buffer * @cycle_cnt - cycles count * @ranges - the memory ranges of this this region */ -struct iwl_fw_ini_monitor_dram_dump { +struct iwl_fw_ini_monitor_dump { struct iwl_fw_ini_error_dump_header header; __le32 write_ptr; __le32 cycle_cnt; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index 877d53355a58..76c1e44b7bdc 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -452,6 +452,10 @@ struct iwl_cfg { u32 d3_debug_data_length; u32 min_txq_size; u32 umac_prph_offset; + u32 fw_mon_smem_write_ptr_addr; + u32 fw_mon_smem_write_ptr_msk; + u32 fw_mon_smem_cycle_cnt_ptr_addr; + u32 fw_mon_smem_cycle_cnt_ptr_msk; }; extern const struct iwl_csr_params iwl_csr_v1; -- cgit v1.2.3-59-g8ed1b From 84294b5be15acb1c4eaf9264e33d93b1da3257cf Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Sun, 17 Feb 2019 17:15:31 +0200 Subject: iwlwifi: dbg_ini: remove redundant curly brackets from trigger collection flow remove redundant curly brackets from iwl_fw_ini_dump_trigger and iwl_fw_ini_get_trigger_len Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless/intel/iwlwifi/fw/dbg.c') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 87da6125683a..3709e90b55f1 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1746,7 +1746,7 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, case IWL_FW_INI_REGION_RXF: size += hdr_len + iwl_dump_ini_rxf_get_size(fwrt, reg); break; - case IWL_FW_INI_REGION_PAGING: { + case IWL_FW_INI_REGION_PAGING: size += hdr_len; if (iwl_fw_dbg_is_paging_enabled(fwrt)) { size += iwl_dump_ini_paging_get_size(fwrt, reg); @@ -1755,7 +1755,6 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, reg); } break; - } case IWL_FW_INI_REGION_DRAM_BUFFER: if (!fwrt->trans->num_blocks) break; @@ -1831,7 +1830,7 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, ops.fill_range = iwl_dump_ini_dev_mem_iter; iwl_dump_ini_mem(fwrt, type, data, reg, &ops); break; - case IWL_FW_INI_REGION_PAGING: { + case IWL_FW_INI_REGION_PAGING: ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header; if (iwl_fw_dbg_is_paging_enabled(fwrt)) { ops.get_num_of_ranges = @@ -1848,7 +1847,6 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, iwl_dump_ini_mem(fwrt, type, data, reg, &ops); break; - } case IWL_FW_INI_REGION_TXF: { struct iwl_ini_txf_iter_data iter = { .init = true }; void *fifo_iter = fwrt->dump.fifo_iter; -- cgit v1.2.3-59-g8ed1b From 33a403861572e7e10656fa89f6c0b9cd14ff2bd6 Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Sun, 17 Feb 2019 17:21:33 +0200 Subject: iwlwifi: dbg_ini: remove redundant type argument from iwl_dump_ini_mem Since iwl_dump_ini_mem receive struct iwl_fw_ini_region_cfg which holds the region type, there is no point to pass the type separately. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) (limited to 'drivers/net/wireless/intel/iwlwifi/fw/dbg.c') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 3709e90b55f1..95804feaeb75 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1664,17 +1664,17 @@ struct iwl_dump_ini_mem_ops { * @fwrt: fw runtime struct. * @data: dump memory data. * @reg: region to copy to the dump. + * @ops: memory dump operations. */ static void iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt, - enum iwl_fw_ini_region_type type, struct iwl_fw_error_dump_data **data, struct iwl_fw_ini_region_cfg *reg, struct iwl_dump_ini_mem_ops *ops) { struct iwl_fw_ini_error_dump_header *header = (void *)(*data)->data; + u32 num_of_ranges, i, type = le32_to_cpu(reg->region_type); void *range; - u32 num_of_ranges, i; if (WARN_ON(!ops || !ops->get_num_of_ranges || !ops->get_size || !ops->fill_mem_hdr || !ops->fill_range)) @@ -1722,7 +1722,6 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, for (i = 0; i < le32_to_cpu(trigger->num_regions); i++) { u32 reg_id = le32_to_cpu(trigger->data[i]); struct iwl_fw_ini_region_cfg *reg; - enum iwl_fw_ini_region_type type; if (WARN_ON(reg_id >= ARRAY_SIZE(fwrt->dump.active_regs))) continue; @@ -1731,8 +1730,7 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, if (WARN(!reg, "Unassigned region %d\n", reg_id)) continue; - type = le32_to_cpu(reg->region_type); - switch (type) { + switch (le32_to_cpu(reg->region_type)) { case IWL_FW_INI_REGION_DEVICE_MEMORY: case IWL_FW_INI_REGION_PERIPHERY_MAC: case IWL_FW_INI_REGION_PERIPHERY_PHY: @@ -1782,7 +1780,6 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, for (i = 0; i < num; i++) { u32 reg_id = le32_to_cpu(trigger->data[i]); - enum iwl_fw_ini_region_type type; struct iwl_fw_ini_region_cfg *reg; struct iwl_dump_ini_mem_ops ops; @@ -1798,14 +1795,13 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, if (le32_to_cpu(reg->domain) != IWL_FW_INI_DBG_DOMAIN_ALWAYS_ON) continue; - type = le32_to_cpu(reg->region_type); - switch (type) { + switch (le32_to_cpu(reg->region_type)) { case IWL_FW_INI_REGION_DEVICE_MEMORY: ops.get_num_of_ranges = iwl_dump_ini_mem_ranges; ops.get_size = iwl_dump_ini_mem_get_size; ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header; ops.fill_range = iwl_dump_ini_dev_mem_iter; - iwl_dump_ini_mem(fwrt, type, data, reg, &ops); + iwl_dump_ini_mem(fwrt, data, reg, &ops); break; case IWL_FW_INI_REGION_PERIPHERY_MAC: case IWL_FW_INI_REGION_PERIPHERY_PHY: @@ -1814,21 +1810,21 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, ops.get_size = iwl_dump_ini_mem_get_size; ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header; ops.fill_range = iwl_dump_ini_prph_iter; - iwl_dump_ini_mem(fwrt, type, data, reg, &ops); + iwl_dump_ini_mem(fwrt, data, reg, &ops); break; case IWL_FW_INI_REGION_DRAM_BUFFER: ops.get_num_of_ranges = iwl_dump_ini_mon_dram_ranges; ops.get_size = iwl_dump_ini_mon_dram_get_size; ops.fill_mem_hdr = iwl_dump_ini_mon_dram_fill_header; ops.fill_range = iwl_dump_ini_mon_dram_iter; - iwl_dump_ini_mem(fwrt, type, data, reg, &ops); + iwl_dump_ini_mem(fwrt, data, reg, &ops); break; case IWL_FW_INI_REGION_INTERNAL_BUFFER: ops.get_num_of_ranges = iwl_dump_ini_mem_ranges; ops.get_size = iwl_dump_ini_mon_smem_get_size; ops.fill_mem_hdr = iwl_dump_ini_mon_smem_fill_header; ops.fill_range = iwl_dump_ini_dev_mem_iter; - iwl_dump_ini_mem(fwrt, type, data, reg, &ops); + iwl_dump_ini_mem(fwrt, data, reg, &ops); break; case IWL_FW_INI_REGION_PAGING: ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header; @@ -1845,7 +1841,7 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, ops.fill_range = iwl_dump_ini_paging_gen2_iter; } - iwl_dump_ini_mem(fwrt, type, data, reg, &ops); + iwl_dump_ini_mem(fwrt, data, reg, &ops); break; case IWL_FW_INI_REGION_TXF: { struct iwl_ini_txf_iter_data iter = { .init = true }; @@ -1856,7 +1852,7 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, ops.get_size = iwl_dump_ini_txf_get_size; ops.fill_mem_hdr = iwl_dump_ini_fifo_fill_header; ops.fill_range = iwl_dump_ini_txf_iter; - iwl_dump_ini_mem(fwrt, type, data, reg, &ops); + iwl_dump_ini_mem(fwrt, data, reg, &ops); fwrt->dump.fifo_iter = fifo_iter; break; } @@ -1865,14 +1861,14 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, ops.get_size = iwl_dump_ini_rxf_get_size; ops.fill_mem_hdr = iwl_dump_ini_fifo_fill_header; ops.fill_range = iwl_dump_ini_rxf_iter; - iwl_dump_ini_mem(fwrt, type, data, reg, &ops); + iwl_dump_ini_mem(fwrt, data, reg, &ops); break; case IWL_FW_INI_REGION_CSR: ops.get_num_of_ranges = iwl_dump_ini_mem_ranges; ops.get_size = iwl_dump_ini_mem_get_size; ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header; ops.fill_range = iwl_dump_ini_csr_iter; - iwl_dump_ini_mem(fwrt, type, data, reg, &ops); + iwl_dump_ini_mem(fwrt, data, reg, &ops); break; case IWL_FW_INI_REGION_DRAM_IMR: /* This is undefined yet */ -- cgit v1.2.3-59-g8ed1b From 30eba3f9a454a7dbaf602e2aa4f5b3df18030be5 Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Tue, 19 Feb 2019 15:34:09 +0200 Subject: iwlwifi: dbg_ini: apply rx fifo offset after reading the region registers The region registers comes in abolute value so read the registers before applying the rx fifo offset. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless/intel/iwlwifi/fw/dbg.c') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 95804feaeb75..f3f00bc9fb48 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1347,8 +1347,6 @@ static int iwl_dump_ini_rxf_iter(struct iwl_fw_runtime *fwrt, if (!iwl_trans_grab_nic_access(fwrt->trans, &flags)) return -EBUSY; - offs += rxf_data.offset; - range->fifo_num = cpu_to_le32(rxf_data.fifo_num); range->num_of_registers = reg->fifos.num_of_registers; range->range_data_size = cpu_to_le32(rxf_data.size + registers_size); @@ -1372,6 +1370,12 @@ static int iwl_dump_ini_rxf_iter(struct iwl_fw_runtime *fwrt, goto out; } + /* + * region register have absolute value so apply rxf offset after + * reading the registers + */ + offs += rxf_data.offset; + /* Lock fence */ iwl_write_prph_no_grab(fwrt->trans, RXF_SET_FENCE_MODE + offs, 0x1); /* Set fence pointer to the same place like WR pointer */ -- cgit v1.2.3-59-g8ed1b From 56fe12d2837fbe5ddaebe8011538d25c48163d49 Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Tue, 26 Feb 2019 17:59:17 +0200 Subject: iwlwifi: dbg: fill radio registers data regardless of fifos data dumping The driver calculates memory regions dump size, allocate memory and fills the data. The driver fills the radio registers data only if the memory size of the fifos is greater then zero, so in case the user masked out the fifos from the dump, the driver will skip filling the radio register data. Solve this by checking filling radio registers data independently from fifos data. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless/intel/iwlwifi/fw/dbg.c') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index f3f00bc9fb48..966caaf7a8a5 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -967,10 +967,11 @@ iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt, if (fifo_len) { iwl_fw_dump_rxf(fwrt, &dump_data); iwl_fw_dump_txf(fwrt, &dump_data); - if (radio_len) - iwl_read_radio_regs(fwrt, &dump_data); } + if (radio_len) + iwl_read_radio_regs(fwrt, &dump_data); + if (iwl_fw_dbg_type_on(fwrt, IWL_FW_ERROR_DUMP_ERROR_INFO) && fwrt->dump.desc) { dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_ERROR_INFO); -- cgit v1.2.3-59-g8ed1b From 77f99ae6487be9c51b8f42ee20171b1e8ec1a170 Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Sun, 3 Mar 2019 17:29:23 +0200 Subject: iwlwifi: dbg_ini: support notification and dhc regions type parsing IWL_FW_INI_REGION_CSR and IWL_FW_INI_REGION_NOTIFICATION does not have memory addresses attached to them so the driver should skip them when parsing the region tlv. Also, instead of declearing what region types should skip the addition of the memory addresses, declare what regions have addition of memory addresses. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless/intel/iwlwifi/fw/dbg.c') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index be72529cc789..b8e0f5ce6461 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -2449,7 +2449,13 @@ static void iwl_fw_dbg_update_regions(struct iwl_fw_runtime *fwrt, type == IWL_FW_INI_REGION_RXF) iter += le32_to_cpu(reg->fifos.num_of_registers) * sizeof(__le32); - else if (type != IWL_FW_INI_REGION_DRAM_BUFFER) + else if (type == IWL_FW_INI_REGION_DEVICE_MEMORY || + type == IWL_FW_INI_REGION_PERIPHERY_MAC || + type == IWL_FW_INI_REGION_PERIPHERY_PHY || + type == IWL_FW_INI_REGION_PERIPHERY_AUX || + type == IWL_FW_INI_REGION_INTERNAL_BUFFER || + type == IWL_FW_INI_REGION_PAGING || + type == IWL_FW_INI_REGION_CSR) iter += le32_to_cpu(reg->internal.num_of_ranges) * sizeof(__le32); -- cgit v1.2.3-59-g8ed1b From 53032e6ec1bfe2eeefb93e1a7f1253ddd18ea42e Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Mon, 4 Mar 2019 12:14:37 +0200 Subject: iwlwifi: dbg_ini: add debug prints to the ini flows Add debug prints to the ini flow and rewrite existing prints to provide more information Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 102 ++++++++++++++++++----- drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c | 2 +- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 2 + 3 files changed, 82 insertions(+), 24 deletions(-) (limited to 'drivers/net/wireless/intel/iwlwifi/fw/dbg.c') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index b8e0f5ce6461..4ced200f297e 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1685,6 +1685,9 @@ iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt, !ops->fill_mem_hdr || !ops->fill_range)) return; + IWL_DEBUG_FW(fwrt, "WRT: collecting region: id=%d, type=%d\n", + le32_to_cpu(reg->region_id), type); + num_of_ranges = ops->get_num_of_ranges(fwrt, reg); (*data)->type = cpu_to_le32(type | INI_DUMP_BIT); @@ -1698,7 +1701,8 @@ iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt, range = ops->fill_mem_hdr(fwrt, reg, header); if (!range) { - IWL_ERR(fwrt, "Failed to fill region header: id=%d, type=%d\n", + IWL_ERR(fwrt, + "WRT: failed to fill region header: id=%d, type=%d\n", le32_to_cpu(reg->region_id), type); memset(*data, 0, le32_to_cpu((*data)->len)); return; @@ -1708,7 +1712,8 @@ iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt, int range_size = ops->fill_range(fwrt, reg, range, i); if (range_size < 0) { - IWL_ERR(fwrt, "Failed to dump region: id=%d, type=%d\n", + IWL_ERR(fwrt, + "WRT: failed to dump region: id=%d, type=%d\n", le32_to_cpu(reg->region_id), type); memset(*data, 0, le32_to_cpu((*data)->len)); return; @@ -1734,8 +1739,12 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, continue; reg = fwrt->dump.active_regs[reg_id]; - if (WARN(!reg, "Unassigned region %d\n", reg_id)) + if (!reg) { + IWL_WARN(fwrt, + "WRT: unassigned region id %d, skipping\n", + reg_id); continue; + } switch (le32_to_cpu(reg->region_type)) { case IWL_FW_INI_REGION_DEVICE_MEMORY: @@ -2108,6 +2117,12 @@ int _iwl_fw_dbg_ini_collect(struct iwl_fw_runtime *fwrt, if (test_and_set_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status)) return -EBUSY; + if (!iwl_fw_ini_trigger_on(fwrt, id)) { + IWL_WARN(fwrt, "WRT: Trigger %d is not active, aborting dump\n", + id); + return -EINVAL; + } + active = &fwrt->dump.active_trigs[id]; delay = le32_to_cpu(active->trig->dump_delay); occur = le32_to_cpu(active->trig->occurrences); @@ -2117,14 +2132,14 @@ int _iwl_fw_dbg_ini_collect(struct iwl_fw_runtime *fwrt, active->trig->occurrences = cpu_to_le32(--occur); if (le32_to_cpu(active->trig->force_restart)) { - IWL_WARN(fwrt, "Force restart: trigger %d fired.\n", id); + IWL_WARN(fwrt, "WRT: force restart: trigger %d fired.\n", id); iwl_force_nmi(fwrt->trans); return 0; } fwrt->dump.ini_trig_id = id; - IWL_WARN(fwrt, "Collecting data: ini trigger %d fired.\n", id); + IWL_WARN(fwrt, "WRT: collecting data: ini trigger %d fired.\n", id); schedule_delayed_work(&fwrt->dump.wk, usecs_to_jiffies(delay)); @@ -2262,12 +2277,12 @@ void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt) iwl_fw_dbg_stop_recording(fwrt, ¶ms); - IWL_DEBUG_INFO(fwrt, "WRT dump start\n"); + IWL_DEBUG_FW_INFO(fwrt, "WRT: data collection start\n"); if (fwrt->trans->ini_valid) iwl_fw_error_ini_dump(fwrt); else iwl_fw_error_dump(fwrt); - IWL_DEBUG_INFO(fwrt, "WRT dump done\n"); + IWL_DEBUG_FW_INFO(fwrt, "WRT: data collection done\n"); /* start recording again if the firmware is not crashed */ if (!test_bit(STATUS_FW_ERROR, &fwrt->trans->status) && @@ -2337,12 +2352,14 @@ iwl_fw_dbg_buffer_allocation(struct iwl_fw_runtime *fwrt, u32 size) if (!virtual_addr) IWL_ERR(fwrt, "Failed to allocate debug memory\n"); + IWL_DEBUG_FW(trans, + "Allocated DRAM buffer[%d], size=0x%x\n", + trans->num_blocks, size); + trans->fw_mon[trans->num_blocks].block = virtual_addr; trans->fw_mon[trans->num_blocks].physical = phys_addr; trans->fw_mon[trans->num_blocks].size = size; trans->num_blocks++; - - IWL_DEBUG_FW(trans, "Allocated debug block of size %d\n", size); } static void iwl_fw_dbg_buffer_apply(struct iwl_fw_runtime *fwrt, @@ -2365,11 +2382,15 @@ static void iwl_fw_dbg_buffer_apply(struct iwl_fw_runtime *fwrt, if (buf_location == IWL_FW_INI_LOCATION_SRAM_PATH) { if (!WARN(pnt != IWL_FW_INI_APPLY_EARLY, - "Invalid apply point %d for SMEM buffer allocation", - pnt)) + "WRT: Invalid apply point %d for SMEM buffer allocation, aborting\n", + pnt)) { + IWL_DEBUG_FW(trans, + "WRT: applying SMEM buffer destination\n"); + /* set sram monitor by enabling bit 7 */ iwl_set_bit(fwrt->trans, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_MONITOR_SRAM); + } return; } @@ -2388,6 +2409,9 @@ static void iwl_fw_dbg_buffer_apply(struct iwl_fw_runtime *fwrt, if (trans->num_blocks == 1) return; + IWL_DEBUG_FW(trans, + "WRT: applying DRAM buffer[%d] destination\n", block_idx); + cmd->num_frags = cpu_to_le32(1); cmd->fragments[0].address = cpu_to_le64(trans->fw_mon[block_idx].physical); @@ -2399,7 +2423,8 @@ static void iwl_fw_dbg_buffer_apply(struct iwl_fw_runtime *fwrt, } static void iwl_fw_dbg_send_hcmd(struct iwl_fw_runtime *fwrt, - struct iwl_ucode_tlv *tlv) + struct iwl_ucode_tlv *tlv, + bool ext) { struct iwl_fw_ini_hcmd_tlv *hcmd_tlv = (void *)&tlv->data[0]; struct iwl_fw_ini_hcmd *data = &hcmd_tlv->hcmd; @@ -2415,6 +2440,10 @@ static void iwl_fw_dbg_send_hcmd(struct iwl_fw_runtime *fwrt, if (le32_to_cpu(hcmd_tlv->domain) != IWL_FW_INI_DBG_DOMAIN_ALWAYS_ON) return; + IWL_DEBUG_FW(fwrt, + "WRT: ext=%d. Sending host command id=0x%x, group=0x%x\n", + ext, data->id, data->group); + iwl_trans_send_cmd(fwrt->trans, &hcmd); } @@ -2431,17 +2460,20 @@ static void iwl_fw_dbg_update_regions(struct iwl_fw_runtime *fwrt, u32 type = le32_to_cpu(reg->region_type); if (WARN(id >= ARRAY_SIZE(fwrt->dump.active_regs), - "Invalid region id %d for apply point %d\n", id, pnt)) + "WRT: ext=%d. Invalid region id %d for apply point %d\n", + ext, id, pnt)) break; active = &fwrt->dump.active_regs[id]; if (*active) - IWL_WARN(fwrt->trans, "region TLV %d override\n", id); + IWL_WARN(fwrt->trans, + "WRT: ext=%d. Region id %d override\n", + ext, id); IWL_DEBUG_FW(fwrt, - "%s: apply point %d, activating region ID %d\n", - __func__, pnt, id); + "WRT: ext=%d. Activating region id %d\n", + ext, id); *active = reg; @@ -2474,7 +2506,8 @@ static int iwl_fw_dbg_trig_realloc(struct iwl_fw_runtime *fwrt, ptr = krealloc(active->trig, size, GFP_KERNEL); if (!ptr) { - IWL_ERR(fwrt, "Failed to allocate memory for trigger %d\n", id); + IWL_ERR(fwrt, "WRT: Failed to allocate memory for trigger %d\n", + id); return -ENOMEM; } active->trig = ptr; @@ -2498,7 +2531,9 @@ static void iwl_fw_dbg_update_triggers(struct iwl_fw_runtime *fwrt, u32 trig_regs_size = le32_to_cpu(trig->num_regions) * sizeof(__le32); - if (WARN_ON(id >= ARRAY_SIZE(fwrt->dump.active_trigs))) + if (WARN(id >= ARRAY_SIZE(fwrt->dump.active_trigs), + "WRT: ext=%d. Invalid trigger id %d for apply point %d\n", + ext, id, apply_point)) break; active = &fwrt->dump.active_trigs[id]; @@ -2506,6 +2541,10 @@ static void iwl_fw_dbg_update_triggers(struct iwl_fw_runtime *fwrt, if (!active->active) { size_t trig_size = sizeof(*trig) + trig_regs_size; + IWL_DEBUG_FW(fwrt, + "WRT: ext=%d. Activating trigger %d\n", + ext, id); + if (iwl_fw_dbg_trig_realloc(fwrt, active, id, trig_size)) goto next; @@ -2524,8 +2563,16 @@ static void iwl_fw_dbg_update_triggers(struct iwl_fw_runtime *fwrt, int mem_to_add = trig_regs_size; if (region_override) { + IWL_DEBUG_FW(fwrt, + "WRT: ext=%d. Trigger %d regions override\n", + ext, id); + mem_to_add -= active_regs * sizeof(__le32); } else { + IWL_DEBUG_FW(fwrt, + "WRT: ext=%d. Trigger %d regions appending\n", + ext, id); + offset += active_regs; new_regs += active_regs; } @@ -2534,8 +2581,13 @@ static void iwl_fw_dbg_update_triggers(struct iwl_fw_runtime *fwrt, active->size + mem_to_add)) goto next; - if (conf_override) + if (conf_override) { + IWL_DEBUG_FW(fwrt, + "WRT: ext=%d. Trigger %d configuration override\n", + ext, id); + memcpy(active->trig, trig, sizeof(*trig)); + } memcpy(active->trig->data + offset, trig->data, trig_regs_size); @@ -2576,11 +2628,11 @@ static void _iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt, case IWL_UCODE_TLV_TYPE_HCMD: if (pnt < IWL_FW_INI_APPLY_AFTER_ALIVE) { IWL_ERR(fwrt, - "Invalid apply point %x for host command\n", - pnt); + "WRT: ext=%d. Invalid apply point %d for host command\n", + ext, pnt); goto next; } - iwl_fw_dbg_send_hcmd(fwrt, tlv); + iwl_fw_dbg_send_hcmd(fwrt, tlv, ext); break; case IWL_UCODE_TLV_TYPE_REGIONS: iwl_fw_dbg_update_regions(fwrt, ini_tlv, ext, pnt); @@ -2591,7 +2643,9 @@ static void _iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt, case IWL_UCODE_TLV_TYPE_DEBUG_FLOW: break; default: - WARN_ONCE(1, "Invalid TLV %x for apply point\n", type); + WARN_ONCE(1, + "WRT: ext=%d. Invalid TLV 0x%x for apply point\n", + ext, type); break; } next: @@ -2605,6 +2659,8 @@ void iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt, void *data = &fwrt->trans->apply_points[apply_point]; int i; + IWL_DEBUG_FW(fwrt, "WRT: enabling apply point %d\n", apply_point); + if (apply_point == IWL_FW_INI_APPLY_EARLY) { for (i = 0; i < IWL_FW_INI_MAX_REGION_ID; i++) fwrt->dump.active_regs[i] = NULL; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c index 9107302cc444..08e40a8f9f6b 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c @@ -138,7 +138,7 @@ void iwl_alloc_dbg_tlv(struct iwl_trans *trans, size_t len, const u8 *data, if (le32_to_cpu(hdr->tlv_version) != 1) continue; - IWL_DEBUG_FW(trans, "Read TLV %x, apply point %d\n", + IWL_DEBUG_FW(trans, "WRT: read TLV 0x%x, apply point %d\n", le32_to_cpu(tlv->type), apply); if (WARN_ON(apply >= IWL_FW_INI_APPLY_NUM)) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index c5baaae8d38e..717b9b5be157 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -896,6 +896,8 @@ void iwl_pcie_apply_destination(struct iwl_trans *trans) if (!trans->num_blocks) return; + IWL_DEBUG_FW(trans, + "WRT: applying DRAM buffer[0] destination\n"); iwl_write_umac_prph(trans, MON_BUFF_BASE_ADDR_VER2, trans->fw_mon[0].physical >> MON_BUFF_SHIFT_VER2); -- cgit v1.2.3-59-g8ed1b From 32d2282a35f7afbb73365c43bffed3d00fb40fcc Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Wed, 6 Mar 2019 15:24:20 +0200 Subject: iwlwifi: dbg: add periphery memory dumping support to ax210 device family Allows to dump periphery memory on ax210 devices. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless/intel/iwlwifi/fw/dbg.c') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 4ced200f297e..e288f1f8fe3d 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -557,6 +557,11 @@ static const struct iwl_prph_range iwl_prph_dump_addr_22000[] = { { .start = 0x00a0c1b0, .end = 0x00a0c1b8 }, }; +static const struct iwl_prph_range iwl_prph_dump_addr_ax210[] = { + { .start = 0x00d03c00, .end = 0x00d03c64 }, + { .start = 0x00d0c000, .end = 0x00d0c174 }, +}; + static void iwl_read_prph_block(struct iwl_trans *trans, u32 start, u32 len_bytes, __le32 *data) { @@ -675,7 +680,8 @@ static void iwl_fw_prph_handler(struct iwl_fw_runtime *fwrt, void *ptr, u32 range_len; if (fwrt->trans->cfg->device_family >= IWL_DEVICE_FAMILY_AX210) { - /* TODO */ + range_len = ARRAY_SIZE(iwl_prph_dump_addr_ax210); + handler(fwrt, iwl_prph_dump_addr_ax210, range_len, ptr); } else if (fwrt->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000) { range_len = ARRAY_SIZE(iwl_prph_dump_addr_22000); handler(fwrt, iwl_prph_dump_addr_22000, range_len, ptr); -- cgit v1.2.3-59-g8ed1b From e91130cebd4749f59e73feeb8c24b4517b213149 Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Thu, 14 Mar 2019 10:05:25 +0200 Subject: iwlwifi: dbg: add lmac and umac PC registers to periphery dump Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net/wireless/intel/iwlwifi/fw/dbg.c') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index e288f1f8fe3d..d070c2c22076 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -545,6 +545,7 @@ static const struct iwl_prph_range iwl_prph_dump_addr_22000[] = { { .start = 0x00a04590, .end = 0x00a04590 }, { .start = 0x00a04598, .end = 0x00a04598 }, { .start = 0x00a045c0, .end = 0x00a045f4 }, + { .start = 0x00a05c18, .end = 0x00a05c1c }, { .start = 0x00a0c000, .end = 0x00a0c018 }, { .start = 0x00a0c020, .end = 0x00a0c028 }, { .start = 0x00a0c038, .end = 0x00a0c094 }, @@ -559,6 +560,7 @@ static const struct iwl_prph_range iwl_prph_dump_addr_22000[] = { static const struct iwl_prph_range iwl_prph_dump_addr_ax210[] = { { .start = 0x00d03c00, .end = 0x00d03c64 }, + { .start = 0x00d05c18, .end = 0x00d05c1c }, { .start = 0x00d0c000, .end = 0x00d0c174 }, }; -- cgit v1.2.3-59-g8ed1b From 69166f7a37dc0bde5a3c26945e3cdbfc740b0562 Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Tue, 19 Mar 2019 09:35:29 +0200 Subject: iwlwifi: dbg_ini: set dump bit only when trigger collection is certain In case the the trigger occurrences is zero or force_restart is set, the driver sets IWL_FWRT_STATUS_DUMPING without actually scheduling trigger collection. At this point no other dump collection can be performed. Solve this by setting IWL_FWRT_STATUS_DUMPING bit only when the driver is surely going to schedule dump collection Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net/wireless/intel/iwlwifi/fw/dbg.c') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index d070c2c22076..79e36336f623 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -2145,6 +2145,9 @@ int _iwl_fw_dbg_ini_collect(struct iwl_fw_runtime *fwrt, return 0; } + if (test_and_set_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status)) + return -EBUSY; + fwrt->dump.ini_trig_id = id; IWL_WARN(fwrt, "WRT: collecting data: ini trigger %d fired.\n", id); -- cgit v1.2.3-59-g8ed1b From 954454d6107ffb0359f70b4de7f3339935f649b8 Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Sun, 7 Apr 2019 10:41:20 +0300 Subject: iwlwifi: dbg_ini: add lmac and umac error tables dumping support Add LMAC_ERROR_TABLE and UMAC_ERROR_TABLE region types and handle them in the same way as we handle DEVICE_MEMORY. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h | 4 ++++ drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 8 +++++++- 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless/intel/iwlwifi/fw/dbg.c') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h index af1e3d08c179..f4202bc231a6 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h @@ -473,6 +473,8 @@ enum iwl_fw_ini_debug_flow { * @IWL_FW_INI_REGION_CSR: CSR registers * @IWL_FW_INI_REGION_NOTIFICATION: FW notification data * @IWL_FW_INI_REGION_DHC: dhc response to dump + * @IWL_FW_INI_REGION_LMAC_ERROR_TABLE: lmac error table + * @IWL_FW_INI_REGION_UMAC_ERROR_TABLE: umac error table * @IWL_FW_INI_REGION_NUM: number of region types */ enum iwl_fw_ini_region_type { @@ -490,6 +492,8 @@ enum iwl_fw_ini_region_type { IWL_FW_INI_REGION_CSR, IWL_FW_INI_REGION_NOTIFICATION, IWL_FW_INI_REGION_DHC, + IWL_FW_INI_REGION_LMAC_ERROR_TABLE, + IWL_FW_INI_REGION_UMAC_ERROR_TABLE, IWL_FW_INI_REGION_NUM }; /* FW_DEBUG_TLV_REGION_TYPE_E_VER_1 */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 79e36336f623..035eeeabfc8c 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1760,6 +1760,8 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, case IWL_FW_INI_REGION_PERIPHERY_PHY: case IWL_FW_INI_REGION_PERIPHERY_AUX: case IWL_FW_INI_REGION_CSR: + case IWL_FW_INI_REGION_LMAC_ERROR_TABLE: + case IWL_FW_INI_REGION_UMAC_ERROR_TABLE: size += hdr_len + iwl_dump_ini_mem_get_size(fwrt, reg); break; case IWL_FW_INI_REGION_TXF: @@ -1821,6 +1823,8 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt, switch (le32_to_cpu(reg->region_type)) { case IWL_FW_INI_REGION_DEVICE_MEMORY: + case IWL_FW_INI_REGION_LMAC_ERROR_TABLE: + case IWL_FW_INI_REGION_UMAC_ERROR_TABLE: ops.get_num_of_ranges = iwl_dump_ini_mem_ranges; ops.get_size = iwl_dump_ini_mem_get_size; ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header; @@ -2498,7 +2502,9 @@ static void iwl_fw_dbg_update_regions(struct iwl_fw_runtime *fwrt, type == IWL_FW_INI_REGION_PERIPHERY_AUX || type == IWL_FW_INI_REGION_INTERNAL_BUFFER || type == IWL_FW_INI_REGION_PAGING || - type == IWL_FW_INI_REGION_CSR) + type == IWL_FW_INI_REGION_CSR || + type == IWL_FW_INI_REGION_LMAC_ERROR_TABLE || + type == IWL_FW_INI_REGION_UMAC_ERROR_TABLE) iter += le32_to_cpu(reg->internal.num_of_ranges) * sizeof(__le32); -- cgit v1.2.3-59-g8ed1b From bfd8e3dade7315130b96c722b7027e61796fb606 Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Tue, 19 Mar 2019 16:40:15 +0200 Subject: iwlwifi: dbg_ini: add periodic trigger support Allows to configure a periodic data collection Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 40 +++++++++++++++++++++++++ drivers/net/wireless/intel/iwlwifi/fw/dbg.h | 3 ++ drivers/net/wireless/intel/iwlwifi/fw/init.c | 2 ++ drivers/net/wireless/intel/iwlwifi/fw/runtime.h | 1 + drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 1 + 5 files changed, 47 insertions(+) (limited to 'drivers/net/wireless/intel/iwlwifi/fw/dbg.c') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 035eeeabfc8c..d8c4fdb8d4a1 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -2616,6 +2616,20 @@ static void iwl_fw_dbg_update_triggers(struct iwl_fw_runtime *fwrt, active->trig->occurrences = cpu_to_le32(-1); active->active = true; + + if (id == IWL_FW_TRIGGER_ID_PERIODIC_TRIGGER) { + u32 collect_interval = le32_to_cpu(trig->trigger_data); + + /* the minimum allowed interval is 50ms */ + if (collect_interval < 50) { + collect_interval = 50; + trig->trigger_data = + cpu_to_le32(collect_interval); + } + + mod_timer(&fwrt->dump.periodic_trig, + jiffies + msecs_to_jiffies(collect_interval)); + } next: iter += sizeof(*trig) + trig_regs_size; @@ -2696,8 +2710,34 @@ IWL_EXPORT_SYMBOL(iwl_fw_dbg_apply_point); void iwl_fwrt_stop_device(struct iwl_fw_runtime *fwrt) { + del_timer(&fwrt->dump.periodic_trig); iwl_fw_dbg_collect_sync(fwrt); iwl_trans_stop_device(fwrt->trans); } IWL_EXPORT_SYMBOL(iwl_fwrt_stop_device); + +void iwl_fw_dbg_periodic_trig_handler(struct timer_list *t) +{ + struct iwl_fw_runtime *fwrt; + enum iwl_fw_ini_trigger_id id = IWL_FW_TRIGGER_ID_PERIODIC_TRIGGER; + int ret; + typeof(fwrt->dump) *dump_ptr = container_of(t, typeof(fwrt->dump), + periodic_trig); + + fwrt = container_of(dump_ptr, typeof(*fwrt), dump); + + ret = _iwl_fw_dbg_ini_collect(fwrt, id); + if (!ret || ret == -EBUSY) { + struct iwl_fw_ini_trigger *trig = + fwrt->dump.active_trigs[id].trig; + u32 occur = le32_to_cpu(trig->occurrences); + u32 collect_interval = le32_to_cpu(trig->trigger_data); + + if (!occur) + return; + + mod_timer(&fwrt->dump.periodic_trig, + jiffies + msecs_to_jiffies(collect_interval)); + } +} diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h index cccf91db74c4..2a9e560a906b 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h @@ -385,11 +385,13 @@ void iwl_fw_dbg_read_d3_debug_data(struct iwl_fw_runtime *fwrt); static inline void iwl_fw_flush_dump(struct iwl_fw_runtime *fwrt) { + del_timer(&fwrt->dump.periodic_trig); flush_delayed_work(&fwrt->dump.wk); } static inline void iwl_fw_cancel_dump(struct iwl_fw_runtime *fwrt) { + del_timer(&fwrt->dump.periodic_trig); cancel_delayed_work_sync(&fwrt->dump.wk); } @@ -468,4 +470,5 @@ static inline void iwl_fw_error_collect(struct iwl_fw_runtime *fwrt) } } +void iwl_fw_dbg_periodic_trig_handler(struct timer_list *t); #endif /* __iwl_fw_dbg_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/init.c b/drivers/net/wireless/intel/iwlwifi/fw/init.c index 12310e3d2fc5..4435c0ce3013 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/init.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/init.c @@ -76,6 +76,8 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans, fwrt->ops_ctx = ops_ctx; INIT_DELAYED_WORK(&fwrt->dump.wk, iwl_fw_error_dump_wk); iwl_fwrt_dbgfs_register(fwrt, dbgfs_dir); + timer_setup(&fwrt->dump.periodic_trig, + iwl_fw_dbg_periodic_trig_handler, 0); } IWL_EXPORT_SYMBOL(iwl_fw_runtime_init); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h index 88a558e082a3..a6402a0b3854 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h @@ -146,6 +146,7 @@ struct iwl_fw_runtime { u32 umac_err_id; void *fifo_iter; enum iwl_fw_ini_trigger_id ini_trig_id; + struct timer_list periodic_trig; } dump; #ifdef CONFIG_IWLWIFI_DEBUGFS struct { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 55d399899d1c..602ff50268f2 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -1261,6 +1261,7 @@ static void iwl_mvm_reprobe_wk(struct work_struct *wk) void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error) { iwl_abort_notification_waits(&mvm->notif_wait); + del_timer(&mvm->fwrt.dump.periodic_trig); /* * This is a bit racy, but worst case we tell mac80211 about -- cgit v1.2.3-59-g8ed1b From 391481ad26904e055298eb4e41fbdba7d20e6526 Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Thu, 4 Apr 2019 14:31:30 +0300 Subject: iwlwifi: dbg: replace dump info device family with HW type In the dump info, the driver sets device_family to IWL_FW_ERROR_DUMP_FAMILY_7 in case IWL_FW_ERROR_DUMP_FAMILY_7 is used or IWL_FW_ERROR_DUMP_FAMILY_8 otherwise. This information is misleading and incorrect since the driver sets the device family to 8 to any device that is from family 8 and later, e.g. device family 9 is represented as 8 in the dump. Also, the device family enum is known only to the driver and does not give any information to the FW developer Change the device family to HW type to give propper data about the nic in use. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 7 ++----- drivers/net/wireless/intel/iwlwifi/fw/error-dump.h | 4 ++-- drivers/net/wireless/intel/iwlwifi/iwl-csr.h | 1 + 3 files changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers/net/wireless/intel/iwlwifi/fw/dbg.c') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index d8c4fdb8d4a1..4ef447480aaf 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -917,11 +917,8 @@ iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt, 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_type = + cpu_to_le32(CSR_HW_REV_TYPE(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, diff --git a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h index 260097c75427..0feff4c33e39 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h @@ -184,7 +184,7 @@ enum iwl_fw_error_dump_family { /** * struct iwl_fw_error_dump_info - info on the device / firmware - * @device_family: the family of the device (7 / 8) + * @hw_type: the type of the device * @hw_step: the step of the device * @fw_human_readable: human readable FW version * @dev_human_readable: name of the device @@ -196,7 +196,7 @@ enum iwl_fw_error_dump_family { * if the dump collection was not initiated by an assert, the value is 0 */ struct iwl_fw_error_dump_info { - __le32 device_family; + __le32 hw_type; __le32 hw_step; u8 fw_human_readable[FW_VER_HUMAN_READABLE_SZ]; u8 dev_human_readable[64]; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h index 2b98ecdcf301..553554846009 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h @@ -290,6 +290,7 @@ /* HW REV */ #define CSR_HW_REV_DASH(_val) (((_val) & 0x0000003) >> 0) #define CSR_HW_REV_STEP(_val) (((_val) & 0x000000C) >> 2) +#define CSR_HW_REV_TYPE(_val) (((_val) & 0x000FFF0) >> 4) /* HW RFID */ #define CSR_HW_RFID_FLAVOR(_val) (((_val) & 0x000000F) >> 0) -- cgit v1.2.3-59-g8ed1b From 0aade8f4846a6fdacbbd6bbe092d0edb2dfa0d0f Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Mon, 8 Apr 2019 16:59:53 +0300 Subject: iwlwifi: avoid allocating memory for region with disabled domain In iwl_fw_ini_get_trigger_len the driver allocates space for memory regions regardless of their domain and in iwl_fw_ini_dump_trigger the driver aborts trigger collection of disabled domain. This diff causes unneeded memory allocation and traling zeros in the dump file. Solve this behavior by enforcing domain checking in iwl_fw_ini_get_trigger_len Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/net/wireless/intel/iwlwifi/fw/dbg.c') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 4ef447480aaf..62fd346ccb77 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1751,6 +1751,10 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt, continue; } + /* currently the driver supports always on domain only */ + if (le32_to_cpu(reg->domain) != IWL_FW_INI_DBG_DOMAIN_ALWAYS_ON) + continue; + switch (le32_to_cpu(reg->region_type)) { case IWL_FW_INI_REGION_DEVICE_MEMORY: case IWL_FW_INI_REGION_PERIPHERY_MAC: -- cgit v1.2.3-59-g8ed1b From a0eaead41db98c08614c4b1ef453bdfaacde962d Mon Sep 17 00:00:00 2001 From: Shahar S Matityahu Date: Sun, 7 Apr 2019 10:46:08 +0300 Subject: iwlwifi: dbg_ini: check for valid region type during regions parsing Add region type checking during regions parsing to avoid attempts to parse unsupported or illegal region types. Signed-off-by: Shahar S Matityahu Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless/intel/iwlwifi/fw/dbg.c') diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 62fd346ccb77..5f52e40a2903 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -2469,15 +2469,20 @@ static void iwl_fw_dbg_update_regions(struct iwl_fw_runtime *fwrt, { void *iter = (void *)tlv->region_config; int i, size = le32_to_cpu(tlv->num_regions); + const char *err_st = + "WRT: ext=%d. Invalid region %s %d for apply point %d\n"; for (i = 0; i < size; i++) { struct iwl_fw_ini_region_cfg *reg = iter, **active; int id = le32_to_cpu(reg->region_id); u32 type = le32_to_cpu(reg->region_type); - if (WARN(id >= ARRAY_SIZE(fwrt->dump.active_regs), - "WRT: ext=%d. Invalid region id %d for apply point %d\n", - ext, id, pnt)) + if (WARN(id >= ARRAY_SIZE(fwrt->dump.active_regs), err_st, ext, + "id", id, pnt)) + break; + + if (WARN(type == 0 || type >= IWL_FW_INI_REGION_NUM, err_st, + ext, "type", type, pnt)) break; active = &fwrt->dump.active_regs[id]; -- cgit v1.2.3-59-g8ed1b