File Index
Files and directories
Sign in
FILE

ice_flow.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/intel/ice/ice_flow.c C
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright (c) 2019, Intel Corporation. */
   3
   4#include "ice_common.h"
   5#include "ice_flow.h"
   6#include <net/gre.h>
   7
   8/* Size of known protocol header fields */
   9#define ICE_FLOW_FLD_SZ_ETH_TYPE	2
  10#define ICE_FLOW_FLD_SZ_VLAN		2
  11#define ICE_FLOW_FLD_SZ_IPV4_ADDR	4
  12#define ICE_FLOW_FLD_SZ_IPV6_ADDR	16
  13#define ICE_FLOW_FLD_SZ_IPV6_PRE32_ADDR	4
  14#define ICE_FLOW_FLD_SZ_IPV6_PRE48_ADDR	6
  15#define ICE_FLOW_FLD_SZ_IPV6_PRE64_ADDR	8
  16#define ICE_FLOW_FLD_SZ_IPV4_ID		2
  17#define ICE_FLOW_FLD_SZ_IPV6_ID		4
  18#define ICE_FLOW_FLD_SZ_IP_CHKSUM	2
  19#define ICE_FLOW_FLD_SZ_TCP_CHKSUM	2
  20#define ICE_FLOW_FLD_SZ_UDP_CHKSUM	2
  21#define ICE_FLOW_FLD_SZ_SCTP_CHKSUM	4
  22#define ICE_FLOW_FLD_SZ_IP_DSCP		1
  23#define ICE_FLOW_FLD_SZ_IP_TTL		1
  24#define ICE_FLOW_FLD_SZ_IP_PROT		1
  25#define ICE_FLOW_FLD_SZ_PORT		2
  26#define ICE_FLOW_FLD_SZ_TCP_FLAGS	1
  27#define ICE_FLOW_FLD_SZ_ICMP_TYPE	1
  28#define ICE_FLOW_FLD_SZ_ICMP_CODE	1
  29#define ICE_FLOW_FLD_SZ_ARP_OPER	2
  30#define ICE_FLOW_FLD_SZ_GRE_KEYID	4
  31#define ICE_FLOW_FLD_SZ_GTP_TEID	4
  32#define ICE_FLOW_FLD_SZ_GTP_QFI		2
  33#define ICE_FLOW_FLD_SZ_PFCP_SEID 8
  34#define ICE_FLOW_FLD_SZ_ESP_SPI	4
  35#define ICE_FLOW_FLD_SZ_AH_SPI	4
  36#define ICE_FLOW_FLD_SZ_NAT_T_ESP_SPI	4
  37#define ICE_FLOW_FLD_SZ_L2TPV2_SESS_ID	2
  38#define ICE_FLOW_FLD_SZ_L2TPV2_LEN_SESS_ID	2
  39
  40/* Describe properties of a protocol header field */
  41struct ice_flow_field_info {
  42	enum ice_flow_seg_hdr hdr;
  43	s16 off;	/* Offset from start of a protocol header, in bits */
  44	u16 size;	/* Size of fields in bits */
  45	u16 mask;	/* 16-bit mask for field */
  46};
  47
  48#define ICE_FLOW_FLD_INFO(_hdr, _offset_bytes, _size_bytes) { \
  49	.hdr = _hdr, \
  50	.off = (_offset_bytes) * BITS_PER_BYTE, \
  51	.size = (_size_bytes) * BITS_PER_BYTE, \
  52	.mask = 0, \
  53}
  54
  55/* QFI: 6-bit field in GTP-U PDU Session Container (3GPP TS 38.415) */
  56#define ICE_FLOW_FLD_INFO_MSK(_hdr, _offset_bytes, _size_bytes, _mask) { \
  57	.hdr = _hdr, \
  58	.off = (_offset_bytes) * BITS_PER_BYTE, \
  59	.size = (_size_bytes) * BITS_PER_BYTE, \
  60	.mask = _mask, \
  61}
  62
  63/* Table containing properties of supported protocol header fields */
  64static const
  65struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = {
  66	/* Ether */
  67	/* ICE_FLOW_FIELD_IDX_ETH_DA */
  68	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ETH_ALEN),
  69	/* ICE_FLOW_FIELD_IDX_ETH_SA */
  70	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, ETH_ALEN, ETH_ALEN),
  71	/* ICE_FLOW_FIELD_IDX_S_VLAN */
  72	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 12, sizeof(__be16)),
  73	/* ICE_FLOW_FIELD_IDX_C_VLAN */
  74	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 14, sizeof(__be16)),
  75	/* ICE_FLOW_FIELD_IDX_ETH_TYPE */
  76	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, sizeof(__be16)),
  77	/* IPv4 / IPv6 */
  78	/* ICE_FLOW_FIELD_IDX_IPV4_DSCP */
  79	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV4, 0, 1, 0x00fc),
  80	/* ICE_FLOW_FIELD_IDX_IPV6_DSCP */
  81	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV6, 0, 1, 0x0ff0),
  82	/* ICE_FLOW_FIELD_IDX_IPV4_TTL */
  83	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8, 1, 0xff00),
  84	/* ICE_FLOW_FIELD_IDX_IPV4_PROT */
  85	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8, 1, 0x00ff),
  86	/* ICE_FLOW_FIELD_IDX_IPV6_TTL */
  87	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6, 1, 0x00ff),
  88	/* ICE_FLOW_FIELD_IDX_IPV6_PROT */
  89	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6, 1, 0xff00),
  90	/* ICE_FLOW_FIELD_IDX_IPV4_SA */
  91	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 12, sizeof(struct in_addr)),
  92	/* ICE_FLOW_FIELD_IDX_IPV4_DA */
  93	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 16, sizeof(struct in_addr)),
  94	/* ICE_FLOW_FIELD_IDX_IPV6_SA */
  95	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, sizeof(struct in6_addr)),
  96	/* ICE_FLOW_FIELD_IDX_IPV6_DA */
  97	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, ICE_FLOW_FLD_SZ_IPV6_ADDR),
  98	/* ICE_FLOW_FIELD_IDX_IPV4_CHKSUM */
  99	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 10, ICE_FLOW_FLD_SZ_IP_CHKSUM),
 100	/* ICE_FLOW_FIELD_IDX_IPV4_FRAG */
 101	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV_FRAG, 4,
 102			  ICE_FLOW_FLD_SZ_IPV4_ID),
 103	/* ICE_FLOW_FIELD_IDX_IPV6_FRAG */
 104	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV_FRAG, 4,
 105			  ICE_FLOW_FLD_SZ_IPV6_ID),
 106	/* ICE_FLOW_FIELD_IDX_IPV6_PRE32_SA */
 107	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8,
 108			  ICE_FLOW_FLD_SZ_IPV6_PRE32_ADDR),
 109	/* ICE_FLOW_FIELD_IDX_IPV6_PRE32_DA */
 110	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24,
 111			  ICE_FLOW_FLD_SZ_IPV6_PRE32_ADDR),
 112	/* ICE_FLOW_FIELD_IDX_IPV6_PRE48_SA */
 113	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8,
 114			  ICE_FLOW_FLD_SZ_IPV6_PRE48_ADDR),
 115	/* ICE_FLOW_FIELD_IDX_IPV6_PRE48_DA */
 116	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24,
 117			  ICE_FLOW_FLD_SZ_IPV6_PRE48_ADDR),
 118	/* ICE_FLOW_FIELD_IDX_IPV6_PRE64_SA */
 119	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8,
 120			  ICE_FLOW_FLD_SZ_IPV6_PRE64_ADDR),
 121	/* ICE_FLOW_FIELD_IDX_IPV6_PRE64_DA */
 122	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24,
 123			  ICE_FLOW_FLD_SZ_IPV6_PRE64_ADDR),
 124	/* Transport */
 125	/* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */
 126	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 0, sizeof(__be16)),
 127	/* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */
 128	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 2, sizeof(__be16)),
 129	/* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */
 130	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 0, sizeof(__be16)),
 131	/* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */
 132	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 2, sizeof(__be16)),
 133	/* ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT */
 134	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 0, sizeof(__be16)),
 135	/* ICE_FLOW_FIELD_IDX_SCTP_DST_PORT */
 136	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 2, sizeof(__be16)),
 137	/* ICE_FLOW_FIELD_IDX_TCP_FLAGS */
 138	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 13, ICE_FLOW_FLD_SZ_TCP_FLAGS),
 139	/* ICE_FLOW_FIELD_IDX_TCP_CHKSUM */
 140	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 16, ICE_FLOW_FLD_SZ_TCP_CHKSUM),
 141	/* ICE_FLOW_FIELD_IDX_UDP_CHKSUM */
 142	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 6, ICE_FLOW_FLD_SZ_UDP_CHKSUM),
 143	/* ICE_FLOW_FIELD_IDX_SCTP_CHKSUM */
 144	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 8,
 145			  ICE_FLOW_FLD_SZ_SCTP_CHKSUM),
 146	/* ARP */
 147	/* ICE_FLOW_FIELD_IDX_ARP_SIP */
 148	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 14, sizeof(struct in_addr)),
 149	/* ICE_FLOW_FIELD_IDX_ARP_DIP */
 150	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 24, sizeof(struct in_addr)),
 151	/* ICE_FLOW_FIELD_IDX_ARP_SHA */
 152	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 8, ETH_ALEN),
 153	/* ICE_FLOW_FIELD_IDX_ARP_DHA */
 154	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 18, ETH_ALEN),
 155	/* ICE_FLOW_FIELD_IDX_ARP_OP */
 156	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 6, sizeof(__be16)),
 157	/* ICMP */
 158	/* ICE_FLOW_FIELD_IDX_ICMP_TYPE */
 159	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 0, 1),
 160	/* ICE_FLOW_FIELD_IDX_ICMP_CODE */
 161	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 1, 1),
 162	/* GRE */
 163	/* ICE_FLOW_FIELD_IDX_GRE_KEYID */
 164	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GRE, 12,
 165			  sizeof_field(struct gre_full_hdr, key)),
 166	/* GTP */
 167	/* ICE_FLOW_FIELD_IDX_GTPC_TEID */
 168	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPC_TEID, 12, sizeof(__be32)),
 169	/* ICE_FLOW_FIELD_IDX_GTPU_IP_TEID */
 170	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_IP, 12, sizeof(__be32)),
 171	/* ICE_FLOW_FIELD_IDX_GTPU_EH_TEID */
 172	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_EH, 12, sizeof(__be32)),
 173	/* ICE_FLOW_FIELD_IDX_GTPU_EH_QFI */
 174	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_GTPU_EH, 22, sizeof(__be16),
 175			      0x3f00),
 176	/* ICE_FLOW_FIELD_IDX_GTPU_UP_TEID */
 177	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_UP, 12,
 178			  ICE_FLOW_FLD_SZ_GTP_TEID),
 179	/* ICE_FLOW_FIELD_IDX_GTPU_UP_QFI */
 180	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_GTPU_UP, 22,
 181			      ICE_FLOW_FLD_SZ_GTP_QFI, 0x3f00),
 182	/* ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID */
 183	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_DWN, 12,
 184			  ICE_FLOW_FLD_SZ_GTP_TEID),
 185	/* ICE_FLOW_FIELD_IDX_GTPU_DWN_QFI */
 186	ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_GTPU_DWN, 22,
 187			      ICE_FLOW_FLD_SZ_GTP_QFI, 0x3f00),
 188	/* PPPoE */
 189	/* ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID */
 190	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PPPOE, 2, sizeof(__be16)),
 191	/* PFCP */
 192	/* ICE_FLOW_FIELD_IDX_PFCP_SEID */
 193	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PFCP_SESSION, 12, sizeof(__be64)),
 194	/* L2TPv3 */
 195	/* ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID */
 196	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_L2TPV3, 0, sizeof(__be32)),
 197	/* ESP */
 198	/* ICE_FLOW_FIELD_IDX_ESP_SPI */
 199	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ESP, 0, sizeof(__be32)),
 200	/* AH */
 201	/* ICE_FLOW_FIELD_IDX_AH_SPI */
 202	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_AH, 4, sizeof(__be32)),
 203	/* NAT_T_ESP */
 204	/* ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI */
 205	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NAT_T_ESP, 8,
 206			  ICE_FLOW_FLD_SZ_NAT_T_ESP_SPI),
 207	/* L2TPV2 */
 208	/* ICE_FLOW_FIELD_IDX_L2TPV2_SESS_ID */
 209	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_L2TPV2, 12,
 210			  ICE_FLOW_FLD_SZ_L2TPV2_SESS_ID),
 211	/* L2TPV2_LEN */
 212	/* ICE_FLOW_FIELD_IDX_L2TPV2_LEN_SESS_ID */
 213	ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_L2TPV2, 14,
 214			  ICE_FLOW_FLD_SZ_L2TPV2_LEN_SESS_ID),
 215};
 216
 217/* Bitmaps indicating relevant packet types for a particular protocol header
 218 *
 219 * Packet types for packets with an Outer/First/Single MAC header
 220 */
 221static const u32 ice_ptypes_mac_ofos[] = {
 222	0xFDC00846, 0xBFBF7F7E, 0xF70001DF, 0xFEFDFDFB,
 223	0x0000077E, 0x000003FF, 0x00000000, 0x00000000,
 224	0x00400000, 0x03FFF000, 0xFFFFFFE0, 0x00000707,
 225	0xFFFFF000, 0x000003FF, 0x00000000, 0x00000000,
 226	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 227	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 228	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 229	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 230};
 231
 232/* Packet types for packets with an Innermost/Last MAC VLAN header */
 233static const u32 ice_ptypes_macvlan_il[] = {
 234	0x00000000, 0xBC000000, 0x000001DF, 0xF0000000,
 235	0x0000077E, 0x00000000, 0x00000000, 0x00000000,
 236	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 237	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 238	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 239	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 240	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 241	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 242};
 243
 244/* Packet types for packets with an Outer/First/Single IPv4 header, does NOT
 245 * include IPv4 other PTYPEs
 246 */
 247static const u32 ice_ptypes_ipv4_ofos[] = {
 248	0x1D800000, 0xBFBF7800, 0x000001DF, 0x00000000,
 249	0x00000000, 0x00000155, 0x00000000, 0x00000000,
 250	0x00000000, 0x000FC000, 0x000002A0, 0x00000000,
 251	0x00015000, 0x00000000, 0x00000000, 0x00000000,
 252	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 253	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 254	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 255	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 256};
 257
 258/* Packet types for packets with an Outer/First/Single IPv4 header, includes
 259 * IPv4 other PTYPEs
 260 */
 261static const u32 ice_ptypes_ipv4_ofos_all[] = {
 262	0x1D800000, 0x27BF7800, 0x00000000, 0x00000000,
 263	0x00000000, 0x00000155, 0x00000000, 0x00000000,
 264	0x00000000, 0x000FC000, 0x83E0FAA0, 0x00000101,
 265	0x3FFD5000, 0x00000000, 0x02FBEFBC, 0x00000000,
 266	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 267	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 268	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 269	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 270};
 271
 272/* Packet types for packets with an Innermost/Last IPv4 header */
 273static const u32 ice_ptypes_ipv4_il[] = {
 274	0xE0000000, 0xB807700E, 0x80000003, 0xE01DC03B,
 275	0x0000000E, 0x00000000, 0x00000000, 0x00000000,
 276	0x00000000, 0x00000000, 0x001FF800, 0x00000000,
 277	0xC0FC0000, 0x0000000F, 0xBC0BC0BC, 0x00000BC0,
 278	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 279	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 280	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 281	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 282};
 283
 284/* Packet types for packets with an Outer/First/Single IPv6 header, does NOT
 285 * include IPv6 other PTYPEs
 286 */
 287static const u32 ice_ptypes_ipv6_ofos[] = {
 288	0x00000000, 0x00000000, 0x76000000, 0x10002000,
 289	0x00000000, 0x000002AA, 0x00000000, 0x00000000,
 290	0x00000000, 0x03F00000, 0x00000540, 0x00000000,
 291	0x0002A000, 0x00000000, 0x00000000, 0x00000000,
 292	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 293	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 294	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 295	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 296};
 297
 298/* Packet types for packets with an Outer/First/Single IPv6 header, includes
 299 * IPv6 other PTYPEs
 300 */
 301static const u32 ice_ptypes_ipv6_ofos_all[] = {
 302	0x00000000, 0x00000000, 0x76000000, 0xFEFDE000,
 303	0x0000077E, 0x000002AA, 0x00000000, 0x00000000,
 304	0x00000000, 0x03F00000, 0x7C1F0540, 0x00000206,
 305	0xC002A000, 0x000003FF, 0xBC000000, 0x0002FBEF,
 306	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 307	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 308	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 309	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 310};
 311
 312/* Packet types for packets with an Innermost/Last IPv6 header */
 313static const u32 ice_ptypes_ipv6_il[] = {
 314	0x00000000, 0x03B80770, 0x000001DC, 0x0EE00000,
 315	0x00000770, 0x00000000, 0x00000000, 0x00000000,
 316	0x00000000, 0x00000000, 0x7FE00000, 0x00000000,
 317	0x3F000000, 0x000003F0, 0x02F02F00, 0x0002F02F,
 318	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 319	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 320	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 321	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 322};
 323
 324/* Packet types for packets with an Outer/First/Single IPv4 header - no L4 */
 325static const u32 ice_ptypes_ipv4_ofos_no_l4[] = {
 326	0x10C00000, 0x04000800, 0x00000000, 0x00000000,
 327	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 328	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 329	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 330	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 331	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 332	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 333	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 334};
 335
 336/* Packet types for packets with an Outermost/First ARP header */
 337static const u32 ice_ptypes_arp_of[] = {
 338	0x00000800, 0x00000000, 0x00000000, 0x00000000,
 339	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 340	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 341	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 342	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 343	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 344	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 345	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 346};
 347
 348/* Packet types for packets with an Innermost/Last IPv4 header - no L4 */
 349static const u32 ice_ptypes_ipv4_il_no_l4[] = {
 350	0x60000000, 0x18043008, 0x80000002, 0x6010c021,
 351	0x00000008, 0x00000000, 0x00000000, 0x00000000,
 352	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 353	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 354	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 355	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 356	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 357	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 358};
 359
 360/* Packet types for packets with an Outer/First/Single IPv6 header - no L4 */
 361static const u32 ice_ptypes_ipv6_ofos_no_l4[] = {
 362	0x00000000, 0x00000000, 0x43000000, 0x10002000,
 363	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 364	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 365	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 366	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 367	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 368	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 369	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 370};
 371
 372/* Packet types for packets with an Innermost/Last IPv6 header - no L4 */
 373static const u32 ice_ptypes_ipv6_il_no_l4[] = {
 374	0x00000000, 0x02180430, 0x0000010c, 0x086010c0,
 375	0x00000430, 0x00000000, 0x00000000, 0x00000000,
 376	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 377	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 378	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 379	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 380	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 381	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 382};
 383
 384/* UDP Packet types for non-tunneled packets or tunneled
 385 * packets with inner UDP.
 386 */
 387static const u32 ice_ptypes_udp_il[] = {
 388	0x81000000, 0x20204040, 0x04000010, 0x80810102,
 389	0x00000040, 0x00000000, 0x00000000, 0x00000000,
 390	0x00000000, 0x00410000, 0x908427E0, 0x00000007,
 391	0x0413F000, 0x00000041, 0x10410410, 0x00004104,
 392	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 393	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 394	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 395	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 396};
 397
 398/* Packet types for packets with an Innermost/Last TCP header */
 399static const u32 ice_ptypes_tcp_il[] = {
 400	0x04000000, 0x80810102, 0x10000040, 0x02040408,
 401	0x00000102, 0x00000000, 0x00000000, 0x00000000,
 402	0x00000000, 0x00820000, 0x21084000, 0x00000000,
 403	0x08200000, 0x00000082, 0x20820820, 0x00008208,
 404	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 405	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 406	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 407	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 408};
 409
 410/* Packet types for packets with an Innermost/Last SCTP header */
 411static const u32 ice_ptypes_sctp_il[] = {
 412	0x08000000, 0x01020204, 0x20000081, 0x04080810,
 413	0x00000204, 0x00000000, 0x00000000, 0x00000000,
 414	0x00000000, 0x01040000, 0x00000000, 0x00000000,
 415	0x10400000, 0x00000104, 0x00000000, 0x00000000,
 416	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 417	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 418	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 419	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 420};
 421
 422/* Packet types for packets with an Outermost/First ICMP header */
 423static const u32 ice_ptypes_icmp_of[] = {
 424	0x10000000, 0x00000000, 0x00000000, 0x00000000,
 425	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 426	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 427	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 428	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 429	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 430	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 431	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 432};
 433
 434/* Packet types for packets with an Innermost/Last ICMP header */
 435static const u32 ice_ptypes_icmp_il[] = {
 436	0x00000000, 0x02040408, 0x40000102, 0x08101020,
 437	0x00000408, 0x00000000, 0x00000000, 0x00000000,
 438	0x00000000, 0x00000000, 0x42108000, 0x00000000,
 439	0x20800000, 0x00000208, 0x00000000, 0x00000000,
 440	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 441	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 442	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 443	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 444};
 445
 446/* Packet types for packets with an Outermost/First GRE header */
 447static const u32 ice_ptypes_gre_of[] = {
 448	0x00000000, 0xBFBF7800, 0x000001DF, 0xFEFDE000,
 449	0x0000017E, 0x00000000, 0x00000000, 0x00000000,
 450	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 451	0x00000000, 0x00000000, 0xBEFBEFBC, 0x0002FBEF,
 452	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 453	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 454	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 455	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 456};
 457
 458/* Packet types for packets with an Innermost/Last MAC header */
 459static const u32 ice_ptypes_mac_il[] = {
 460	0x00000000, 0x20000000, 0x00000000, 0x00000000,
 461	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 462	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 463	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 464	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 465	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 466	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 467	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 468};
 469
 470/* Packet types for GTPC */
 471static const u32 ice_ptypes_gtpc[] = {
 472	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 473	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 474	0x00000000, 0x00000000, 0x000001E0, 0x00000000,
 475	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 476	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 477	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 478	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 479	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 480};
 481
 482/* Packet types for GTPC with TEID */
 483static const u32 ice_ptypes_gtpc_tid[] = {
 484	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 485	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 486	0x00000000, 0x00000000, 0x00000060, 0x00000000,
 487	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 488	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 489	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 490	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 491	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 492};
 493
 494/* Packet types for GTPU */
 495static const struct ice_ptype_attributes ice_attr_gtpu_session[] = {
 496	{ ICE_MAC_IPV4_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_SESSION },
 497	{ ICE_MAC_IPV4_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_SESSION },
 498	{ ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_SESSION },
 499	{ ICE_MAC_IPV4_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_SESSION },
 500	{ ICE_MAC_IPV4_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_SESSION },
 501	{ ICE_MAC_IPV6_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_SESSION },
 502	{ ICE_MAC_IPV6_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_SESSION },
 503	{ ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_SESSION },
 504	{ ICE_MAC_IPV6_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_SESSION },
 505	{ ICE_MAC_IPV6_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_SESSION },
 506	{ ICE_MAC_IPV4_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_SESSION },
 507	{ ICE_MAC_IPV4_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_SESSION },
 508	{ ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_SESSION },
 509	{ ICE_MAC_IPV4_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_SESSION },
 510	{ ICE_MAC_IPV4_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_SESSION },
 511	{ ICE_MAC_IPV6_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_SESSION },
 512	{ ICE_MAC_IPV6_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_SESSION },
 513	{ ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_SESSION },
 514	{ ICE_MAC_IPV6_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_SESSION },
 515	{ ICE_MAC_IPV6_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_SESSION },
 516};
 517
 518static const struct ice_ptype_attributes ice_attr_gtpu_eh[] = {
 519	{ ICE_MAC_IPV4_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
 520	{ ICE_MAC_IPV4_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
 521	{ ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
 522	{ ICE_MAC_IPV4_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
 523	{ ICE_MAC_IPV4_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
 524	{ ICE_MAC_IPV6_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
 525	{ ICE_MAC_IPV6_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
 526	{ ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
 527	{ ICE_MAC_IPV6_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
 528	{ ICE_MAC_IPV6_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
 529	{ ICE_MAC_IPV4_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
 530	{ ICE_MAC_IPV4_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
 531	{ ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
 532	{ ICE_MAC_IPV4_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
 533	{ ICE_MAC_IPV4_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_PDU_EH },
 534	{ ICE_MAC_IPV6_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
 535	{ ICE_MAC_IPV6_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
 536	{ ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
 537	{ ICE_MAC_IPV6_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_PDU_EH },
 538	{ ICE_MAC_IPV6_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_PDU_EH },
 539};
 540
 541static const struct ice_ptype_attributes ice_attr_gtpu_down[] = {
 542	{ ICE_MAC_IPV4_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
 543	{ ICE_MAC_IPV4_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
 544	{ ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
 545	{ ICE_MAC_IPV4_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
 546	{ ICE_MAC_IPV4_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
 547	{ ICE_MAC_IPV6_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
 548	{ ICE_MAC_IPV6_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
 549	{ ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
 550	{ ICE_MAC_IPV6_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
 551	{ ICE_MAC_IPV6_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
 552	{ ICE_MAC_IPV4_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
 553	{ ICE_MAC_IPV4_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
 554	{ ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
 555	{ ICE_MAC_IPV4_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
 556	{ ICE_MAC_IPV4_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_DOWNLINK },
 557	{ ICE_MAC_IPV6_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
 558	{ ICE_MAC_IPV6_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
 559	{ ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
 560	{ ICE_MAC_IPV6_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_DOWNLINK },
 561	{ ICE_MAC_IPV6_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_DOWNLINK },
 562};
 563
 564static const struct ice_ptype_attributes ice_attr_gtpu_up[] = {
 565	{ ICE_MAC_IPV4_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_UPLINK },
 566	{ ICE_MAC_IPV4_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_UPLINK },
 567	{ ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
 568	{ ICE_MAC_IPV4_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_UPLINK },
 569	{ ICE_MAC_IPV4_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_UPLINK },
 570	{ ICE_MAC_IPV6_GTPU_IPV4_FRAG,	  ICE_PTYPE_ATTR_GTP_UPLINK },
 571	{ ICE_MAC_IPV6_GTPU_IPV4_PAY,	  ICE_PTYPE_ATTR_GTP_UPLINK },
 572	{ ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
 573	{ ICE_MAC_IPV6_GTPU_IPV4_TCP,	  ICE_PTYPE_ATTR_GTP_UPLINK },
 574	{ ICE_MAC_IPV6_GTPU_IPV4_ICMP,	  ICE_PTYPE_ATTR_GTP_UPLINK },
 575	{ ICE_MAC_IPV4_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_UPLINK },
 576	{ ICE_MAC_IPV4_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_UPLINK },
 577	{ ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
 578	{ ICE_MAC_IPV4_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_UPLINK },
 579	{ ICE_MAC_IPV4_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_UPLINK },
 580	{ ICE_MAC_IPV6_GTPU_IPV6_FRAG,	  ICE_PTYPE_ATTR_GTP_UPLINK },
 581	{ ICE_MAC_IPV6_GTPU_IPV6_PAY,	  ICE_PTYPE_ATTR_GTP_UPLINK },
 582	{ ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
 583	{ ICE_MAC_IPV6_GTPU_IPV6_TCP,	  ICE_PTYPE_ATTR_GTP_UPLINK },
 584	{ ICE_MAC_IPV6_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_UPLINK },
 585};
 586
 587static const u32 ice_ptypes_gtpu[] = {
 588	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 589	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 590	0x00000000, 0x00000000, 0x7FFFFE00, 0x00000000,
 591	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 592	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 593	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 594	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 595	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 596};
 597
 598/* Packet types for PPPoE */
 599static const u32 ice_ptypes_pppoe[] = {
 600	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 601	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 602	0x00000000, 0x03ffe000, 0x00000000, 0x00000000,
 603	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 604	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 605	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 606	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 607	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 608};
 609
 610/* Packet types for packets with PFCP NODE header */
 611static const u32 ice_ptypes_pfcp_node[] = {
 612	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 613	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 614	0x00000000, 0x00000000, 0x80000000, 0x00000002,
 615	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 616	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 617	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 618	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 619	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 620};
 621
 622/* Packet types for packets with PFCP SESSION header */
 623static const u32 ice_ptypes_pfcp_session[] = {
 624	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 625	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 626	0x00000000, 0x00000000, 0x00000000, 0x00000005,
 627	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 628	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 629	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 630	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 631	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 632};
 633
 634/* Packet types for L2TPv3 */
 635static const u32 ice_ptypes_l2tpv3[] = {
 636	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 637	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 638	0x00000000, 0x00000000, 0x00000000, 0x00000300,
 639	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 640	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 641	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 642	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 643	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 644};
 645
 646/* Packet types for ESP */
 647static const u32 ice_ptypes_esp[] = {
 648	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 649	0x00000000, 0x00000003, 0x00000000, 0x00000000,
 650	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 651	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 652	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 653	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 654	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 655	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 656};
 657
 658/* Packet types for AH */
 659static const u32 ice_ptypes_ah[] = {
 660	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 661	0x00000000, 0x0000000C, 0x00000000, 0x00000000,
 662	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 663	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 664	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 665	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 666	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 667	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 668};
 669
 670/* Packet types for packets with NAT_T ESP header */
 671static const u32 ice_ptypes_nat_t_esp[] = {
 672	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 673	0x00000000, 0x00000030, 0x00000000, 0x00000000,
 674	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 675	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 676	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 677	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 678	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 679	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 680};
 681
 682static const u32 ice_ptypes_mac_non_ip_ofos[] = {
 683	0x00000846, 0x00000000, 0x00000000, 0x00000000,
 684	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 685	0x00400000, 0x03FFF000, 0x00000000, 0x00000000,
 686	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 687	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 688	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 689	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 690	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 691};
 692
 693/* Manage parameters and info. used during the creation of a flow profile */
 694struct ice_flow_prof_params {
 695	enum ice_block blk;
 696	u16 entry_length; /* # of bytes formatted entry will require */
 697	u8 es_cnt;
 698	struct ice_flow_prof *prof;
 699
 700	/* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0
 701	 * This will give us the direction flags.
 702	 */
 703	struct ice_fv_word es[ICE_MAX_FV_WORDS];
 704	/* attributes can be used to add attributes to a particular PTYPE */
 705	const struct ice_ptype_attributes *attr;
 706	u16 attr_cnt;
 707
 708	u16 mask[ICE_MAX_FV_WORDS];
 709	DECLARE_BITMAP(ptypes, ICE_FLOW_PTYPE_MAX);
 710};
 711
 712#define ICE_FLOW_RSS_HDRS_INNER_MASK \
 713	(ICE_FLOW_SEG_HDR_PPPOE | ICE_FLOW_SEG_HDR_GTPC | \
 714	ICE_FLOW_SEG_HDR_GTPC_TEID | ICE_FLOW_SEG_HDR_GTPU | \
 715	ICE_FLOW_SEG_HDR_PFCP_SESSION | ICE_FLOW_SEG_HDR_L2TPV3 | \
 716	ICE_FLOW_SEG_HDR_ESP | ICE_FLOW_SEG_HDR_AH | \
 717	ICE_FLOW_SEG_HDR_NAT_T_ESP)
 718
 719#define ICE_FLOW_SEG_HDRS_L3_MASK	\
 720	(ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_ARP)
 721#define ICE_FLOW_SEG_HDRS_L4_MASK	\
 722	(ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
 723	 ICE_FLOW_SEG_HDR_SCTP)
 724/* mask for L4 protocols that are NOT part of IPv4/6 OTHER PTYPE groups */
 725#define ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER	\
 726	(ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
 727
 728/**
 729 * ice_flow_val_hdrs - validates packet segments for valid protocol headers
 730 * @segs: array of one or more packet segments that describe the flow
 731 * @segs_cnt: number of packet segments provided
 732 */
 733static int ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt)
 734{
 735	u8 i;
 736
 737	for (i = 0; i < segs_cnt; i++) {
 738		/* Multiple L3 headers */
 739		if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK &&
 740		    !is_power_of_2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK))
 741			return -EINVAL;
 742
 743		/* Multiple L4 headers */
 744		if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK &&
 745		    !is_power_of_2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK))
 746			return -EINVAL;
 747	}
 748
 749	return 0;
 750}
 751
 752/* Sizes of fixed known protocol headers without header options */
 753#define ICE_FLOW_PROT_HDR_SZ_MAC	14
 754#define ICE_FLOW_PROT_HDR_SZ_MAC_VLAN	(ICE_FLOW_PROT_HDR_SZ_MAC + 2)
 755#define ICE_FLOW_PROT_HDR_SZ_IPV4	20
 756#define ICE_FLOW_PROT_HDR_SZ_IPV6	40
 757#define ICE_FLOW_PROT_HDR_SZ_ARP	28
 758#define ICE_FLOW_PROT_HDR_SZ_ICMP	8
 759#define ICE_FLOW_PROT_HDR_SZ_TCP	20
 760#define ICE_FLOW_PROT_HDR_SZ_UDP	8
 761#define ICE_FLOW_PROT_HDR_SZ_SCTP	12
 762
 763/**
 764 * ice_flow_calc_seg_sz - calculates size of a packet segment based on headers
 765 * @params: information about the flow to be processed
 766 * @seg: index of packet segment whose header size is to be determined
 767 */
 768static u16 ice_flow_calc_seg_sz(struct ice_flow_prof_params *params, u8 seg)
 769{
 770	u16 sz;
 771
 772	/* L2 headers */
 773	sz = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_VLAN) ?
 774		ICE_FLOW_PROT_HDR_SZ_MAC_VLAN : ICE_FLOW_PROT_HDR_SZ_MAC;
 775
 776	/* L3 headers */
 777	if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4)
 778		sz += ICE_FLOW_PROT_HDR_SZ_IPV4;
 779	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
 780		sz += ICE_FLOW_PROT_HDR_SZ_IPV6;
 781	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ARP)
 782		sz += ICE_FLOW_PROT_HDR_SZ_ARP;
 783	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)
 784		/* An L3 header is required if L4 is specified */
 785		return 0;
 786
 787	/* L4 headers */
 788	if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ICMP)
 789		sz += ICE_FLOW_PROT_HDR_SZ_ICMP;
 790	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_TCP)
 791		sz += ICE_FLOW_PROT_HDR_SZ_TCP;
 792	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_UDP)
 793		sz += ICE_FLOW_PROT_HDR_SZ_UDP;
 794	else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_SCTP)
 795		sz += ICE_FLOW_PROT_HDR_SZ_SCTP;
 796
 797	return sz;
 798}
 799
 800/**
 801 * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments
 802 * @params: information about the flow to be processed
 803 *
 804 * This function identifies the packet types associated with the protocol
 805 * headers being present in packet segments of the specified flow profile.
 806 */
 807static int ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
 808{
 809	struct ice_flow_prof *prof;
 810	u8 i;
 811
 812	memset(params->ptypes, 0xff, sizeof(params->ptypes));
 813
 814	prof = params->prof;
 815
 816	for (i = 0; i < params->prof->segs_cnt; i++) {
 817		const unsigned long *src;
 818		u32 hdrs;
 819
 820		hdrs = prof->segs[i].hdrs;
 821
 822		if (hdrs & ICE_FLOW_SEG_HDR_ETH) {
 823			src = !i ? (const unsigned long *)ice_ptypes_mac_ofos :
 824				(const unsigned long *)ice_ptypes_mac_il;
 825			bitmap_and(params->ptypes, params->ptypes, src,
 826				   ICE_FLOW_PTYPE_MAX);
 827		}
 828
 829		if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) {
 830			src = (const unsigned long *)ice_ptypes_macvlan_il;
 831			bitmap_and(params->ptypes, params->ptypes, src,
 832				   ICE_FLOW_PTYPE_MAX);
 833		}
 834
 835		if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) {
 836			bitmap_and(params->ptypes, params->ptypes,
 837				   (const unsigned long *)ice_ptypes_arp_of,
 838				   ICE_FLOW_PTYPE_MAX);
 839		}
 840
 841		if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) &&
 842		    (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) {
 843			src = i ? (const unsigned long *)ice_ptypes_ipv4_il :
 844				(const unsigned long *)ice_ptypes_ipv4_ofos_all;
 845			bitmap_and(params->ptypes, params->ptypes, src,
 846				   ICE_FLOW_PTYPE_MAX);
 847		} else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) &&
 848			   (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) {
 849			src = i ? (const unsigned long *)ice_ptypes_ipv6_il :
 850				(const unsigned long *)ice_ptypes_ipv6_ofos_all;
 851			bitmap_and(params->ptypes, params->ptypes, src,
 852				   ICE_FLOW_PTYPE_MAX);
 853		} else if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) &&
 854			   !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) {
 855			src = !i ? (const unsigned long *)ice_ptypes_ipv4_ofos_no_l4 :
 856				(const unsigned long *)ice_ptypes_ipv4_il_no_l4;
 857			bitmap_and(params->ptypes, params->ptypes, src,
 858				   ICE_FLOW_PTYPE_MAX);
 859		} else if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
 860			src = !i ? (const unsigned long *)ice_ptypes_ipv4_ofos :
 861				(const unsigned long *)ice_ptypes_ipv4_il;
 862			bitmap_and(params->ptypes, params->ptypes, src,
 863				   ICE_FLOW_PTYPE_MAX);
 864		} else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) &&
 865			   !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) {
 866			src = !i ? (const unsigned long *)ice_ptypes_ipv6_ofos_no_l4 :
 867				(const unsigned long *)ice_ptypes_ipv6_il_no_l4;
 868			bitmap_and(params->ptypes, params->ptypes, src,
 869				   ICE_FLOW_PTYPE_MAX);
 870		} else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
 871			src = !i ? (const unsigned long *)ice_ptypes_ipv6_ofos :
 872				(const unsigned long *)ice_ptypes_ipv6_il;
 873			bitmap_and(params->ptypes, params->ptypes, src,
 874				   ICE_FLOW_PTYPE_MAX);
 875		}
 876
 877		if (hdrs & ICE_FLOW_SEG_HDR_ETH_NON_IP) {
 878			src = (const unsigned long *)ice_ptypes_mac_non_ip_ofos;
 879			bitmap_and(params->ptypes, params->ptypes, src,
 880				   ICE_FLOW_PTYPE_MAX);
 881		} else if (hdrs & ICE_FLOW_SEG_HDR_PPPOE) {
 882			src = (const unsigned long *)ice_ptypes_pppoe;
 883			bitmap_and(params->ptypes, params->ptypes, src,
 884				   ICE_FLOW_PTYPE_MAX);
 885		} else {
 886			src = (const unsigned long *)ice_ptypes_pppoe;
 887			bitmap_andnot(params->ptypes, params->ptypes, src,
 888				      ICE_FLOW_PTYPE_MAX);
 889		}
 890
 891		if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
 892			src = (const unsigned long *)ice_ptypes_udp_il;
 893			bitmap_and(params->ptypes, params->ptypes, src,
 894				   ICE_FLOW_PTYPE_MAX);
 895		} else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
 896			bitmap_and(params->ptypes, params->ptypes,
 897				   (const unsigned long *)ice_ptypes_tcp_il,
 898				   ICE_FLOW_PTYPE_MAX);
 899		} else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
 900			src = (const unsigned long *)ice_ptypes_sctp_il;
 901			bitmap_and(params->ptypes, params->ptypes, src,
 902				   ICE_FLOW_PTYPE_MAX);
 903		}
 904
 905		if (hdrs & ICE_FLOW_SEG_HDR_ICMP) {
 906			src = !i ? (const unsigned long *)ice_ptypes_icmp_of :
 907				(const unsigned long *)ice_ptypes_icmp_il;
 908			bitmap_and(params->ptypes, params->ptypes, src,
 909				   ICE_FLOW_PTYPE_MAX);
 910		} else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
 911			if (!i) {
 912				src = (const unsigned long *)ice_ptypes_gre_of;
 913				bitmap_and(params->ptypes, params->ptypes,
 914					   src, ICE_FLOW_PTYPE_MAX);
 915			}
 916		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPC) {
 917			src = (const unsigned long *)ice_ptypes_gtpc;
 918			bitmap_and(params->ptypes, params->ptypes, src,
 919				   ICE_FLOW_PTYPE_MAX);
 920		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPC_TEID) {
 921			src = (const unsigned long *)ice_ptypes_gtpc_tid;
 922			bitmap_and(params->ptypes, params->ptypes, src,
 923				   ICE_FLOW_PTYPE_MAX);
 924		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_DWN) {
 925			src = (const unsigned long *)ice_ptypes_gtpu;
 926			bitmap_and(params->ptypes, params->ptypes, src,
 927				   ICE_FLOW_PTYPE_MAX);
 928
 929			/* Attributes for GTP packet with downlink */
 930			params->attr = ice_attr_gtpu_down;
 931			params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_down);
 932		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_UP) {
 933			src = (const unsigned long *)ice_ptypes_gtpu;
 934			bitmap_and(params->ptypes, params->ptypes, src,
 935				   ICE_FLOW_PTYPE_MAX);
 936
 937			/* Attributes for GTP packet with uplink */
 938			params->attr = ice_attr_gtpu_up;
 939			params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_up);
 940		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_EH) {
 941			src = (const unsigned long *)ice_ptypes_gtpu;
 942			bitmap_and(params->ptypes, params->ptypes, src,
 943				   ICE_FLOW_PTYPE_MAX);
 944
 945			/* Attributes for GTP packet with Extension Header */
 946			params->attr = ice_attr_gtpu_eh;
 947			params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_eh);
 948		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_IP) {
 949			src = (const unsigned long *)ice_ptypes_gtpu;
 950			bitmap_and(params->ptypes, params->ptypes, src,
 951				   ICE_FLOW_PTYPE_MAX);
 952		} else if (hdrs & ICE_FLOW_SEG_HDR_L2TPV3) {
 953			src = (const unsigned long *)ice_ptypes_l2tpv3;
 954			bitmap_and(params->ptypes, params->ptypes, src,
 955				   ICE_FLOW_PTYPE_MAX);
 956		} else if (hdrs & ICE_FLOW_SEG_HDR_ESP) {
 957			src = (const unsigned long *)ice_ptypes_esp;
 958			bitmap_and(params->ptypes, params->ptypes, src,
 959				   ICE_FLOW_PTYPE_MAX);
 960		} else if (hdrs & ICE_FLOW_SEG_HDR_AH) {
 961			src = (const unsigned long *)ice_ptypes_ah;
 962			bitmap_and(params->ptypes, params->ptypes, src,
 963				   ICE_FLOW_PTYPE_MAX);
 964		} else if (hdrs & ICE_FLOW_SEG_HDR_NAT_T_ESP) {
 965			src = (const unsigned long *)ice_ptypes_nat_t_esp;
 966			bitmap_and(params->ptypes, params->ptypes, src,
 967				   ICE_FLOW_PTYPE_MAX);
 968		}
 969
 970		if (hdrs & ICE_FLOW_SEG_HDR_PFCP) {
 971			if (hdrs & ICE_FLOW_SEG_HDR_PFCP_NODE)
 972				src = (const unsigned long *)ice_ptypes_pfcp_node;
 973			else
 974				src = (const unsigned long *)ice_ptypes_pfcp_session;
 975
 976			bitmap_and(params->ptypes, params->ptypes, src,
 977				   ICE_FLOW_PTYPE_MAX);
 978		} else {
 979			src = (const unsigned long *)ice_ptypes_pfcp_node;
 980			bitmap_andnot(params->ptypes, params->ptypes, src,
 981				      ICE_FLOW_PTYPE_MAX);
 982
 983			src = (const unsigned long *)ice_ptypes_pfcp_session;
 984			bitmap_andnot(params->ptypes, params->ptypes, src,
 985				      ICE_FLOW_PTYPE_MAX);
 986		}
 987	}
 988
 989	return 0;
 990}
 991
 992/**
 993 * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
 994 * @hw: pointer to the HW struct
 995 * @params: information about the flow to be processed
 996 * @seg: packet segment index of the field to be extracted
 997 * @fld: ID of field to be extracted
 998 * @match: bit field of all fields
 999 *
1000 * This function determines the protocol ID, offset, and size of the given
1001 * field. It then allocates one or more extraction sequence entries for the
1002 * given field, and fill the entries with protocol ID and offset information.
1003 */
1004static int
1005ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
1006		    u8 seg, enum ice_flow_field fld, u64 match)
1007{
1008	enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX;
1009	enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
1010	u8 fv_words = hw->blk[params->blk].es.fvw;
1011	struct ice_flow_fld_info *flds;
1012	u16 cnt, ese_bits, i;
1013	u16 sib_mask = 0;
1014	u16 mask;
1015	u16 off;
1016
1017	flds = params->prof->segs[seg].fields;
1018
1019	switch (fld) {
1020	case ICE_FLOW_FIELD_IDX_ETH_DA:
1021	case ICE_FLOW_FIELD_IDX_ETH_SA:
1022	case ICE_FLOW_FIELD_IDX_S_VLAN:
1023	case ICE_FLOW_FIELD_IDX_C_VLAN:
1024		prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL;
1025		break;
1026	case ICE_FLOW_FIELD_IDX_ETH_TYPE:
1027		prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL;
1028		break;
1029	case ICE_FLOW_FIELD_IDX_IPV4_DSCP:
1030		prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
1031		break;
1032	case ICE_FLOW_FIELD_IDX_IPV6_DSCP:
1033		prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
1034		break;
1035	case ICE_FLOW_FIELD_IDX_IPV4_TTL:
1036	case ICE_FLOW_FIELD_IDX_IPV4_PROT:
1037		prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
1038
1039		/* TTL and PROT share the same extraction seq. entry.
1040		 * Each is considered a sibling to the other in terms of sharing
1041		 * the same extraction sequence entry.
1042		 */
1043		if (fld == ICE_FLOW_FIELD_IDX_IPV4_TTL)
1044			sib = ICE_FLOW_FIELD_IDX_IPV4_PROT;
1045		else if (fld == ICE_FLOW_FIELD_IDX_IPV4_PROT)
1046			sib = ICE_FLOW_FIELD_IDX_IPV4_TTL;
1047
1048		/* If the sibling field is also included, that field's
1049		 * mask needs to be included.
1050		 */
1051		if (match & BIT(sib))
1052			sib_mask = ice_flds_info[sib].mask;
1053		break;
1054	case ICE_FLOW_FIELD_IDX_IPV6_TTL:
1055	case ICE_FLOW_FIELD_IDX_IPV6_PROT:
1056		prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
1057
1058		/* TTL and PROT share the same extraction seq. entry.
1059		 * Each is considered a sibling to the other in terms of sharing
1060		 * the same extraction sequence entry.
1061		 */
1062		if (fld == ICE_FLOW_FIELD_IDX_IPV6_TTL)
1063			sib = ICE_FLOW_FIELD_IDX_IPV6_PROT;
1064		else if (fld == ICE_FLOW_FIELD_IDX_IPV6_PROT)
1065			sib = ICE_FLOW_FIELD_IDX_IPV6_TTL;
1066
1067		/* If the sibling field is also included, that field's
1068		 * mask needs to be included.
1069		 */
1070		if (match & BIT(sib))
1071			sib_mask = ice_flds_info[sib].mask;
1072		break;
1073	case ICE_FLOW_FIELD_IDX_IPV4_SA:
1074	case ICE_FLOW_FIELD_IDX_IPV4_DA:
1075		prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
1076		break;
1077	case ICE_FLOW_FIELD_IDX_IPV6_SA:
1078	case ICE_FLOW_FIELD_IDX_IPV6_DA:
1079		prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
1080		break;
1081	case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
1082	case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
1083	case ICE_FLOW_FIELD_IDX_TCP_FLAGS:
1084		prot_id = ICE_PROT_TCP_IL;
1085		break;
1086	case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
1087	case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
1088		prot_id = ICE_PROT_UDP_IL_OR_S;
1089		break;
1090	case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
1091	case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
1092		prot_id = ICE_PROT_SCTP_IL;
1093		break;
1094	case ICE_FLOW_FIELD_IDX_GTPC_TEID:
1095	case ICE_FLOW_FIELD_IDX_GTPU_IP_TEID:
1096	case ICE_FLOW_FIELD_IDX_GTPU_UP_TEID:
1097	case ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID:
1098	case ICE_FLOW_FIELD_IDX_GTPU_EH_TEID:
1099	case ICE_FLOW_FIELD_IDX_GTPU_EH_QFI:
1100		/* GTP is accessed through UDP OF protocol */
1101		prot_id = ICE_PROT_UDP_OF;
1102		break;
1103	case ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID:
1104		prot_id = ICE_PROT_PPPOE;
1105		break;
1106	case ICE_FLOW_FIELD_IDX_PFCP_SEID:
1107		prot_id = ICE_PROT_UDP_IL_OR_S;
1108		break;
1109	case ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID:
1110		prot_id = ICE_PROT_L2TPV3;
1111		break;
1112	case ICE_FLOW_FIELD_IDX_ESP_SPI:
1113		prot_id = ICE_PROT_ESP_F;
1114		break;
1115	case ICE_FLOW_FIELD_IDX_AH_SPI:
1116		prot_id = ICE_PROT_ESP_2;
1117		break;
1118	case ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI:
1119		prot_id = ICE_PROT_UDP_IL_OR_S;
1120		break;
1121	case ICE_FLOW_FIELD_IDX_ARP_SIP:
1122	case ICE_FLOW_FIELD_IDX_ARP_DIP:
1123	case ICE_FLOW_FIELD_IDX_ARP_SHA:
1124	case ICE_FLOW_FIELD_IDX_ARP_DHA:
1125	case ICE_FLOW_FIELD_IDX_ARP_OP:
1126		prot_id = ICE_PROT_ARP_OF;
1127		break;
1128	case ICE_FLOW_FIELD_IDX_ICMP_TYPE:
1129	case ICE_FLOW_FIELD_IDX_ICMP_CODE:
1130		/* ICMP type and code share the same extraction seq. entry */
1131		prot_id = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) ?
1132				ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL;
1133		sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ?
1134			ICE_FLOW_FIELD_IDX_ICMP_CODE :
1135			ICE_FLOW_FIELD_IDX_ICMP_TYPE;
1136		break;
1137	case ICE_FLOW_FIELD_IDX_GRE_KEYID:
1138		prot_id = ICE_PROT_GRE_OF;
1139		break;
1140	default:
1141		return -EOPNOTSUPP;
1142	}
1143
1144	/* Each extraction sequence entry is a word in size, and extracts a
1145	 * word-aligned offset from a protocol header.
1146	 */
1147	ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;
1148
1149	flds[fld].xtrct.prot_id = prot_id;
1150	flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
1151		ICE_FLOW_FV_EXTRACT_SZ;
1152	flds[fld].xtrct.disp = (u8)(ice_flds_info[fld].off % ese_bits);
1153	flds[fld].xtrct.idx = params->es_cnt;
1154	flds[fld].xtrct.mask = ice_flds_info[fld].mask;
1155
1156	/* Adjust the next field-entry index after accommodating the number of
1157	 * entries this field consumes
1158	 */
1159	cnt = DIV_ROUND_UP(flds[fld].xtrct.disp + ice_flds_info[fld].size,
1160			   ese_bits);
1161
1162	/* Fill in the extraction sequence entries needed for this field */
1163	off = flds[fld].xtrct.off;
1164	mask = flds[fld].xtrct.mask;
1165	for (i = 0; i < cnt; i++) {
1166		/* Only consume an extraction sequence entry if there is no
1167		 * sibling field associated with this field or the sibling entry
1168		 * already extracts the word shared with this field.
1169		 */
1170		if (sib == ICE_FLOW_FIELD_IDX_MAX ||
1171		    flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL ||
1172		    flds[sib].xtrct.off != off) {
1173			u8 idx;
1174
1175			/* Make sure the number of extraction sequence required
1176			 * does not exceed the block's capability
1177			 */
1178			if (params->es_cnt >= fv_words)
1179				return -ENOSPC;
1180
1181			/* some blocks require a reversed field vector layout */
1182			if (hw->blk[params->blk].es.reverse)
1183				idx = fv_words - params->es_cnt - 1;
1184			else
1185				idx = params->es_cnt;
1186
1187			params->es[idx].prot_id = prot_id;
1188			params->es[idx].off = off;
1189			params->mask[idx] = mask | sib_mask;
1190			params->es_cnt++;
1191		}
1192
1193		off += ICE_FLOW_FV_EXTRACT_SZ;
1194	}
1195
1196	return 0;
1197}
1198
1199/**
1200 * ice_flow_xtract_raws - Create extract sequence entries for raw bytes
1201 * @hw: pointer to the HW struct
1202 * @params: information about the flow to be processed
1203 * @seg: index of packet segment whose raw fields are to be extracted
1204 */
1205static int
1206ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
1207		     u8 seg)
1208{
1209	u16 fv_words;
1210	u16 hdrs_sz;
1211	u8 i;
1212
1213	if (!params->prof->segs[seg].raws_cnt)
1214		return 0;
1215
1216	if (params->prof->segs[seg].raws_cnt >
1217	    ARRAY_SIZE(params->prof->segs[seg].raws))
1218		return -ENOSPC;
1219
1220	/* Offsets within the segment headers are not supported */
1221	hdrs_sz = ice_flow_calc_seg_sz(params, seg);
1222	if (!hdrs_sz)
1223		return -EINVAL;
1224
1225	fv_words = hw->blk[params->blk].es.fvw;
1226
1227	for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) {
1228		struct ice_flow_seg_fld_raw *raw;
1229		u16 off, cnt, j;
1230
1231		raw = &params->prof->segs[seg].raws[i];
1232
1233		/* Storing extraction information */
1234		raw->info.xtrct.prot_id = ICE_PROT_MAC_OF_OR_S;
1235		raw->info.xtrct.off = (raw->off / ICE_FLOW_FV_EXTRACT_SZ) *
1236			ICE_FLOW_FV_EXTRACT_SZ;
1237		raw->info.xtrct.disp = (raw->off % ICE_FLOW_FV_EXTRACT_SZ) *
1238			BITS_PER_BYTE;
1239		raw->info.xtrct.idx = params->es_cnt;
1240
1241		/* Determine the number of field vector entries this raw field
1242		 * consumes.
1243		 */
1244		cnt = DIV_ROUND_UP(raw->info.xtrct.disp +
1245				   (raw->info.src.last * BITS_PER_BYTE),
1246				   (ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE));
1247		off = raw->info.xtrct.off;
1248		for (j = 0; j < cnt; j++) {
1249			u16 idx;
1250
1251			/* Make sure the number of extraction sequence required
1252			 * does not exceed the block's capability
1253			 */
1254			if (params->es_cnt >= hw->blk[params->blk].es.count ||
1255			    params->es_cnt >= ICE_MAX_FV_WORDS)
1256				return -ENOSPC;
1257
1258			/* some blocks require a reversed field vector layout */
1259			if (hw->blk[params->blk].es.reverse)
1260				idx = fv_words - params->es_cnt - 1;
1261			else
1262				idx = params->es_cnt;
1263
1264			params->es[idx].prot_id = raw->info.xtrct.prot_id;
1265			params->es[idx].off = off;
1266			params->es_cnt++;
1267			off += ICE_FLOW_FV_EXTRACT_SZ;
1268		}
1269	}
1270
1271	return 0;
1272}
1273
1274/**
1275 * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
1276 * @hw: pointer to the HW struct
1277 * @params: information about the flow to be processed
1278 *
1279 * This function iterates through all matched fields in the given segments, and
1280 * creates an extraction sequence for the fields.
1281 */
1282static int
1283ice_flow_create_xtrct_seq(struct ice_hw *hw,
1284			  struct ice_flow_prof_params *params)
1285{
1286	struct ice_flow_prof *prof = params->prof;
1287	int status = 0;
1288	u8 i;
1289
1290	for (i = 0; i < prof->segs_cnt; i++) {
1291		u64 match = params->prof->segs[i].match;
1292		enum ice_flow_field j;
1293
1294		for_each_set_bit(j, (unsigned long *)&match,
1295				 ICE_FLOW_FIELD_IDX_MAX) {
1296			status = ice_flow_xtract_fld(hw, params, i, j, match);
1297			if (status)
1298				return status;
1299			clear_bit(j, (unsigned long *)&match);
1300		}
1301
1302		/* Process raw matching bytes */
1303		status = ice_flow_xtract_raws(hw, params, i);
1304		if (status)
1305			return status;
1306	}
1307
1308	return status;
1309}
1310
1311/**
1312 * ice_flow_proc_segs - process all packet segments associated with a profile
1313 * @hw: pointer to the HW struct
1314 * @params: information about the flow to be processed
1315 */
1316static int
1317ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
1318{
1319	int status;
1320
1321	status = ice_flow_proc_seg_hdrs(params);
1322	if (status)
1323		return status;
1324
1325	status = ice_flow_create_xtrct_seq(hw, params);
1326	if (status)
1327		return status;
1328
1329	switch (params->blk) {
1330	case ICE_BLK_FD:
1331	case ICE_BLK_RSS:
1332		status = 0;
1333		break;
1334	default:
1335		return -EOPNOTSUPP;
1336	}
1337
1338	return status;
1339}
1340
1341#define ICE_FLOW_FIND_PROF_CHK_FLDS	0x00000001
1342#define ICE_FLOW_FIND_PROF_CHK_VSI	0x00000002
1343#define ICE_FLOW_FIND_PROF_NOT_CHK_DIR	0x00000004
1344#define ICE_FLOW_FIND_PROF_CHK_SYMM	0x00000008
1345
1346/**
1347 * ice_flow_find_prof_conds - Find a profile matching headers and conditions
1348 * @hw: pointer to the HW struct
1349 * @blk: classification stage
1350 * @dir: flow direction
1351 * @segs: array of one or more packet segments that describe the flow
1352 * @segs_cnt: number of packet segments provided
1353 * @symm: symmetric setting for RSS profiles
1354 * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
1355 * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
1356 */
1357static struct ice_flow_prof *
1358ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
1359			 enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
1360			 u8 segs_cnt, bool symm, u16 vsi_handle, u32 conds)
1361{
1362	struct ice_flow_prof *p, *prof = NULL;
1363
1364	mutex_lock(&hw->fl_profs_locks[blk]);
1365	list_for_each_entry(p, &hw->fl_profs[blk], l_entry)
1366		if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&
1367		    segs_cnt && segs_cnt == p->segs_cnt) {
1368			u8 i;
1369
1370			/* Check for profile-VSI association if specified */
1371			if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
1372			    ice_is_vsi_valid(hw, vsi_handle) &&
1373			    !test_bit(vsi_handle, p->vsis))
1374				continue;
1375
1376			/* Check for symmetric settings */
1377			if ((conds & ICE_FLOW_FIND_PROF_CHK_SYMM) &&
1378			    p->symm != symm)
1379				continue;
1380
1381			/* Protocol headers must be checked. Matched fields are
1382			 * checked if specified.
1383			 */
1384			for (i = 0; i < segs_cnt; i++)
1385				if (segs[i].hdrs != p->segs[i].hdrs ||
1386				    ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
1387				     segs[i].match != p->segs[i].match))
1388					break;
1389
1390			/* A match is found if all segments are matched */
1391			if (i == segs_cnt) {
1392				prof = p;
1393				break;
1394			}
1395		}
1396	mutex_unlock(&hw->fl_profs_locks[blk]);
1397
1398	return prof;
1399}
1400
1401/**
1402 * ice_flow_find_prof_id - Look up a profile with given profile ID
1403 * @hw: pointer to the HW struct
1404 * @blk: classification stage
1405 * @prof_id: unique ID to identify this flow profile
1406 */
1407static struct ice_flow_prof *
1408ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1409{
1410	struct ice_flow_prof *p;
1411
1412	list_for_each_entry(p, &hw->fl_profs[blk], l_entry)
1413		if (p->id == prof_id)
1414			return p;
1415
1416	return NULL;
1417}
1418
1419/**
1420 * ice_flow_rem_entry_sync - Remove a flow entry
1421 * @hw: pointer to the HW struct
1422 * @blk: classification stage
1423 * @entry: flow entry to be removed
1424 */
1425static int
1426ice_flow_rem_entry_sync(struct ice_hw *hw, enum ice_block __always_unused blk,
1427			struct ice_flow_entry *entry)
1428{
1429	if (!entry)
1430		return -EINVAL;
1431
1432	list_del(&entry->l_entry);
1433
1434	devm_kfree(ice_hw_to_dev(hw), entry);
1435
1436	return 0;
1437}
1438
1439/**
1440 * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
1441 * @hw: pointer to the HW struct
1442 * @blk: classification stage
1443 * @dir: flow direction
1444 * @segs: array of one or more packet segments that describe the flow
1445 * @segs_cnt: number of packet segments provided
1446 * @symm: symmetric setting for RSS profiles
1447 * @prof: stores the returned flow profile added
1448 *
1449 * Assumption: the caller has acquired the lock to the profile list
1450 */
1451static int
1452ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
1453		       enum ice_flow_dir dir,
1454		       struct ice_flow_seg_info *segs, u8 segs_cnt,
1455		       bool symm, struct ice_flow_prof **prof)
1456{
1457	struct ice_flow_prof_params *params;
1458	struct ice_prof_id *ids;
1459	int status;
1460	u64 prof_id;
1461	u8 i;
1462
1463	if (!prof)
1464		return -EINVAL;
1465
1466	ids = &hw->blk[blk].prof_id;
1467	prof_id = find_first_zero_bit(ids->id, ids->count);
1468	if (prof_id >= ids->count)
1469		return -ENOSPC;
1470
1471	params = kzalloc(sizeof(*params), GFP_KERNEL);
1472	if (!params)
1473		return -ENOMEM;
1474
1475	params->prof = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*params->prof),
1476				    GFP_KERNEL);
1477	if (!params->prof) {
1478		status = -ENOMEM;
1479		goto free_params;
1480	}
1481
1482	/* initialize extraction sequence to all invalid (0xff) */
1483	for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
1484		params->es[i].prot_id = ICE_PROT_INVALID;
1485		params->es[i].off = ICE_FV_OFFSET_INVAL;
1486	}
1487
1488	params->blk = blk;
1489	params->prof->id = prof_id;
1490	params->prof->dir = dir;
1491	params->prof->segs_cnt = segs_cnt;
1492	params->prof->symm = symm;
1493
1494	/* Make a copy of the segments that need to be persistent in the flow
1495	 * profile instance
1496	 */
1497	for (i = 0; i < segs_cnt; i++)
1498		memcpy(&params->prof->segs[i], &segs[i], sizeof(*segs));
1499
1500	status = ice_flow_proc_segs(hw, params);
1501	if (status) {
1502		ice_debug(hw, ICE_DBG_FLOW, "Error processing a flow's packet segments\n");
1503		goto out;
1504	}
1505
1506	/* Add a HW profile for this flow profile */
1507	status = ice_add_prof(hw, blk, prof_id, params->ptypes,
1508			      params->attr, params->attr_cnt, params->es,
1509			      params->mask, symm, true);
1510	if (status) {
1511		ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
1512		goto out;
1513	}
1514
1515	INIT_LIST_HEAD(&params->prof->entries);
1516	mutex_init(&params->prof->entries_lock);
1517	set_bit(prof_id, ids->id);
1518	*prof = params->prof;
1519
1520out:
1521	if (status)
1522		devm_kfree(ice_hw_to_dev(hw), params->prof);
1523free_params:
1524	kfree(params);
1525
1526	return status;
1527}
1528
1529/**
1530 * ice_flow_rem_prof_sync - remove a flow profile
1531 * @hw: pointer to the hardware structure
1532 * @blk: classification stage
1533 * @prof: pointer to flow profile to remove
1534 *
1535 * Assumption: the caller has acquired the lock to the profile list
1536 */
1537static int
1538ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
1539		       struct ice_flow_prof *prof)
1540{
1541	int status;
1542
1543	/* Remove all remaining flow entries before removing the flow profile */
1544	if (!list_empty(&prof->entries)) {
1545		struct ice_flow_entry *e, *t;
1546
1547		mutex_lock(&prof->entries_lock);
1548
1549		list_for_each_entry_safe(e, t, &prof->entries, l_entry) {
1550			status = ice_flow_rem_entry_sync(hw, blk, e);
1551			if (status)
1552				break;
1553		}
1554
1555		mutex_unlock(&prof->entries_lock);
1556	}
1557
1558	/* Remove all hardware profiles associated with this flow profile */
1559	status = ice_rem_prof(hw, blk, prof->id);
1560	if (!status) {
1561		clear_bit(prof->id, hw->blk[blk].prof_id.id);
1562		list_del(&prof->l_entry);
1563		mutex_destroy(&prof->entries_lock);
1564		devm_kfree(ice_hw_to_dev(hw), prof);
1565	}
1566
1567	return status;
1568}
1569
1570/**
1571 * ice_flow_assoc_prof - associate a VSI with a flow profile
1572 * @hw: pointer to the hardware structure
1573 * @blk: classification stage
1574 * @prof: pointer to flow profile
1575 * @vsi_handle: software VSI handle
1576 *
1577 * Assumption: the caller has acquired the lock to the profile list
1578 * and the software VSI handle has been validated
1579 */
1580static int
1581ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
1582		    struct ice_flow_prof *prof, u16 vsi_handle)
1583{
1584	int status = 0;
1585
1586	if (!test_bit(vsi_handle, prof->vsis)) {
1587		status = ice_add_prof_id_flow(hw, blk,
1588					      ice_get_hw_vsi_num(hw,
1589								 vsi_handle),
1590					      prof->id);
1591		if (!status)
1592			set_bit(vsi_handle, prof->vsis);
1593		else
1594			ice_debug(hw, ICE_DBG_FLOW, "HW profile add failed, %d\n",
1595				  status);
1596	}
1597
1598	return status;
1599}
1600
1601/**
1602 * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
1603 * @hw: pointer to the hardware structure
1604 * @blk: classification stage
1605 * @prof: pointer to flow profile
1606 * @vsi_handle: software VSI handle
1607 *
1608 * Assumption: the caller has acquired the lock to the profile list
1609 * and the software VSI handle has been validated
1610 */
1611static int
1612ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
1613		       struct ice_flow_prof *prof, u16 vsi_handle)
1614{
1615	int status = 0;
1616
1617	if (test_bit(vsi_handle, prof->vsis)) {
1618		status = ice_rem_prof_id_flow(hw, blk,
1619					      ice_get_hw_vsi_num(hw,
1620								 vsi_handle),
1621					      prof->id);
1622		if (!status)
1623			clear_bit(vsi_handle, prof->vsis);
1624		else
1625			ice_debug(hw, ICE_DBG_FLOW, "HW profile remove failed, %d\n",
1626				  status);
1627	}
1628
1629	return status;
1630}
1631
1632#define FLAG_GTP_EH_PDU_LINK	BIT_ULL(13)
1633#define FLAG_GTP_EH_PDU		BIT_ULL(14)
1634
1635#define HI_BYTE_IN_WORD		GENMASK(15, 8)
1636#define LO_BYTE_IN_WORD		GENMASK(7, 0)
1637
1638#define FLAG_GTPU_MSK	\
1639	(FLAG_GTP_EH_PDU | FLAG_GTP_EH_PDU_LINK)
1640#define FLAG_GTPU_UP	\
1641	(FLAG_GTP_EH_PDU | FLAG_GTP_EH_PDU_LINK)
1642#define FLAG_GTPU_DW	FLAG_GTP_EH_PDU
1643
1644/**
1645 * ice_flow_set_parser_prof - Set flow profile based on the parsed profile info
1646 * @hw: pointer to the HW struct
1647 * @dest_vsi: dest VSI
1648 * @fdir_vsi: fdir programming VSI
1649 * @prof: stores parsed profile info from raw flow
1650 * @blk: classification blk
1651 *
1652 * Return: 0 on success or negative errno on failure.
1653 */
1654int
1655ice_flow_set_parser_prof(struct ice_hw *hw, u16 dest_vsi, u16 fdir_vsi,
1656			 struct ice_parser_profile *prof, enum ice_block blk)
1657{
1658	u64 id = find_first_bit(prof->ptypes, ICE_FLOW_PTYPE_MAX);
1659	struct ice_flow_prof_params *params __free(kfree);
1660	u8 fv_words = hw->blk[blk].es.fvw;
1661	int status;
1662	int i, idx;
1663
1664	params = kzalloc(sizeof(*params), GFP_KERNEL);
1665	if (!params)
1666		return -ENOMEM;
1667
1668	for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
1669		params->es[i].prot_id = ICE_PROT_INVALID;
1670		params->es[i].off = ICE_FV_OFFSET_INVAL;
1671	}
1672
1673	for (i = 0; i < prof->fv_num; i++) {
1674		if (hw->blk[blk].es.reverse)
1675			idx = fv_words - i - 1;
1676		else
1677			idx = i;
1678		params->es[idx].prot_id = prof->fv[i].proto_id;
1679		params->es[idx].off = prof->fv[i].offset;
1680		params->mask[idx] = (((prof->fv[i].msk) << BITS_PER_BYTE) &
1681				      HI_BYTE_IN_WORD) |
1682				    (((prof->fv[i].msk) >> BITS_PER_BYTE) &
1683				      LO_BYTE_IN_WORD);
1684	}
1685
1686	switch (prof->flags) {
1687	case FLAG_GTPU_DW:
1688		params->attr = ice_attr_gtpu_down;
1689		params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_down);
1690		break;
1691	case FLAG_GTPU_UP:
1692		params->attr = ice_attr_gtpu_up;
1693		params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_up);
1694		break;
1695	default:
1696		if (prof->flags_msk & FLAG_GTPU_MSK) {
1697			params->attr = ice_attr_gtpu_session;
1698			params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_session);
1699		}
1700		break;
1701	}
1702
1703	status = ice_add_prof(hw, blk, id, prof->ptypes,
1704			      params->attr, params->attr_cnt,
1705			      params->es, params->mask, false, false);
1706	if (status)
1707		return status;
1708
1709	status = ice_flow_assoc_fdir_prof(hw, blk, dest_vsi, fdir_vsi, id);
1710	if (status)
1711		ice_rem_prof(hw, blk, id);
1712
1713	return status;
1714}
1715
1716/**
1717 * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
1718 * @hw: pointer to the HW struct
1719 * @blk: classification stage
1720 * @dir: flow direction
1721 * @segs: array of one or more packet segments that describe the flow
1722 * @segs_cnt: number of packet segments provided
1723 * @symm: symmetric setting for RSS profiles
1724 * @prof: stores the returned flow profile added
1725 */
1726int
1727ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1728		  struct ice_flow_seg_info *segs, u8 segs_cnt,
1729		  bool symm, struct ice_flow_prof **prof)
1730{
1731	int status;
1732
1733	if (segs_cnt > ICE_FLOW_SEG_MAX)
1734		return -ENOSPC;
1735
1736	if (!segs_cnt)
1737		return -EINVAL;
1738
1739	if (!segs)
1740		return -EINVAL;
1741
1742	status = ice_flow_val_hdrs(segs, segs_cnt);
1743	if (status)
1744		return status;
1745
1746	mutex_lock(&hw->fl_profs_locks[blk]);
1747
1748	status = ice_flow_add_prof_sync(hw, blk, dir, segs, segs_cnt,
1749					symm, prof);
1750	if (!status)
1751		list_add(&(*prof)->l_entry, &hw->fl_profs[blk]);
1752
1753	mutex_unlock(&hw->fl_profs_locks[blk]);
1754
1755	return status;
1756}
1757
1758/**
1759 * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
1760 * @hw: pointer to the HW struct
1761 * @blk: the block for which the flow profile is to be removed
1762 * @prof_id: unique ID of the flow profile to be removed
1763 */
1764int ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1765{
1766	struct ice_flow_prof *prof;
1767	int status;
1768
1769	mutex_lock(&hw->fl_profs_locks[blk]);
1770
1771	prof = ice_flow_find_prof_id(hw, blk, prof_id);
1772	if (!prof) {
1773		status = -ENOENT;
1774		goto out;
1775	}
1776
1777	/* prof becomes invalid after the call */
1778	status = ice_flow_rem_prof_sync(hw, blk, prof);
1779
1780out:
1781	mutex_unlock(&hw->fl_profs_locks[blk]);
1782
1783	return status;
1784}
1785
1786/**
1787 * ice_flow_add_entry - Add a flow entry
1788 * @hw: pointer to the HW struct
1789 * @blk: classification stage
1790 * @prof_id: ID of the profile to add a new flow entry to
1791 * @entry_id: unique ID to identify this flow entry
1792 * @vsi_handle: software VSI handle for the flow entry
1793 * @prio: priority of the flow entry
1794 * @data: pointer to a data buffer containing flow entry's match values/masks
1795 * @entry_h: pointer to buffer that receives the new flow entry's handle
1796 */
1797int
1798ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1799		   u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio,
1800		   void *data, u64 *entry_h)
1801{
1802	struct ice_flow_entry *e = NULL;
1803	struct ice_flow_prof *prof;
1804	int status;
1805
1806	/* No flow entry data is expected for RSS */
1807	if (!entry_h || (!data && blk != ICE_BLK_RSS))
1808		return -EINVAL;
1809
1810	if (!ice_is_vsi_valid(hw, vsi_handle))
1811		return -EINVAL;
1812
1813	mutex_lock(&hw->fl_profs_locks[blk]);
1814
1815	prof = ice_flow_find_prof_id(hw, blk, prof_id);
1816	if (!prof) {
1817		status = -ENOENT;
1818	} else {
1819		/* Allocate memory for the entry being added and associate
1820		 * the VSI to the found flow profile
1821		 */
1822		e = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*e), GFP_KERNEL);
1823		if (!e)
1824			status = -ENOMEM;
1825		else
1826			status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1827	}
1828
1829	mutex_unlock(&hw->fl_profs_locks[blk]);
1830	if (status)
1831		goto out;
1832
1833	e->id = entry_id;
1834	e->vsi_handle = vsi_handle;
1835	e->prof = prof;
1836	e->priority = prio;
1837
1838	switch (blk) {
1839	case ICE_BLK_FD:
1840	case ICE_BLK_RSS:
1841		break;
1842	default:
1843		status = -EOPNOTSUPP;
1844		goto out;
1845	}
1846
1847	mutex_lock(&prof->entries_lock);
1848	list_add(&e->l_entry, &prof->entries);
1849	mutex_unlock(&prof->entries_lock);
1850
1851	*entry_h = ICE_FLOW_ENTRY_HNDL(e);
1852
1853out:
1854	if (status)
1855		devm_kfree(ice_hw_to_dev(hw), e);
1856
1857	return status;
1858}
1859
1860/**
1861 * ice_flow_rem_entry - Remove a flow entry
1862 * @hw: pointer to the HW struct
1863 * @blk: classification stage
1864 * @entry_h: handle to the flow entry to be removed
1865 */
1866int ice_flow_rem_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_h)
1867{
1868	struct ice_flow_entry *entry;
1869	struct ice_flow_prof *prof;
1870	int status = 0;
1871
1872	if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL)
1873		return -EINVAL;
1874
1875	entry = ICE_FLOW_ENTRY_PTR(entry_h);
1876
1877	/* Retain the pointer to the flow profile as the entry will be freed */
1878	prof = entry->prof;
1879
1880	if (prof) {
1881		mutex_lock(&prof->entries_lock);
1882		status = ice_flow_rem_entry_sync(hw, blk, entry);
1883		mutex_unlock(&prof->entries_lock);
1884	}
1885
1886	return status;
1887}
1888
1889/**
1890 * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
1891 * @seg: packet segment the field being set belongs to
1892 * @fld: field to be set
1893 * @field_type: type of the field
1894 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1895 *           entry's input buffer
1896 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1897 *            input buffer
1898 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1899 *            entry's input buffer
1900 *
1901 * This helper function stores information of a field being matched, including
1902 * the type of the field and the locations of the value to match, the mask, and
1903 * the upper-bound value in the start of the input buffer for a flow entry.
1904 * This function should only be used for fixed-size data structures.
1905 *
1906 * This function also opportunistically determines the protocol headers to be
1907 * present based on the fields being set. Some fields cannot be used alone to
1908 * determine the protocol headers present. Sometimes, fields for particular
1909 * protocol headers are not matched. In those cases, the protocol headers
1910 * must be explicitly set.
1911 */
1912static void
1913ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1914		     enum ice_flow_fld_match_type field_type, u16 val_loc,
1915		     u16 mask_loc, u16 last_loc)
1916{
1917	u64 bit = BIT_ULL(fld);
1918
1919	seg->match |= bit;
1920	if (field_type == ICE_FLOW_FLD_TYPE_RANGE)
1921		seg->range |= bit;
1922
1923	seg->fields[fld].type = field_type;
1924	seg->fields[fld].src.val = val_loc;
1925	seg->fields[fld].src.mask = mask_loc;
1926	seg->fields[fld].src.last = last_loc;
1927
1928	ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
1929}
1930
1931/**
1932 * ice_flow_set_fld - specifies locations of field from entry's input buffer
1933 * @seg: packet segment the field being set belongs to
1934 * @fld: field to be set
1935 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1936 *           entry's input buffer
1937 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1938 *            input buffer
1939 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1940 *            entry's input buffer
1941 * @range: indicate if field being matched is to be in a range
1942 *
1943 * This function specifies the locations, in the form of byte offsets from the
1944 * start of the input buffer for a flow entry, from where the value to match,
1945 * the mask value, and upper value can be extracted. These locations are then
1946 * stored in the flow profile. When adding a flow entry associated with the
1947 * flow profile, these locations will be used to quickly extract the values and
1948 * create the content of a match entry. This function should only be used for
1949 * fixed-size data structures.
1950 */
1951void
1952ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1953		 u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
1954{
1955	enum ice_flow_fld_match_type t = range ?
1956		ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
1957
1958	ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
1959}
1960
1961/**
1962 * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf
1963 * @seg: packet segment the field being set belongs to
1964 * @off: offset of the raw field from the beginning of the segment in bytes
1965 * @len: length of the raw pattern to be matched
1966 * @val_loc: location of the value to match from entry's input buffer
1967 * @mask_loc: location of mask value from entry's input buffer
1968 *
1969 * This function specifies the offset of the raw field to be match from the
1970 * beginning of the specified packet segment, and the locations, in the form of
1971 * byte offsets from the start of the input buffer for a flow entry, from where
1972 * the value to match and the mask value to be extracted. These locations are
1973 * then stored in the flow profile. When adding flow entries to the associated
1974 * flow profile, these locations can be used to quickly extract the values to
1975 * create the content of a match entry. This function should only be used for
1976 * fixed-size data structures.
1977 */
1978void
1979ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len,
1980		     u16 val_loc, u16 mask_loc)
1981{
1982	if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) {
1983		seg->raws[seg->raws_cnt].off = off;
1984		seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE;
1985		seg->raws[seg->raws_cnt].info.src.val = val_loc;
1986		seg->raws[seg->raws_cnt].info.src.mask = mask_loc;
1987		/* The "last" field is used to store the length of the field */
1988		seg->raws[seg->raws_cnt].info.src.last = len;
1989	}
1990
1991	/* Overflows of "raws" will be handled as an error condition later in
1992	 * the flow when this information is processed.
1993	 */
1994	seg->raws_cnt++;
1995}
1996
1997/**
1998 * ice_flow_rem_vsi_prof - remove VSI from flow profile
1999 * @hw: pointer to the hardware structure
2000 * @vsi_handle: software VSI handle
2001 * @prof_id: unique ID to identify this flow profile
2002 *
2003 * This function removes the flow entries associated to the input
2004 * VSI handle and disassociate the VSI from the flow profile.
2005 */
2006int ice_flow_rem_vsi_prof(struct ice_hw *hw, u16 vsi_handle, u64 prof_id)
2007{
2008	struct ice_flow_prof *prof;
2009	int status = 0;
2010
2011	if (!ice_is_vsi_valid(hw, vsi_handle))
2012		return -EINVAL;
2013
2014	/* find flow profile pointer with input package block and profile ID */
2015	prof = ice_flow_find_prof_id(hw, ICE_BLK_FD, prof_id);
2016	if (!prof) {
2017		ice_debug(hw, ICE_DBG_PKG, "Cannot find flow profile id=%llu\n",
2018			  prof_id);
2019		return -ENOENT;
2020	}
2021
2022	/* Remove all remaining flow entries before removing the flow profile */
2023	if (!list_empty(&prof->entries)) {
2024		struct ice_flow_entry *e, *t;
2025
2026		mutex_lock(&prof->entries_lock);
2027		list_for_each_entry_safe(e, t, &prof->entries, l_entry) {
2028			if (e->vsi_handle != vsi_handle)
2029				continue;
2030
2031			status = ice_flow_rem_entry_sync(hw, ICE_BLK_FD, e);
2032			if (status)
2033				break;
2034		}
2035		mutex_unlock(&prof->entries_lock);
2036	}
2037	if (status)
2038		return status;
2039
2040	/* disassociate the flow profile from sw VSI handle */
2041	status = ice_flow_disassoc_prof(hw, ICE_BLK_FD, prof, vsi_handle);
2042	if (status)
2043		ice_debug(hw, ICE_DBG_PKG, "ice_flow_disassoc_prof() failed with status=%d\n",
2044			  status);
2045	return status;
2046}
2047
2048#define ICE_FLOW_RSS_SEG_HDR_L2_MASKS \
2049	(ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
2050
2051#define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
2052	(ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
2053
2054#define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
2055	(ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
2056
2057#define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
2058	(ICE_FLOW_RSS_SEG_HDR_L2_MASKS | \
2059	 ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
2060	 ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
2061
2062/**
2063 * ice_flow_set_rss_seg_info - setup packet segments for RSS
2064 * @segs: pointer to the flow field segment(s)
2065 * @seg_cnt: segment count
2066 * @cfg: configure parameters
2067 *
2068 * Helper function to extract fields from hash bitmap and use flow
2069 * header value to set flow field segment for further use in flow
2070 * profile entry or removal.
2071 */
2072static int
2073ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u8 seg_cnt,
2074			  const struct ice_rss_hash_cfg *cfg)
2075{
2076	struct ice_flow_seg_info *seg;
2077	u64 val;
2078	u16 i;
2079
2080	/* set inner most segment */
2081	seg = &segs[seg_cnt - 1];
2082
2083	for_each_set_bit(i, (const unsigned long *)&cfg->hash_flds,
2084			 (u16)ICE_FLOW_FIELD_IDX_MAX)
2085		ice_flow_set_fld(seg, (enum ice_flow_field)i,
2086				 ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL,
2087				 ICE_FLOW_FLD_OFF_INVAL, false);
2088
2089	ICE_FLOW_SET_HDRS(seg, cfg->addl_hdrs);
2090
2091	/* set outer most header */
2092	if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV4)
2093		segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV4 |
2094						    ICE_FLOW_SEG_HDR_IPV_OTHER;
2095	else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV6)
2096		segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV6 |
2097						    ICE_FLOW_SEG_HDR_IPV_OTHER;
2098
2099	if (seg->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS &
2100	    ~ICE_FLOW_RSS_HDRS_INNER_MASK & ~ICE_FLOW_SEG_HDR_IPV_OTHER)
2101		return -EINVAL;
2102
2103	val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
2104	if (val && !is_power_of_2(val))
2105		return -EIO;
2106
2107	val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
2108	if (val && !is_power_of_2(val))
2109		return -EIO;
2110
2111	return 0;
2112}
2113
2114/**
2115 * ice_rem_vsi_rss_list - remove VSI from RSS list
2116 * @hw: pointer to the hardware structure
2117 * @vsi_handle: software VSI handle
2118 *
2119 * Remove the VSI from all RSS configurations in the list.
2120 */
2121void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
2122{
2123	struct ice_rss_cfg *r, *tmp;
2124
2125	if (list_empty(&hw->rss_list_head))
2126		return;
2127
2128	mutex_lock(&hw->rss_locks);
2129	list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry)
2130		if (test_and_clear_bit(vsi_handle, r->vsis))
2131			if (bitmap_empty(r->vsis, ICE_MAX_VSI)) {
2132				list_del(&r->l_entry);
2133				devm_kfree(ice_hw_to_dev(hw), r);
2134			}
2135	mutex_unlock(&hw->rss_locks);
2136}
2137
2138/**
2139 * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
2140 * @hw: pointer to the hardware structure
2141 * @vsi_handle: software VSI handle
2142 *
2143 * This function will iterate through all flow profiles and disassociate
2144 * the VSI from that profile. If the flow profile has no VSIs it will
2145 * be removed.
2146 */
2147int ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
2148{
2149	const enum ice_block blk = ICE_BLK_RSS;
2150	struct ice_flow_prof *p, *t;
2151	int status = 0;
2152
2153	if (!ice_is_vsi_valid(hw, vsi_handle))
2154		return -EINVAL;
2155
2156	if (list_empty(&hw->fl_profs[blk]))
2157		return 0;
2158
2159	mutex_lock(&hw->rss_locks);
2160	list_for_each_entry_safe(p, t, &hw->fl_profs[blk], l_entry)
2161		if (test_bit(vsi_handle, p->vsis)) {
2162			status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
2163			if (status)
2164				break;
2165
2166			if (bitmap_empty(p->vsis, ICE_MAX_VSI)) {
2167				status = ice_flow_rem_prof(hw, blk, p->id);
2168				if (status)
2169					break;
2170			}
2171		}
2172	mutex_unlock(&hw->rss_locks);
2173
2174	return status;
2175}
2176
2177/**
2178 * ice_get_rss_hdr_type - get a RSS profile's header type
2179 * @prof: RSS flow profile
2180 */
2181static enum ice_rss_cfg_hdr_type
2182ice_get_rss_hdr_type(struct ice_flow_prof *prof)
2183{
2184	if (prof->segs_cnt == ICE_FLOW_SEG_SINGLE) {
2185		return ICE_RSS_OUTER_HEADERS;
2186	} else if (prof->segs_cnt == ICE_FLOW_SEG_MAX) {
2187		const struct ice_flow_seg_info *s;
2188
2189		s = &prof->segs[ICE_RSS_OUTER_HEADERS];
2190		if (s->hdrs == ICE_FLOW_SEG_HDR_NONE)
2191			return ICE_RSS_INNER_HEADERS;
2192		if (s->hdrs & ICE_FLOW_SEG_HDR_IPV4)
2193			return ICE_RSS_INNER_HEADERS_W_OUTER_IPV4;
2194		if (s->hdrs & ICE_FLOW_SEG_HDR_IPV6)
2195			return ICE_RSS_INNER_HEADERS_W_OUTER_IPV6;
2196	}
2197
2198	return ICE_RSS_ANY_HEADERS;
2199}
2200
2201static bool
2202ice_rss_match_prof(struct ice_rss_cfg *r, struct ice_flow_prof *prof,
2203		   enum ice_rss_cfg_hdr_type hdr_type)
2204{
2205	return (r->hash.hdr_type == hdr_type &&
2206		r->hash.hash_flds == prof->segs[prof->segs_cnt - 1].match &&
2207		r->hash.addl_hdrs == prof->segs[prof->segs_cnt - 1].hdrs);
2208}
2209
2210/**
2211 * ice_rem_rss_list - remove RSS configuration from list
2212 * @hw: pointer to the hardware structure
2213 * @vsi_handle: software VSI handle
2214 * @prof: pointer to flow profile
2215 *
2216 * Assumption: lock has already been acquired for RSS list
2217 */
2218static void
2219ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
2220{
2221	enum ice_rss_cfg_hdr_type hdr_type;
2222	struct ice_rss_cfg *r, *tmp;
2223
2224	/* Search for RSS hash fields associated to the VSI that match the
2225	 * hash configurations associated to the flow profile. If found
2226	 * remove from the RSS entry list of the VSI context and delete entry.
2227	 */
2228	hdr_type = ice_get_rss_hdr_type(prof);
2229	list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry)
2230		if (ice_rss_match_prof(r, prof, hdr_type)) {
2231			clear_bit(vsi_handle, r->vsis);
2232			if (bitmap_empty(r->vsis, ICE_MAX_VSI)) {
2233				list_del(&r->l_entry);
2234				devm_kfree(ice_hw_to_dev(hw), r);
2235			}
2236			return;
2237		}
2238}
2239
2240/**
2241 * ice_add_rss_list - add RSS configuration to list
2242 * @hw: pointer to the hardware structure
2243 * @vsi_handle: software VSI handle
2244 * @prof: pointer to flow profile
2245 *
2246 * Assumption: lock has already been acquired for RSS list
2247 */
2248static int
2249ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
2250{
2251	enum ice_rss_cfg_hdr_type hdr_type;
2252	struct ice_rss_cfg *r, *rss_cfg;
2253
2254	hdr_type = ice_get_rss_hdr_type(prof);
2255	list_for_each_entry(r, &hw->rss_list_head, l_entry)
2256		if (ice_rss_match_prof(r, prof, hdr_type)) {
2257			set_bit(vsi_handle, r->vsis);
2258			return 0;
2259		}
2260
2261	rss_cfg = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*rss_cfg),
2262			       GFP_KERNEL);
2263	if (!rss_cfg)
2264		return -ENOMEM;
2265
2266	rss_cfg->hash.hash_flds = prof->segs[prof->segs_cnt - 1].match;
2267	rss_cfg->hash.addl_hdrs = prof->segs[prof->segs_cnt - 1].hdrs;
2268	rss_cfg->hash.hdr_type = hdr_type;
2269	rss_cfg->hash.symm = prof->symm;
2270	set_bit(vsi_handle, rss_cfg->vsis);
2271
2272	list_add_tail(&rss_cfg->l_entry, &hw->rss_list_head);
2273
2274	return 0;
2275}
2276
2277/**
2278 * ice_rss_config_xor_word - set the HSYMM registers for one input set word
2279 * @hw: pointer to the hardware structure
2280 * @prof_id: RSS hardware profile id
2281 * @src: the FV index used by the protocol's source field
2282 * @dst: the FV index used by the protocol's destination field
2283 *
2284 * Write to the HSYMM register with the index of @src FV the value of the @dst
2285 * FV index. This will tell the hardware to XOR HSYMM[src] with INSET[dst]
2286 * while calculating the RSS input set.
2287 */
2288static void
2289ice_rss_config_xor_word(struct ice_hw *hw, u8 prof_id, u8 src, u8 dst)
2290{
2291	u32 val, reg, bits_shift;
2292	u8 reg_idx;
2293
2294	reg_idx = src / GLQF_HSYMM_REG_SIZE;
2295	bits_shift = ((src % GLQF_HSYMM_REG_SIZE) << 3);
2296	val = dst | GLQF_HSYMM_ENABLE_BIT;
2297
2298	reg = rd32(hw, GLQF_HSYMM(prof_id, reg_idx));
2299	reg = (reg & ~(0xff << bits_shift)) | (val << bits_shift);
2300	wr32(hw, GLQF_HSYMM(prof_id, reg_idx), reg);
2301}
2302
2303/**
2304 * ice_rss_config_xor - set the symmetric registers for a profile's protocol
2305 * @hw: pointer to the hardware structure
2306 * @prof_id: RSS hardware profile id
2307 * @src: the FV index used by the protocol's source field
2308 * @dst: the FV index used by the protocol's destination field
2309 * @len: length of the source/destination fields in words
2310 */
2311static void
2312ice_rss_config_xor(struct ice_hw *hw, u8 prof_id, u8 src, u8 dst, u8 len)
2313{
2314	int fv_last_word =
2315		ICE_FLOW_SW_FIELD_VECTOR_MAX / ICE_FLOW_FV_EXTRACT_SZ - 1;
2316	int i;
2317
2318	for (i = 0; i < len; i++) {
2319		ice_rss_config_xor_word(hw, prof_id,
2320					/* Yes, field vector in GLQF_HSYMM and
2321					 * GLQF_HINSET is inversed!
2322					 */
2323					fv_last_word - (src + i),
2324					fv_last_word - (dst + i));
2325		ice_rss_config_xor_word(hw, prof_id,
2326					fv_last_word - (dst + i),
2327					fv_last_word - (src + i));
2328	}
2329}
2330
2331/**
2332 * ice_rss_set_symm - set the symmetric settings for an RSS profile
2333 * @hw: pointer to the hardware structure
2334 * @prof: pointer to flow profile
2335 *
2336 * The symmetric hash will result from XORing the protocol's fields with
2337 * indexes in GLQF_HSYMM and GLQF_HINSET. This function configures the profile's
2338 * GLQF_HSYMM registers.
2339 */
2340static void ice_rss_set_symm(struct ice_hw *hw, struct ice_flow_prof *prof)
2341{
2342	struct ice_prof_map *map;
2343	u8 prof_id, m;
2344
2345	mutex_lock(&hw->blk[ICE_BLK_RSS].es.prof_map_lock);
2346	map = ice_search_prof_id(hw, ICE_BLK_RSS, prof->id);
2347	if (map)
2348		prof_id = map->prof_id;
2349	mutex_unlock(&hw->blk[ICE_BLK_RSS].es.prof_map_lock);
2350
2351	if (!map)
2352		return;
2353
2354	/* clear to default */
2355	for (m = 0; m < GLQF_HSYMM_REG_PER_PROF; m++)
2356		wr32(hw, GLQF_HSYMM(prof_id, m), 0);
2357
2358	if (prof->symm) {
2359		struct ice_flow_seg_xtrct *ipv4_src, *ipv4_dst;
2360		struct ice_flow_seg_xtrct *ipv6_src, *ipv6_dst;
2361		struct ice_flow_seg_xtrct *sctp_src, *sctp_dst;
2362		struct ice_flow_seg_xtrct *tcp_src, *tcp_dst;
2363		struct ice_flow_seg_xtrct *udp_src, *udp_dst;
2364		struct ice_flow_seg_info *seg;
2365
2366		seg = &prof->segs[prof->segs_cnt - 1];
2367
2368		ipv4_src = &seg->fields[ICE_FLOW_FIELD_IDX_IPV4_SA].xtrct;
2369		ipv4_dst = &seg->fields[ICE_FLOW_FIELD_IDX_IPV4_DA].xtrct;
2370
2371		ipv6_src = &seg->fields[ICE_FLOW_FIELD_IDX_IPV6_SA].xtrct;
2372		ipv6_dst = &seg->fields[ICE_FLOW_FIELD_IDX_IPV6_DA].xtrct;
2373
2374		tcp_src = &seg->fields[ICE_FLOW_FIELD_IDX_TCP_SRC_PORT].xtrct;
2375		tcp_dst = &seg->fields[ICE_FLOW_FIELD_IDX_TCP_DST_PORT].xtrct;
2376
2377		udp_src = &seg->fields[ICE_FLOW_FIELD_IDX_UDP_SRC_PORT].xtrct;
2378		udp_dst = &seg->fields[ICE_FLOW_FIELD_IDX_UDP_DST_PORT].xtrct;
2379
2380		sctp_src = &seg->fields[ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT].xtrct;
2381		sctp_dst = &seg->fields[ICE_FLOW_FIELD_IDX_SCTP_DST_PORT].xtrct;
2382
2383		/* xor IPv4 */
2384		if (ipv4_src->prot_id != 0 && ipv4_dst->prot_id != 0)
2385			ice_rss_config_xor(hw, prof_id,
2386					   ipv4_src->idx, ipv4_dst->idx, 2);
2387
2388		/* xor IPv6 */
2389		if (ipv6_src->prot_id != 0 && ipv6_dst->prot_id != 0)
2390			ice_rss_config_xor(hw, prof_id,
2391					   ipv6_src->idx, ipv6_dst->idx, 8);
2392
2393		/* xor TCP */
2394		if (tcp_src->prot_id != 0 && tcp_dst->prot_id != 0)
2395			ice_rss_config_xor(hw, prof_id,
2396					   tcp_src->idx, tcp_dst->idx, 1);
2397
2398		/* xor UDP */
2399		if (udp_src->prot_id != 0 && udp_dst->prot_id != 0)
2400			ice_rss_config_xor(hw, prof_id,
2401					   udp_src->idx, udp_dst->idx, 1);
2402
2403		/* xor SCTP */
2404		if (sctp_src->prot_id != 0 && sctp_dst->prot_id != 0)
2405			ice_rss_config_xor(hw, prof_id,
2406					   sctp_src->idx, sctp_dst->idx, 1);
2407	}
2408}
2409
2410/**
2411 * ice_rss_cfg_raw_symm - Configure symmetric RSS for a raw parser profile
2412 * @hw:      device HW
2413 * @prof:    parser profile describing extracted FV (field vector) entries
2414 * @prof_id: RSS profile identifier used to program symmetry registers
2415 *
2416 * The routine scans the parser profile's FV entries and looks for
2417 * direction-sensitive pairs (L3 src/dst, L4 src/dst). When a pair is found,
2418 * it programs XOR-based symmetry so that flows hash identically regardless
2419 * of packet direction. This preserves CPU affinity for the same 5-tuple.
2420 *
2421 * Notes:
2422 * - The size of each logical field (IPv4/IPv6 address, L4 port) is expressed
2423 *   in units of ICE_FLOW_FV_EXTRACT_SZ so we can step across fv[] correctly.
2424 * - We guard against out-of-bounds access before looking at fv[i + len].
2425 */
2426static void ice_rss_cfg_raw_symm(struct ice_hw *hw,
2427				 const struct ice_parser_profile *prof,
2428				 u64 prof_id)
2429{
2430	for (size_t i = 0; i < prof->fv_num; i++) {
2431		u8 proto_id = prof->fv[i].proto_id;
2432		u16 src_off = 0, dst_off = 0;
2433		size_t src_idx, dst_idx;
2434		bool is_matched = false;
2435		unsigned int len = 0;
2436
2437		switch (proto_id) {
2438		/* IPv4 address pairs (outer/inner variants) */
2439		case ICE_PROT_IPV4_OF_OR_S:
2440		case ICE_PROT_IPV4_IL:
2441		case ICE_PROT_IPV4_IL_IL:
2442			len = ICE_FLOW_FLD_SZ_IPV4_ADDR /
2443			      ICE_FLOW_FV_EXTRACT_SZ;
2444			src_off = ICE_FLOW_FIELD_IPV4_SRC_OFFSET;
2445			dst_off = ICE_FLOW_FIELD_IPV4_DST_OFFSET;
2446			break;
2447
2448		/* IPv6 address pairs (outer/inner variants) */
2449		case ICE_PROT_IPV6_OF_OR_S:
2450		case ICE_PROT_IPV6_IL:
2451		case ICE_PROT_IPV6_IL_IL:
2452			len = ICE_FLOW_FLD_SZ_IPV6_ADDR /
2453			      ICE_FLOW_FV_EXTRACT_SZ;
2454			src_off = ICE_FLOW_FIELD_IPV6_SRC_OFFSET;
2455			dst_off = ICE_FLOW_FIELD_IPV6_DST_OFFSET;
2456			break;
2457
2458		/* L4 port pairs (TCP/UDP/SCTP) */
2459		case ICE_PROT_TCP_IL:
2460		case ICE_PROT_UDP_IL_OR_S:
2461		case ICE_PROT_SCTP_IL:
2462			len = ICE_FLOW_FLD_SZ_PORT / ICE_FLOW_FV_EXTRACT_SZ;
2463			src_off = ICE_FLOW_FIELD_SRC_PORT_OFFSET;
2464			dst_off = ICE_FLOW_FIELD_DST_PORT_OFFSET;
2465			break;
2466
2467		default:
2468			continue;
2469		}
2470
2471		/* Bounds check before accessing fv[i + len]. */
2472		if (i + len >= prof->fv_num)
2473			continue;
2474
2475		/* Verify src/dst pairing for this protocol id. */
2476		is_matched = prof->fv[i].offset == src_off &&
2477			     prof->fv[i + len].proto_id == proto_id &&
2478			     prof->fv[i + len].offset == dst_off;
2479		if (!is_matched)
2480			continue;
2481
2482		/* Program XOR symmetry for this field pair. */
2483		src_idx = i;
2484		dst_idx = i + len;
2485
2486		ice_rss_config_xor(hw, prof_id, src_idx, dst_idx, len);
2487
2488		/* Skip over the pair we just handled; the loop's ++i advances
2489		 * one more element, hence the --i after the jump.
2490		 */
2491		i += (2 * len);
2492		/* not strictly needed; keeps static analyzers happy */
2493		if (i == 0)
2494			break;
2495		--i;
2496	}
2497}
2498
2499/* Max registers index per packet profile */
2500#define ICE_SYMM_REG_INDEX_MAX 6
2501
2502/**
2503 * ice_rss_update_raw_symm - update symmetric hash configuration
2504 * for raw pattern
2505 * @hw: pointer to the hardware structure
2506 * @cfg: configure parameters for raw pattern
2507 * @id: profile tracking ID
2508 *
2509 * Update symmetric hash configuration for raw pattern if required.
2510 * Otherwise only clear to default.
2511 */
2512void
2513ice_rss_update_raw_symm(struct ice_hw *hw,
2514			struct ice_rss_raw_cfg *cfg, u64 id)
2515{
2516	struct ice_prof_map *map;
2517	u8 prof_id, m;
2518
2519	mutex_lock(&hw->blk[ICE_BLK_RSS].es.prof_map_lock);
2520	map = ice_search_prof_id(hw, ICE_BLK_RSS, id);
2521	if (map)
2522		prof_id = map->prof_id;
2523	mutex_unlock(&hw->blk[ICE_BLK_RSS].es.prof_map_lock);
2524	if (!map)
2525		return;
2526	/* clear to default */
2527	for (m = 0; m < ICE_SYMM_REG_INDEX_MAX; m++)
2528		wr32(hw, GLQF_HSYMM(prof_id, m), 0);
2529
2530	if (cfg->symm)
2531		ice_rss_cfg_raw_symm(hw, &cfg->prof, prof_id);
2532}
2533
2534/**
2535 * ice_add_rss_cfg_sync - add an RSS configuration
2536 * @hw: pointer to the hardware structure
2537 * @vsi_handle: software VSI handle
2538 * @cfg: configure parameters
2539 *
2540 * Assumption: lock has already been acquired for RSS list
2541 */
2542static int
2543ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle,
2544		     const struct ice_rss_hash_cfg *cfg)
2545{
2546	const enum ice_block blk = ICE_BLK_RSS;
2547	struct ice_flow_prof *prof = NULL;
2548	struct ice_flow_seg_info *segs;
2549	u8 segs_cnt;
2550	int status;
2551
2552	segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ?
2553			ICE_FLOW_SEG_SINGLE : ICE_FLOW_SEG_MAX;
2554
2555	segs = kcalloc(segs_cnt, sizeof(*segs), GFP_KERNEL);
2556	if (!segs)
2557		return -ENOMEM;
2558
2559	/* Construct the packet segment info from the hashed fields */
2560	status = ice_flow_set_rss_seg_info(segs, segs_cnt, cfg);
2561	if (status)
2562		goto exit;
2563
2564	/* Search for a flow profile that has matching headers, hash fields,
2565	 * symm and has the input VSI associated to it. If found, no further
2566	 * operations required and exit.
2567	 */
2568	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
2569					cfg->symm, vsi_handle,
2570					ICE_FLOW_FIND_PROF_CHK_FLDS |
2571					ICE_FLOW_FIND_PROF_CHK_SYMM |
2572					ICE_FLOW_FIND_PROF_CHK_VSI);
2573	if (prof)
2574		goto exit;
2575
2576	/* Check if a flow profile exists with the same protocol headers and
2577	 * associated with the input VSI. If so disassociate the VSI from
2578	 * this profile. The VSI will be added to a new profile created with
2579	 * the protocol header and new hash field configuration.
2580	 */
2581	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
2582					cfg->symm, vsi_handle,
2583					ICE_FLOW_FIND_PROF_CHK_VSI);
2584	if (prof) {
2585		status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
2586		if (!status)
2587			ice_rem_rss_list(hw, vsi_handle, prof);
2588		else
2589			goto exit;
2590
2591		/* Remove profile if it has no VSIs associated */
2592		if (bitmap_empty(prof->vsis, ICE_MAX_VSI)) {
2593			status = ice_flow_rem_prof(hw, blk, prof->id);
2594			if (status)
2595				goto exit;
2596		}
2597	}
2598
2599	/* Search for a profile that has the same match fields and symmetric
2600	 * setting. If this exists then associate the VSI to this profile.
2601	 */
2602	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
2603					cfg->symm, vsi_handle,
2604					ICE_FLOW_FIND_PROF_CHK_SYMM |
2605					ICE_FLOW_FIND_PROF_CHK_FLDS);
2606	if (prof) {
2607		status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
2608		if (!status)
2609			status = ice_add_rss_list(hw, vsi_handle, prof);
2610		goto exit;
2611	}
2612
2613	/* Create a new flow profile with packet segment information. */
2614	status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
2615				   segs, segs_cnt, cfg->symm, &prof);
2616	if (status)
2617		goto exit;
2618
2619	prof->symm = cfg->symm;
2620	ice_rss_set_symm(hw, prof);
2621	status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
2622	/* If association to a new flow profile failed then this profile can
2623	 * be removed.
2624	 */
2625	if (status) {
2626		ice_flow_rem_prof(hw, blk, prof->id);
2627		goto exit;
2628	}
2629
2630	status = ice_add_rss_list(hw, vsi_handle, prof);
2631
2632exit:
2633	kfree(segs);
2634	return status;
2635}
2636
2637/**
2638 * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
2639 * @hw: pointer to the hardware structure
2640 * @vsi: VSI to add the RSS configuration to
2641 * @cfg: configure parameters
2642 *
2643 * This function will generate a flow profile based on fields associated with
2644 * the input fields to hash on, the flow type and use the VSI number to add
2645 * a flow entry to the profile.
2646 */
2647int
2648ice_add_rss_cfg(struct ice_hw *hw, struct ice_vsi *vsi,
2649		const struct ice_rss_hash_cfg *cfg)
2650{
2651	struct ice_rss_hash_cfg local_cfg;
2652	u16 vsi_handle;
2653	int status;
2654
2655	if (!vsi)
2656		return -EINVAL;
2657
2658	vsi_handle = vsi->idx;
2659	if (!ice_is_vsi_valid(hw, vsi_handle) ||
2660	    !cfg || cfg->hdr_type > ICE_RSS_ANY_HEADERS ||
2661	    cfg->hash_flds == ICE_HASH_INVALID)
2662		return -EINVAL;
2663
2664	mutex_lock(&hw->rss_locks);
2665	local_cfg = *cfg;
2666	if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) {
2667		status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg);
2668	} else {
2669		local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS;
2670		status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg);
2671		if (!status) {
2672			local_cfg.hdr_type = ICE_RSS_INNER_HEADERS;
2673			status = ice_add_rss_cfg_sync(hw, vsi_handle,
2674						      &local_cfg);
2675		}
2676	}
2677	mutex_unlock(&hw->rss_locks);
2678
2679	return status;
2680}
2681
2682/**
2683 * ice_rem_rss_cfg_sync - remove an existing RSS configuration
2684 * @hw: pointer to the hardware structure
2685 * @vsi_handle: software VSI handle
2686 * @cfg: configure parameters
2687 *
2688 * Assumption: lock has already been acquired for RSS list
2689 */
2690static int
2691ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle,
2692		     const struct ice_rss_hash_cfg *cfg)
2693{
2694	const enum ice_block blk = ICE_BLK_RSS;
2695	struct ice_flow_seg_info *segs;
2696	struct ice_flow_prof *prof;
2697	u8 segs_cnt;
2698	int status;
2699
2700	segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ?
2701			ICE_FLOW_SEG_SINGLE : ICE_FLOW_SEG_MAX;
2702	segs = kcalloc(segs_cnt, sizeof(*segs), GFP_KERNEL);
2703	if (!segs)
2704		return -ENOMEM;
2705
2706	/* Construct the packet segment info from the hashed fields */
2707	status = ice_flow_set_rss_seg_info(segs, segs_cnt, cfg);
2708	if (status)
2709		goto out;
2710
2711	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
2712					cfg->symm, vsi_handle,
2713					ICE_FLOW_FIND_PROF_CHK_FLDS);
2714	if (!prof) {
2715		status = -ENOENT;
2716		goto out;
2717	}
2718
2719	status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
2720	if (status)
2721		goto out;
2722
2723	/* Remove RSS configuration from VSI context before deleting
2724	 * the flow profile.
2725	 */
2726	ice_rem_rss_list(hw, vsi_handle, prof);
2727
2728	if (bitmap_empty(prof->vsis, ICE_MAX_VSI))
2729		status = ice_flow_rem_prof(hw, blk, prof->id);
2730
2731out:
2732	kfree(segs);
2733	return status;
2734}
2735
2736/**
2737 * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
2738 * @hw: pointer to the hardware structure
2739 * @vsi_handle: software VSI handle
2740 * @cfg: configure parameters
2741 *
2742 * This function will lookup the flow profile based on the input
2743 * hash field bitmap, iterate through the profile entry list of
2744 * that profile and find entry associated with input VSI to be
2745 * removed. Calls are made to underlying flow apis which will in
2746 * turn build or update buffers for RSS XLT1 section.
2747 */
2748int
2749ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle,
2750		const struct ice_rss_hash_cfg *cfg)
2751{
2752	struct ice_rss_hash_cfg local_cfg;
2753	int status;
2754
2755	if (!ice_is_vsi_valid(hw, vsi_handle) ||
2756	    !cfg || cfg->hdr_type > ICE_RSS_ANY_HEADERS ||
2757	    cfg->hash_flds == ICE_HASH_INVALID)
2758		return -EINVAL;
2759
2760	mutex_lock(&hw->rss_locks);
2761	local_cfg = *cfg;
2762	if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) {
2763		status = ice_rem_rss_cfg_sync(hw, vsi_handle, &local_cfg);
2764	} else {
2765		local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS;
2766		status = ice_rem_rss_cfg_sync(hw, vsi_handle, &local_cfg);
2767		if (!status) {
2768			local_cfg.hdr_type = ICE_RSS_INNER_HEADERS;
2769			status = ice_rem_rss_cfg_sync(hw, vsi_handle,
2770						      &local_cfg);
2771		}
2772	}
2773	mutex_unlock(&hw->rss_locks);
2774
2775	return status;
2776}
2777
2778/* Mapping of AVF hash bit fields to an L3-L4 hash combination.
2779 * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash,
2780 * convert its values to their appropriate flow L3, L4 values.
2781 */
2782#define ICE_FLOW_AVF_RSS_IPV4_MASKS \
2783	(BIT_ULL(LIBIE_FILTER_PCTYPE_NONF_IPV4_OTHER) | \
2784	 BIT_ULL(LIBIE_FILTER_PCTYPE_FRAG_IPV4))
2785#define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \
2786	(BIT_ULL(LIBIE_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK) | \
2787	 BIT_ULL(LIBIE_FILTER_PCTYPE_NONF_IPV4_TCP))
2788#define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \
2789	(BIT_ULL(LIBIE_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) | \
2790	 BIT_ULL(LIBIE_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP) | \
2791	 BIT_ULL(LIBIE_FILTER_PCTYPE_NONF_IPV4_UDP))
2792#define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \
2793	(ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \
2794	 ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(LIBIE_FILTER_PCTYPE_NONF_IPV4_SCTP))
2795
2796#define ICE_FLOW_AVF_RSS_IPV6_MASKS \
2797	(BIT_ULL(LIBIE_FILTER_PCTYPE_NONF_IPV6_OTHER) | \
2798	 BIT_ULL(LIBIE_FILTER_PCTYPE_FRAG_IPV6))
2799#define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \
2800	(BIT_ULL(LIBIE_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) | \
2801	 BIT_ULL(LIBIE_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP) | \
2802	 BIT_ULL(LIBIE_FILTER_PCTYPE_NONF_IPV6_UDP))
2803#define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \
2804	(BIT_ULL(LIBIE_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK) | \
2805	 BIT_ULL(LIBIE_FILTER_PCTYPE_NONF_IPV6_TCP))
2806#define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \
2807	(ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \
2808	 ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(LIBIE_FILTER_PCTYPE_NONF_IPV6_SCTP))
2809
2810/**
2811 * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver
2812 * @hw: pointer to the hardware structure
2813 * @vsi: VF's VSI
2814 * @avf_hash: hash bit fields (LIBIE_FILTER_PCTYPE_*) to configure
2815 *
2816 * This function will take the hash bitmap provided by the AVF driver via a
2817 * message, convert it to ICE-compatible values, and configure RSS flow
2818 * profiles.
2819 */
2820int ice_add_avf_rss_cfg(struct ice_hw *hw, struct ice_vsi *vsi, u64 avf_hash)
2821{
2822	struct ice_rss_hash_cfg hcfg;
2823	u16 vsi_handle;
2824	int status = 0;
2825	u64 hash_flds;
2826
2827	if (!vsi)
2828		return -EINVAL;
2829
2830	vsi_handle = vsi->idx;
2831	if (!avf_hash || !ice_is_vsi_valid(hw, vsi_handle))
2832		return -EINVAL;
2833
2834	/* Make sure no unsupported bits are specified */
2835	if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS |
2836			 ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS))
2837		return -EIO;
2838
2839	hash_flds = avf_hash;
2840
2841	/* Always create an L3 RSS configuration for any L4 RSS configuration */
2842	if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS)
2843		hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS;
2844
2845	if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)
2846		hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS;
2847
2848	/* Create the corresponding RSS configuration for each valid hash bit */
2849	while (hash_flds) {
2850		u64 rss_hash = ICE_HASH_INVALID;
2851
2852		if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) {
2853			if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) {
2854				rss_hash = ICE_FLOW_HASH_IPV4;
2855				hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS;
2856			} else if (hash_flds &
2857				   ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) {
2858				rss_hash = ICE_FLOW_HASH_IPV4 |
2859					ICE_FLOW_HASH_TCP_PORT;
2860				hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS;
2861			} else if (hash_flds &
2862				   ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) {
2863				rss_hash = ICE_FLOW_HASH_IPV4 |
2864					ICE_FLOW_HASH_UDP_PORT;
2865				hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS;
2866			} else if (hash_flds &
2867				   BIT_ULL(LIBIE_FILTER_PCTYPE_NONF_IPV4_SCTP)) {
2868				rss_hash = ICE_FLOW_HASH_IPV4 |
2869					ICE_FLOW_HASH_SCTP_PORT;
2870				hash_flds &=
2871					~BIT_ULL(LIBIE_FILTER_PCTYPE_NONF_IPV4_SCTP);
2872			}
2873		} else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) {
2874			if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) {
2875				rss_hash = ICE_FLOW_HASH_IPV6;
2876				hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS;
2877			} else if (hash_flds &
2878				   ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) {
2879				rss_hash = ICE_FLOW_HASH_IPV6 |
2880					ICE_FLOW_HASH_TCP_PORT;
2881				hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS;
2882			} else if (hash_flds &
2883				   ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) {
2884				rss_hash = ICE_FLOW_HASH_IPV6 |
2885					ICE_FLOW_HASH_UDP_PORT;
2886				hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS;
2887			} else if (hash_flds &
2888				   BIT_ULL(LIBIE_FILTER_PCTYPE_NONF_IPV6_SCTP)) {
2889				rss_hash = ICE_FLOW_HASH_IPV6 |
2890					ICE_FLOW_HASH_SCTP_PORT;
2891				hash_flds &=
2892					~BIT_ULL(LIBIE_FILTER_PCTYPE_NONF_IPV6_SCTP);
2893			}
2894		}
2895
2896		if (rss_hash == ICE_HASH_INVALID)
2897			return -EIO;
2898
2899		hcfg.addl_hdrs = ICE_FLOW_SEG_HDR_NONE;
2900		hcfg.hash_flds = rss_hash;
2901		hcfg.hdr_type = ICE_RSS_ANY_HEADERS;
2902		hcfg.symm = false;
2903		status = ice_add_rss_cfg(hw, vsi, &hcfg);
2904		if (status)
2905			break;
2906	}
2907
2908	return status;
2909}
2910
2911static bool rss_cfg_symm_valid(u64 hfld)
2912{
2913	return !((!!(hfld & ICE_FLOW_HASH_FLD_IPV4_SA) ^
2914		  !!(hfld & ICE_FLOW_HASH_FLD_IPV4_DA)) ||
2915		 (!!(hfld & ICE_FLOW_HASH_FLD_IPV6_SA) ^
2916		  !!(hfld & ICE_FLOW_HASH_FLD_IPV6_DA)) ||
2917		 (!!(hfld & ICE_FLOW_HASH_FLD_TCP_SRC_PORT) ^
2918		  !!(hfld & ICE_FLOW_HASH_FLD_TCP_DST_PORT)) ||
2919		 (!!(hfld & ICE_FLOW_HASH_FLD_UDP_SRC_PORT) ^
2920		  !!(hfld & ICE_FLOW_HASH_FLD_UDP_DST_PORT)) ||
2921		 (!!(hfld & ICE_FLOW_HASH_FLD_SCTP_SRC_PORT) ^
2922		  !!(hfld & ICE_FLOW_HASH_FLD_SCTP_DST_PORT)));
2923}
2924
2925/**
2926 * ice_set_rss_cfg_symm - set symmtery for all VSI's RSS configurations
2927 * @hw: pointer to the hardware structure
2928 * @vsi: VSI to set/unset Symmetric RSS
2929 * @symm: TRUE to set Symmetric RSS hashing
2930 */
2931int ice_set_rss_cfg_symm(struct ice_hw *hw, struct ice_vsi *vsi, bool symm)
2932{
2933	struct ice_rss_hash_cfg	local;
2934	struct ice_rss_cfg *r, *tmp;
2935	u16 vsi_handle = vsi->idx;
2936	int status = 0;
2937
2938	if (!ice_is_vsi_valid(hw, vsi_handle))
2939		return -EINVAL;
2940
2941	mutex_lock(&hw->rss_locks);
2942	list_for_each_entry_safe(r, tmp, &hw->rss_list_head, l_entry) {
2943		if (test_bit(vsi_handle, r->vsis) && r->hash.symm != symm) {
2944			local = r->hash;
2945			local.symm = symm;
2946			if (symm && !rss_cfg_symm_valid(r->hash.hash_flds))
2947				continue;
2948
2949			status = ice_add_rss_cfg_sync(hw, vsi_handle, &local);
2950			if (status)
2951				break;
2952		}
2953	}
2954	mutex_unlock(&hw->rss_locks);
2955
2956	return status;
2957}
2958
2959/**
2960 * ice_replay_rss_cfg - replay RSS configurations associated with VSI
2961 * @hw: pointer to the hardware structure
2962 * @vsi_handle: software VSI handle
2963 */
2964int ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
2965{
2966	struct ice_rss_cfg *r;
2967	int status = 0;
2968
2969	if (!ice_is_vsi_valid(hw, vsi_handle))
2970		return -EINVAL;
2971
2972	mutex_lock(&hw->rss_locks);
2973	list_for_each_entry(r, &hw->rss_list_head, l_entry) {
2974		if (test_bit(vsi_handle, r->vsis)) {
2975			status = ice_add_rss_cfg_sync(hw, vsi_handle, &r->hash);
2976			if (status)
2977				break;
2978		}
2979	}
2980	mutex_unlock(&hw->rss_locks);
2981
2982	return status;
2983}
2984
2985/**
2986 * ice_get_rss_cfg - returns hashed fields for the given header types
2987 * @hw: pointer to the hardware structure
2988 * @vsi_handle: software VSI handle
2989 * @hdrs: protocol header type
2990 * @symm: whether the RSS is symmetric (bool, output)
2991 *
2992 * This function will return the match fields of the first instance of flow
2993 * profile having the given header types and containing input VSI
2994 */
2995u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs, bool *symm)
2996{
2997	u64 rss_hash = ICE_HASH_INVALID;
2998	struct ice_rss_cfg *r;
2999
3000	/* verify if the protocol header is non zero and VSI is valid */
3001	if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
3002		return ICE_HASH_INVALID;
3003
3004	mutex_lock(&hw->rss_locks);
3005	list_for_each_entry(r, &hw->rss_list_head, l_entry)
3006		if (test_bit(vsi_handle, r->vsis) &&
3007		    r->hash.addl_hdrs == hdrs) {
3008			rss_hash = r->hash.hash_flds;
3009			*symm = r->hash.symm;
3010			break;
3011		}
3012	mutex_unlock(&hw->rss_locks);
3013
3014	return rss_hash;
3015}
~/ Read-only file preview.