Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c1219653 authored by Rahul Lakkireddy's avatar Rahul Lakkireddy Committed by David S. Miller
Browse files

cxgb4: skip TX and RX payload regions in memory dumps



Use meminfo to identify TX and RX payload regions and skip them in
collection of EDC, MC, and HMA.

Signed-off-by: default avatarRahul Lakkireddy <rahul.lakkireddy@chelsio.com>
Signed-off-by: default avatarGanesh Goudar <ganeshgr@chelsio.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 4db0401f
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -95,6 +95,13 @@ static const char * const cudbg_region[] = {
	"On-chip queues:"
};

/* Memory region info relative to current memory (i.e. wrt 0). */
struct cudbg_region_info {
	bool exist; /* Does region exists in current memory? */
	u32 start;  /* Start wrt 0 */
	u32 end;    /* End wrt 0 */
};

struct cudbg_mem_desc {
	u32 base;
	u32 limit;
+141 −0
Original line number Diff line number Diff line
@@ -730,6 +730,116 @@ static int cudbg_meminfo_get_mem_index(struct adapter *padap,
	return CUDBG_STATUS_ENTITY_NOT_FOUND;
}

/* Fetch the @region_name's start and end from @meminfo. */
static int cudbg_get_mem_region(struct adapter *padap,
				struct cudbg_meminfo *meminfo,
				u8 mem_type, const char *region_name,
				struct cudbg_mem_desc *mem_desc)
{
	u8 mc, found = 0;
	u32 i, idx = 0;
	int rc;

	rc = cudbg_meminfo_get_mem_index(padap, meminfo, mem_type, &mc);
	if (rc)
		return rc;

	for (i = 0; i < ARRAY_SIZE(cudbg_region); i++) {
		if (!strcmp(cudbg_region[i], region_name)) {
			found = 1;
			idx = i;
			break;
		}
	}
	if (!found)
		return -EINVAL;

	found = 0;
	for (i = 0; i < meminfo->mem_c; i++) {
		if (meminfo->mem[i].idx >= ARRAY_SIZE(cudbg_region))
			continue; /* Skip holes */

		if (!(meminfo->mem[i].limit))
			meminfo->mem[i].limit =
				i < meminfo->mem_c - 1 ?
				meminfo->mem[i + 1].base - 1 : ~0;

		if (meminfo->mem[i].idx == idx) {
			/* Check if the region exists in @mem_type memory */
			if (meminfo->mem[i].base < meminfo->avail[mc].base &&
			    meminfo->mem[i].limit < meminfo->avail[mc].base)
				return -EINVAL;

			if (meminfo->mem[i].base > meminfo->avail[mc].limit)
				return -EINVAL;

			memcpy(mem_desc, &meminfo->mem[i],
			       sizeof(struct cudbg_mem_desc));
			found = 1;
			break;
		}
	}
	if (!found)
		return -EINVAL;

	return 0;
}

/* Fetch and update the start and end of the requested memory region w.r.t 0
 * in the corresponding EDC/MC/HMA.
 */
static int cudbg_get_mem_relative(struct adapter *padap,
				  struct cudbg_meminfo *meminfo,
				  u8 mem_type, u32 *out_base, u32 *out_end)
{
	u8 mc_idx;
	int rc;

	rc = cudbg_meminfo_get_mem_index(padap, meminfo, mem_type, &mc_idx);
	if (rc)
		return rc;

	if (*out_base < meminfo->avail[mc_idx].base)
		*out_base = 0;
	else
		*out_base -= meminfo->avail[mc_idx].base;

	if (*out_end > meminfo->avail[mc_idx].limit)
		*out_end = meminfo->avail[mc_idx].limit;
	else
		*out_end -= meminfo->avail[mc_idx].base;

	return 0;
}

/* Get TX and RX Payload region */
static int cudbg_get_payload_range(struct adapter *padap, u8 mem_type,
				   const char *region_name,
				   struct cudbg_region_info *payload)
{
	struct cudbg_mem_desc mem_desc = { 0 };
	struct cudbg_meminfo meminfo;
	int rc;

	rc = cudbg_fill_meminfo(padap, &meminfo);
	if (rc)
		return rc;

	rc = cudbg_get_mem_region(padap, &meminfo, mem_type, region_name,
				  &mem_desc);
	if (rc) {
		payload->exist = false;
		return 0;
	}

	payload->exist = true;
	payload->start = mem_desc.base;
	payload->end = mem_desc.limit;

	return cudbg_get_mem_relative(padap, &meminfo, mem_type,
				      &payload->start, &payload->end);
}

#define CUDBG_YIELD_ITERATION 256

static int cudbg_read_fw_mem(struct cudbg_init *pdbg_init,
@@ -737,11 +847,32 @@ static int cudbg_read_fw_mem(struct cudbg_init *pdbg_init,
			     unsigned long tot_len,
			     struct cudbg_error *cudbg_err)
{
	static const char * const region_name[] = { "Tx payload:",
						    "Rx payload:" };
	unsigned long bytes, bytes_left, bytes_read = 0;
	struct adapter *padap = pdbg_init->adap;
	struct cudbg_buffer temp_buff = { 0 };
	struct cudbg_region_info payload[2];
	u32 yield_count = 0;
	int rc = 0;
	u8 i;

	/* Get TX/RX Payload region range if they exist */
	memset(payload, 0, sizeof(payload));
	for (i = 0; i < ARRAY_SIZE(region_name); i++) {
		rc = cudbg_get_payload_range(padap, mem_type, region_name[i],
					     &payload[i]);
		if (rc)
			return rc;

		if (payload[i].exist) {
			/* Align start and end to avoid wrap around */
			payload[i].start = roundup(payload[i].start,
						   CUDBG_CHUNK_SIZE);
			payload[i].end = rounddown(payload[i].end,
						   CUDBG_CHUNK_SIZE);
		}
	}

	bytes_left = tot_len;
	while (bytes_left > 0) {
@@ -759,6 +890,14 @@ static int cudbg_read_fw_mem(struct cudbg_init *pdbg_init,
		rc = cudbg_get_buff(dbg_buff, bytes, &temp_buff);
		if (rc)
			return rc;

		for (i = 0; i < ARRAY_SIZE(payload); i++)
			if (payload[i].exist &&
			    bytes_read >= payload[i].start &&
			    bytes_read + bytes <= payload[i].end)
				/* TX and RX Payload regions can't overlap */
				goto skip_read;

		spin_lock(&padap->win0_lock);
		rc = t4_memory_rw(padap, MEMWIN_NIC, mem_type,
				  bytes_read, bytes,
@@ -770,6 +909,8 @@ static int cudbg_read_fw_mem(struct cudbg_init *pdbg_init,
			cudbg_put_buff(&temp_buff, dbg_buff);
			return rc;
		}

skip_read:
		bytes_left -= bytes;
		bytes_read += bytes;
		cudbg_write_and_release_buff(&temp_buff, dbg_buff);