Signed-off-by: Rahul Lakkireddy <rahul.lakkire...@chelsio.com>
Signed-off-by: Ganesh Goudar <ganes...@chelsio.com>
---
 drivers/net/ethernet/chelsio/cxgb4/cudbg_entity.h |  30 ++++
 drivers/net/ethernet/chelsio/cxgb4/cudbg_if.h     |   1 +
 drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c    | 175 ++++++++++++++++++++++
 drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.h    |   7 +
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_cudbg.c  |   7 +
 drivers/net/ethernet/chelsio/cxgb4/t4_regs.h      |  41 +++++
 6 files changed, 261 insertions(+)

diff --git a/drivers/net/ethernet/chelsio/cxgb4/cudbg_entity.h 
b/drivers/net/ethernet/chelsio/cxgb4/cudbg_entity.h
index 1de1d811fde3..f99db7b283fc 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cudbg_entity.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cudbg_entity.h
@@ -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
 
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cudbg_if.h 
b/drivers/net/ethernet/chelsio/cxgb4/cudbg_if.h
index e484c514e9ae..4e5d189eae62 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cudbg_if.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cudbg_if.h
@@ -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,
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c 
b/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c
index 32c9858da110..dd7e26be98cf 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c
@@ -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)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.h 
b/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.h
index 230ba88a6a81..ebb2d9907fc9 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.h
@@ -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__ */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_cudbg.c 
b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_cudbg.c
index 7373617da635..05eb2d2ef592 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_cudbg.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_cudbg.c
@@ -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;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h 
b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
index 623f453bd327..f5576ce004fa 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
@@ -65,6 +65,9 @@
 
 #define PCIE_FW_REG(reg_addr, idx) ((reg_addr) + (idx) * 4)
 
+#define NUM_LE_DB_DBGI_REQ_DATA_INSTANCES 17
+#define NUM_LE_DB_DBGI_RSP_DATA_INSTANCES 17
+
 #define SGE_PF_KDOORBELL_A 0x0
 
 #define QID_S    15
@@ -2273,6 +2276,35 @@
 #define CHNENABLE_V(x) ((x) << CHNENABLE_S)
 #define CHNENABLE_F    CHNENABLE_V(1U)
 
+#define LE_DB_DBGI_CONFIG_A 0x19cf0
+
+#define DBGICMDBUSY_S    3
+#define DBGICMDBUSY_V(x) ((x) << DBGICMDBUSY_S)
+#define DBGICMDBUSY_F    DBGICMDBUSY_V(1U)
+
+#define DBGICMDSTRT_S    2
+#define DBGICMDSTRT_V(x) ((x) << DBGICMDSTRT_S)
+#define DBGICMDSTRT_F    DBGICMDSTRT_V(1U)
+
+#define DBGICMDMODE_S    0
+#define DBGICMDMODE_M    0x3U
+#define DBGICMDMODE_V(x) ((x) << DBGICMDMODE_S)
+
+#define LE_DB_DBGI_REQ_TCAM_CMD_A 0x19cf4
+
+#define DBGICMD_S    20
+#define DBGICMD_M    0xfU
+#define DBGICMD_V(x) ((x) << DBGICMD_S)
+
+#define DBGITID_S    0
+#define DBGITID_M    0xfffffU
+#define DBGITID_V(x) ((x) << DBGITID_S)
+
+#define LE_DB_DBGI_REQ_DATA_A 0x19d00
+#define LE_DB_DBGI_RSP_STATUS_A 0x19d94
+
+#define LE_DB_DBGI_RSP_DATA_A 0x19da0
+
 #define PRTENABLE_S    29
 #define PRTENABLE_V(x) ((x) << PRTENABLE_S)
 #define PRTENABLE_F    PRTENABLE_V(1U)
@@ -2882,11 +2914,20 @@
 #define T6_LIPMISS_F    T6_LIPMISS_V(1U)
 
 #define LE_DB_CONFIG_A 0x19c04
+#define LE_DB_ROUTING_TABLE_INDEX_A 0x19c10
 #define LE_DB_ACTIVE_TABLE_START_INDEX_A 0x19c10
+#define LE_DB_FILTER_TABLE_INDEX_A 0x19c14
 #define LE_DB_SERVER_INDEX_A 0x19c18
 #define LE_DB_SRVR_START_INDEX_A 0x19c18
+#define LE_DB_CLIP_TABLE_INDEX_A 0x19c1c
 #define LE_DB_ACT_CNT_IPV4_A 0x19c20
 #define LE_DB_ACT_CNT_IPV6_A 0x19c24
+#define LE_DB_HASH_CONFIG_A 0x19c28
+
+#define HASHTIDSIZE_S    16
+#define HASHTIDSIZE_M    0x3fU
+#define HASHTIDSIZE_G(x) (((x) >> HASHTIDSIZE_S) & HASHTIDSIZE_M)
+
 #define LE_DB_HASH_TID_BASE_A 0x19c30
 #define LE_DB_HASH_TBL_BASE_ADDR_A 0x19c30
 #define LE_DB_INT_CAUSE_A 0x19c3c
-- 
2.14.1

Reply via email to