forked from mirrors/linux
		
	 e312b3a1e2
			
		
	
	
		e312b3a1e2
		
	
	
	
	
		
			
			Add API ice_parser_profile_init() to init a parser profile based on a parser result and a mask buffer. The ice_parser_profile struct is used by the low level FXP engine to create HW profile/field vectors. Reviewed-by: Marcin Szycik <marcin.szycik@linux.intel.com> Signed-off-by: Qi Zhang <qi.z.zhang@intel.com> Signed-off-by: Junfeng Guo <junfeng.guo@intel.com> Signed-off-by: Ahmed Zaki <ahmed.zaki@intel.com> Tested-by: Rafal Romanowski <rafal.romanowski@intel.com> Reviewed-by: Simon Horman <horms@kernel.org> Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
		
			
				
	
	
		
			2430 lines
		
	
	
	
		
			73 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			2430 lines
		
	
	
	
		
			73 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| // SPDX-License-Identifier: GPL-2.0
 | |
| /* Copyright (C) 2024 Intel Corporation */
 | |
| 
 | |
| #include "ice_common.h"
 | |
| 
 | |
| struct ice_pkg_sect_hdr {
 | |
| 	__le16 count;
 | |
| 	__le16 offset;
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * ice_parser_sect_item_get - parse an item from a section
 | |
|  * @sect_type: section type
 | |
|  * @section: section object
 | |
|  * @index: index of the item to get
 | |
|  * @offset: dummy as prototype of ice_pkg_enum_entry's last parameter
 | |
|  *
 | |
|  * Return: a pointer to the item or NULL.
 | |
|  */
 | |
| static void *ice_parser_sect_item_get(u32 sect_type, void *section,
 | |
| 				      u32 index, u32 __maybe_unused *offset)
 | |
| {
 | |
| 	size_t data_off = ICE_SEC_DATA_OFFSET;
 | |
| 	struct ice_pkg_sect_hdr *hdr;
 | |
| 	size_t size;
 | |
| 
 | |
| 	if (!section)
 | |
| 		return NULL;
 | |
| 
 | |
| 	switch (sect_type) {
 | |
| 	case ICE_SID_RXPARSER_IMEM:
 | |
| 		size = ICE_SID_RXPARSER_IMEM_ENTRY_SIZE;
 | |
| 		break;
 | |
| 	case ICE_SID_RXPARSER_METADATA_INIT:
 | |
| 		size = ICE_SID_RXPARSER_METADATA_INIT_ENTRY_SIZE;
 | |
| 		break;
 | |
| 	case ICE_SID_RXPARSER_CAM:
 | |
| 		size = ICE_SID_RXPARSER_CAM_ENTRY_SIZE;
 | |
| 		break;
 | |
| 	case ICE_SID_RXPARSER_PG_SPILL:
 | |
| 		size = ICE_SID_RXPARSER_PG_SPILL_ENTRY_SIZE;
 | |
| 		break;
 | |
| 	case ICE_SID_RXPARSER_NOMATCH_CAM:
 | |
| 		size = ICE_SID_RXPARSER_NOMATCH_CAM_ENTRY_SIZE;
 | |
| 		break;
 | |
| 	case ICE_SID_RXPARSER_NOMATCH_SPILL:
 | |
| 		size = ICE_SID_RXPARSER_NOMATCH_SPILL_ENTRY_SIZE;
 | |
| 		break;
 | |
| 	case ICE_SID_RXPARSER_BOOST_TCAM:
 | |
| 		size = ICE_SID_RXPARSER_BOOST_TCAM_ENTRY_SIZE;
 | |
| 		break;
 | |
| 	case ICE_SID_LBL_RXPARSER_TMEM:
 | |
| 		data_off = ICE_SEC_LBL_DATA_OFFSET;
 | |
| 		size = ICE_SID_LBL_ENTRY_SIZE;
 | |
| 		break;
 | |
| 	case ICE_SID_RXPARSER_MARKER_PTYPE:
 | |
| 		size = ICE_SID_RXPARSER_MARKER_TYPE_ENTRY_SIZE;
 | |
| 		break;
 | |
| 	case ICE_SID_RXPARSER_MARKER_GRP:
 | |
| 		size = ICE_SID_RXPARSER_MARKER_GRP_ENTRY_SIZE;
 | |
| 		break;
 | |
| 	case ICE_SID_RXPARSER_PROTO_GRP:
 | |
| 		size = ICE_SID_RXPARSER_PROTO_GRP_ENTRY_SIZE;
 | |
| 		break;
 | |
| 	case ICE_SID_RXPARSER_FLAG_REDIR:
 | |
| 		size = ICE_SID_RXPARSER_FLAG_REDIR_ENTRY_SIZE;
 | |
| 		break;
 | |
| 	default:
 | |
| 		return NULL;
 | |
| 	}
 | |
| 
 | |
| 	hdr = section;
 | |
| 	if (index >= le16_to_cpu(hdr->count))
 | |
| 		return NULL;
 | |
| 
 | |
| 	return section + data_off + index * size;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_parser_create_table - create an item table from a section
 | |
|  * @hw: pointer to the hardware structure
 | |
|  * @sect_type: section type
 | |
|  * @item_size: item size in bytes
 | |
|  * @length: number of items in the table to create
 | |
|  * @parse_item: the function to parse the item
 | |
|  * @no_offset: ignore header offset, calculate index from 0
 | |
|  *
 | |
|  * Return: a pointer to the allocated table or ERR_PTR.
 | |
|  */
 | |
| static void *
 | |
| ice_parser_create_table(struct ice_hw *hw, u32 sect_type,
 | |
| 			u32 item_size, u32 length,
 | |
| 			void (*parse_item)(struct ice_hw *hw, u16 idx,
 | |
| 					   void *item, void *data,
 | |
| 					   int size), bool no_offset)
 | |
| {
 | |
| 	struct ice_pkg_enum state = {};
 | |
| 	struct ice_seg *seg = hw->seg;
 | |
| 	void *table, *data, *item;
 | |
| 	u16 idx = 0;
 | |
| 
 | |
| 	if (!seg)
 | |
| 		return ERR_PTR(-EINVAL);
 | |
| 
 | |
| 	table = kzalloc(item_size * length, GFP_KERNEL);
 | |
| 	if (!table)
 | |
| 		return ERR_PTR(-ENOMEM);
 | |
| 
 | |
| 	do {
 | |
| 		data = ice_pkg_enum_entry(seg, &state, sect_type, NULL,
 | |
| 					  ice_parser_sect_item_get);
 | |
| 		seg = NULL;
 | |
| 		if (data) {
 | |
| 			struct ice_pkg_sect_hdr *hdr = state.sect;
 | |
| 
 | |
| 			if (!no_offset)
 | |
| 				idx = le16_to_cpu(hdr->offset) +
 | |
| 					state.entry_idx;
 | |
| 
 | |
| 			item = (void *)((uintptr_t)table + idx * item_size);
 | |
| 			parse_item(hw, idx, item, data, item_size);
 | |
| 
 | |
| 			if (no_offset)
 | |
| 				idx++;
 | |
| 		}
 | |
| 	} while (data);
 | |
| 
 | |
| 	return table;
 | |
| }
 | |
| 
 | |
| /*** ICE_SID_RXPARSER_IMEM section ***/
 | |
| static void ice_imem_bst_bm_dump(struct ice_hw *hw, struct ice_bst_main *bm)
 | |
| {
 | |
| 	struct device *dev = ice_hw_to_dev(hw);
 | |
| 
 | |
| 	dev_info(dev, "boost main:\n");
 | |
| 	dev_info(dev, "\talu0 = %d\n", bm->alu0);
 | |
| 	dev_info(dev, "\talu1 = %d\n", bm->alu1);
 | |
| 	dev_info(dev, "\talu2 = %d\n", bm->alu2);
 | |
| 	dev_info(dev, "\tpg = %d\n", bm->pg);
 | |
| }
 | |
| 
 | |
| static void ice_imem_bst_kb_dump(struct ice_hw *hw,
 | |
| 				 struct ice_bst_keybuilder *kb)
 | |
| {
 | |
| 	struct device *dev = ice_hw_to_dev(hw);
 | |
| 
 | |
| 	dev_info(dev, "boost key builder:\n");
 | |
| 	dev_info(dev, "\tpriority = %d\n", kb->prio);
 | |
| 	dev_info(dev, "\ttsr_ctrl = %d\n", kb->tsr_ctrl);
 | |
| }
 | |
| 
 | |
| static void ice_imem_np_kb_dump(struct ice_hw *hw,
 | |
| 				struct ice_np_keybuilder *kb)
 | |
| {
 | |
| 	struct device *dev = ice_hw_to_dev(hw);
 | |
| 
 | |
| 	dev_info(dev, "next proto key builder:\n");
 | |
| 	dev_info(dev, "\topc = %d\n", kb->opc);
 | |
| 	dev_info(dev, "\tstart_or_reg0 = %d\n", kb->start_reg0);
 | |
| 	dev_info(dev, "\tlen_or_reg1 = %d\n", kb->len_reg1);
 | |
| }
 | |
| 
 | |
| static void ice_imem_pg_kb_dump(struct ice_hw *hw,
 | |
| 				struct ice_pg_keybuilder *kb)
 | |
| {
 | |
| 	struct device *dev = ice_hw_to_dev(hw);
 | |
| 
 | |
| 	dev_info(dev, "parse graph key builder:\n");
 | |
| 	dev_info(dev, "\tflag0_ena = %d\n", kb->flag0_ena);
 | |
| 	dev_info(dev, "\tflag1_ena = %d\n", kb->flag1_ena);
 | |
| 	dev_info(dev, "\tflag2_ena = %d\n", kb->flag2_ena);
 | |
| 	dev_info(dev, "\tflag3_ena = %d\n", kb->flag3_ena);
 | |
| 	dev_info(dev, "\tflag0_idx = %d\n", kb->flag0_idx);
 | |
| 	dev_info(dev, "\tflag1_idx = %d\n", kb->flag1_idx);
 | |
| 	dev_info(dev, "\tflag2_idx = %d\n", kb->flag2_idx);
 | |
| 	dev_info(dev, "\tflag3_idx = %d\n", kb->flag3_idx);
 | |
| 	dev_info(dev, "\talu_reg_idx = %d\n", kb->alu_reg_idx);
 | |
| }
 | |
| 
 | |
| static void ice_imem_alu_dump(struct ice_hw *hw,
 | |
| 			      struct ice_alu *alu, int index)
 | |
| {
 | |
| 	struct device *dev = ice_hw_to_dev(hw);
 | |
| 
 | |
| 	dev_info(dev, "alu%d:\n", index);
 | |
| 	dev_info(dev, "\topc = %d\n", alu->opc);
 | |
| 	dev_info(dev, "\tsrc_start = %d\n", alu->src_start);
 | |
| 	dev_info(dev, "\tsrc_len = %d\n", alu->src_len);
 | |
| 	dev_info(dev, "\tshift_xlate_sel = %d\n", alu->shift_xlate_sel);
 | |
| 	dev_info(dev, "\tshift_xlate_key = %d\n", alu->shift_xlate_key);
 | |
| 	dev_info(dev, "\tsrc_reg_id = %d\n", alu->src_reg_id);
 | |
| 	dev_info(dev, "\tdst_reg_id = %d\n", alu->dst_reg_id);
 | |
| 	dev_info(dev, "\tinc0 = %d\n", alu->inc0);
 | |
| 	dev_info(dev, "\tinc1 = %d\n", alu->inc1);
 | |
| 	dev_info(dev, "\tproto_offset_opc = %d\n", alu->proto_offset_opc);
 | |
| 	dev_info(dev, "\tproto_offset = %d\n", alu->proto_offset);
 | |
| 	dev_info(dev, "\tbranch_addr = %d\n", alu->branch_addr);
 | |
| 	dev_info(dev, "\timm = %d\n", alu->imm);
 | |
| 	dev_info(dev, "\tdst_start = %d\n", alu->dst_start);
 | |
| 	dev_info(dev, "\tdst_len = %d\n", alu->dst_len);
 | |
| 	dev_info(dev, "\tflags_extr_imm = %d\n", alu->flags_extr_imm);
 | |
| 	dev_info(dev, "\tflags_start_imm= %d\n", alu->flags_start_imm);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_imem_dump - dump an imem item info
 | |
|  * @hw: pointer to the hardware structure
 | |
|  * @item: imem item to dump
 | |
|  */
 | |
| static void ice_imem_dump(struct ice_hw *hw, struct ice_imem_item *item)
 | |
| {
 | |
| 	struct device *dev = ice_hw_to_dev(hw);
 | |
| 
 | |
| 	dev_info(dev, "index = %d\n", item->idx);
 | |
| 	ice_imem_bst_bm_dump(hw, &item->b_m);
 | |
| 	ice_imem_bst_kb_dump(hw, &item->b_kb);
 | |
| 	dev_info(dev, "pg priority = %d\n", item->pg_prio);
 | |
| 	ice_imem_np_kb_dump(hw, &item->np_kb);
 | |
| 	ice_imem_pg_kb_dump(hw, &item->pg_kb);
 | |
| 	ice_imem_alu_dump(hw, &item->alu0, 0);
 | |
| 	ice_imem_alu_dump(hw, &item->alu1, 1);
 | |
| 	ice_imem_alu_dump(hw, &item->alu2, 2);
 | |
| }
 | |
| 
 | |
| #define ICE_IM_BM_ALU0		BIT(0)
 | |
| #define ICE_IM_BM_ALU1		BIT(1)
 | |
| #define ICE_IM_BM_ALU2		BIT(2)
 | |
| #define ICE_IM_BM_PG		BIT(3)
 | |
| 
 | |
| /**
 | |
|  * ice_imem_bm_init - parse 4 bits of Boost Main
 | |
|  * @bm: pointer to the Boost Main structure
 | |
|  * @data: Boost Main data to be parsed
 | |
|  */
 | |
| static void ice_imem_bm_init(struct ice_bst_main *bm, u8 data)
 | |
| {
 | |
| 	bm->alu0	= FIELD_GET(ICE_IM_BM_ALU0, data);
 | |
| 	bm->alu1	= FIELD_GET(ICE_IM_BM_ALU1, data);
 | |
| 	bm->alu2	= FIELD_GET(ICE_IM_BM_ALU2, data);
 | |
| 	bm->pg		= FIELD_GET(ICE_IM_BM_PG, data);
 | |
| }
 | |
| 
 | |
| #define ICE_IM_BKB_PRIO		GENMASK(7, 0)
 | |
| #define ICE_IM_BKB_TSR_CTRL	BIT(8)
 | |
| 
 | |
| /**
 | |
|  * ice_imem_bkb_init - parse 10 bits of Boost Main Build
 | |
|  * @bkb: pointer to the Boost Main Build structure
 | |
|  * @data: Boost Main Build data to be parsed
 | |
|  */
 | |
| static void ice_imem_bkb_init(struct ice_bst_keybuilder *bkb, u16 data)
 | |
| {
 | |
| 	bkb->prio	= FIELD_GET(ICE_IM_BKB_PRIO, data);
 | |
| 	bkb->tsr_ctrl	= FIELD_GET(ICE_IM_BKB_TSR_CTRL, data);
 | |
| }
 | |
| 
 | |
| #define ICE_IM_NPKB_OPC		GENMASK(1, 0)
 | |
| #define ICE_IM_NPKB_S_R0	GENMASK(9, 2)
 | |
| #define ICE_IM_NPKB_L_R1	GENMASK(17, 10)
 | |
| 
 | |
| /**
 | |
|  * ice_imem_npkb_init - parse 18 bits of Next Protocol Key Build
 | |
|  * @kb: pointer to the Next Protocol Key Build structure
 | |
|  * @data: Next Protocol Key Build data to be parsed
 | |
|  */
 | |
| static void ice_imem_npkb_init(struct ice_np_keybuilder *kb, u32 data)
 | |
| {
 | |
| 	kb->opc		= FIELD_GET(ICE_IM_NPKB_OPC, data);
 | |
| 	kb->start_reg0	= FIELD_GET(ICE_IM_NPKB_S_R0, data);
 | |
| 	kb->len_reg1	= FIELD_GET(ICE_IM_NPKB_L_R1, data);
 | |
| }
 | |
| 
 | |
| #define ICE_IM_PGKB_F0_ENA	BIT_ULL(0)
 | |
| #define ICE_IM_PGKB_F0_IDX	GENMASK_ULL(6, 1)
 | |
| #define ICE_IM_PGKB_F1_ENA	BIT_ULL(7)
 | |
| #define ICE_IM_PGKB_F1_IDX	GENMASK_ULL(13, 8)
 | |
| #define ICE_IM_PGKB_F2_ENA	BIT_ULL(14)
 | |
| #define ICE_IM_PGKB_F2_IDX	GENMASK_ULL(20, 15)
 | |
| #define ICE_IM_PGKB_F3_ENA	BIT_ULL(21)
 | |
| #define ICE_IM_PGKB_F3_IDX	GENMASK_ULL(27, 22)
 | |
| #define ICE_IM_PGKB_AR_IDX	GENMASK_ULL(34, 28)
 | |
| 
 | |
| /**
 | |
|  * ice_imem_pgkb_init - parse 35 bits of Parse Graph Key Build
 | |
|  * @kb: pointer to the Parse Graph Key Build structure
 | |
|  * @data: Parse Graph Key Build data to be parsed
 | |
|  */
 | |
| static void ice_imem_pgkb_init(struct ice_pg_keybuilder *kb, u64 data)
 | |
| {
 | |
| 	kb->flag0_ena	= FIELD_GET(ICE_IM_PGKB_F0_ENA, data);
 | |
| 	kb->flag0_idx	= FIELD_GET(ICE_IM_PGKB_F0_IDX, data);
 | |
| 	kb->flag1_ena	= FIELD_GET(ICE_IM_PGKB_F1_ENA, data);
 | |
| 	kb->flag1_idx	= FIELD_GET(ICE_IM_PGKB_F1_IDX, data);
 | |
| 	kb->flag2_ena	= FIELD_GET(ICE_IM_PGKB_F2_ENA, data);
 | |
| 	kb->flag2_idx	= FIELD_GET(ICE_IM_PGKB_F2_IDX, data);
 | |
| 	kb->flag3_ena	= FIELD_GET(ICE_IM_PGKB_F3_ENA, data);
 | |
| 	kb->flag3_idx	= FIELD_GET(ICE_IM_PGKB_F3_IDX, data);
 | |
| 	kb->alu_reg_idx	= FIELD_GET(ICE_IM_PGKB_AR_IDX, data);
 | |
| }
 | |
| 
 | |
| #define ICE_IM_ALU_OPC		GENMASK_ULL(5, 0)
 | |
| #define ICE_IM_ALU_SS		GENMASK_ULL(13, 6)
 | |
| #define ICE_IM_ALU_SL		GENMASK_ULL(18, 14)
 | |
| #define ICE_IM_ALU_SXS		BIT_ULL(19)
 | |
| #define ICE_IM_ALU_SXK		GENMASK_ULL(23, 20)
 | |
| #define ICE_IM_ALU_SRID		GENMASK_ULL(30, 24)
 | |
| #define ICE_IM_ALU_DRID		GENMASK_ULL(37, 31)
 | |
| #define ICE_IM_ALU_INC0		BIT_ULL(38)
 | |
| #define ICE_IM_ALU_INC1		BIT_ULL(39)
 | |
| #define ICE_IM_ALU_POO		GENMASK_ULL(41, 40)
 | |
| #define ICE_IM_ALU_PO		GENMASK_ULL(49, 42)
 | |
| #define ICE_IM_ALU_BA_S		50	/* offset for the 2nd 64-bits field */
 | |
| #define ICE_IM_ALU_BA		GENMASK_ULL(57 - ICE_IM_ALU_BA_S, \
 | |
| 					    50 - ICE_IM_ALU_BA_S)
 | |
| #define ICE_IM_ALU_IMM		GENMASK_ULL(73 - ICE_IM_ALU_BA_S, \
 | |
| 					    58 - ICE_IM_ALU_BA_S)
 | |
| #define ICE_IM_ALU_DFE		BIT_ULL(74 - ICE_IM_ALU_BA_S)
 | |
| #define ICE_IM_ALU_DS		GENMASK_ULL(80 - ICE_IM_ALU_BA_S, \
 | |
| 					    75 - ICE_IM_ALU_BA_S)
 | |
