// SPDX-License-Identifier: GPL-2.0
/* Copyright (C) 2024 Intel Corporation */
#include "ice_common.h"
static void ice_rt_tsr_set(struct ice_parser_rt *rt, u16 tsr)
{
rt->gpr[ICE_GPR_TSR_IDX] = tsr;
}
static void ice_rt_ho_set(struct ice_parser_rt *rt, u16 ho)
{
rt->gpr[ICE_GPR_HO_IDX] = ho;
memcpy(&rt->gpr[ICE_GPR_HV_IDX], &rt->pkt_buf[ho], ICE_GPR_HV_SIZE);
}
static void ice_rt_np_set(struct ice_parser_rt *rt, u16 pc)
{
rt->gpr[ICE_GPR_NP_IDX] = pc;
}
static void ice_rt_nn_set(struct ice_parser_rt *rt, u16 node)
{
rt->gpr[ICE_GPR_NN_IDX] = node;
}
static void
ice_rt_flag_set(struct ice_parser_rt *rt, unsigned int idx, bool set)
{
struct ice_hw *hw = rt->psr->hw;
unsigned int word, id;
word = idx / ICE_GPR_FLG_SIZE;
id = idx % ICE_GPR_FLG_SIZE;
if (set) {
rt->gpr[ICE_GPR_FLG_IDX + word] |= (u16)BIT(id);
ice_debug(hw, ICE_DBG_PARSER, "Set parser flag %u\n", idx);
} else {
rt->gpr[ICE_GPR_FLG_IDX + word] &= ~(u16)BIT(id);
ice_debug(hw, ICE_DBG_PARSER, "Clear parser flag %u\n", idx);
}
}
static void ice_rt_gpr_set(struct ice_parser_rt *rt, int idx, u16 val)
{
struct ice_hw *hw = rt->psr->hw;
if (idx == ICE_GPR_HO_IDX)
ice_rt_ho_set(rt, val);
else
rt->gpr[idx] = val;
ice_debug(hw, ICE_DBG_PARSER, "Set GPR %d value %d\n", idx, val);
}
static void ice_rt_err_set(struct ice_parser_rt *rt, unsigned int idx, bool set)
{
struct ice_hw *hw = rt->psr->hw;
if (set) {
rt->gpr[ICE_GPR_ERR_IDX] |= (u16)BIT(idx);
ice_debug(hw, ICE_DBG_PARSER, "Set parser error %u\n", idx);
} else {
rt->gpr[ICE_GPR_ERR_IDX] &= ~(u16)BIT(idx);
ice_debug(hw, ICE_DBG_PARSER, "Reset parser error %u\n", idx);
}
}
/**
* ice_parser_rt_reset - reset the parser runtime
* @rt: pointer to the parser runtime
*/
void ice_parser_rt_reset(struct ice_parser_rt *rt)
{
struct ice_parser *psr = rt->psr;
struct ice_metainit_item *mi;
unsigned int i;
mi = &psr->mi_table[0];
memset(rt, 0, sizeof(*rt));
rt->psr = psr;
ice_rt_tsr_set(rt, mi->tsr);
ice_rt_ho_set(rt, mi->ho);
ice_rt_np_set(rt, mi->pc);
ice_rt_nn_set(rt, mi->pg_rn);
for (i = 0; i < ICE_PARSER_FLG_NUM; i++) {
if (mi->flags & BIT(i))
ice_rt_flag_set(rt, i, true);
}
}
/**
* ice_parser_rt_pktbuf_set - set a packet into parser runtime
* @rt: pointer to the parser runtime
* @pkt_buf: buffer with packet data
* @pkt_len: packet buffer length
*/
void ice_parser_rt_pktbuf_set(struct ice_parser_rt *rt, const u8 *pkt_buf,
int pkt_len)
{
int len = min(ICE_PARSER_MAX_PKT_LEN, pkt_len);
u16 ho = rt->gpr[ICE_GPR_HO_IDX];
memcpy(rt->pkt_buf, pkt_buf, len);
rt->pkt_len = pkt_len;
memcpy(&rt->gpr[ICE_GPR_HV_IDX], &rt->pkt_buf[ho], ICE_GPR_HV_SIZE);
}
static void ice_bst_key_init(struct ice_parser_rt *rt,
struct ice_imem_item *imem)
{
u8 tsr = (u8)rt->gpr[ICE_GPR_TSR_IDX];
u16 ho = rt->gpr[ICE_GPR_HO_IDX];
u8 *key = rt->bst_key;
int idd, i;
idd = ICE_BST_TCAM_KEY_SIZE - 1;
if (imem->b_kb.tsr_ctrl)
key[idd] = tsr;
else
key[idd] = imem->b_kb.prio;
idd = ICE_BST_KEY_TCAM_SIZE - 1;
for (i = idd; i >= 0; i--) {
int j;
j = ho + idd - i;
if (j < ICE_PARSER_MAX_PKT_LEN)
key[i] = rt->pkt_buf[ho + idd - i];
else
key[i] = 0;
}
ice_debug(rt->psr->hw, ICE_DBG_PARSER, "Generated Boost TCAM Key:\n");
ice_debug(rt->psr->hw, ICE_DBG_PARSER, "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n",
key[0], key[1], key[2], key[3], key[4],
key[5], key[6], key[7], key[8], key[9]);
ice_debug(rt->psr->hw, ICE_DBG_PARSER, "\n");
}
static u16 ice_bit_rev_u16(u16 v, int len)
{
return bitrev16(v) >> (BITS_PER_TYPE(v) - len);
}
static u32 ice_bit_rev_u32(u32 v, int len)
{
return bitrev32(v) >> (BITS_PER_TYPE(v) - len);
}
static u32 ice_hv_bit_sel(struct ice_parser_rt *rt, int start, int len)
{
int offset;
u32 buf[2];
u64 val;
offset = ICE_GPR_HV_IDX + (start / BITS_PER_TYPE(u16));
memcpy(buf, &rt->gpr[offset], sizeof(buf));
buf[0] = bitrev8x4(buf[0]);
buf[1] = bitrev8x4(buf[1]);
val = *(u64 *)buf;
val >>= start % BITS_PER_TYPE(u16);
return ice_bit_rev_u32(val, len);
}
static u32 ice_pk_build(struct ice_parser_rt *rt,
struct ice_np_keybuilder *kb)
{
if (kb->opc == ICE_NPKB_OPC_EXTRACT)
return ice_hv_bit_sel(rt, kb->start_reg0, kb->