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: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
Signed-off-by: Ganesh Goudar <ganeshgr@chelsio.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Rahul Lakkireddy 2017-12-08 09:48:39 +05:30 committed by David S. Miller
parent 4db0401f8a
commit c1219653f3
2 changed files with 148 additions and 0 deletions

View File

@ -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;

View File

@ -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);