| #define ICE_IM_ALU_DL		GENMASK_ULL(86 - ICE_IM_ALU_BA_S, \
 | |
| 					    81 - ICE_IM_ALU_BA_S)
 | |
| #define ICE_IM_ALU_FEI		BIT_ULL(87 - ICE_IM_ALU_BA_S)
 | |
| #define ICE_IM_ALU_FSI		GENMASK_ULL(95 - ICE_IM_ALU_BA_S, \
 | |
| 					    88 - ICE_IM_ALU_BA_S)
 | |
| 
 | |
| /**
 | |
|  * ice_imem_alu_init - parse 96 bits of ALU entry
 | |
|  * @alu: pointer to the ALU entry structure
 | |
|  * @data: ALU entry data to be parsed
 | |
|  * @off: offset of the ALU entry data
 | |
|  */
 | |
| static void ice_imem_alu_init(struct ice_alu *alu, u8 *data, u8 off)
 | |
| {
 | |
| 	u64 d64;
 | |
| 	u8 idd;
 | |
| 
 | |
| 	d64 = *((u64 *)data) >> off;
 | |
| 
 | |
| 	alu->opc		= FIELD_GET(ICE_IM_ALU_OPC, d64);
 | |
| 	alu->src_start		= FIELD_GET(ICE_IM_ALU_SS, d64);
 | |
| 	alu->src_len		= FIELD_GET(ICE_IM_ALU_SL, d64);
 | |
| 	alu->shift_xlate_sel	= FIELD_GET(ICE_IM_ALU_SXS, d64);
 | |
| 	alu->shift_xlate_key	= FIELD_GET(ICE_IM_ALU_SXK, d64);
 | |
| 	alu->src_reg_id		= FIELD_GET(ICE_IM_ALU_SRID, d64);
 | |
| 	alu->dst_reg_id		= FIELD_GET(ICE_IM_ALU_DRID, d64);
 | |
| 	alu->inc0		= FIELD_GET(ICE_IM_ALU_INC0, d64);
 | |
| 	alu->inc1		= FIELD_GET(ICE_IM_ALU_INC1, d64);
 | |
| 	alu->proto_offset_opc	= FIELD_GET(ICE_IM_ALU_POO, d64);
 | |
| 	alu->proto_offset	= FIELD_GET(ICE_IM_ALU_PO, d64);
 | |
| 
 | |
| 	idd = (ICE_IM_ALU_BA_S + off) / BITS_PER_BYTE;
 | |
| 	off = (ICE_IM_ALU_BA_S + off) % BITS_PER_BYTE;
 | |
| 	d64 = *((u64 *)(&data[idd])) >> off;
 | |
| 
 | |
| 	alu->branch_addr	= FIELD_GET(ICE_IM_ALU_BA, d64);
 | |
| 	alu->imm		= FIELD_GET(ICE_IM_ALU_IMM, d64);
 | |
| 	alu->dedicate_flags_ena	= FIELD_GET(ICE_IM_ALU_DFE, d64);
 | |
| 	alu->dst_start		= FIELD_GET(ICE_IM_ALU_DS, d64);
 | |
| 	alu->dst_len		= FIELD_GET(ICE_IM_ALU_DL, d64);
 | |
| 	alu->flags_extr_imm	= FIELD_GET(ICE_IM_ALU_FEI, d64);
 | |
| 	alu->flags_start_imm	= FIELD_GET(ICE_IM_ALU_FSI, d64);
 | |
| }
 | |
| 
 | |
| #define ICE_IMEM_BM_S		0
 | |
| #define ICE_IMEM_BKB_S		4
 | |
| #define ICE_IMEM_BKB_IDD	(ICE_IMEM_BKB_S / BITS_PER_BYTE)
 | |
| #define ICE_IMEM_BKB_OFF	(ICE_IMEM_BKB_S % BITS_PER_BYTE)
 | |
| #define ICE_IMEM_PGP		GENMASK(15, 14)
 | |
| #define ICE_IMEM_NPKB_S		16
 | |
| #define ICE_IMEM_NPKB_IDD	(ICE_IMEM_NPKB_S / BITS_PER_BYTE)
 | |
| #define ICE_IMEM_NPKB_OFF	(ICE_IMEM_NPKB_S % BITS_PER_BYTE)
 | |
| #define ICE_IMEM_PGKB_S		34
 | |
| #define ICE_IMEM_PGKB_IDD	(ICE_IMEM_PGKB_S / BITS_PER_BYTE)
 | |
| #define ICE_IMEM_PGKB_OFF	(ICE_IMEM_PGKB_S % BITS_PER_BYTE)
 | |
| #define ICE_IMEM_ALU0_S		69
 | |
| #define ICE_IMEM_ALU0_IDD	(ICE_IMEM_ALU0_S / BITS_PER_BYTE)
 | |
| #define ICE_IMEM_ALU0_OFF	(ICE_IMEM_ALU0_S % BITS_PER_BYTE)
 | |
| #define ICE_IMEM_ALU1_S		165
 | |
| #define ICE_IMEM_ALU1_IDD	(ICE_IMEM_ALU1_S / BITS_PER_BYTE)
 | |
| #define ICE_IMEM_ALU1_OFF	(ICE_IMEM_ALU1_S % BITS_PER_BYTE)
 | |
| #define ICE_IMEM_ALU2_S		357
 | |
| #define ICE_IMEM_ALU2_IDD	(ICE_IMEM_ALU2_S / BITS_PER_BYTE)
 | |
| #define ICE_IMEM_ALU2_OFF	(ICE_IMEM_ALU2_S % BITS_PER_BYTE)
 | |
| 
 | |
| /**
 | |
|  * ice_imem_parse_item - parse 384 bits of IMEM entry
 | |
|  * @hw: pointer to the hardware structure
 | |
|  * @idx: index of IMEM entry
 | |
|  * @item: item of IMEM entry
 | |
|  * @data: IMEM entry data to be parsed
 | |
|  * @size: size of IMEM entry
 | |
|  */
 | |
| static void ice_imem_parse_item(struct ice_hw *hw, u16 idx, void *item,
 | |
| 				void *data, int __maybe_unused size)
 | |
| {
 | |
| 	struct ice_imem_item *ii = item;
 | |
| 	u8 *buf = data;
 | |
| 
 | |
| 	ii->idx = idx;
 | |
| 
 | |
| 	ice_imem_bm_init(&ii->b_m, *(u8 *)buf);
 | |
| 	ice_imem_bkb_init(&ii->b_kb,
 | |
| 			  *((u16 *)(&buf[ICE_IMEM_BKB_IDD])) >>
 | |
| 			   ICE_IMEM_BKB_OFF);
 | |
| 
 | |
| 	ii->pg_prio = FIELD_GET(ICE_IMEM_PGP, *(u16 *)buf);
 | |
| 
 | |
| 	ice_imem_npkb_init(&ii->np_kb,
 | |
| 			   *((u32 *)(&buf[ICE_IMEM_NPKB_IDD])) >>
 | |
| 			    ICE_IMEM_NPKB_OFF);
 | |
| 	ice_imem_pgkb_init(&ii->pg_kb,
 | |
| 			   *((u64 *)(&buf[ICE_IMEM_PGKB_IDD])) >>
 | |
| 			    ICE_IMEM_PGKB_OFF);
 | |
| 
 | |
| 	ice_imem_alu_init(&ii->alu0,
 | |
| 			  &buf[ICE_IMEM_ALU0_IDD],
 | |
| 			  ICE_IMEM_ALU0_OFF);
 | |
| 	ice_imem_alu_init(&ii->alu1,
 | |
| 			  &buf[ICE_IMEM_ALU1_IDD],
 | |
| 			  ICE_IMEM_ALU1_OFF);
 | |
| 	ice_imem_alu_init(&ii->alu2,
 | |
| 			  &buf[ICE_IMEM_ALU2_IDD],
 | |
| 			  ICE_IMEM_ALU2_OFF);
 | |
| 
 | |
| 	if (hw->debug_mask & ICE_DBG_PARSER)
 | |
| 		ice_imem_dump(hw, ii);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_imem_table_get - create an imem table
 | |
|  * @hw: pointer to the hardware structure
 | |
|  *
 | |
|  * Return: a pointer to the allocated IMEM table.
 | |
|  */
 | |
| static struct ice_imem_item *ice_imem_table_get(struct ice_hw *hw)
 | |
| {
 | |
| 	return ice_parser_create_table(hw, ICE_SID_RXPARSER_IMEM,
 | |
| 				       sizeof(struct ice_imem_item),
 | |
| 				       ICE_IMEM_TABLE_SIZE,
 | |
| 				       ice_imem_parse_item, false);
 | |
| }
 | |
| 
 | |
| /*** ICE_SID_RXPARSER_METADATA_INIT section ***/
 | |
| /**
 | |
|  * ice_metainit_dump - dump an metainit item info
 | |
|  * @hw: pointer to the hardware structure
 | |
|  * @item: metainit item to dump
 | |
|  */
 | |
| static void ice_metainit_dump(struct ice_hw *hw, struct ice_metainit_item *item)
 | |
| {
 | |
| 	struct device *dev = ice_hw_to_dev(hw);
 | |
| 
 | |
| 	dev_info(dev, "index = %d\n", item->idx);
 | |
| 
 | |
| 	dev_info(dev, "tsr = %d\n", item->tsr);
 | |
| 	dev_info(dev, "ho = %d\n", item->ho);
 | |
| 	dev_info(dev, "pc = %d\n", item->pc);
 | |
| 	dev_info(dev, "pg_rn = %d\n", item->pg_rn);
 | |
| 	dev_info(dev, "cd = %d\n", item->cd);
 | |
| 
 | |
| 	dev_info(dev, "gpr_a_ctrl = %d\n", item->gpr_a_ctrl);
 | |
| 	dev_info(dev, "gpr_a_data_mdid = %d\n", item->gpr_a_data_mdid);
 | |
| 	dev_info(dev, "gpr_a_data_start = %d\n", item->gpr_a_data_start);
 | |
| 	dev_info(dev, "gpr_a_data_len = %d\n", item->gpr_a_data_len);
 | |
| 	dev_info(dev, "gpr_a_id = %d\n", item->gpr_a_id);
 | |
| 
 | |
| 	dev_info(dev, "gpr_b_ctrl = %d\n", item->gpr_b_ctrl);
 | |
| 	dev_info(dev, "gpr_b_data_mdid = %d\n", item->gpr_b_data_mdid);
 | |
| 	dev_info(dev, "gpr_b_data_start = %d\n", item->gpr_b_data_start);
 | |
| 	dev_info(dev, "gpr_b_data_len = %d\n", item->gpr_b_data_len);
 | |
| 	dev_info(dev, "gpr_b_id = %d\n", item->gpr_b_id);
 | |
| 
 | |
| 	dev_info(dev, "gpr_c_ctrl = %d\n", item->gpr_c_ctrl);
 | |
| 	dev_info(dev, "gpr_c_data_mdid = %d\n", item->gpr_c_data_mdid);
 | |
| 	dev_info(dev, "gpr_c_data_start = %d\n", item->gpr_c_data_start);
 | |
| 	dev_info(dev, "gpr_c_data_len = %d\n", item->gpr_c_data_len);
 | |
| 	dev_info(dev, "gpr_c_id = %d\n", item->gpr_c_id);
 | |
| 
 | |
| 	dev_info(dev, "gpr_d_ctrl = %d\n", item->gpr_d_ctrl);
 | |
| 	dev_info(dev, "gpr_d_data_mdid = %d\n", item->gpr_d_data_mdid);
 | |
| 	dev_info(dev, "gpr_d_data_start = %d\n", item->gpr_d_data_start);
 | |
| 	dev_info(dev, "gpr_d_data_len = %d\n", item->gpr_d_data_len);
 | |
| 	dev_info(dev, "gpr_d_id = %d\n", item->gpr_d_id);
 | |
| 
 | |
| 	dev_info(dev, "flags = 0x%llx\n", (unsigned long long)(item->flags));
 | |
| }
 | |
| 
 | |
| #define ICE_MI_TSR		GENMASK_ULL(7, 0)
 | |
| #define ICE_MI_HO		GENMASK_ULL(16, 8)
 | |
| #define ICE_MI_PC		GENMASK_ULL(24, 17)
 | |
| #define ICE_MI_PGRN		GENMASK_ULL(35, 25)
 | |
| #define ICE_MI_CD		GENMASK_ULL(38, 36)
 | |
| #define ICE_MI_GAC		BIT_ULL(39)
 | |
| #define ICE_MI_GADM		GENMASK_ULL(44, 40)
 | |
| #define ICE_MI_GADS		GENMASK_ULL(48, 45)
 | |
| #define ICE_MI_GADL		GENMASK_ULL(53, 49)
 | |
| #define ICE_MI_GAI		GENMASK_ULL(59, 56)
 | |
| #define ICE_MI_GBC		BIT_ULL(60)
 | |
| #define ICE_MI_GBDM_S		61	/* offset for the 2nd 64-bits field */
 | |
| #define ICE_MI_GBDM_IDD		(ICE_MI_GBDM_S / BITS_PER_BYTE)
 | |
| #define ICE_MI_GBDM_OFF		(ICE_MI_GBDM_S % BITS_PER_BYTE)
 | |
| 
 | |
| #define ICE_MI_GBDM_GENMASK_ULL(high, low) \
 | |
| 	GENMASK_ULL((high) - ICE_MI_GBDM_S, (low) - ICE_MI_GBDM_S)
 | |
| #define ICE_MI_GBDM		ICE_MI_GBDM_GENMASK_ULL(65, 61)
 | |
| #define ICE_MI_GBDS		ICE_MI_GBDM_GENMASK_ULL(69, 66)
 | |
| #define ICE_MI_GBDL		ICE_MI_GBDM_GENMASK_ULL(74, 70)
 | |
| #define ICE_MI_GBI		ICE_MI_GBDM_GENMASK_ULL(80, 77)
 | |
| #define ICE_MI_GCC		BIT_ULL(81 - ICE_MI_GBDM_S)
 | |
| #define ICE_MI_GCDM		ICE_MI_GBDM_GENMASK_ULL(86, 82)
 | |
| #define ICE_MI_GCDS		ICE_MI_GBDM_GENMASK_ULL(90, 87)
 | |
| #define ICE_MI_GCDL		ICE_MI_GBDM_GENMASK_ULL(95, 91)
 | |
| #define ICE_MI_GCI		ICE_MI_GBDM_GENMASK_ULL(101, 98)
 | |
| #define ICE_MI_GDC		BIT_ULL(102 - ICE_MI_GBDM_S)
 | |
| #define ICE_MI_GDDM		ICE_MI_GBDM_GENMASK_ULL(107, 103)
 | |
| #define ICE_MI_GDDS		ICE_MI_GBDM_GENMASK_ULL(111, 108)
 | |
| #define ICE_MI_GDDL		ICE_MI_GBDM_GENMASK_ULL(116, 112)
 | |
| #define ICE_MI_GDI		ICE_MI_GBDM_GENMASK_ULL(122, 119)
 | |
| #define ICE_MI_FLAG_S		123	/* offset for the 3rd 64-bits field */
 | |
| #define ICE_MI_FLAG_IDD		(ICE_MI_FLAG_S / BITS_PER_BYTE)
 | |
| #define ICE_MI_FLAG_OFF		(ICE_MI_FLAG_S % BITS_PER_BYTE)
 | |
| #define ICE_MI_FLAG		GENMASK_ULL(186 - ICE_MI_FLAG_S, \
 | |
| 					    123 - ICE_MI_FLAG_S)
 | |
| 
 | |
| /**
 | |
|  * ice_metainit_parse_item - parse 192 bits of Metadata Init entry
 | |
|  * @hw: pointer to the hardware structure
 | |
|  * @idx: index of Metadata Init entry
 | |
|  * @item: item of Metadata Init entry
 | |
|  * @data: Metadata Init entry data to be parsed
 | |
|  * @size: size of Metadata Init entry
 | |
|  */
 | |
| static void ice_metainit_parse_item(struct ice_hw *hw, u16 idx, void *item,
 | |
| 				    void *data, int __maybe_unused size)
 | |
| {
 | |
| 	struct ice_metainit_item *mi = item;
 | |
| 	u8 *buf = data;
 | |
| 	u64 d64;
 | |
| 
 | |
| 	mi->idx = idx;
 | |
| 
 | |
| 	d64 = *(u64 *)buf;
 | |
| 
 | |
| 	mi->tsr			= FIELD_GET(ICE_MI_TSR, d64);
 | |
| 	mi->ho			= FIELD_GET(ICE_MI_HO, d64);
 | |
| 	mi->pc			= FIELD_GET(ICE_MI_PC, d64);
 | |
| 	mi->pg_rn		= FIELD_GET(ICE_MI_PGRN, d64);
 | |
| 	mi->cd			= FIELD_GET(ICE_MI_CD, d64);
 | |
| 
 | |
| 	mi->gpr_a_ctrl		= FIELD_GET(ICE_MI_GAC, d64);
 | |
| 	mi->gpr_a_data_mdid	= FIELD_GET(ICE_MI_GADM, d64);
 | |
| 	mi->gpr_a_data_start	= FIELD_GET(ICE_MI_GADS, d64);
 | |
| 	mi->gpr_a_data_len	= FIELD_GET(ICE_MI_GADL, d64);
 | |
| 	mi->gpr_a_id		= FIELD_GET(ICE_MI_GAI, d64);
 | |
| 
 | |
| 	mi->gpr_b_ctrl		= FIELD_GET(ICE_MI_GBC, d64);
 | |
| 
 | |
| 	d64 = *((u64 *)&buf[ICE_MI_GBDM_IDD]) >> ICE_MI_GBDM_OFF;
 | |
| 
 | |
| 	mi->gpr_b_data_mdid	= FIELD_GET(ICE_MI_GBDM, d64);
 | |
| 	mi->gpr_b_data_start	= FIELD_GET(ICE_MI_GBDS, d64);
 | |
| 	mi->gpr_b_data_len	= FIELD_GET(ICE_MI_GBDL, d64);
 | |
| 	mi->gpr_b_id		= FIELD_GET(ICE_MI_GBI, d64);
 | |
| 
 | |
| 	mi->gpr_c_ctrl		= FIELD_GET(ICE_MI_GCC, d64);
 | |
| 	mi->gpr_c_data_mdid	= FIELD_GET(ICE_MI_GCDM, d64);
 | |
| 	mi->gpr_c_data_start	= FIELD_GET(ICE_MI_GCDS, d64);
 | |
| 	mi->gpr_c_data_len	= FIELD_GET(ICE_MI_GCDL, d64);
 | |
| 	mi->gpr_c_id		= FIELD_GET(ICE_MI_GCI, d64);
 | |
| 
 | |
| 	mi->gpr_d_ctrl		= FIELD_GET(ICE_MI_GDC, d64);
 | |
| 	mi->gpr_d_data_mdid	= FIELD_GET(ICE_MI_GDDM, d64);
 | |
| 	mi->gpr_d_data_start	= FIELD_GET(ICE_MI_GDDS, d64);
 | |
| 	mi->gpr_d_data_len	= FIELD_GET(ICE_MI_GDDL, d64);
 | |
| 	mi->gpr_d_id		= FIELD_GET(ICE_MI_GDI, d64);
 | |
| 
 | |
| 	d64 = *((u64 *)&buf[ICE_MI_FLAG_IDD]) >> ICE_MI_FLAG_OFF;
 | |
| 
 | |
| 	mi->flags		= FIELD_GET(ICE_MI_FLAG, d64);
 | |
| 
 | |
| 	if (hw->debug_mask & ICE_DBG_PARSER)
 | |
| 		ice_metainit_dump(hw, mi);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_metainit_table_get - create a metainit table
 | |
|  * @hw: pointer to the hardware structure
 | |
|  *
 | |
|  * Return: a pointer to the allocated Metadata initialization table.
 | |
|  */
 | |
| static struct ice_metainit_item *ice_metainit_table_get(struct ice_hw *hw)
 | |
| {
 | |
| 	return ice_parser_create_table(hw, ICE_SID_RXPARSER_METADATA_INIT,
 | |
| 				       sizeof(struct ice_metainit_item),
 | |
| 				       ICE_METAINIT_TABLE_SIZE,
 | |
| 				       ice_metainit_parse_item, false);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_bst_tcam_search - find a TCAM item with specific type
 | |
|  * @tcam_table: the TCAM table
 | |
|  * @lbl_table: the lbl table to search
 | |
|  * @type: the type we need to match against
 | |
|  * @start: start searching from this index
 | |
|  *
 | |
|  * Return: a pointer to the matching BOOST TCAM item or NULL.
 | |
|  */
 | |
| struct ice_bst_tcam_item *
 | |
| ice_bst_tcam_search(struct ice_bst_tcam_item *tcam_table,
 | |
| 		    struct ice_lbl_item *lbl_table,
 | |
| 		    enum ice_lbl_type type, u16 *start)
 | |
| {
 | |
| 	u16 i = *start;
 | |
| 
 | |
| 	for (; i < ICE_BST_TCAM_TABLE_SIZE; i++) {
 | |
| 		if (lbl_table[i].type == type) {
 | |
| 			*start = i;
 | |
| 			return &tcam_table[lbl_table[i].idx];
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return NULL;
 | |
| }
 | |
| 
 | |
| /*** ICE_SID_RXPARSER_CAM, ICE_SID_RXPARSER_PG_SPILL,
 | |
|  *    ICE_SID_RXPARSER_NOMATCH_CAM and ICE_SID_RXPARSER_NOMATCH_CAM
 | |
|  *    sections ***/
 | |
| static void ice_pg_cam_key_dump(struct ice_hw *hw, struct ice_pg_cam_key *key)
 | |
| {
 | |
| 	struct device *dev = ice_hw_to_dev(hw);
 | |
| 
 | |
| 	dev_info(dev, "key:\n");
 | |
| 	dev_info(dev, "\tvalid = %d\n", key->valid);
 | |
| 	dev_info(dev, "\tnode_id = %d\n", key->node_id);
 | |
| 	dev_info(dev, "\tflag0 = %d\n", key->flag0);
 | |
| 	dev_info(dev, "\tflag1 = %d\n", key->flag1);
 | |
| 	dev_info(dev, "\tflag2 = %d\n", key->flag2);
 | |
| 	dev_info(dev, "\tflag3 = %d\n", key->flag3);
 | |
| 	dev_info(dev, "\tboost_idx = %d\n", key->boost_idx);
 | |
| 	dev_info(dev, "\talu_reg = 0x%04x\n", key->alu_reg);
 | |
| 	dev_info(dev, "\tnext_proto = 0x%08x\n", key->next_proto);
 | |
| }
 | |
| 
 | |
| static void ice_pg_nm_cam_key_dump(struct ice_hw *hw,
 | |
| 				   struct ice_pg_nm_cam_key *key)
 | |
| {
 | |
| 	struct device *dev = ice_hw_to_dev(hw);
 | |
| 
 | |
| 	dev_info(dev, "key:\n");
 | |
| 	dev_info(dev, "\tvalid = %d\n", key->valid);
 | |
| 	dev_info(dev, "\tnode_id = %d\n", key->node_id);
 | |
| 	dev_info(dev, "\tflag0 = %d\n", key->flag0);
 | |
| 	dev_info(dev, "\tflag1 = %d\n", key->flag1);
 | |
| 	dev_info(dev, "\tflag2 = %d\n", key->flag2);
 | |
| 	dev_info(dev, "\tflag3 = %d\n", key->flag3);
 | |
| 	dev_info(dev, "\tboost_idx = %d\n", key->boost_idx);
 | |
| 	dev_info(dev, "\talu_reg = 0x%04x\n", key->alu_reg);
 | |
| }
 | |
| 
 | |
| static void ice_pg_cam_action_dump(struct ice_hw *hw,
 | |
| 				   struct ice_pg_cam_action *action)
 | |
| {
 | |
| 	struct device *dev = ice_hw_to_dev(hw);
 | |
| 
 | |
| 	dev_info(dev, "action:\n");
 | |
| 	dev_info(dev, "\tnext_node = %d\n", action->next_node);
 | |
| 	dev_info(dev, "\tnext_pc = %d\n", action->next_pc);
 | |
| 	dev_info(dev, "\tis_pg = %d\n", action->is_pg);
 | |
| 	dev_info(dev, "\tproto_id = %d\n", action->proto_id);
 | |
| 	dev_info(dev, "\tis_mg = %d\n", action->is_mg);
 | |
| 	dev_info(dev, "\tmarker_id = %d\n", action->marker_id);
 | |
| 	dev_info(dev, "\tis_last_round = %d\n", action->is_last_round);
 | |
| 	dev_info(dev, "\tho_polarity = %d\n", action->ho_polarity);
 | |
| 	dev_info(dev, "\tho_inc = %d\n", action->ho_inc);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_pg_cam_dump - dump an parse graph cam info
 | |
|  * @hw: pointer to the hardware structure
 | |
|  * @item: parse graph cam to dump
 | |
|  */
 | |
| static void ice_pg_cam_dump(struct ice_hw *hw, struct ice_pg_cam_item *item)
 | |
| {
 | |
| 	dev_info(ice_hw_to_dev(hw), "index = %d\n", item->idx);
 | |
| 	ice_pg_cam_key_dump(hw, &item->key);
 | |
| 	ice_pg_cam_action_dump(hw, &item->action);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_pg_nm_cam_dump - dump an parse graph no match cam info
 | |
|  * @hw: pointer to the hardware structure
 | |
|  * @item: parse graph no match cam to dump
 | |
|  */
 | |
| static void ice_pg_nm_cam_dump(struct ice_hw *hw,
 | |
| 			       struct ice_pg_nm_cam_item *item)
 | |
| {
 | |
| 	dev_info(ice_hw_to_dev(hw), "index = %d\n", item->idx);
 | |
| 	ice_pg_nm_cam_key_dump(hw, &item->key);
 | |
| 	ice_pg_cam_action_dump(hw, &item->action);
 | |
| }
 | |
| 
 | |
| #define ICE_PGCA_NN	GENMASK_ULL(10, 0)
 | |
| #define ICE_PGCA_NPC	GENMASK_ULL(18, 11)
 | |
| #define ICE_PGCA_IPG	BIT_ULL(19)
 | |
| #define ICE_PGCA_PID	GENMASK_ULL(30, 23)
 | |
| #define ICE_PGCA_IMG	BIT_ULL(31)
 | |
| #define ICE_PGCA_MID	GENMASK_ULL(39, 32)
 | |
| #define ICE_PGCA_ILR	BIT_ULL(40)
 | |
| #define ICE_PGCA_HOP	BIT_ULL(41)
 | |
| #define ICE_PGCA_HOI	GENMASK_ULL(50, 42)
 | |
| 
 | |
| /**
 | |
|  * ice_pg_cam_action_init - parse 55 bits of Parse Graph CAM Action
 | |
|  * @action: pointer to the Parse Graph CAM Action structure
 | |
|  * @data: Parse Graph CAM Action data to be parsed
 | |
|  */
 | |
| static void ice_pg_cam_action_init(struct ice_pg_cam_action *action, u64 data)
 | |
| {
 | |
| 	action->next_node	= FIELD_GET(ICE_PGCA_NN, data);
 | |
| 	action->next_pc		= FIELD_GET(ICE_PGCA_NPC, data);
 | |
| 	action->is_pg		= FIELD_GET(ICE_PGCA_IPG, data);
 | |
| 	action->proto_id	= FIELD_GET(ICE_PGCA_PID, data);
 | |
| 	action->is_mg		= FIELD_GET(ICE_PGCA_IMG, data);
 | |
| 	action->marker_id	= FIELD_GET(ICE_PGCA_MID, data);
 | |
| 	action->is_last_round	= FIELD_GET(ICE_PGCA_ILR, data);
 | |
| 	action->ho_polarity	= FIELD_GET(ICE_PGCA_HOP, data);
 | |
| 	action->ho_inc		= FIELD_GET(ICE_PGCA_HOI, data);
 | |
| }
 | |
| 
 | |
| #define ICE_PGNCK_VLD		BIT_ULL(0)
 | |
| #define ICE_PGNCK_NID		GENMASK_ULL(11, 1)
 | |
| #define ICE_PGNCK_F0		BIT_ULL(12)
 | |
| #define ICE_PGNCK_F1		BIT_ULL(13)
 | |
| #define ICE_PGNCK_F2		BIT_ULL(14)
 | |
| #define ICE_PGNCK_F3		BIT_ULL(15)
 | |
| #define ICE_PGNCK_BH		BIT_ULL(16)
 | |
| #define ICE_PGNCK_BI		GENMASK_ULL(24, 17)
 | |
| #define ICE_PGNCK_AR		GENMASK_ULL(40, 25)
 | |
| 
 | |
| /**
 | |
|  * ice_pg_nm_cam_key_init - parse 41 bits of Parse Graph NoMatch CAM Key
 | |
|  * @key: pointer to the Parse Graph NoMatch CAM Key structure
 | |
|  * @data: Parse Graph NoMatch CAM Key data to be parsed
 | |
|  */
 | |
| static void ice_pg_nm_cam_key_init(struct ice_pg_nm_cam_key *key, u64 data)
 | |
| {
 | |
| 	key->valid	= FIELD_GET(ICE_PGNCK_VLD, data);
 | |
| 	key->node_id	= FIELD_GET(ICE_PGNCK_NID, data);
 | |
| 	key->flag0	= FIELD_GET(ICE_PGNCK_F0, data);
 | |
| 	key->flag1	= FIELD_GET(ICE_PGNCK_F1, data);
 | |
| 	key->flag2	= FIELD_GET(ICE_PGNCK_F2, data);
 | |
| 	key->flag3	= FIELD_GET(ICE_PGNCK_F3, data);
 | |
| 
 | |
| 	if (FIELD_GET(ICE_PGNCK_BH, data))
 | |
| 		key->boost_idx = FIELD_GET(ICE_PGNCK_BI, data);
 | |
| 	else
 | |
| 		key->boost_idx = 0;
 | |
| 
 | |
| 	key->alu_reg	= FIELD_GET(ICE_PGNCK_AR, data);
 | |
| }
 | |
| 
 | |
| #define ICE_PGCK_VLD		BIT_ULL(0)
 | |
| #define ICE_PGCK_NID		GENMASK_ULL(11, 1)
 | |
| #define ICE_PGCK_F0		BIT_ULL(12)
 | |
| #define ICE_PGCK_F1		BIT_ULL(13)
 | |
| #define ICE_PGCK_F2		BIT_ULL(14)
 | |
| #define ICE_PGCK_F3		BIT_ULL(15)
 | |
| #define ICE_PGCK_BH		BIT_ULL(16)
 | |
| #define ICE_PGCK_BI		GENMASK_ULL(24, 17)
 | |
| #define ICE_PGCK_AR		GENMASK_ULL(40, 25)
 | |
| #define ICE_PGCK_NPK_S		41	/* offset for the 2nd 64-bits field */
 | |
| #define ICE_PGCK_NPK_IDD	(ICE_PGCK_NPK_S / BITS_PER_BYTE)
 | |
| #define ICE_PGCK_NPK_OFF	(ICE_PGCK_NPK_S % BITS_PER_BYTE)
 | |
| #define ICE_PGCK_NPK		GENMASK_ULL(72 - ICE_PGCK_NPK_S, \
 | |
| 					    41 - ICE_PGCK_NPK_S)
 | |
| 
 | |
| /**
 | |
|  * ice_pg_cam_key_init - parse 73 bits of Parse Graph CAM Key
 | |
|  * @key: pointer to the Parse Graph CAM Key structure
 | |
|  * @data: Parse Graph CAM Key data to be parsed
 | |
|  */
 | |
| static void ice_pg_cam_key_init(struct ice_pg_cam_key *key, u8 *data)
 | |
| {
 | |
| 	u64 d64 = *(u64 *)data;
 | |
| 
 | |
| 	key->valid	= FIELD_GET(ICE_PGCK_VLD, d64);
 | |
| 	key->node_id	= FIELD_GET(ICE_PGCK_NID, d64);
 | |
| 	key->flag0	= FIELD_GET(ICE_PGCK_F0, d64);
 | |
| 	key->flag1	= FIELD_GET(ICE_PGCK_F1, d64);
 | |
| 	key->flag2	= FIELD_GET(ICE_PGCK_F2, d64);
 | |
| 	key->flag3	= FIELD_GET(ICE_PGCK_F3, d64);
 | |
| 
 | |
| 	if (FIELD_GET(ICE_PGCK_BH, d64))
 | |
| 		key->boost_idx = FIELD_GET(ICE_PGCK_BI, d64);
 | |
| 	else
 | |
| 		key->boost_idx = 0;
 | |
| 
 | |
| 	key->alu_reg	= FIELD_GET(ICE_PGCK_AR, d64);
 | |
| 
 | |
| 	d64 = *((u64 *)&data[ICE_PGCK_NPK_IDD]) >> ICE_PGCK_NPK_OFF;
 | |
| 
 | |
| 	key->next_proto	= FIELD_GET(ICE_PGCK_NPK, d64);
 | |
| }
 | |
| 
 | |
| #define ICE_PG_CAM_ACT_S	73
 | |
| #define ICE_PG_CAM_ACT_IDD	(ICE_PG_CAM_ACT_S / BITS_PER_BYTE)
 | |
| #define ICE_PG_CAM_ACT_OFF	(ICE_PG_CAM_ACT_S % BITS_PER_BYTE)
 | |
| 
 | |
| /**
 | |
|  * ice_pg_cam_parse_item - parse 128 bits of Parse Graph CAM Entry
 | |
|  * @hw: pointer to the hardware structure
 | |
|  * @idx: index of Parse Graph CAM Entry
 | |
|  * @item: item of Parse Graph CAM Entry
 | |
|  * @data: Parse Graph CAM Entry data to be parsed
 | |
|  * @size: size of Parse Graph CAM Entry
 | |
|  */
 | |
| static void ice_pg_cam_parse_item(struct ice_hw *hw, u16 idx, void *item,
 | |
| 				  void *data, int __maybe_unused size)
 | |
| {
 | |
| 	struct ice_pg_cam_item *ci = item;
 | |
| 	u8 *buf = data;
 | |
| 	u64 d64;
 | |
| 
 | |
| 	ci->idx = idx;
 | |
| 
 | |
| 	ice_pg_cam_key_init(&ci->key, buf);
 | |
| 
 | |
| 	d64 = *((u64 *)&buf[ICE_PG_CAM_ACT_IDD]) >> ICE_PG_CAM_ACT_OFF;
 | |
| 	ice_pg_cam_action_init(&ci->action, d64);
 | |
| 
 | |
| 	if (hw->debug_mask & ICE_DBG_PARSER)
 | |
| 		ice_pg_cam_dump(hw, ci);
 | |
| }
 | |
| 
 | |
| #define ICE_PG_SP_CAM_KEY_S	56
 | |
| #define ICE_PG_SP_CAM_KEY_IDD	(ICE_PG_SP_CAM_KEY_S / BITS_PER_BYTE)
 | |
| 
 | |
| /**
 | |
|  * ice_pg_sp_cam_parse_item - parse 136 bits of Parse Graph Spill CAM Entry
 | |
|  * @hw: pointer to the hardware structure
 | |
|  * @idx: index of Parse Graph Spill CAM Entry
 | |
|  * @item: item of Parse Graph Spill CAM Entry
 | |
|  * @data: Parse Graph Spill CAM Entry data to be parsed
 | |
|  * @size: size of Parse Graph Spill CAM Entry
 | |
|  */
 | |
| static void ice_pg_sp_cam_parse_item(struct ice_hw *hw, u16 idx, void *item,
 | |
| 				     void *data, int __maybe_unused size)
 | |
| {
 | |
| 	struct ice_pg_cam_item *ci = item;
 | |
| 	u8 *buf = data;
 | |
| 	u64 d64;
 | |
| 
 | |
| 	ci->idx = idx;
 | |
| 
 | |
| 	d64 = *(u64 *)buf;
 | |
| 	ice_pg_cam_action_init(&ci->action, d64);
 | |
| 
 | |
| 	ice_pg_cam_key_init(&ci->key, &buf[ICE_PG_SP_CAM_KEY_IDD]);
 | |
| 
 | |
| 	if (hw->debug_mask & ICE_DBG_PARSER)
 | |
| 		ice_pg_cam_dump(hw, ci);
 | |
| }
 | |
| 
 | |
| #define ICE_PG_NM_CAM_ACT_S	41
 | |
| #define ICE_PG_NM_CAM_ACT_IDD	(ICE_PG_NM_CAM_ACT_S / BITS_PER_BYTE)
 | |
| #define ICE_PG_NM_CAM_ACT_OFF   (ICE_PG_NM_CAM_ACT_S % BITS_PER_BYTE)
 | |
| 
 | |
| /**
 | |
|  * ice_pg_nm_cam_parse_item - parse 96 bits of Parse Graph NoMatch CAM Entry
 | |
|  * @hw: pointer to the hardware structure
 | |
|  * @idx: index of Parse Graph NoMatch CAM Entry
 | |
|  * @item: item of Parse Graph NoMatch CAM Entry
 | |
|  * @data: Parse Graph NoMatch CAM Entry data to be parsed
 | |
|  * @size: size of Parse Graph NoMatch CAM Entry
 | |
|  */
 | |
| static void ice_pg_nm_cam_parse_item(struct ice_hw *hw, u16 idx, void *item,
 | |
| 				     void *data, int __maybe_unused size)
 | |
| {
 | |
| 	struct ice_pg_nm_cam_item *ci = item;
 | |
| 	u8 *buf = data;
 | |
| 	u64 d64;
 | |
| 
 | |
| 	ci->idx = idx;
 | |
| 
 | |
| 	d64 = *(u64 *)buf;
 | |
| 	ice_pg_nm_cam_key_init(&ci->key, d64);
 | |
| 
 | |
| 	d64 = *((u64 *)&buf[ICE_PG_NM_CAM_ACT_IDD]) >> ICE_PG_NM_CAM_ACT_OFF;
 | |
| 	ice_pg_cam_action_init(&ci->action, d64);
 | |
| 
 | |
| 	if (hw->debug_mask & ICE_DBG_PARSER)
 | |
| 		ice_pg_nm_cam_dump(hw, ci);
 | |
| }
 | |
| 
 | |
| #define ICE_PG_NM_SP_CAM_ACT_S		56
 | |
| #define ICE_PG_NM_SP_CAM_ACT_IDD	(ICE_PG_NM_SP_CAM_ACT_S / BITS_PER_BYTE)
 | |
| #define ICE_PG_NM_SP_CAM_ACT_OFF	(ICE_PG_NM_SP_CAM_ACT_S % BITS_PER_BYTE)
 | |
| 
 | |
| /**
 | |
|  * ice_pg_nm_sp_cam_parse_item - parse 104 bits of Parse Graph NoMatch Spill
 | |
|  *  CAM Entry
 | |
|  * @hw: pointer to the hardware structure
 | |
|  * @idx: index of Parse Graph NoMatch Spill CAM Entry
 | |
|  * @item: item of Parse Graph NoMatch Spill CAM Entry
 | |
|  * @data: Parse Graph NoMatch Spill CAM Entry data to be parsed
 | |
|  * @size: size of Parse Graph NoMatch Spill CAM Entry
 | |
|  */
 | |
| static void ice_pg_nm_sp_cam_parse_item(struct ice_hw *hw, u16 idx,
 | |
| 					void *item, void *data,
 | |
| 					int __maybe_unused size)
 | |
| {
 | |
| 	struct ice_pg_nm_cam_item *ci = item;
 | |
| 	u8 *buf = data;
 | |
| 	u64 d64;
 | |
| 
 | |
| 	ci->idx = idx;
 | |
| 
 | |
| 	d64 = *(u64 *)buf;
 | |
| 	ice_pg_cam_action_init(&ci->action, d64);
 | |
| 
 | |
| 	d64 = *((u64 *)&buf[ICE_PG_NM_SP_CAM_ACT_IDD]) >>
 | |
| 		ICE_PG_NM_SP_CAM_ACT_OFF;
 | |
| 	ice_pg_nm_cam_key_init(&ci->key, d64);
 | |
| 
 | |
| 	if (hw->debug_mask & ICE_DBG_PARSER)
 | |
| 		ice_pg_nm_cam_dump(hw, ci);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_pg_cam_table_get - create a parse graph cam table
 | |
|  * @hw: pointer to the hardware structure
 | |
|  *
 | |
|  * Return: a pointer to the allocated Parse Graph CAM table.
 | |
|  */
 | |
| static struct ice_pg_cam_item *ice_pg_cam_table_get(struct ice_hw *hw)
 | |
| {
 | |
| 	return ice_parser_create_table(hw, ICE_SID_RXPARSER_CAM,
 | |
| 				       sizeof(struct ice_pg_cam_item),
 | |
| 				       ICE_PG_CAM_TABLE_SIZE,
 | |
| 				       ice_pg_cam_parse_item, false);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_pg_sp_cam_table_get - create a parse graph spill cam table
 | |
|  * @hw: pointer to the hardware structure
 | |
|  *
 | |
|  * Return: a pointer to the allocated Parse Graph Spill CAM table.
 | |
|  */
 | |
| static struct ice_pg_cam_item *ice_pg_sp_cam_table_get(struct ice_hw *hw)
 | |
| {
 | |
| 	return ice_parser_create_table(hw, ICE_SID_RXPARSER_PG_SPILL,
 | |
| 				       sizeof(struct ice_pg_cam_item),
 | |
| 				       ICE_PG_SP_CAM_TABLE_SIZE,
 | |
| 				       ice_pg_sp_cam_parse_item, false);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_pg_nm_cam_table_get - create a parse graph no match cam table
 | |
|  * @hw: pointer to the hardware structure
 | |
|  *
 | |
|  * Return: a pointer to the allocated Parse Graph No Match CAM table.
 | |
|  */
 | |
| static struct ice_pg_nm_cam_item *ice_pg_nm_cam_table_get(struct ice_hw *hw)
 | |
| {
 | |
| 	return ice_parser_create_table(hw, ICE_SID_RXPARSER_NOMATCH_CAM,
 | |
| 				       sizeof(struct ice_pg_nm_cam_item),
 | |
| 				       ICE_PG_NM_CAM_TABLE_SIZE,
 | |
| 				       ice_pg_nm_cam_parse_item, false);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_pg_nm_sp_cam_table_get - create a parse graph no match spill cam table
 | |
|  * @hw: pointer to the hardware structure
 | |
|  *
 | |
|  * Return: a pointer to the allocated Parse Graph No Match Spill CAM table.
 | |
|  */
 | |
| static struct ice_pg_nm_cam_item *ice_pg_nm_sp_cam_table_get(struct ice_hw *hw)
 | |
| {
 | |
| 	return ice_parser_create_table(hw, ICE_SID_RXPARSER_NOMATCH_SPILL,
 | |
| 				       sizeof(struct ice_pg_nm_cam_item),
 | |
| 				       ICE_PG_NM_SP_CAM_TABLE_SIZE,
 | |
| 				       ice_pg_nm_sp_cam_parse_item, false);
 | |
| }
 | |
| 
 | |
| static bool __ice_pg_cam_match(struct ice_pg_cam_item *item,
 | |
| 			       struct ice_pg_cam_key *key)
 | |
| {
 | |
| 	return (item->key.valid &&
 | |
| 		!memcmp(&item->key.val, &key->val, sizeof(key->val)));
 | |
| }
 | |
| 
 | |
| static bool __ice_pg_nm_cam_match(struct ice_pg_nm_cam_item *item,
 | |
| 				  struct ice_pg_cam_key *key)
 | |
| {
 | |
| 	return (item->key.valid &&
 | |
| 		!memcmp(&item->key.val, &key->val, sizeof(item->key.val)));
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_pg_cam_match - search parse graph cam table by key
 | |
|  * @table: parse graph cam table to search
 | |
|  * @size: cam table size
 | |
|  * @key: search key
 | |
|  *
 | |
|  * Return: a pointer to the matching PG CAM item or NULL.
 | |
|  */
 | |
| struct ice_pg_cam_item *ice_pg_cam_match(struct ice_pg_cam_item *table,
 | |
| 					 int size, struct ice_pg_cam_key *key)
 | |
| {
 | |
| 	int i;
 | |
| 
 | |
| 	for (i = 0; i < size; i++) {
 | |
| 		struct ice_pg_cam_item *item = &table[i];
 | |
| 
 | |
| 		if (__ice_pg_cam_match(item, key))
 | |
| 			return item;
 | |
| 	}
 | |
| 
 | |
| 	return NULL;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_pg_nm_cam_match - search parse graph no match cam table by key
 | |
|  * @table: parse graph no match cam table to search
 | |
|  * @size: cam table size
 | |
|  * @key: search key
 | |
|  *
 | |
|  * Return: a pointer to the matching PG No Match CAM item or NULL.
 | |
|  */
 | |
| struct ice_pg_nm_cam_item *
 | |
| ice_pg_nm_cam_match(struct ice_pg_nm_cam_item *table, int size,
 | |
| 		    struct ice_pg_cam_key *key)
 | |
| {
 | |
| 	int i;
 | |
| 
 | |
| 	for (i = 0; i < size; i++) {
 | |
| 		struct ice_pg_nm_cam_item *item = &table[i];
 | |
| 
 | |
| 		if (__ice_pg_nm_cam_match(item, key))
 | |
| 			return item;
 | |
| 	}
 | |
| 
 | |
| 	return NULL;
 | |
| }
 | |
| 
 | |
| /*** Ternary match ***/
 | |
| /* Perform a ternary match on a 1-byte pattern (@pat) given @key and @key_inv
 | |
|  * Rules (per bit):
 | |
|  *     Key == 0 and Key_inv == 0 : Never match (Don't care)
 | |
|  *     Key == 0 and Key_inv == 1 : Match on bit == 1
 | |
|  *     Key == 1 and Key_inv == 0 : Match on bit == 0
 | |
|  *     Key == 1 and Key_inv == 1 : Always match (Don't care)
 | |
|  *
 | |
|  * Return: true if all bits match, false otherwise.
 | |
|  */
 | |
| static bool ice_ternary_match_byte(u8 key, u8 key_inv, u8 pat)
 | |
| {
 | |
| 	u8 bit_key, bit_key_inv, bit_pat;
 | |
| 	int i;
 | |
| 
 | |
| 	for (i = 0; i < BITS_PER_BYTE; i++) {
 | |
| 		bit_key = key & BIT(i);
 | |
| 		bit_key_inv = key_inv & BIT(i);
 | |
| 		bit_pat = pat & BIT(i);
 | |
| 
 | |
| 		if (bit_key != 0 && bit_key_inv != 0)
 | |
| 			continue;
 | |
| 
 | |
| 		if ((bit_key == 0 && bit_key_inv == 0) || bit_key == bit_pat)
 | |
| 			return false;
 | |
| 	}
 | |
| 
 | |
| 	return true;
 | |
| }
 | |
| 
 | |
| static bool ice_ternary_match(const u8 *key, const u8 *key_inv,
 | |
| 			      const u8 *pat, int len)
 | |
| {
 | |
| 	int i;
 | |
| 
 | |
| 	for (i = 0; i < len; i++)
 | |
| 		if (!ice_ternary_match_byte(key[i], key_inv[i], pat[i]))
 | |
| 			return false;
 | |
| 
 | |
| 	return true;
 | |
| }
 | |
| 
 | |
| /*** ICE_SID_RXPARSER_BOOST_TCAM and ICE_SID_LBL_RXPARSER_TMEM sections ***/
 | |
| static void ice_bst_np_kb_dump(struct ice_hw *hw, struct ice_np_keybuilder *kb)
 | |
| {
 | |
| 	struct device *dev = ice_hw_to_dev(hw);
 | |
| 
 | |
| 	dev_info(dev, "next proto key builder:\n");
 | |
| 	dev_info(dev, "\topc = %d\n", kb->opc);
 | |
| 	dev_info(dev, "\tstart_reg0 = %d\n", kb->start_reg0);
 | |
| 	dev_info(dev, "\tlen_reg1 = %d\n", kb->len_reg1);
 | |
| }
 | |
| 
 | |
| static void ice_bst_pg_kb_dump(struct ice_hw *hw, struct ice_pg_keybuilder *kb)
 | |
| {
 | |
| 	struct device *dev = ice_hw_to_dev(hw);
 | |
| 
 | |
| 	dev_info(dev, "parse graph key builder:\n");
 | |
| 	dev_info(dev, "\tflag0_ena = %d\n", kb->flag0_ena);
 | |
| 	dev_info(dev, "\tflag1_ena = %d\n", kb->flag1_ena);
 | |
| 	dev_info(dev, "\tflag2_ena = %d\n", kb->flag2_ena);
 | |
| 	dev_info(dev, "\tflag3_ena = %d\n", kb->flag3_ena);
 | |
| 	dev_info(dev, "\tflag0_idx = %d\n", kb->flag0_idx);
 | |
| 	dev_info(dev, "\tflag1_idx = %d\n", kb->flag1_idx);
 | |
| 	dev_info(dev, "\tflag2_idx = %d\n", kb->flag2_idx);
 | |
| 	dev_info(dev, "\tflag3_idx = %d\n", kb->flag3_idx);
 | |
| 	dev_info(dev, "\talu_reg_idx = %d\n", kb->alu_reg_idx);
 | |
| }
 | |
| 
 | |
| static void ice_bst_alu_dump(struct ice_hw *hw, struct ice_alu *alu, int idx)
 | |
| {
 | |
| 	struct device *dev = ice_hw_to_dev(hw);
 | |
| 
 | |
| 	dev_info(dev, "alu%d:\n", idx);
 | |
| 	dev_info(dev, "\topc = %d\n", alu->opc);
 | |
| 	dev_info(dev, "\tsrc_start = %d\n", alu->src_start);
 | |
| 	dev_info(dev, "\tsrc_len = %d\n", alu->src_len);
 | |
| 	dev_info(dev, "\tshift_xlate_sel = %d\n", alu->shift_xlate_sel);
 | |
| 	dev_info(dev, "\tshift_xlate_key = %d\n", alu->shift_xlate_key);
 | |
| 	dev_info(dev, "\tsrc_reg_id = %d\n", alu->src_reg_id);
 | |
| 	dev_info(dev, "\tdst_reg_id = %d\n", alu->dst_reg_id);
 | |
| 	dev_info(dev, "\tinc0 = %d\n", alu->inc0);
 | |
| 	dev_info(dev, "\tinc1 = %d\n", alu->inc1);
 | |
| 	dev_info(dev, "\tproto_offset_opc = %d\n", alu->proto_offset_opc);
 | |
| 	dev_info(dev, "\tproto_offset = %d\n", alu->proto_offset);
 | |
| 	dev_info(dev, "\tbranch_addr = %d\n", alu->branch_addr);
 | |
| 	dev_info(dev, "\timm = %d\n", alu->imm);
 | |
| 	dev_info(dev, "\tdst_start = %d\n", alu->dst_start);
 | |
| 	dev_info(dev, "\tdst_len = %d\n", alu->dst_len);
 | |
| 	dev_info(dev, "\tflags_extr_imm = %d\n", alu->flags_extr_imm);
 | |
| 	dev_info(dev, "\tflags_start_imm= %d\n", alu->flags_start_imm);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_bst_tcam_dump - dump a boost tcam info
 | |
|  * @hw: pointer to the hardware structure
 | |
|  * @item: boost tcam to dump
 | |
|  */
 | |
| static void ice_bst_tcam_dump(struct ice_hw *hw, struct ice_bst_tcam_item *item)
 | |
| {
 | |
| 	struct device *dev = ice_hw_to_dev(hw);
 | |
| 	int i;
 | |
| 
 | |
| 	dev_info(dev, "addr = %d\n", item->addr);
 | |
| 
 | |
| 	dev_info(dev, "key    : ");
 | |
| 	for (i = 0; i < ICE_BST_TCAM_KEY_SIZE; i++)
 | |
| 		dev_info(dev, "%02x ", item->key[i]);
 | |
| 
 | |
| 	dev_info(dev, "\n");
 | |
| 
 | |
| 	dev_info(dev, "key_inv: ");
 | |
| 	for (i = 0; i < ICE_BST_TCAM_KEY_SIZE; i++)
 | |
| 		dev_info(dev, "%02x ", item->key_inv[i]);
 | |
| 
 | |
| 	dev_info(dev, "\n");
 | |
| 
 | |
| 	dev_info(dev, "hit_idx_grp = %d\n", item->hit_idx_grp);
 | |
| 	dev_info(dev, "pg_prio = %d\n", item->pg_prio);
 | |
| 
 | |
| 	ice_bst_np_kb_dump(hw, &item->np_kb);
 | |
| 	ice_bst_pg_kb_dump(hw, &item->pg_kb);
 | |
| 
 | |
| 	ice_bst_alu_dump(hw, &item->alu0, ICE_ALU0_IDX);
 | |
| 	ice_bst_alu_dump(hw, &item->alu1, ICE_ALU1_IDX);
 | |
| 	ice_bst_alu_dump(hw, &item->alu2, ICE_ALU2_IDX);
 | |
| }
 | |
| 
 | |
| static void ice_lbl_dump(struct ice_hw *hw, struct ice_lbl_item *item)
 | |
| {
 | |
| 	struct device *dev = ice_hw_to_dev(hw);
 | |
| 
 | |
| 	dev_info(dev, "index = %u\n", item->idx);
 | |
| 	dev_info(dev, "type = %u\n", item->type);
 | |
| 	dev_info(dev, "label = %s\n", item->label);
 | |
| }
 | |
| 
 | |
| #define ICE_BST_ALU_OPC		GENMASK_ULL(5, 0)
 | |
| #define ICE_BST_ALU_SS		GENMASK_ULL(13, 6)
 | |
| #define ICE_BST_ALU_SL		GENMASK_ULL(18, 14)
 | |
| #define ICE_BST_ALU_SXS		BIT_ULL(19)
 | |
| #define ICE_BST_ALU_SXK		GENMASK_ULL(23, 20)
 | |
| #define ICE_BST_ALU_SRID	GENMASK_ULL(30, 24)
 | |
| #define ICE_BST_ALU_DRID	GENMASK_ULL(37, 31)
 | |
| #define ICE_BST_ALU_INC0	BIT_ULL(38)
 | |
| #define ICE_BST_ALU_INC1	BIT_ULL(39)
 | |
| #define ICE_BST_ALU_POO		GENMASK_ULL(41, 40)
 | |
| #define ICE_BST_ALU_PO		GENMASK_ULL(49, 42)
 | |
| #define ICE_BST_ALU_BA_S	50	/* offset for the 2nd 64-bits field */
 | |
| #define ICE_BST_ALU_BA		GENMASK_ULL(57 - ICE_BST_ALU_BA_S, \
 | |
| 					    50 - ICE_BST_ALU_BA_S)
 | |
| #define ICE_BST_ALU_IMM		GENMASK_ULL(73 - ICE_BST_ALU_BA_S, \
 | |
| 					    58 - ICE_BST_ALU_BA_S)
 | |
| #define ICE_BST_ALU_DFE		BIT_ULL(74 - ICE_BST_ALU_BA_S)
 | |
| #define ICE_BST_ALU_DS		GENMASK_ULL(80 - ICE_BST_ALU_BA_S, \
 | |
| 					    75 - ICE_BST_ALU_BA_S)
 | |
| #define ICE_BST_ALU_DL		GENMASK_ULL(86 - ICE_BST_ALU_BA_S, \
 | |
| 					    81 - ICE_BST_ALU_BA_S)
 | |
| #define ICE_BST_ALU_FEI		BIT_ULL(87 - ICE_BST_ALU_BA_S)
 | |
| #define ICE_BST_ALU_FSI		GENMASK_ULL(95 - ICE_BST_ALU_BA_S, \
 | |
| 					    88 - ICE_BST_ALU_BA_S)
 | |
| 
 | |
| /**
 | |
|  * ice_bst_alu_init - parse 96 bits of ALU entry
 | |
|  * @alu: pointer to the ALU entry structure
 | |
|  * @data: ALU entry data to be parsed
 | |
|  * @off: offset of the ALU entry data
 | |
|  */
 | |
| static void ice_bst_alu_init(struct ice_alu *alu, u8 *data, u8 off)
 | |
| {
 | |
| 	u64 d64;
 | |
| 	u8 idd;
 | |
| 
 | |
| 	d64 = *((u64 *)data) >> off;
 | |
| 
 | |
| 	alu->opc		= FIELD_GET(ICE_BST_ALU_OPC, d64);
 | |
| 	alu->src_start		= FIELD_GET(ICE_BST_ALU_SS, d64);
 | |
| 	alu->src_len		= FIELD_GET(ICE_BST_ALU_SL, d64);
 | |
| 	alu->shift_xlate_sel	= FIELD_GET(ICE_BST_ALU_SXS, d64);
 | |
| 	alu->shift_xlate_key	= FIELD_GET(ICE_BST_ALU_SXK, d64);
 | |
| 	alu->src_reg_id		= FIELD_GET(ICE_BST_ALU_SRID, d64);
 | |
| 	alu->dst_reg_id		= FIELD_GET(ICE_BST_ALU_DRID, d64);
 | |
| 	alu->inc0		= FIELD_GET(ICE_BST_ALU_INC0, d64);
 | |
| 	alu->inc1		= FIELD_GET(ICE_BST_ALU_INC1, d64);
 | |
| 	alu->proto_offset_opc	= FIELD_GET(ICE_BST_ALU_POO, d64);
 | |
| 	alu->proto_offset	= FIELD_GET(ICE_BST_ALU_PO, d64);
 | |
| 
 | |
| 	idd = (ICE_BST_ALU_BA_S + off) / BITS_PER_BYTE;
 | |
| 	off = (ICE_BST_ALU_BA_S + off) % BITS_PER_BYTE;
 | |
| 	d64 = *((u64 *)(&data[idd])) >> off;
 | |
| 
 | |
| 	alu->branch_addr	= FIELD_GET(ICE_BST_ALU_BA, d64);
 | |
| 	alu->imm		= FIELD_GET(ICE_BST_ALU_IMM, d64);
 | |
| 	alu->dedicate_flags_ena	= FIELD_GET(ICE_BST_ALU_DFE, d64);
 | |
| 	alu->dst_start		= FIELD_GET(ICE_BST_ALU_DS, d64);
 | |
| 	alu->dst_len		= FIELD_GET(ICE_BST_ALU_DL, d64);
 | |
| 	alu->flags_extr_imm	= FIELD_GET(ICE_BST_ALU_FEI, d64);
 | |
| 	alu->flags_start_imm	= FIELD_GET(ICE_BST_ALU_FSI, d64);
 | |
| }
 | |
| 
 | |
| #define ICE_BST_PGKB_F0_ENA		BIT_ULL(0)
 | |
| #define ICE_BST_PGKB_F0_IDX		GENMASK_ULL(6, 1)
 | |
| #define ICE_BST_PGKB_F1_ENA		BIT_ULL(7)
 | |
| #define ICE_BST_PGKB_F1_IDX		GENMASK_ULL(13, 8)
 | |
| #define ICE_BST_PGKB_F2_ENA		BIT_ULL(14)
 | |
| #define ICE_BST_PGKB_F2_IDX		GENMASK_ULL(20, 15)
 | |
| #define ICE_BST_PGKB_F3_ENA		BIT_ULL(21)
 | |
| #define ICE_BST_PGKB_F3_IDX		GENMASK_ULL(27, 22)
 | |
| #define ICE_BST_PGKB_AR_IDX		GENMASK_ULL(34, 28)
 | |
| 
 | |
| /**
 | |
|  * ice_bst_pgkb_init - parse 35 bits of Parse Graph Key Build
 | |
|  * @kb: pointer to the Parse Graph Key Build structure
 | |
|  * @data: Parse Graph Key Build data to be parsed
 | |
|  */
 | |
| static void ice_bst_pgkb_init(struct ice_pg_keybuilder *kb, u64 data)
 | |
| {
 | |
| 	kb->flag0_ena	= FIELD_GET(ICE_BST_PGKB_F0_ENA, data);
 | |
| 	kb->flag0_idx	= FIELD_GET(ICE_BST_PGKB_F0_IDX, data);
 | |
| 	kb->flag1_ena	= FIELD_GET(ICE_BST_PGKB_F1_ENA, data);
 | |
| 	kb->flag1_idx	= FIELD_GET(ICE_BST_PGKB_F1_IDX, data);
 | |
| 	kb->flag2_ena	= FIELD_GET(ICE_BST_PGKB_F2_ENA, data);
 | |
| 	kb->flag2_idx	= FIELD_GET(ICE_BST_PGKB_F2_IDX, data);
 | |
| 	kb->flag3_ena	= FIELD_GET(ICE_BST_PGKB_F3_ENA, data);
 | |
| 	kb->flag3_idx	= FIELD_GET(ICE_BST_PGKB_F3_IDX, data);
 | |
| 	kb->alu_reg_idx	= FIELD_GET(ICE_BST_PGKB_AR_IDX, data);
 | |
| }
 | |
| 
 | |
| #define ICE_BST_NPKB_OPC	GENMASK(1, 0)
 | |
| #define ICE_BST_NPKB_S_R0	GENMASK(9, 2)
 | |
| #define ICE_BST_NPKB_L_R1	GENMASK(17, 10)
 | |
| 
 | |
| /**
 | |
|  * ice_bst_npkb_init - parse 18 bits of Next Protocol Key Build
 | |
|  * @kb: pointer to the Next Protocol Key Build structure
 | |
|  * @data: Next Protocol Key Build data to be parsed
 | |
|  */
 | |
| static void ice_bst_npkb_init(struct ice_np_keybuilder *kb, u32 data)
 | |
| {
 | |
| 	kb->opc		= FIELD_GET(ICE_BST_NPKB_OPC, data);
 | |
| 	kb->start_reg0	= FIELD_GET(ICE_BST_NPKB_S_R0, data);
 | |
| 	kb->len_reg1	= FIELD_GET(ICE_BST_NPKB_L_R1, data);
 | |
| }
 | |
| 
 | |
| #define ICE_BT_KEY_S		32
 | |
| #define ICE_BT_KEY_IDD		(ICE_BT_KEY_S / BITS_PER_BYTE)
 | |
| #define ICE_BT_KIV_S		192
 | |
| #define ICE_BT_KIV_IDD		(ICE_BT_KIV_S / BITS_PER_BYTE)
 | |
| #define ICE_BT_HIG_S		352
 | |
| #define ICE_BT_HIG_IDD		(ICE_BT_HIG_S / BITS_PER_BYTE)
 | |
| #define ICE_BT_PGP_S		360
 | |
| #define ICE_BT_PGP_IDD		(ICE_BT_PGP_S / BITS_PER_BYTE)
 | |
| #define ICE_BT_PGP_M		GENMASK(361 - ICE_BT_PGP_S, 360 - ICE_BT_PGP_S)
 | |
| #define ICE_BT_NPKB_S		362
 | |
| #define ICE_BT_NPKB_IDD		(ICE_BT_NPKB_S / BITS_PER_BYTE)
 | |
| #define ICE_BT_NPKB_OFF		(ICE_BT_NPKB_S % BITS_PER_BYTE)
 | |
| #define ICE_BT_PGKB_S		380
 | |
| #define ICE_BT_PGKB_IDD		(ICE_BT_PGKB_S / BITS_PER_BYTE)
 | |
| #define ICE_BT_PGKB_OFF		(ICE_BT_PGKB_S % BITS_PER_BYTE)
 | |
| #define ICE_BT_ALU0_S		415
 | |
| #define ICE_BT_ALU0_IDD		(ICE_BT_ALU0_S / BITS_PER_BYTE)
 | |
| #define ICE_BT_ALU0_OFF		(ICE_BT_ALU0_S % BITS_PER_BYTE)
 | |
| #define ICE_BT_ALU1_S		511
 | |
| #define ICE_BT_ALU1_IDD		(ICE_BT_ALU1_S / BITS_PER_BYTE)
 | |
| #define ICE_BT_ALU1_OFF		(ICE_BT_ALU1_S % BITS_PER_BYTE)
 | |
| #define ICE_BT_ALU2_S		607
 | |
| #define ICE_BT_ALU2_IDD		(ICE_BT_ALU2_S / BITS_PER_BYTE)
 | |
| #define ICE_BT_ALU2_OFF		(ICE_BT_ALU2_S % BITS_PER_BYTE)
 | |
| 
 | |
| /**
 | |
|  * ice_bst_parse_item - parse 704 bits of Boost TCAM entry
 | |
|  * @hw: pointer to the hardware structure
 | |
|  * @idx: index of Boost TCAM entry
 | |
|  * @item: item of Boost TCAM entry
 | |
|  * @data: Boost TCAM entry data to be parsed
 | |
|  * @size: size of Boost TCAM entry
 | |
|  */
 | |
| static void ice_bst_parse_item(struct ice_hw *hw, u16 idx, void *item,
 | |
| 			       void *data, int __maybe_unused size)
 | |
| {
 | |
| 	struct ice_bst_tcam_item *ti = item;
 | |
| 	u8 *buf = (u8 *)data;
 | |
| 	int i;
 | |
| 
 | |
| 	ti->addr = *(u16 *)buf;
 | |
| 
 | |
| 	for (i = 0; i < ICE_BST_TCAM_KEY_SIZE; i++) {
 | |
| 		ti->key[i] = buf[ICE_BT_KEY_IDD + i];
 | |
| 		ti->key_inv[i] = buf[ICE_BT_KIV_IDD + i];
 | |
| 	}
 | |
| 	ti->hit_idx_grp	= buf[ICE_BT_HIG_IDD];
 | |
| 	ti->pg_prio	= buf[ICE_BT_PGP_IDD] & ICE_BT_PGP_M;
 | |
| 
 | |
| 	ice_bst_npkb_init(&ti->np_kb,
 | |
| 			  *((u32 *)(&buf[ICE_BT_NPKB_IDD])) >>
 | |
| 			   ICE_BT_NPKB_OFF);
 | |
| 	ice_bst_pgkb_init(&ti->pg_kb,
 | |
| 			  *((u64 *)(&buf[ICE_BT_PGKB_IDD])) >>
 | |
| 			   ICE_BT_PGKB_OFF);
 | |
| 
 | |
| 	ice_bst_alu_init(&ti->alu0, &buf[ICE_BT_ALU0_IDD], ICE_BT_ALU0_OFF);
 | |
| 	ice_bst_alu_init(&ti->alu1, &buf[ICE_BT_ALU1_IDD], ICE_BT_ALU1_OFF);
 | |
| 	ice_bst_alu_init(&ti->alu2, &buf[ICE_BT_ALU2_IDD], ICE_BT_ALU2_OFF);
 | |
| 
 | |
| 	if (hw->debug_mask & ICE_DBG_PARSER)
 | |
| 		ice_bst_tcam_dump(hw, ti);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_bst_tcam_table_get - create a boost tcam table
 | |
|  * @hw: pointer to the hardware structure
 | |
|  *
 | |
|  * Return: a pointer to the allocated Boost TCAM table.
 | |
|  */
 | |
| static struct ice_bst_tcam_item *ice_bst_tcam_table_get(struct ice_hw *hw)
 | |
| {
 | |
| 	return ice_parser_create_table(hw, ICE_SID_RXPARSER_BOOST_TCAM,
 | |
| 				       sizeof(struct ice_bst_tcam_item),
 | |
| 				       ICE_BST_TCAM_TABLE_SIZE,
 | |
| 				       ice_bst_parse_item, true);
 | |
| }
 | |
| 
 | |
| static void ice_parse_lbl_item(struct ice_hw *hw, u16 idx, void *item,
 | |
| 			       void *data, int __maybe_unused size)
 | |
| {
 | |
| 	struct ice_lbl_item *lbl_item = item;
 | |
| 	struct ice_lbl_item *lbl_data = data;
 | |
| 
 | |
| 	lbl_item->idx = lbl_data->idx;
 | |
| 	memcpy(lbl_item->label, lbl_data->label, sizeof(lbl_item->label));
 | |
| 
 | |
| 	if (strstarts(lbl_item->label, ICE_LBL_BST_DVM))
 | |
| 		lbl_item->type = ICE_LBL_BST_TYPE_DVM;
 | |
| 	else if (strstarts(lbl_item->label, ICE_LBL_BST_SVM))
 | |
| 		lbl_item->type = ICE_LBL_BST_TYPE_SVM;
 | |
| 	else if (strstarts(lbl_item->label, ICE_LBL_TNL_VXLAN))
 | |
| 		lbl_item->type = ICE_LBL_BST_TYPE_VXLAN;
 | |
| 	else if (strstarts(lbl_item->label, ICE_LBL_TNL_GENEVE))
 | |
| 		lbl_item->type = ICE_LBL_BST_TYPE_GENEVE;
 | |
| 	else if (strstarts(lbl_item->label, ICE_LBL_TNL_UDP_ECPRI))
 | |
| 		lbl_item->type = ICE_LBL_BST_TYPE_UDP_ECPRI;
 | |
| 
 | |
| 	if (hw->debug_mask & ICE_DBG_PARSER)
 | |
| 		ice_lbl_dump(hw, lbl_item);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_bst_lbl_table_get - create a boost label table
 | |
|  * @hw: pointer to the hardware structure
 | |
|  *
 | |
|  * Return: a pointer to the allocated Boost label table.
 | |
|  */
 | |
| static struct ice_lbl_item *ice_bst_lbl_table_get(struct ice_hw *hw)
 | |
| {
 | |
| 	return ice_parser_create_table(hw, ICE_SID_LBL_RXPARSER_TMEM,
 | |
| 				       sizeof(struct ice_lbl_item),
 | |
| 				       ICE_BST_TCAM_TABLE_SIZE,
 | |
| 				       ice_parse_lbl_item, true);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_bst_tcam_match - match a pattern on the boost tcam table
 | |
|  * @tcam_table: boost tcam table to search
 | |
|  * @pat: pattern to match
 | |
|  *
 | |
|  * Return: a pointer to the matching Boost TCAM item or NULL.
 | |
|  */
 | |
| struct ice_bst_tcam_item *
 | |
| ice_bst_tcam_match(struct ice_bst_tcam_item *tcam_table, u8 *pat)
 | |
| {
 | |
| 	int i;
 | |
| 
 | |
| 	for (i = 0; i < ICE_BST_TCAM_TABLE_SIZE; i++) {
 | |
| 		struct ice_bst_tcam_item *item = &tcam_table[i];
 | |
| 
 | |
| 		if (item->hit_idx_grp == 0)
 | |
| 			continue;
 | |
| 		if (ice_ternary_match(item->key, item->key_inv, pat,
 | |
| 				      ICE_BST_TCAM_KEY_SIZE))
 | |
| 			return item;
 | |
| 	}
 | |
| 
 | |
| 	return NULL;
 | |
| }
 | |
| 
 | |
| /*** ICE_SID_RXPARSER_MARKER_PTYPE section ***/
 | |
| /**
 | |
|  * ice_ptype_mk_tcam_dump - dump an ptype marker tcam info
 | |
|  * @hw: pointer to the hardware structure
 | |
|  * @item: ptype marker tcam to dump
 | |
|  */
 | |
| static void ice_ptype_mk_tcam_dump(struct ice_hw *hw,
 | |
| 				   struct ice_ptype_mk_tcam_item *item)
 | |
| {
 | |
| 	struct device *dev = ice_hw_to_dev(hw);
 | |
| 	int i;
 | |
| 
 | |
| 	dev_info(dev, "address = %d\n", item->address);
 | |
| 	dev_info(dev, "ptype = %d\n", item->ptype);
 | |
| 
 | |
| 	dev_info(dev, "key    :");
 | |
| 	for (i = 0; i < ICE_PTYPE_MK_TCAM_KEY_SIZE; i++)
 | |
| 		dev_info(dev, "%02x ", item->key[i]);
 | |
| 
 | |
| 	dev_info(dev, "\n");
 | |
| 
 | |
| 	dev_info(dev, "key_inv:");
 | |
| 	for (i = 0; i < ICE_PTYPE_MK_TCAM_KEY_SIZE; i++)
 | |
| 		dev_info(dev, "%02x ", item->key_inv[i]);
 | |
| 
 | |
| 	dev_info(dev, "\n");
 | |
| }
 | |
| 
 | |
| static void ice_parse_ptype_mk_tcam_item(struct ice_hw *hw, u16 idx,
 | |
| 					 void *item, void *data, int size)
 | |
| {
 | |
| 	memcpy(item, data, size);
 | |
| 
 | |
| 	if (hw->debug_mask & ICE_DBG_PARSER)
 | |
| 		ice_ptype_mk_tcam_dump(hw,
 | |
| 				       (struct ice_ptype_mk_tcam_item *)item);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_ptype_mk_tcam_table_get - create a ptype marker tcam table
 | |
|  * @hw: pointer to the hardware structure
 | |
|  *
 | |
|  * Return: a pointer to the allocated Marker PType TCAM table.
 | |
|  */
 | |
| static
 | |
| struct ice_ptype_mk_tcam_item *ice_ptype_mk_tcam_table_get(struct ice_hw *hw)
 | |
| {
 | |
| 	return ice_parser_create_table(hw, ICE_SID_RXPARSER_MARKER_PTYPE,
 | |
| 				       sizeof(struct ice_ptype_mk_tcam_item),
 | |
| 				       ICE_PTYPE_MK_TCAM_TABLE_SIZE,
 | |
| 				       ice_parse_ptype_mk_tcam_item, true);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_ptype_mk_tcam_match - match a pattern on a ptype marker tcam table
 | |
|  * @table: ptype marker tcam table to search
 | |
|  * @pat: pattern to match
 | |
|  * @len: length of the pattern
 | |
|  *
 | |
|  * Return: a pointer to the matching Marker PType item or NULL.
 | |
|  */
 | |
| struct ice_ptype_mk_tcam_item *
 | |
| ice_ptype_mk_tcam_match(struct ice_ptype_mk_tcam_item *table,
 | |
| 			u8 *pat, int len)
 | |
| {
 | |
| 	int i;
 | |
| 
 | |
| 	for (i = 0; i < ICE_PTYPE_MK_TCAM_TABLE_SIZE; i++) {
 | |
| 		struct ice_ptype_mk_tcam_item *item = &table[i];
 | |
| 
 | |
| 		if (ice_ternary_match(item->key, item->key_inv, pat, len))
 | |
| 			return item;
 | |
| 	}
 | |
| 
 | |
| 	return NULL;
 | |
| }
 | |
| 
 | |
| /*** ICE_SID_RXPARSER_MARKER_GRP section ***/
 | |
| /**
 | |
|  * ice_mk_grp_dump - dump an marker group item info
 | |
|  * @hw: pointer to the hardware structure
 | |
|  * @item: marker group item to dump
 | |
|  */
 | |
| static void ice_mk_grp_dump(struct ice_hw *hw, struct ice_mk_grp_item *item)
 | |
| {
 | |
| 	struct device *dev = ice_hw_to_dev(hw);
 | |
| 	int i;
 | |
| 
 | |
| 	dev_info(dev, "index = %d\n", item->idx);
 | |
| 
 | |
| 	dev_info(dev, "markers: ");
 | |
| 	for (i = 0; i < ICE_MK_COUNT_PER_GRP; i++)
 | |
| 		dev_info(dev, "%d ", item->markers[i]);
 | |
| 
 | |
| 	dev_info(dev, "\n");
 | |
| }
 | |
| 
 | |
| static void ice_mk_grp_parse_item(struct ice_hw *hw, u16 idx, void *item,
 | |
| 				  void *data, int __maybe_unused size)
 | |
| {
 | |
| 	struct ice_mk_grp_item *grp = item;
 | |
| 	u8 *buf = data;
 | |
| 	int i;
 | |
| 
 | |
| 	grp->idx = idx;
 | |
| 
 | |
| 	for (i = 0; i < ICE_MK_COUNT_PER_GRP; i++)
 | |
| 		grp->markers[i] = buf[i];
 | |
| 
 | |
| 	if (hw->debug_mask & ICE_DBG_PARSER)
 | |
| 		ice_mk_grp_dump(hw, grp);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_mk_grp_table_get - create a marker group table
 | |
|  * @hw: pointer to the hardware structure
 | |
|  *
 | |
|  * Return: a pointer to the allocated Marker Group ID table.
 | |
|  */
 | |
| static struct ice_mk_grp_item *ice_mk_grp_table_get(struct ice_hw *hw)
 | |
| {
 | |
| 	return ice_parser_create_table(hw, ICE_SID_RXPARSER_MARKER_GRP,
 | |
| 				       sizeof(struct ice_mk_grp_item),
 | |
| 				       ICE_MK_GRP_TABLE_SIZE,
 | |
| 				       ice_mk_grp_parse_item, false);
 | |
| }
 | |
| 
 | |
| /*** ICE_SID_RXPARSER_PROTO_GRP section ***/
 | |
| static void ice_proto_off_dump(struct ice_hw *hw,
 | |
| 			       struct ice_proto_off *po, int idx)
 | |
| {
 | |
| 	struct device *dev = ice_hw_to_dev(hw);
 | |
| 
 | |
| 	dev_info(dev, "proto %d\n", idx);
 | |
| 	dev_info(dev, "\tpolarity = %d\n", po->polarity);
 | |
| 	dev_info(dev, "\tproto_id = %d\n", po->proto_id);
 | |
| 	dev_info(dev, "\toffset = %d\n", po->offset);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_proto_grp_dump - dump a proto group item info
 | |
|  * @hw: pointer to the hardware structure
 | |
|  * @item: proto group item to dump
 | |
|  */
 | |
| static void ice_proto_grp_dump(struct ice_hw *hw,
 | |
| 			       struct ice_proto_grp_item *item)
 | |
| {
 | |
| 	int i;
 | |
| 
 | |
| 	dev_info(ice_hw_to_dev(hw), "index = %d\n", item->idx);
 | |
| 
 | |
| 	for (i = 0; i < ICE_PROTO_COUNT_PER_GRP; i++)
 | |
| 		ice_proto_off_dump(hw, &item->po[i], i);
 | |
| }
 | |
| 
 | |
| #define ICE_PO_POL	BIT(0)
 | |
| #define ICE_PO_PID	GENMASK(8, 1)
 | |
| #define ICE_PO_OFF	GENMASK(21, 12)
 | |
| 
 | |
| /**
 | |
|  * ice_proto_off_parse - parse 22 bits of Protocol entry
 | |
|  * @po: pointer to the Protocol entry structure
 | |
|  * @data: Protocol entry data to be parsed
 | |
|  */
 | |
| static void ice_proto_off_parse(struct ice_proto_off *po, u32 data)
 | |
| {
 | |
| 	po->polarity = FIELD_GET(ICE_PO_POL, data);
 | |
| 	po->proto_id = FIELD_GET(ICE_PO_PID, data);
 | |
| 	po->offset = FIELD_GET(ICE_PO_OFF, data);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_proto_grp_parse_item - parse 192 bits of Protocol Group Table entry
 | |
|  * @hw: pointer to the hardware structure
 | |
|  * @idx: index of Protocol Group Table entry
 | |
|  * @item: item of Protocol Group Table entry
 | |
|  * @data: Protocol Group Table entry data to be parsed
 | |
|  * @size: size of Protocol Group Table entry
 | |
|  */
 | |
| static void ice_proto_grp_parse_item(struct ice_hw *hw, u16 idx, void *item,
 | |
| 				     void *data, int __maybe_unused size)
 | |
| {
 | |
| 	struct ice_proto_grp_item *grp = item;
 | |
| 	u8 *buf = (u8 *)data;
 | |
| 	u8 idd, off;
 | |
| 	u32 d32;
 | |
| 	int i;
 | |
| 
 | |
| 	grp->idx = idx;
 | |
| 
 | |
| 	for (i = 0; i < ICE_PROTO_COUNT_PER_GRP; i++) {
 | |
| 		idd = (ICE_PROTO_GRP_ITEM_SIZE * i) / BITS_PER_BYTE;
 | |
| 		off = (ICE_PROTO_GRP_ITEM_SIZE * i) % BITS_PER_BYTE;
 | |
| 		d32 = *((u32 *)&buf[idd]) >> off;
 | |
| 		ice_proto_off_parse(&grp->po[i], d32);
 | |
| 	}
 | |
| 
 | |
| 	if (hw->debug_mask & ICE_DBG_PARSER)
 | |
| 		ice_proto_grp_dump(hw, grp);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_proto_grp_table_get - create a proto group table
 | |
|  * @hw: pointer to the hardware structure
 | |
|  *
 | |
|  * Return: a pointer to the allocated Protocol Group table.
 | |
|  */
 | |
| static struct ice_proto_grp_item *ice_proto_grp_table_get(struct ice_hw *hw)
 | |
| {
 | |
| 	return ice_parser_create_table(hw, ICE_SID_RXPARSER_PROTO_GRP,
 | |
| 				       sizeof(struct ice_proto_grp_item),
 | |
| 				       ICE_PROTO_GRP_TABLE_SIZE,
 | |
| 				       ice_proto_grp_parse_item, false);
 | |
| }
 | |
| 
 | |
| /*** ICE_SID_RXPARSER_FLAG_REDIR section ***/
 | |
| /**
 | |
|  * ice_flg_rd_dump - dump a flag redirect item info
 | |
|  * @hw: pointer to the hardware structure
 | |
|  * @item: flag redirect item to dump
 | |
|  */
 | |
| static void ice_flg_rd_dump(struct ice_hw *hw, struct ice_flg_rd_item *item)
 | |
| {
 | |
| 	struct device *dev = ice_hw_to_dev(hw);
 | |
| 
 | |
| 	dev_info(dev, "index = %d\n", item->idx);
 | |
| 	dev_info(dev, "expose = %d\n", item->expose);
 | |
| 	dev_info(dev, "intr_flg_id = %d\n", item->intr_flg_id);
 | |
| }
 | |
| 
 | |
| #define ICE_FRT_EXPO	BIT(0)
 | |
| #define ICE_FRT_IFID	GENMASK(6, 1)
 | |
| 
 | |
| /**
 | |
|  * ice_flg_rd_parse_item - parse 8 bits of Flag Redirect Table entry
 | |
|  * @hw: pointer to the hardware structure
 | |
|  * @idx: index of Flag Redirect Table entry
 | |
|  * @item: item of Flag Redirect Table entry
 | |
|  * @data: Flag Redirect Table entry data to be parsed
 | |
|  * @size: size of Flag Redirect Table entry
 | |
|  */
 | |
| static void ice_flg_rd_parse_item(struct ice_hw *hw, u16 idx, void *item,
 | |
| 				  void *data, int __maybe_unused size)
 | |
| {
 | |
| 	struct ice_flg_rd_item *rdi = item;
 | |
| 	u8 d8 = *(u8 *)data;
 | |
| 
 | |
| 	rdi->idx = idx;
 | |
| 	rdi->expose = FIELD_GET(ICE_FRT_EXPO, d8);
 | |
| 	rdi->intr_flg_id = FIELD_GET(ICE_FRT_IFID, d8);
 | |
| 
 | |
| 	if (hw->debug_mask & ICE_DBG_PARSER)
 | |
| 		ice_flg_rd_dump(hw, rdi);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_flg_rd_table_get - create a flag redirect table
 | |
|  * @hw: pointer to the hardware structure
 | |
|  *
 | |
|  * Return: a pointer to the allocated Flags Redirection table.
 | |
|  */
 | |
| static struct ice_flg_rd_item *ice_flg_rd_table_get(struct ice_hw *hw)
 | |
| {
 | |
| 	return ice_parser_create_table(hw, ICE_SID_RXPARSER_FLAG_REDIR,
 | |
| 				       sizeof(struct ice_flg_rd_item),
 | |
| 				       ICE_FLG_RD_TABLE_SIZE,
 | |
| 				       ice_flg_rd_parse_item, false);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_flg_redirect - redirect a parser flag to packet flag
 | |
|  * @table: flag redirect table
 | |
|  * @psr_flg: parser flag to redirect
 | |
|  *
 | |
|  * Return: flag or 0 if @psr_flag = 0.
 | |
|  */
 | |
| u64 ice_flg_redirect(struct ice_flg_rd_item *table, u64 psr_flg)
 | |
| {
 | |
| 	u64 flg = 0;
 | |
| 	int i;
 | |
| 
 | |
| 	for (i = 0; i < ICE_FLG_RDT_SIZE; i++) {
 | |
| 		struct ice_flg_rd_item *item = &table[i];
 | |
| 
 | |
| 		if (!item->expose)
 | |
| 			continue;
 | |
| 
 | |
| 		if (psr_flg & BIT(item->intr_flg_id))
 | |
| 			flg |= BIT(i);
 | |
| 	}
 | |
| 
 | |
| 	return flg;
 | |
| }
 | |
| 
 | |
| /*** ICE_SID_XLT_KEY_BUILDER_SW, ICE_SID_XLT_KEY_BUILDER_ACL,
 | |
|  * ICE_SID_XLT_KEY_BUILDER_FD and ICE_SID_XLT_KEY_BUILDER_RSS
 | |
|  * sections ***/
 | |
| static void ice_xlt_kb_entry_dump(struct ice_hw *hw,
 | |
| 				  struct ice_xlt_kb_entry *entry, int idx)
 | |
| {
 | |
| 	struct device *dev = ice_hw_to_dev(hw);
 | |
| 	int i;
 | |
| 
 | |
| 	dev_info(dev, "key builder entry %d\n", idx);
 | |
| 	dev_info(dev, "\txlt1_ad_sel = %d\n", entry->xlt1_ad_sel);
 | |
| 	dev_info(dev, "\txlt2_ad_sel = %d\n", entry->xlt2_ad_sel);
 | |
| 
 | |
| 	for (i = 0; i < ICE_XLT_KB_FLAG0_14_CNT; i++)
 | |
| 		dev_info(dev, "\tflg%d_sel = %d\n", i, entry->flg0_14_sel[i]);
 | |
| 
 | |
| 	dev_info(dev, "\txlt1_md_sel = %d\n", entry->xlt1_md_sel);
 | |
| 	dev_info(dev, "\txlt2_md_sel = %d\n", entry->xlt2_md_sel);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_xlt_kb_dump - dump a xlt key build info
 | |
|  * @hw: pointer to the hardware structure
 | |
|  * @kb: key build to dump
 | |
|  */
 | |
| static void ice_xlt_kb_dump(struct ice_hw *hw, struct ice_xlt_kb *kb)
 | |
| {
 | |
| 	struct device *dev = ice_hw_to_dev(hw);
 | |
| 	int i;
 | |
| 
 | |
| 	dev_info(dev, "xlt1_pm = %d\n", kb->xlt1_pm);
 | |
| 	dev_info(dev, "xlt2_pm = %d\n", kb->xlt2_pm);
 | |
| 	dev_info(dev, "prof_id_pm = %d\n", kb->prof_id_pm);
 | |
| 	dev_info(dev, "flag15 lo = 0x%08x\n", (u32)kb->flag15);
 | |
| 	dev_info(dev, "flag15 hi = 0x%08x\n",
 | |
| 		 (u32)(kb->flag15 >> (sizeof(u32) * BITS_PER_BYTE)));
 | |
| 
 | |
| 	for (i = 0; i < ICE_XLT_KB_TBL_CNT; i++)
 | |
| 		ice_xlt_kb_entry_dump(hw, &kb->entries[i], i);
 | |
| }
 | |
| 
 | |
| #define ICE_XLT_KB_X1AS_S	32	/* offset for the 1st 64-bits field */
 | |
| #define ICE_XLT_KB_X1AS_IDD	(ICE_XLT_KB_X1AS_S / BITS_PER_BYTE)
 | |
| #define ICE_XLT_KB_X1AS_OFF	(ICE_XLT_KB_X1AS_S % BITS_PER_BYTE)
 | |
| #define ICE_XLT_KB_X1AS		GENMASK_ULL(34 - ICE_XLT_KB_X1AS_S, \
 | |
| 					    32 - ICE_XLT_KB_X1AS_S)
 | |
| #define ICE_XLT_KB_X2AS		GENMASK_ULL(37 - ICE_XLT_KB_X1AS_S, \
 | |
| 					    35 - ICE_XLT_KB_X1AS_S)
 | |
| #define ICE_XLT_KB_FL00		GENMASK_ULL(46 - ICE_XLT_KB_X1AS_S, \
 | |
| 					    38 - ICE_XLT_KB_X1AS_S)
 | |
| #define ICE_XLT_KB_FL01		GENMASK_ULL(55 - ICE_XLT_KB_X1AS_S, \
 | |
| 					    47 - ICE_XLT_KB_X1AS_S)
 | |
| #define ICE_XLT_KB_FL02		GENMASK_ULL(64 - ICE_XLT_KB_X1AS_S, \
 | |
| 					    56 - ICE_XLT_KB_X1AS_S)
 | |
| #define ICE_XLT_KB_FL03		GENMASK_ULL(73 - ICE_XLT_KB_X1AS_S, \
 | |
| 					    65 - ICE_XLT_KB_X1AS_S)
 | |
| #define ICE_XLT_KB_FL04		GENMASK_ULL(82 - ICE_XLT_KB_X1AS_S, \
 | |
| 					    74 - ICE_XLT_KB_X1AS_S)
 | |
| #define ICE_XLT_KB_FL05		GENMASK_ULL(91 - ICE_XLT_KB_X1AS_S, \
 | |
| 					    83 - ICE_XLT_KB_X1AS_S)
 | |
| #define ICE_XLT_KB_FL06_S	92	/* offset for the 2nd 64-bits field */
 | |
| #define ICE_XLT_KB_FL06_IDD	(ICE_XLT_KB_FL06_S / BITS_PER_BYTE)
 | |
| #define ICE_XLT_KB_FL06_OFF	(ICE_XLT_KB_FL06_S % BITS_PER_BYTE)
 | |
| #define ICE_XLT_KB_FL06		GENMASK_ULL(100 - ICE_XLT_KB_FL06_S, \
 | |
| 					    92 - ICE_XLT_KB_FL06_S)
 | |
| #define ICE_XLT_KB_FL07		GENMASK_ULL(109 - ICE_XLT_KB_FL06_S, \
 | |
| 					    101 - ICE_XLT_KB_FL06_S)
 | |
| #define ICE_XLT_KB_FL08		GENMASK_ULL(118 - ICE_XLT_KB_FL06_S, \
 | |
| 					    110 - ICE_XLT_KB_FL06_S)
 | |
| #define ICE_XLT_KB_FL09		GENMASK_ULL(127 - ICE_XLT_KB_FL06_S, \
 | |
| 					    119 - ICE_XLT_KB_FL06_S)
 | |
| #define ICE_XLT_KB_FL10		GENMASK_ULL(136 - ICE_XLT_KB_FL06_S, \
 | |
| 					    128 - ICE_XLT_KB_FL06_S)
 | |
| #define ICE_XLT_KB_FL11		GENMASK_ULL(145 - ICE_XLT_KB_FL06_S, \
 | |
| 					    137 - ICE_XLT_KB_FL06_S)
 | |
| #define ICE_XLT_KB_FL12_S	146	/* offset for the 3rd 64-bits field */
 | |
| #define ICE_XLT_KB_FL12_IDD	(ICE_XLT_KB_FL12_S / BITS_PER_BYTE)
 | |
| #define ICE_XLT_KB_FL12_OFF	(ICE_XLT_KB_FL12_S % BITS_PER_BYTE)
 | |
| #define ICE_XLT_KB_FL12		GENMASK_ULL(154 - ICE_XLT_KB_FL12_S, \
 | |
| 					    146 - ICE_XLT_KB_FL12_S)
 | |
| #define ICE_XLT_KB_FL13		GENMASK_ULL(163 - ICE_XLT_KB_FL12_S, \
 | |
| 					    155 - ICE_XLT_KB_FL12_S)
 | |
| #define ICE_XLT_KB_FL14		GENMASK_ULL(181 - ICE_XLT_KB_FL12_S, \
 | |
| 					    164 - ICE_XLT_KB_FL12_S)
 | |
| #define ICE_XLT_KB_X1MS		GENMASK_ULL(186 - ICE_XLT_KB_FL12_S, \
 | |
| 					    182 - ICE_XLT_KB_FL12_S)
 | |
| #define ICE_XLT_KB_X2MS		GENMASK_ULL(191 - ICE_XLT_KB_FL12_S, \
 | |
| 					    187 - ICE_XLT_KB_FL12_S)
 | |
| 
 | |
| /**
 | |
|  * ice_kb_entry_init - parse 192 bits of XLT Key Builder entry
 | |
|  * @entry: pointer to the XLT Key Builder entry structure
 | |
|  * @data: XLT Key Builder entry data to be parsed
 | |
|  */
 | |
| static void ice_kb_entry_init(struct ice_xlt_kb_entry *entry, u8 *data)
 | |
| {
 | |
| 	u8 i = 0;
 | |
| 	u64 d64;
 | |
| 
 | |
| 	d64 = *((u64 *)&data[ICE_XLT_KB_X1AS_IDD]) >> ICE_XLT_KB_X1AS_OFF;
 | |
| 
 | |
| 	entry->xlt1_ad_sel	= FIELD_GET(ICE_XLT_KB_X1AS, d64);
 | |
| 	entry->xlt2_ad_sel	= FIELD_GET(ICE_XLT_KB_X2AS, d64);
 | |
| 
 | |
| 	entry->flg0_14_sel[i++]	= FIELD_GET(ICE_XLT_KB_FL00, d64);
 | |
| 	entry->flg0_14_sel[i++]	= FIELD_GET(ICE_XLT_KB_FL01, d64);
 | |
| 	entry->flg0_14_sel[i++]	= FIELD_GET(ICE_XLT_KB_FL02, d64);
 | |
| 	entry->flg0_14_sel[i++]	= FIELD_GET(ICE_XLT_KB_FL03, d64);
 | |
| 	entry->flg0_14_sel[i++]	= FIELD_GET(ICE_XLT_KB_FL04, d64);
 | |
| 	entry->flg0_14_sel[i++]	= FIELD_GET(ICE_XLT_KB_FL05, d64);
 | |
| 
 | |
| 	d64 = *((u64 *)&data[ICE_XLT_KB_FL06_IDD]) >> ICE_XLT_KB_FL06_OFF;
 | |
| 
 | |
| 	entry->flg0_14_sel[i++]	= FIELD_GET(ICE_XLT_KB_FL06, d64);
 | |
| 	entry->flg0_14_sel[i++]	= FIELD_GET(ICE_XLT_KB_FL07, d64);
 | |
| 	entry->flg0_14_sel[i++]	= FIELD_GET(ICE_XLT_KB_FL08, d64);
 | |
| 	entry->flg0_14_sel[i++]	= FIELD_GET(ICE_XLT_KB_FL09, d64);
 | |
| 	entry->flg0_14_sel[i++]	= FIELD_GET(ICE_XLT_KB_FL10, d64);
 | |
| 	entry->flg0_14_sel[i++]	= FIELD_GET(ICE_XLT_KB_FL11, d64);
 | |
| 
 | |
| 	d64 = *((u64 *)&data[ICE_XLT_KB_FL12_IDD]) >> ICE_XLT_KB_FL12_OFF;
 | |
| 
 | |
| 	entry->flg0_14_sel[i++]	= FIELD_GET(ICE_XLT_KB_FL12, d64);
 | |
| 	entry->flg0_14_sel[i++]	= FIELD_GET(ICE_XLT_KB_FL13, d64);
 | |
| 	entry->flg0_14_sel[i]	= FIELD_GET(ICE_XLT_KB_FL14, d64);
 | |
| 
 | |
| 	entry->xlt1_md_sel	= FIELD_GET(ICE_XLT_KB_X1MS, d64);
 | |
| 	entry->xlt2_md_sel	= FIELD_GET(ICE_XLT_KB_X2MS, d64);
 | |
| }
 | |
| 
 | |
| #define ICE_XLT_KB_X1PM_OFF	0
 | |
| #define ICE_XLT_KB_X2PM_OFF	1
 | |
| #define ICE_XLT_KB_PIPM_OFF	2
 | |
| #define ICE_XLT_KB_FL15_OFF	4
 | |
| #define ICE_XLT_KB_TBL_OFF	12
 | |
| 
 | |
| /**
 | |
|  * ice_parse_kb_data - parse 204 bits of XLT Key Build Table
 | |
|  * @hw: pointer to the hardware structure
 | |
|  * @kb: pointer to the XLT Key Build Table structure
 | |
|  * @data: XLT Key Build Table data to be parsed
 | |
|  */
 | |
| static void ice_parse_kb_data(struct ice_hw *hw, struct ice_xlt_kb *kb,
 | |
| 			      void *data)
 | |
| {
 | |
| 	u8 *buf = data;
 | |
| 	int i;
 | |
| 
 | |
| 	kb->xlt1_pm	= buf[ICE_XLT_KB_X1PM_OFF];
 | |
| 	kb->xlt2_pm	= buf[ICE_XLT_KB_X2PM_OFF];
 | |
| 	kb->prof_id_pm	= buf[ICE_XLT_KB_PIPM_OFF];
 | |
| 
 | |
| 	kb->flag15 = *(u64 *)&buf[ICE_XLT_KB_FL15_OFF];
 | |
| 	for (i = 0; i < ICE_XLT_KB_TBL_CNT; i++)
 | |
| 		ice_kb_entry_init(&kb->entries[i],
 | |
| 				  &buf[ICE_XLT_KB_TBL_OFF +
 | |
| 				       i * ICE_XLT_KB_TBL_ENTRY_SIZE]);
 | |
| 
 | |
| 	if (hw->debug_mask & ICE_DBG_PARSER)
 | |
| 		ice_xlt_kb_dump(hw, kb);
 | |
| }
 | |
| 
 | |
| static struct ice_xlt_kb *ice_xlt_kb_get(struct ice_hw *hw, u32 sect_type)
 | |
| {
 | |
| 	struct ice_pkg_enum state = {};
 | |
| 	struct ice_seg *seg = hw->seg;
 | |
| 	struct ice_xlt_kb *kb;
 | |
| 	void *data;
 | |
| 
 | |
| 	if (!seg)
 | |
| 		return ERR_PTR(-EINVAL);
 | |
| 
 | |
| 	kb = kzalloc(sizeof(*kb), GFP_KERNEL);
 | |
| 	if (!kb)
 | |
| 		return ERR_PTR(-ENOMEM);
 | |
| 
 | |
| 	data = ice_pkg_enum_section(seg, &state, sect_type);
 | |
| 	if (!data) {
 | |
| 		ice_debug(hw, ICE_DBG_PARSER, "failed to find section type %d.\n",
 | |
| 			  sect_type);
 | |
| 		kfree(kb);
 | |
| 		return ERR_PTR(-EINVAL);
 | |
| 	}
 | |
| 
 | |
| 	ice_parse_kb_data(hw, kb, data);
 | |
| 
 | |
| 	return kb;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_xlt_kb_get_sw - create switch xlt key build
 | |
|  * @hw: pointer to the hardware structure
 | |
|  *
 | |
|  * Return: a pointer to the allocated Key Builder table for Switch.
 | |
|  */
 | |
| static struct ice_xlt_kb *ice_xlt_kb_get_sw(struct ice_hw *hw)
 | |
| {
 | |
| 	return ice_xlt_kb_get(hw, ICE_SID_XLT_KEY_BUILDER_SW);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_xlt_kb_get_acl - create acl xlt key build
 | |
|  * @hw: pointer to the hardware structure
 | |
|  *
 | |
|  * Return: a pointer to the allocated Key Builder table for ACL.
 | |
|  */
 | |
| static struct ice_xlt_kb *ice_xlt_kb_get_acl(struct ice_hw *hw)
 | |
| {
 | |
| 	return ice_xlt_kb_get(hw, ICE_SID_XLT_KEY_BUILDER_ACL);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_xlt_kb_get_fd - create fdir xlt key build
 | |
|  * @hw: pointer to the hardware structure
 | |
|  *
 | |
|  * Return: a pointer to the allocated Key Builder table for Flow Director.
 | |
|  */
 | |
| static struct ice_xlt_kb *ice_xlt_kb_get_fd(struct ice_hw *hw)
 | |
| {
 | |
| 	return ice_xlt_kb_get(hw, ICE_SID_XLT_KEY_BUILDER_FD);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_xlt_kb_get_rss - create rss xlt key build
 | |
|  * @hw: pointer to the hardware structure
 | |
|  *
 | |
|  * Return: a pointer to the allocated Key Builder table for RSS.
 | |
|  */
 | |
| static struct ice_xlt_kb *ice_xlt_kb_get_rss(struct ice_hw *hw)
 | |
| {
 | |
| 	return ice_xlt_kb_get(hw, ICE_SID_XLT_KEY_BUILDER_RSS);
 | |
| }
 | |
| 
 | |
| #define ICE_XLT_KB_MASK		GENMASK_ULL(5, 0)
 | |
| 
 | |
| /**
 | |
|  * ice_xlt_kb_flag_get - aggregate 64 bits packet flag into 16 bits xlt flag
 | |
|  * @kb: xlt key build
 | |
|  * @pkt_flag: 64 bits packet flag
 | |
|  *
 | |
|  * Return: XLT flag or 0 if @pkt_flag = 0.
 | |
|  */
 | |
| u16 ice_xlt_kb_flag_get(struct ice_xlt_kb *kb, u64 pkt_flag)
 | |
| {
 | |
| 	struct ice_xlt_kb_entry *entry = &kb->entries[0];
 | |
| 	u16 flag = 0;
 | |
| 	int i;
 | |
| 
 | |
| 	/* check flag 15 */
 | |
| 	if (kb->flag15 & pkt_flag)
 | |
| 		flag = BIT(ICE_XLT_KB_FLAG0_14_CNT);
 | |
| 
 | |
| 	/* check flag 0 - 14 */
 | |
| 	for (i = 0; i < ICE_XLT_KB_FLAG0_14_CNT; i++) {
 | |
| 		/* only check first entry */
 | |
| 		u16 idx = entry->flg0_14_sel[i] & ICE_XLT_KB_MASK;
 | |
| 
 | |
| 		if (pkt_flag & BIT(idx))
 | |
| 			flag |= (u16)BIT(i);
 | |
| 	}
 | |
| 
 | |
| 	return flag;
 | |
| }
 | |
| 
 | |
| /*** Parser API ***/
 | |
| /**
 | |
|  * ice_parser_create - create a parser instance
 | |
|  * @hw: pointer to the hardware structure
 | |
|  *
 | |
|  * Return: a pointer to the allocated parser instance or ERR_PTR
 | |
|  * in case of error.
 | |
|  */
 | |
| struct ice_parser *ice_parser_create(struct ice_hw *hw)
 | |
| {
 | |
| 	struct ice_parser *p;
 | |
| 	void *err;
 | |
| 
 | |
| 	p = kzalloc(sizeof(*p), GFP_KERNEL);
 | |
| 	if (!p)
 | |
| 		return ERR_PTR(-ENOMEM);
 | |
| 
 | |
| 	p->hw = hw;
 | |
| 	p->rt.psr = p;
 | |
| 
 | |
| 	p->imem_table = ice_imem_table_get(hw);
 | |
| 	if (IS_ERR(p->imem_table)) {
 | |
| 		err = p->imem_table;
 | |
| 		goto err;
 | |
| 	}
 | |
| 
 | |
| 	p->mi_table = ice_metainit_table_get(hw);
 | |
| 	if (IS_ERR(p->mi_table)) {
 | |
| 		err = p->mi_table;
 | |
| 		goto err;
 | |
| 	}
 | |
| 
 | |
| 	p->pg_cam_table = ice_pg_cam_table_get(hw);
 | |
| 	if (IS_ERR(p->pg_cam_table)) {
 | |
| 		err = p->pg_cam_table;
 | |
| 		goto err;
 | |
| 	}
 | |
| 
 | |
| 	p->pg_sp_cam_table = ice_pg_sp_cam_table_get(hw);
 | |
| 	if (IS_ERR(p->pg_sp_cam_table)) {
 | |
| 		err = p->pg_sp_cam_table;
 | |
| 		goto err;
 | |
| 	}
 | |
| 
 | |
| 	p->pg_nm_cam_table = ice_pg_nm_cam_table_get(hw);
 | |
| 	if (IS_ERR(p->pg_nm_cam_table)) {
 | |
| 		err = p->pg_nm_cam_table;
 | |
| 		goto err;
 | |
| 	}
 | |
| 
 | |
| 	p->pg_nm_sp_cam_table = ice_pg_nm_sp_cam_table_get(hw);
 | |
| 	if (IS_ERR(p->pg_nm_sp_cam_table)) {
 | |
| 		err = p->pg_nm_sp_cam_table;
 | |
| 		goto err;
 | |
| 	}
 | |
| 
 | |
| 	p->bst_tcam_table = ice_bst_tcam_table_get(hw);
 | |
| 	if (IS_ERR(p->bst_tcam_table)) {
 | |
| 		err = p->bst_tcam_table;
 | |
| 		goto err;
 | |
| 	}
 | |
| 
 | |
| 	p->bst_lbl_table = ice_bst_lbl_table_get(hw);
 | |
| 	if (IS_ERR(p->bst_lbl_table)) {
 | |
| 		err = p->bst_lbl_table;
 | |
| 		goto err;
 | |
| 	}
 | |
| 
 | |
| 	p->ptype_mk_tcam_table = ice_ptype_mk_tcam_table_get(hw);
 | |
| 	if (IS_ERR(p->ptype_mk_tcam_table)) {
 | |
| 		err = p->ptype_mk_tcam_table;
 | |
| 		goto err;
 | |
| 	}
 | |
| 
 | |
| 	p->mk_grp_table = ice_mk_grp_table_get(hw);
 | |
| 	if (IS_ERR(p->mk_grp_table)) {
 | |
| 		err = p->mk_grp_table;
 | |
| 		goto err;
 | |
| 	}
 | |
| 
 | |
| 	p->proto_grp_table = ice_proto_grp_table_get(hw);
 | |
| 	if (IS_ERR(p->proto_grp_table)) {
 | |
| 		err = p->proto_grp_table;
 | |
| 		goto err;
 | |
| 	}
 | |
| 
 | |
| 	p->flg_rd_table = ice_flg_rd_table_get(hw);
 | |
| 	if (IS_ERR(p->flg_rd_table)) {
 | |
| 		err = p->flg_rd_table;
 | |
| 		goto err;
 | |
| 	}
 | |
| 
 | |
| 	p->xlt_kb_sw = ice_xlt_kb_get_sw(hw);
 | |
| 	if (IS_ERR(p->xlt_kb_sw)) {
 | |
| 		err = p->xlt_kb_sw;
 | |
| 		goto err;
 | |
| 	}
 | |
| 
 | |
| 	p->xlt_kb_acl = ice_xlt_kb_get_acl(hw);
 | |
| 	if (IS_ERR(p->xlt_kb_acl)) {
 | |
| 		err = p->xlt_kb_acl;
 | |
| 		goto err;
 | |
| 	}
 | |
| 
 | |
| 	p->xlt_kb_fd = ice_xlt_kb_get_fd(hw);
 | |
| 	if (IS_ERR(p->xlt_kb_fd)) {
 | |
| 		err = p->xlt_kb_fd;
 | |
| 		goto err;
 | |
| 	}
 | |
| 
 | |
| 	p->xlt_kb_rss = ice_xlt_kb_get_rss(hw);
 | |
| 	if (IS_ERR(p->xlt_kb_rss)) {
 | |
| 		err = p->xlt_kb_rss;
 | |
| 		goto err;
 | |
| 	}
 | |
| 
 | |
| 	return p;
 | |
| err:
 | |
| 	ice_parser_destroy(p);
 | |
| 	return err;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_parser_destroy - destroy a parser instance
 | |
|  * @psr: pointer to a parser instance
 | |
|  */
 | |
| void ice_parser_destroy(struct ice_parser *psr)
 | |
| {
 | |
| 	kfree(psr->imem_table);
 | |
| 	kfree(psr->mi_table);
 | |
| 	kfree(psr->pg_cam_table);
 | |
| 	kfree(psr->pg_sp_cam_table);
 | |
| 	kfree(psr->pg_nm_cam_table);
 | |
| 	kfree(psr->pg_nm_sp_cam_table);
 | |
| 	kfree(psr->bst_tcam_table);
 | |
| 	kfree(psr->bst_lbl_table);
 | |
| 	kfree(psr->ptype_mk_tcam_table);
 | |
| 	kfree(psr->mk_grp_table);
 | |
| 	kfree(psr->proto_grp_table);
 | |
| 	kfree(psr->flg_rd_table);
 | |
| 	kfree(psr->xlt_kb_sw);
 | |
| 	kfree(psr->xlt_kb_acl);
 | |
| 	kfree(psr->xlt_kb_fd);
 | |
| 	kfree(psr->xlt_kb_rss);
 | |
| 
 | |
| 	kfree(psr);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_parser_run - parse on a packet in binary and return the result
 | |
|  * @psr: pointer to a parser instance
 | |
|  * @pkt_buf: packet data
 | |
|  * @pkt_len: packet length
 | |
|  * @rslt: input/output parameter to save parser result.
 | |
|  *
 | |
|  * Return: 0 on success or errno.
 | |
|  */
 | |
| int ice_parser_run(struct ice_parser *psr, const u8 *pkt_buf,
 | |
| 		   int pkt_len, struct ice_parser_result *rslt)
 | |
| {
 | |
| 	ice_parser_rt_reset(&psr->rt);
 | |
| 	ice_parser_rt_pktbuf_set(&psr->rt, pkt_buf, pkt_len);
 | |
| 
 | |
| 	return ice_parser_rt_execute(&psr->rt, rslt);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_parser_result_dump - dump a parser result info
 | |
|  * @hw: pointer to the hardware structure
 | |
|  * @rslt: parser result info to dump
 | |
|  */
 | |
| void ice_parser_result_dump(struct ice_hw *hw, struct ice_parser_result *rslt)
 | |
| {
 | |
| 	struct device *dev = ice_hw_to_dev(hw);
 | |
| 	int i;
 | |
| 
 | |
| 	dev_info(dev, "ptype = %d\n", rslt->ptype);
 | |
| 	for (i = 0; i < rslt->po_num; i++)
 | |
| 		dev_info(dev, "proto = %d, offset = %d\n",
 | |
| 			 rslt->po[i].proto_id, rslt->po[i].offset);
 | |
| 
 | |
| 	dev_info(dev, "flags_psr = 0x%016llx\n", rslt->flags_psr);
 | |
| 	dev_info(dev, "flags_pkt = 0x%016llx\n", rslt->flags_pkt);
 | |
| 	dev_info(dev, "flags_sw = 0x%04x\n", rslt->flags_sw);
 | |
| 	dev_info(dev, "flags_fd = 0x%04x\n", rslt->flags_fd);
 | |
| 	dev_info(dev, "flags_rss = 0x%04x\n", rslt->flags_rss);
 | |
| }
 | |
| 
 | |
| #define ICE_BT_VLD_KEY	0xFF
 | |
| #define ICE_BT_INV_KEY	0xFE
 | |
| 
 | |
| static void ice_bst_dvm_set(struct ice_parser *psr, enum ice_lbl_type type,
 | |
| 			    bool on)
 | |
| {
 | |
| 	u16 i = 0;
 | |
| 
 | |
| 	while (true) {
 | |
| 		struct ice_bst_tcam_item *item;
 | |
| 		u8 key;
 | |
| 
 | |
| 		item = ice_bst_tcam_search(psr->bst_tcam_table,
 | |
| 					   psr->bst_lbl_table,
 | |
| 					   type, &i);
 | |
| 		if (!item)
 | |
| 			break;
 | |
| 
 | |
| 		key = on ? ICE_BT_VLD_KEY : ICE_BT_INV_KEY;
 | |
| 		item->key[ICE_BT_VM_OFF] = key;
 | |
| 		item->key_inv[ICE_BT_VM_OFF] = key;
 | |
| 		i++;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_parser_dvm_set - configure double vlan mode for parser
 | |
|  * @psr: pointer to a parser instance
 | |
|  * @on: true to turn on; false to turn off
 | |
|  */
 | |
| void ice_parser_dvm_set(struct ice_parser *psr, bool on)
 | |
| {
 | |
| 	ice_bst_dvm_set(psr, ICE_LBL_BST_TYPE_DVM, on);
 | |
| 	ice_bst_dvm_set(psr, ICE_LBL_BST_TYPE_SVM, !on);
 | |
| }
 | |
| 
 | |
| static int ice_tunnel_port_set(struct ice_parser *psr, enum ice_lbl_type type,
 | |
| 			       u16 udp_port, bool on)
 | |
| {
 | |
| 	u8 *buf = (u8 *)&udp_port;
 | |
| 	u16 i = 0;
 | |
| 
 | |
| 	while (true) {
 | |
| 		struct ice_bst_tcam_item *item;
 | |
| 
 | |
| 		item = ice_bst_tcam_search(psr->bst_tcam_table,
 | |
| 					   psr->bst_lbl_table,
 | |
| 					   type, &i);
 | |
| 		if (!item)
 | |
| 			break;
 | |
| 
 | |
| 		/* found empty slot to add */
 | |
| 		if (on && item->key[ICE_BT_TUN_PORT_OFF_H] == ICE_BT_INV_KEY &&
 | |
| 		    item->key_inv[ICE_BT_TUN_PORT_OFF_H] == ICE_BT_INV_KEY) {
 | |
| 			item->key_inv[ICE_BT_TUN_PORT_OFF_L] =
 | |
| 						buf[ICE_UDP_PORT_OFF_L];
 | |
| 			item->key_inv[ICE_BT_TUN_PORT_OFF_H] =
 | |
| 						buf[ICE_UDP_PORT_OFF_H];
 | |
| 
 | |
| 			item->key[ICE_BT_TUN_PORT_OFF_L] =
 | |
| 				ICE_BT_VLD_KEY - buf[ICE_UDP_PORT_OFF_L];
 | |
| 			item->key[ICE_BT_TUN_PORT_OFF_H] =
 | |
| 				ICE_BT_VLD_KEY - buf[ICE_UDP_PORT_OFF_H];
 | |
| 
 | |
| 			return 0;
 | |
| 		/* found a matched slot to delete */
 | |
| 		} else if (!on &&
 | |
| 			   (item->key_inv[ICE_BT_TUN_PORT_OFF_L] ==
 | |
| 				buf[ICE_UDP_PORT_OFF_L] ||
 | |
| 			    item->key_inv[ICE_BT_TUN_PORT_OFF_H] ==
 | |
| 				buf[ICE_UDP_PORT_OFF_H])) {
 | |
| 			item->key_inv[ICE_BT_TUN_PORT_OFF_L] = ICE_BT_VLD_KEY;
 | |
| 			item->key_inv[ICE_BT_TUN_PORT_OFF_H] = ICE_BT_INV_KEY;
 | |
| 
 | |
| 			item->key[ICE_BT_TUN_PORT_OFF_L] = ICE_BT_VLD_KEY;
 | |
| 			item->key[ICE_BT_TUN_PORT_OFF_H] = ICE_BT_INV_KEY;
 | |
| 
 | |
| 			return 0;
 | |
| 		}
 | |
| 		i++;
 | |
| 	}
 | |
| 
 | |
| 	return -EINVAL;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_parser_vxlan_tunnel_set - configure vxlan tunnel for parser
 | |
|  * @psr: pointer to a parser instance
 | |
|  * @udp_port: vxlan tunnel port in UDP header
 | |
|  * @on: true to turn on; false to turn off
 | |
|  *
 | |
|  * Return: 0 on success or errno on failure.
 | |
|  */
 | |
| int ice_parser_vxlan_tunnel_set(struct ice_parser *psr,
 | |
| 				u16 udp_port, bool on)
 | |
| {
 | |
| 	return ice_tunnel_port_set(psr, ICE_LBL_BST_TYPE_VXLAN, udp_port, on);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_parser_geneve_tunnel_set - configure geneve tunnel for parser
 | |
|  * @psr: pointer to a parser instance
 | |
|  * @udp_port: geneve tunnel port in UDP header
 | |
|  * @on: true to turn on; false to turn off
 | |
|  *
 | |
|  * Return: 0 on success or errno on failure.
 | |
|  */
 | |
| int ice_parser_geneve_tunnel_set(struct ice_parser *psr,
 | |
| 				 u16 udp_port, bool on)
 | |
| {
 | |
| 	return ice_tunnel_port_set(psr, ICE_LBL_BST_TYPE_GENEVE, udp_port, on);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_parser_ecpri_tunnel_set - configure ecpri tunnel for parser
 | |
|  * @psr: pointer to a parser instance
 | |
|  * @udp_port: ecpri tunnel port in UDP header
 | |
|  * @on: true to turn on; false to turn off
 | |
|  *
 | |
|  * Return: 0 on success or errno on failure.
 | |
|  */
 | |
| int ice_parser_ecpri_tunnel_set(struct ice_parser *psr,
 | |
| 				u16 udp_port, bool on)
 | |
| {
 | |
| 	return ice_tunnel_port_set(psr, ICE_LBL_BST_TYPE_UDP_ECPRI,
 | |
| 				   udp_port, on);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_nearest_proto_id - find nearest protocol ID
 | |
|  * @rslt: pointer to a parser result instance
 | |
|  * @offset: a min value for the protocol offset
 | |
|  * @proto_id: the protocol ID (output)
 | |
|  * @proto_off: the protocol offset (output)
 | |
|  *
 | |
|  * From the protocols in @rslt, find the nearest protocol that has offset
 | |
|  * larger than @offset.
 | |
|  *
 | |
|  * Return: if true, the protocol's ID and offset
 | |
|  */
 | |
| static bool ice_nearest_proto_id(struct ice_parser_result *rslt, u16 offset,
 | |
| 				 u8 *proto_id, u16 *proto_off)
 | |
| {
 | |
| 	u16 dist = U16_MAX;
 | |
| 	u8 proto = 0;
 | |
| 	int i;
 | |
| 
 | |
| 	for (i = 0; i < rslt->po_num; i++) {
 | |
| 		if (offset < rslt->po[i].offset)
 | |
| 			continue;
 | |
| 		if (offset - rslt->po[i].offset < dist) {
 | |
| 			proto = rslt->po[i].proto_id;
 | |
| 			dist = offset - rslt->po[i].offset;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if (dist % 2)
 | |
| 		return false;
 | |
| 
 | |
| 	*proto_id = proto;
 | |
| 	*proto_off = dist;
 | |
| 
 | |
| 	return true;
 | |
| }
 | |
| 
 | |
| /* default flag mask to cover GTP_EH_PDU, GTP_EH_PDU_LINK and TUN2
 | |
|  * In future, the flag masks should learn from DDP
 | |
|  */
 | |
| #define ICE_KEYBUILD_FLAG_MASK_DEFAULT_SW	0x4002
 | |
| #define ICE_KEYBUILD_FLAG_MASK_DEFAULT_ACL	0x0000
 | |
| #define ICE_KEYBUILD_FLAG_MASK_DEFAULT_FD	0x6080
 | |
| #define ICE_KEYBUILD_FLAG_MASK_DEFAULT_RSS	0x6010
 | |
| 
 | |
| /**
 | |
|  * ice_parser_profile_init - initialize a FXP profile based on parser result
 | |
|  * @rslt: a instance of a parser result
 | |
|  * @pkt_buf: packet data buffer
 | |
|  * @msk_buf: packet mask buffer
 | |
|  * @buf_len: packet length
 | |
|  * @blk: FXP pipeline stage
 | |
|  * @prof: input/output parameter to save the profile
 | |
|  *
 | |
|  * Return: 0 on success or errno on failure.
 | |
|  */
 | |
| int ice_parser_profile_init(struct ice_parser_result *rslt,
 | |
| 			    const u8 *pkt_buf, const u8 *msk_buf,
 | |
| 			    int buf_len, enum ice_block blk,
 | |
| 			    struct ice_parser_profile *prof)
 | |
| {
 | |
| 	u8 proto_id = U8_MAX;
 | |
| 	u16 proto_off = 0;
 | |
| 	u16 off;
 | |
| 
 | |
| 	memset(prof, 0, sizeof(*prof));
 | |
| 	set_bit(rslt->ptype, prof->ptypes);
 | |
| 	if (blk == ICE_BLK_SW) {
 | |
| 		prof->flags	= rslt->flags_sw;
 | |
| 		prof->flags_msk	= ICE_KEYBUILD_FLAG_MASK_DEFAULT_SW;
 | |
| 	} else if (blk == ICE_BLK_ACL) {
 | |
| 		prof->flags	= rslt->flags_acl;
 | |
| 		prof->flags_msk	= ICE_KEYBUILD_FLAG_MASK_DEFAULT_ACL;
 | |
| 	} else if (blk == ICE_BLK_FD) {
 | |
| 		prof->flags	= rslt->flags_fd;
 | |
| 		prof->flags_msk	= ICE_KEYBUILD_FLAG_MASK_DEFAULT_FD;
 | |
| 	} else if (blk == ICE_BLK_RSS) {
 | |
| 		prof->flags	= rslt->flags_rss;
 | |
| 		prof->flags_msk	= ICE_KEYBUILD_FLAG_MASK_DEFAULT_RSS;
 | |
| 	} else {
 | |
| 		return -EINVAL;
 | |
| 	}
 | |
| 
 | |
| 	for (off = 0; off < buf_len - 1; off++) {
 | |
| 		if (msk_buf[off] == 0 && msk_buf[off + 1] == 0)
 | |
| 			continue;
 | |
| 		if (!ice_nearest_proto_id(rslt, off, &proto_id, &proto_off))
 | |
| 			continue;
 | |
| 		if (prof->fv_num >= ICE_PARSER_FV_MAX)
 | |
| 			return -EINVAL;
 | |
| 
 | |
| 		prof->fv[prof->fv_num].proto_id	= proto_id;
 | |
| 		prof->fv[prof->fv_num].offset	= proto_off;
 | |
| 		prof->fv[prof->fv_num].spec	= *(const u16 *)&pkt_buf[off];
 | |
| 		prof->fv[prof->fv_num].msk	= *(const u16 *)&msk_buf[off];
 | |
| 		prof->fv_num++;
 | |
| 	}
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * ice_parser_profile_dump - dump an FXP profile info
 | |
|  * @hw: pointer to the hardware structure
 | |
|  * @prof: profile info to dump
 | |
|  */
 | |
| void ice_parser_profile_dump(struct ice_hw *hw,
 | |
| 			     struct ice_parser_profile *prof)
 | |
| {
 | |
| 	struct device *dev = ice_hw_to_dev(hw);
 | |
| 	u16 i;
 | |
| 
 | |
| 	dev_info(dev, "ptypes:\n");
 | |
| 	for (i = 0; i < ICE_FLOW_PTYPE_MAX; i++)
 | |
| 		if (test_bit(i, prof->ptypes))
 | |
| 			dev_info(dev, "\t%u\n", i);
 | |
| 
 | |
| 	for (i = 0; i < prof->fv_num; i++)
 | |
| 		dev_info(dev, "proto = %u, offset = %2u, spec = 0x%04x, mask = 0x%04x\n",
 | |
| 			 prof->fv[i].proto_id, prof->fv[i].offset,
 | |
| 			 prof->fv[i].spec, prof->fv[i].msk);
 | |
| 
 | |
| 	dev_info(dev, "flags = 0x%04x\n", prof->flags);
 | |
| 	dev_info(dev, "flags_msk = 0x%04x\n", prof->flags_msk);
 | |
| }
 |