cxgb4: collect on-chip memory dump
Collect EDC0 and EDC1 memory dump. 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:
parent
a7975a2f9a
commit
b33af022e5
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (C) 2017 Chelsio Communications. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in
|
||||
* the file called "COPYING".
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __CUDBG_ENTITY_H__
|
||||
#define __CUDBG_ENTITY_H__
|
||||
|
||||
#define EDC0_FLAG 3
|
||||
#define EDC1_FLAG 4
|
||||
|
||||
struct card_mem {
|
||||
u16 size_edc0;
|
||||
u16 size_edc1;
|
||||
u16 mem_flag;
|
||||
};
|
||||
#endif /* __CUDBG_ENTITY_H__ */
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
/* Error codes */
|
||||
#define CUDBG_STATUS_NO_MEM -19
|
||||
#define CUDBG_STATUS_ENTITY_NOT_FOUND -24
|
||||
#define CUDBG_SYSTEM_ERROR -29
|
||||
|
||||
#define CUDBG_MAJOR_VERSION 1
|
||||
|
@ -27,6 +28,8 @@
|
|||
|
||||
enum cudbg_dbg_entity_type {
|
||||
CUDBG_REG_DUMP = 1,
|
||||
CUDBG_EDC0 = 18,
|
||||
CUDBG_EDC1 = 19,
|
||||
CUDBG_MAX_ENTITY = 70,
|
||||
};
|
||||
|
||||
|
@ -35,4 +38,9 @@ struct cudbg_init {
|
|||
void *outbuf; /* Output buffer */
|
||||
u32 outbuf_size; /* Output buffer size */
|
||||
};
|
||||
|
||||
static inline unsigned int cudbg_mbytes_to_bytes(unsigned int size)
|
||||
{
|
||||
return size * 1024 * 1024;
|
||||
}
|
||||
#endif /* __CUDBG_IF_H__ */
|
||||
|
|
|
@ -15,10 +15,12 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "t4_regs.h"
|
||||
#include "cxgb4.h"
|
||||
#include "cudbg_if.h"
|
||||
#include "cudbg_lib_common.h"
|
||||
#include "cudbg_lib.h"
|
||||
#include "cudbg_entity.h"
|
||||
|
||||
static void cudbg_write_and_release_buff(struct cudbg_buffer *pin_buff,
|
||||
struct cudbg_buffer *dbg_buff)
|
||||
|
@ -27,6 +29,16 @@ static void cudbg_write_and_release_buff(struct cudbg_buffer *pin_buff,
|
|||
cudbg_put_buff(pin_buff, dbg_buff);
|
||||
}
|
||||
|
||||
static int is_fw_attached(struct cudbg_init *pdbg_init)
|
||||
{
|
||||
struct adapter *padap = pdbg_init->adap;
|
||||
|
||||
if (!(padap->flags & FW_OK) || padap->use_bd)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* This function will add additional padding bytes into debug_buffer to make it
|
||||
* 4 byte aligned.
|
||||
*/
|
||||
|
@ -77,3 +89,127 @@ int cudbg_collect_reg_dump(struct cudbg_init *pdbg_init,
|
|||
cudbg_write_and_release_buff(&temp_buff, dbg_buff);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cudbg_read_fw_mem(struct cudbg_init *pdbg_init,
|
||||
struct cudbg_buffer *dbg_buff, u8 mem_type,
|
||||
unsigned long tot_len,
|
||||
struct cudbg_error *cudbg_err)
|
||||
{
|
||||
unsigned long bytes, bytes_left, bytes_read = 0;
|
||||
struct adapter *padap = pdbg_init->adap;
|
||||
struct cudbg_buffer temp_buff = { 0 };
|
||||
int rc = 0;
|
||||
|
||||
bytes_left = tot_len;
|
||||
while (bytes_left > 0) {
|
||||
bytes = min_t(unsigned long, bytes_left,
|
||||
(unsigned long)CUDBG_CHUNK_SIZE);
|
||||
rc = cudbg_get_buff(dbg_buff, bytes, &temp_buff);
|
||||
if (rc)
|
||||
return rc;
|
||||
spin_lock(&padap->win0_lock);
|
||||
rc = t4_memory_rw(padap, MEMWIN_NIC, mem_type,
|
||||
bytes_read, bytes,
|
||||
(__be32 *)temp_buff.data,
|
||||
1);
|
||||
spin_unlock(&padap->win0_lock);
|
||||
if (rc) {
|
||||
cudbg_err->sys_err = rc;
|
||||
cudbg_put_buff(&temp_buff, dbg_buff);
|
||||
return rc;
|
||||
}
|
||||
bytes_left -= bytes;
|
||||
bytes_read += bytes;
|
||||
cudbg_write_and_release_buff(&temp_buff, dbg_buff);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void cudbg_collect_mem_info(struct cudbg_init *pdbg_init,
|
||||
struct card_mem *mem_info)
|
||||
{
|
||||
struct adapter *padap = pdbg_init->adap;
|
||||
u32 value;
|
||||
|
||||
value = t4_read_reg(padap, MA_EDRAM0_BAR_A);
|
||||
value = EDRAM0_SIZE_G(value);
|
||||
mem_info->size_edc0 = (u16)value;
|
||||
|
||||
value = t4_read_reg(padap, MA_EDRAM1_BAR_A);
|
||||
value = EDRAM1_SIZE_G(value);
|
||||
mem_info->size_edc1 = (u16)value;
|
||||
|
||||
value = t4_read_reg(padap, MA_TARGET_MEM_ENABLE_A);
|
||||
if (value & EDRAM0_ENABLE_F)
|
||||
mem_info->mem_flag |= (1 << EDC0_FLAG);
|
||||
if (value & EDRAM1_ENABLE_F)
|
||||
mem_info->mem_flag |= (1 << EDC1_FLAG);
|
||||
}
|
||||
|
||||
static void cudbg_t4_fwcache(struct cudbg_init *pdbg_init,
|
||||
struct cudbg_error *cudbg_err)
|
||||
{
|
||||
struct adapter *padap = pdbg_init->adap;
|
||||
int rc;
|
||||
|
||||
if (is_fw_attached(pdbg_init)) {
|
||||
/* Flush uP dcache before reading edcX/mcX */
|
||||
rc = t4_fwcache(padap, FW_PARAM_DEV_FWCACHE_FLUSH);
|
||||
if (rc)
|
||||
cudbg_err->sys_warn = rc;
|
||||
}
|
||||
}
|
||||
|
||||
static int cudbg_collect_mem_region(struct cudbg_init *pdbg_init,
|
||||
struct cudbg_buffer *dbg_buff,
|
||||
struct cudbg_error *cudbg_err,
|
||||
u8 mem_type)
|
||||
{
|
||||
struct card_mem mem_info = {0};
|
||||
unsigned long flag, size;
|
||||
int rc;
|
||||
|
||||
cudbg_t4_fwcache(pdbg_init, cudbg_err);
|
||||
cudbg_collect_mem_info(pdbg_init, &mem_info);
|
||||
switch (mem_type) {
|
||||
case MEM_EDC0:
|
||||
flag = (1 << EDC0_FLAG);
|
||||
size = cudbg_mbytes_to_bytes(mem_info.size_edc0);
|
||||
break;
|
||||
case MEM_EDC1:
|
||||
flag = (1 << EDC1_FLAG);
|
||||
size = cudbg_mbytes_to_bytes(mem_info.size_edc1);
|
||||
break;
|
||||
default:
|
||||
rc = CUDBG_STATUS_ENTITY_NOT_FOUND;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (mem_info.mem_flag & flag) {
|
||||
rc = cudbg_read_fw_mem(pdbg_init, dbg_buff, mem_type,
|
||||
size, cudbg_err);
|
||||
if (rc)
|
||||
goto err;
|
||||
} else {
|
||||
rc = CUDBG_STATUS_ENTITY_NOT_FOUND;
|
||||
goto err;
|
||||
}
|
||||
err:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cudbg_collect_edc0_meminfo(struct cudbg_init *pdbg_init,
|
||||
struct cudbg_buffer *dbg_buff,
|
||||
struct cudbg_error *cudbg_err)
|
||||
{
|
||||
return cudbg_collect_mem_region(pdbg_init, dbg_buff, cudbg_err,
|
||||
MEM_EDC0);
|
||||
}
|
||||
|
||||
int cudbg_collect_edc1_meminfo(struct cudbg_init *pdbg_init,
|
||||
struct cudbg_buffer *dbg_buff,
|
||||
struct cudbg_error *cudbg_err)
|
||||
{
|
||||
return cudbg_collect_mem_region(pdbg_init, dbg_buff, cudbg_err,
|
||||
MEM_EDC1);
|
||||
}
|
||||
|
|
|
@ -21,6 +21,12 @@
|
|||
int cudbg_collect_reg_dump(struct cudbg_init *pdbg_init,
|
||||
struct cudbg_buffer *dbg_buff,
|
||||
struct cudbg_error *cudbg_err);
|
||||
int cudbg_collect_edc0_meminfo(struct cudbg_init *pdbg_init,
|
||||
struct cudbg_buffer *dbg_buff,
|
||||
struct cudbg_error *cudbg_err);
|
||||
int cudbg_collect_edc1_meminfo(struct cudbg_init *pdbg_init,
|
||||
struct cudbg_buffer *dbg_buff,
|
||||
struct cudbg_error *cudbg_err);
|
||||
|
||||
struct cudbg_entity_hdr *cudbg_get_entity_hdr(void *outbuf, int i);
|
||||
void cudbg_align_debug_buffer(struct cudbg_buffer *dbg_buff,
|
||||
|
|
|
@ -69,6 +69,9 @@ struct cudbg_error {
|
|||
int app_err;
|
||||
};
|
||||
|
||||
#define CDUMP_MAX_COMP_BUF_SIZE ((64 * 1024) - 1)
|
||||
#define CUDBG_CHUNK_SIZE ((CDUMP_MAX_COMP_BUF_SIZE / 1024) * 1024)
|
||||
|
||||
int cudbg_get_buff(struct cudbg_buffer *pdbg_buff, u32 size,
|
||||
struct cudbg_buffer *pin_buff);
|
||||
void cudbg_put_buff(struct cudbg_buffer *pin_buff,
|
||||
|
|
|
@ -15,16 +15,22 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "t4_regs.h"
|
||||
#include "cxgb4.h"
|
||||
#include "cxgb4_cudbg.h"
|
||||
|
||||
static const struct cxgb4_collect_entity cxgb4_collect_mem_dump[] = {
|
||||
{ CUDBG_EDC0, cudbg_collect_edc0_meminfo },
|
||||
{ CUDBG_EDC1, cudbg_collect_edc1_meminfo },
|
||||
};
|
||||
|
||||
static const struct cxgb4_collect_entity cxgb4_collect_hw_dump[] = {
|
||||
{ CUDBG_REG_DUMP, cudbg_collect_reg_dump },
|
||||
};
|
||||
|
||||
static u32 cxgb4_get_entity_length(struct adapter *adap, u32 entity)
|
||||
{
|
||||
u32 len = 0;
|
||||
u32 value, len = 0;
|
||||
|
||||
switch (entity) {
|
||||
case CUDBG_REG_DUMP:
|
||||
|
@ -40,6 +46,22 @@ static u32 cxgb4_get_entity_length(struct adapter *adap, u32 entity)
|
|||
break;
|
||||
}
|
||||
break;
|
||||
case CUDBG_EDC0:
|
||||
value = t4_read_reg(adap, MA_TARGET_MEM_ENABLE_A);
|
||||
if (value & EDRAM0_ENABLE_F) {
|
||||
value = t4_read_reg(adap, MA_EDRAM0_BAR_A);
|
||||
len = EDRAM0_SIZE_G(value);
|
||||
}
|
||||
len = cudbg_mbytes_to_bytes(len);
|
||||
break;
|
||||
case CUDBG_EDC1:
|
||||
value = t4_read_reg(adap, MA_TARGET_MEM_ENABLE_A);
|
||||
if (value & EDRAM1_ENABLE_F) {
|
||||
value = t4_read_reg(adap, MA_EDRAM1_BAR_A);
|
||||
len = EDRAM1_SIZE_G(value);
|
||||
}
|
||||
len = cudbg_mbytes_to_bytes(len);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -59,6 +81,13 @@ u32 cxgb4_get_dump_length(struct adapter *adap, u32 flag)
|
|||
}
|
||||
}
|
||||
|
||||
if (flag & CXGB4_ETH_DUMP_MEM) {
|
||||
for (i = 0; i < ARRAY_SIZE(cxgb4_collect_mem_dump); i++) {
|
||||
entity = cxgb4_collect_mem_dump[i].entity;
|
||||
len += cxgb4_get_entity_length(adap, entity);
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
@ -152,6 +181,13 @@ int cxgb4_cudbg_collect(struct adapter *adap, void *buf, u32 *buf_size,
|
|||
buf,
|
||||
&total_size);
|
||||
|
||||
if (flag & CXGB4_ETH_DUMP_MEM)
|
||||
cxgb4_cudbg_collect_entity(&cudbg_init, &dbg_buff,
|
||||
cxgb4_collect_mem_dump,
|
||||
ARRAY_SIZE(cxgb4_collect_mem_dump),
|
||||
buf,
|
||||
&total_size);
|
||||
|
||||
cudbg_hdr->data_len = total_size;
|
||||
*buf_size = total_size;
|
||||
return 0;
|
||||
|
|
|
@ -33,6 +33,7 @@ struct cxgb4_collect_entity {
|
|||
|
||||
enum CXGB4_ETHTOOL_DUMP_FLAGS {
|
||||
CXGB4_ETH_DUMP_NONE = ETH_FW_DUMP_DISABLE,
|
||||
CXGB4_ETH_DUMP_MEM = (1 << 0), /* On-Chip Memory Dumps */
|
||||
CXGB4_ETH_DUMP_HW = (1 << 1), /* various FW and HW dumps */
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue