net/ice/base: add parser execution main loop
authorQi Zhang <qi.z.zhang@intel.com>
Fri, 17 Sep 2021 14:43:19 +0000 (22:43 +0800)
committerQi Zhang <qi.z.zhang@intel.com>
Tue, 21 Sep 2021 13:17:58 +0000 (15:17 +0200)
Implement function ice_parser_rt_execute which perform the main
loop of the parser.

Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
Acked-by: Junfeng Guo <junfeng.guo@intel.com>
drivers/net/ice/base/ice_parser_rt.c
drivers/net/ice/base/ice_parser_rt.h

index d62d017..7a44675 100644 (file)
@@ -34,12 +34,40 @@ static void _rt_nn_set(struct ice_parser_rt *rt, u16 node)
        rt->gpr[GPR_NN_IDX] = node;
 }
 
-static void _rt_flag_set(struct ice_parser_rt *rt, int idx)
+static void _rt_flag_set(struct ice_parser_rt *rt, int idx, bool val)
 {
        int y = idx / 16;
        int x = idx % 16;
 
-       rt->gpr[GPR_FLG_IDX + y] |= (u16)(1 << x);
+       if (val)
+               rt->gpr[GPR_FLG_IDX + y] |= (u16)(1 << x);
+       else
+               rt->gpr[GPR_FLG_IDX + y] &= ~(u16)(1 << x);
+
+       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Set parser flag %d value %d\n",
+                 idx, val);
+}
+
+static void _rt_gpr_set(struct ice_parser_rt *rt, int idx, u16 val)
+{
+       if (idx == GPR_HO_IDX)
+               _rt_ho_set(rt, val);
+       else
+               rt->gpr[idx] = val;
+
+       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Set GPR %d value %d\n",
+                 idx, val);
+}
+
+static void _rt_err_set(struct ice_parser_rt *rt, int idx, bool val)
+{
+       if (val)
+               rt->gpr[GPR_ERR_IDX] |= (u16)(1 << idx);
+       else
+               rt->gpr[GPR_ERR_IDX] &= ~(u16)(1 << idx);
+
+       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Set parser error %d value %d\n",
+                 idx, val);
 }
 
 /**
@@ -61,7 +89,7 @@ void ice_parser_rt_reset(struct ice_parser_rt *rt)
 
        for (i = 0; i < 64; i++) {
                if ((mi->flags & (1ul << i)) != 0ul)
-                       _rt_flag_set(rt, i);
+                       _rt_flag_set(rt, i, true);
        }
 
        rt->psr = psr;
@@ -82,8 +110,655 @@ void ice_parser_rt_pktbuf_set(struct ice_parser_rt *rt, const u8 *pkt_buf,
        ice_memcpy(rt->pkt_buf, pkt_buf, len, ICE_NONDMA_TO_NONDMA);
        rt->pkt_len = pkt_len;
 
-       ice_memcpy(&rt->gpr[GPR_HB_IDX], &rt->pkt_buf[ho], 32,
+       ice_memcpy(&rt->gpr[GPR_HB_IDX], &rt->pkt_buf[ho],
+                  ICE_PARSER_HDR_BUF_LEN, ICE_NONDMA_TO_NONDMA);
+}
+
+static void _bst_key_init(struct ice_parser_rt *rt, struct ice_imem_item *imem)
+{
+       int second_last_key_idx = ICE_PARSER_BST_KEY_LEN - 2;
+       int last_key_idx = ICE_PARSER_BST_KEY_LEN - 1;
+       u8 tsr = (u8)rt->gpr[GPR_TSR_IDX];
+       u16 ho = rt->gpr[GPR_HO_IDX];
+       u8 *key = rt->bst_key;
+
+       int i, j;
+
+       if (imem->b_kb.tsr_ctrl)
+               key[last_key_idx] = (u8)tsr;
+       else
+               key[last_key_idx] = imem->b_kb.priority;
+
+       for (i = second_last_key_idx; i >= 0; i--) {
+               j = ho + second_last_key_idx - i;
+               if (j < ICE_PARSER_MAX_PKT_LEN)
+                       key[i] = rt->pkt_buf[ho + second_last_key_idx - i];
+               else
+                       key[i] = 0;
+       }
+
+       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Generated Boost TCAM Key:\n");
+       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
+                 key[0], key[1], key[2], key[3], key[4],
+                 key[5], key[6], key[7], key[8], key[9],
+                 key[10], key[11], key[12], key[13], key[14],
+                 key[15], key[16], key[17], key[18], key[19]);
+       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "\n");
+}
+
+static u8 _bit_rev_u8(u8 v)
+{
+       u8 r = 0;
+       int i;
+
+       for (i = 0; i < 8; i++) {
+               r |= (u8)((v & 0x1) << (7 - i));
+               v >>= 1;
+       }
+
+       return r;
+}
+
+static u8 _bit_rev_u16(u16 v, int len)
+{
+       u16 r = 0;
+       int i;
+
+       for (i = 0; i < len; i++) {
+               r |= (u16)((v & 0x1) << (len - 1 - i));
+               v >>= 1;
+       }
+
+       return r;
+}
+
+static u32 _bit_rev_u32(u32 v, int len)
+{
+       u32 r = 0;
+       int i;
+
+       for (i = 0; i < len; i++) {
+               r |= (u32)((v & 0x1) << (len - 1 - i));
+               v >>= 1;
+       }
+
+       return r;
+}
+
+static u32 _hv_bit_sel(struct ice_parser_rt *rt, int start, int len)
+{
+       u64 d64, msk;
+       u8 b[8];
+       int i;
+
+       int offset = GPR_HB_IDX + start / 16;
+
+       ice_memcpy(b, &rt->gpr[offset], 8, ICE_NONDMA_TO_NONDMA);
+
+       for (i = 0; i < 8; i++)
+               b[i] = _bit_rev_u8(b[i]);
+
+       d64 = *(u64 *)&b[0];
+       msk = (1ul << len) - 1;
+
+       return _bit_rev_u32((u32)((d64 >> (start % 16)) & msk), len);
+}
+
+static u32 _pk_build(struct ice_parser_rt *rt, struct ice_np_keybuilder *kb)
+{
+       if (kb->ops == 0)
+               return _hv_bit_sel(rt, kb->start_or_reg0, kb->len_or_reg1);
+       else if (kb->ops == 1)
+               return rt->gpr[kb->start_or_reg0] |
+                      ((u32)rt->gpr[kb->len_or_reg1] << 16);
+       else if (kb->ops == 2)
+               return 0;
+
+       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Unsupported ops %d\n", kb->ops);
+       return 0xffffffff;
+}
+
+static bool _flag_get(struct ice_parser_rt *rt, int index)
+{
+       int y = index / 16;
+       int x = index % 16;
+
+       return (rt->gpr[GPR_FLG_IDX + y] & (u16)(1 << x)) != 0;
+}
+
+static void _imem_pgk_init(struct ice_parser_rt *rt, struct ice_imem_item *imem)
+{
+       ice_memset(&rt->pg_key, 0, sizeof(rt->pg_key), ICE_NONDMA_MEM);
+       rt->pg_key.next_proto = _pk_build(rt, &imem->np_kb);
+
+       if (imem->pg_kb.flag0_ena)
+               rt->pg_key.flag0 = _flag_get(rt, imem->pg_kb.flag0_idx);
+       if (imem->pg_kb.flag1_ena)
+               rt->pg_key.flag1 = _flag_get(rt, imem->pg_kb.flag1_idx);
+       if (imem->pg_kb.flag2_ena)
+               rt->pg_key.flag2 = _flag_get(rt, imem->pg_kb.flag2_idx);
+       if (imem->pg_kb.flag3_ena)
+               rt->pg_key.flag3 = _flag_get(rt, imem->pg_kb.flag3_idx);
+
+       rt->pg_key.alu_reg = rt->gpr[imem->pg_kb.alu_reg_idx];
+       rt->pg_key.node_id = rt->gpr[GPR_NN_IDX];
+
+       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Generate Parse Graph Key: node_id(%d),flag0(%d), flag1(%d), flag2(%d), flag3(%d), boost_idx(%d), alu_reg(0x%04x), next_proto(0x%08x)\n",
+                 rt->pg_key.node_id,
+                 rt->pg_key.flag0,
+                 rt->pg_key.flag1,
+                 rt->pg_key.flag2,
+                 rt->pg_key.flag3,
+                 rt->pg_key.boost_idx,
+                 rt->pg_key.alu_reg,
+                 rt->pg_key.next_proto);
+}
+
+static void _imem_alu0_set(struct ice_parser_rt *rt, struct ice_imem_item *imem)
+{
+       rt->alu0 = &imem->alu0;
+       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Load ALU0 from imem pc %d\n",
+                 imem->idx);
+}
+
+static void _imem_alu1_set(struct ice_parser_rt *rt, struct ice_imem_item *imem)
+{
+       rt->alu1 = &imem->alu1;
+       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Load ALU1 from imem pc %d\n",
+                 imem->idx);
+}
+
+static void _imem_alu2_set(struct ice_parser_rt *rt, struct ice_imem_item *imem)
+{
+       rt->alu2 = &imem->alu2;
+       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Load ALU2 from imem pc %d\n",
+                 imem->idx);
+}
+
+static void _imem_pgp_set(struct ice_parser_rt *rt, struct ice_imem_item *imem)
+{
+       rt->pg = imem->pg;
+       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Load PG priority %d from imem pc %d\n",
+                 rt->pg, imem->idx);
+}
+
+static void
+_bst_pgk_init(struct ice_parser_rt *rt, struct ice_bst_tcam_item *bst)
+{
+       ice_memset(&rt->pg_key, 0, sizeof(rt->pg_key), ICE_NONDMA_MEM);
+       rt->pg_key.boost_idx = bst->hit_idx_grp;
+       rt->pg_key.next_proto = _pk_build(rt, &bst->np_kb);
+
+       if (bst->pg_kb.flag0_ena)
+               rt->pg_key.flag0 = _flag_get(rt, bst->pg_kb.flag0_idx);
+       if (bst->pg_kb.flag1_ena)
+               rt->pg_key.flag1 = _flag_get(rt, bst->pg_kb.flag1_idx);
+       if (bst->pg_kb.flag2_ena)
+               rt->pg_key.flag2 = _flag_get(rt, bst->pg_kb.flag2_idx);
+       if (bst->pg_kb.flag3_ena)
+               rt->pg_key.flag3 = _flag_get(rt, bst->pg_kb.flag3_idx);
+
+       rt->pg_key.alu_reg = rt->gpr[bst->pg_kb.alu_reg_idx];
+       rt->pg_key.node_id = rt->gpr[GPR_NN_IDX];
+
+       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Generate Parse Graph Key: node_id(%d),flag0(%d), flag1(%d), flag2(%d), flag3(%d), boost_idx(%d), alu_reg(0x%04x), next_proto(0x%08x)\n",
+                 rt->pg_key.node_id,
+                 rt->pg_key.flag0,
+                 rt->pg_key.flag1,
+                 rt->pg_key.flag2,
+                 rt->pg_key.flag3,
+                 rt->pg_key.boost_idx,
+                 rt->pg_key.alu_reg,
+                 rt->pg_key.next_proto);
+}
+
+static void _bst_alu0_set(struct ice_parser_rt *rt,
+                         struct ice_bst_tcam_item *bst)
+{
+       rt->alu0 = &bst->alu0;
+       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Load ALU0 from boost address %d\n",
+                 bst->address);
+}
+
+static void _bst_alu1_set(struct ice_parser_rt *rt,
+                         struct ice_bst_tcam_item *bst)
+{
+       rt->alu1 = &bst->alu1;
+       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Load ALU1 from boost address %d\n",
+                 bst->address);
+}
+
+static void _bst_alu2_set(struct ice_parser_rt *rt,
+                         struct ice_bst_tcam_item *bst)
+{
+       rt->alu2 = &bst->alu2;
+       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Load ALU2 from boost address %d\n",
+                 bst->address);
+}
+
+static void _bst_pgp_set(struct ice_parser_rt *rt,
+                        struct ice_bst_tcam_item *bst)
+{
+       rt->pg = bst->pg_pri;
+       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Load PG priority %d from boost address %d\n",
+                 rt->pg, bst->address);
+}
+
+static struct ice_pg_cam_item *_pg_cam_match(struct ice_parser_rt *rt)
+{
+       struct ice_parser *psr = rt->psr;
+       struct ice_pg_cam_item *item;
+
+       item = ice_pg_cam_match(psr->pg_cam_table, ICE_PG_CAM_TABLE_SIZE,
+                               &rt->pg_key);
+       if (item)
+               return item;
+
+       item = ice_pg_cam_match(psr->pg_sp_cam_table, ICE_PG_SP_CAM_TABLE_SIZE,
+                               &rt->pg_key);
+       return item;
+}
+
+static struct ice_pg_nm_cam_item *_pg_nm_cam_match(struct ice_parser_rt *rt)
+{
+       struct ice_parser *psr = rt->psr;
+       struct ice_pg_nm_cam_item *item;
+
+       item = ice_pg_nm_cam_match(psr->pg_nm_cam_table,
+                                  ICE_PG_NM_CAM_TABLE_SIZE, &rt->pg_key);
+
+       if (item)
+               return item;
+
+       item = ice_pg_nm_cam_match(psr->pg_nm_sp_cam_table,
+                                  ICE_PG_NM_SP_CAM_TABLE_SIZE,
+                                  &rt->pg_key);
+       return item;
+}
+
+static void _gpr_add(struct ice_parser_rt *rt, int idx, u16 val)
+{
+       rt->pu.gpr_val_upd[idx] = true;
+       rt->pu.gpr_val[idx] = val;
+
+       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Pending update for register %d value %d\n",
+                 idx, val);
+}
+
+static void _pg_exe(struct ice_parser_rt *rt)
+{
+       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Executing ParseGraph action ...\n");
+
+       _gpr_add(rt, GPR_NP_IDX, rt->action->next_pc);
+       _gpr_add(rt, GPR_NN_IDX, rt->action->next_node);
+
+       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Executing ParseGraph action done.\n");
+}
+
+static void _flg_add(struct ice_parser_rt *rt, int idx, bool val)
+{
+       rt->pu.flg_msk |= (1ul << idx);
+       if (val)
+               rt->pu.flg_val |= (1ul << idx);
+       else
+               rt->pu.flg_val &= ~(1ul << idx);
+
+       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Pending update for flag %d value %d\n",
+                 idx, val);
+}
+
+static void _flg_update(struct ice_parser_rt *rt, struct ice_alu *alu)
+{
+       int i;
+
+       if (alu->dedicate_flags_ena) {
+               if (alu->flags_extr_imm) {
+                       for (i = 0; i < alu->dst_len; i++)
+                               _flg_add(rt, alu->dst_start + i,
+                                        (alu->flags_start_imm &
+                                         (1u << i)) != 0);
+               } else {
+                       for (i = 0; i < alu->dst_len; i++) {
+                               _flg_add(rt, alu->dst_start + i,
+                                        _hv_bit_sel(rt,
+                                                    alu->flags_start_imm + i,
+                                                    1) != 0);
+                       }
+               }
+       }
+}
+
+static void _po_update(struct ice_parser_rt *rt, struct ice_alu *alu)
+{
+       if (alu->proto_offset_opc == 1)
+               rt->po = (u16)(rt->gpr[GPR_HO_IDX] + alu->proto_offset);
+       else if (alu->proto_offset_opc == 2)
+               rt->po = (u16)(rt->gpr[GPR_HO_IDX] - alu->proto_offset);
+       else if (alu->proto_offset_opc == 0)
+               rt->po = rt->gpr[GPR_HO_IDX];
+
+       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Update Protocol Offset = %d\n",
+                 rt->po);
+}
+
+static u16 _reg_bit_sel(struct ice_parser_rt *rt, int reg_idx,
+                       int start, int len)
+{
+       u32 d32, msk;
+       u8 b[4];
+       u8 v[4];
+
+       ice_memcpy(b, &rt->gpr[reg_idx + start / 16], 4, ICE_NONDMA_TO_NONDMA);
+
+       v[0] = _bit_rev_u8(b[0]);
+       v[1] = _bit_rev_u8(b[1]);
+       v[2] = _bit_rev_u8(b[2]);
+       v[3] = _bit_rev_u8(b[3]);
+
+       d32 = *(u32 *)&v[0];
+       msk = (1u << len) - 1;
+
+       return _bit_rev_u16((u16)((d32 >> (start % 16)) & msk), len);
+}
+
+static void _err_add(struct ice_parser_rt *rt, int idx, bool val)
+{
+       rt->pu.err_msk |= (u16)(1 << idx);
+       if (val)
+               rt->pu.flg_val |= (u16)(1 << idx);
+       else
+               rt->pu.flg_val &= ~(u16)(1 << idx);
+
+       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Pending update for error %d value %d\n",
+                 idx, val);
+}
+
+static void _dst_reg_bit_set(struct ice_parser_rt *rt, struct ice_alu *alu,
+                            bool val)
+{
+       u16 flg_idx;
+
+       if (alu->dedicate_flags_ena) {
+               ice_debug(rt->psr->hw, ICE_DBG_PARSER, "DedicatedFlagsEnable should not be enabled in opcode %d\n",
+                         alu->opc);
+               return;
+       }
+
+       if (alu->dst_reg_id == GPR_ERR_IDX) {
+               if (alu->dst_start >= 16) {
+                       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Invalid error %d\n",
+                                 alu->dst_start);
+                       return;
+               }
+               _err_add(rt, alu->dst_start, val);
+       } else if (alu->dst_reg_id >= GPR_FLG_IDX) {
+               flg_idx = (u16)(((alu->dst_reg_id - GPR_FLG_IDX) << 4) +
+                               alu->dst_start);
+
+               if (flg_idx >= 64) {
+                       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Invalid flag %d\n",
+                                 flg_idx);
+                       return;
+               }
+               _flg_add(rt, flg_idx, val);
+       } else {
+               ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Unexpected Dest Register Bit set, RegisterID %d Start %d\n",
+                         alu->dst_reg_id, alu->dst_start);
+       }
+}
+
+static void _alu_exe(struct ice_parser_rt *rt, struct ice_alu *alu)
+{
+       u16 dst, src, shift, imm;
+
+       if (alu->shift_xlate_select) {
+               ice_debug(rt->psr->hw, ICE_DBG_PARSER, "shift_xlate_select != 0 is not expected\n");
+               return;
+       }
+
+       _po_update(rt, alu);
+       _flg_update(rt, alu);
+
+       dst = rt->gpr[alu->dst_reg_id];
+       src = _reg_bit_sel(rt, alu->src_reg_id, alu->src_start, alu->src_len);
+       shift = alu->shift_xlate_key;
+       imm = alu->imm;
+
+       switch (alu->opc) {
+       case ICE_ALU_PARK:
+               break;
+       case ICE_ALU_MOV_ADD:
+               dst = (u16)((src << shift) + imm);
+               _gpr_add(rt, alu->dst_reg_id, dst);
+               break;
+       case ICE_ALU_ADD:
+               dst += (u16)((src << shift) + imm);
+               _gpr_add(rt, alu->dst_reg_id, dst);
+               break;
+       case ICE_ALU_ORLT:
+               if (src < imm)
+                       _dst_reg_bit_set(rt, alu, true);
+               _gpr_add(rt, GPR_NP_IDX, alu->branch_addr);
+               break;
+       case ICE_ALU_OREQ:
+               if (src == imm)
+                       _dst_reg_bit_set(rt, alu, true);
+               _gpr_add(rt, GPR_NP_IDX, alu->branch_addr);
+               break;
+       case ICE_ALU_SETEQ:
+               if (src == imm)
+                       _dst_reg_bit_set(rt, alu, true);
+               else
+                       _dst_reg_bit_set(rt, alu, false);
+               _gpr_add(rt, GPR_NP_IDX, alu->branch_addr);
+               break;
+       case ICE_ALU_MOV_XOR:
+               dst = (u16)((u16)(src << shift) ^ (u16)imm);
+               _gpr_add(rt, alu->dst_reg_id, dst);
+               break;
+       default:
+               ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Unsupported ALU instruction %d\n",
+                         alu->opc);
+               break;
+       }
+}
+
+static void _alu0_exe(struct ice_parser_rt *rt)
+{
+       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Executing ALU0 ...\n");
+       _alu_exe(rt, rt->alu0);
+       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Executing ALU0 done.\n");
+}
+
+static void _alu1_exe(struct ice_parser_rt *rt)
+{
+       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Executing ALU1 ...\n");
+       _alu_exe(rt, rt->alu1);
+       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Executing ALU1 done.\n");
+}
+
+static void _alu2_exe(struct ice_parser_rt *rt)
+{
+       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Executing ALU2 ...\n");
+       _alu_exe(rt, rt->alu2);
+       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Executing ALU2 done.\n");
+}
+
+static void _pu_exe(struct ice_parser_rt *rt)
+{
+       struct ice_gpr_pu *pu = &rt->pu;
+       int i;
+
+       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Updating Registers ...\n");
+
+       for (i = 0; i < ICE_PARSER_GPR_NUM; i++) {
+               if (pu->gpr_val_upd[i])
+                       _rt_gpr_set(rt, i, pu->gpr_val[i]);
+       }
+
+       for (i = 0; i < 64; i++) {
+               if (pu->flg_msk & (1ul << i))
+                       _rt_flag_set(rt, i, pu->flg_val & (1ul << i));
+       }
+
+       for (i = 0; i < 16; i++) {
+               if (pu->err_msk & (1u << 1))
+                       _rt_err_set(rt, i, pu->err_val & (1u << i));
+       }
+
+       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Updating Registers done.\n");
+}
+
+static void _alu_pg_exe(struct ice_parser_rt *rt)
+{
+       ice_memset(&rt->pu, 0, sizeof(rt->pu), ICE_NONDMA_MEM);
+
+       if (rt->pg == 0) {
+               _pg_exe(rt);
+               _alu0_exe(rt);
+               _alu1_exe(rt);
+               _alu2_exe(rt);
+       } else if (rt->pg == 1) {
+               _alu0_exe(rt);
+               _pg_exe(rt);
+               _alu1_exe(rt);
+               _alu2_exe(rt);
+       } else if (rt->pg == 2) {
+               _alu0_exe(rt);
+               _alu1_exe(rt);
+               _pg_exe(rt);
+               _alu2_exe(rt);
+       } else if (rt->pg == 3) {
+               _alu0_exe(rt);
+               _alu1_exe(rt);
+               _alu2_exe(rt);
+               _pg_exe(rt);
+       }
+
+       _pu_exe(rt);
+
+       if (rt->action->ho_inc == 0)
+               return;
+
+       if (rt->action->ho_polarity)
+               _rt_ho_set(rt, rt->gpr[GPR_HO_IDX] + rt->action->ho_inc);
+       else
+               _rt_ho_set(rt, rt->gpr[GPR_HO_IDX] - rt->action->ho_inc);
+}
+
+static void _proto_off_update(struct ice_parser_rt *rt)
+{
+       struct ice_parser *psr = rt->psr;
+       int i;
+
+       if (rt->action->is_pg) {
+               struct ice_proto_grp_item *proto_grp =
+                       &psr->proto_grp_table[rt->action->proto_id];
+               u16 po;
+
+               for (i = 0; i < 8; i++) {
+                       struct ice_proto_off *entry = &proto_grp->po[i];
+
+                       if (entry->proto_id == 0xff)
+                               break;
+
+                       if (!entry->polarity)
+                               po = (u16)(rt->po + entry->offset);
+                       else
+                               po = (u16)(rt->po - entry->offset);
+
+                       rt->protocols[entry->proto_id] = true;
+                       rt->offsets[entry->proto_id] = po;
+
+                       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Set Protocol %d at offset %d\n",
+                                 entry->proto_id, po);
+               }
+       } else {
+               rt->protocols[rt->action->proto_id] = true;
+               rt->offsets[rt->action->proto_id] = rt->po;
+               ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Set Protocol %d at offset %d\n",
+                         rt->action->proto_id, rt->po);
+       }
+}
+
+static void _marker_set(struct ice_parser_rt *rt, int idx)
+{
+       int x = idx / 8;
+       int y = idx % 8;
+
+       rt->markers[x] |= (u8)(1u << y);
+}
+
+static void _marker_update(struct ice_parser_rt *rt)
+{
+       struct ice_parser *psr = rt->psr;
+       int i;
+
+       if (rt->action->is_mg) {
+               struct ice_mk_grp_item *mk_grp =
+                       &psr->mk_grp_table[rt->action->marker_id];
+
+               for (i = 0; i < 8; i++) {
+                       u8 marker = mk_grp->markers[i];
+
+                       if (marker == 71)
+                               break;
+
+                       _marker_set(rt, marker);
+                       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Set Marker %d\n",
+                                 marker);
+               }
+       } else {
+               if (rt->action->marker_id != 71)
+                       _marker_set(rt, rt->action->marker_id);
+               ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Set Marker %d\n",
+                         rt->action->marker_id);
+       }
+}
+
+static u16 _ptype_resolve(struct ice_parser_rt *rt)
+{
+       struct ice_parser *psr = rt->psr;
+       struct ice_ptype_mk_tcam_item *item;
+
+       item = ice_ptype_mk_tcam_match(psr->ptype_mk_tcam_table,
+                                      rt->markers, 9);
+       if (item)
+               return item->ptype;
+       return 0xffff;
+}
+
+static void _proto_off_resolve(struct ice_parser_rt *rt,
+                              struct ice_parser_result *rslt)
+{
+       int i;
+
+       for (i = 0; i < 255; i++) {
+               if (rt->protocols[i]) {
+                       rslt->po[rslt->po_num].proto_id = (u8)i;
+                       rslt->po[rslt->po_num].offset = rt->offsets[i];
+                       rslt->po_num++;
+               }
+       }
+}
+
+static void _result_resolve(struct ice_parser_rt *rt,
+                           struct ice_parser_result *rslt)
+{
+       struct ice_parser *psr = rt->psr;
+
+       ice_memset(rslt, 0, sizeof(*rslt), ICE_NONDMA_MEM);
+
+       rslt->ptype = _ptype_resolve(rt);
+
+       ice_memcpy(&rslt->flags_psr, &rt->gpr[GPR_FLG_IDX], 8,
                   ICE_NONDMA_TO_NONDMA);
+       rslt->flags_pkt = ice_flg_redirect(psr->flg_rd_table, rslt->flags_psr);
+       rslt->flags_sw = ice_xlt_kb_flag_get(psr->xlt_kb_sw, rslt->flags_pkt);
+       rslt->flags_fd = ice_xlt_kb_flag_get(psr->xlt_kb_fd, rslt->flags_pkt);
+       rslt->flags_rss = ice_xlt_kb_flag_get(psr->xlt_kb_rss, rslt->flags_pkt);
+
+       _proto_off_resolve(rt, rslt);
 }
 
 /**
@@ -94,5 +769,102 @@ void ice_parser_rt_pktbuf_set(struct ice_parser_rt *rt, const u8 *pkt_buf,
 enum ice_status ice_parser_rt_execute(struct ice_parser_rt *rt,
                                      struct ice_parser_result *rslt)
 {
-       return ICE_ERR_NOT_IMPL;
+       enum ice_status status = ICE_SUCCESS;
+       struct ice_pg_nm_cam_item *pg_nm_cam;
+       struct ice_parser *psr = rt->psr;
+       struct ice_pg_cam_item *pg_cam;
+       struct ice_bst_tcam_item *bst;
+       struct ice_imem_item *imem;
+       u16 node;
+       u16 pc;
+
+       node = rt->gpr[GPR_NN_IDX];
+       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Start with Node: %d\n", node);
+
+       while (true) {
+               pc = rt->gpr[GPR_NP_IDX];
+               imem = &psr->imem_table[pc];
+               ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Load imem at pc: %d\n",
+                         pc);
+
+               _bst_key_init(rt, imem);
+               bst = ice_bst_tcam_match(psr->bst_tcam_table, rt->bst_key);
+
+               if (!bst) {
+                       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "No Boost TCAM Match\n");
+                       _imem_pgk_init(rt, imem);
+                       _imem_alu0_set(rt, imem);
+                       _imem_alu1_set(rt, imem);
+                       _imem_alu2_set(rt, imem);
+                       _imem_pgp_set(rt, imem);
+               } else {
+                       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Boost TCAM Match address: %d\n",
+                                 bst->address);
+                       if (imem->b_m.pg) {
+                               _bst_pgk_init(rt, bst);
+                               _bst_pgp_set(rt, bst);
+                       } else {
+                               _imem_pgk_init(rt, imem);
+                               _imem_pgp_set(rt, imem);
+                       }
+
+                       if (imem->b_m.al0)
+                               _bst_alu0_set(rt, bst);
+                       else
+                               _imem_alu0_set(rt, imem);
+
+                       if (imem->b_m.al1)
+                               _bst_alu1_set(rt, bst);
+                       else
+                               _imem_alu1_set(rt, imem);
+
+                       if (imem->b_m.al2)
+                               _bst_alu2_set(rt, bst);
+                       else
+                               _imem_alu2_set(rt, imem);
+               }
+
+               rt->action = NULL;
+               pg_cam = _pg_cam_match(rt);
+               if (!pg_cam) {
+                       pg_nm_cam = _pg_nm_cam_match(rt);
+                       if (pg_nm_cam) {
+                               ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Match ParseGraph Nomatch CAM Address %d\n",
+                                         pg_nm_cam->idx);
+                               rt->action = &pg_nm_cam->action;
+                       }
+               } else {
+                       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Match ParseGraph CAM Address %d\n",
+                                 pg_cam->idx);
+                       rt->action = &pg_cam->action;
+               }
+
+               if (!rt->action) {
+                       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Failed to match ParseGraph CAM, stop parsing.\n");
+                       status = ICE_ERR_PARAM;
+                       break;
+               }
+
+               _alu_pg_exe(rt);
+               _marker_update(rt);
+               _proto_off_update(rt);
+
+               ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Go to node %d\n",
+                         rt->action->next_node);
+
+               if (rt->action->is_last_round) {
+                       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Last Round in ParseGraph Action, stop parsing.\n");
+                       break;
+               }
+
+               if (rt->gpr[GPR_HO_IDX] >= rt->pkt_len) {
+                       ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Header Offset %d is larger than packet len %d, stop parsing\n",
+                                 rt->gpr[GPR_HO_IDX], rt->pkt_len);
+                       break;
+               }
+       }
+
+       _result_resolve(rt, rslt);
+
+       return status;
 }
index 32fa7f6..28350d0 100644 (file)
@@ -9,13 +9,38 @@ struct ice_parser_ctx;
 
 #define ICE_PARSER_MAX_PKT_LEN 504
 #define ICE_PARSER_GPR_NUM 128
+#define ICE_PARSER_HDR_BUF_LEN 32
+#define ICE_PARSER_BST_KEY_LEN 20
+#define ICE_PARSER_MARKER_NUM_IN_BYTES 9 /* 72 bits */
+#define ICE_PARSER_PROTO_NUM 256
+
+struct ice_gpr_pu {
+       /* flag to indicate if GRP needs to be updated */
+       bool gpr_val_upd[ICE_PARSER_GPR_NUM];
+       u16 gpr_val[ICE_PARSER_GPR_NUM];
+       u64 flg_msk;
+       u64 flg_val;
+       u16 err_msk;
+       u16 err_val;
+};
 
 struct ice_parser_rt {
        struct ice_parser *psr;
        u16 gpr[ICE_PARSER_GPR_NUM];
-       u8 pkt_buf[ICE_PARSER_MAX_PKT_LEN + 32];
+       u8 pkt_buf[ICE_PARSER_MAX_PKT_LEN + ICE_PARSER_HDR_BUF_LEN];
        u16 pkt_len;
        u16 po;
+       u8 bst_key[ICE_PARSER_BST_KEY_LEN];
+       struct ice_pg_cam_key pg_key;
+       struct ice_alu *alu0;
+       struct ice_alu *alu1;
+       struct ice_alu *alu2;
+       struct ice_pg_cam_action *action;
+       u8 pg;
+       struct ice_gpr_pu pu;
+       u8 markers[ICE_PARSER_MARKER_NUM_IN_BYTES];
+       bool protocols[ICE_PARSER_PROTO_NUM];
+       u16 offsets[ICE_PARSER_PROTO_NUM];
 };
 
 void ice_parser_rt_reset(struct ice_parser_rt *rt);