File Index
Files and directories
Sign in
FILE

rss.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/intel/ice/virt/rss.c C
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright (C) 2022, Intel Corporation. */
   3
   4#include "rss.h"
   5#include "ice_vf_lib_private.h"
   6#include "ice.h"
   7
   8#define FIELD_SELECTOR(proto_hdr_field) \
   9		BIT((proto_hdr_field) & PROTO_HDR_FIELD_MASK)
  10
  11struct ice_vc_hdr_match_type {
  12	u32 vc_hdr;	/* virtchnl headers (VIRTCHNL_PROTO_HDR_XXX) */
  13	u32 ice_hdr;	/* ice headers (ICE_FLOW_SEG_HDR_XXX) */
  14};
  15
  16static const struct ice_vc_hdr_match_type ice_vc_hdr_list[] = {
  17	{VIRTCHNL_PROTO_HDR_NONE,	ICE_FLOW_SEG_HDR_NONE},
  18	{VIRTCHNL_PROTO_HDR_ETH,	ICE_FLOW_SEG_HDR_ETH},
  19	{VIRTCHNL_PROTO_HDR_S_VLAN,	ICE_FLOW_SEG_HDR_VLAN},
  20	{VIRTCHNL_PROTO_HDR_C_VLAN,	ICE_FLOW_SEG_HDR_VLAN},
  21	{VIRTCHNL_PROTO_HDR_IPV4,	ICE_FLOW_SEG_HDR_IPV4 |
  22					ICE_FLOW_SEG_HDR_IPV_OTHER},
  23	{VIRTCHNL_PROTO_HDR_IPV6,	ICE_FLOW_SEG_HDR_IPV6 |
  24					ICE_FLOW_SEG_HDR_IPV_OTHER},
  25	{VIRTCHNL_PROTO_HDR_TCP,	ICE_FLOW_SEG_HDR_TCP},
  26	{VIRTCHNL_PROTO_HDR_UDP,	ICE_FLOW_SEG_HDR_UDP},
  27	{VIRTCHNL_PROTO_HDR_SCTP,	ICE_FLOW_SEG_HDR_SCTP},
  28	{VIRTCHNL_PROTO_HDR_PPPOE,	ICE_FLOW_SEG_HDR_PPPOE},
  29	{VIRTCHNL_PROTO_HDR_GTPU_IP,	ICE_FLOW_SEG_HDR_GTPU_IP},
  30	{VIRTCHNL_PROTO_HDR_GTPU_EH,	ICE_FLOW_SEG_HDR_GTPU_EH},
  31	{VIRTCHNL_PROTO_HDR_GTPU_EH_PDU_DWN,
  32					ICE_FLOW_SEG_HDR_GTPU_DWN},
  33	{VIRTCHNL_PROTO_HDR_GTPU_EH_PDU_UP,
  34					ICE_FLOW_SEG_HDR_GTPU_UP},
  35	{VIRTCHNL_PROTO_HDR_L2TPV3,	ICE_FLOW_SEG_HDR_L2TPV3},
  36	{VIRTCHNL_PROTO_HDR_ESP,	ICE_FLOW_SEG_HDR_ESP},
  37	{VIRTCHNL_PROTO_HDR_AH,		ICE_FLOW_SEG_HDR_AH},
  38	{VIRTCHNL_PROTO_HDR_PFCP,	ICE_FLOW_SEG_HDR_PFCP_SESSION},
  39	{VIRTCHNL_PROTO_HDR_GTPC,	ICE_FLOW_SEG_HDR_GTPC},
  40	{VIRTCHNL_PROTO_HDR_L2TPV2,	ICE_FLOW_SEG_HDR_L2TPV2},
  41	{VIRTCHNL_PROTO_HDR_IPV4_FRAG,	ICE_FLOW_SEG_HDR_IPV_FRAG},
  42	{VIRTCHNL_PROTO_HDR_IPV6_EH_FRAG,	ICE_FLOW_SEG_HDR_IPV_FRAG},
  43	{VIRTCHNL_PROTO_HDR_GRE,        ICE_FLOW_SEG_HDR_GRE},
  44};
  45
  46struct ice_vc_hash_field_match_type {
  47	u32 vc_hdr;		/* virtchnl headers
  48				 * (VIRTCHNL_PROTO_HDR_XXX)
  49				 */
  50	u32 vc_hash_field;	/* virtchnl hash fields selector
  51				 * FIELD_SELECTOR((VIRTCHNL_PROTO_HDR_ETH_XXX))
  52				 */
  53	u64 ice_hash_field;	/* ice hash fields
  54				 * (BIT_ULL(ICE_FLOW_FIELD_IDX_XXX))
  55				 */
  56};
  57
  58static const struct
  59ice_vc_hash_field_match_type ice_vc_hash_field_list[] = {
  60	{VIRTCHNL_PROTO_HDR_ETH, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_ETH_SRC),
  61		BIT_ULL(ICE_FLOW_FIELD_IDX_ETH_SA)},
  62	{VIRTCHNL_PROTO_HDR_ETH, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_ETH_DST),
  63		BIT_ULL(ICE_FLOW_FIELD_IDX_ETH_DA)},
  64	{VIRTCHNL_PROTO_HDR_ETH, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_ETH_SRC) |
  65		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_ETH_DST),
  66		ICE_FLOW_HASH_ETH},
  67	{VIRTCHNL_PROTO_HDR_ETH,
  68		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_ETH_ETHERTYPE),
  69		BIT_ULL(ICE_FLOW_FIELD_IDX_ETH_TYPE)},
  70	{VIRTCHNL_PROTO_HDR_S_VLAN,
  71		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_S_VLAN_ID),
  72		BIT_ULL(ICE_FLOW_FIELD_IDX_S_VLAN)},
  73	{VIRTCHNL_PROTO_HDR_C_VLAN,
  74		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_C_VLAN_ID),
  75		BIT_ULL(ICE_FLOW_FIELD_IDX_C_VLAN)},
  76	{VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC),
  77		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA)},
  78	{VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST),
  79		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA)},
  80	{VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC) |
  81		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST),
  82		ICE_FLOW_HASH_IPV4},
  83	{VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC) |
  84		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT),
  85		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA) |
  86		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT)},
  87	{VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST) |
  88		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT),
  89		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA) |
  90		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT)},
  91	{VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC) |
  92		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST) |
  93		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT),
  94		ICE_FLOW_HASH_IPV4 | BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT)},
  95	{VIRTCHNL_PROTO_HDR_IPV4,
  96		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_FRAG_PKID),
  97		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_ID)},
  98	{VIRTCHNL_PROTO_HDR_IPV4,
  99		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_CHKSUM),
 100		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_CHKSUM)},
 101	{VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC) |
 102		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_CHKSUM),
 103		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA) |
 104		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_CHKSUM)},
 105	{VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST) |
 106		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_CHKSUM),
 107		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA) |
 108		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_CHKSUM)},
 109	{VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC) |
 110		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST) |
 111		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_CHKSUM),
 112		ICE_FLOW_HASH_IPV4 | BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_CHKSUM)},
 113	{VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC) |
 114		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT) |
 115		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_CHKSUM),
 116		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA) |
 117		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT) |
 118		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_CHKSUM)},
 119	{VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST) |
 120		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT) |
 121		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_CHKSUM),
 122		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA) |
 123		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT) |
 124		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_CHKSUM)},
 125	{VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC) |
 126		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST) |
 127		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT) |
 128		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_CHKSUM),
 129		ICE_FLOW_HASH_IPV4 | BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT) |
 130		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_CHKSUM)},
 131	{VIRTCHNL_PROTO_HDR_IPV4,
 132		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT) |
 133		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_CHKSUM),
 134		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT) |
 135		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_CHKSUM)},
 136	{VIRTCHNL_PROTO_HDR_IPV4_FRAG,
 137		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT),
 138		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT)},
 139	{VIRTCHNL_PROTO_HDR_IPV4_FRAG,
 140		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC),
 141		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA)},
 142	{VIRTCHNL_PROTO_HDR_IPV4_FRAG,
 143		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST),
 144		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA)},
 145	{VIRTCHNL_PROTO_HDR_IPV4_FRAG,
 146		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC) |
 147		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST),
 148		ICE_FLOW_HASH_IPV4},
 149	{VIRTCHNL_PROTO_HDR_IPV4_FRAG,
 150		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC) |
 151		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT),
 152		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA) |
 153		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT)},
 154	{VIRTCHNL_PROTO_HDR_IPV4_FRAG,
 155		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST) |
 156		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT),
 157		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA) |
 158		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT)},
 159	{VIRTCHNL_PROTO_HDR_IPV4_FRAG,
 160		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC) |
 161		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST) |
 162		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT),
 163		ICE_FLOW_HASH_IPV4 | BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT)},
 164	{VIRTCHNL_PROTO_HDR_IPV4_FRAG,
 165		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT),
 166		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT)},
 167	{VIRTCHNL_PROTO_HDR_IPV4_FRAG,
 168		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_FRAG_PKID),
 169		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_ID)},
 170	{VIRTCHNL_PROTO_HDR_IPV4_FRAG,
 171		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_CHKSUM),
 172		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_CHKSUM)},
 173	{VIRTCHNL_PROTO_HDR_IPV4_FRAG,
 174		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC) |
 175		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_CHKSUM),
 176		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA) |
 177		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_CHKSUM)},
 178	{VIRTCHNL_PROTO_HDR_IPV4_FRAG,
 179		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST) |
 180		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_CHKSUM),
 181		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA) |
 182		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_CHKSUM)},
 183	{VIRTCHNL_PROTO_HDR_IPV4_FRAG,
 184		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC) |
 185		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST) |
 186		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_CHKSUM),
 187		ICE_FLOW_HASH_IPV4 | BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_CHKSUM)},
 188	{VIRTCHNL_PROTO_HDR_IPV4_FRAG,
 189		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC) |
 190		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT) |
 191		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_CHKSUM),
 192		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA) |
 193		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT) |
 194		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_CHKSUM)},
 195	{VIRTCHNL_PROTO_HDR_IPV4_FRAG,
 196		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST) |
 197		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT) |
 198		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_CHKSUM),
 199		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA) |
 200		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT) |
 201		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_CHKSUM)},
 202	{VIRTCHNL_PROTO_HDR_IPV4_FRAG,
 203		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC) |
 204		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST) |
 205		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT) |
 206		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_CHKSUM),
 207		ICE_FLOW_HASH_IPV4 | BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT) |
 208		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_CHKSUM)},
 209	{VIRTCHNL_PROTO_HDR_IPV4_FRAG,
 210		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT) |
 211		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_CHKSUM),
 212		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT) |
 213		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_CHKSUM)},
 214	{VIRTCHNL_PROTO_HDR_IPV6, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_SRC),
 215		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_SA)},
 216	{VIRTCHNL_PROTO_HDR_IPV6, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_DST),
 217		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_DA)},
 218	{VIRTCHNL_PROTO_HDR_IPV6, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_SRC) |
 219		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_DST),
 220		ICE_FLOW_HASH_IPV6},
 221	{VIRTCHNL_PROTO_HDR_IPV6, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_SRC) |
 222		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PROT),
 223		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_SA) |
 224		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_PROT)},
 225	{VIRTCHNL_PROTO_HDR_IPV6, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_DST) |
 226		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PROT),
 227		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_DA) |
 228		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_PROT)},
 229	{VIRTCHNL_PROTO_HDR_IPV6, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_SRC) |
 230		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_DST) |
 231		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PROT),
 232		ICE_FLOW_HASH_IPV6 | BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_PROT)},
 233	{VIRTCHNL_PROTO_HDR_IPV6, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PROT),
 234		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_PROT)},
 235	{VIRTCHNL_PROTO_HDR_IPV6_EH_FRAG,
 236		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_EH_FRAG_PKID),
 237		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_ID)},
 238	{VIRTCHNL_PROTO_HDR_IPV6,
 239		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PREFIX64_SRC) |
 240		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PREFIX64_DST),
 241		ICE_FLOW_HASH_IPV6_PRE64},
 242	{VIRTCHNL_PROTO_HDR_IPV6,
 243		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PREFIX64_SRC),
 244		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_PRE64_SA)},
 245	{VIRTCHNL_PROTO_HDR_IPV6,
 246		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PREFIX64_DST),
 247		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_PRE64_DA)},
 248	{VIRTCHNL_PROTO_HDR_IPV6,
 249		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PREFIX64_SRC) |
 250		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PREFIX64_DST) |
 251		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PROT),
 252		ICE_FLOW_HASH_IPV6_PRE64 |
 253		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_PROT)},
 254	{VIRTCHNL_PROTO_HDR_IPV6,
 255		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PREFIX64_SRC) |
 256		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PROT),
 257		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_PRE64_SA) |
 258		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_PROT)},
 259	{VIRTCHNL_PROTO_HDR_IPV6,
 260		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PREFIX64_DST) |
 261		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PROT),
 262		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_PRE64_DA) |
 263		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_PROT)},
 264	{VIRTCHNL_PROTO_HDR_TCP,
 265		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_TCP_SRC_PORT),
 266		BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_SRC_PORT)},
 267	{VIRTCHNL_PROTO_HDR_TCP,
 268		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_TCP_DST_PORT),
 269		BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_DST_PORT)},
 270	{VIRTCHNL_PROTO_HDR_TCP,
 271		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_TCP_SRC_PORT) |
 272		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_TCP_DST_PORT),
 273		ICE_FLOW_HASH_TCP_PORT},
 274	{VIRTCHNL_PROTO_HDR_TCP,
 275		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_TCP_CHKSUM),
 276		BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_CHKSUM)},
 277	{VIRTCHNL_PROTO_HDR_TCP,
 278		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_TCP_SRC_PORT) |
 279		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_TCP_CHKSUM),
 280		BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_SRC_PORT) |
 281		BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_CHKSUM)},
 282	{VIRTCHNL_PROTO_HDR_TCP,
 283		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_TCP_DST_PORT) |
 284		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_TCP_CHKSUM),
 285		BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_DST_PORT) |
 286		BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_CHKSUM)},
 287	{VIRTCHNL_PROTO_HDR_TCP,
 288		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_TCP_SRC_PORT) |
 289		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_TCP_DST_PORT) |
 290		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_TCP_CHKSUM),
 291		ICE_FLOW_HASH_TCP_PORT |
 292		BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_CHKSUM)},
 293	{VIRTCHNL_PROTO_HDR_UDP,
 294		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_UDP_SRC_PORT),
 295		BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_SRC_PORT)},
 296	{VIRTCHNL_PROTO_HDR_UDP,
 297		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_UDP_DST_PORT),
 298		BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_DST_PORT)},
 299	{VIRTCHNL_PROTO_HDR_UDP,
 300		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_UDP_SRC_PORT) |
 301		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_UDP_DST_PORT),
 302		ICE_FLOW_HASH_UDP_PORT},
 303	{VIRTCHNL_PROTO_HDR_UDP,
 304		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_UDP_CHKSUM),
 305		BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_CHKSUM)},
 306	{VIRTCHNL_PROTO_HDR_UDP,
 307		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_UDP_SRC_PORT) |
 308		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_UDP_CHKSUM),
 309		BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_SRC_PORT) |
 310		BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_CHKSUM)},
 311	{VIRTCHNL_PROTO_HDR_UDP,
 312		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_UDP_DST_PORT) |
 313		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_UDP_CHKSUM),
 314		BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_DST_PORT) |
 315		BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_CHKSUM)},
 316	{VIRTCHNL_PROTO_HDR_UDP,
 317		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_UDP_SRC_PORT) |
 318		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_UDP_DST_PORT) |
 319		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_UDP_CHKSUM),
 320		ICE_FLOW_HASH_UDP_PORT |
 321		BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_CHKSUM)},
 322	{VIRTCHNL_PROTO_HDR_SCTP,
 323		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_SCTP_SRC_PORT),
 324		BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT)},
 325	{VIRTCHNL_PROTO_HDR_SCTP,
 326		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_SCTP_DST_PORT),
 327		BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_DST_PORT)},
 328	{VIRTCHNL_PROTO_HDR_SCTP,
 329		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_SCTP_SRC_PORT) |
 330		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_SCTP_DST_PORT),
 331		ICE_FLOW_HASH_SCTP_PORT},
 332	{VIRTCHNL_PROTO_HDR_SCTP,
 333		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_SCTP_CHKSUM),
 334		BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_CHKSUM)},
 335	{VIRTCHNL_PROTO_HDR_SCTP,
 336		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_SCTP_SRC_PORT) |
 337		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_SCTP_CHKSUM),
 338		BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT) |
 339		BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_CHKSUM)},
 340	{VIRTCHNL_PROTO_HDR_SCTP,
 341		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_SCTP_DST_PORT) |
 342		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_SCTP_CHKSUM),
 343		BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_DST_PORT) |
 344		BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_CHKSUM)},
 345	{VIRTCHNL_PROTO_HDR_SCTP,
 346		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_SCTP_SRC_PORT) |
 347		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_SCTP_DST_PORT) |
 348		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_SCTP_CHKSUM),
 349		ICE_FLOW_HASH_SCTP_PORT |
 350		BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_CHKSUM)},
 351	{VIRTCHNL_PROTO_HDR_PPPOE,
 352		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_PPPOE_SESS_ID),
 353		BIT_ULL(ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID)},
 354	{VIRTCHNL_PROTO_HDR_GTPU_IP,
 355		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_GTPU_IP_TEID),
 356		BIT_ULL(ICE_FLOW_FIELD_IDX_GTPU_IP_TEID)},
 357	{VIRTCHNL_PROTO_HDR_L2TPV3,
 358		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_L2TPV3_SESS_ID),
 359		BIT_ULL(ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID)},
 360	{VIRTCHNL_PROTO_HDR_ESP, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_ESP_SPI),
 361		BIT_ULL(ICE_FLOW_FIELD_IDX_ESP_SPI)},
 362	{VIRTCHNL_PROTO_HDR_AH, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_AH_SPI),
 363		BIT_ULL(ICE_FLOW_FIELD_IDX_AH_SPI)},
 364	{VIRTCHNL_PROTO_HDR_PFCP, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_PFCP_SEID),
 365		BIT_ULL(ICE_FLOW_FIELD_IDX_PFCP_SEID)},
 366	{VIRTCHNL_PROTO_HDR_GTPC,
 367		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_GTPC_TEID),
 368		BIT_ULL(ICE_FLOW_FIELD_IDX_GTPC_TEID)},
 369	{VIRTCHNL_PROTO_HDR_L2TPV2,
 370		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_L2TPV2_SESS_ID),
 371		BIT_ULL(ICE_FLOW_FIELD_IDX_L2TPV2_SESS_ID)},
 372	{VIRTCHNL_PROTO_HDR_L2TPV2,
 373		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_L2TPV2_LEN_SESS_ID),
 374		BIT_ULL(ICE_FLOW_FIELD_IDX_L2TPV2_LEN_SESS_ID)},
 375};
 376
 377static int
 378ice_vc_rss_hash_update(struct ice_hw *hw, struct ice_vsi *vsi, u8 hash_type)
 379{
 380	struct ice_vsi_ctx *ctx;
 381	int ret;
 382
 383	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
 384	if (!ctx)
 385		return -ENOMEM;
 386
 387	/* clear previous hash_type */
 388	ctx->info.q_opt_rss = vsi->info.q_opt_rss &
 389		~ICE_AQ_VSI_Q_OPT_RSS_HASH_M;
 390	/* hash_type is passed in as ICE_AQ_VSI_Q_OPT_RSS_<XOR|TPLZ|SYM_TPLZ */
 391	ctx->info.q_opt_rss |= FIELD_PREP(ICE_AQ_VSI_Q_OPT_RSS_HASH_M,
 392					  hash_type);
 393
 394	/* Preserve existing queueing option setting */
 395	ctx->info.q_opt_tc = vsi->info.q_opt_tc;
 396	ctx->info.q_opt_flags = vsi->info.q_opt_flags;
 397
 398	ctx->info.valid_sections =
 399			cpu_to_le16(ICE_AQ_VSI_PROP_Q_OPT_VALID);
 400
 401	ret = ice_update_vsi(hw, vsi->idx, ctx, NULL);
 402	if (ret) {
 403		dev_err(ice_hw_to_dev(hw), "update VSI for RSS failed, err %d aq_err %s\n",
 404			ret, libie_aq_str(hw->adminq.sq_last_status));
 405	} else {
 406		vsi->info.q_opt_rss = ctx->info.q_opt_rss;
 407	}
 408
 409	kfree(ctx);
 410
 411	return ret;
 412}
 413
 414/**
 415 * ice_vc_validate_pattern
 416 * @vf: pointer to the VF info
 417 * @proto: virtchnl protocol headers
 418 *
 419 * validate the pattern is supported or not.
 420 *
 421 * Return: true on success, false on error.
 422 */
 423bool
 424ice_vc_validate_pattern(struct ice_vf *vf, struct virtchnl_proto_hdrs *proto)
 425{
 426	bool is_ipv4 = false;
 427	bool is_ipv6 = false;
 428	bool is_udp = false;
 429	u16 ptype = -1;
 430	int i = 0;
 431
 432	while (i < proto->count &&
 433	       proto->proto_hdr[i].type != VIRTCHNL_PROTO_HDR_NONE) {
 434		switch (proto->proto_hdr[i].type) {
 435		case VIRTCHNL_PROTO_HDR_ETH:
 436			ptype = ICE_PTYPE_MAC_PAY;
 437			break;
 438		case VIRTCHNL_PROTO_HDR_IPV4:
 439			ptype = ICE_PTYPE_IPV4_PAY;
 440			is_ipv4 = true;
 441			break;
 442		case VIRTCHNL_PROTO_HDR_IPV6:
 443			ptype = ICE_PTYPE_IPV6_PAY;
 444			is_ipv6 = true;
 445			break;
 446		case VIRTCHNL_PROTO_HDR_UDP:
 447			if (is_ipv4)
 448				ptype = ICE_PTYPE_IPV4_UDP_PAY;
 449			else if (is_ipv6)
 450				ptype = ICE_PTYPE_IPV6_UDP_PAY;
 451			is_udp = true;
 452			break;
 453		case VIRTCHNL_PROTO_HDR_TCP:
 454			if (is_ipv4)
 455				ptype = ICE_PTYPE_IPV4_TCP_PAY;
 456			else if (is_ipv6)
 457				ptype = ICE_PTYPE_IPV6_TCP_PAY;
 458			break;
 459		case VIRTCHNL_PROTO_HDR_SCTP:
 460			if (is_ipv4)
 461				ptype = ICE_PTYPE_IPV4_SCTP_PAY;
 462			else if (is_ipv6)
 463				ptype = ICE_PTYPE_IPV6_SCTP_PAY;
 464			break;
 465		case VIRTCHNL_PROTO_HDR_GTPU_IP:
 466		case VIRTCHNL_PROTO_HDR_GTPU_EH:
 467			if (is_ipv4)
 468				ptype = ICE_MAC_IPV4_GTPU;
 469			else if (is_ipv6)
 470				ptype = ICE_MAC_IPV6_GTPU;
 471			goto out;
 472		case VIRTCHNL_PROTO_HDR_L2TPV3:
 473			if (is_ipv4)
 474				ptype = ICE_MAC_IPV4_L2TPV3;
 475			else if (is_ipv6)
 476				ptype = ICE_MAC_IPV6_L2TPV3;
 477			goto out;
 478		case VIRTCHNL_PROTO_HDR_ESP:
 479			if (is_ipv4)
 480				ptype = is_udp ? ICE_MAC_IPV4_NAT_T_ESP :
 481						ICE_MAC_IPV4_ESP;
 482			else if (is_ipv6)
 483				ptype = is_udp ? ICE_MAC_IPV6_NAT_T_ESP :
 484						ICE_MAC_IPV6_ESP;
 485			goto out;
 486		case VIRTCHNL_PROTO_HDR_AH:
 487			if (is_ipv4)
 488				ptype = ICE_MAC_IPV4_AH;
 489			else if (is_ipv6)
 490				ptype = ICE_MAC_IPV6_AH;
 491			goto out;
 492		case VIRTCHNL_PROTO_HDR_PFCP:
 493			if (is_ipv4)
 494				ptype = ICE_MAC_IPV4_PFCP_SESSION;
 495			else if (is_ipv6)
 496				ptype = ICE_MAC_IPV6_PFCP_SESSION;
 497			goto out;
 498		default:
 499			break;
 500		}
 501		i++;
 502	}
 503
 504out:
 505	return ice_hw_ptype_ena(&vf->pf->hw, ptype);
 506}
 507
 508/**
 509 * ice_vc_parse_rss_cfg - parses hash fields and headers from
 510 * a specific virtchnl RSS cfg
 511 * @hw: pointer to the hardware
 512 * @rss_cfg: pointer to the virtchnl RSS cfg
 513 * @hash_cfg: pointer to the HW hash configuration
 514 *
 515 * Return true if all the protocol header and hash fields in the RSS cfg could
 516 * be parsed, else return false
 517 *
 518 * This function parses the virtchnl RSS cfg to be the intended
 519 * hash fields and the intended header for RSS configuration
 520 */
 521static bool ice_vc_parse_rss_cfg(struct ice_hw *hw,
 522				 struct virtchnl_rss_cfg *rss_cfg,
 523				 struct ice_rss_hash_cfg *hash_cfg)
 524{
 525	const struct ice_vc_hash_field_match_type *hf_list;
 526	const struct ice_vc_hdr_match_type *hdr_list;
 527	int i, hf_list_len, hdr_list_len;
 528	bool outer_ipv4 = false;
 529	bool outer_ipv6 = false;
 530	bool inner_hdr = false;
 531	bool has_gre = false;
 532
 533	u32 *addl_hdrs = &hash_cfg->addl_hdrs;
 534	u64 *hash_flds = &hash_cfg->hash_flds;
 535
 536	/* set outer layer RSS as default */
 537	hash_cfg->hdr_type = ICE_RSS_OUTER_HEADERS;
 538
 539	if (rss_cfg->rss_algorithm == VIRTCHNL_RSS_ALG_TOEPLITZ_SYMMETRIC)
 540		hash_cfg->symm = true;
 541	else
 542		hash_cfg->symm = false;
 543
 544	hf_list = ice_vc_hash_field_list;
 545	hf_list_len = ARRAY_SIZE(ice_vc_hash_field_list);
 546	hdr_list = ice_vc_hdr_list;
 547	hdr_list_len = ARRAY_SIZE(ice_vc_hdr_list);
 548
 549	for (i = 0; i < rss_cfg->proto_hdrs.count; i++) {
 550		struct virtchnl_proto_hdr *proto_hdr =
 551					&rss_cfg->proto_hdrs.proto_hdr[i];
 552		u32 hdr_found = 0;
 553		int j;
 554
 555		/* Find matched ice headers according to virtchnl headers.
 556		 * Also figure out the outer type of GTPU headers.
 557		 */
 558		for (j = 0; j < hdr_list_len; j++) {
 559			struct ice_vc_hdr_match_type hdr_map = hdr_list[j];
 560
 561			if (proto_hdr->type == hdr_map.vc_hdr)
 562				hdr_found = hdr_map.ice_hdr;
 563		}
 564
 565		if (!hdr_found)
 566			return false;
 567
 568		/* Find matched ice hash fields according to
 569		 * virtchnl hash fields.
 570		 */
 571		for (j = 0; j < hf_list_len; j++) {
 572			struct ice_vc_hash_field_match_type hf_map = hf_list[j];
 573
 574			if (proto_hdr->type == hf_map.vc_hdr &&
 575			    proto_hdr->field_selector == hf_map.vc_hash_field) {
 576				*hash_flds |= hf_map.ice_hash_field;
 577				break;
 578			}
 579		}
 580
 581		if (proto_hdr->type == VIRTCHNL_PROTO_HDR_IPV4 && !inner_hdr)
 582			outer_ipv4 = true;
 583		else if (proto_hdr->type == VIRTCHNL_PROTO_HDR_IPV6 &&
 584			 !inner_hdr)
 585			outer_ipv6 = true;
 586		/* for GRE and L2TPv2, take inner header as input set if no
 587		 * any field is selected from outer headers.
 588		 * for GTPU, take inner header and GTPU teid as input set.
 589		 */
 590		else if ((proto_hdr->type == VIRTCHNL_PROTO_HDR_GTPU_IP ||
 591			  proto_hdr->type == VIRTCHNL_PROTO_HDR_GTPU_EH ||
 592			  proto_hdr->type == VIRTCHNL_PROTO_HDR_GTPU_EH_PDU_DWN ||
 593			  proto_hdr->type ==
 594				VIRTCHNL_PROTO_HDR_GTPU_EH_PDU_UP) ||
 595			 ((proto_hdr->type == VIRTCHNL_PROTO_HDR_L2TPV2 ||
 596			   proto_hdr->type == VIRTCHNL_PROTO_HDR_GRE) &&
 597			   *hash_flds == 0)) {
 598			/* set inner_hdr flag, and clean up outer header */
 599			inner_hdr = true;
 600
 601			/* clear outer headers */
 602			*addl_hdrs = 0;
 603
 604			if (outer_ipv4 && outer_ipv6)
 605				return false;
 606
 607			if (outer_ipv4)
 608				hash_cfg->hdr_type = ICE_RSS_INNER_HEADERS_W_OUTER_IPV4;
 609			else if (outer_ipv6)
 610				hash_cfg->hdr_type = ICE_RSS_INNER_HEADERS_W_OUTER_IPV6;
 611			else
 612				hash_cfg->hdr_type = ICE_RSS_INNER_HEADERS;
 613
 614			if (has_gre && outer_ipv4)
 615				hash_cfg->hdr_type =
 616					ICE_RSS_INNER_HEADERS_W_OUTER_IPV4_GRE;
 617			if (has_gre && outer_ipv6)
 618				hash_cfg->hdr_type =
 619					ICE_RSS_INNER_HEADERS_W_OUTER_IPV6_GRE;
 620
 621			if (proto_hdr->type == VIRTCHNL_PROTO_HDR_GRE)
 622				has_gre = true;
 623		}
 624
 625		*addl_hdrs |= hdr_found;
 626
 627		/* refine hash hdrs and fields for IP fragment */
 628		if (VIRTCHNL_TEST_PROTO_HDR_FIELD(proto_hdr,
 629						  VIRTCHNL_PROTO_HDR_IPV4_FRAG_PKID) &&
 630		    proto_hdr->type == VIRTCHNL_PROTO_HDR_IPV4_FRAG) {
 631			*addl_hdrs |= ICE_FLOW_SEG_HDR_IPV_FRAG;
 632			*addl_hdrs &= ~(ICE_FLOW_SEG_HDR_IPV_OTHER);
 633			*hash_flds |= BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_ID);
 634			VIRTCHNL_DEL_PROTO_HDR_FIELD(proto_hdr,
 635						     VIRTCHNL_PROTO_HDR_IPV4_FRAG_PKID);
 636		}
 637		if (VIRTCHNL_TEST_PROTO_HDR_FIELD(proto_hdr,
 638						  VIRTCHNL_PROTO_HDR_IPV6_EH_FRAG_PKID) &&
 639		    proto_hdr->type == VIRTCHNL_PROTO_HDR_IPV6_EH_FRAG) {
 640			*addl_hdrs |= ICE_FLOW_SEG_HDR_IPV_FRAG;
 641			*addl_hdrs &= ~(ICE_FLOW_SEG_HDR_IPV_OTHER);
 642			*hash_flds |= BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_ID);
 643			VIRTCHNL_DEL_PROTO_HDR_FIELD(proto_hdr,
 644						     VIRTCHNL_PROTO_HDR_IPV6_EH_FRAG_PKID);
 645		}
 646	}
 647
 648	/* refine gtpu header if we take outer as input set for a no inner
 649	 * ip gtpu flow.
 650	 */
 651	if (hash_cfg->hdr_type == ICE_RSS_OUTER_HEADERS &&
 652	    *addl_hdrs & ICE_FLOW_SEG_HDR_GTPU_IP) {
 653		*addl_hdrs &= ~(ICE_FLOW_SEG_HDR_GTPU_IP);
 654		*addl_hdrs |= ICE_FLOW_SEG_HDR_GTPU_NON_IP;
 655	}
 656
 657	/* refine hash field for esp and nat-t-esp. */
 658	if ((*addl_hdrs & ICE_FLOW_SEG_HDR_UDP) &&
 659	    (*addl_hdrs & ICE_FLOW_SEG_HDR_ESP)) {
 660		*addl_hdrs &= ~(ICE_FLOW_SEG_HDR_ESP | ICE_FLOW_SEG_HDR_UDP);
 661		*addl_hdrs |= ICE_FLOW_SEG_HDR_NAT_T_ESP;
 662		*hash_flds &= ~(BIT_ULL(ICE_FLOW_FIELD_IDX_ESP_SPI));
 663		*hash_flds |= BIT_ULL(ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI);
 664	}
 665
 666	/* refine hash hdrs for L4 udp/tcp/sctp. */
 667	if (*addl_hdrs & (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP |
 668			  ICE_FLOW_SEG_HDR_SCTP) &&
 669	    *addl_hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)
 670		*addl_hdrs &= ~ICE_FLOW_SEG_HDR_IPV_OTHER;
 671
 672	return true;
 673}
 674
 675/**
 676 * ice_vf_adv_rss_offload_ena - determine if capabilities support advanced
 677 * RSS offloads
 678 * @caps: VF driver negotiated capabilities
 679 *
 680 * Return true if VIRTCHNL_VF_OFFLOAD_ADV_RSS_PF capability is set,
 681 * else return false
 682 */
 683static bool ice_vf_adv_rss_offload_ena(u32 caps)
 684{
 685	return !!(caps & VIRTCHNL_VF_OFFLOAD_ADV_RSS_PF);
 686}
 687
 688/**
 689 * ice_is_hash_cfg_valid - Check whether an RSS hash context is valid
 690 * @cfg: RSS hash configuration to test
 691 *
 692 * Return: true if both @cfg->hash_flds and @cfg->addl_hdrs are non-zero; false otherwise.
 693 */
 694static bool ice_is_hash_cfg_valid(struct ice_rss_hash_cfg *cfg)
 695{
 696	return cfg->hash_flds && cfg->addl_hdrs;
 697}
 698
 699/**
 700 * ice_hash_cfg_reset - Reset an RSS hash context
 701 * @cfg: RSS hash configuration to reset
 702 *
 703 * Reset fields of @cfg that store the active rule information.
 704 */
 705static void ice_hash_cfg_reset(struct ice_rss_hash_cfg *cfg)
 706{
 707	cfg->hash_flds = 0;
 708	cfg->addl_hdrs = 0;
 709	cfg->hdr_type = ICE_RSS_OUTER_HEADERS;
 710	cfg->symm = 0;
 711}
 712
 713/**
 714 * ice_hash_cfg_record - Record an RSS hash context
 715 * @ctx: destination (global) RSS hash configuration
 716 * @cfg: source RSS hash configuration to record
 717 *
 718 * Copy the active rule information from @cfg into @ctx.
 719 */
 720static void ice_hash_cfg_record(struct ice_rss_hash_cfg *ctx,
 721				struct ice_rss_hash_cfg *cfg)
 722{
 723	ctx->hash_flds = cfg->hash_flds;
 724	ctx->addl_hdrs = cfg->addl_hdrs;
 725	ctx->hdr_type = cfg->hdr_type;
 726	ctx->symm = cfg->symm;
 727}
 728
 729/**
 730 * ice_hash_moveout - Delete an RSS configuration (keep context)
 731 * @vf: VF pointer
 732 * @cfg: RSS hash configuration
 733 *
 734 * Return: 0 on success (including when already absent); -ENOENT if @cfg is
 735 * invalid or VSI is missing; -EBUSY on hardware removal failure.
 736 */
 737static int
 738ice_hash_moveout(struct ice_vf *vf, struct ice_rss_hash_cfg *cfg)
 739{
 740	struct device *dev = ice_pf_to_dev(vf->pf);
 741	struct ice_vsi *vsi = ice_get_vf_vsi(vf);
 742	struct ice_hw *hw = &vf->pf->hw;
 743	int ret;
 744
 745	if (!ice_is_hash_cfg_valid(cfg) || !vsi)
 746		return -ENOENT;
 747
 748	ret = ice_rem_rss_cfg(hw, vsi->idx, cfg);
 749	if (ret && ret != -ENOENT) {
 750		dev_err(dev, "ice_rem_rss_cfg failed for VF %d, VSI %d, error:%d\n",
 751			vf->vf_id, vf->lan_vsi_idx, ret);
 752		return -EBUSY;
 753	}
 754
 755	return 0;
 756}
 757
 758/**
 759 * ice_hash_moveback - Add an RSS hash configuration for a VF
 760 * @vf: VF pointer
 761 * @cfg: RSS hash configuration to apply
 762 *
 763 * Add @cfg to @vf if the context is valid and VSI exists; programs HW.
 764 *
 765 * Return:
 766 * * 0 on success
 767 * * -ENOENT if @cfg is invalid or VSI is missing
 768 * * -EBUSY if hardware programming fails
 769 */
 770static int
 771ice_hash_moveback(struct ice_vf *vf, struct ice_rss_hash_cfg *cfg)
 772{
 773	struct device *dev = ice_pf_to_dev(vf->pf);
 774	struct ice_vsi *vsi = ice_get_vf_vsi(vf);
 775	struct ice_hw *hw = &vf->pf->hw;
 776	int ret;
 777
 778	if (!ice_is_hash_cfg_valid(cfg) || !vsi)
 779		return -ENOENT;
 780
 781	ret = ice_add_rss_cfg(hw, vsi, cfg);
 782	if (ret) {
 783		dev_err(dev, "ice_add_rss_cfg failed for VF %d, VSI %d, error:%d\n",
 784			vf->vf_id, vf->lan_vsi_idx, ret);
 785		return -EBUSY;
 786	}
 787
 788	return 0;
 789}
 790
 791/**
 792 * ice_hash_remove - remove a RSS configuration
 793 * @vf: pointer to the VF info
 794 * @cfg: pointer to the RSS hash configuration
 795 *
 796 * This function will delete a RSS hash configuration and also delete the
 797 * hash context which stores the rule info.
 798 *
 799 * Return: 0 on success, or a negative error code on failure.
 800 */
 801static int
 802ice_hash_remove(struct ice_vf *vf, struct ice_rss_hash_cfg *cfg)
 803{
 804	int ret;
 805
 806	ret = ice_hash_moveout(vf, cfg);
 807	if (ret && ret != -ENOENT)
 808		return ret;
 809
 810	ice_hash_cfg_reset(cfg);
 811
 812	return 0;
 813}
 814
 815struct ice_gtpu_ctx_action {
 816	u32 ctx_idx;
 817	const u32 *remove_list;
 818	int remove_count;
 819	const u32 *moveout_list;
 820	int moveout_count;
 821};
 822
 823/**
 824 * ice_add_rss_cfg_pre_gtpu - Pre-process the GTPU RSS configuration
 825 * @vf: pointer to the VF info
 826 * @ctx: pointer to the context of the GTPU hash
 827 * @ctx_idx: index of the hash context
 828 *
 829 * Pre-processes the GTPU hash configuration before adding a new
 830 * hash context. It removes or reorders existing hash configurations that may
 831 * conflict with the new one. For example, if a GTPU_UP or GTPU_DWN rule is
 832 * configured after a GTPU_EH rule, the GTPU_EH hash will be matched first due
 833 * to TCAM write and match order (top-down). In such cases, the GTPU_EH rule
 834 * must be moved after the GTPU_UP/DWN rule. Conversely, if a GTPU_EH rule is
 835 * configured after a GTPU_UP/DWN rule, the UP/DWN rules should be removed to
 836 * avoid conflict.
 837 *
 838 * Return: 0 on success or a negative error code on failure
 839 */
 840static int ice_add_rss_cfg_pre_gtpu(struct ice_vf *vf,
 841				    struct ice_vf_hash_gtpu_ctx *ctx,
 842				    u32 ctx_idx)
 843{
 844	int ret, i;
 845
 846	static const u32 remove_eh_ip[] = {
 847		ICE_HASH_GTPU_CTX_EH_IP_UDP, ICE_HASH_GTPU_CTX_EH_IP_TCP,
 848		ICE_HASH_GTPU_CTX_UP_IP,     ICE_HASH_GTPU_CTX_UP_IP_UDP,
 849		ICE_HASH_GTPU_CTX_UP_IP_TCP, ICE_HASH_GTPU_CTX_DW_IP,
 850		ICE_HASH_GTPU_CTX_DW_IP_UDP, ICE_HASH_GTPU_CTX_DW_IP_TCP,
 851	};
 852
 853	static const u32 remove_eh_ip_udp[] = {
 854		ICE_HASH_GTPU_CTX_UP_IP_UDP,
 855		ICE_HASH_GTPU_CTX_DW_IP_UDP,
 856	};
 857	static const u32 moveout_eh_ip_udp[] = {
 858		ICE_HASH_GTPU_CTX_UP_IP,
 859		ICE_HASH_GTPU_CTX_UP_IP_TCP,
 860		ICE_HASH_GTPU_CTX_DW_IP,
 861		ICE_HASH_GTPU_CTX_DW_IP_TCP,
 862	};
 863
 864	static const u32 remove_eh_ip_tcp[] = {
 865		ICE_HASH_GTPU_CTX_UP_IP_TCP,
 866		ICE_HASH_GTPU_CTX_DW_IP_TCP,
 867	};
 868	static const u32 moveout_eh_ip_tcp[] = {
 869		ICE_HASH_GTPU_CTX_UP_IP,
 870		ICE_HASH_GTPU_CTX_UP_IP_UDP,
 871		ICE_HASH_GTPU_CTX_DW_IP,
 872		ICE_HASH_GTPU_CTX_DW_IP_UDP,
 873	};
 874
 875	static const u32 remove_up_ip[] = {
 876		ICE_HASH_GTPU_CTX_UP_IP_UDP,
 877		ICE_HASH_GTPU_CTX_UP_IP_TCP,
 878	};
 879	static const u32 moveout_up_ip[] = {
 880		ICE_HASH_GTPU_CTX_EH_IP,
 881		ICE_HASH_GTPU_CTX_EH_IP_UDP,
 882		ICE_HASH_GTPU_CTX_EH_IP_TCP,
 883	};
 884
 885	static const u32 moveout_up_ip_udp_tcp[] = {
 886		ICE_HASH_GTPU_CTX_EH_IP,
 887		ICE_HASH_GTPU_CTX_EH_IP_UDP,
 888		ICE_HASH_GTPU_CTX_EH_IP_TCP,
 889	};
 890
 891	static const u32 remove_dw_ip[] = {
 892		ICE_HASH_GTPU_CTX_DW_IP_UDP,
 893		ICE_HASH_GTPU_CTX_DW_IP_TCP,
 894	};
 895	static const u32 moveout_dw_ip[] = {
 896		ICE_HASH_GTPU_CTX_EH_IP,
 897		ICE_HASH_GTPU_CTX_EH_IP_UDP,
 898		ICE_HASH_GTPU_CTX_EH_IP_TCP,
 899	};
 900
 901	static const struct ice_gtpu_ctx_action actions[] = {
 902		{ ICE_HASH_GTPU_CTX_EH_IP, remove_eh_ip,
 903		  ARRAY_SIZE(remove_eh_ip), NULL, 0 },
 904		{ ICE_HASH_GTPU_CTX_EH_IP_UDP, remove_eh_ip_udp,
 905		  ARRAY_SIZE(remove_eh_ip_udp), moveout_eh_ip_udp,
 906		  ARRAY_SIZE(moveout_eh_ip_udp) },
 907		{ ICE_HASH_GTPU_CTX_EH_IP_TCP, remove_eh_ip_tcp,
 908		  ARRAY_SIZE(remove_eh_ip_tcp), moveout_eh_ip_tcp,
 909		  ARRAY_SIZE(moveout_eh_ip_tcp) },
 910		{ ICE_HASH_GTPU_CTX_UP_IP, remove_up_ip,
 911		  ARRAY_SIZE(remove_up_ip), moveout_up_ip,
 912		  ARRAY_SIZE(moveout_up_ip) },
 913		{ ICE_HASH_GTPU_CTX_UP_IP_UDP, NULL, 0, moveout_up_ip_udp_tcp,
 914		  ARRAY_SIZE(moveout_up_ip_udp_tcp) },
 915		{ ICE_HASH_GTPU_CTX_UP_IP_TCP, NULL, 0, moveout_up_ip_udp_tcp,
 916		  ARRAY_SIZE(moveout_up_ip_udp_tcp) },
 917		{ ICE_HASH_GTPU_CTX_DW_IP, remove_dw_ip,
 918		  ARRAY_SIZE(remove_dw_ip), moveout_dw_ip,
 919		  ARRAY_SIZE(moveout_dw_ip) },
 920		{ ICE_HASH_GTPU_CTX_DW_IP_UDP, NULL, 0, moveout_dw_ip,
 921		  ARRAY_SIZE(moveout_dw_ip) },
 922		{ ICE_HASH_GTPU_CTX_DW_IP_TCP, NULL, 0, moveout_dw_ip,
 923		  ARRAY_SIZE(moveout_dw_ip) },
 924	};
 925
 926	for (i = 0; i < ARRAY_SIZE(actions); i++) {
 927		if (actions[i].ctx_idx != ctx_idx)
 928			continue;
 929
 930		if (actions[i].remove_list) {
 931			for (int j = 0; j < actions[i].remove_count; j++) {
 932				u16 rm = actions[i].remove_list[j];
 933
 934				ret = ice_hash_remove(vf, &ctx->ctx[rm]);
 935				if (ret && ret != -ENOENT)
 936					return ret;
 937			}
 938		}
 939
 940		if (actions[i].moveout_list) {
 941			for (int j = 0; j < actions[i].moveout_count; j++) {
 942				u16 mv = actions[i].moveout_list[j];
 943
 944				ret = ice_hash_moveout(vf, &ctx->ctx[mv]);
 945				if (ret && ret != -ENOENT)
 946					return ret;
 947			}
 948		}
 949		break;
 950	}
 951
 952	return 0;
 953}
 954
 955/**
 956 * ice_add_rss_cfg_pre_ip - Pre-process IP-layer RSS configuration
 957 * @vf: VF pointer
 958 * @ctx: IP L4 hash context (ESP/UDP-ESP/AH/PFCP and UDP/TCP/SCTP)
 959 *
 960 * Remove covered/recorded IP RSS configurations prior to adding a new one.
 961 *
 962 * Return: 0 on success; negative error code on failure.
 963 */
 964static int
 965ice_add_rss_cfg_pre_ip(struct ice_vf *vf, struct ice_vf_hash_ip_ctx *ctx)
 966{
 967	int i, ret;
 968
 969	for (i = 1; i < ICE_HASH_IP_CTX_MAX; i++)
 970		if (ice_is_hash_cfg_valid(&ctx->ctx[i])) {
 971			ret = ice_hash_remove(vf, &ctx->ctx[i]);
 972			if (ret)
 973				return ret;
 974		}
 975
 976	return 0;
 977}
 978
 979/**
 980 * ice_calc_gtpu_ctx_idx - Calculate GTPU hash context index
 981 * @hdrs: Bitmask of protocol headers prefixed with ICE_FLOW_SEG_HDR_*
 982 *
 983 * Determine the GTPU hash context index based on the combination of
 984 * encapsulation headers (GTPU_EH, GTPU_UP, GTPU_DWN) and transport
 985 * protocols (UDP, TCP) within IPv4 or IPv6 flows.
 986 *
 987 * Return: A valid context index (0-8) if the header combination is supported,
 988 *         or ICE_HASH_GTPU_CTX_MAX if the combination is invalid.
 989 */
 990static enum ice_hash_gtpu_ctx_type ice_calc_gtpu_ctx_idx(u32 hdrs)
 991{
 992	u32 eh_idx, ip_idx;
 993
 994	if (hdrs & ICE_FLOW_SEG_HDR_GTPU_EH)
 995		eh_idx = 0;
 996	else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_UP)
 997		eh_idx = 1;
 998	else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_DWN)
 999		eh_idx = 2;
1000	else
1001		return ICE_HASH_GTPU_CTX_MAX;
1002
1003	ip_idx = 0;
1004	if (hdrs & ICE_FLOW_SEG_HDR_UDP)
1005		ip_idx = 1;
1006	else if (hdrs & ICE_FLOW_SEG_HDR_TCP)
1007		ip_idx = 2;
1008
1009	if (hdrs & (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6))
1010		return eh_idx * 3 + ip_idx;
1011	else
1012		return ICE_HASH_GTPU_CTX_MAX;
1013}
1014
1015/**
1016 * ice_map_ip_ctx_idx - map the index of the IP L4 hash context
1017 * @hdrs: protocol headers prefix with ICE_FLOW_SEG_HDR_XXX.
1018 *
1019 * The IP L4 hash context use the index to classify for IPv4/IPv6 with
1020 * ESP/UDP_ESP/AH/PFCP and non-tunnel UDP/TCP/SCTP
1021 * this function map the index based on the protocol headers.
1022 *
1023 * Return: The mapped IP context index on success, or ICE_HASH_IP_CTX_MAX
1024 *         if no matching context is found.
1025 */
1026static u8 ice_map_ip_ctx_idx(u32 hdrs)
1027{
1028	u8 i;
1029
1030	static struct {
1031		u32 hdrs;
1032		u8 ctx_idx;
1033	} ip_ctx_idx_map[] = {
1034		{ ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV_OTHER |
1035			ICE_FLOW_SEG_HDR_ESP,
1036			ICE_HASH_IP_CTX_IP_ESP },
1037		{ ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV_OTHER |
1038			ICE_FLOW_SEG_HDR_NAT_T_ESP,
1039			ICE_HASH_IP_CTX_IP_UDP_ESP },
1040		{ ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV_OTHER |
1041			ICE_FLOW_SEG_HDR_AH,
1042			ICE_HASH_IP_CTX_IP_AH },
1043		{ ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV_OTHER |
1044			ICE_FLOW_SEG_HDR_PFCP_SESSION,
1045			ICE_HASH_IP_CTX_IP_PFCP },
1046		{ ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN |
1047			ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_UDP,
1048			ICE_HASH_IP_CTX_IP_UDP },
1049		{ ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN |
1050			ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_TCP,
1051			ICE_HASH_IP_CTX_IP_TCP },
1052		{ ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN |
1053			ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_SCTP,
1054			ICE_HASH_IP_CTX_IP_SCTP },
1055		{ ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN |
1056			ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV_OTHER,
1057			ICE_HASH_IP_CTX_IP },
1058		{ ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_IPV_OTHER |
1059			ICE_FLOW_SEG_HDR_ESP,
1060			ICE_HASH_IP_CTX_IP_ESP },
1061		{ ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_IPV_OTHER |
1062			ICE_FLOW_SEG_HDR_NAT_T_ESP,
1063			ICE_HASH_IP_CTX_IP_UDP_ESP },
1064		{ ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_IPV_OTHER |
1065			ICE_FLOW_SEG_HDR_AH,
1066			ICE_HASH_IP_CTX_IP_AH },
1067		{ ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_IPV_OTHER |
1068			ICE_FLOW_SEG_HDR_PFCP_SESSION,
1069			ICE_HASH_IP_CTX_IP_PFCP },
1070		{ ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN |
1071			ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_UDP,
1072			ICE_HASH_IP_CTX_IP_UDP },
1073		{ ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN |
1074			ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_TCP,
1075			ICE_HASH_IP_CTX_IP_TCP },
1076		{ ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN |
1077			ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_SCTP,
1078			ICE_HASH_IP_CTX_IP_SCTP },
1079		{ ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN |
1080			ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_IPV_OTHER,
1081			ICE_HASH_IP_CTX_IP },
1082		/* the remaining mappings are used for default RSS */
1083		{ ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_UDP,
1084			ICE_HASH_IP_CTX_IP_UDP },
1085		{ ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_TCP,
1086			ICE_HASH_IP_CTX_IP_TCP },
1087		{ ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_SCTP,
1088			ICE_HASH_IP_CTX_IP_SCTP },
1089		{ ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV_OTHER,
1090			ICE_HASH_IP_CTX_IP },
1091		{ ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_UDP,
1092			ICE_HASH_IP_CTX_IP_UDP },
1093		{ ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_TCP,
1094			ICE_HASH_IP_CTX_IP_TCP },
1095		{ ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_SCTP,
1096			ICE_HASH_IP_CTX_IP_SCTP },
1097		{ ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_IPV_OTHER,
1098			ICE_HASH_IP_CTX_IP },
1099	};
1100
1101	for (i = 0; i < ARRAY_SIZE(ip_ctx_idx_map); i++) {
1102		if (hdrs == ip_ctx_idx_map[i].hdrs)
1103			return ip_ctx_idx_map[i].ctx_idx;
1104	}
1105
1106	return ICE_HASH_IP_CTX_MAX;
1107}
1108
1109/**
1110 * ice_add_rss_cfg_pre - Prepare RSS configuration context for a VF
1111 * @vf: pointer to the VF structure
1112 * @cfg: pointer to the RSS hash configuration
1113 *
1114 * Prepare the RSS hash context for a given VF based on the additional
1115 * protocol headers specified in @cfg. This includes pre-configuration
1116 * for IP and GTPU-based flows.
1117 *
1118 * If the configuration matches a known IP context, the function sets up
1119 * the appropriate IP hash context. If the configuration includes GTPU
1120 * headers, it prepares the GTPU-specific context accordingly.
1121 *
1122 * Return: 0 on success, or a negative error code on failure.
1123 */
1124static int
1125ice_add_rss_cfg_pre(struct ice_vf *vf, struct ice_rss_hash_cfg *cfg)
1126{
1127	u32 ice_gtpu_ctx_idx = ice_calc_gtpu_ctx_idx(cfg->addl_hdrs);
1128	u8 ip_ctx_idx = ice_map_ip_ctx_idx(cfg->addl_hdrs);
1129
1130	if (ip_ctx_idx == ICE_HASH_IP_CTX_IP) {
1131		int ret = 0;
1132
1133		if (cfg->addl_hdrs & ICE_FLOW_SEG_HDR_IPV4)
1134			ret = ice_add_rss_cfg_pre_ip(vf, &vf->hash_ctx.v4);
1135		else if (cfg->addl_hdrs & ICE_FLOW_SEG_HDR_IPV6)
1136			ret = ice_add_rss_cfg_pre_ip(vf, &vf->hash_ctx.v6);
1137
1138		if (ret)
1139			return ret;
1140	}
1141
1142	if (cfg->addl_hdrs & ICE_FLOW_SEG_HDR_IPV4) {
1143		return ice_add_rss_cfg_pre_gtpu(vf, &vf->hash_ctx.ipv4,
1144						ice_gtpu_ctx_idx);
1145	} else if (cfg->addl_hdrs & ICE_FLOW_SEG_HDR_IPV6) {
1146		return ice_add_rss_cfg_pre_gtpu(vf, &vf->hash_ctx.ipv6,
1147						ice_gtpu_ctx_idx);
1148	}
1149
1150	return 0;
1151}
1152
1153/**
1154 * ice_add_rss_cfg_post_gtpu - Post-process GTPU RSS configuration
1155 * @vf: pointer to the VF info
1156 * @ctx: pointer to the context of the GTPU hash
1157 * @cfg: pointer to the RSS hash configuration
1158 * @ctx_idx: index of the hash context
1159 *
1160 * Post-processes the GTPU hash configuration after a new hash
1161 * context has been successfully added. It updates the context with the new
1162 * configuration and restores any previously removed hash contexts that need
1163 * to be re-applied. This ensures proper TCAM rule ordering and avoids
1164 * conflicts between overlapping GTPU rules.
1165 *
1166 * Return: 0 on success or a negative error code on failure
1167 */
1168static int ice_add_rss_cfg_post_gtpu(struct ice_vf *vf,
1169				     struct ice_vf_hash_gtpu_ctx *ctx,
1170				     struct ice_rss_hash_cfg *cfg, u32 ctx_idx)
1171{
1172	/* GTPU hash moveback lookup table indexed by context ID.
1173	 * Each entry is a bitmap indicating which contexts need moveback
1174	 * operations when the corresponding context index is processed.
1175	 */
1176	static const unsigned long
1177		ice_gtpu_moveback_tbl[ICE_HASH_GTPU_CTX_MAX] = {
1178			[ICE_HASH_GTPU_CTX_EH_IP] = 0,
1179			[ICE_HASH_GTPU_CTX_EH_IP_UDP] =
1180				BIT(ICE_HASH_GTPU_CTX_UP_IP) |
1181				BIT(ICE_HASH_GTPU_CTX_UP_IP_TCP) |
1182				BIT(ICE_HASH_GTPU_CTX_DW_IP) |
1183				BIT(ICE_HASH_GTPU_CTX_DW_IP_TCP),
1184			[ICE_HASH_GTPU_CTX_EH_IP_TCP] =
1185				BIT(ICE_HASH_GTPU_CTX_UP_IP) |
1186				BIT(ICE_HASH_GTPU_CTX_UP_IP_UDP) |
1187				BIT(ICE_HASH_GTPU_CTX_DW_IP) |
1188				BIT(ICE_HASH_GTPU_CTX_DW_IP_UDP),
1189			[ICE_HASH_GTPU_CTX_UP_IP] =
1190				BIT(ICE_HASH_GTPU_CTX_EH_IP) |
1191				BIT(ICE_HASH_GTPU_CTX_EH_IP_UDP) |
1192				BIT(ICE_HASH_GTPU_CTX_EH_IP_TCP),
1193			[ICE_HASH_GTPU_CTX_UP_IP_UDP] =
1194				BIT(ICE_HASH_GTPU_CTX_EH_IP) |
1195				BIT(ICE_HASH_GTPU_CTX_EH_IP_UDP) |
1196				BIT(ICE_HASH_GTPU_CTX_EH_IP_TCP),
1197			[ICE_HASH_GTPU_CTX_UP_IP_TCP] =
1198				BIT(ICE_HASH_GTPU_CTX_EH_IP) |
1199				BIT(ICE_HASH_GTPU_CTX_EH_IP_UDP) |
1200				BIT(ICE_HASH_GTPU_CTX_EH_IP_TCP),
1201			[ICE_HASH_GTPU_CTX_DW_IP] =
1202				BIT(ICE_HASH_GTPU_CTX_EH_IP) |
1203				BIT(ICE_HASH_GTPU_CTX_EH_IP_UDP) |
1204				BIT(ICE_HASH_GTPU_CTX_EH_IP_TCP),
1205			[ICE_HASH_GTPU_CTX_DW_IP_UDP] =
1206				BIT(ICE_HASH_GTPU_CTX_EH_IP) |
1207				BIT(ICE_HASH_GTPU_CTX_EH_IP_UDP) |
1208				BIT(ICE_HASH_GTPU_CTX_EH_IP_TCP),
1209			[ICE_HASH_GTPU_CTX_DW_IP_TCP] =
1210				BIT(ICE_HASH_GTPU_CTX_EH_IP) |
1211				BIT(ICE_HASH_GTPU_CTX_EH_IP_UDP) |
1212				BIT(ICE_HASH_GTPU_CTX_EH_IP_TCP),
1213		};
1214	unsigned long moveback_mask;
1215	int ret;
1216	int i;
1217
1218	if (unlikely(ctx_idx >= ICE_HASH_GTPU_CTX_MAX))
1219		return 0;
1220
1221	ctx->ctx[ctx_idx].addl_hdrs = cfg->addl_hdrs;
1222	ctx->ctx[ctx_idx].hash_flds = cfg->hash_flds;
1223	ctx->ctx[ctx_idx].hdr_type = cfg->hdr_type;
1224	ctx->ctx[ctx_idx].symm = cfg->symm;
1225
1226	moveback_mask = ice_gtpu_moveback_tbl[ctx_idx];
1227	for_each_set_bit(i, &moveback_mask, ICE_HASH_GTPU_CTX_MAX) {
1228		ret = ice_hash_moveback(vf, &ctx->ctx[i]);
1229		if (ret && ret != -ENOENT)
1230			return ret;
1231	}
1232
1233	return 0;
1234}
1235
1236static int
1237ice_add_rss_cfg_post(struct ice_vf *vf, struct ice_rss_hash_cfg *cfg)
1238{
1239	u32 ice_gtpu_ctx_idx = ice_calc_gtpu_ctx_idx(cfg->addl_hdrs);
1240	u8 ip_ctx_idx = ice_map_ip_ctx_idx(cfg->addl_hdrs);
1241
1242	if (ip_ctx_idx && ip_ctx_idx < ICE_HASH_IP_CTX_MAX) {
1243		if (cfg->addl_hdrs & ICE_FLOW_SEG_HDR_IPV4)
1244			ice_hash_cfg_record(&vf->hash_ctx.v4.ctx[ip_ctx_idx], cfg);
1245		else if (cfg->addl_hdrs & ICE_FLOW_SEG_HDR_IPV6)
1246			ice_hash_cfg_record(&vf->hash_ctx.v6.ctx[ip_ctx_idx], cfg);
1247	}
1248
1249	if (cfg->addl_hdrs & ICE_FLOW_SEG_HDR_IPV4) {
1250		return ice_add_rss_cfg_post_gtpu(vf, &vf->hash_ctx.ipv4,
1251						 cfg, ice_gtpu_ctx_idx);
1252	} else if (cfg->addl_hdrs & ICE_FLOW_SEG_HDR_IPV6) {
1253		return ice_add_rss_cfg_post_gtpu(vf, &vf->hash_ctx.ipv6,
1254						 cfg, ice_gtpu_ctx_idx);
1255	}
1256
1257	return 0;
1258}
1259
1260/**
1261 * ice_rem_rss_cfg_post - post-process the RSS configuration
1262 * @vf: pointer to the VF info
1263 * @cfg: pointer to the RSS hash configuration
1264 *
1265 * Post process the RSS hash configuration after deleting a hash
1266 * config. Such as, it will reset the hash context for the GTPU hash.
1267 */
1268static void
1269ice_rem_rss_cfg_post(struct ice_vf *vf, struct ice_rss_hash_cfg *cfg)
1270{
1271	u32 ice_gtpu_ctx_idx = ice_calc_gtpu_ctx_idx(cfg->addl_hdrs);
1272	u8 ip_ctx_idx = ice_map_ip_ctx_idx(cfg->addl_hdrs);
1273
1274	if (ip_ctx_idx && ip_ctx_idx < ICE_HASH_IP_CTX_MAX) {
1275		if (cfg->addl_hdrs & ICE_FLOW_SEG_HDR_IPV4)
1276			ice_hash_cfg_reset(&vf->hash_ctx.v4.ctx[ip_ctx_idx]);
1277		else if (cfg->addl_hdrs & ICE_FLOW_SEG_HDR_IPV6)
1278			ice_hash_cfg_reset(&vf->hash_ctx.v6.ctx[ip_ctx_idx]);
1279	}
1280
1281	if (ice_gtpu_ctx_idx >= ICE_HASH_GTPU_CTX_MAX)
1282		return;
1283
1284	if (cfg->addl_hdrs & ICE_FLOW_SEG_HDR_IPV4)
1285		ice_hash_cfg_reset(&vf->hash_ctx.ipv4.ctx[ice_gtpu_ctx_idx]);
1286	else if (cfg->addl_hdrs & ICE_FLOW_SEG_HDR_IPV6)
1287		ice_hash_cfg_reset(&vf->hash_ctx.ipv6.ctx[ice_gtpu_ctx_idx]);
1288}
1289
1290/**
1291 * ice_rem_rss_cfg_wrap - Wrapper for deleting an RSS configuration
1292 * @vf: pointer to the VF info
1293 * @cfg: pointer to the RSS hash configuration
1294 *
1295 * Wrapper function to delete a flow profile base on an RSS configuration,
1296 * and also post process the hash context base on the rollback mechanism
1297 * which handle some rules conflict by ice_add_rss_cfg_wrap.
1298 *
1299 * Return: 0 on success; negative error code on failure.
1300 */
1301static int
1302ice_rem_rss_cfg_wrap(struct ice_vf *vf, struct ice_rss_hash_cfg *cfg)
1303{
1304	struct device *dev = ice_pf_to_dev(vf->pf);
1305	struct ice_vsi *vsi = ice_get_vf_vsi(vf);
1306	struct ice_hw *hw = &vf->pf->hw;
1307	int ret;
1308
1309	ret = ice_rem_rss_cfg(hw, vsi->idx, cfg);
1310	/* We just ignore -ENOENT, because if two configurations share the same
1311	 * profile remove one of them actually removes both, since the
1312	 * profile is deleted.
1313	 */
1314	if (ret && ret != -ENOENT) {
1315		dev_err(dev, "ice_rem_rss_cfg failed for VF %d, VSI %d, error:%d\n",
1316			vf->vf_id, vf->lan_vsi_idx, ret);
1317		return ret;
1318	}
1319
1320	ice_rem_rss_cfg_post(vf, cfg);
1321
1322	return 0;
1323}
1324
1325/**
1326 * ice_add_rss_cfg_wrap - Wrapper for adding an RSS configuration
1327 * @vf: pointer to the VF info
1328 * @cfg: pointer to the RSS hash configuration
1329 *
1330 * Add a flow profile based on an RSS configuration. Use a rollback
1331 * mechanism to handle rule conflicts due to TCAM
1332 * write sequence from top to down.
1333 *
1334 * Return: 0 on success; negative error code on failure.
1335 */
1336static int
1337ice_add_rss_cfg_wrap(struct ice_vf *vf, struct ice_rss_hash_cfg *cfg)
1338{
1339	struct device *dev = ice_pf_to_dev(vf->pf);
1340	struct ice_vsi *vsi = ice_get_vf_vsi(vf);
1341	struct ice_hw *hw = &vf->pf->hw;
1342	int ret;
1343
1344	if (ice_add_rss_cfg_pre(vf, cfg))
1345		return -EINVAL;
1346
1347	ret = ice_add_rss_cfg(hw, vsi, cfg);
1348	if (ret) {
1349		dev_err(dev, "ice_add_rss_cfg failed for VF %d, VSI %d, error:%d\n",
1350			vf->vf_id, vf->lan_vsi_idx, ret);
1351		return ret;
1352	}
1353
1354	if (ice_add_rss_cfg_post(vf, cfg))
1355		ret = -EINVAL;
1356
1357	return ret;
1358}
1359
1360/**
1361 * ice_parse_raw_rss_pattern - Parse raw pattern spec and mask for RSS
1362 * @vf: pointer to the VF info
1363 * @proto: pointer to the virtchnl protocol header
1364 * @raw_cfg: pointer to the RSS raw pattern configuration
1365 *
1366 * Parser function to get spec and mask from virtchnl message, and parse
1367 * them to get the corresponding profile and offset. The profile is used
1368 * to add RSS configuration.
1369 *
1370 * Return: 0 on success; negative error code on failure.
1371 */
1372static int
1373ice_parse_raw_rss_pattern(struct ice_vf *vf, struct virtchnl_proto_hdrs *proto,
1374			  struct ice_rss_raw_cfg *raw_cfg)
1375{
1376	struct ice_parser_result pkt_parsed;
1377	struct ice_hw *hw = &vf->pf->hw;
1378	struct ice_parser_profile prof;
1379	struct ice_parser *psr;
1380	u8 *pkt_buf, *msk_buf;
1381	u16 pkt_len;
1382	int ret = 0;
1383
1384	pkt_len = proto->raw.pkt_len;
1385	if (!pkt_len)
1386		return -EINVAL;
1387	if (pkt_len > VIRTCHNL_MAX_SIZE_RAW_PACKET)
1388		pkt_len = VIRTCHNL_MAX_SIZE_RAW_PACKET;
1389
1390	pkt_buf = kzalloc(pkt_len, GFP_KERNEL);
1391	msk_buf = kzalloc(pkt_len, GFP_KERNEL);
1392	if (!pkt_buf || !msk_buf) {
1393		ret = -ENOMEM;
1394		goto free_alloc;
1395	}
1396
1397	memcpy(pkt_buf, proto->raw.spec, pkt_len);
1398	memcpy(msk_buf, proto->raw.mask, pkt_len);
1399
1400	psr = ice_parser_create(hw);
1401	if (IS_ERR(psr)) {
1402		ret = PTR_ERR(psr);
1403		goto free_alloc;
1404	}
1405
1406	ret = ice_parser_run(psr, pkt_buf, pkt_len, &pkt_parsed);
1407	if (ret)
1408		goto parser_destroy;
1409
1410	ret = ice_parser_profile_init(&pkt_parsed, pkt_buf, msk_buf,
1411				      pkt_len, ICE_BLK_RSS, &prof);
1412	if (ret)
1413		goto parser_destroy;
1414
1415	memcpy(&raw_cfg->prof, &prof, sizeof(prof));
1416
1417parser_destroy:
1418	ice_parser_destroy(psr);
1419free_alloc:
1420	kfree(pkt_buf);
1421	kfree(msk_buf);
1422	return ret;
1423}
1424
1425/**
1426 * ice_add_raw_rss_cfg - add RSS configuration for raw pattern
1427 * @vf: pointer to the VF info
1428 * @cfg: pointer to the RSS raw pattern configuration
1429 *
1430 * This function adds the RSS configuration for raw pattern.
1431 * Check if current profile is matched. If not, remove the old
1432 * one and add the new profile to HW directly. Update the symmetric
1433 * hash configuration as well.
1434 *
1435 * Return: 0 on success; negative error code on failure.
1436 */
1437static int
1438ice_add_raw_rss_cfg(struct ice_vf *vf, struct ice_rss_raw_cfg *cfg)
1439{
1440	struct ice_parser_profile *prof = &cfg->prof;
1441	struct device *dev = ice_pf_to_dev(vf->pf);
1442	struct ice_rss_prof_info *rss_prof;
1443	struct ice_hw *hw = &vf->pf->hw;
1444	int i, ptg, ret = 0;
1445	u16 vsi_handle;
1446	u64 id;
1447
1448	vsi_handle = vf->lan_vsi_idx;
1449	id = find_first_bit(prof->ptypes, ICE_FLOW_PTYPE_MAX);
1450
1451	ptg = hw->blk[ICE_BLK_RSS].xlt1.t[id];
1452	rss_prof = &vf->rss_prof_info[ptg];
1453
1454	/* check if ptg already has a profile */
1455	if (rss_prof->prof.fv_num) {
1456		for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
1457			if (rss_prof->prof.fv[i].proto_id !=
1458			    prof->fv[i].proto_id ||
1459			    rss_prof->prof.fv[i].offset !=
1460			    prof->fv[i].offset)
1461				break;
1462		}
1463
1464		/* current profile is matched, check symmetric hash */
1465		if (i == ICE_MAX_FV_WORDS) {
1466			if (rss_prof->symm != cfg->symm)
1467				goto update_symm;
1468			return ret;
1469		}
1470
1471		/* current profile is not matched, remove it */
1472		ret =
1473		ice_rem_prof_id_flow(hw, ICE_BLK_RSS,
1474				     ice_get_hw_vsi_num(hw, vsi_handle),
1475				     id);
1476		if (ret) {
1477			dev_err(dev, "remove RSS flow failed\n");
1478			return ret;
1479		}
1480
1481		ret = ice_rem_prof(hw, ICE_BLK_RSS, id);
1482		if (ret) {
1483			dev_err(dev, "remove RSS profile failed\n");
1484			return ret;
1485		}
1486	}
1487
1488	/* add new profile */
1489	ret = ice_flow_set_parser_prof(hw, vsi_handle, 0, prof, ICE_BLK_RSS);
1490	if (ret) {
1491		dev_err(dev, "HW profile add failed\n");
1492		return ret;
1493	}
1494
1495	memcpy(&rss_prof->prof, prof, sizeof(struct ice_parser_profile));
1496
1497update_symm:
1498	rss_prof->symm = cfg->symm;
1499	ice_rss_update_raw_symm(hw, cfg, id);
1500	return ret;
1501}
1502
1503/**
1504 * ice_rem_raw_rss_cfg - remove RSS configuration for raw pattern
1505 * @vf: pointer to the VF info
1506 * @cfg: pointer to the RSS raw pattern configuration
1507 *
1508 * This function removes the RSS configuration for raw pattern.
1509 * Check if vsi group is already removed first. If not, remove the
1510 * profile.
1511 *
1512 * Return: 0 on success; negative error code on failure.
1513 */
1514static int
1515ice_rem_raw_rss_cfg(struct ice_vf *vf, struct ice_rss_raw_cfg *cfg)
1516{
1517	struct ice_parser_profile *prof = &cfg->prof;
1518	struct device *dev = ice_pf_to_dev(vf->pf);
1519	struct ice_hw *hw = &vf->pf->hw;
1520	int ptg, ret = 0;
1521	u16 vsig, vsi;
1522	u64 id;
1523
1524	id = find_first_bit(prof->ptypes, ICE_FLOW_PTYPE_MAX);
1525
1526	ptg = hw->blk[ICE_BLK_RSS].xlt1.t[id];
1527
1528	memset(&vf->rss_prof_info[ptg], 0,
1529	       sizeof(struct ice_rss_prof_info));
1530
1531	/* check if vsig is already removed */
1532	vsi = ice_get_hw_vsi_num(hw, vf->lan_vsi_idx);
1533	if (vsi >= ICE_MAX_VSI) {
1534		ret = -EINVAL;
1535		goto err;
1536	}
1537
1538	vsig = hw->blk[ICE_BLK_RSS].xlt2.vsis[vsi].vsig;
1539	if (vsig) {
1540		ret = ice_rem_prof_id_flow(hw, ICE_BLK_RSS, vsi, id);
1541		if (ret)
1542			goto err;
1543
1544		ret = ice_rem_prof(hw, ICE_BLK_RSS, id);
1545		if (ret)
1546			goto err;
1547	}
1548
1549	return ret;
1550
1551err:
1552	dev_err(dev, "HW profile remove failed\n");
1553	return ret;
1554}
1555
1556/**
1557 * ice_vc_handle_rss_cfg
1558 * @vf: pointer to the VF info
1559 * @msg: pointer to the message buffer
1560 * @add: add a RSS config if true, otherwise delete a RSS config
1561 *
1562 * This function adds/deletes a RSS config
1563 */
1564int ice_vc_handle_rss_cfg(struct ice_vf *vf, u8 *msg, bool add)
1565{
1566	u32 v_opcode = add ? VIRTCHNL_OP_ADD_RSS_CFG : VIRTCHNL_OP_DEL_RSS_CFG;
1567	struct virtchnl_rss_cfg *rss_cfg = (struct virtchnl_rss_cfg *)msg;
1568	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
1569	struct device *dev = ice_pf_to_dev(vf->pf);
1570	struct ice_hw *hw = &vf->pf->hw;
1571	struct ice_vsi *vsi;
1572	u8 hash_type;
1573	bool symm;
1574	int ret;
1575
1576	if (!test_bit(ICE_FLAG_RSS_ENA, vf->pf->flags)) {
1577		dev_dbg(dev, "VF %d attempting to configure RSS, but RSS is not supported by the PF\n",
1578			vf->vf_id);
1579		v_ret = VIRTCHNL_STATUS_ERR_NOT_SUPPORTED;
1580		goto error_param;
1581	}
1582
1583	if (!ice_vf_adv_rss_offload_ena(vf->driver_caps)) {
1584		dev_dbg(dev, "VF %d attempting to configure RSS, but Advanced RSS offload is not supported\n",
1585			vf->vf_id);
1586		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1587		goto error_param;
1588	}
1589
1590	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
1591		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1592		goto error_param;
1593	}
1594
1595	if (rss_cfg->proto_hdrs.count > VIRTCHNL_MAX_NUM_PROTO_HDRS ||
1596	    rss_cfg->rss_algorithm < VIRTCHNL_RSS_ALG_TOEPLITZ_ASYMMETRIC ||
1597	    rss_cfg->rss_algorithm > VIRTCHNL_RSS_ALG_XOR_SYMMETRIC) {
1598		dev_dbg(dev, "VF %d attempting to configure RSS, but RSS configuration is not valid\n",
1599			vf->vf_id);
1600		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1601		goto error_param;
1602	}
1603
1604	vsi = ice_get_vf_vsi(vf);
1605	if (!vsi) {
1606		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1607		goto error_param;
1608	}
1609
1610	if (rss_cfg->rss_algorithm == VIRTCHNL_RSS_ALG_R_ASYMMETRIC) {
1611		hash_type = add ? ICE_AQ_VSI_Q_OPT_RSS_HASH_XOR :
1612				  ICE_AQ_VSI_Q_OPT_RSS_HASH_TPLZ;
1613
1614		ret = ice_vc_rss_hash_update(hw, vsi, hash_type);
1615		if (ret)
1616			v_ret = ice_err_to_virt_err(ret);
1617		goto error_param;
1618	}
1619
1620	hash_type = add ? ICE_AQ_VSI_Q_OPT_RSS_HASH_SYM_TPLZ :
1621			  ICE_AQ_VSI_Q_OPT_RSS_HASH_TPLZ;
1622	ret = ice_vc_rss_hash_update(hw, vsi, hash_type);
1623	if (ret) {
1624		v_ret = ice_err_to_virt_err(ret);
1625		goto error_param;
1626	}
1627
1628	symm = rss_cfg->rss_algorithm == VIRTCHNL_RSS_ALG_TOEPLITZ_SYMMETRIC;
1629	/* Configure RSS hash for raw pattern */
1630	if (rss_cfg->proto_hdrs.tunnel_level == 0 &&
1631	    rss_cfg->proto_hdrs.count == 0) {
1632		struct ice_rss_raw_cfg raw_cfg;
1633
1634		if (ice_parse_raw_rss_pattern(vf, &rss_cfg->proto_hdrs,
1635					      &raw_cfg)) {
1636			v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1637			goto error_param;
1638		}
1639
1640		if (add) {
1641			raw_cfg.symm = symm;
1642			if (ice_add_raw_rss_cfg(vf, &raw_cfg))
1643				v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1644		} else {
1645			if (ice_rem_raw_rss_cfg(vf, &raw_cfg))
1646				v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1647		}
1648	} else {
1649		struct ice_rss_hash_cfg cfg;
1650
1651		/* Only check for none raw pattern case */
1652		if (!ice_vc_validate_pattern(vf, &rss_cfg->proto_hdrs)) {
1653			v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1654			goto error_param;
1655		}
1656		cfg.addl_hdrs = ICE_FLOW_SEG_HDR_NONE;
1657		cfg.hash_flds = ICE_HASH_INVALID;
1658		cfg.hdr_type = ICE_RSS_ANY_HEADERS;
1659
1660		if (!ice_vc_parse_rss_cfg(hw, rss_cfg, &cfg)) {
1661			v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1662			goto error_param;
1663		}
1664
1665		if (add) {
1666			cfg.symm = symm;
1667			if (ice_add_rss_cfg_wrap(vf, &cfg))
1668				v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1669		} else {
1670			if (ice_rem_rss_cfg_wrap(vf, &cfg))
1671				v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1672		}
1673	}
1674
1675error_param:
1676	return ice_vc_send_msg_to_vf(vf, v_opcode, v_ret, NULL, 0);
1677}
1678
1679/**
1680 * ice_vc_config_rss_key
1681 * @vf: pointer to the VF info
1682 * @msg: pointer to the msg buffer
1683 *
1684 * Configure the VF's RSS key
1685 */
1686int ice_vc_config_rss_key(struct ice_vf *vf, u8 *msg)
1687{
1688	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
1689	struct virtchnl_rss_key *vrk =
1690		(struct virtchnl_rss_key *)msg;
1691	struct ice_vsi *vsi;
1692
1693	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
1694		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1695		goto error_param;
1696	}
1697
1698	if (!ice_vc_isvalid_vsi_id(vf, vrk->vsi_id)) {
1699		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1700		goto error_param;
1701	}
1702
1703	if (vrk->key_len != ICE_VSIQF_HKEY_ARRAY_SIZE) {
1704		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1705		goto error_param;
1706	}
1707
1708	if (!test_bit(ICE_FLAG_RSS_ENA, vf->pf->flags)) {
1709		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1710		goto error_param;
1711	}
1712
1713	vsi = ice_get_vf_vsi(vf);
1714	if (!vsi) {
1715		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1716		goto error_param;
1717	}
1718
1719	if (ice_set_rss_key(vsi, vrk->key))
1720		v_ret = VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR;
1721error_param:
1722	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_RSS_KEY, v_ret,
1723				     NULL, 0);
1724}
1725
1726/**
1727 * ice_vc_config_rss_lut
1728 * @vf: pointer to the VF info
1729 * @msg: pointer to the msg buffer
1730 *
1731 * Configure the VF's RSS LUT
1732 */
1733int ice_vc_config_rss_lut(struct ice_vf *vf, u8 *msg)
1734{
1735	struct virtchnl_rss_lut *vrl = (struct virtchnl_rss_lut *)msg;
1736	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
1737	struct ice_vsi *vsi;
1738
1739	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
1740		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1741		goto error_param;
1742	}
1743
1744	if (!ice_vc_isvalid_vsi_id(vf, vrl->vsi_id)) {
1745		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1746		goto error_param;
1747	}
1748
1749	if (vrl->lut_entries != ICE_LUT_VSI_SIZE) {
1750		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1751		goto error_param;
1752	}
1753
1754	if (!test_bit(ICE_FLAG_RSS_ENA, vf->pf->flags)) {
1755		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1756		goto error_param;
1757	}
1758
1759	vsi = ice_get_vf_vsi(vf);
1760	if (!vsi) {
1761		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1762		goto error_param;
1763	}
1764
1765	if (ice_set_rss_lut(vsi, vrl->lut, ICE_LUT_VSI_SIZE))
1766		v_ret = VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR;
1767error_param:
1768	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_RSS_LUT, v_ret,
1769				     NULL, 0);
1770}
1771
1772/**
1773 * ice_vc_config_rss_hfunc
1774 * @vf: pointer to the VF info
1775 * @msg: pointer to the msg buffer
1776 *
1777 * Configure the VF's RSS Hash function
1778 */
1779int ice_vc_config_rss_hfunc(struct ice_vf *vf, u8 *msg)
1780{
1781	struct virtchnl_rss_hfunc *vrh = (struct virtchnl_rss_hfunc *)msg;
1782	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
1783	u8 hfunc = ICE_AQ_VSI_Q_OPT_RSS_HASH_TPLZ;
1784	struct ice_vsi *vsi;
1785
1786	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
1787		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1788		goto error_param;
1789	}
1790
1791	if (!ice_vc_isvalid_vsi_id(vf, vrh->vsi_id)) {
1792		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1793		goto error_param;
1794	}
1795
1796	if (!test_bit(ICE_FLAG_RSS_ENA, vf->pf->flags)) {
1797		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1798		goto error_param;
1799	}
1800
1801	vsi = ice_get_vf_vsi(vf);
1802	if (!vsi) {
1803		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1804		goto error_param;
1805	}
1806
1807	if (vrh->rss_algorithm == VIRTCHNL_RSS_ALG_TOEPLITZ_SYMMETRIC)
1808		hfunc = ICE_AQ_VSI_Q_OPT_RSS_HASH_SYM_TPLZ;
1809
1810	if (ice_set_rss_hfunc(vsi, hfunc))
1811		v_ret = VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR;
1812error_param:
1813	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_RSS_HFUNC, v_ret,
1814				     NULL, 0);
1815}
1816
1817/**
1818 * ice_vc_get_rss_hashcfg - return the RSS Hash configuration
1819 * @vf: pointer to the VF info
1820 */
1821int ice_vc_get_rss_hashcfg(struct ice_vf *vf)
1822{
1823	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
1824	struct virtchnl_rss_hashcfg *vrh = NULL;
1825	int len = 0, ret;
1826
1827	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
1828		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1829		goto err;
1830	}
1831
1832	if (!test_bit(ICE_FLAG_RSS_ENA, vf->pf->flags)) {
1833		dev_err(ice_pf_to_dev(vf->pf), "RSS not supported by PF\n");
1834		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1835		goto err;
1836	}
1837
1838	len = sizeof(struct virtchnl_rss_hashcfg);
1839	vrh = kzalloc(len, GFP_KERNEL);
1840	if (!vrh) {
1841		v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY;
1842		len = 0;
1843		goto err;
1844	}
1845
1846	vrh->hashcfg = ICE_DEFAULT_RSS_HASHCFG;
1847err:
1848	/* send the response back to the VF */
1849	ret = ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_GET_RSS_HASHCFG_CAPS, v_ret,
1850				    (u8 *)vrh, len);
1851	kfree(vrh);
1852	return ret;
1853}
1854
1855/**
1856 * ice_vc_set_rss_hashcfg - set RSS Hash configuration bits for the VF
1857 * @vf: pointer to the VF info
1858 * @msg: pointer to the msg buffer
1859 */
1860int ice_vc_set_rss_hashcfg(struct ice_vf *vf, u8 *msg)
1861{
1862	struct virtchnl_rss_hashcfg *vrh = (struct virtchnl_rss_hashcfg *)msg;
1863	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
1864	struct ice_pf *pf = vf->pf;
1865	struct ice_vsi *vsi;
1866	struct device *dev;
1867	int status;
1868
1869	dev = ice_pf_to_dev(pf);
1870
1871	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
1872		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1873		goto err;
1874	}
1875
1876	if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) {
1877		dev_err(dev, "RSS not supported by PF\n");
1878		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1879		goto err;
1880	}
1881
1882	vsi = ice_get_vf_vsi(vf);
1883	if (!vsi) {
1884		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1885		goto err;
1886	}
1887
1888	/* clear all previously programmed RSS configuration to allow VF drivers
1889	 * the ability to customize the RSS configuration and/or completely
1890	 * disable RSS
1891	 */
1892	status = ice_rem_vsi_rss_cfg(&pf->hw, vsi->idx);
1893	if (status && !vrh->hashcfg) {
1894		/* only report failure to clear the current RSS configuration if
1895		 * that was clearly the VF's intention (i.e. vrh->hashcfg = 0)
1896		 */
1897		v_ret = ice_err_to_virt_err(status);
1898		goto err;
1899	} else if (status) {
1900		/* allow the VF to update the RSS configuration even on failure
1901		 * to clear the current RSS confguration in an attempt to keep
1902		 * RSS in a working state
1903		 */
1904		dev_warn(dev, "Failed to clear the RSS configuration for VF %u\n",
1905			 vf->vf_id);
1906	}
1907
1908	if (vrh->hashcfg) {
1909		status = ice_add_avf_rss_cfg(&pf->hw, vsi, vrh->hashcfg);
1910		v_ret = ice_err_to_virt_err(status);
1911	}
1912
1913	/* save the requested VF configuration */
1914	if (!v_ret)
1915		vf->rss_hashcfg = vrh->hashcfg;
1916
1917	/* send the response to the VF */
1918err:
1919	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_SET_RSS_HASHCFG, v_ret,
1920				     NULL, 0);
1921}
1922
~/ Read-only file preview.