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

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

cxgb4: collect LE-TCAM dump

parent 8bff3685
Loading
Loading
Loading
Loading
+30 −0
Original line number Diff line number Diff line
@@ -185,6 +185,36 @@ struct cudbg_vpd_data {
	u32 vpd_vers;
};

#define CUDBG_MAX_TCAM_TID 0x800

enum cudbg_le_entry_types {
	LE_ET_UNKNOWN = 0,
	LE_ET_TCAM_CON = 1,
	LE_ET_TCAM_SERVER = 2,
	LE_ET_TCAM_FILTER = 3,
	LE_ET_TCAM_CLIP = 4,
	LE_ET_TCAM_ROUTING = 5,
	LE_ET_HASH_CON = 6,
	LE_ET_INVALID_TID = 8,
};

struct cudbg_tcam {
	u32 filter_start;
	u32 server_start;
	u32 clip_start;
	u32 routing_start;
	u32 tid_hash_base;
	u32 max_tid;
};

struct cudbg_tid_data {
	u32 tid;
	u32 dbig_cmd;
	u32 dbig_conf;
	u32 dbig_rsp_stat;
	u32 data[NUM_LE_DB_DBGI_RSP_DATA_INSTANCES];
};

#define CUDBG_NUM_ULPTX 11
#define CUDBG_NUM_ULPTX_READ 512

