iwlwifi: dbg_ini: separate cfg and dump flows to different modules
authorShahar S Matityahu <shahar.s.matityahu@intel.com>
Thu, 13 Jun 2019 13:41:35 +0000 (16:41 +0300)
committerLuca Coelho <luciano.coelho@intel.com>
Fri, 6 Sep 2019 12:31:22 +0000 (15:31 +0300)
separate configuration flows and dump collection flows.
make ini configuration flows be in iwl-dbg-tlv.c and dump related flows
in dbg.c to better reflect their logical difference.

Signed-off-by: Shahar S Matityahu <shahar.s.matityahu@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
drivers/net/wireless/intel/iwlwifi/fw/dbg.c
drivers/net/wireless/intel/iwlwifi/fw/dbg.h
drivers/net/wireless/intel/iwlwifi/fw/runtime.h
drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.h
drivers/net/wireless/intel/iwlwifi/mvm/fw.c
drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/scan.c

index 2a4c2e7..3320acc 100644 (file)
@@ -2438,435 +2438,6 @@ void iwl_fw_dbg_read_d3_debug_data(struct iwl_fw_runtime *fwrt)
 }
 IWL_EXPORT_SYMBOL(iwl_fw_dbg_read_d3_debug_data);
 
-static void iwl_fw_dbg_info_apply(struct iwl_fw_runtime *fwrt,
-                                 struct iwl_fw_ini_debug_info_tlv *dbg_info,
-                                 bool ext, enum iwl_fw_ini_apply_point pnt)
-{
-       u32 img_name_len = le32_to_cpu(dbg_info->img_name_len);
-       u32 dbg_cfg_name_len = le32_to_cpu(dbg_info->dbg_cfg_name_len);
-
-       if (img_name_len != IWL_FW_INI_MAX_IMG_NAME_LEN) {
-               IWL_WARN(fwrt,
-                        "WRT: ext=%d. Invalid image name length %d, expected %d\n",
-                        ext, img_name_len,
-                        IWL_FW_INI_MAX_IMG_NAME_LEN);
-               return;
-       }
-
-       if (dbg_cfg_name_len != IWL_FW_INI_MAX_DBG_CFG_NAME_LEN) {
-               IWL_WARN(fwrt,
-                        "WRT: ext=%d. Invalid debug cfg name length %d, expected %d\n",
-                        ext, dbg_cfg_name_len,
-                        IWL_FW_INI_MAX_DBG_CFG_NAME_LEN);
-               return;
-       }
-
-       if (ext) {
-               memcpy(fwrt->dump.external_dbg_cfg_name, dbg_info->dbg_cfg_name,
-                      sizeof(fwrt->dump.external_dbg_cfg_name));
-       } else {
-               memcpy(fwrt->dump.img_name, dbg_info->img_name,
-                      sizeof(fwrt->dump.img_name));
-               memcpy(fwrt->dump.internal_dbg_cfg_name, dbg_info->dbg_cfg_name,
-                      sizeof(fwrt->dump.internal_dbg_cfg_name));
-       }
-}
-
-static void
-iwl_fw_dbg_buffer_allocation(struct iwl_fw_runtime *fwrt, u32 size)
-{
-       struct iwl_trans *trans = fwrt->trans;
-       void *virtual_addr = NULL;
-       dma_addr_t phys_addr;
-
-       if (WARN_ON_ONCE(trans->dbg.num_blocks ==
-                        ARRAY_SIZE(trans->dbg.fw_mon)))
-               return;
-
-       virtual_addr =
-               dma_alloc_coherent(fwrt->trans->dev, size, &phys_addr,
-                                  GFP_KERNEL | __GFP_NOWARN);
-
-       /* TODO: alloc fragments if needed */
-       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->dbg.num_blocks, size);
-
-       trans->dbg.fw_mon[trans->dbg.num_blocks].block = virtual_addr;
-       trans->dbg.fw_mon[trans->dbg.num_blocks].physical = phys_addr;
-       trans->dbg.fw_mon[trans->dbg.num_blocks].size = size;
-       trans->dbg.num_blocks++;
-}
-
-static void iwl_fw_dbg_buffer_apply(struct iwl_fw_runtime *fwrt,
-                                   struct iwl_fw_ini_allocation_tlv *alloc,
-                                   enum iwl_fw_ini_apply_point pnt)
-{
-       struct iwl_trans *trans = fwrt->trans;
-       struct iwl_ldbg_config_cmd ldbg_cmd = {
-               .type = cpu_to_le32(BUFFER_ALLOCATION),
-       };
-       struct iwl_buffer_allocation_cmd *cmd = &ldbg_cmd.buffer_allocation;
-       struct iwl_host_cmd hcmd = {
-               .id = LDBG_CONFIG_CMD,
-               .flags = CMD_ASYNC,
-               .data[0] = &ldbg_cmd,
-               .len[0] = sizeof(ldbg_cmd),
-       };
-       int block_idx = trans->dbg.num_blocks;
-       u32 buf_location = le32_to_cpu(alloc->buffer_location);
-       u32 alloc_id = le32_to_cpu(alloc->allocation_id);
-
-       if (alloc_id <= IWL_FW_INI_ALLOCATION_INVALID ||
-           alloc_id >= IWL_FW_INI_ALLOCATION_NUM) {
-               IWL_ERR(fwrt, "WRT: Invalid allocation id %d\n", alloc_id);
-               return;
-       }
-
-       if (fwrt->trans->dbg.ini_dest == IWL_FW_INI_LOCATION_INVALID)
-               fwrt->trans->dbg.ini_dest = buf_location;
-
-       if (buf_location != fwrt->trans->dbg.ini_dest) {
-               WARN(fwrt,
-                    "WRT: attempt to override buffer location on apply point %d\n",
-                    pnt);
-
-               return;
-       }
-
-       if (buf_location == IWL_FW_INI_LOCATION_SRAM_PATH) {
-               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;
-       }
-
-       if (buf_location != IWL_FW_INI_LOCATION_DRAM_PATH)
-               return;
-
-       if (!(BIT(alloc_id) & fwrt->trans->dbg.is_alloc)) {
-               iwl_fw_dbg_buffer_allocation(fwrt, le32_to_cpu(alloc->size));
-               if (block_idx == trans->dbg.num_blocks)
-                       return;
-               fwrt->trans->dbg.is_alloc |= BIT(alloc_id);
-       }
-
-       /* First block is assigned via registers / context info */
-       if (trans->dbg.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->dbg.fw_mon[block_idx].physical);
-       cmd->fragments[0].size = alloc->size;
-       cmd->allocation_id = alloc->allocation_id;
-       cmd->buffer_location = alloc->buffer_location;
-
-       iwl_trans_send_cmd(trans, &hcmd);
-}
-
-static void iwl_fw_dbg_send_hcmd(struct iwl_fw_runtime *fwrt,
-                                struct iwl_ucode_tlv *tlv)
-{
-       struct iwl_fw_ini_hcmd_tlv *hcmd_tlv = (void *)&tlv->data[0];
-       struct iwl_fw_ini_hcmd *data = &hcmd_tlv->hcmd;
-       u16 len = le32_to_cpu(tlv->length) - sizeof(*hcmd_tlv);
-
-       struct iwl_host_cmd hcmd = {
-               .id = WIDE_ID(data->group, data->id),
-               .len = { len, },
-               .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_DEBUG_FW(fwrt, "WRT: Sending host command id=0x%x, group=0x%x\n",
-                    data->id, data->group);
-
-       iwl_trans_send_cmd(fwrt->trans, &hcmd);
-}
-
-static void iwl_fw_dbg_update_regions(struct iwl_fw_runtime *fwrt,
-                                     struct iwl_fw_ini_region_tlv *tlv,
-                                     enum iwl_fw_ini_apply_point pnt)
-{
-       void *iter = (void *)tlv->region_config;
-       int i, size = le32_to_cpu(tlv->num_regions);
-       const char *err_st =
-               "WRT: 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), err_st, "id",
-                        id, pnt))
-                       break;
-
-               if (WARN(type == 0 || type >= IWL_FW_INI_REGION_NUM, err_st,
-                        "type", type, pnt))
-                       break;
-
-               active = &fwrt->dump.active_regs[id];
-
-               if (*active)
-                       IWL_WARN(fwrt->trans, "WRT: Region id %d override\n",
-                                id);
-
-               IWL_DEBUG_FW(fwrt, "WRT: Activating region id %d\n", id);
-
-               *active = reg;
-
-               if (type == IWL_FW_INI_REGION_TXF ||
-                   type == IWL_FW_INI_REGION_RXF)
-                       iter += le32_to_cpu(reg->fifos.num_of_registers) *
-                               sizeof(__le32);
-               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 ||
-                        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);
-
-               iter += sizeof(*reg);
-       }
-}
-
-static int iwl_fw_dbg_trig_realloc(struct iwl_fw_runtime *fwrt,
-                                  struct iwl_fw_ini_active_triggers *active,
-                                  u32 id, int size)
-{
-       void *ptr;
-
-       if (size <= active->size)
-               return 0;
-
-       ptr = krealloc(active->trig, size, GFP_KERNEL);
-       if (!ptr) {
-               IWL_ERR(fwrt, "WRT: Failed to allocate memory for trigger %d\n",
-                       id);
-               return -ENOMEM;
-       }
-       active->trig = ptr;
-       active->size = size;
-
-       return 0;
-}
-
-static void iwl_fw_dbg_update_triggers(struct iwl_fw_runtime *fwrt,
-                                      struct iwl_fw_ini_trigger_tlv *tlv,
-                                      enum iwl_fw_ini_apply_point apply_point)
-{
-       int i, size = le32_to_cpu(tlv->num_triggers);
-       void *iter = (void *)tlv->trigger_config;
-
-       for (i = 0; i < size; i++) {
-               struct iwl_fw_ini_trigger *trig = iter;
-               struct iwl_fw_ini_active_triggers *active;
-               int id = le32_to_cpu(trig->trigger_id);
-               u32 trig_regs_size = le32_to_cpu(trig->num_regions) *
-                       sizeof(__le32);
-
-               if (WARN(id >= ARRAY_SIZE(fwrt->dump.active_trigs),
-                        "WRT: Invalid trigger id %d for apply point %d\n", id,
-                        apply_point))
-                       break;
-
-               active = &fwrt->dump.active_trigs[id];
-
-               if (!active->active) {
-                       size_t trig_size = sizeof(*trig) + trig_regs_size;
-
-                       IWL_DEBUG_FW(fwrt, "WRT: Activating trigger %d\n", id);
-
-                       if (iwl_fw_dbg_trig_realloc(fwrt, active, id,
-                                                   trig_size))
-                               goto next;
-
-                       memcpy(active->trig, trig, trig_size);
-
-               } else {
-                       u32 conf_override =
-                               !(le32_to_cpu(trig->override_trig) & 0xff);
-                       u32 region_override =
-                               !(le32_to_cpu(trig->override_trig) & 0xff00);
-                       u32 offset = 0;
-                       u32 active_regs =
-                               le32_to_cpu(active->trig->num_regions);
-                       u32 new_regs = le32_to_cpu(trig->num_regions);
-                       int mem_to_add = trig_regs_size;
-
-                       if (region_override) {
-                               IWL_DEBUG_FW(fwrt,
-                                            "WRT: Trigger %d regions override\n",
-                                            id);
-
-                               mem_to_add -= active_regs * sizeof(__le32);
-                       } else {
-                               IWL_DEBUG_FW(fwrt,
-                                            "WRT: Trigger %d regions appending\n",
-                                            id);
-
-                               offset += active_regs;
-                               new_regs += active_regs;
-                       }
-
-                       if (iwl_fw_dbg_trig_realloc(fwrt, active, id,
-                                                   active->size + mem_to_add))
-                               goto next;
-
-                       if (conf_override) {
-                               IWL_DEBUG_FW(fwrt,
-                                            "WRT: Trigger %d configuration override\n",
-                                            id);
-
-                               memcpy(active->trig, trig, sizeof(*trig));
-                       }
-
-                       memcpy(active->trig->data + offset, trig->data,
-                              trig_regs_size);
-                       active->trig->num_regions = cpu_to_le32(new_regs);
-               }
-
-               /* Since zero means infinity - just set to -1 */
-               if (!le32_to_cpu(active->trig->occurrences))
-                       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;
-
-       }
-}
-
-static void _iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt,
-                                   struct iwl_apply_point_data *data,
-                                   enum iwl_fw_ini_apply_point pnt,
-                                   bool ext)
-{
-       struct iwl_apply_point_data *iter;
-
-       if (!data->list.next)
-               return;
-
-       list_for_each_entry(iter, &data->list, list) {
-               struct iwl_ucode_tlv *tlv = &iter->tlv;
-               void *ini_tlv = (void *)tlv->data;
-               u32 type = le32_to_cpu(tlv->type);
-
-               switch (type) {
-               case IWL_UCODE_TLV_TYPE_DEBUG_INFO:
-                       iwl_fw_dbg_info_apply(fwrt, ini_tlv, ext, pnt);
-                       break;
-               case IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION:
-                       if (pnt != IWL_FW_INI_APPLY_EARLY) {
-                               IWL_ERR(fwrt,
-                                       "WRT: ext=%d. Invalid apply point %d for buffer allocation\n",
-                                       ext, pnt);
-                               break;
-                       }
-                       iwl_fw_dbg_buffer_apply(fwrt, ini_tlv, pnt);
-                       break;
-               case IWL_UCODE_TLV_TYPE_HCMD:
-                       if (pnt < IWL_FW_INI_APPLY_AFTER_ALIVE) {
-                               IWL_ERR(fwrt,
-                                       "WRT: ext=%d. Invalid apply point %d for host command\n",
-                                       ext, pnt);
-                               break;
-                       }
-                       iwl_fw_dbg_send_hcmd(fwrt, tlv);
-                       break;
-               case IWL_UCODE_TLV_TYPE_REGIONS:
-                       iwl_fw_dbg_update_regions(fwrt, ini_tlv, pnt);
-                       break;
-               case IWL_UCODE_TLV_TYPE_TRIGGERS:
-                       iwl_fw_dbg_update_triggers(fwrt, ini_tlv, pnt);
-                       break;
-               default:
-                       WARN_ONCE(1, "WRT: Invalid TLV 0x%x for apply point\n",
-                                 type);
-                       break;
-               }
-       }
-}
-
-static void iwl_fw_dbg_ini_reset_cfg(struct iwl_fw_runtime *fwrt)
-{
-       int i;
-
-       for (i = 0; i < IWL_FW_INI_MAX_REGION_ID; i++)
-               fwrt->dump.active_regs[i] = NULL;
-
-       /* disable the triggers, used in recovery flow */
-       for (i = 0; i < IWL_FW_TRIGGER_ID_NUM; i++)
-               fwrt->dump.active_trigs[i].active = false;
-
-       memset(fwrt->dump.img_name, 0,
-              sizeof(fwrt->dump.img_name));
-       memset(fwrt->dump.internal_dbg_cfg_name, 0,
-              sizeof(fwrt->dump.internal_dbg_cfg_name));
-       memset(fwrt->dump.external_dbg_cfg_name, 0,
-              sizeof(fwrt->dump.external_dbg_cfg_name));
-
-       fwrt->trans->dbg.ini_dest = IWL_FW_INI_LOCATION_INVALID;
-}
-
-void iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt,
-                           enum iwl_fw_ini_apply_point apply_point)
-{
-       void *data;
-
-       if (apply_point == IWL_FW_INI_APPLY_EARLY)
-               iwl_fw_dbg_ini_reset_cfg(fwrt);
-
-       if (fwrt->trans->dbg.internal_ini_cfg != IWL_INI_CFG_STATE_NOT_LOADED) {
-               IWL_DEBUG_FW(fwrt,
-                            "WRT: Enabling internal configuration apply point %d\n",
-                            apply_point);
-               data = &fwrt->trans->dbg.apply_points[apply_point];
-               _iwl_fw_dbg_apply_point(fwrt, data, apply_point, false);
-       }
-
-       if (fwrt->trans->dbg.external_ini_cfg != IWL_INI_CFG_STATE_NOT_LOADED) {
-               IWL_DEBUG_FW(fwrt,
-                            "WRT: Enabling external configuration apply point %d\n",
-                            apply_point);
-               data = &fwrt->trans->dbg.apply_points_ext[apply_point];
-               _iwl_fw_dbg_apply_point(fwrt, data, apply_point, true);
-       }
-}
-IWL_EXPORT_SYMBOL(iwl_fw_dbg_apply_point);
-
 void iwl_fw_dbg_stop_sync(struct iwl_fw_runtime *fwrt)
 {
        int i;
index 8faea25..deb84ba 100644 (file)
@@ -368,9 +368,6 @@ static inline void iwl_fw_resume_timestamp(struct iwl_fw_runtime *fwrt) {}
 
 #endif /* CONFIG_IWLWIFI_DEBUGFS */
 
-void iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt,
-                           enum iwl_fw_ini_apply_point apply_point);
-
 void iwl_fw_dbg_stop_sync(struct iwl_fw_runtime *fwrt);
 
 static inline void iwl_fw_lmac1_set_alive_err_table(struct iwl_trans *trans,
index 406ef73..0a4e13e 100644 (file)
@@ -64,7 +64,6 @@
 #include "iwl-trans.h"
 #include "img.h"
 #include "fw/api/debug.h"
-#include "fw/api/dbg-tlv.h"
 #include "fw/api/paging.h"
 #include "iwl-eeprom-parse.h"
 
index 5b1644a..b4fba73 100644 (file)
  *****************************************************************************/
 
 #include <linux/firmware.h>
+#include "iwl-drv.h"
 #include "iwl-trans.h"
 #include "iwl-dbg-tlv.h"
+#include "fw/dbg.h"
+#include "fw/runtime.h"
 
 /**
  * enum iwl_dbg_tlv_type - debug TLV types
@@ -254,3 +257,429 @@ void iwl_dbg_tlv_load_bin(struct device *dev, struct iwl_trans *trans)
 
        release_firmware(fw);
 }
+
+static void
+iwl_dbg_tlv_apply_debug_info(struct iwl_fw_runtime *fwrt,
+                            struct iwl_fw_ini_debug_info_tlv *dbg_info,
+                            bool ext, enum iwl_fw_ini_apply_point pnt)
+{
+       u32 img_name_len = le32_to_cpu(dbg_info->img_name_len);
+       u32 dbg_cfg_name_len = le32_to_cpu(dbg_info->dbg_cfg_name_len);
+       const char err_str[] =
+               "WRT: Invalid %s name length %d, expected %d\n";
+
+       if (img_name_len != IWL_FW_INI_MAX_IMG_NAME_LEN) {
+               IWL_WARN(fwrt, err_str, "image", img_name_len,
+                        IWL_FW_INI_MAX_IMG_NAME_LEN);
+               return;
+       }
+
+       if (dbg_cfg_name_len != IWL_FW_INI_MAX_DBG_CFG_NAME_LEN) {
+               IWL_WARN(fwrt, err_str, "debug cfg", dbg_cfg_name_len,
+                        IWL_FW_INI_MAX_DBG_CFG_NAME_LEN);
+               return;
+       }
+
+       if (ext) {
+               memcpy(fwrt->dump.external_dbg_cfg_name, dbg_info->dbg_cfg_name,
+                      sizeof(fwrt->dump.external_dbg_cfg_name));
+       } else {
+               memcpy(fwrt->dump.img_name, dbg_info->img_name,
+                      sizeof(fwrt->dump.img_name));
+               memcpy(fwrt->dump.internal_dbg_cfg_name, dbg_info->dbg_cfg_name,
+                      sizeof(fwrt->dump.internal_dbg_cfg_name));
+       }
+}
+
+static void iwl_dbg_tlv_alloc_buffer(struct iwl_fw_runtime *fwrt, u32 size)
+{
+       struct iwl_trans *trans = fwrt->trans;
+       void *virtual_addr = NULL;
+       dma_addr_t phys_addr;
+
+       if (WARN_ON_ONCE(trans->dbg.num_blocks ==
+                        ARRAY_SIZE(trans->dbg.fw_mon)))
+               return;
+
+       virtual_addr =
+               dma_alloc_coherent(fwrt->trans->dev, size, &phys_addr,
+                                  GFP_KERNEL | __GFP_NOWARN);
+
+       /* TODO: alloc fragments if needed */
+       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->dbg.num_blocks, size);
+
+       trans->dbg.fw_mon[trans->dbg.num_blocks].block = virtual_addr;
+       trans->dbg.fw_mon[trans->dbg.num_blocks].physical = phys_addr;
+       trans->dbg.fw_mon[trans->dbg.num_blocks].size = size;
+       trans->dbg.num_blocks++;
+}
+
+static void iwl_dbg_tlv_apply_buffer(struct iwl_fw_runtime *fwrt,
+                                    struct iwl_fw_ini_allocation_tlv *alloc,
+                                    enum iwl_fw_ini_apply_point pnt)
+{
+       struct iwl_trans *trans = fwrt->trans;
+       struct iwl_ldbg_config_cmd ldbg_cmd = {
+               .type = cpu_to_le32(BUFFER_ALLOCATION),
+       };
+       struct iwl_buffer_allocation_cmd *cmd = &ldbg_cmd.buffer_allocation;
+       struct iwl_host_cmd hcmd = {
+               .id = LDBG_CONFIG_CMD,
+               .flags = CMD_ASYNC,
+               .data[0] = &ldbg_cmd,
+               .len[0] = sizeof(ldbg_cmd),
+       };
+       int block_idx = trans->dbg.num_blocks;
+       u32 buf_location = le32_to_cpu(alloc->buffer_location);
+       u32 alloc_id = le32_to_cpu(alloc->allocation_id);
+
+       if (alloc_id <= IWL_FW_INI_ALLOCATION_INVALID ||
+           alloc_id >= IWL_FW_INI_ALLOCATION_NUM) {
+               IWL_ERR(fwrt, "WRT: Invalid allocation id %d\n", alloc_id);
+               return;
+       }
+
+       if (fwrt->trans->dbg.ini_dest == IWL_FW_INI_LOCATION_INVALID)
+               fwrt->trans->dbg.ini_dest = buf_location;
+
+       if (buf_location != fwrt->trans->dbg.ini_dest) {
+               WARN(fwrt,
+                    "WRT: attempt to override buffer location on apply point %d\n",
+                    pnt);
+
+               return;
+       }
+
+       if (buf_location == IWL_FW_INI_LOCATION_SRAM_PATH) {
+               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;
+       }
+
+       if (buf_location != IWL_FW_INI_LOCATION_DRAM_PATH)
+               return;
+
+       if (!(BIT(alloc_id) & fwrt->trans->dbg.is_alloc)) {
+               iwl_dbg_tlv_alloc_buffer(fwrt, le32_to_cpu(alloc->size));
+               if (block_idx == trans->dbg.num_blocks)
+                       return;
+               fwrt->trans->dbg.is_alloc |= BIT(alloc_id);
+       }
+
+       /* First block is assigned via registers / context info */
+       if (trans->dbg.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->dbg.fw_mon[block_idx].physical);
+       cmd->fragments[0].size = alloc->size;
+       cmd->allocation_id = alloc->allocation_id;
+       cmd->buffer_location = alloc->buffer_location;
+
+       iwl_trans_send_cmd(trans, &hcmd);
+}
+
+static void iwl_dbg_tlv_apply_hcmd(struct iwl_fw_runtime *fwrt,
+                                  struct iwl_ucode_tlv *tlv)
+{
+       struct iwl_fw_ini_hcmd_tlv *hcmd_tlv = (void *)&tlv->data[0];
+       struct iwl_fw_ini_hcmd *data = &hcmd_tlv->hcmd;
+       u16 len = le32_to_cpu(tlv->length) - sizeof(*hcmd_tlv);
+
+       struct iwl_host_cmd hcmd = {
+               .id = WIDE_ID(data->group, data->id),
+               .len = { len, },
+               .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_DEBUG_FW(fwrt, "WRT: Sending host command id=0x%x, group=0x%x\n",
+                    data->id, data->group);
+
+       iwl_trans_send_cmd(fwrt->trans, &hcmd);
+}
+
+static void iwl_dbg_tlv_apply_region(struct iwl_fw_runtime *fwrt,
+                                    struct iwl_fw_ini_region_tlv *tlv,
+                                    enum iwl_fw_ini_apply_point pnt)
+{
+       void *iter = (void *)tlv->region_config;
+       int i, size = le32_to_cpu(tlv->num_regions);
+       const char *err_st =
+               "WRT: 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), err_st, "id",
+                        id, pnt))
+                       break;
+
+               if (WARN(type == 0 || type >= IWL_FW_INI_REGION_NUM, err_st,
+                        "type", type, pnt))
+                       break;
+
+               active = &fwrt->dump.active_regs[id];
+
+               if (*active)
+                       IWL_WARN(fwrt->trans, "WRT: Region id %d override\n",
+                                id);
+
+               IWL_DEBUG_FW(fwrt, "WRT: Activating region id %d\n", id);
+
+               *active = reg;
+
+               if (type == IWL_FW_INI_REGION_TXF ||
+                   type == IWL_FW_INI_REGION_RXF)
+                       iter += le32_to_cpu(reg->fifos.num_of_registers) *
+                               sizeof(__le32);
+               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 ||
+                        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);
+
+               iter += sizeof(*reg);
+       }
+}
+
+static int iwl_dbg_tlv_trig_realloc(struct iwl_fw_runtime *fwrt,
+                                   struct iwl_fw_ini_active_triggers *active,
+                                   u32 id, int size)
+{
+       void *ptr;
+
+       if (size <= active->size)
+               return 0;
+
+       ptr = krealloc(active->trig, size, GFP_KERNEL);
+       if (!ptr) {
+               IWL_ERR(fwrt, "WRT: Failed to allocate memory for trigger %d\n",
+                       id);
+               return -ENOMEM;
+       }
+       active->trig = ptr;
+       active->size = size;
+
+       return 0;
+}
+
+static void iwl_dbg_tlv_apply_trigger(struct iwl_fw_runtime *fwrt,
+                                     struct iwl_fw_ini_trigger_tlv *tlv,
+                                     enum iwl_fw_ini_apply_point apply_point)
+{
+       int i, size = le32_to_cpu(tlv->num_triggers);
+       void *iter = (void *)tlv->trigger_config;
+
+       for (i = 0; i < size; i++) {
+               struct iwl_fw_ini_trigger *trig = iter;
+               struct iwl_fw_ini_active_triggers *active;
+               int id = le32_to_cpu(trig->trigger_id);
+               u32 trig_regs_size = le32_to_cpu(trig->num_regions) *
+                       sizeof(__le32);
+
+               if (WARN(id >= ARRAY_SIZE(fwrt->dump.active_trigs),
+                        "WRT: Invalid trigger id %d for apply point %d\n", id,
+                        apply_point))
+                       break;
+
+               active = &fwrt->dump.active_trigs[id];
+
+               if (!active->active) {
+                       size_t trig_size = sizeof(*trig) + trig_regs_size;
+
+                       IWL_DEBUG_FW(fwrt, "WRT: Activating trigger %d\n", id);
+
+                       if (iwl_dbg_tlv_trig_realloc(fwrt, active, id,
+                                                    trig_size))
+                               goto next;
+
+                       memcpy(active->trig, trig, trig_size);
+
+               } else {
+                       u32 conf_override =
+                               !(le32_to_cpu(trig->override_trig) & 0xff);
+                       u32 region_override =
+                               !(le32_to_cpu(trig->override_trig) & 0xff00);
+                       u32 offset = 0;
+                       u32 active_regs =
+                               le32_to_cpu(active->trig->num_regions);
+                       u32 new_regs = le32_to_cpu(trig->num_regions);
+                       int mem_to_add = trig_regs_size;
+
+                       if (region_override) {
+                               IWL_DEBUG_FW(fwrt,
+                                            "WRT: Trigger %d regions override\n",
+                                            id);
+
+                               mem_to_add -= active_regs * sizeof(__le32);
+                       } else {
+                               IWL_DEBUG_FW(fwrt,
+                                            "WRT: Trigger %d regions appending\n",
+                                            id);
+
+                               offset += active_regs;
+                               new_regs += active_regs;
+                       }
+
+                       if (iwl_dbg_tlv_trig_realloc(fwrt, active, id,
+                                                    active->size + mem_to_add))
+                               goto next;
+
+                       if (conf_override) {
+                               IWL_DEBUG_FW(fwrt,
+                                            "WRT: Trigger %d configuration override\n",
+                                            id);
+
+                               memcpy(active->trig, trig, sizeof(*trig));
+                       }
+
+                       memcpy(active->trig->data + offset, trig->data,
+                              trig_regs_size);
+                       active->trig->num_regions = cpu_to_le32(new_regs);
+               }
+
+               /* Since zero means infinity - just set to -1 */
+               if (!le32_to_cpu(active->trig->occurrences))
+                       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;
+       }
+}
+
+static void _iwl_dbg_tlv_apply_point(struct iwl_fw_runtime *fwrt,
+                                    struct iwl_apply_point_data *data,
+                                    enum iwl_fw_ini_apply_point pnt,
+                                    bool ext)
+{
+       struct iwl_apply_point_data *iter;
+
+       if (!data->list.next)
+               return;
+
+       list_for_each_entry(iter, &data->list, list) {
+               struct iwl_ucode_tlv *tlv = &iter->tlv;
+               void *ini_tlv = (void *)tlv->data;
+               u32 type = le32_to_cpu(tlv->type);
+               const char invalid_ap_str[] =
+                       "WRT: Invalid apply point %d for %s\n";
+
+               switch (type) {
+               case IWL_UCODE_TLV_TYPE_DEBUG_INFO:
+                       iwl_dbg_tlv_apply_debug_info(fwrt, ini_tlv, ext, pnt);
+                       break;
+               case IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION:
+                       if (pnt != IWL_FW_INI_APPLY_EARLY) {
+                               IWL_ERR(fwrt, invalid_ap_str, pnt,
+                                       "buffer allocation");
+                               break;
+                       }
+                       iwl_dbg_tlv_apply_buffer(fwrt, ini_tlv, pnt);
+                       break;
+               case IWL_UCODE_TLV_TYPE_HCMD:
+                       if (pnt < IWL_FW_INI_APPLY_AFTER_ALIVE) {
+                               IWL_ERR(fwrt, invalid_ap_str, pnt,
+                                       "host command");
+                               break;
+                       }
+                       iwl_dbg_tlv_apply_hcmd(fwrt, tlv);
+                       break;
+               case IWL_UCODE_TLV_TYPE_REGIONS:
+                       iwl_dbg_tlv_apply_region(fwrt, ini_tlv, pnt);
+                       break;
+               case IWL_UCODE_TLV_TYPE_TRIGGERS:
+                       iwl_dbg_tlv_apply_trigger(fwrt, ini_tlv, pnt);
+                       break;
+               default:
+                       WARN_ONCE(1, "WRT: Invalid TLV 0x%x for apply point\n",
+                                 type);
+                       break;
+               }
+       }
+}
+
+static void iwl_dbg_tlv_reset_cfg(struct iwl_fw_runtime *fwrt)
+{
+       int i;
+
+       for (i = 0; i < IWL_FW_INI_MAX_REGION_ID; i++)
+               fwrt->dump.active_regs[i] = NULL;
+
+       /* disable the triggers, used in recovery flow */
+       for (i = 0; i < IWL_FW_TRIGGER_ID_NUM; i++)
+               fwrt->dump.active_trigs[i].active = false;
+
+       memset(fwrt->dump.img_name, 0,
+              sizeof(fwrt->dump.img_name));
+       memset(fwrt->dump.internal_dbg_cfg_name, 0,
+              sizeof(fwrt->dump.internal_dbg_cfg_name));
+       memset(fwrt->dump.external_dbg_cfg_name, 0,
+              sizeof(fwrt->dump.external_dbg_cfg_name));
+
+       fwrt->trans->dbg.ini_dest = IWL_FW_INI_LOCATION_INVALID;
+}
+
+void iwl_dbg_tlv_apply_point(struct iwl_fw_runtime *fwrt,
+                            enum iwl_fw_ini_apply_point apply_point)
+{
+       void *data;
+
+       if (apply_point == IWL_FW_INI_APPLY_EARLY)
+               iwl_dbg_tlv_reset_cfg(fwrt);
+
+       if (fwrt->trans->dbg.internal_ini_cfg != IWL_INI_CFG_STATE_NOT_LOADED) {
+               IWL_DEBUG_FW(fwrt,
+                            "WRT: Enabling internal configuration apply point %d\n",
+                            apply_point);
+               data = &fwrt->trans->dbg.apply_points[apply_point];
+               _iwl_dbg_tlv_apply_point(fwrt, data, apply_point, false);
+       }
+
+       if (fwrt->trans->dbg.external_ini_cfg != IWL_INI_CFG_STATE_NOT_LOADED) {
+               IWL_DEBUG_FW(fwrt,
+                            "WRT: Enabling external configuration apply point %d\n",
+                            apply_point);
+               data = &fwrt->trans->dbg.apply_points_ext[apply_point];
+               _iwl_dbg_tlv_apply_point(fwrt, data, apply_point, true);
+       }
+}
+IWL_EXPORT_SYMBOL(iwl_dbg_tlv_apply_point);
index 3a60590..9349694 100644 (file)
@@ -75,9 +75,13 @@ struct iwl_apply_point_data {
 };
 
 struct iwl_trans;
