OSDN Git Service

iwlwifi: yoyo: add PCI config space region type
authorLuca Coelho <luciano.coelho@intel.com>
Fri, 1 Nov 2019 13:31:02 +0000 (15:31 +0200)
committerLuca Coelho <luciano.coelho@intel.com>
Fri, 27 Mar 2020 06:12:47 +0000 (08:12 +0200)
Add a new region type that allows us to dump the PCI config space.
This is mostly the same as dumping a memory region, but reading from
the device's config space instead.

In order to make this generic and independent of the trans type, we
make a function called iwl_dump_ini_config_iter() that calls a new op
in the transport to read its config space.

Change-Id: I15151bddf589f13b0e0a45c28b96bbcd73bcfdeb
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
drivers/net/wireless/intel/iwlwifi/fw/dbg.c
drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
drivers/net/wireless/intel/iwlwifi/iwl-trans.h

index 91df1ee..d5dda93 100644 (file)
@@ -1108,6 +1108,38 @@ static int iwl_dump_ini_csr_iter(struct iwl_fw_runtime *fwrt,
        return sizeof(*range) + le32_to_cpu(range->range_data_size);
 }
 
+static int iwl_dump_ini_config_iter(struct iwl_fw_runtime *fwrt,
+                                   struct iwl_dump_ini_region_data *reg_data,
+                                   void *range_ptr, int idx)
+{
+       struct iwl_trans *trans = fwrt->trans;
+       struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
+       struct iwl_fw_ini_error_dump_range *range = range_ptr;
+       __le32 *val = range->data;
+       u32 addr = le32_to_cpu(reg->addrs[idx]) +
+                  le32_to_cpu(reg->dev_addr.offset);
+       int i;
+
+       /* we shouldn't get here if the trans doesn't have read_config32 */
+       if (WARN_ON_ONCE(!trans->ops->read_config32))
+               return -EOPNOTSUPP;
+
+       range->internal_base_addr = cpu_to_le32(addr);
+       range->range_data_size = reg->dev_addr.size;
+       for (i = 0; i < le32_to_cpu(reg->dev_addr.size); i += 4) {
+               int ret;
+               u32 tmp;
+
+               ret = trans->ops->read_config32(trans, addr + i, &tmp);
+               if (ret < 0)
+                       return ret;
+
+               *val++ = cpu_to_le32(tmp);
+       }
+
+       return sizeof(*range) + le32_to_cpu(range->range_data_size);
+}
+
 static int iwl_dump_ini_dev_mem_iter(struct iwl_fw_runtime *fwrt,
                                     struct iwl_dump_ini_region_data *reg_data,
                                     void *range_ptr, int idx)
@@ -2052,7 +2084,12 @@ static const struct iwl_dump_ini_mem_ops iwl_dump_ini_region_ops[] = {
                .fill_range = iwl_dump_ini_csr_iter,
        },
        [IWL_FW_INI_REGION_DRAM_IMR] = {},
-       [IWL_FW_INI_REGION_PCI_IOSF_CONFIG] = {},
+       [IWL_FW_INI_REGION_PCI_IOSF_CONFIG] = {
+               .get_num_of_ranges = iwl_dump_ini_mem_ranges,
+               .get_size = iwl_dump_ini_mem_get_size,
+               .fill_mem_hdr = iwl_dump_ini_mem_fill_header,
+               .fill_range = iwl_dump_ini_config_iter,
+       },
 };
 
 static u32 iwl_dump_ini_trigger(struct iwl_fw_runtime *fwrt,
index 4208e72..bf2f00b 100644 (file)
@@ -236,6 +236,12 @@ static int iwl_dbg_tlv_alloc_region(struct iwl_trans *trans,
                return -EINVAL;
        }
 
+       if (type == IWL_FW_INI_REGION_PCI_IOSF_CONFIG &&
+           !trans->ops->read_config32) {
+               IWL_ERR(trans, "WRT: Unsupported region type %u\n", type);
+               return -EOPNOTSUPP;
+       }
+
        active_reg = &trans->dbg.active_regions[id];
        if (*active_reg) {
                IWL_WARN(trans, "WRT: Overriding region id %u\n", id);
index 7b3b1f4..bba527b 100644 (file)
@@ -544,6 +544,8 @@ struct iwl_trans_rxq_dma_data {
  * @read_mem: read device's SRAM in DWORD
  * @write_mem: write device's SRAM in DWORD. If %buf is %NULL, then the memory
  *     will be zeroed.
+ * @read_config32: read a u32 value from the device's config space at
+ *     the given offset.
  * @configure: configure parameters required by the transport layer from
  *     the op_mode. May be called several times before start_fw, can't be
  *     called after that.
@@ -614,6 +616,7 @@ struct iwl_trans_ops {
                        void *buf, int dwords);
        int (*write_mem)(struct iwl_trans *trans, u32 addr,
                         const void *buf, int dwords);
+       int (*read_config32)(struct iwl_trans *trans, u32 ofs, u32 *val);
        void (*configure)(struct iwl_trans *trans,
                          const struct iwl_trans_config *trans_cfg);
        void (*set_pmi)(struct iwl_trans *trans, bool state);