+1 −0
Original line number Diff line number Diff line
@@ -65,6 +65,7 @@ enum cudbg_dbg_entity_type {
	CUDBG_TID_INFO = 54,
	CUDBG_MPS_TCAM = 57,
	CUDBG_VPD_DATA = 58,
	CUDBG_LE_TCAM = 59,
	CUDBG_CCTRL = 60,
	CUDBG_MA_INDIRECT = 61,
	CUDBG_ULPTX_LA = 62,
+175 −0
Original line number Diff line number Diff line
@@ -1367,6 +1367,181 @@ int cudbg_collect_vpd_data(struct cudbg_init *pdbg_init,
	return rc;
}

static int cudbg_read_tid(struct cudbg_init *pdbg_init, u32 tid,
			  struct cudbg_tid_data *tid_data)
{
	struct adapter *padap = pdbg_init->adap;
	int i, cmd_retry = 8;
	u32 val;

	/* Fill REQ_DATA regs with 0's */
	for (i = 0; i < NUM_LE_DB_DBGI_REQ_DATA_INSTANCES; i++)
		t4_write_reg(padap, LE_DB_DBGI_REQ_DATA_A + (i << 2), 0);

	/* Write DBIG command */
	val = DBGICMD_V(4) | DBGITID_V(tid);
	t4_write_reg(padap, LE_DB_DBGI_REQ_TCAM_CMD_A, val);
	tid_data->dbig_cmd = val;

	val = DBGICMDSTRT_F | DBGICMDMODE_V(1); /* LE mode */
	t4_write_reg(padap, LE_DB_DBGI_CONFIG_A, val);
	tid_data->dbig_conf = val;

	/* Poll the DBGICMDBUSY bit */
	val = 1;
	while (val) {
		val = t4_read_reg(padap, LE_DB_DBGI_CONFIG_A);
		val = val & DBGICMDBUSY_F;
		cmd_retry--;
		if (!cmd_retry)
			return CUDBG_SYSTEM_ERROR;
	}

	/* Check RESP status */
	val = t4_read_reg(padap, LE_DB_DBGI_RSP_STATUS_A);
	tid_data->dbig_rsp_stat = val;
	if (!(val & 1))
		return CUDBG_SYSTEM_ERROR;

	/* Read RESP data */
	for (i = 0; i < NUM_LE_DB_DBGI_RSP_DATA_INSTANCES; i++)
		tid_data->data[i] = t4_read_reg(padap,
						LE_DB_DBGI_RSP_DATA_A +
						(i << 2));
	tid_data->tid = tid;
	return 0;
}

static int cudbg_get_le_type(u32 tid, struct cudbg_tcam tcam_region)
{
	int type = LE_ET_UNKNOWN;

	if (tid < tcam_region.server_start)
		type = LE_ET_TCAM_CON;
	else if (tid < tcam_region.filter_start)
		type = LE_ET_TCAM_SERVER;
	else if (tid < tcam_region.clip_start)
		type = LE_ET_TCAM_FILTER;
	else if (tid < tcam_region.routing_start)
		type = LE_ET_TCAM_CLIP;
	else if (tid < tcam_region.tid_hash_base)
		type = LE_ET_TCAM_ROUTING;
	else if (tid < tcam_region.max_tid)
		type = LE_ET_HASH_CON;
	else
		type = LE_ET_INVALID_TID;

	return type;
}

static int cudbg_is_ipv6_entry(struct cudbg_tid_data *tid_data,
			       struct cudbg_tcam tcam_region)
{
	int ipv6 = 0;
	int le_type;

	le_type = cudbg_get_le_type(tid_data->tid, tcam_region);
	if (tid_data->tid & 1)
		return 0;

	if (le_type == LE_ET_HASH_CON) {
		ipv6 = tid_data->data[16] & 0x8000;
	} else if (le_type == LE_ET_TCAM_CON) {
		ipv6 = tid_data->data[16] & 0x8000;
		if (ipv6)
			ipv6 = tid_data->data[9] == 0x00C00000;
	} else {
		ipv6 = 0;
	}
	return ipv6;
}

void cudbg_fill_le_tcam_info(struct adapter *padap,
			     struct cudbg_tcam *tcam_region)
{
	u32 value;

	/* Get the LE regions */
	value = t4_read_reg(padap, LE_DB_TID_HASHBASE_A); /* hash base index */
	tcam_region->tid_hash_base = value;

	/* Get routing table index */
	value = t4_read_reg(padap, LE_DB_ROUTING_TABLE_INDEX_A);
	tcam_region->routing_start = value;

	/*Get clip table index */
	value = t4_read_reg(padap, LE_DB_CLIP_TABLE_INDEX_A);
	tcam_region->clip_start = value;

	/* Get filter table index */
	value = t4_read_reg(padap, LE_DB_FILTER_TABLE_INDEX_A);
	tcam_region->filter_start = value;

	/* Get server table index */
	value = t4_read_reg(padap, LE_DB_SERVER_INDEX_A);
	tcam_region->server_start = value;

	/* Check whether hash is enabled and calculate the max tids */
	value = t4_read_reg(padap, LE_DB_CONFIG_A);
	if ((value >> HASHEN_S) & 1) {
		value = t4_read_reg(padap, LE_DB_HASH_CONFIG_A);
		if (CHELSIO_CHIP_VERSION(padap->params.chip) > CHELSIO_T5) {
			tcam_region->max_tid = (value & 0xFFFFF) +
					       tcam_region->tid_hash_base;
		} else {
			value = HASHTIDSIZE_G(value);
			value = 1 << value;
			tcam_region->max_tid = value +
					       tcam_region->tid_hash_base;
		}
	} else { /* hash not enabled */
		tcam_region->max_tid = CUDBG_MAX_TCAM_TID;
	}
}

int cudbg_collect_le_tcam(struct cudbg_init *pdbg_init,
			  struct cudbg_buffer *dbg_buff,
			  struct cudbg_error *cudbg_err)
{
	struct adapter *padap = pdbg_init->adap;
	struct cudbg_buffer temp_buff = { 0 };
	struct cudbg_tcam tcam_region = { 0 };
	struct cudbg_tid_data *tid_data;
	u32 bytes = 0;
	int rc, size;
	u32 i;

	cudbg_fill_le_tcam_info(padap, &tcam_region);

	size = sizeof(struct cudbg_tid_data) * tcam_region.max_tid;
	size += sizeof(struct cudbg_tcam);
	rc = cudbg_get_buff(dbg_buff, size, &temp_buff);
	if (rc)
		return rc;

	memcpy(temp_buff.data, &tcam_region, sizeof(struct cudbg_tcam));
	bytes = sizeof(struct cudbg_tcam);
	tid_data = (struct cudbg_tid_data *)(temp_buff.data + bytes);
	/* read all tid */
	for (i = 0; i < tcam_region.max_tid; ) {
		rc = cudbg_read_tid(pdbg_init, i, tid_data);
		if (rc) {
			cudbg_err->sys_err = rc;
			cudbg_put_buff(&temp_buff, dbg_buff);
			return rc;
		}

		/* ipv6 takes two tids */
		cudbg_is_ipv6_entry(tid_data, tcam_region) ? i += 2 : i++;

		tid_data++;
		bytes += sizeof(struct cudbg_tid_data);
	}

	cudbg_write_and_release_buff(&temp_buff, dbg_buff);
	return rc;
}

int cudbg_collect_cctrl(struct cudbg_init *pdbg_init,
			struct cudbg_buffer *dbg_buff,
			struct cudbg_error *cudbg_err)
+7 −0
Original line number Diff line number Diff line
@@ -129,6 +129,9 @@ int cudbg_collect_mps_tcam(struct cudbg_init *pdbg_init,
int cudbg_collect_vpd_data(struct cudbg_init *pdbg_init,
			   struct cudbg_buffer *dbg_buff,
			   struct cudbg_error *cudbg_err);
int cudbg_collect_le_tcam(struct cudbg_init *pdbg_init,
			  struct cudbg_buffer *dbg_buff,
			  struct cudbg_error *cudbg_err);
int cudbg_collect_cctrl(struct cudbg_init *pdbg_init,
			struct cudbg_buffer *dbg_buff,
			struct cudbg_error *cudbg_err);
@@ -155,4 +158,8 @@ struct cudbg_entity_hdr *cudbg_get_entity_hdr(void *outbuf, int i);
void cudbg_align_debug_buffer(struct cudbg_buffer *dbg_buff,
			      struct cudbg_entity_hdr *entity_hdr);
u32 cudbg_cim_obq_size(struct adapter *padap, int qid);

struct cudbg_tcam;
void cudbg_fill_le_tcam_info(struct adapter *padap,
			     struct cudbg_tcam *tcam_region);
#endif /* __CUDBG_LIB_H__ */
+7 −0
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ static const struct cxgb4_collect_entity cxgb4_collect_hw_dump[] = {
	{ CUDBG_TID_INFO, cudbg_collect_tid },
	{ CUDBG_MPS_TCAM, cudbg_collect_mps_tcam },
	{ CUDBG_VPD_DATA, cudbg_collect_vpd_data },
	{ CUDBG_LE_TCAM, cudbg_collect_le_tcam },
	{ CUDBG_CCTRL, cudbg_collect_cctrl },
	{ CUDBG_MA_INDIRECT, cudbg_collect_ma_indirect },
	{ CUDBG_ULPTX_LA, cudbg_collect_ulptx_la },
@@ -72,6 +73,7 @@ static const struct cxgb4_collect_entity cxgb4_collect_hw_dump[] = {

static u32 cxgb4_get_entity_length(struct adapter *adap, u32 entity)
{
	struct cudbg_tcam tcam_region = { 0 };
	u32 value, n = 0, len = 0;

	switch (entity) {
@@ -223,6 +225,11 @@ static u32 cxgb4_get_entity_length(struct adapter *adap, u32 entity)
	case CUDBG_VPD_DATA:
		len = sizeof(struct cudbg_vpd_data);
		break;
	case CUDBG_LE_TCAM:
		cudbg_fill_le_tcam_info(adap, &tcam_region);
		len = sizeof(struct cudbg_tcam) +
		      sizeof(struct cudbg_tid_data) * tcam_region.max_tid;
		break;
	case CUDBG_CCTRL:
		len = sizeof(u16) * NMTUS * NCCTRL_WIN;
		break;
Loading