Commit f696a7ee authored by Luca Coelho's avatar Luca Coelho
Browse files

iwlwifi: yoyo: add PCI config space region type



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: default avatarLuca Coelho <luciano.coelho@intel.com>
parent cceb4507
Loading
Loading
Loading
Loading
+38 −1
Original line number Diff line number Diff line
@@ -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,
+6 −0
Original line number Diff line number Diff line
@@ -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);
+3 −0
Original line number Diff line number Diff line
@@ -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);