OSDN Git Service

iwlwifi: dbg: add dumping special device memory
authorMordechay Goodstein <mordechay.goodstein@intel.com>
Fri, 25 Sep 2020 21:30:40 +0000 (00:30 +0300)
committerLuca Coelho <luciano.coelho@intel.com>
Thu, 1 Oct 2020 18:57:21 +0000 (21:57 +0300)
With the new region we can handle in user space understanding
the struct type and version and driver doesn't need to be involved
at all.

Signed-off-by: Mordechay Goodstein <mordechay.goodstein@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/iwlwifi.20200926002540.88c431fad7da.I282944cbad5aa367735a9f9a5c47cfbd107a5fc0@changeid
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h
drivers/net/wireless/intel/iwlwifi/fw/dbg.c
drivers/net/wireless/intel/iwlwifi/fw/error-dump.h
drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c

index 8e34b50..cefd833 100644 (file)
@@ -135,6 +135,25 @@ struct iwl_fw_ini_region_err_table {
 } __packed; /* FW_TLV_DEBUG_REGION_ERROR_TABLE_API_S_VER_1 */
 
 /**
+ * struct iwl_fw_ini_region_special_device_memory - special device memory
+ *
+ * Configuration to read a special memory
+ *
+ * @type: type of the special memory
+ * @version: version of the special memory
+ * @base_addr: base address of the error table
+ * @size: size of the error table
+ * @offset: offset to add to &base_addr
+ */
+struct iwl_fw_ini_region_special_device_memory {
+       __le16 type;
+       __le16 version;
+       __le32 base_addr;
+       __le32 size;
+       __le32 offset;
+} __packed; /* FW_TLV_DEBUG_REGION_SPECIAL_DEVICE_ADDR_API_S_VER_1 */
+
+/**
  * struct iwl_fw_ini_region_internal_buffer - internal buffer region data
  *
  * Configuration to read internal monitor buffer
@@ -185,6 +204,7 @@ struct iwl_fw_ini_region_tlv {
                struct iwl_fw_ini_region_fifos fifos;
                struct iwl_fw_ini_region_err_table err_table;
                struct iwl_fw_ini_region_internal_buffer internal_buffer;
+               struct iwl_fw_ini_region_special_device_memory special_mem;
                __le32 dram_alloc_id;
                __le32 tlv_mask;
        }; /* FW_TLV_DEBUG_REGION_CONF_PARAMS_API_U_VER_1 */
@@ -327,6 +347,7 @@ enum iwl_fw_ini_buffer_location {
  * @IWL_FW_INI_REGION_CSR: CSR registers
  * @IWL_FW_INI_REGION_DRAM_IMR: IMR memory
  * @IWL_FW_INI_REGION_PCI_IOSF_CONFIG: PCI/IOSF config
+ * @IWL_FW_INI_REGION_SPECIAL_DEVICE_MEMORY: special device memroy
  * @IWL_FW_INI_REGION_NUM: number of region types
  */
 enum iwl_fw_ini_region_type {
@@ -347,6 +368,7 @@ enum iwl_fw_ini_region_type {
        IWL_FW_INI_REGION_CSR,
        IWL_FW_INI_REGION_DRAM_IMR,
        IWL_FW_INI_REGION_PCI_IOSF_CONFIG,
+       IWL_FW_INI_REGION_SPECIAL_DEVICE_MEMORY,
        IWL_FW_INI_REGION_NUM
 }; /* FW_TLV_DEBUG_REGION_TYPE_API_E */
 
index 7ea55cf..ab4a8b9 100644 (file)
@@ -1507,6 +1507,27 @@ iwl_dump_ini_err_table_iter(struct iwl_fw_runtime *fwrt,
        return sizeof(*range) + le32_to_cpu(range->range_data_size);
 }
 
+static int
+iwl_dump_ini_special_mem_iter(struct iwl_fw_runtime *fwrt,
+                             struct iwl_dump_ini_region_data *reg_data,
+                             void *range_ptr, int idx)
+{
+       struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
+       struct iwl_fw_ini_region_special_device_memory *special_mem =
+               &reg->special_mem;
+
+       struct iwl_fw_ini_error_dump_range *range = range_ptr;
+       u32 addr = le32_to_cpu(special_mem->base_addr) +
+                  le32_to_cpu(special_mem->offset);
+
+       range->internal_base_addr = cpu_to_le32(addr);
+       range->range_data_size = special_mem->size;
+       iwl_trans_read_mem_bytes(fwrt->trans, addr, range->data,
+                                le32_to_cpu(special_mem->size));
+
+       return sizeof(*range) + le32_to_cpu(range->range_data_size);
+}
+
 static int iwl_dump_ini_fw_pkt_iter(struct iwl_fw_runtime *fwrt,
                                    struct iwl_dump_ini_region_data *reg_data,
                                    void *range_ptr, int idx)
@@ -1636,6 +1657,21 @@ iwl_dump_ini_err_table_fill_header(struct iwl_fw_runtime *fwrt,
        return dump->ranges;
 }
 
+static void *
+iwl_dump_ini_special_mem_fill_header(struct iwl_fw_runtime *fwrt,
+                                    struct iwl_dump_ini_region_data *reg_data,
+                                    void *data)
+{
+       struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
+       struct iwl_fw_ini_special_device_memory *dump = data;
+
+       dump->header.version = cpu_to_le32(IWL_INI_DUMP_VER);
+       dump->type = reg->special_mem.type;
+       dump->version = reg->special_mem.version;
+
+       return dump->ranges;
+}
+
 static u32 iwl_dump_ini_mem_ranges(struct iwl_fw_runtime *fwrt,
                                   struct iwl_dump_ini_region_data *reg_data)
 {
@@ -1827,6 +1863,20 @@ iwl_dump_ini_err_table_get_size(struct iwl_fw_runtime *fwrt,
 }
 
 static u32
+iwl_dump_ini_special_mem_get_size(struct iwl_fw_runtime *fwrt,
+                                 struct iwl_dump_ini_region_data *reg_data)
+{
+       struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
+       u32 size = le32_to_cpu(reg->special_mem.size);
+
+       if (size)
+               size += sizeof(struct iwl_fw_ini_special_device_memory) +
+                       sizeof(struct iwl_fw_ini_error_dump_range);
+
+       return size;
+}
+
+static u32
 iwl_dump_ini_fw_pkt_get_size(struct iwl_fw_runtime *fwrt,
                             struct iwl_dump_ini_region_data *reg_data)
 {
@@ -2125,6 +2175,12 @@ static const struct iwl_dump_ini_mem_ops iwl_dump_ini_region_ops[] = {
                .fill_mem_hdr = iwl_dump_ini_mem_fill_header,
                .fill_range = iwl_dump_ini_config_iter,
        },
+       [IWL_FW_INI_REGION_SPECIAL_DEVICE_MEMORY] = {
+               .get_num_of_ranges = iwl_dump_ini_single_range,
+               .get_size = iwl_dump_ini_special_mem_get_size,
+               .fill_mem_hdr = iwl_dump_ini_special_mem_fill_header,
+               .fill_range = iwl_dump_ini_special_mem_iter,
+       },
 };
 
 static u32 iwl_dump_ini_trigger(struct iwl_fw_runtime *fwrt,
index 72bfc64..cb40f50 100644 (file)
@@ -495,6 +495,20 @@ struct iwl_fw_ini_monitor_dump {
 } __packed;
 
 /**
+ * struct iwl_fw_ini_special_device_memory - special device memory
+ * @header: header of the region
+ * @type: type of special memory
+ * @version: struct special memory version
+ * @ranges: the memory ranges of this this region
+ */
+struct iwl_fw_ini_special_device_memory {
+       struct iwl_fw_ini_error_dump_header header;
+       __le16 type;
+       __le16 version;
+       struct iwl_fw_ini_error_dump_range ranges[];
+} __packed;
+
+/**
  * struct iwl_fw_error_dump_paging - content of the UMAC's image page
  *     block on DRAM
  * @index: the index of the page block
index 9ce7207..c44e61a 100644 (file)
@@ -233,6 +233,13 @@ static int iwl_dbg_tlv_alloc_region(struct iwl_trans *trans,
        if (le32_to_cpu(tlv->length) < sizeof(*reg))
                return -EINVAL;
 
+       /* For safe using a string from FW make sure we have a
+        * null terminator
+        */
+       reg->name[IWL_FW_INI_MAX_NAME - 1] = 0;
+
+       IWL_DEBUG_FW(trans, "WRT: parsing region: %s\n", reg->name);
+
        if (id >= IWL_FW_INI_MAX_REGION_ID) {
                IWL_ERR(trans, "WRT: Invalid region id %u\n", id);
                return -EINVAL;