+struct iwl_fw_runtime;
+
 void iwl_dbg_tlv_load_bin(struct device *dev, struct iwl_trans *trans);
 void iwl_dbg_tlv_free(struct iwl_trans *trans);
 void iwl_dbg_tlv_alloc(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv,
                       bool ext);
+void iwl_dbg_tlv_apply_point(struct iwl_fw_runtime *fwrt,
+                            enum iwl_fw_ini_apply_point apply_point);
 
 #endif /* __iwl_dbg_tlv_h__*/
index a6e3601..f09f240 100644 (file)
@@ -430,7 +430,7 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
                                   iwl_wait_init_complete,
                                   NULL);
 
-       iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_EARLY);
+       iwl_dbg_tlv_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_EARLY);
 
        /* Will also start the device */
        ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_REGULAR);
@@ -438,7 +438,7 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
                IWL_ERR(mvm, "Failed to start RT ucode: %d\n", ret);
                goto error;
        }
-       iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_AFTER_ALIVE);
+       iwl_dbg_tlv_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_AFTER_ALIVE);
 
        /* Send init config command to mark that we are sending NVM access
         * commands
@@ -1263,7 +1263,7 @@ static int iwl_mvm_load_rt_fw(struct iwl_mvm *mvm)
        if (ret)
                return ret;
 
-       iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_EARLY);
+       iwl_dbg_tlv_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_EARLY);
 
        mvm->rfkill_safe_init_done = false;
        ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_REGULAR);
@@ -1272,7 +1272,7 @@ static int iwl_mvm_load_rt_fw(struct iwl_mvm *mvm)
 
        mvm->rfkill_safe_init_done = true;
 
-       iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_AFTER_ALIVE);
+       iwl_dbg_tlv_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_AFTER_ALIVE);
 
        return iwl_init_paging(&mvm->fwrt, mvm->fwrt.cur_fw_img);
 }
index 8fa3564..62536c0 100644 (file)
@@ -1447,7 +1447,7 @@ void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
            rx_missed_bcon >= stop_trig_missed_bcon)
                iwl_fw_dbg_collect_trig(&mvm->fwrt, trigger, NULL);
 
-       iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_MISSED_BEACONS);
+       iwl_dbg_tlv_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_MISSED_BEACONS);
 
 out:
        rcu_read_unlock();
index b8d8250..acc7fee 100644 (file)
@@ -1106,7 +1106,7 @@ int __iwl_mvm_mac_start(struct iwl_mvm *mvm)
        }
        ret = iwl_mvm_up(mvm);
 
-       iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_POST_INIT);
+       iwl_dbg_tlv_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_POST_INIT);
 
        if (ret && test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
                /* Something went wrong - we need to finish some cleanup
index afa4434..892db3d 100644 (file)
@@ -1940,7 +1940,7 @@ void iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm,
 
        mvm->scan_uid_status[uid] = 0;
 
-       iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_SCAN_COMPLETE);
+       iwl_dbg_tlv_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_SCAN_COMPLETE);
 }
 
 void iwl_mvm_rx_umac_scan_iter_complete_notif(struct iwl_mvm *mvm,