cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ice_switch.c (189547B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* Copyright (c) 2018, Intel Corporation. */
      3
      4#include "ice_lib.h"
      5#include "ice_switch.h"
      6
      7#define ICE_ETH_DA_OFFSET		0
      8#define ICE_ETH_ETHTYPE_OFFSET		12
      9#define ICE_ETH_VLAN_TCI_OFFSET		14
     10#define ICE_MAX_VLAN_ID			0xFFF
     11#define ICE_IPV6_ETHER_ID		0x86DD
     12
     13/* Dummy ethernet header needed in the ice_aqc_sw_rules_elem
     14 * struct to configure any switch filter rules.
     15 * {DA (6 bytes), SA(6 bytes),
     16 * Ether type (2 bytes for header without VLAN tag) OR
     17 * VLAN tag (4 bytes for header with VLAN tag) }
     18 *
     19 * Word on Hardcoded values
     20 * byte 0 = 0x2: to identify it as locally administered DA MAC
     21 * byte 6 = 0x2: to identify it as locally administered SA MAC
     22 * byte 12 = 0x81 & byte 13 = 0x00:
     23 *	In case of VLAN filter first two bytes defines ether type (0x8100)
     24 *	and remaining two bytes are placeholder for programming a given VLAN ID
     25 *	In case of Ether type filter it is treated as header without VLAN tag
     26 *	and byte 12 and 13 is used to program a given Ether type instead
     27 */
     28#define DUMMY_ETH_HDR_LEN		16
     29static const u8 dummy_eth_header[DUMMY_ETH_HDR_LEN] = { 0x2, 0, 0, 0, 0, 0,
     30							0x2, 0, 0, 0, 0, 0,
     31							0x81, 0, 0, 0};
     32
     33enum {
     34	ICE_PKT_VLAN		= BIT(0),
     35	ICE_PKT_OUTER_IPV6	= BIT(1),
     36	ICE_PKT_TUN_GTPC	= BIT(2),
     37	ICE_PKT_TUN_GTPU	= BIT(3),
     38	ICE_PKT_TUN_NVGRE	= BIT(4),
     39	ICE_PKT_TUN_UDP		= BIT(5),
     40	ICE_PKT_INNER_IPV6	= BIT(6),
     41	ICE_PKT_INNER_TCP	= BIT(7),
     42	ICE_PKT_INNER_UDP	= BIT(8),
     43	ICE_PKT_GTP_NOPAY	= BIT(9),
     44};
     45
     46struct ice_dummy_pkt_offsets {
     47	enum ice_protocol_type type;
     48	u16 offset; /* ICE_PROTOCOL_LAST indicates end of list */
     49};
     50
     51struct ice_dummy_pkt_profile {
     52	const struct ice_dummy_pkt_offsets *offsets;
     53	const u8 *pkt;
     54	u32 match;
     55	u16 pkt_len;
     56};
     57
     58#define ICE_DECLARE_PKT_OFFSETS(type)				\
     59	static const struct ice_dummy_pkt_offsets		\
     60	ice_dummy_##type##_packet_offsets[]
     61
     62#define ICE_DECLARE_PKT_TEMPLATE(type)				\
     63	static const u8 ice_dummy_##type##_packet[]
     64
     65#define ICE_PKT_PROFILE(type, m) {				\
     66	.match		= (m),					\
     67	.pkt		= ice_dummy_##type##_packet,		\
     68	.pkt_len	= sizeof(ice_dummy_##type##_packet),	\
     69	.offsets	= ice_dummy_##type##_packet_offsets,	\
     70}
     71
     72ICE_DECLARE_PKT_OFFSETS(gre_tcp) = {
     73	{ ICE_MAC_OFOS,		0 },
     74	{ ICE_ETYPE_OL,		12 },
     75	{ ICE_IPV4_OFOS,	14 },
     76	{ ICE_NVGRE,		34 },
     77	{ ICE_MAC_IL,		42 },
     78	{ ICE_ETYPE_IL,		54 },
     79	{ ICE_IPV4_IL,		56 },
     80	{ ICE_TCP_IL,		76 },
     81	{ ICE_PROTOCOL_LAST,	0 },
     82};
     83
     84ICE_DECLARE_PKT_TEMPLATE(gre_tcp) = {
     85	0x00, 0x00, 0x00, 0x00,	/* ICE_MAC_OFOS 0 */
     86	0x00, 0x00, 0x00, 0x00,
     87	0x00, 0x00, 0x00, 0x00,
     88
     89	0x08, 0x00,		/* ICE_ETYPE_OL 12 */
     90
     91	0x45, 0x00, 0x00, 0x3E,	/* ICE_IPV4_OFOS 14 */
     92	0x00, 0x00, 0x00, 0x00,
     93	0x00, 0x2F, 0x00, 0x00,
     94	0x00, 0x00, 0x00, 0x00,
     95	0x00, 0x00, 0x00, 0x00,
     96
     97	0x80, 0x00, 0x65, 0x58,	/* ICE_NVGRE 34 */
     98	0x00, 0x00, 0x00, 0x00,
     99
    100	0x00, 0x00, 0x00, 0x00,	/* ICE_MAC_IL 42 */
    101	0x00, 0x00, 0x00, 0x00,
    102	0x00, 0x00, 0x00, 0x00,
    103
    104	0x08, 0x00,		/* ICE_ETYPE_IL 54 */
    105
    106	0x45, 0x00, 0x00, 0x14,	/* ICE_IPV4_IL 56 */
    107	0x00, 0x00, 0x00, 0x00,
    108	0x00, 0x06, 0x00, 0x00,
    109	0x00, 0x00, 0x00, 0x00,
    110	0x00, 0x00, 0x00, 0x00,
    111
    112	0x00, 0x00, 0x00, 0x00,	/* ICE_TCP_IL 76 */
    113	0x00, 0x00, 0x00, 0x00,
    114	0x00, 0x00, 0x00, 0x00,
    115	0x50, 0x02, 0x20, 0x00,
    116	0x00, 0x00, 0x00, 0x00
    117};
    118
    119ICE_DECLARE_PKT_OFFSETS(gre_udp) = {
    120	{ ICE_MAC_OFOS,		0 },
    121	{ ICE_ETYPE_OL,		12 },
    122	{ ICE_IPV4_OFOS,	14 },
    123	{ ICE_NVGRE,		34 },
    124	{ ICE_MAC_IL,		42 },
    125	{ ICE_ETYPE_IL,		54 },
    126	{ ICE_IPV4_IL,		56 },
    127	{ ICE_UDP_ILOS,		76 },
    128	{ ICE_PROTOCOL_LAST,	0 },
    129};
    130
    131ICE_DECLARE_PKT_TEMPLATE(gre_udp) = {
    132	0x00, 0x00, 0x00, 0x00,	/* ICE_MAC_OFOS 0 */
    133	0x00, 0x00, 0x00, 0x00,
    134	0x00, 0x00, 0x00, 0x00,
    135
    136	0x08, 0x00,		/* ICE_ETYPE_OL 12 */
    137
    138	0x45, 0x00, 0x00, 0x3E,	/* ICE_IPV4_OFOS 14 */
    139	0x00, 0x00, 0x00, 0x00,
    140	0x00, 0x2F, 0x00, 0x00,
    141	0x00, 0x00, 0x00, 0x00,
    142	0x00, 0x00, 0x00, 0x00,
    143
    144	0x80, 0x00, 0x65, 0x58,	/* ICE_NVGRE 34 */
    145	0x00, 0x00, 0x00, 0x00,
    146
    147	0x00, 0x00, 0x00, 0x00,	/* ICE_MAC_IL 42 */
    148	0x00, 0x00, 0x00, 0x00,
    149	0x00, 0x00, 0x00, 0x00,
    150
    151	0x08, 0x00,		/* ICE_ETYPE_IL 54 */
    152
    153	0x45, 0x00, 0x00, 0x14,	/* ICE_IPV4_IL 56 */
    154	0x00, 0x00, 0x00, 0x00,
    155	0x00, 0x11, 0x00, 0x00,
    156	0x00, 0x00, 0x00, 0x00,
    157	0x00, 0x00, 0x00, 0x00,
    158
    159	0x00, 0x00, 0x00, 0x00,	/* ICE_UDP_ILOS 76 */
    160	0x00, 0x08, 0x00, 0x00,
    161};
    162
    163ICE_DECLARE_PKT_OFFSETS(udp_tun_tcp) = {
    164	{ ICE_MAC_OFOS,		0 },
    165	{ ICE_ETYPE_OL,		12 },
    166	{ ICE_IPV4_OFOS,	14 },
    167	{ ICE_UDP_OF,		34 },
    168	{ ICE_VXLAN,		42 },
    169	{ ICE_GENEVE,		42 },
    170	{ ICE_VXLAN_GPE,	42 },
    171	{ ICE_MAC_IL,		50 },
    172	{ ICE_ETYPE_IL,		62 },
    173	{ ICE_IPV4_IL,		64 },
    174	{ ICE_TCP_IL,		84 },
    175	{ ICE_PROTOCOL_LAST,	0 },
    176};
    177
    178ICE_DECLARE_PKT_TEMPLATE(udp_tun_tcp) = {
    179	0x00, 0x00, 0x00, 0x00,  /* ICE_MAC_OFOS 0 */
    180	0x00, 0x00, 0x00, 0x00,
    181	0x00, 0x00, 0x00, 0x00,
    182
    183	0x08, 0x00,		/* ICE_ETYPE_OL 12 */
    184
    185	0x45, 0x00, 0x00, 0x5a, /* ICE_IPV4_OFOS 14 */
    186	0x00, 0x01, 0x00, 0x00,
    187	0x40, 0x11, 0x00, 0x00,
    188	0x00, 0x00, 0x00, 0x00,
    189	0x00, 0x00, 0x00, 0x00,
    190
    191	0x00, 0x00, 0x12, 0xb5, /* ICE_UDP_OF 34 */
    192	0x00, 0x46, 0x00, 0x00,
    193
    194	0x00, 0x00, 0x65, 0x58, /* ICE_VXLAN 42 */
    195	0x00, 0x00, 0x00, 0x00,
    196
    197	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 50 */
    198	0x00, 0x00, 0x00, 0x00,
    199	0x00, 0x00, 0x00, 0x00,
    200
    201	0x08, 0x00,		/* ICE_ETYPE_IL 62 */
    202
    203	0x45, 0x00, 0x00, 0x28, /* ICE_IPV4_IL 64 */
    204	0x00, 0x01, 0x00, 0x00,
    205	0x40, 0x06, 0x00, 0x00,
    206	0x00, 0x00, 0x00, 0x00,
    207	0x00, 0x00, 0x00, 0x00,
    208
    209	0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 84 */
    210	0x00, 0x00, 0x00, 0x00,
    211	0x00, 0x00, 0x00, 0x00,
    212	0x50, 0x02, 0x20, 0x00,
    213	0x00, 0x00, 0x00, 0x00
    214};
    215
    216ICE_DECLARE_PKT_OFFSETS(udp_tun_udp) = {
    217	{ ICE_MAC_OFOS,		0 },
    218	{ ICE_ETYPE_OL,		12 },
    219	{ ICE_IPV4_OFOS,	14 },
    220	{ ICE_UDP_OF,		34 },
    221	{ ICE_VXLAN,		42 },
    222	{ ICE_GENEVE,		42 },
    223	{ ICE_VXLAN_GPE,	42 },
    224	{ ICE_MAC_IL,		50 },
    225	{ ICE_ETYPE_IL,		62 },
    226	{ ICE_IPV4_IL,		64 },
    227	{ ICE_UDP_ILOS,		84 },
    228	{ ICE_PROTOCOL_LAST,	0 },
    229};
    230
    231ICE_DECLARE_PKT_TEMPLATE(udp_tun_udp) = {
    232	0x00, 0x00, 0x00, 0x00,  /* ICE_MAC_OFOS 0 */
    233	0x00, 0x00, 0x00, 0x00,
    234	0x00, 0x00, 0x00, 0x00,
    235
    236	0x08, 0x00,		/* ICE_ETYPE_OL 12 */
    237
    238	0x45, 0x00, 0x00, 0x4e, /* ICE_IPV4_OFOS 14 */
    239	0x00, 0x01, 0x00, 0x00,
    240	0x00, 0x11, 0x00, 0x00,
    241	0x00, 0x00, 0x00, 0x00,
    242	0x00, 0x00, 0x00, 0x00,
    243
    244	0x00, 0x00, 0x12, 0xb5, /* ICE_UDP_OF 34 */
    245	0x00, 0x3a, 0x00, 0x00,
    246
    247	0x00, 0x00, 0x65, 0x58, /* ICE_VXLAN 42 */
    248	0x00, 0x00, 0x00, 0x00,
    249
    250	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 50 */
    251	0x00, 0x00, 0x00, 0x00,
    252	0x00, 0x00, 0x00, 0x00,
    253
    254	0x08, 0x00,		/* ICE_ETYPE_IL 62 */
    255
    256	0x45, 0x00, 0x00, 0x1c, /* ICE_IPV4_IL 64 */
    257	0x00, 0x01, 0x00, 0x00,
    258	0x00, 0x11, 0x00, 0x00,
    259	0x00, 0x00, 0x00, 0x00,
    260	0x00, 0x00, 0x00, 0x00,
    261
    262	0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 84 */
    263	0x00, 0x08, 0x00, 0x00,
    264};
    265
    266ICE_DECLARE_PKT_OFFSETS(gre_ipv6_tcp) = {
    267	{ ICE_MAC_OFOS,		0 },
    268	{ ICE_ETYPE_OL,		12 },
    269	{ ICE_IPV4_OFOS,	14 },
    270	{ ICE_NVGRE,		34 },
    271	{ ICE_MAC_IL,		42 },
    272	{ ICE_ETYPE_IL,		54 },
    273	{ ICE_IPV6_IL,		56 },
    274	{ ICE_TCP_IL,		96 },
    275	{ ICE_PROTOCOL_LAST,	0 },
    276};
    277
    278ICE_DECLARE_PKT_TEMPLATE(gre_ipv6_tcp) = {
    279	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
    280	0x00, 0x00, 0x00, 0x00,
    281	0x00, 0x00, 0x00, 0x00,
    282
    283	0x08, 0x00,		/* ICE_ETYPE_OL 12 */
    284
    285	0x45, 0x00, 0x00, 0x66, /* ICE_IPV4_OFOS 14 */
    286	0x00, 0x00, 0x00, 0x00,
    287	0x00, 0x2F, 0x00, 0x00,
    288	0x00, 0x00, 0x00, 0x00,
    289	0x00, 0x00, 0x00, 0x00,
    290
    291	0x80, 0x00, 0x65, 0x58, /* ICE_NVGRE 34 */
    292	0x00, 0x00, 0x00, 0x00,
    293
    294	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 42 */
    295	0x00, 0x00, 0x00, 0x00,
    296	0x00, 0x00, 0x00, 0x00,
    297
    298	0x86, 0xdd,		/* ICE_ETYPE_IL 54 */
    299
    300	0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_IL 56 */
    301	0x00, 0x08, 0x06, 0x40,
    302	0x00, 0x00, 0x00, 0x00,
    303	0x00, 0x00, 0x00, 0x00,
    304	0x00, 0x00, 0x00, 0x00,
    305	0x00, 0x00, 0x00, 0x00,
    306	0x00, 0x00, 0x00, 0x00,
    307	0x00, 0x00, 0x00, 0x00,
    308	0x00, 0x00, 0x00, 0x00,
    309	0x00, 0x00, 0x00, 0x00,
    310
    311	0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 96 */
    312	0x00, 0x00, 0x00, 0x00,
    313	0x00, 0x00, 0x00, 0x00,
    314	0x50, 0x02, 0x20, 0x00,
    315	0x00, 0x00, 0x00, 0x00
    316};
    317
    318ICE_DECLARE_PKT_OFFSETS(gre_ipv6_udp) = {
    319	{ ICE_MAC_OFOS,		0 },
    320	{ ICE_ETYPE_OL,		12 },
    321	{ ICE_IPV4_OFOS,	14 },
    322	{ ICE_NVGRE,		34 },
    323	{ ICE_MAC_IL,		42 },
    324	{ ICE_ETYPE_IL,		54 },
    325	{ ICE_IPV6_IL,		56 },
    326	{ ICE_UDP_ILOS,		96 },
    327	{ ICE_PROTOCOL_LAST,	0 },
    328};
    329
    330ICE_DECLARE_PKT_TEMPLATE(gre_ipv6_udp) = {
    331	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
    332	0x00, 0x00, 0x00, 0x00,
    333	0x00, 0x00, 0x00, 0x00,
    334
    335	0x08, 0x00,		/* ICE_ETYPE_OL 12 */
    336
    337	0x45, 0x00, 0x00, 0x5a, /* ICE_IPV4_OFOS 14 */
    338	0x00, 0x00, 0x00, 0x00,
    339	0x00, 0x2F, 0x00, 0x00,
    340	0x00, 0x00, 0x00, 0x00,
    341	0x00, 0x00, 0x00, 0x00,
    342
    343	0x80, 0x00, 0x65, 0x58, /* ICE_NVGRE 34 */
    344	0x00, 0x00, 0x00, 0x00,
    345
    346	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 42 */
    347	0x00, 0x00, 0x00, 0x00,
    348	0x00, 0x00, 0x00, 0x00,
    349
    350	0x86, 0xdd,		/* ICE_ETYPE_IL 54 */
    351
    352	0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_IL 56 */
    353	0x00, 0x08, 0x11, 0x40,
    354	0x00, 0x00, 0x00, 0x00,
    355	0x00, 0x00, 0x00, 0x00,
    356	0x00, 0x00, 0x00, 0x00,
    357	0x00, 0x00, 0x00, 0x00,
    358	0x00, 0x00, 0x00, 0x00,
    359	0x00, 0x00, 0x00, 0x00,
    360	0x00, 0x00, 0x00, 0x00,
    361	0x00, 0x00, 0x00, 0x00,
    362
    363	0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 96 */
    364	0x00, 0x08, 0x00, 0x00,
    365};
    366
    367ICE_DECLARE_PKT_OFFSETS(udp_tun_ipv6_tcp) = {
    368	{ ICE_MAC_OFOS,		0 },
    369	{ ICE_ETYPE_OL,		12 },
    370	{ ICE_IPV4_OFOS,	14 },
    371	{ ICE_UDP_OF,		34 },
    372	{ ICE_VXLAN,		42 },
    373	{ ICE_GENEVE,		42 },
    374	{ ICE_VXLAN_GPE,	42 },
    375	{ ICE_MAC_IL,		50 },
    376	{ ICE_ETYPE_IL,		62 },
    377	{ ICE_IPV6_IL,		64 },
    378	{ ICE_TCP_IL,		104 },
    379	{ ICE_PROTOCOL_LAST,	0 },
    380};
    381
    382ICE_DECLARE_PKT_TEMPLATE(udp_tun_ipv6_tcp) = {
    383	0x00, 0x00, 0x00, 0x00,  /* ICE_MAC_OFOS 0 */
    384	0x00, 0x00, 0x00, 0x00,
    385	0x00, 0x00, 0x00, 0x00,
    386
    387	0x08, 0x00,		/* ICE_ETYPE_OL 12 */
    388
    389	0x45, 0x00, 0x00, 0x6e, /* ICE_IPV4_OFOS 14 */
    390	0x00, 0x01, 0x00, 0x00,
    391	0x40, 0x11, 0x00, 0x00,
    392	0x00, 0x00, 0x00, 0x00,
    393	0x00, 0x00, 0x00, 0x00,
    394
    395	0x00, 0x00, 0x12, 0xb5, /* ICE_UDP_OF 34 */
    396	0x00, 0x5a, 0x00, 0x00,
    397
    398	0x00, 0x00, 0x65, 0x58, /* ICE_VXLAN 42 */
    399	0x00, 0x00, 0x00, 0x00,
    400
    401	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 50 */
    402	0x00, 0x00, 0x00, 0x00,
    403	0x00, 0x00, 0x00, 0x00,
    404
    405	0x86, 0xdd,		/* ICE_ETYPE_IL 62 */
    406
    407	0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_IL 64 */
    408	0x00, 0x08, 0x06, 0x40,
    409	0x00, 0x00, 0x00, 0x00,
    410	0x00, 0x00, 0x00, 0x00,
    411	0x00, 0x00, 0x00, 0x00,
    412	0x00, 0x00, 0x00, 0x00,
    413	0x00, 0x00, 0x00, 0x00,
    414	0x00, 0x00, 0x00, 0x00,
    415	0x00, 0x00, 0x00, 0x00,
    416	0x00, 0x00, 0x00, 0x00,
    417
    418	0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 104 */
    419	0x00, 0x00, 0x00, 0x00,
    420	0x00, 0x00, 0x00, 0x00,
    421	0x50, 0x02, 0x20, 0x00,
    422	0x00, 0x00, 0x00, 0x00
    423};
    424
    425ICE_DECLARE_PKT_OFFSETS(udp_tun_ipv6_udp) = {
    426	{ ICE_MAC_OFOS,		0 },
    427	{ ICE_ETYPE_OL,		12 },
    428	{ ICE_IPV4_OFOS,	14 },
    429	{ ICE_UDP_OF,		34 },
    430	{ ICE_VXLAN,		42 },
    431	{ ICE_GENEVE,		42 },
    432	{ ICE_VXLAN_GPE,	42 },
    433	{ ICE_MAC_IL,		50 },
    434	{ ICE_ETYPE_IL,		62 },
    435	{ ICE_IPV6_IL,		64 },
    436	{ ICE_UDP_ILOS,		104 },
    437	{ ICE_PROTOCOL_LAST,	0 },
    438};
    439
    440ICE_DECLARE_PKT_TEMPLATE(udp_tun_ipv6_udp) = {
    441	0x00, 0x00, 0x00, 0x00,  /* ICE_MAC_OFOS 0 */
    442	0x00, 0x00, 0x00, 0x00,
    443	0x00, 0x00, 0x00, 0x00,
    444
    445	0x08, 0x00,		/* ICE_ETYPE_OL 12 */
    446
    447	0x45, 0x00, 0x00, 0x62, /* ICE_IPV4_OFOS 14 */
    448	0x00, 0x01, 0x00, 0x00,
    449	0x00, 0x11, 0x00, 0x00,
    450	0x00, 0x00, 0x00, 0x00,
    451	0x00, 0x00, 0x00, 0x00,
    452
    453	0x00, 0x00, 0x12, 0xb5, /* ICE_UDP_OF 34 */
    454	0x00, 0x4e, 0x00, 0x00,
    455
    456	0x00, 0x00, 0x65, 0x58, /* ICE_VXLAN 42 */
    457	0x00, 0x00, 0x00, 0x00,
    458
    459	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 50 */
    460	0x00, 0x00, 0x00, 0x00,
    461	0x00, 0x00, 0x00, 0x00,
    462
    463	0x86, 0xdd,		/* ICE_ETYPE_IL 62 */
    464
    465	0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_IL 64 */
    466	0x00, 0x08, 0x11, 0x40,
    467	0x00, 0x00, 0x00, 0x00,
    468	0x00, 0x00, 0x00, 0x00,
    469	0x00, 0x00, 0x00, 0x00,
    470	0x00, 0x00, 0x00, 0x00,
    471	0x00, 0x00, 0x00, 0x00,
    472	0x00, 0x00, 0x00, 0x00,
    473	0x00, 0x00, 0x00, 0x00,
    474	0x00, 0x00, 0x00, 0x00,
    475
    476	0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 104 */
    477	0x00, 0x08, 0x00, 0x00,
    478};
    479
    480/* offset info for MAC + IPv4 + UDP dummy packet */
    481ICE_DECLARE_PKT_OFFSETS(udp) = {
    482	{ ICE_MAC_OFOS,		0 },
    483	{ ICE_ETYPE_OL,		12 },
    484	{ ICE_IPV4_OFOS,	14 },
    485	{ ICE_UDP_ILOS,		34 },
    486	{ ICE_PROTOCOL_LAST,	0 },
    487};
    488
    489/* Dummy packet for MAC + IPv4 + UDP */
    490ICE_DECLARE_PKT_TEMPLATE(udp) = {
    491	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
    492	0x00, 0x00, 0x00, 0x00,
    493	0x00, 0x00, 0x00, 0x00,
    494
    495	0x08, 0x00,		/* ICE_ETYPE_OL 12 */
    496
    497	0x45, 0x00, 0x00, 0x1c, /* ICE_IPV4_OFOS 14 */
    498	0x00, 0x01, 0x00, 0x00,
    499	0x00, 0x11, 0x00, 0x00,
    500	0x00, 0x00, 0x00, 0x00,
    501	0x00, 0x00, 0x00, 0x00,
    502
    503	0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 34 */
    504	0x00, 0x08, 0x00, 0x00,
    505
    506	0x00, 0x00,	/* 2 bytes for 4 byte alignment */
    507};
    508
    509/* offset info for MAC + VLAN + IPv4 + UDP dummy packet */
    510ICE_DECLARE_PKT_OFFSETS(vlan_udp) = {
    511	{ ICE_MAC_OFOS,		0 },
    512	{ ICE_VLAN_OFOS,	12 },
    513	{ ICE_ETYPE_OL,		16 },
    514	{ ICE_IPV4_OFOS,	18 },
    515	{ ICE_UDP_ILOS,		38 },
    516	{ ICE_PROTOCOL_LAST,	0 },
    517};
    518
    519/* C-tag (801.1Q), IPv4:UDP dummy packet */
    520ICE_DECLARE_PKT_TEMPLATE(vlan_udp) = {
    521	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
    522	0x00, 0x00, 0x00, 0x00,
    523	0x00, 0x00, 0x00, 0x00,
    524
    525	0x81, 0x00, 0x00, 0x00, /* ICE_VLAN_OFOS 12 */
    526
    527	0x08, 0x00,		/* ICE_ETYPE_OL 16 */
    528
    529	0x45, 0x00, 0x00, 0x1c, /* ICE_IPV4_OFOS 18 */
    530	0x00, 0x01, 0x00, 0x00,
    531	0x00, 0x11, 0x00, 0x00,
    532	0x00, 0x00, 0x00, 0x00,
    533	0x00, 0x00, 0x00, 0x00,
    534
    535	0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 38 */
    536	0x00, 0x08, 0x00, 0x00,
    537
    538	0x00, 0x00,	/* 2 bytes for 4 byte alignment */
    539};
    540
    541/* offset info for MAC + IPv4 + TCP dummy packet */
    542ICE_DECLARE_PKT_OFFSETS(tcp) = {
    543	{ ICE_MAC_OFOS,		0 },
    544	{ ICE_ETYPE_OL,		12 },
    545	{ ICE_IPV4_OFOS,	14 },
    546	{ ICE_TCP_IL,		34 },
    547	{ ICE_PROTOCOL_LAST,	0 },
    548};
    549
    550/* Dummy packet for MAC + IPv4 + TCP */
    551ICE_DECLARE_PKT_TEMPLATE(tcp) = {
    552	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
    553	0x00, 0x00, 0x00, 0x00,
    554	0x00, 0x00, 0x00, 0x00,
    555
    556	0x08, 0x00,		/* ICE_ETYPE_OL 12 */
    557
    558	0x45, 0x00, 0x00, 0x28, /* ICE_IPV4_OFOS 14 */
    559	0x00, 0x01, 0x00, 0x00,
    560	0x00, 0x06, 0x00, 0x00,
    561	0x00, 0x00, 0x00, 0x00,
    562	0x00, 0x00, 0x00, 0x00,
    563
    564	0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 34 */
    565	0x00, 0x00, 0x00, 0x00,
    566	0x00, 0x00, 0x00, 0x00,
    567	0x50, 0x00, 0x00, 0x00,
    568	0x00, 0x00, 0x00, 0x00,
    569
    570	0x00, 0x00,	/* 2 bytes for 4 byte alignment */
    571};
    572
    573/* offset info for MAC + VLAN (C-tag, 802.1Q) + IPv4 + TCP dummy packet */
    574ICE_DECLARE_PKT_OFFSETS(vlan_tcp) = {
    575	{ ICE_MAC_OFOS,		0 },
    576	{ ICE_VLAN_OFOS,	12 },
    577	{ ICE_ETYPE_OL,		16 },
    578	{ ICE_IPV4_OFOS,	18 },
    579	{ ICE_TCP_IL,		38 },
    580	{ ICE_PROTOCOL_LAST,	0 },
    581};
    582
    583/* C-tag (801.1Q), IPv4:TCP dummy packet */
    584ICE_DECLARE_PKT_TEMPLATE(vlan_tcp) = {
    585	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
    586	0x00, 0x00, 0x00, 0x00,
    587	0x00, 0x00, 0x00, 0x00,
    588
    589	0x81, 0x00, 0x00, 0x00,	/* ICE_VLAN_OFOS 12 */
    590
    591	0x08, 0x00,		/* ICE_ETYPE_OL 16 */
    592
    593	0x45, 0x00, 0x00, 0x28, /* ICE_IPV4_OFOS 18 */
    594	0x00, 0x01, 0x00, 0x00,
    595	0x00, 0x06, 0x00, 0x00,
    596	0x00, 0x00, 0x00, 0x00,
    597	0x00, 0x00, 0x00, 0x00,
    598
    599	0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 38 */
    600	0x00, 0x00, 0x00, 0x00,
    601	0x00, 0x00, 0x00, 0x00,
    602	0x50, 0x00, 0x00, 0x00,
    603	0x00, 0x00, 0x00, 0x00,
    604
    605	0x00, 0x00,	/* 2 bytes for 4 byte alignment */
    606};
    607
    608ICE_DECLARE_PKT_OFFSETS(tcp_ipv6) = {
    609	{ ICE_MAC_OFOS,		0 },
    610	{ ICE_ETYPE_OL,		12 },
    611	{ ICE_IPV6_OFOS,	14 },
    612	{ ICE_TCP_IL,		54 },
    613	{ ICE_PROTOCOL_LAST,	0 },
    614};
    615
    616ICE_DECLARE_PKT_TEMPLATE(tcp_ipv6) = {
    617	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
    618	0x00, 0x00, 0x00, 0x00,
    619	0x00, 0x00, 0x00, 0x00,
    620
    621	0x86, 0xDD,		/* ICE_ETYPE_OL 12 */
    622
    623	0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 40 */
    624	0x00, 0x14, 0x06, 0x00, /* Next header is TCP */
    625	0x00, 0x00, 0x00, 0x00,
    626	0x00, 0x00, 0x00, 0x00,
    627	0x00, 0x00, 0x00, 0x00,
    628	0x00, 0x00, 0x00, 0x00,
    629	0x00, 0x00, 0x00, 0x00,
    630	0x00, 0x00, 0x00, 0x00,
    631	0x00, 0x00, 0x00, 0x00,
    632	0x00, 0x00, 0x00, 0x00,
    633
    634	0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 54 */
    635	0x00, 0x00, 0x00, 0x00,
    636	0x00, 0x00, 0x00, 0x00,
    637	0x50, 0x00, 0x00, 0x00,
    638	0x00, 0x00, 0x00, 0x00,
    639
    640	0x00, 0x00, /* 2 bytes for 4 byte alignment */
    641};
    642
    643/* C-tag (802.1Q): IPv6 + TCP */
    644ICE_DECLARE_PKT_OFFSETS(vlan_tcp_ipv6) = {
    645	{ ICE_MAC_OFOS,		0 },
    646	{ ICE_VLAN_OFOS,	12 },
    647	{ ICE_ETYPE_OL,		16 },
    648	{ ICE_IPV6_OFOS,	18 },
    649	{ ICE_TCP_IL,		58 },
    650	{ ICE_PROTOCOL_LAST,	0 },
    651};
    652
    653/* C-tag (802.1Q), IPv6 + TCP dummy packet */
    654ICE_DECLARE_PKT_TEMPLATE(vlan_tcp_ipv6) = {
    655	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
    656	0x00, 0x00, 0x00, 0x00,
    657	0x00, 0x00, 0x00, 0x00,
    658
    659	0x81, 0x00, 0x00, 0x00,	/* ICE_VLAN_OFOS 12 */
    660
    661	0x86, 0xDD,		/* ICE_ETYPE_OL 16 */
    662
    663	0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 18 */
    664	0x00, 0x14, 0x06, 0x00, /* Next header is TCP */
    665	0x00, 0x00, 0x00, 0x00,
    666	0x00, 0x00, 0x00, 0x00,
    667	0x00, 0x00, 0x00, 0x00,
    668	0x00, 0x00, 0x00, 0x00,
    669	0x00, 0x00, 0x00, 0x00,
    670	0x00, 0x00, 0x00, 0x00,
    671	0x00, 0x00, 0x00, 0x00,
    672	0x00, 0x00, 0x00, 0x00,
    673
    674	0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 58 */
    675	0x00, 0x00, 0x00, 0x00,
    676	0x00, 0x00, 0x00, 0x00,
    677	0x50, 0x00, 0x00, 0x00,
    678	0x00, 0x00, 0x00, 0x00,
    679
    680	0x00, 0x00, /* 2 bytes for 4 byte alignment */
    681};
    682
    683/* IPv6 + UDP */
    684ICE_DECLARE_PKT_OFFSETS(udp_ipv6) = {
    685	{ ICE_MAC_OFOS,		0 },
    686	{ ICE_ETYPE_OL,		12 },
    687	{ ICE_IPV6_OFOS,	14 },
    688	{ ICE_UDP_ILOS,		54 },
    689	{ ICE_PROTOCOL_LAST,	0 },
    690};
    691
    692/* IPv6 + UDP dummy packet */
    693ICE_DECLARE_PKT_TEMPLATE(udp_ipv6) = {
    694	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
    695	0x00, 0x00, 0x00, 0x00,
    696	0x00, 0x00, 0x00, 0x00,
    697
    698	0x86, 0xDD,		/* ICE_ETYPE_OL 12 */
    699
    700	0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 40 */
    701	0x00, 0x10, 0x11, 0x00, /* Next header UDP */
    702	0x00, 0x00, 0x00, 0x00,
    703	0x00, 0x00, 0x00, 0x00,
    704	0x00, 0x00, 0x00, 0x00,
    705	0x00, 0x00, 0x00, 0x00,
    706	0x00, 0x00, 0x00, 0x00,
    707	0x00, 0x00, 0x00, 0x00,
    708	0x00, 0x00, 0x00, 0x00,
    709	0x00, 0x00, 0x00, 0x00,
    710
    711	0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 54 */
    712	0x00, 0x10, 0x00, 0x00,
    713
    714	0x00, 0x00, 0x00, 0x00, /* needed for ESP packets */
    715	0x00, 0x00, 0x00, 0x00,
    716
    717	0x00, 0x00, /* 2 bytes for 4 byte alignment */
    718};
    719
    720/* C-tag (802.1Q): IPv6 + UDP */
    721ICE_DECLARE_PKT_OFFSETS(vlan_udp_ipv6) = {
    722	{ ICE_MAC_OFOS,		0 },
    723	{ ICE_VLAN_OFOS,	12 },
    724	{ ICE_ETYPE_OL,		16 },
    725	{ ICE_IPV6_OFOS,	18 },
    726	{ ICE_UDP_ILOS,		58 },
    727	{ ICE_PROTOCOL_LAST,	0 },
    728};
    729
    730/* C-tag (802.1Q), IPv6 + UDP dummy packet */
    731ICE_DECLARE_PKT_TEMPLATE(vlan_udp_ipv6) = {
    732	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
    733	0x00, 0x00, 0x00, 0x00,
    734	0x00, 0x00, 0x00, 0x00,
    735
    736	0x81, 0x00, 0x00, 0x00,/* ICE_VLAN_OFOS 12 */
    737
    738	0x86, 0xDD,		/* ICE_ETYPE_OL 16 */
    739
    740	0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 18 */
    741	0x00, 0x08, 0x11, 0x00, /* Next header UDP */
    742	0x00, 0x00, 0x00, 0x00,
    743	0x00, 0x00, 0x00, 0x00,
    744	0x00, 0x00, 0x00, 0x00,
    745	0x00, 0x00, 0x00, 0x00,
    746	0x00, 0x00, 0x00, 0x00,
    747	0x00, 0x00, 0x00, 0x00,
    748	0x00, 0x00, 0x00, 0x00,
    749	0x00, 0x00, 0x00, 0x00,
    750
    751	0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 58 */
    752	0x00, 0x08, 0x00, 0x00,
    753
    754	0x00, 0x00, /* 2 bytes for 4 byte alignment */
    755};
    756
    757/* Outer IPv4 + Outer UDP + GTP + Inner IPv4 + Inner TCP */
    758ICE_DECLARE_PKT_OFFSETS(ipv4_gtpu_ipv4_tcp) = {
    759	{ ICE_MAC_OFOS,		0 },
    760	{ ICE_IPV4_OFOS,	14 },
    761	{ ICE_UDP_OF,		34 },
    762	{ ICE_GTP,		42 },
    763	{ ICE_IPV4_IL,		62 },
    764	{ ICE_TCP_IL,		82 },
    765	{ ICE_PROTOCOL_LAST,	0 },
    766};
    767
    768ICE_DECLARE_PKT_TEMPLATE(ipv4_gtpu_ipv4_tcp) = {
    769	0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
    770	0x00, 0x00, 0x00, 0x00,
    771	0x00, 0x00, 0x00, 0x00,
    772	0x08, 0x00,
    773
    774	0x45, 0x00, 0x00, 0x58, /* IP 14 */
    775	0x00, 0x00, 0x00, 0x00,
    776	0x00, 0x11, 0x00, 0x00,
    777	0x00, 0x00, 0x00, 0x00,
    778	0x00, 0x00, 0x00, 0x00,
    779
    780	0x00, 0x00, 0x08, 0x68, /* UDP 34 */
    781	0x00, 0x44, 0x00, 0x00,
    782
    783	0x34, 0xff, 0x00, 0x34, /* ICE_GTP Header 42 */
    784	0x00, 0x00, 0x00, 0x00,
    785	0x00, 0x00, 0x00, 0x85,
    786
    787	0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 54 */
    788	0x00, 0x00, 0x00, 0x00,
    789
    790	0x45, 0x00, 0x00, 0x28, /* IP 62 */
    791	0x00, 0x00, 0x00, 0x00,
    792	0x00, 0x06, 0x00, 0x00,
    793	0x00, 0x00, 0x00, 0x00,
    794	0x00, 0x00, 0x00, 0x00,
    795
    796	0x00, 0x00, 0x00, 0x00, /* TCP 82 */
    797	0x00, 0x00, 0x00, 0x00,
    798	0x00, 0x00, 0x00, 0x00,
    799	0x50, 0x00, 0x00, 0x00,
    800	0x00, 0x00, 0x00, 0x00,
    801
    802	0x00, 0x00, /* 2 bytes for 4 byte alignment */
    803};
    804
    805/* Outer IPv4 + Outer UDP + GTP + Inner IPv4 + Inner UDP */
    806ICE_DECLARE_PKT_OFFSETS(ipv4_gtpu_ipv4_udp) = {
    807	{ ICE_MAC_OFOS,		0 },
    808	{ ICE_IPV4_OFOS,	14 },
    809	{ ICE_UDP_OF,		34 },
    810	{ ICE_GTP,		42 },
    811	{ ICE_IPV4_IL,		62 },
    812	{ ICE_UDP_ILOS,		82 },
    813	{ ICE_PROTOCOL_LAST,	0 },
    814};
    815
    816ICE_DECLARE_PKT_TEMPLATE(ipv4_gtpu_ipv4_udp) = {
    817	0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
    818	0x00, 0x00, 0x00, 0x00,
    819	0x00, 0x00, 0x00, 0x00,
    820	0x08, 0x00,
    821
    822	0x45, 0x00, 0x00, 0x4c, /* IP 14 */
    823	0x00, 0x00, 0x00, 0x00,
    824	0x00, 0x11, 0x00, 0x00,
    825	0x00, 0x00, 0x00, 0x00,
    826	0x00, 0x00, 0x00, 0x00,
    827
    828	0x00, 0x00, 0x08, 0x68, /* UDP 34 */
    829	0x00, 0x38, 0x00, 0x00,
    830
    831	0x34, 0xff, 0x00, 0x28, /* ICE_GTP Header 42 */
    832	0x00, 0x00, 0x00, 0x00,
    833	0x00, 0x00, 0x00, 0x85,
    834
    835	0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 54 */
    836	0x00, 0x00, 0x00, 0x00,
    837
    838	0x45, 0x00, 0x00, 0x1c, /* IP 62 */
    839	0x00, 0x00, 0x00, 0x00,
    840	0x00, 0x11, 0x00, 0x00,
    841	0x00, 0x00, 0x00, 0x00,
    842	0x00, 0x00, 0x00, 0x00,
    843
    844	0x00, 0x00, 0x00, 0x00, /* UDP 82 */
    845	0x00, 0x08, 0x00, 0x00,
    846
    847	0x00, 0x00, /* 2 bytes for 4 byte alignment */
    848};
    849
    850/* Outer IPv6 + Outer UDP + GTP + Inner IPv4 + Inner TCP */
    851ICE_DECLARE_PKT_OFFSETS(ipv4_gtpu_ipv6_tcp) = {
    852	{ ICE_MAC_OFOS,		0 },
    853	{ ICE_IPV4_OFOS,	14 },
    854	{ ICE_UDP_OF,		34 },
    855	{ ICE_GTP,		42 },
    856	{ ICE_IPV6_IL,		62 },
    857	{ ICE_TCP_IL,		102 },
    858	{ ICE_PROTOCOL_LAST,	0 },
    859};
    860
    861ICE_DECLARE_PKT_TEMPLATE(ipv4_gtpu_ipv6_tcp) = {
    862	0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
    863	0x00, 0x00, 0x00, 0x00,
    864	0x00, 0x00, 0x00, 0x00,
    865	0x08, 0x00,
    866
    867	0x45, 0x00, 0x00, 0x6c, /* IP 14 */
    868	0x00, 0x00, 0x00, 0x00,
    869	0x00, 0x11, 0x00, 0x00,
    870	0x00, 0x00, 0x00, 0x00,
    871	0x00, 0x00, 0x00, 0x00,
    872
    873	0x00, 0x00, 0x08, 0x68, /* UDP 34 */
    874	0x00, 0x58, 0x00, 0x00,
    875
    876	0x34, 0xff, 0x00, 0x48, /* ICE_GTP Header 42 */
    877	0x00, 0x00, 0x00, 0x00,
    878	0x00, 0x00, 0x00, 0x85,
    879
    880	0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 54 */
    881	0x00, 0x00, 0x00, 0x00,
    882
    883	0x60, 0x00, 0x00, 0x00, /* IPv6 62 */
    884	0x00, 0x14, 0x06, 0x00,
    885	0x00, 0x00, 0x00, 0x00,
    886	0x00, 0x00, 0x00, 0x00,
    887	0x00, 0x00, 0x00, 0x00,
    888	0x00, 0x00, 0x00, 0x00,
    889	0x00, 0x00, 0x00, 0x00,
    890	0x00, 0x00, 0x00, 0x00,
    891	0x00, 0x00, 0x00, 0x00,
    892	0x00, 0x00, 0x00, 0x00,
    893
    894	0x00, 0x00, 0x00, 0x00, /* TCP 102 */
    895	0x00, 0x00, 0x00, 0x00,
    896	0x00, 0x00, 0x00, 0x00,
    897	0x50, 0x00, 0x00, 0x00,
    898	0x00, 0x00, 0x00, 0x00,
    899
    900	0x00, 0x00, /* 2 bytes for 4 byte alignment */
    901};
    902
    903ICE_DECLARE_PKT_OFFSETS(ipv4_gtpu_ipv6_udp) = {
    904	{ ICE_MAC_OFOS,		0 },
    905	{ ICE_IPV4_OFOS,	14 },
    906	{ ICE_UDP_OF,		34 },
    907	{ ICE_GTP,		42 },
    908	{ ICE_IPV6_IL,		62 },
    909	{ ICE_UDP_ILOS,		102 },
    910	{ ICE_PROTOCOL_LAST,	0 },
    911};
    912
    913ICE_DECLARE_PKT_TEMPLATE(ipv4_gtpu_ipv6_udp) = {
    914	0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
    915	0x00, 0x00, 0x00, 0x00,
    916	0x00, 0x00, 0x00, 0x00,
    917	0x08, 0x00,
    918
    919	0x45, 0x00, 0x00, 0x60, /* IP 14 */
    920	0x00, 0x00, 0x00, 0x00,
    921	0x00, 0x11, 0x00, 0x00,
    922	0x00, 0x00, 0x00, 0x00,
    923	0x00, 0x00, 0x00, 0x00,
    924
    925	0x00, 0x00, 0x08, 0x68, /* UDP 34 */
    926	0x00, 0x4c, 0x00, 0x00,
    927
    928	0x34, 0xff, 0x00, 0x3c, /* ICE_GTP Header 42 */
    929	0x00, 0x00, 0x00, 0x00,
    930	0x00, 0x00, 0x00, 0x85,
    931
    932	0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 54 */
    933	0x00, 0x00, 0x00, 0x00,
    934
    935	0x60, 0x00, 0x00, 0x00, /* IPv6 62 */
    936	0x00, 0x08, 0x11, 0x00,
    937	0x00, 0x00, 0x00, 0x00,
    938	0x00, 0x00, 0x00, 0x00,
    939	0x00, 0x00, 0x00, 0x00,
    940	0x00, 0x00, 0x00, 0x00,
    941	0x00, 0x00, 0x00, 0x00,
    942	0x00, 0x00, 0x00, 0x00,
    943	0x00, 0x00, 0x00, 0x00,
    944	0x00, 0x00, 0x00, 0x00,
    945
    946	0x00, 0x00, 0x00, 0x00, /* UDP 102 */
    947	0x00, 0x08, 0x00, 0x00,
    948
    949	0x00, 0x00, /* 2 bytes for 4 byte alignment */
    950};
    951
    952ICE_DECLARE_PKT_OFFSETS(ipv6_gtpu_ipv4_tcp) = {
    953	{ ICE_MAC_OFOS,		0 },
    954	{ ICE_IPV6_OFOS,	14 },
    955	{ ICE_UDP_OF,		54 },
    956	{ ICE_GTP,		62 },
    957	{ ICE_IPV4_IL,		82 },
    958	{ ICE_TCP_IL,		102 },
    959	{ ICE_PROTOCOL_LAST,	0 },
    960};
    961
    962ICE_DECLARE_PKT_TEMPLATE(ipv6_gtpu_ipv4_tcp) = {
    963	0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
    964	0x00, 0x00, 0x00, 0x00,
    965	0x00, 0x00, 0x00, 0x00,
    966	0x86, 0xdd,
    967
    968	0x60, 0x00, 0x00, 0x00, /* IPv6 14 */
    969	0x00, 0x44, 0x11, 0x00,
    970	0x00, 0x00, 0x00, 0x00,
    971	0x00, 0x00, 0x00, 0x00,
    972	0x00, 0x00, 0x00, 0x00,
    973	0x00, 0x00, 0x00, 0x00,
    974	0x00, 0x00, 0x00, 0x00,
    975	0x00, 0x00, 0x00, 0x00,
    976	0x00, 0x00, 0x00, 0x00,
    977	0x00, 0x00, 0x00, 0x00,
    978
    979	0x00, 0x00, 0x08, 0x68, /* UDP 54 */
    980	0x00, 0x44, 0x00, 0x00,
    981
    982	0x34, 0xff, 0x00, 0x34, /* ICE_GTP Header 62 */
    983	0x00, 0x00, 0x00, 0x00,
    984	0x00, 0x00, 0x00, 0x85,
    985
    986	0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 74 */
    987	0x00, 0x00, 0x00, 0x00,
    988
    989	0x45, 0x00, 0x00, 0x28, /* IP 82 */
    990	0x00, 0x00, 0x00, 0x00,
    991	0x00, 0x06, 0x00, 0x00,
    992	0x00, 0x00, 0x00, 0x00,
    993	0x00, 0x00, 0x00, 0x00,
    994
    995	0x00, 0x00, 0x00, 0x00, /* TCP 102 */
    996	0x00, 0x00, 0x00, 0x00,
    997	0x00, 0x00, 0x00, 0x00,
    998	0x50, 0x00, 0x00, 0x00,
    999	0x00, 0x00, 0x00, 0x00,
   1000
   1001	0x00, 0x00, /* 2 bytes for 4 byte alignment */
   1002};
   1003
   1004ICE_DECLARE_PKT_OFFSETS(ipv6_gtpu_ipv4_udp) = {
   1005	{ ICE_MAC_OFOS,		0 },
   1006	{ ICE_IPV6_OFOS,	14 },
   1007	{ ICE_UDP_OF,		54 },
   1008	{ ICE_GTP,		62 },
   1009	{ ICE_IPV4_IL,		82 },
   1010	{ ICE_UDP_ILOS,		102 },
   1011	{ ICE_PROTOCOL_LAST,	0 },
   1012};
   1013
   1014ICE_DECLARE_PKT_TEMPLATE(ipv6_gtpu_ipv4_udp) = {
   1015	0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
   1016	0x00, 0x00, 0x00, 0x00,
   1017	0x00, 0x00, 0x00, 0x00,
   1018	0x86, 0xdd,
   1019
   1020	0x60, 0x00, 0x00, 0x00, /* IPv6 14 */
   1021	0x00, 0x38, 0x11, 0x00,
   1022	0x00, 0x00, 0x00, 0x00,
   1023	0x00, 0x00, 0x00, 0x00,
   1024	0x00, 0x00, 0x00, 0x00,
   1025	0x00, 0x00, 0x00, 0x00,
   1026	0x00, 0x00, 0x00, 0x00,
   1027	0x00, 0x00, 0x00, 0x00,
   1028	0x00, 0x00, 0x00, 0x00,
   1029	0x00, 0x00, 0x00, 0x00,
   1030
   1031	0x00, 0x00, 0x08, 0x68, /* UDP 54 */
   1032	0x00, 0x38, 0x00, 0x00,
   1033
   1034	0x34, 0xff, 0x00, 0x28, /* ICE_GTP Header 62 */
   1035	0x00, 0x00, 0x00, 0x00,
   1036	0x00, 0x00, 0x00, 0x85,
   1037
   1038	0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 74 */
   1039	0x00, 0x00, 0x00, 0x00,
   1040
   1041	0x45, 0x00, 0x00, 0x1c, /* IP 82 */
   1042	0x00, 0x00, 0x00, 0x00,
   1043	0x00, 0x11, 0x00, 0x00,
   1044	0x00, 0x00, 0x00, 0x00,
   1045	0x00, 0x00, 0x00, 0x00,
   1046
   1047	0x00, 0x00, 0x00, 0x00, /* UDP 102 */
   1048	0x00, 0x08, 0x00, 0x00,
   1049
   1050	0x00, 0x00, /* 2 bytes for 4 byte alignment */
   1051};
   1052
   1053ICE_DECLARE_PKT_OFFSETS(ipv6_gtpu_ipv6_tcp) = {
   1054	{ ICE_MAC_OFOS,		0 },
   1055	{ ICE_IPV6_OFOS,	14 },
   1056	{ ICE_UDP_OF,		54 },
   1057	{ ICE_GTP,		62 },
   1058	{ ICE_IPV6_IL,		82 },
   1059	{ ICE_TCP_IL,		122 },
   1060	{ ICE_PROTOCOL_LAST,	0 },
   1061};
   1062
   1063ICE_DECLARE_PKT_TEMPLATE(ipv6_gtpu_ipv6_tcp) = {
   1064	0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
   1065	0x00, 0x00, 0x00, 0x00,
   1066	0x00, 0x00, 0x00, 0x00,
   1067	0x86, 0xdd,
   1068
   1069	0x60, 0x00, 0x00, 0x00, /* IPv6 14 */
   1070	0x00, 0x58, 0x11, 0x00,
   1071	0x00, 0x00, 0x00, 0x00,
   1072	0x00, 0x00, 0x00, 0x00,
   1073	0x00, 0x00, 0x00, 0x00,
   1074	0x00, 0x00, 0x00, 0x00,
   1075	0x00, 0x00, 0x00, 0x00,
   1076	0x00, 0x00, 0x00, 0x00,
   1077	0x00, 0x00, 0x00, 0x00,
   1078	0x00, 0x00, 0x00, 0x00,
   1079
   1080	0x00, 0x00, 0x08, 0x68, /* UDP 54 */
   1081	0x00, 0x58, 0x00, 0x00,
   1082
   1083	0x34, 0xff, 0x00, 0x48, /* ICE_GTP Header 62 */
   1084	0x00, 0x00, 0x00, 0x00,
   1085	0x00, 0x00, 0x00, 0x85,
   1086
   1087	0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 74 */
   1088	0x00, 0x00, 0x00, 0x00,
   1089
   1090	0x60, 0x00, 0x00, 0x00, /* IPv6 82 */
   1091	0x00, 0x14, 0x06, 0x00,
   1092	0x00, 0x00, 0x00, 0x00,
   1093	0x00, 0x00, 0x00, 0x00,
   1094	0x00, 0x00, 0x00, 0x00,
   1095	0x00, 0x00, 0x00, 0x00,
   1096	0x00, 0x00, 0x00, 0x00,
   1097	0x00, 0x00, 0x00, 0x00,
   1098	0x00, 0x00, 0x00, 0x00,
   1099	0x00, 0x00, 0x00, 0x00,
   1100
   1101	0x00, 0x00, 0x00, 0x00, /* TCP 122 */
   1102	0x00, 0x00, 0x00, 0x00,
   1103	0x00, 0x00, 0x00, 0x00,
   1104	0x50, 0x00, 0x00, 0x00,
   1105	0x00, 0x00, 0x00, 0x00,
   1106
   1107	0x00, 0x00, /* 2 bytes for 4 byte alignment */
   1108};
   1109
   1110ICE_DECLARE_PKT_OFFSETS(ipv6_gtpu_ipv6_udp) = {
   1111	{ ICE_MAC_OFOS,		0 },
   1112	{ ICE_IPV6_OFOS,	14 },
   1113	{ ICE_UDP_OF,		54 },
   1114	{ ICE_GTP,		62 },
   1115	{ ICE_IPV6_IL,		82 },
   1116	{ ICE_UDP_ILOS,		122 },
   1117	{ ICE_PROTOCOL_LAST,	0 },
   1118};
   1119
   1120ICE_DECLARE_PKT_TEMPLATE(ipv6_gtpu_ipv6_udp) = {
   1121	0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
   1122	0x00, 0x00, 0x00, 0x00,
   1123	0x00, 0x00, 0x00, 0x00,
   1124	0x86, 0xdd,
   1125
   1126	0x60, 0x00, 0x00, 0x00, /* IPv6 14 */
   1127	0x00, 0x4c, 0x11, 0x00,
   1128	0x00, 0x00, 0x00, 0x00,
   1129	0x00, 0x00, 0x00, 0x00,
   1130	0x00, 0x00, 0x00, 0x00,
   1131	0x00, 0x00, 0x00, 0x00,
   1132	0x00, 0x00, 0x00, 0x00,
   1133	0x00, 0x00, 0x00, 0x00,
   1134	0x00, 0x00, 0x00, 0x00,
   1135	0x00, 0x00, 0x00, 0x00,
   1136
   1137	0x00, 0x00, 0x08, 0x68, /* UDP 54 */
   1138	0x00, 0x4c, 0x00, 0x00,
   1139
   1140	0x34, 0xff, 0x00, 0x3c, /* ICE_GTP Header 62 */
   1141	0x00, 0x00, 0x00, 0x00,
   1142	0x00, 0x00, 0x00, 0x85,
   1143
   1144	0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 74 */
   1145	0x00, 0x00, 0x00, 0x00,
   1146
   1147	0x60, 0x00, 0x00, 0x00, /* IPv6 82 */
   1148	0x00, 0x08, 0x11, 0x00,
   1149	0x00, 0x00, 0x00, 0x00,
   1150	0x00, 0x00, 0x00, 0x00,
   1151	0x00, 0x00, 0x00, 0x00,
   1152	0x00, 0x00, 0x00, 0x00,
   1153	0x00, 0x00, 0x00, 0x00,
   1154	0x00, 0x00, 0x00, 0x00,
   1155	0x00, 0x00, 0x00, 0x00,
   1156	0x00, 0x00, 0x00, 0x00,
   1157
   1158	0x00, 0x00, 0x00, 0x00, /* UDP 122 */
   1159	0x00, 0x08, 0x00, 0x00,
   1160
   1161	0x00, 0x00, /* 2 bytes for 4 byte alignment */
   1162};
   1163
   1164ICE_DECLARE_PKT_OFFSETS(ipv4_gtpu_ipv4) = {
   1165	{ ICE_MAC_OFOS,		0 },
   1166	{ ICE_IPV4_OFOS,	14 },
   1167	{ ICE_UDP_OF,		34 },
   1168	{ ICE_GTP_NO_PAY,	42 },
   1169	{ ICE_PROTOCOL_LAST,	0 },
   1170};
   1171
   1172ICE_DECLARE_PKT_TEMPLATE(ipv4_gtpu_ipv4) = {
   1173	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
   1174	0x00, 0x00, 0x00, 0x00,
   1175	0x00, 0x00, 0x00, 0x00,
   1176	0x08, 0x00,
   1177
   1178	0x45, 0x00, 0x00, 0x44, /* ICE_IPV4_OFOS 14 */
   1179	0x00, 0x00, 0x40, 0x00,
   1180	0x40, 0x11, 0x00, 0x00,
   1181	0x00, 0x00, 0x00, 0x00,
   1182	0x00, 0x00, 0x00, 0x00,
   1183
   1184	0x08, 0x68, 0x08, 0x68, /* ICE_UDP_OF 34 */
   1185	0x00, 0x00, 0x00, 0x00,
   1186
   1187	0x34, 0xff, 0x00, 0x28, /* ICE_GTP 42 */
   1188	0x00, 0x00, 0x00, 0x00,
   1189	0x00, 0x00, 0x00, 0x85,
   1190
   1191	0x02, 0x00, 0x00, 0x00, /* PDU Session extension header */
   1192	0x00, 0x00, 0x00, 0x00,
   1193
   1194	0x45, 0x00, 0x00, 0x14, /* ICE_IPV4_IL 62 */
   1195	0x00, 0x00, 0x40, 0x00,
   1196	0x40, 0x00, 0x00, 0x00,
   1197	0x00, 0x00, 0x00, 0x00,
   1198	0x00, 0x00, 0x00, 0x00,
   1199	0x00, 0x00,
   1200};
   1201
   1202ICE_DECLARE_PKT_OFFSETS(ipv6_gtp) = {
   1203	{ ICE_MAC_OFOS,		0 },
   1204	{ ICE_IPV6_OFOS,	14 },
   1205	{ ICE_UDP_OF,		54 },
   1206	{ ICE_GTP_NO_PAY,	62 },
   1207	{ ICE_PROTOCOL_LAST,	0 },
   1208};
   1209
   1210ICE_DECLARE_PKT_TEMPLATE(ipv6_gtp) = {
   1211	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
   1212	0x00, 0x00, 0x00, 0x00,
   1213	0x00, 0x00, 0x00, 0x00,
   1214	0x86, 0xdd,
   1215
   1216	0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 14 */
   1217	0x00, 0x6c, 0x11, 0x00, /* Next header UDP*/
   1218	0x00, 0x00, 0x00, 0x00,
   1219	0x00, 0x00, 0x00, 0x00,
   1220	0x00, 0x00, 0x00, 0x00,
   1221	0x00, 0x00, 0x00, 0x00,
   1222	0x00, 0x00, 0x00, 0x00,
   1223	0x00, 0x00, 0x00, 0x00,
   1224	0x00, 0x00, 0x00, 0x00,
   1225	0x00, 0x00, 0x00, 0x00,
   1226
   1227	0x08, 0x68, 0x08, 0x68, /* ICE_UDP_OF 54 */
   1228	0x00, 0x00, 0x00, 0x00,
   1229
   1230	0x30, 0x00, 0x00, 0x28, /* ICE_GTP 62 */
   1231	0x00, 0x00, 0x00, 0x00,
   1232
   1233	0x00, 0x00,
   1234};
   1235
   1236static const struct ice_dummy_pkt_profile ice_dummy_pkt_profiles[] = {
   1237	ICE_PKT_PROFILE(ipv6_gtp, ICE_PKT_TUN_GTPU | ICE_PKT_OUTER_IPV6 |
   1238				  ICE_PKT_GTP_NOPAY),
   1239	ICE_PKT_PROFILE(ipv6_gtpu_ipv6_udp, ICE_PKT_TUN_GTPU |
   1240					    ICE_PKT_OUTER_IPV6 |
   1241					    ICE_PKT_INNER_IPV6 |
   1242					    ICE_PKT_INNER_UDP),
   1243	ICE_PKT_PROFILE(ipv6_gtpu_ipv6_tcp, ICE_PKT_TUN_GTPU |
   1244					    ICE_PKT_OUTER_IPV6 |
   1245					    ICE_PKT_INNER_IPV6),
   1246	ICE_PKT_PROFILE(ipv6_gtpu_ipv4_udp, ICE_PKT_TUN_GTPU |
   1247					    ICE_PKT_OUTER_IPV6 |
   1248					    ICE_PKT_INNER_UDP),
   1249	ICE_PKT_PROFILE(ipv6_gtpu_ipv4_tcp, ICE_PKT_TUN_GTPU |
   1250					    ICE_PKT_OUTER_IPV6),
   1251	ICE_PKT_PROFILE(ipv4_gtpu_ipv4, ICE_PKT_TUN_GTPU | ICE_PKT_GTP_NOPAY),
   1252	ICE_PKT_PROFILE(ipv4_gtpu_ipv6_udp, ICE_PKT_TUN_GTPU |
   1253					    ICE_PKT_INNER_IPV6 |
   1254					    ICE_PKT_INNER_UDP),
   1255	ICE_PKT_PROFILE(ipv4_gtpu_ipv6_tcp, ICE_PKT_TUN_GTPU |
   1256					    ICE_PKT_INNER_IPV6),
   1257	ICE_PKT_PROFILE(ipv4_gtpu_ipv4_udp, ICE_PKT_TUN_GTPU |
   1258					    ICE_PKT_INNER_UDP),
   1259	ICE_PKT_PROFILE(ipv4_gtpu_ipv4_tcp, ICE_PKT_TUN_GTPU),
   1260	ICE_PKT_PROFILE(ipv6_gtp, ICE_PKT_TUN_GTPC | ICE_PKT_OUTER_IPV6),
   1261	ICE_PKT_PROFILE(ipv4_gtpu_ipv4, ICE_PKT_TUN_GTPC),
   1262	ICE_PKT_PROFILE(gre_ipv6_tcp, ICE_PKT_TUN_NVGRE | ICE_PKT_INNER_IPV6 |
   1263				      ICE_PKT_INNER_TCP),
   1264	ICE_PKT_PROFILE(gre_tcp, ICE_PKT_TUN_NVGRE | ICE_PKT_INNER_TCP),
   1265	ICE_PKT_PROFILE(gre_ipv6_udp, ICE_PKT_TUN_NVGRE | ICE_PKT_INNER_IPV6),
   1266	ICE_PKT_PROFILE(gre_udp, ICE_PKT_TUN_NVGRE),
   1267	ICE_PKT_PROFILE(udp_tun_ipv6_tcp, ICE_PKT_TUN_UDP |
   1268					  ICE_PKT_INNER_IPV6 |
   1269					  ICE_PKT_INNER_TCP),
   1270	ICE_PKT_PROFILE(udp_tun_tcp, ICE_PKT_TUN_UDP | ICE_PKT_INNER_TCP),
   1271	ICE_PKT_PROFILE(udp_tun_ipv6_udp, ICE_PKT_TUN_UDP |
   1272					  ICE_PKT_INNER_IPV6),
   1273	ICE_PKT_PROFILE(udp_tun_udp, ICE_PKT_TUN_UDP),
   1274	ICE_PKT_PROFILE(vlan_udp_ipv6, ICE_PKT_OUTER_IPV6 | ICE_PKT_INNER_UDP |
   1275				       ICE_PKT_VLAN),
   1276	ICE_PKT_PROFILE(udp_ipv6, ICE_PKT_OUTER_IPV6 | ICE_PKT_INNER_UDP),
   1277	ICE_PKT_PROFILE(vlan_udp, ICE_PKT_INNER_UDP | ICE_PKT_VLAN),
   1278	ICE_PKT_PROFILE(udp, ICE_PKT_INNER_UDP),
   1279	ICE_PKT_PROFILE(vlan_tcp_ipv6, ICE_PKT_OUTER_IPV6 | ICE_PKT_VLAN),
   1280	ICE_PKT_PROFILE(tcp_ipv6, ICE_PKT_OUTER_IPV6),
   1281	ICE_PKT_PROFILE(vlan_tcp, ICE_PKT_VLAN),
   1282	ICE_PKT_PROFILE(tcp, 0),
   1283};
   1284
   1285#define ICE_SW_RULE_RX_TX_HDR_SIZE(s, l)	struct_size((s), hdr_data, (l))
   1286#define ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(s)	\
   1287	ICE_SW_RULE_RX_TX_HDR_SIZE((s), DUMMY_ETH_HDR_LEN)
   1288#define ICE_SW_RULE_RX_TX_NO_HDR_SIZE(s)	\
   1289	ICE_SW_RULE_RX_TX_HDR_SIZE((s), 0)
   1290#define ICE_SW_RULE_LG_ACT_SIZE(s, n)		struct_size((s), act, (n))
   1291#define ICE_SW_RULE_VSI_LIST_SIZE(s, n)		struct_size((s), vsi, (n))
   1292
   1293/* this is a recipe to profile association bitmap */
   1294static DECLARE_BITMAP(recipe_to_profile[ICE_MAX_NUM_RECIPES],
   1295			  ICE_MAX_NUM_PROFILES);
   1296
   1297/* this is a profile to recipe association bitmap */
   1298static DECLARE_BITMAP(profile_to_recipe[ICE_MAX_NUM_PROFILES],
   1299			  ICE_MAX_NUM_RECIPES);
   1300
   1301/**
   1302 * ice_init_def_sw_recp - initialize the recipe book keeping tables
   1303 * @hw: pointer to the HW struct
   1304 *
   1305 * Allocate memory for the entire recipe table and initialize the structures/
   1306 * entries corresponding to basic recipes.
   1307 */
   1308int ice_init_def_sw_recp(struct ice_hw *hw)
   1309{
   1310	struct ice_sw_recipe *recps;
   1311	u8 i;
   1312
   1313	recps = devm_kcalloc(ice_hw_to_dev(hw), ICE_MAX_NUM_RECIPES,
   1314			     sizeof(*recps), GFP_KERNEL);
   1315	if (!recps)
   1316		return -ENOMEM;
   1317
   1318	for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
   1319		recps[i].root_rid = i;
   1320		INIT_LIST_HEAD(&recps[i].filt_rules);
   1321		INIT_LIST_HEAD(&recps[i].filt_replay_rules);
   1322		INIT_LIST_HEAD(&recps[i].rg_list);
   1323		mutex_init(&recps[i].filt_rule_lock);
   1324	}
   1325
   1326	hw->switch_info->recp_list = recps;
   1327
   1328	return 0;
   1329}
   1330
   1331/**
   1332 * ice_aq_get_sw_cfg - get switch configuration
   1333 * @hw: pointer to the hardware structure
   1334 * @buf: pointer to the result buffer
   1335 * @buf_size: length of the buffer available for response
   1336 * @req_desc: pointer to requested descriptor
   1337 * @num_elems: pointer to number of elements
   1338 * @cd: pointer to command details structure or NULL
   1339 *
   1340 * Get switch configuration (0x0200) to be placed in buf.
   1341 * This admin command returns information such as initial VSI/port number
   1342 * and switch ID it belongs to.
   1343 *
   1344 * NOTE: *req_desc is both an input/output parameter.
   1345 * The caller of this function first calls this function with *request_desc set
   1346 * to 0. If the response from f/w has *req_desc set to 0, all the switch
   1347 * configuration information has been returned; if non-zero (meaning not all
   1348 * the information was returned), the caller should call this function again
   1349 * with *req_desc set to the previous value returned by f/w to get the
   1350 * next block of switch configuration information.
   1351 *
   1352 * *num_elems is output only parameter. This reflects the number of elements
   1353 * in response buffer. The caller of this function to use *num_elems while
   1354 * parsing the response buffer.
   1355 */
   1356static int
   1357ice_aq_get_sw_cfg(struct ice_hw *hw, struct ice_aqc_get_sw_cfg_resp_elem *buf,
   1358		  u16 buf_size, u16 *req_desc, u16 *num_elems,
   1359		  struct ice_sq_cd *cd)
   1360{
   1361	struct ice_aqc_get_sw_cfg *cmd;
   1362	struct ice_aq_desc desc;
   1363	int status;
   1364
   1365	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_sw_cfg);
   1366	cmd = &desc.params.get_sw_conf;
   1367	cmd->element = cpu_to_le16(*req_desc);
   1368
   1369	status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
   1370	if (!status) {
   1371		*req_desc = le16_to_cpu(cmd->element);
   1372		*num_elems = le16_to_cpu(cmd->num_elems);
   1373	}
   1374
   1375	return status;
   1376}
   1377
   1378/**
   1379 * ice_aq_add_vsi
   1380 * @hw: pointer to the HW struct
   1381 * @vsi_ctx: pointer to a VSI context struct
   1382 * @cd: pointer to command details structure or NULL
   1383 *
   1384 * Add a VSI context to the hardware (0x0210)
   1385 */
   1386static int
   1387ice_aq_add_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
   1388	       struct ice_sq_cd *cd)
   1389{
   1390	struct ice_aqc_add_update_free_vsi_resp *res;
   1391	struct ice_aqc_add_get_update_free_vsi *cmd;
   1392	struct ice_aq_desc desc;
   1393	int status;
   1394
   1395	cmd = &desc.params.vsi_cmd;
   1396	res = &desc.params.add_update_free_vsi_res;
   1397
   1398	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_vsi);
   1399
   1400	if (!vsi_ctx->alloc_from_pool)
   1401		cmd->vsi_num = cpu_to_le16(vsi_ctx->vsi_num |
   1402					   ICE_AQ_VSI_IS_VALID);
   1403	cmd->vf_id = vsi_ctx->vf_num;
   1404
   1405	cmd->vsi_flags = cpu_to_le16(vsi_ctx->flags);
   1406
   1407	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
   1408
   1409	status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info,
   1410				 sizeof(vsi_ctx->info), cd);
   1411
   1412	if (!status) {
   1413		vsi_ctx->vsi_num = le16_to_cpu(res->vsi_num) & ICE_AQ_VSI_NUM_M;
   1414		vsi_ctx->vsis_allocd = le16_to_cpu(res->vsi_used);
   1415		vsi_ctx->vsis_unallocated = le16_to_cpu(res->vsi_free);
   1416	}
   1417
   1418	return status;
   1419}
   1420
   1421/**
   1422 * ice_aq_free_vsi
   1423 * @hw: pointer to the HW struct
   1424 * @vsi_ctx: pointer to a VSI context struct
   1425 * @keep_vsi_alloc: keep VSI allocation as part of this PF's resources
   1426 * @cd: pointer to command details structure or NULL
   1427 *
   1428 * Free VSI context info from hardware (0x0213)
   1429 */
   1430static int
   1431ice_aq_free_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
   1432		bool keep_vsi_alloc, struct ice_sq_cd *cd)
   1433{
   1434	struct ice_aqc_add_update_free_vsi_resp *resp;
   1435	struct ice_aqc_add_get_update_free_vsi *cmd;
   1436	struct ice_aq_desc desc;
   1437	int status;
   1438
   1439	cmd = &desc.params.vsi_cmd;
   1440	resp = &desc.params.add_update_free_vsi_res;
   1441
   1442	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_free_vsi);
   1443
   1444	cmd->vsi_num = cpu_to_le16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID);
   1445	if (keep_vsi_alloc)
   1446		cmd->cmd_flags = cpu_to_le16(ICE_AQ_VSI_KEEP_ALLOC);
   1447
   1448	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
   1449	if (!status) {
   1450		vsi_ctx->vsis_allocd = le16_to_cpu(resp->vsi_used);
   1451		vsi_ctx->vsis_unallocated = le16_to_cpu(resp->vsi_free);
   1452	}
   1453
   1454	return status;
   1455}
   1456
   1457/**
   1458 * ice_aq_update_vsi
   1459 * @hw: pointer to the HW struct
   1460 * @vsi_ctx: pointer to a VSI context struct
   1461 * @cd: pointer to command details structure or NULL
   1462 *
   1463 * Update VSI context in the hardware (0x0211)
   1464 */
   1465static int
   1466ice_aq_update_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
   1467		  struct ice_sq_cd *cd)
   1468{
   1469	struct ice_aqc_add_update_free_vsi_resp *resp;
   1470	struct ice_aqc_add_get_update_free_vsi *cmd;
   1471	struct ice_aq_desc desc;
   1472	int status;
   1473
   1474	cmd = &desc.params.vsi_cmd;
   1475	resp = &desc.params.add_update_free_vsi_res;
   1476
   1477	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_update_vsi);
   1478
   1479	cmd->vsi_num = cpu_to_le16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID);
   1480
   1481	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
   1482
   1483	status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info,
   1484				 sizeof(vsi_ctx->info), cd);
   1485
   1486	if (!status) {
   1487		vsi_ctx->vsis_allocd = le16_to_cpu(resp->vsi_used);
   1488		vsi_ctx->vsis_unallocated = le16_to_cpu(resp->vsi_free);
   1489	}
   1490
   1491	return status;
   1492}
   1493
   1494/**
   1495 * ice_is_vsi_valid - check whether the VSI is valid or not
   1496 * @hw: pointer to the HW struct
   1497 * @vsi_handle: VSI handle
   1498 *
   1499 * check whether the VSI is valid or not
   1500 */
   1501bool ice_is_vsi_valid(struct ice_hw *hw, u16 vsi_handle)
   1502{
   1503	return vsi_handle < ICE_MAX_VSI && hw->vsi_ctx[vsi_handle];
   1504}
   1505
   1506/**
   1507 * ice_get_hw_vsi_num - return the HW VSI number
   1508 * @hw: pointer to the HW struct
   1509 * @vsi_handle: VSI handle
   1510 *
   1511 * return the HW VSI number
   1512 * Caution: call this function only if VSI is valid (ice_is_vsi_valid)
   1513 */
   1514u16 ice_get_hw_vsi_num(struct ice_hw *hw, u16 vsi_handle)
   1515{
   1516	return hw->vsi_ctx[vsi_handle]->vsi_num;
   1517}
   1518
   1519/**
   1520 * ice_get_vsi_ctx - return the VSI context entry for a given VSI handle
   1521 * @hw: pointer to the HW struct
   1522 * @vsi_handle: VSI handle
   1523 *
   1524 * return the VSI context entry for a given VSI handle
   1525 */
   1526struct ice_vsi_ctx *ice_get_vsi_ctx(struct ice_hw *hw, u16 vsi_handle)
   1527{
   1528	return (vsi_handle >= ICE_MAX_VSI) ? NULL : hw->vsi_ctx[vsi_handle];
   1529}
   1530
   1531/**
   1532 * ice_save_vsi_ctx - save the VSI context for a given VSI handle
   1533 * @hw: pointer to the HW struct
   1534 * @vsi_handle: VSI handle
   1535 * @vsi: VSI context pointer
   1536 *
   1537 * save the VSI context entry for a given VSI handle
   1538 */
   1539static void
   1540ice_save_vsi_ctx(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi)
   1541{
   1542	hw->vsi_ctx[vsi_handle] = vsi;
   1543}
   1544
   1545/**
   1546 * ice_clear_vsi_q_ctx - clear VSI queue contexts for all TCs
   1547 * @hw: pointer to the HW struct
   1548 * @vsi_handle: VSI handle
   1549 */
   1550static void ice_clear_vsi_q_ctx(struct ice_hw *hw, u16 vsi_handle)
   1551{
   1552	struct ice_vsi_ctx *vsi;
   1553	u8 i;
   1554
   1555	vsi = ice_get_vsi_ctx(hw, vsi_handle);
   1556	if (!vsi)
   1557		return;
   1558	ice_for_each_traffic_class(i) {
   1559		if (vsi->lan_q_ctx[i]) {
   1560			devm_kfree(ice_hw_to_dev(hw), vsi->lan_q_ctx[i]);
   1561			vsi->lan_q_ctx[i] = NULL;
   1562		}
   1563		if (vsi->rdma_q_ctx[i]) {
   1564			devm_kfree(ice_hw_to_dev(hw), vsi->rdma_q_ctx[i]);
   1565			vsi->rdma_q_ctx[i] = NULL;
   1566		}
   1567	}
   1568}
   1569
   1570/**
   1571 * ice_clear_vsi_ctx - clear the VSI context entry
   1572 * @hw: pointer to the HW struct
   1573 * @vsi_handle: VSI handle
   1574 *
   1575 * clear the VSI context entry
   1576 */
   1577static void ice_clear_vsi_ctx(struct ice_hw *hw, u16 vsi_handle)
   1578{
   1579	struct ice_vsi_ctx *vsi;
   1580
   1581	vsi = ice_get_vsi_ctx(hw, vsi_handle);
   1582	if (vsi) {
   1583		ice_clear_vsi_q_ctx(hw, vsi_handle);
   1584		devm_kfree(ice_hw_to_dev(hw), vsi);
   1585		hw->vsi_ctx[vsi_handle] = NULL;
   1586	}
   1587}
   1588
   1589/**
   1590 * ice_clear_all_vsi_ctx - clear all the VSI context entries
   1591 * @hw: pointer to the HW struct
   1592 */
   1593void ice_clear_all_vsi_ctx(struct ice_hw *hw)
   1594{
   1595	u16 i;
   1596
   1597	for (i = 0; i < ICE_MAX_VSI; i++)
   1598		ice_clear_vsi_ctx(hw, i);
   1599}
   1600
   1601/**
   1602 * ice_add_vsi - add VSI context to the hardware and VSI handle list
   1603 * @hw: pointer to the HW struct
   1604 * @vsi_handle: unique VSI handle provided by drivers
   1605 * @vsi_ctx: pointer to a VSI context struct
   1606 * @cd: pointer to command details structure or NULL
   1607 *
   1608 * Add a VSI context to the hardware also add it into the VSI handle list.
   1609 * If this function gets called after reset for existing VSIs then update
   1610 * with the new HW VSI number in the corresponding VSI handle list entry.
   1611 */
   1612int
   1613ice_add_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
   1614	    struct ice_sq_cd *cd)
   1615{
   1616	struct ice_vsi_ctx *tmp_vsi_ctx;
   1617	int status;
   1618
   1619	if (vsi_handle >= ICE_MAX_VSI)
   1620		return -EINVAL;
   1621	status = ice_aq_add_vsi(hw, vsi_ctx, cd);
   1622	if (status)
   1623		return status;
   1624	tmp_vsi_ctx = ice_get_vsi_ctx(hw, vsi_handle);
   1625	if (!tmp_vsi_ctx) {
   1626		/* Create a new VSI context */
   1627		tmp_vsi_ctx = devm_kzalloc(ice_hw_to_dev(hw),
   1628					   sizeof(*tmp_vsi_ctx), GFP_KERNEL);
   1629		if (!tmp_vsi_ctx) {
   1630			ice_aq_free_vsi(hw, vsi_ctx, false, cd);
   1631			return -ENOMEM;
   1632		}
   1633		*tmp_vsi_ctx = *vsi_ctx;
   1634		ice_save_vsi_ctx(hw, vsi_handle, tmp_vsi_ctx);
   1635	} else {
   1636		/* update with new HW VSI num */
   1637		tmp_vsi_ctx->vsi_num = vsi_ctx->vsi_num;
   1638	}
   1639
   1640	return 0;
   1641}
   1642
   1643/**
   1644 * ice_free_vsi- free VSI context from hardware and VSI handle list
   1645 * @hw: pointer to the HW struct
   1646 * @vsi_handle: unique VSI handle
   1647 * @vsi_ctx: pointer to a VSI context struct
   1648 * @keep_vsi_alloc: keep VSI allocation as part of this PF's resources
   1649 * @cd: pointer to command details structure or NULL
   1650 *
   1651 * Free VSI context info from hardware as well as from VSI handle list
   1652 */
   1653int
   1654ice_free_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
   1655	     bool keep_vsi_alloc, struct ice_sq_cd *cd)
   1656{
   1657	int status;
   1658
   1659	if (!ice_is_vsi_valid(hw, vsi_handle))
   1660		return -EINVAL;
   1661	vsi_ctx->vsi_num = ice_get_hw_vsi_num(hw, vsi_handle);
   1662	status = ice_aq_free_vsi(hw, vsi_ctx, keep_vsi_alloc, cd);
   1663	if (!status)
   1664		ice_clear_vsi_ctx(hw, vsi_handle);
   1665	return status;
   1666}
   1667
   1668/**
   1669 * ice_update_vsi
   1670 * @hw: pointer to the HW struct
   1671 * @vsi_handle: unique VSI handle
   1672 * @vsi_ctx: pointer to a VSI context struct
   1673 * @cd: pointer to command details structure or NULL
   1674 *
   1675 * Update VSI context in the hardware
   1676 */
   1677int
   1678ice_update_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
   1679	       struct ice_sq_cd *cd)
   1680{
   1681	if (!ice_is_vsi_valid(hw, vsi_handle))
   1682		return -EINVAL;
   1683	vsi_ctx->vsi_num = ice_get_hw_vsi_num(hw, vsi_handle);
   1684	return ice_aq_update_vsi(hw, vsi_ctx, cd);
   1685}
   1686
   1687/**
   1688 * ice_cfg_rdma_fltr - enable/disable RDMA filtering on VSI
   1689 * @hw: pointer to HW struct
   1690 * @vsi_handle: VSI SW index
   1691 * @enable: boolean for enable/disable
   1692 */
   1693int
   1694ice_cfg_rdma_fltr(struct ice_hw *hw, u16 vsi_handle, bool enable)
   1695{
   1696	struct ice_vsi_ctx *ctx;
   1697
   1698	ctx = ice_get_vsi_ctx(hw, vsi_handle);
   1699	if (!ctx)
   1700		return -EIO;
   1701
   1702	if (enable)
   1703		ctx->info.q_opt_flags |= ICE_AQ_VSI_Q_OPT_PE_FLTR_EN;
   1704	else
   1705		ctx->info.q_opt_flags &= ~ICE_AQ_VSI_Q_OPT_PE_FLTR_EN;
   1706
   1707	return ice_update_vsi(hw, vsi_handle, ctx, NULL);
   1708}
   1709
   1710/**
   1711 * ice_aq_alloc_free_vsi_list
   1712 * @hw: pointer to the HW struct
   1713 * @vsi_list_id: VSI list ID returned or used for lookup
   1714 * @lkup_type: switch rule filter lookup type
   1715 * @opc: switch rules population command type - pass in the command opcode
   1716 *
   1717 * allocates or free a VSI list resource
   1718 */
   1719static int
   1720ice_aq_alloc_free_vsi_list(struct ice_hw *hw, u16 *vsi_list_id,
   1721			   enum ice_sw_lkup_type lkup_type,
   1722			   enum ice_adminq_opc opc)
   1723{
   1724	struct ice_aqc_alloc_free_res_elem *sw_buf;
   1725	struct ice_aqc_res_elem *vsi_ele;
   1726	u16 buf_len;
   1727	int status;
   1728
   1729	buf_len = struct_size(sw_buf, elem, 1);
   1730	sw_buf = devm_kzalloc(ice_hw_to_dev(hw), buf_len, GFP_KERNEL);
   1731	if (!sw_buf)
   1732		return -ENOMEM;
   1733	sw_buf->num_elems = cpu_to_le16(1);
   1734
   1735	if (lkup_type == ICE_SW_LKUP_MAC ||
   1736	    lkup_type == ICE_SW_LKUP_MAC_VLAN ||
   1737	    lkup_type == ICE_SW_LKUP_ETHERTYPE ||
   1738	    lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
   1739	    lkup_type == ICE_SW_LKUP_PROMISC ||
   1740	    lkup_type == ICE_SW_LKUP_PROMISC_VLAN) {
   1741		sw_buf->res_type = cpu_to_le16(ICE_AQC_RES_TYPE_VSI_LIST_REP);
   1742	} else if (lkup_type == ICE_SW_LKUP_VLAN) {
   1743		sw_buf->res_type =
   1744			cpu_to_le16(ICE_AQC_RES_TYPE_VSI_LIST_PRUNE);
   1745	} else {
   1746		status = -EINVAL;
   1747		goto ice_aq_alloc_free_vsi_list_exit;
   1748	}
   1749
   1750	if (opc == ice_aqc_opc_free_res)
   1751		sw_buf->elem[0].e.sw_resp = cpu_to_le16(*vsi_list_id);
   1752
   1753	status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len, opc, NULL);
   1754	if (status)
   1755		goto ice_aq_alloc_free_vsi_list_exit;
   1756
   1757	if (opc == ice_aqc_opc_alloc_res) {
   1758		vsi_ele = &sw_buf->elem[0];
   1759		*vsi_list_id = le16_to_cpu(vsi_ele->e.sw_resp);
   1760	}
   1761
   1762ice_aq_alloc_free_vsi_list_exit:
   1763	devm_kfree(ice_hw_to_dev(hw), sw_buf);
   1764	return status;
   1765}
   1766
   1767/**
   1768 * ice_aq_sw_rules - add/update/remove switch rules
   1769 * @hw: pointer to the HW struct
   1770 * @rule_list: pointer to switch rule population list
   1771 * @rule_list_sz: total size of the rule list in bytes
   1772 * @num_rules: number of switch rules in the rule_list
   1773 * @opc: switch rules population command type - pass in the command opcode
   1774 * @cd: pointer to command details structure or NULL
   1775 *
   1776 * Add(0x02a0)/Update(0x02a1)/Remove(0x02a2) switch rules commands to firmware
   1777 */
   1778int
   1779ice_aq_sw_rules(struct ice_hw *hw, void *rule_list, u16 rule_list_sz,
   1780		u8 num_rules, enum ice_adminq_opc opc, struct ice_sq_cd *cd)
   1781{
   1782	struct ice_aq_desc desc;
   1783	int status;
   1784
   1785	if (opc != ice_aqc_opc_add_sw_rules &&
   1786	    opc != ice_aqc_opc_update_sw_rules &&
   1787	    opc != ice_aqc_opc_remove_sw_rules)
   1788		return -EINVAL;
   1789
   1790	ice_fill_dflt_direct_cmd_desc(&desc, opc);
   1791
   1792	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
   1793	desc.params.sw_rules.num_rules_fltr_entry_index =
   1794		cpu_to_le16(num_rules);
   1795	status = ice_aq_send_cmd(hw, &desc, rule_list, rule_list_sz, cd);
   1796	if (opc != ice_aqc_opc_add_sw_rules &&
   1797	    hw->adminq.sq_last_status == ICE_AQ_RC_ENOENT)
   1798		status = -ENOENT;
   1799
   1800	return status;
   1801}
   1802
   1803/**
   1804 * ice_aq_add_recipe - add switch recipe
   1805 * @hw: pointer to the HW struct
   1806 * @s_recipe_list: pointer to switch rule population list
   1807 * @num_recipes: number of switch recipes in the list
   1808 * @cd: pointer to command details structure or NULL
   1809 *
   1810 * Add(0x0290)
   1811 */
   1812static int
   1813ice_aq_add_recipe(struct ice_hw *hw,
   1814		  struct ice_aqc_recipe_data_elem *s_recipe_list,
   1815		  u16 num_recipes, struct ice_sq_cd *cd)
   1816{
   1817	struct ice_aqc_add_get_recipe *cmd;
   1818	struct ice_aq_desc desc;
   1819	u16 buf_size;
   1820
   1821	cmd = &desc.params.add_get_recipe;
   1822	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_recipe);
   1823
   1824	cmd->num_sub_recipes = cpu_to_le16(num_recipes);
   1825	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
   1826
   1827	buf_size = num_recipes * sizeof(*s_recipe_list);
   1828
   1829	return ice_aq_send_cmd(hw, &desc, s_recipe_list, buf_size, cd);
   1830}
   1831
   1832/**
   1833 * ice_aq_get_recipe - get switch recipe
   1834 * @hw: pointer to the HW struct
   1835 * @s_recipe_list: pointer to switch rule population list
   1836 * @num_recipes: pointer to the number of recipes (input and output)
   1837 * @recipe_root: root recipe number of recipe(s) to retrieve
   1838 * @cd: pointer to command details structure or NULL
   1839 *
   1840 * Get(0x0292)
   1841 *
   1842 * On input, *num_recipes should equal the number of entries in s_recipe_list.
   1843 * On output, *num_recipes will equal the number of entries returned in
   1844 * s_recipe_list.
   1845 *
   1846 * The caller must supply enough space in s_recipe_list to hold all possible
   1847 * recipes and *num_recipes must equal ICE_MAX_NUM_RECIPES.
   1848 */
   1849static int
   1850ice_aq_get_recipe(struct ice_hw *hw,
   1851		  struct ice_aqc_recipe_data_elem *s_recipe_list,
   1852		  u16 *num_recipes, u16 recipe_root, struct ice_sq_cd *cd)
   1853{
   1854	struct ice_aqc_add_get_recipe *cmd;
   1855	struct ice_aq_desc desc;
   1856	u16 buf_size;
   1857	int status;
   1858
   1859	if (*num_recipes != ICE_MAX_NUM_RECIPES)
   1860		return -EINVAL;
   1861
   1862	cmd = &desc.params.add_get_recipe;
   1863	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_recipe);
   1864
   1865	cmd->return_index = cpu_to_le16(recipe_root);
   1866	cmd->num_sub_recipes = 0;
   1867
   1868	buf_size = *num_recipes * sizeof(*s_recipe_list);
   1869
   1870	status = ice_aq_send_cmd(hw, &desc, s_recipe_list, buf_size, cd);
   1871	*num_recipes = le16_to_cpu(cmd->num_sub_recipes);
   1872
   1873	return status;
   1874}
   1875
   1876/**
   1877 * ice_update_recipe_lkup_idx - update a default recipe based on the lkup_idx
   1878 * @hw: pointer to the HW struct
   1879 * @params: parameters used to update the default recipe
   1880 *
   1881 * This function only supports updating default recipes and it only supports
   1882 * updating a single recipe based on the lkup_idx at a time.
   1883 *
   1884 * This is done as a read-modify-write operation. First, get the current recipe
   1885 * contents based on the recipe's ID. Then modify the field vector index and
   1886 * mask if it's valid at the lkup_idx. Finally, use the add recipe AQ to update
   1887 * the pre-existing recipe with the modifications.
   1888 */
   1889int
   1890ice_update_recipe_lkup_idx(struct ice_hw *hw,
   1891			   struct ice_update_recipe_lkup_idx_params *params)
   1892{
   1893	struct ice_aqc_recipe_data_elem *rcp_list;
   1894	u16 num_recps = ICE_MAX_NUM_RECIPES;
   1895	int status;
   1896
   1897	rcp_list = kcalloc(num_recps, sizeof(*rcp_list), GFP_KERNEL);
   1898	if (!rcp_list)
   1899		return -ENOMEM;
   1900
   1901	/* read current recipe list from firmware */
   1902	rcp_list->recipe_indx = params->rid;
   1903	status = ice_aq_get_recipe(hw, rcp_list, &num_recps, params->rid, NULL);
   1904	if (status) {
   1905		ice_debug(hw, ICE_DBG_SW, "Failed to get recipe %d, status %d\n",
   1906			  params->rid, status);
   1907		goto error_out;
   1908	}
   1909
   1910	/* only modify existing recipe's lkup_idx and mask if valid, while
   1911	 * leaving all other fields the same, then update the recipe firmware
   1912	 */
   1913	rcp_list->content.lkup_indx[params->lkup_idx] = params->fv_idx;
   1914	if (params->mask_valid)
   1915		rcp_list->content.mask[params->lkup_idx] =
   1916			cpu_to_le16(params->mask);
   1917
   1918	if (params->ignore_valid)
   1919		rcp_list->content.lkup_indx[params->lkup_idx] |=
   1920			ICE_AQ_RECIPE_LKUP_IGNORE;
   1921
   1922	status = ice_aq_add_recipe(hw, &rcp_list[0], 1, NULL);
   1923	if (status)
   1924		ice_debug(hw, ICE_DBG_SW, "Failed to update recipe %d lkup_idx %d fv_idx %d mask %d mask_valid %s, status %d\n",
   1925			  params->rid, params->lkup_idx, params->fv_idx,
   1926			  params->mask, params->mask_valid ? "true" : "false",
   1927			  status);
   1928
   1929error_out:
   1930	kfree(rcp_list);
   1931	return status;
   1932}
   1933
   1934/**
   1935 * ice_aq_map_recipe_to_profile - Map recipe to packet profile
   1936 * @hw: pointer to the HW struct
   1937 * @profile_id: package profile ID to associate the recipe with
   1938 * @r_bitmap: Recipe bitmap filled in and need to be returned as response
   1939 * @cd: pointer to command details structure or NULL
   1940 * Recipe to profile association (0x0291)
   1941 */
   1942static int
   1943ice_aq_map_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u8 *r_bitmap,
   1944			     struct ice_sq_cd *cd)
   1945{
   1946	struct ice_aqc_recipe_to_profile *cmd;
   1947	struct ice_aq_desc desc;
   1948
   1949	cmd = &desc.params.recipe_to_profile;
   1950	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_recipe_to_profile);
   1951	cmd->profile_id = cpu_to_le16(profile_id);
   1952	/* Set the recipe ID bit in the bitmask to let the device know which
   1953	 * profile we are associating the recipe to
   1954	 */
   1955	memcpy(cmd->recipe_assoc, r_bitmap, sizeof(cmd->recipe_assoc));
   1956
   1957	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
   1958}
   1959
   1960/**
   1961 * ice_aq_get_recipe_to_profile - Map recipe to packet profile
   1962 * @hw: pointer to the HW struct
   1963 * @profile_id: package profile ID to associate the recipe with
   1964 * @r_bitmap: Recipe bitmap filled in and need to be returned as response
   1965 * @cd: pointer to command details structure or NULL
   1966 * Associate profile ID with given recipe (0x0293)
   1967 */
   1968static int
   1969ice_aq_get_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u8 *r_bitmap,
   1970			     struct ice_sq_cd *cd)
   1971{
   1972	struct ice_aqc_recipe_to_profile *cmd;
   1973	struct ice_aq_desc desc;
   1974	int status;
   1975
   1976	cmd = &desc.params.recipe_to_profile;
   1977	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_recipe_to_profile);
   1978	cmd->profile_id = cpu_to_le16(profile_id);
   1979
   1980	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
   1981	if (!status)
   1982		memcpy(r_bitmap, cmd->recipe_assoc, sizeof(cmd->recipe_assoc));
   1983
   1984	return status;
   1985}
   1986
   1987/**
   1988 * ice_alloc_recipe - add recipe resource
   1989 * @hw: pointer to the hardware structure
   1990 * @rid: recipe ID returned as response to AQ call
   1991 */
   1992static int ice_alloc_recipe(struct ice_hw *hw, u16 *rid)
   1993{
   1994	struct ice_aqc_alloc_free_res_elem *sw_buf;
   1995	u16 buf_len;
   1996	int status;
   1997
   1998	buf_len = struct_size(sw_buf, elem, 1);
   1999	sw_buf = kzalloc(buf_len, GFP_KERNEL);
   2000	if (!sw_buf)
   2001		return -ENOMEM;
   2002
   2003	sw_buf->num_elems = cpu_to_le16(1);
   2004	sw_buf->res_type = cpu_to_le16((ICE_AQC_RES_TYPE_RECIPE <<
   2005					ICE_AQC_RES_TYPE_S) |
   2006					ICE_AQC_RES_TYPE_FLAG_SHARED);
   2007	status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len,
   2008				       ice_aqc_opc_alloc_res, NULL);
   2009	if (!status)
   2010		*rid = le16_to_cpu(sw_buf->elem[0].e.sw_resp);
   2011	kfree(sw_buf);
   2012
   2013	return status;
   2014}
   2015
   2016/**
   2017 * ice_get_recp_to_prof_map - updates recipe to profile mapping
   2018 * @hw: pointer to hardware structure
   2019 *
   2020 * This function is used to populate recipe_to_profile matrix where index to
   2021 * this array is the recipe ID and the element is the mapping of which profiles
   2022 * is this recipe mapped to.
   2023 */
   2024static void ice_get_recp_to_prof_map(struct ice_hw *hw)
   2025{
   2026	DECLARE_BITMAP(r_bitmap, ICE_MAX_NUM_RECIPES);
   2027	u16 i;
   2028
   2029	for (i = 0; i < hw->switch_info->max_used_prof_index + 1; i++) {
   2030		u16 j;
   2031
   2032		bitmap_zero(profile_to_recipe[i], ICE_MAX_NUM_RECIPES);
   2033		bitmap_zero(r_bitmap, ICE_MAX_NUM_RECIPES);
   2034		if (ice_aq_get_recipe_to_profile(hw, i, (u8 *)r_bitmap, NULL))
   2035			continue;
   2036		bitmap_copy(profile_to_recipe[i], r_bitmap,
   2037			    ICE_MAX_NUM_RECIPES);
   2038		for_each_set_bit(j, r_bitmap, ICE_MAX_NUM_RECIPES)
   2039			set_bit(i, recipe_to_profile[j]);
   2040	}
   2041}
   2042
   2043/**
   2044 * ice_collect_result_idx - copy result index values
   2045 * @buf: buffer that contains the result index
   2046 * @recp: the recipe struct to copy data into
   2047 */
   2048static void
   2049ice_collect_result_idx(struct ice_aqc_recipe_data_elem *buf,
   2050		       struct ice_sw_recipe *recp)
   2051{
   2052	if (buf->content.result_indx & ICE_AQ_RECIPE_RESULT_EN)
   2053		set_bit(buf->content.result_indx & ~ICE_AQ_RECIPE_RESULT_EN,
   2054			recp->res_idxs);
   2055}
   2056
   2057/**
   2058 * ice_get_recp_frm_fw - update SW bookkeeping from FW recipe entries
   2059 * @hw: pointer to hardware structure
   2060 * @recps: struct that we need to populate
   2061 * @rid: recipe ID that we are populating
   2062 * @refresh_required: true if we should get recipe to profile mapping from FW
   2063 *
   2064 * This function is used to populate all the necessary entries into our
   2065 * bookkeeping so that we have a current list of all the recipes that are
   2066 * programmed in the firmware.
   2067 */
   2068static int
   2069ice_get_recp_frm_fw(struct ice_hw *hw, struct ice_sw_recipe *recps, u8 rid,
   2070		    bool *refresh_required)
   2071{
   2072	DECLARE_BITMAP(result_bm, ICE_MAX_FV_WORDS);
   2073	struct ice_aqc_recipe_data_elem *tmp;
   2074	u16 num_recps = ICE_MAX_NUM_RECIPES;
   2075	struct ice_prot_lkup_ext *lkup_exts;
   2076	u8 fv_word_idx = 0;
   2077	u16 sub_recps;
   2078	int status;
   2079
   2080	bitmap_zero(result_bm, ICE_MAX_FV_WORDS);
   2081
   2082	/* we need a buffer big enough to accommodate all the recipes */
   2083	tmp = kcalloc(ICE_MAX_NUM_RECIPES, sizeof(*tmp), GFP_KERNEL);
   2084	if (!tmp)
   2085		return -ENOMEM;
   2086
   2087	tmp[0].recipe_indx = rid;
   2088	status = ice_aq_get_recipe(hw, tmp, &num_recps, rid, NULL);
   2089	/* non-zero status meaning recipe doesn't exist */
   2090	if (status)
   2091		goto err_unroll;
   2092
   2093	/* Get recipe to profile map so that we can get the fv from lkups that
   2094	 * we read for a recipe from FW. Since we want to minimize the number of
   2095	 * times we make this FW call, just make one call and cache the copy
   2096	 * until a new recipe is added. This operation is only required the
   2097	 * first time to get the changes from FW. Then to search existing
   2098	 * entries we don't need to update the cache again until another recipe
   2099	 * gets added.
   2100	 */
   2101	if (*refresh_required) {
   2102		ice_get_recp_to_prof_map(hw);
   2103		*refresh_required = false;
   2104	}
   2105
   2106	/* Start populating all the entries for recps[rid] based on lkups from
   2107	 * firmware. Note that we are only creating the root recipe in our
   2108	 * database.
   2109	 */
   2110	lkup_exts = &recps[rid].lkup_exts;
   2111
   2112	for (sub_recps = 0; sub_recps < num_recps; sub_recps++) {
   2113		struct ice_aqc_recipe_data_elem root_bufs = tmp[sub_recps];
   2114		struct ice_recp_grp_entry *rg_entry;
   2115		u8 i, prof, idx, prot = 0;
   2116		bool is_root;
   2117		u16 off = 0;
   2118
   2119		rg_entry = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*rg_entry),
   2120					GFP_KERNEL);
   2121		if (!rg_entry) {
   2122			status = -ENOMEM;
   2123			goto err_unroll;
   2124		}
   2125
   2126		idx = root_bufs.recipe_indx;
   2127		is_root = root_bufs.content.rid & ICE_AQ_RECIPE_ID_IS_ROOT;
   2128
   2129		/* Mark all result indices in this chain */
   2130		if (root_bufs.content.result_indx & ICE_AQ_RECIPE_RESULT_EN)
   2131			set_bit(root_bufs.content.result_indx & ~ICE_AQ_RECIPE_RESULT_EN,
   2132				result_bm);
   2133
   2134		/* get the first profile that is associated with rid */
   2135		prof = find_first_bit(recipe_to_profile[idx],
   2136				      ICE_MAX_NUM_PROFILES);
   2137		for (i = 0; i < ICE_NUM_WORDS_RECIPE; i++) {
   2138			u8 lkup_indx = root_bufs.content.lkup_indx[i + 1];
   2139
   2140			rg_entry->fv_idx[i] = lkup_indx;
   2141			rg_entry->fv_mask[i] =
   2142				le16_to_cpu(root_bufs.content.mask[i + 1]);
   2143
   2144			/* If the recipe is a chained recipe then all its
   2145			 * child recipe's result will have a result index.
   2146			 * To fill fv_words we should not use those result
   2147			 * index, we only need the protocol ids and offsets.
   2148			 * We will skip all the fv_idx which stores result
   2149			 * index in them. We also need to skip any fv_idx which
   2150			 * has ICE_AQ_RECIPE_LKUP_IGNORE or 0 since it isn't a
   2151			 * valid offset value.
   2152			 */
   2153			if (test_bit(rg_entry->fv_idx[i], hw->switch_info->prof_res_bm[prof]) ||
   2154			    rg_entry->fv_idx[i] & ICE_AQ_RECIPE_LKUP_IGNORE ||
   2155			    rg_entry->fv_idx[i] == 0)
   2156				continue;
   2157
   2158			ice_find_prot_off(hw, ICE_BLK_SW, prof,
   2159					  rg_entry->fv_idx[i], &prot, &off);
   2160			lkup_exts->fv_words[fv_word_idx].prot_id = prot;
   2161			lkup_exts->fv_words[fv_word_idx].off = off;
   2162			lkup_exts->field_mask[fv_word_idx] =
   2163				rg_entry->fv_mask[i];
   2164			fv_word_idx++;
   2165		}
   2166		/* populate rg_list with the data from the child entry of this
   2167		 * recipe
   2168		 */
   2169		list_add(&rg_entry->l_entry, &recps[rid].rg_list);
   2170
   2171		/* Propagate some data to the recipe database */
   2172		recps[idx].is_root = !!is_root;
   2173		recps[idx].priority = root_bufs.content.act_ctrl_fwd_priority;
   2174		bitmap_zero(recps[idx].res_idxs, ICE_MAX_FV_WORDS);
   2175		if (root_bufs.content.result_indx & ICE_AQ_RECIPE_RESULT_EN) {
   2176			recps[idx].chain_idx = root_bufs.content.result_indx &
   2177				~ICE_AQ_RECIPE_RESULT_EN;
   2178			set_bit(recps[idx].chain_idx, recps[idx].res_idxs);
   2179		} else {
   2180			recps[idx].chain_idx = ICE_INVAL_CHAIN_IND;
   2181		}
   2182
   2183		if (!is_root)
   2184			continue;
   2185
   2186		/* Only do the following for root recipes entries */
   2187		memcpy(recps[idx].r_bitmap, root_bufs.recipe_bitmap,
   2188		       sizeof(recps[idx].r_bitmap));
   2189		recps[idx].root_rid = root_bufs.content.rid &
   2190			~ICE_AQ_RECIPE_ID_IS_ROOT;
   2191		recps[idx].priority = root_bufs.content.act_ctrl_fwd_priority;
   2192	}
   2193
   2194	/* Complete initialization of the root recipe entry */
   2195	lkup_exts->n_val_words = fv_word_idx;
   2196	recps[rid].big_recp = (num_recps > 1);
   2197	recps[rid].n_grp_count = (u8)num_recps;
   2198	recps[rid].root_buf = devm_kmemdup(ice_hw_to_dev(hw), tmp,
   2199					   recps[rid].n_grp_count * sizeof(*recps[rid].root_buf),
   2200					   GFP_KERNEL);
   2201	if (!recps[rid].root_buf) {
   2202		status = -ENOMEM;
   2203		goto err_unroll;
   2204	}
   2205
   2206	/* Copy result indexes */
   2207	bitmap_copy(recps[rid].res_idxs, result_bm, ICE_MAX_FV_WORDS);
   2208	recps[rid].recp_created = true;
   2209
   2210err_unroll:
   2211	kfree(tmp);
   2212	return status;
   2213}
   2214
   2215/* ice_init_port_info - Initialize port_info with switch configuration data
   2216 * @pi: pointer to port_info
   2217 * @vsi_port_num: VSI number or port number
   2218 * @type: Type of switch element (port or VSI)
   2219 * @swid: switch ID of the switch the element is attached to
   2220 * @pf_vf_num: PF or VF number
   2221 * @is_vf: true if the element is a VF, false otherwise
   2222 */
   2223static void
   2224ice_init_port_info(struct ice_port_info *pi, u16 vsi_port_num, u8 type,
   2225		   u16 swid, u16 pf_vf_num, bool is_vf)
   2226{
   2227	switch (type) {
   2228	case ICE_AQC_GET_SW_CONF_RESP_PHYS_PORT:
   2229		pi->lport = (u8)(vsi_port_num & ICE_LPORT_MASK);
   2230		pi->sw_id = swid;
   2231		pi->pf_vf_num = pf_vf_num;
   2232		pi->is_vf = is_vf;
   2233		pi->dflt_tx_vsi_num = ICE_DFLT_VSI_INVAL;
   2234		pi->dflt_rx_vsi_num = ICE_DFLT_VSI_INVAL;
   2235		break;
   2236	default:
   2237		ice_debug(pi->hw, ICE_DBG_SW, "incorrect VSI/port type received\n");
   2238		break;
   2239	}
   2240}
   2241
   2242/* ice_get_initial_sw_cfg - Get initial port and default VSI data
   2243 * @hw: pointer to the hardware structure
   2244 */
   2245int ice_get_initial_sw_cfg(struct ice_hw *hw)
   2246{
   2247	struct ice_aqc_get_sw_cfg_resp_elem *rbuf;
   2248	u16 req_desc = 0;
   2249	u16 num_elems;
   2250	int status;
   2251	u16 i;
   2252
   2253	rbuf = devm_kzalloc(ice_hw_to_dev(hw), ICE_SW_CFG_MAX_BUF_LEN,
   2254			    GFP_KERNEL);
   2255
   2256	if (!rbuf)
   2257		return -ENOMEM;
   2258
   2259	/* Multiple calls to ice_aq_get_sw_cfg may be required
   2260	 * to get all the switch configuration information. The need
   2261	 * for additional calls is indicated by ice_aq_get_sw_cfg
   2262	 * writing a non-zero value in req_desc
   2263	 */
   2264	do {
   2265		struct ice_aqc_get_sw_cfg_resp_elem *ele;
   2266
   2267		status = ice_aq_get_sw_cfg(hw, rbuf, ICE_SW_CFG_MAX_BUF_LEN,
   2268					   &req_desc, &num_elems, NULL);
   2269
   2270		if (status)
   2271			break;
   2272
   2273		for (i = 0, ele = rbuf; i < num_elems; i++, ele++) {
   2274			u16 pf_vf_num, swid, vsi_port_num;
   2275			bool is_vf = false;
   2276			u8 res_type;
   2277
   2278			vsi_port_num = le16_to_cpu(ele->vsi_port_num) &
   2279				ICE_AQC_GET_SW_CONF_RESP_VSI_PORT_NUM_M;
   2280
   2281			pf_vf_num = le16_to_cpu(ele->pf_vf_num) &
   2282				ICE_AQC_GET_SW_CONF_RESP_FUNC_NUM_M;
   2283
   2284			swid = le16_to_cpu(ele->swid);
   2285
   2286			if (le16_to_cpu(ele->pf_vf_num) &
   2287			    ICE_AQC_GET_SW_CONF_RESP_IS_VF)
   2288				is_vf = true;
   2289
   2290			res_type = (u8)(le16_to_cpu(ele->vsi_port_num) >>
   2291					ICE_AQC_GET_SW_CONF_RESP_TYPE_S);
   2292
   2293			if (res_type == ICE_AQC_GET_SW_CONF_RESP_VSI) {
   2294				/* FW VSI is not needed. Just continue. */
   2295				continue;
   2296			}
   2297
   2298			ice_init_port_info(hw->port_info, vsi_port_num,
   2299					   res_type, swid, pf_vf_num, is_vf);
   2300		}
   2301	} while (req_desc && !status);
   2302
   2303	devm_kfree(ice_hw_to_dev(hw), rbuf);
   2304	return status;
   2305}
   2306
   2307/**
   2308 * ice_fill_sw_info - Helper function to populate lb_en and lan_en
   2309 * @hw: pointer to the hardware structure
   2310 * @fi: filter info structure to fill/update
   2311 *
   2312 * This helper function populates the lb_en and lan_en elements of the provided
   2313 * ice_fltr_info struct using the switch's type and characteristics of the
   2314 * switch rule being configured.
   2315 */
   2316static void ice_fill_sw_info(struct ice_hw *hw, struct ice_fltr_info *fi)
   2317{
   2318	fi->lb_en = false;
   2319	fi->lan_en = false;
   2320	if ((fi->flag & ICE_FLTR_TX) &&
   2321	    (fi->fltr_act == ICE_FWD_TO_VSI ||
   2322	     fi->fltr_act == ICE_FWD_TO_VSI_LIST ||
   2323	     fi->fltr_act == ICE_FWD_TO_Q ||
   2324	     fi->fltr_act == ICE_FWD_TO_QGRP)) {
   2325		/* Setting LB for prune actions will result in replicated
   2326		 * packets to the internal switch that will be dropped.
   2327		 */
   2328		if (fi->lkup_type != ICE_SW_LKUP_VLAN)
   2329			fi->lb_en = true;
   2330
   2331		/* Set lan_en to TRUE if
   2332		 * 1. The switch is a VEB AND
   2333		 * 2
   2334		 * 2.1 The lookup is a directional lookup like ethertype,
   2335		 * promiscuous, ethertype-MAC, promiscuous-VLAN
   2336		 * and default-port OR
   2337		 * 2.2 The lookup is VLAN, OR
   2338		 * 2.3 The lookup is MAC with mcast or bcast addr for MAC, OR
   2339		 * 2.4 The lookup is MAC_VLAN with mcast or bcast addr for MAC.
   2340		 *
   2341		 * OR
   2342		 *
   2343		 * The switch is a VEPA.
   2344		 *
   2345		 * In all other cases, the LAN enable has to be set to false.
   2346		 */
   2347		if (hw->evb_veb) {
   2348			if (fi->lkup_type == ICE_SW_LKUP_ETHERTYPE ||
   2349			    fi->lkup_type == ICE_SW_LKUP_PROMISC ||
   2350			    fi->lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
   2351			    fi->lkup_type == ICE_SW_LKUP_PROMISC_VLAN ||
   2352			    fi->lkup_type == ICE_SW_LKUP_DFLT ||
   2353			    fi->lkup_type == ICE_SW_LKUP_VLAN ||
   2354			    (fi->lkup_type == ICE_SW_LKUP_MAC &&
   2355			     !is_unicast_ether_addr(fi->l_data.mac.mac_addr)) ||
   2356			    (fi->lkup_type == ICE_SW_LKUP_MAC_VLAN &&
   2357			     !is_unicast_ether_addr(fi->l_data.mac.mac_addr)))
   2358				fi->lan_en = true;
   2359		} else {
   2360			fi->lan_en = true;
   2361		}
   2362	}
   2363}
   2364
   2365/**
   2366 * ice_fill_sw_rule - Helper function to fill switch rule structure
   2367 * @hw: pointer to the hardware structure
   2368 * @f_info: entry containing packet forwarding information
   2369 * @s_rule: switch rule structure to be filled in based on mac_entry
   2370 * @opc: switch rules population command type - pass in the command opcode
   2371 */
   2372static void
   2373ice_fill_sw_rule(struct ice_hw *hw, struct ice_fltr_info *f_info,
   2374		 struct ice_sw_rule_lkup_rx_tx *s_rule,
   2375		 enum ice_adminq_opc opc)
   2376{
   2377	u16 vlan_id = ICE_MAX_VLAN_ID + 1;
   2378	u16 vlan_tpid = ETH_P_8021Q;
   2379	void *daddr = NULL;
   2380	u16 eth_hdr_sz;
   2381	u8 *eth_hdr;
   2382	u32 act = 0;
   2383	__be16 *off;
   2384	u8 q_rgn;
   2385
   2386	if (opc == ice_aqc_opc_remove_sw_rules) {
   2387		s_rule->act = 0;
   2388		s_rule->index = cpu_to_le16(f_info->fltr_rule_id);
   2389		s_rule->hdr_len = 0;
   2390		return;
   2391	}
   2392
   2393	eth_hdr_sz = sizeof(dummy_eth_header);
   2394	eth_hdr = s_rule->hdr_data;
   2395
   2396	/* initialize the ether header with a dummy header */
   2397	memcpy(eth_hdr, dummy_eth_header, eth_hdr_sz);
   2398	ice_fill_sw_info(hw, f_info);
   2399
   2400	switch (f_info->fltr_act) {
   2401	case ICE_FWD_TO_VSI:
   2402		act |= (f_info->fwd_id.hw_vsi_id << ICE_SINGLE_ACT_VSI_ID_S) &
   2403			ICE_SINGLE_ACT_VSI_ID_M;
   2404		if (f_info->lkup_type != ICE_SW_LKUP_VLAN)
   2405			act |= ICE_SINGLE_ACT_VSI_FORWARDING |
   2406				ICE_SINGLE_ACT_VALID_BIT;
   2407		break;
   2408	case ICE_FWD_TO_VSI_LIST:
   2409		act |= ICE_SINGLE_ACT_VSI_LIST;
   2410		act |= (f_info->fwd_id.vsi_list_id <<
   2411			ICE_SINGLE_ACT_VSI_LIST_ID_S) &
   2412			ICE_SINGLE_ACT_VSI_LIST_ID_M;
   2413		if (f_info->lkup_type != ICE_SW_LKUP_VLAN)
   2414			act |= ICE_SINGLE_ACT_VSI_FORWARDING |
   2415				ICE_SINGLE_ACT_VALID_BIT;
   2416		break;
   2417	case ICE_FWD_TO_Q:
   2418		act |= ICE_SINGLE_ACT_TO_Q;
   2419		act |= (f_info->fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) &
   2420			ICE_SINGLE_ACT_Q_INDEX_M;
   2421		break;
   2422	case ICE_DROP_PACKET:
   2423		act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_DROP |
   2424			ICE_SINGLE_ACT_VALID_BIT;
   2425		break;
   2426	case ICE_FWD_TO_QGRP:
   2427		q_rgn = f_info->qgrp_size > 0 ?
   2428			(u8)ilog2(f_info->qgrp_size) : 0;
   2429		act |= ICE_SINGLE_ACT_TO_Q;
   2430		act |= (f_info->fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) &
   2431			ICE_SINGLE_ACT_Q_INDEX_M;
   2432		act |= (q_rgn << ICE_SINGLE_ACT_Q_REGION_S) &
   2433			ICE_SINGLE_ACT_Q_REGION_M;
   2434		break;
   2435	default:
   2436		return;
   2437	}
   2438
   2439	if (f_info->lb_en)
   2440		act |= ICE_SINGLE_ACT_LB_ENABLE;
   2441	if (f_info->lan_en)
   2442		act |= ICE_SINGLE_ACT_LAN_ENABLE;
   2443
   2444	switch (f_info->lkup_type) {
   2445	case ICE_SW_LKUP_MAC:
   2446		daddr = f_info->l_data.mac.mac_addr;
   2447		break;
   2448	case ICE_SW_LKUP_VLAN:
   2449		vlan_id = f_info->l_data.vlan.vlan_id;
   2450		if (f_info->l_data.vlan.tpid_valid)
   2451			vlan_tpid = f_info->l_data.vlan.tpid;
   2452		if (f_info->fltr_act == ICE_FWD_TO_VSI ||
   2453		    f_info->fltr_act == ICE_FWD_TO_VSI_LIST) {
   2454			act |= ICE_SINGLE_ACT_PRUNE;
   2455			act |= ICE_SINGLE_ACT_EGRESS | ICE_SINGLE_ACT_INGRESS;
   2456		}
   2457		break;
   2458	case ICE_SW_LKUP_ETHERTYPE_MAC:
   2459		daddr = f_info->l_data.ethertype_mac.mac_addr;
   2460		fallthrough;
   2461	case ICE_SW_LKUP_ETHERTYPE:
   2462		off = (__force __be16 *)(eth_hdr + ICE_ETH_ETHTYPE_OFFSET);
   2463		*off = cpu_to_be16(f_info->l_data.ethertype_mac.ethertype);
   2464		break;
   2465	case ICE_SW_LKUP_MAC_VLAN:
   2466		daddr = f_info->l_data.mac_vlan.mac_addr;
   2467		vlan_id = f_info->l_data.mac_vlan.vlan_id;
   2468		break;
   2469	case ICE_SW_LKUP_PROMISC_VLAN:
   2470		vlan_id = f_info->l_data.mac_vlan.vlan_id;
   2471		fallthrough;
   2472	case ICE_SW_LKUP_PROMISC:
   2473		daddr = f_info->l_data.mac_vlan.mac_addr;
   2474		break;
   2475	default:
   2476		break;
   2477	}
   2478
   2479	s_rule->hdr.type = (f_info->flag & ICE_FLTR_RX) ?
   2480		cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_RX) :
   2481		cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_TX);
   2482
   2483	/* Recipe set depending on lookup type */
   2484	s_rule->recipe_id = cpu_to_le16(f_info->lkup_type);
   2485	s_rule->src = cpu_to_le16(f_info->src);
   2486	s_rule->act = cpu_to_le32(act);
   2487
   2488	if (daddr)
   2489		ether_addr_copy(eth_hdr + ICE_ETH_DA_OFFSET, daddr);
   2490
   2491	if (!(vlan_id > ICE_MAX_VLAN_ID)) {
   2492		off = (__force __be16 *)(eth_hdr + ICE_ETH_VLAN_TCI_OFFSET);
   2493		*off = cpu_to_be16(vlan_id);
   2494		off = (__force __be16 *)(eth_hdr + ICE_ETH_ETHTYPE_OFFSET);
   2495		*off = cpu_to_be16(vlan_tpid);
   2496	}
   2497
   2498	/* Create the switch rule with the final dummy Ethernet header */
   2499	if (opc != ice_aqc_opc_update_sw_rules)
   2500		s_rule->hdr_len = cpu_to_le16(eth_hdr_sz);
   2501}
   2502
   2503/**
   2504 * ice_add_marker_act
   2505 * @hw: pointer to the hardware structure
   2506 * @m_ent: the management entry for which sw marker needs to be added
   2507 * @sw_marker: sw marker to tag the Rx descriptor with
   2508 * @l_id: large action resource ID
   2509 *
   2510 * Create a large action to hold software marker and update the switch rule
   2511 * entry pointed by m_ent with newly created large action
   2512 */
   2513static int
   2514ice_add_marker_act(struct ice_hw *hw, struct ice_fltr_mgmt_list_entry *m_ent,
   2515		   u16 sw_marker, u16 l_id)
   2516{
   2517	struct ice_sw_rule_lkup_rx_tx *rx_tx;
   2518	struct ice_sw_rule_lg_act *lg_act;
   2519	/* For software marker we need 3 large actions
   2520	 * 1. FWD action: FWD TO VSI or VSI LIST
   2521	 * 2. GENERIC VALUE action to hold the profile ID
   2522	 * 3. GENERIC VALUE action to hold the software marker ID
   2523	 */
   2524	const u16 num_lg_acts = 3;
   2525	u16 lg_act_size;
   2526	u16 rules_size;
   2527	int status;
   2528	u32 act;
   2529	u16 id;
   2530
   2531	if (m_ent->fltr_info.lkup_type != ICE_SW_LKUP_MAC)
   2532		return -EINVAL;
   2533
   2534	/* Create two back-to-back switch rules and submit them to the HW using
   2535	 * one memory buffer:
   2536	 *    1. Large Action
   2537	 *    2. Look up Tx Rx
   2538	 */
   2539	lg_act_size = (u16)ICE_SW_RULE_LG_ACT_SIZE(lg_act, num_lg_acts);
   2540	rules_size = lg_act_size + ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(rx_tx);
   2541	lg_act = devm_kzalloc(ice_hw_to_dev(hw), rules_size, GFP_KERNEL);
   2542	if (!lg_act)
   2543		return -ENOMEM;
   2544
   2545	rx_tx = (typeof(rx_tx))((u8 *)lg_act + lg_act_size);
   2546
   2547	/* Fill in the first switch rule i.e. large action */
   2548	lg_act->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_LG_ACT);
   2549	lg_act->index = cpu_to_le16(l_id);
   2550	lg_act->size = cpu_to_le16(num_lg_acts);
   2551
   2552	/* First action VSI forwarding or VSI list forwarding depending on how
   2553	 * many VSIs
   2554	 */
   2555	id = (m_ent->vsi_count > 1) ? m_ent->fltr_info.fwd_id.vsi_list_id :
   2556		m_ent->fltr_info.fwd_id.hw_vsi_id;
   2557
   2558	act = ICE_LG_ACT_VSI_FORWARDING | ICE_LG_ACT_VALID_BIT;
   2559	act |= (id << ICE_LG_ACT_VSI_LIST_ID_S) & ICE_LG_ACT_VSI_LIST_ID_M;
   2560	if (m_ent->vsi_count > 1)
   2561		act |= ICE_LG_ACT_VSI_LIST;
   2562	lg_act->act[0] = cpu_to_le32(act);
   2563
   2564	/* Second action descriptor type */
   2565	act = ICE_LG_ACT_GENERIC;
   2566
   2567	act |= (1 << ICE_LG_ACT_GENERIC_VALUE_S) & ICE_LG_ACT_GENERIC_VALUE_M;
   2568	lg_act->act[1] = cpu_to_le32(act);
   2569
   2570	act = (ICE_LG_ACT_GENERIC_OFF_RX_DESC_PROF_IDX <<
   2571	       ICE_LG_ACT_GENERIC_OFFSET_S) & ICE_LG_ACT_GENERIC_OFFSET_M;
   2572
   2573	/* Third action Marker value */
   2574	act |= ICE_LG_ACT_GENERIC;
   2575	act |= (sw_marker << ICE_LG_ACT_GENERIC_VALUE_S) &
   2576		ICE_LG_ACT_GENERIC_VALUE_M;
   2577
   2578	lg_act->act[2] = cpu_to_le32(act);
   2579
   2580	/* call the fill switch rule to fill the lookup Tx Rx structure */
   2581	ice_fill_sw_rule(hw, &m_ent->fltr_info, rx_tx,
   2582			 ice_aqc_opc_update_sw_rules);
   2583
   2584	/* Update the action to point to the large action ID */
   2585	rx_tx->act = cpu_to_le32(ICE_SINGLE_ACT_PTR |
   2586				 ((l_id << ICE_SINGLE_ACT_PTR_VAL_S) &
   2587				  ICE_SINGLE_ACT_PTR_VAL_M));
   2588
   2589	/* Use the filter rule ID of the previously created rule with single
   2590	 * act. Once the update happens, hardware will treat this as large
   2591	 * action
   2592	 */
   2593	rx_tx->index = cpu_to_le16(m_ent->fltr_info.fltr_rule_id);
   2594
   2595	status = ice_aq_sw_rules(hw, lg_act, rules_size, 2,
   2596				 ice_aqc_opc_update_sw_rules, NULL);
   2597	if (!status) {
   2598		m_ent->lg_act_idx = l_id;
   2599		m_ent->sw_marker_id = sw_marker;
   2600	}
   2601
   2602	devm_kfree(ice_hw_to_dev(hw), lg_act);
   2603	return status;
   2604}
   2605
   2606/**
   2607 * ice_create_vsi_list_map
   2608 * @hw: pointer to the hardware structure
   2609 * @vsi_handle_arr: array of VSI handles to set in the VSI mapping
   2610 * @num_vsi: number of VSI handles in the array
   2611 * @vsi_list_id: VSI list ID generated as part of allocate resource
   2612 *
   2613 * Helper function to create a new entry of VSI list ID to VSI mapping
   2614 * using the given VSI list ID
   2615 */
   2616static struct ice_vsi_list_map_info *
   2617ice_create_vsi_list_map(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
   2618			u16 vsi_list_id)
   2619{
   2620	struct ice_switch_info *sw = hw->switch_info;
   2621	struct ice_vsi_list_map_info *v_map;
   2622	int i;
   2623
   2624	v_map = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*v_map), GFP_KERNEL);
   2625	if (!v_map)
   2626		return NULL;
   2627
   2628	v_map->vsi_list_id = vsi_list_id;
   2629	v_map->ref_cnt = 1;
   2630	for (i = 0; i < num_vsi; i++)
   2631		set_bit(vsi_handle_arr[i], v_map->vsi_map);
   2632
   2633	list_add(&v_map->list_entry, &sw->vsi_list_map_head);
   2634	return v_map;
   2635}
   2636
   2637/**
   2638 * ice_update_vsi_list_rule
   2639 * @hw: pointer to the hardware structure
   2640 * @vsi_handle_arr: array of VSI handles to form a VSI list
   2641 * @num_vsi: number of VSI handles in the array
   2642 * @vsi_list_id: VSI list ID generated as part of allocate resource
   2643 * @remove: Boolean value to indicate if this is a remove action
   2644 * @opc: switch rules population command type - pass in the command opcode
   2645 * @lkup_type: lookup type of the filter
   2646 *
   2647 * Call AQ command to add a new switch rule or update existing switch rule
   2648 * using the given VSI list ID
   2649 */
   2650static int
   2651ice_update_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
   2652			 u16 vsi_list_id, bool remove, enum ice_adminq_opc opc,
   2653			 enum ice_sw_lkup_type lkup_type)
   2654{
   2655	struct ice_sw_rule_vsi_list *s_rule;
   2656	u16 s_rule_size;
   2657	u16 rule_type;
   2658	int status;
   2659	int i;
   2660
   2661	if (!num_vsi)
   2662		return -EINVAL;
   2663
   2664	if (lkup_type == ICE_SW_LKUP_MAC ||
   2665	    lkup_type == ICE_SW_LKUP_MAC_VLAN ||
   2666	    lkup_type == ICE_SW_LKUP_ETHERTYPE ||
   2667	    lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
   2668	    lkup_type == ICE_SW_LKUP_PROMISC ||
   2669	    lkup_type == ICE_SW_LKUP_PROMISC_VLAN)
   2670		rule_type = remove ? ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR :
   2671			ICE_AQC_SW_RULES_T_VSI_LIST_SET;
   2672	else if (lkup_type == ICE_SW_LKUP_VLAN)
   2673		rule_type = remove ? ICE_AQC_SW_RULES_T_PRUNE_LIST_CLEAR :
   2674			ICE_AQC_SW_RULES_T_PRUNE_LIST_SET;
   2675	else
   2676		return -EINVAL;
   2677
   2678	s_rule_size = (u16)ICE_SW_RULE_VSI_LIST_SIZE(s_rule, num_vsi);
   2679	s_rule = devm_kzalloc(ice_hw_to_dev(hw), s_rule_size, GFP_KERNEL);
   2680	if (!s_rule)
   2681		return -ENOMEM;
   2682	for (i = 0; i < num_vsi; i++) {
   2683		if (!ice_is_vsi_valid(hw, vsi_handle_arr[i])) {
   2684			status = -EINVAL;
   2685			goto exit;
   2686		}
   2687		/* AQ call requires hw_vsi_id(s) */
   2688		s_rule->vsi[i] =
   2689			cpu_to_le16(ice_get_hw_vsi_num(hw, vsi_handle_arr[i]));
   2690	}
   2691
   2692	s_rule->hdr.type = cpu_to_le16(rule_type);
   2693	s_rule->number_vsi = cpu_to_le16(num_vsi);
   2694	s_rule->index = cpu_to_le16(vsi_list_id);
   2695
   2696	status = ice_aq_sw_rules(hw, s_rule, s_rule_size, 1, opc, NULL);
   2697
   2698exit:
   2699	devm_kfree(ice_hw_to_dev(hw), s_rule);
   2700	return status;
   2701}
   2702
   2703/**
   2704 * ice_create_vsi_list_rule - Creates and populates a VSI list rule
   2705 * @hw: pointer to the HW struct
   2706 * @vsi_handle_arr: array of VSI handles to form a VSI list
   2707 * @num_vsi: number of VSI handles in the array
   2708 * @vsi_list_id: stores the ID of the VSI list to be created
   2709 * @lkup_type: switch rule filter's lookup type
   2710 */
   2711static int
   2712ice_create_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
   2713			 u16 *vsi_list_id, enum ice_sw_lkup_type lkup_type)
   2714{
   2715	int status;
   2716
   2717	status = ice_aq_alloc_free_vsi_list(hw, vsi_list_id, lkup_type,
   2718					    ice_aqc_opc_alloc_res);
   2719	if (status)
   2720		return status;
   2721
   2722	/* Update the newly created VSI list to include the specified VSIs */
   2723	return ice_update_vsi_list_rule(hw, vsi_handle_arr, num_vsi,
   2724					*vsi_list_id, false,
   2725					ice_aqc_opc_add_sw_rules, lkup_type);
   2726}
   2727
   2728/**
   2729 * ice_create_pkt_fwd_rule
   2730 * @hw: pointer to the hardware structure
   2731 * @f_entry: entry containing packet forwarding information
   2732 *
   2733 * Create switch rule with given filter information and add an entry
   2734 * to the corresponding filter management list to track this switch rule
   2735 * and VSI mapping
   2736 */
   2737static int
   2738ice_create_pkt_fwd_rule(struct ice_hw *hw,
   2739			struct ice_fltr_list_entry *f_entry)
   2740{
   2741	struct ice_fltr_mgmt_list_entry *fm_entry;
   2742	struct ice_sw_rule_lkup_rx_tx *s_rule;
   2743	enum ice_sw_lkup_type l_type;
   2744	struct ice_sw_recipe *recp;
   2745	int status;
   2746
   2747	s_rule = devm_kzalloc(ice_hw_to_dev(hw),
   2748			      ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(s_rule),
   2749			      GFP_KERNEL);
   2750	if (!s_rule)
   2751		return -ENOMEM;
   2752	fm_entry = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*fm_entry),
   2753				GFP_KERNEL);
   2754	if (!fm_entry) {
   2755		status = -ENOMEM;
   2756		goto ice_create_pkt_fwd_rule_exit;
   2757	}
   2758
   2759	fm_entry->fltr_info = f_entry->fltr_info;
   2760
   2761	/* Initialize all the fields for the management entry */
   2762	fm_entry->vsi_count = 1;
   2763	fm_entry->lg_act_idx = ICE_INVAL_LG_ACT_INDEX;
   2764	fm_entry->sw_marker_id = ICE_INVAL_SW_MARKER_ID;
   2765	fm_entry->counter_index = ICE_INVAL_COUNTER_ID;
   2766
   2767	ice_fill_sw_rule(hw, &fm_entry->fltr_info, s_rule,
   2768			 ice_aqc_opc_add_sw_rules);
   2769
   2770	status = ice_aq_sw_rules(hw, s_rule,
   2771				 ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(s_rule), 1,
   2772				 ice_aqc_opc_add_sw_rules, NULL);
   2773	if (status) {
   2774		devm_kfree(ice_hw_to_dev(hw), fm_entry);
   2775		goto ice_create_pkt_fwd_rule_exit;
   2776	}
   2777
   2778	f_entry->fltr_info.fltr_rule_id = le16_to_cpu(s_rule->index);
   2779	fm_entry->fltr_info.fltr_rule_id = le16_to_cpu(s_rule->index);
   2780
   2781	/* The book keeping entries will get removed when base driver
   2782	 * calls remove filter AQ command
   2783	 */
   2784	l_type = fm_entry->fltr_info.lkup_type;
   2785	recp = &hw->switch_info->recp_list[l_type];
   2786	list_add(&fm_entry->list_entry, &recp->filt_rules);
   2787
   2788ice_create_pkt_fwd_rule_exit:
   2789	devm_kfree(ice_hw_to_dev(hw), s_rule);
   2790	return status;
   2791}
   2792
   2793/**
   2794 * ice_update_pkt_fwd_rule
   2795 * @hw: pointer to the hardware structure
   2796 * @f_info: filter information for switch rule
   2797 *
   2798 * Call AQ command to update a previously created switch rule with a
   2799 * VSI list ID
   2800 */
   2801static int
   2802ice_update_pkt_fwd_rule(struct ice_hw *hw, struct ice_fltr_info *f_info)
   2803{
   2804	struct ice_sw_rule_lkup_rx_tx *s_rule;
   2805	int status;
   2806
   2807	s_rule = devm_kzalloc(ice_hw_to_dev(hw),
   2808			      ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(s_rule),
   2809			      GFP_KERNEL);
   2810	if (!s_rule)
   2811		return -ENOMEM;
   2812
   2813	ice_fill_sw_rule(hw, f_info, s_rule, ice_aqc_opc_update_sw_rules);
   2814
   2815	s_rule->index = cpu_to_le16(f_info->fltr_rule_id);
   2816
   2817	/* Update switch rule with new rule set to forward VSI list */
   2818	status = ice_aq_sw_rules(hw, s_rule,
   2819				 ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(s_rule), 1,
   2820				 ice_aqc_opc_update_sw_rules, NULL);
   2821
   2822	devm_kfree(ice_hw_to_dev(hw), s_rule);
   2823	return status;
   2824}
   2825
   2826/**
   2827 * ice_update_sw_rule_bridge_mode
   2828 * @hw: pointer to the HW struct
   2829 *
   2830 * Updates unicast switch filter rules based on VEB/VEPA mode
   2831 */
   2832int ice_update_sw_rule_bridge_mode(struct ice_hw *hw)
   2833{
   2834	struct ice_switch_info *sw = hw->switch_info;
   2835	struct ice_fltr_mgmt_list_entry *fm_entry;
   2836	struct list_head *rule_head;
   2837	struct mutex *rule_lock; /* Lock to protect filter rule list */
   2838	int status = 0;
   2839
   2840	rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock;
   2841	rule_head = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rules;
   2842
   2843	mutex_lock(rule_lock);
   2844	list_for_each_entry(fm_entry, rule_head, list_entry) {
   2845		struct ice_fltr_info *fi = &fm_entry->fltr_info;
   2846		u8 *addr = fi->l_data.mac.mac_addr;
   2847
   2848		/* Update unicast Tx rules to reflect the selected
   2849		 * VEB/VEPA mode
   2850		 */
   2851		if ((fi->flag & ICE_FLTR_TX) && is_unicast_ether_addr(addr) &&
   2852		    (fi->fltr_act == ICE_FWD_TO_VSI ||
   2853		     fi->fltr_act == ICE_FWD_TO_VSI_LIST ||
   2854		     fi->fltr_act == ICE_FWD_TO_Q ||
   2855		     fi->fltr_act == ICE_FWD_TO_QGRP)) {
   2856			status = ice_update_pkt_fwd_rule(hw, fi);
   2857			if (status)
   2858				break;
   2859		}
   2860	}
   2861
   2862	mutex_unlock(rule_lock);
   2863
   2864	return status;
   2865}
   2866
   2867/**
   2868 * ice_add_update_vsi_list
   2869 * @hw: pointer to the hardware structure
   2870 * @m_entry: pointer to current filter management list entry
   2871 * @cur_fltr: filter information from the book keeping entry
   2872 * @new_fltr: filter information with the new VSI to be added
   2873 *
   2874 * Call AQ command to add or update previously created VSI list with new VSI.
   2875 *
   2876 * Helper function to do book keeping associated with adding filter information
   2877 * The algorithm to do the book keeping is described below :
   2878 * When a VSI needs to subscribe to a given filter (MAC/VLAN/Ethtype etc.)
   2879 *	if only one VSI has been added till now
   2880 *		Allocate a new VSI list and add two VSIs
   2881 *		to this list using switch rule command
   2882 *		Update the previously created switch rule with the
   2883 *		newly created VSI list ID
   2884 *	if a VSI list was previously created
   2885 *		Add the new VSI to the previously created VSI list set
   2886 *		using the update switch rule command
   2887 */
   2888static int
   2889ice_add_update_vsi_list(struct ice_hw *hw,
   2890			struct ice_fltr_mgmt_list_entry *m_entry,
   2891			struct ice_fltr_info *cur_fltr,
   2892			struct ice_fltr_info *new_fltr)
   2893{
   2894	u16 vsi_list_id = 0;
   2895	int status = 0;
   2896
   2897	if ((cur_fltr->fltr_act == ICE_FWD_TO_Q ||
   2898	     cur_fltr->fltr_act == ICE_FWD_TO_QGRP))
   2899		return -EOPNOTSUPP;
   2900
   2901	if ((new_fltr->fltr_act == ICE_FWD_TO_Q ||
   2902	     new_fltr->fltr_act == ICE_FWD_TO_QGRP) &&
   2903	    (cur_fltr->fltr_act == ICE_FWD_TO_VSI ||
   2904	     cur_fltr->fltr_act == ICE_FWD_TO_VSI_LIST))
   2905		return -EOPNOTSUPP;
   2906
   2907	if (m_entry->vsi_count < 2 && !m_entry->vsi_list_info) {
   2908		/* Only one entry existed in the mapping and it was not already
   2909		 * a part of a VSI list. So, create a VSI list with the old and
   2910		 * new VSIs.
   2911		 */
   2912		struct ice_fltr_info tmp_fltr;
   2913		u16 vsi_handle_arr[2];
   2914
   2915		/* A rule already exists with the new VSI being added */
   2916		if (cur_fltr->fwd_id.hw_vsi_id == new_fltr->fwd_id.hw_vsi_id)
   2917			return -EEXIST;
   2918
   2919		vsi_handle_arr[0] = cur_fltr->vsi_handle;
   2920		vsi_handle_arr[1] = new_fltr->vsi_handle;
   2921		status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2,
   2922						  &vsi_list_id,
   2923						  new_fltr->lkup_type);
   2924		if (status)
   2925			return status;
   2926
   2927		tmp_fltr = *new_fltr;
   2928		tmp_fltr.fltr_rule_id = cur_fltr->fltr_rule_id;
   2929		tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST;
   2930		tmp_fltr.fwd_id.vsi_list_id = vsi_list_id;
   2931		/* Update the previous switch rule of "MAC forward to VSI" to
   2932		 * "MAC fwd to VSI list"
   2933		 */
   2934		status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
   2935		if (status)
   2936			return status;
   2937
   2938		cur_fltr->fwd_id.vsi_list_id = vsi_list_id;
   2939		cur_fltr->fltr_act = ICE_FWD_TO_VSI_LIST;
   2940		m_entry->vsi_list_info =
   2941			ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2,
   2942						vsi_list_id);
   2943
   2944		if (!m_entry->vsi_list_info)
   2945			return -ENOMEM;
   2946
   2947		/* If this entry was large action then the large action needs
   2948		 * to be updated to point to FWD to VSI list
   2949		 */
   2950		if (m_entry->sw_marker_id != ICE_INVAL_SW_MARKER_ID)
   2951			status =
   2952			    ice_add_marker_act(hw, m_entry,
   2953					       m_entry->sw_marker_id,
   2954					       m_entry->lg_act_idx);
   2955	} else {
   2956		u16 vsi_handle = new_fltr->vsi_handle;
   2957		enum ice_adminq_opc opcode;
   2958
   2959		if (!m_entry->vsi_list_info)
   2960			return -EIO;
   2961
   2962		/* A rule already exists with the new VSI being added */
   2963		if (test_bit(vsi_handle, m_entry->vsi_list_info->vsi_map))
   2964			return 0;
   2965
   2966		/* Update the previously created VSI list set with
   2967		 * the new VSI ID passed in
   2968		 */
   2969		vsi_list_id = cur_fltr->fwd_id.vsi_list_id;
   2970		opcode = ice_aqc_opc_update_sw_rules;
   2971
   2972		status = ice_update_vsi_list_rule(hw, &vsi_handle, 1,
   2973						  vsi_list_id, false, opcode,
   2974						  new_fltr->lkup_type);
   2975		/* update VSI list mapping info with new VSI ID */
   2976		if (!status)
   2977			set_bit(vsi_handle, m_entry->vsi_list_info->vsi_map);
   2978	}
   2979	if (!status)
   2980		m_entry->vsi_count++;
   2981	return status;
   2982}
   2983
   2984/**
   2985 * ice_find_rule_entry - Search a rule entry
   2986 * @hw: pointer to the hardware structure
   2987 * @recp_id: lookup type for which the specified rule needs to be searched
   2988 * @f_info: rule information
   2989 *
   2990 * Helper function to search for a given rule entry
   2991 * Returns pointer to entry storing the rule if found
   2992 */
   2993static struct ice_fltr_mgmt_list_entry *
   2994ice_find_rule_entry(struct ice_hw *hw, u8 recp_id, struct ice_fltr_info *f_info)
   2995{
   2996	struct ice_fltr_mgmt_list_entry *list_itr, *ret = NULL;
   2997	struct ice_switch_info *sw = hw->switch_info;
   2998	struct list_head *list_head;
   2999
   3000	list_head = &sw->recp_list[recp_id].filt_rules;
   3001	list_for_each_entry(list_itr, list_head, list_entry) {
   3002		if (!memcmp(&f_info->l_data, &list_itr->fltr_info.l_data,
   3003			    sizeof(f_info->l_data)) &&
   3004		    f_info->flag == list_itr->fltr_info.flag) {
   3005			ret = list_itr;
   3006			break;
   3007		}
   3008	}
   3009	return ret;
   3010}
   3011
   3012/**
   3013 * ice_find_vsi_list_entry - Search VSI list map with VSI count 1
   3014 * @hw: pointer to the hardware structure
   3015 * @recp_id: lookup type for which VSI lists needs to be searched
   3016 * @vsi_handle: VSI handle to be found in VSI list
   3017 * @vsi_list_id: VSI list ID found containing vsi_handle
   3018 *
   3019 * Helper function to search a VSI list with single entry containing given VSI
   3020 * handle element. This can be extended further to search VSI list with more
   3021 * than 1 vsi_count. Returns pointer to VSI list entry if found.
   3022 */
   3023static struct ice_vsi_list_map_info *
   3024ice_find_vsi_list_entry(struct ice_hw *hw, u8 recp_id, u16 vsi_handle,
   3025			u16 *vsi_list_id)
   3026{
   3027	struct ice_vsi_list_map_info *map_info = NULL;
   3028	struct ice_switch_info *sw = hw->switch_info;
   3029	struct ice_fltr_mgmt_list_entry *list_itr;
   3030	struct list_head *list_head;
   3031
   3032	list_head = &sw->recp_list[recp_id].filt_rules;
   3033	list_for_each_entry(list_itr, list_head, list_entry) {
   3034		if (list_itr->vsi_count == 1 && list_itr->vsi_list_info) {
   3035			map_info = list_itr->vsi_list_info;
   3036			if (test_bit(vsi_handle, map_info->vsi_map)) {
   3037				*vsi_list_id = map_info->vsi_list_id;
   3038				return map_info;
   3039			}
   3040		}
   3041	}
   3042	return NULL;
   3043}
   3044
   3045/**
   3046 * ice_add_rule_internal - add rule for a given lookup type
   3047 * @hw: pointer to the hardware structure
   3048 * @recp_id: lookup type (recipe ID) for which rule has to be added
   3049 * @f_entry: structure containing MAC forwarding information
   3050 *
   3051 * Adds or updates the rule lists for a given recipe
   3052 */
   3053static int
   3054ice_add_rule_internal(struct ice_hw *hw, u8 recp_id,
   3055		      struct ice_fltr_list_entry *f_entry)
   3056{
   3057	struct ice_switch_info *sw = hw->switch_info;
   3058	struct ice_fltr_info *new_fltr, *cur_fltr;
   3059	struct ice_fltr_mgmt_list_entry *m_entry;
   3060	struct mutex *rule_lock; /* Lock to protect filter rule list */
   3061	int status = 0;
   3062
   3063	if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle))
   3064		return -EINVAL;
   3065	f_entry->fltr_info.fwd_id.hw_vsi_id =
   3066		ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
   3067
   3068	rule_lock = &sw->recp_list[recp_id].filt_rule_lock;
   3069
   3070	mutex_lock(rule_lock);
   3071	new_fltr = &f_entry->fltr_info;
   3072	if (new_fltr->flag & ICE_FLTR_RX)
   3073		new_fltr->src = hw->port_info->lport;
   3074	else if (new_fltr->flag & ICE_FLTR_TX)
   3075		new_fltr->src = f_entry->fltr_info.fwd_id.hw_vsi_id;
   3076
   3077	m_entry = ice_find_rule_entry(hw, recp_id, new_fltr);
   3078	if (!m_entry) {
   3079		mutex_unlock(rule_lock);
   3080		return ice_create_pkt_fwd_rule(hw, f_entry);
   3081	}
   3082
   3083	cur_fltr = &m_entry->fltr_info;
   3084	status = ice_add_update_vsi_list(hw, m_entry, cur_fltr, new_fltr);
   3085	mutex_unlock(rule_lock);
   3086
   3087	return status;
   3088}
   3089
   3090/**
   3091 * ice_remove_vsi_list_rule
   3092 * @hw: pointer to the hardware structure
   3093 * @vsi_list_id: VSI list ID generated as part of allocate resource
   3094 * @lkup_type: switch rule filter lookup type
   3095 *
   3096 * The VSI list should be emptied before this function is called to remove the
   3097 * VSI list.
   3098 */
   3099static int
   3100ice_remove_vsi_list_rule(struct ice_hw *hw, u16 vsi_list_id,
   3101			 enum ice_sw_lkup_type lkup_type)
   3102{
   3103	struct ice_sw_rule_vsi_list *s_rule;
   3104	u16 s_rule_size;
   3105	int status;
   3106
   3107	s_rule_size = (u16)ICE_SW_RULE_VSI_LIST_SIZE(s_rule, 0);
   3108	s_rule = devm_kzalloc(ice_hw_to_dev(hw), s_rule_size, GFP_KERNEL);
   3109	if (!s_rule)
   3110		return -ENOMEM;
   3111
   3112	s_rule->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR);
   3113	s_rule->index = cpu_to_le16(vsi_list_id);
   3114
   3115	/* Free the vsi_list resource that we allocated. It is assumed that the
   3116	 * list is empty at this point.
   3117	 */
   3118	status = ice_aq_alloc_free_vsi_list(hw, &vsi_list_id, lkup_type,
   3119					    ice_aqc_opc_free_res);
   3120
   3121	devm_kfree(ice_hw_to_dev(hw), s_rule);
   3122	return status;
   3123}
   3124
   3125/**
   3126 * ice_rem_update_vsi_list
   3127 * @hw: pointer to the hardware structure
   3128 * @vsi_handle: VSI handle of the VSI to remove
   3129 * @fm_list: filter management entry for which the VSI list management needs to
   3130 *           be done
   3131 */
   3132static int
   3133ice_rem_update_vsi_list(struct ice_hw *hw, u16 vsi_handle,
   3134			struct ice_fltr_mgmt_list_entry *fm_list)
   3135{
   3136	enum ice_sw_lkup_type lkup_type;
   3137	u16 vsi_list_id;
   3138	int status = 0;
   3139
   3140	if (fm_list->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST ||
   3141	    fm_list->vsi_count == 0)
   3142		return -EINVAL;
   3143
   3144	/* A rule with the VSI being removed does not exist */
   3145	if (!test_bit(vsi_handle, fm_list->vsi_list_info->vsi_map))
   3146		return -ENOENT;
   3147
   3148	lkup_type = fm_list->fltr_info.lkup_type;
   3149	vsi_list_id = fm_list->fltr_info.fwd_id.vsi_list_id;
   3150	status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, vsi_list_id, true,
   3151					  ice_aqc_opc_update_sw_rules,
   3152					  lkup_type);
   3153	if (status)
   3154		return status;
   3155
   3156	fm_list->vsi_count--;
   3157	clear_bit(vsi_handle, fm_list->vsi_list_info->vsi_map);
   3158
   3159	if (fm_list->vsi_count == 1 && lkup_type != ICE_SW_LKUP_VLAN) {
   3160		struct ice_fltr_info tmp_fltr_info = fm_list->fltr_info;
   3161		struct ice_vsi_list_map_info *vsi_list_info =
   3162			fm_list->vsi_list_info;
   3163		u16 rem_vsi_handle;
   3164
   3165		rem_vsi_handle = find_first_bit(vsi_list_info->vsi_map,
   3166						ICE_MAX_VSI);
   3167		if (!ice_is_vsi_valid(hw, rem_vsi_handle))
   3168			return -EIO;
   3169
   3170		/* Make sure VSI list is empty before removing it below */
   3171		status = ice_update_vsi_list_rule(hw, &rem_vsi_handle, 1,
   3172						  vsi_list_id, true,
   3173						  ice_aqc_opc_update_sw_rules,
   3174						  lkup_type);
   3175		if (status)
   3176			return status;
   3177
   3178		tmp_fltr_info.fltr_act = ICE_FWD_TO_VSI;
   3179		tmp_fltr_info.fwd_id.hw_vsi_id =
   3180			ice_get_hw_vsi_num(hw, rem_vsi_handle);
   3181		tmp_fltr_info.vsi_handle = rem_vsi_handle;
   3182		status = ice_update_pkt_fwd_rule(hw, &tmp_fltr_info);
   3183		if (status) {
   3184			ice_debug(hw, ICE_DBG_SW, "Failed to update pkt fwd rule to FWD_TO_VSI on HW VSI %d, error %d\n",
   3185				  tmp_fltr_info.fwd_id.hw_vsi_id, status);
   3186			return status;
   3187		}
   3188
   3189		fm_list->fltr_info = tmp_fltr_info;
   3190	}
   3191
   3192	if ((fm_list->vsi_count == 1 && lkup_type != ICE_SW_LKUP_VLAN) ||
   3193	    (fm_list->vsi_count == 0 && lkup_type == ICE_SW_LKUP_VLAN)) {
   3194		struct ice_vsi_list_map_info *vsi_list_info =
   3195			fm_list->vsi_list_info;
   3196
   3197		/* Remove the VSI list since it is no longer used */
   3198		status = ice_remove_vsi_list_rule(hw, vsi_list_id, lkup_type);
   3199		if (status) {
   3200			ice_debug(hw, ICE_DBG_SW, "Failed to remove VSI list %d, error %d\n",
   3201				  vsi_list_id, status);
   3202			return status;
   3203		}
   3204
   3205		list_del(&vsi_list_info->list_entry);
   3206		devm_kfree(ice_hw_to_dev(hw), vsi_list_info);
   3207		fm_list->vsi_list_info = NULL;
   3208	}
   3209
   3210	return status;
   3211}
   3212
   3213/**
   3214 * ice_remove_rule_internal - Remove a filter rule of a given type
   3215 * @hw: pointer to the hardware structure
   3216 * @recp_id: recipe ID for which the rule needs to removed
   3217 * @f_entry: rule entry containing filter information
   3218 */
   3219static int
   3220ice_remove_rule_internal(struct ice_hw *hw, u8 recp_id,
   3221			 struct ice_fltr_list_entry *f_entry)
   3222{
   3223	struct ice_switch_info *sw = hw->switch_info;
   3224	struct ice_fltr_mgmt_list_entry *list_elem;
   3225	struct mutex *rule_lock; /* Lock to protect filter rule list */
   3226	bool remove_rule = false;
   3227	u16 vsi_handle;
   3228	int status = 0;
   3229
   3230	if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle))
   3231		return -EINVAL;
   3232	f_entry->fltr_info.fwd_id.hw_vsi_id =
   3233		ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
   3234
   3235	rule_lock = &sw->recp_list[recp_id].filt_rule_lock;
   3236	mutex_lock(rule_lock);
   3237	list_elem = ice_find_rule_entry(hw, recp_id, &f_entry->fltr_info);
   3238	if (!list_elem) {
   3239		status = -ENOENT;
   3240		goto exit;
   3241	}
   3242
   3243	if (list_elem->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST) {
   3244		remove_rule = true;
   3245	} else if (!list_elem->vsi_list_info) {
   3246		status = -ENOENT;
   3247		goto exit;
   3248	} else if (list_elem->vsi_list_info->ref_cnt > 1) {
   3249		/* a ref_cnt > 1 indicates that the vsi_list is being
   3250		 * shared by multiple rules. Decrement the ref_cnt and
   3251		 * remove this rule, but do not modify the list, as it
   3252		 * is in-use by other rules.
   3253		 */
   3254		list_elem->vsi_list_info->ref_cnt--;
   3255		remove_rule = true;
   3256	} else {
   3257		/* a ref_cnt of 1 indicates the vsi_list is only used
   3258		 * by one rule. However, the original removal request is only
   3259		 * for a single VSI. Update the vsi_list first, and only
   3260		 * remove the rule if there are no further VSIs in this list.
   3261		 */
   3262		vsi_handle = f_entry->fltr_info.vsi_handle;
   3263		status = ice_rem_update_vsi_list(hw, vsi_handle, list_elem);
   3264		if (status)
   3265			goto exit;
   3266		/* if VSI count goes to zero after updating the VSI list */
   3267		if (list_elem->vsi_count == 0)
   3268			remove_rule = true;
   3269	}
   3270
   3271	if (remove_rule) {
   3272		/* Remove the lookup rule */
   3273		struct ice_sw_rule_lkup_rx_tx *s_rule;
   3274
   3275		s_rule = devm_kzalloc(ice_hw_to_dev(hw),
   3276				      ICE_SW_RULE_RX_TX_NO_HDR_SIZE(s_rule),
   3277				      GFP_KERNEL);
   3278		if (!s_rule) {
   3279			status = -ENOMEM;
   3280			goto exit;
   3281		}
   3282
   3283		ice_fill_sw_rule(hw, &list_elem->fltr_info, s_rule,
   3284				 ice_aqc_opc_remove_sw_rules);
   3285
   3286		status = ice_aq_sw_rules(hw, s_rule,
   3287					 ICE_SW_RULE_RX_TX_NO_HDR_SIZE(s_rule),
   3288					 1, ice_aqc_opc_remove_sw_rules, NULL);
   3289
   3290		/* Remove a book keeping from the list */
   3291		devm_kfree(ice_hw_to_dev(hw), s_rule);
   3292
   3293		if (status)
   3294			goto exit;
   3295
   3296		list_del(&list_elem->list_entry);
   3297		devm_kfree(ice_hw_to_dev(hw), list_elem);
   3298	}
   3299exit:
   3300	mutex_unlock(rule_lock);
   3301	return status;
   3302}
   3303
   3304/**
   3305 * ice_mac_fltr_exist - does this MAC filter exist for given VSI
   3306 * @hw: pointer to the hardware structure
   3307 * @mac: MAC address to be checked (for MAC filter)
   3308 * @vsi_handle: check MAC filter for this VSI
   3309 */
   3310bool ice_mac_fltr_exist(struct ice_hw *hw, u8 *mac, u16 vsi_handle)
   3311{
   3312	struct ice_fltr_mgmt_list_entry *entry;
   3313	struct list_head *rule_head;
   3314	struct ice_switch_info *sw;
   3315	struct mutex *rule_lock; /* Lock to protect filter rule list */
   3316	u16 hw_vsi_id;
   3317
   3318	if (!ice_is_vsi_valid(hw, vsi_handle))
   3319		return false;
   3320
   3321	hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
   3322	sw = hw->switch_info;
   3323	rule_head = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rules;
   3324	if (!rule_head)
   3325		return false;
   3326
   3327	rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock;
   3328	mutex_lock(rule_lock);
   3329	list_for_each_entry(entry, rule_head, list_entry) {
   3330		struct ice_fltr_info *f_info = &entry->fltr_info;
   3331		u8 *mac_addr = &f_info->l_data.mac.mac_addr[0];
   3332
   3333		if (is_zero_ether_addr(mac_addr))
   3334			continue;
   3335
   3336		if (f_info->flag != ICE_FLTR_TX ||
   3337		    f_info->src_id != ICE_SRC_ID_VSI ||
   3338		    f_info->lkup_type != ICE_SW_LKUP_MAC ||
   3339		    f_info->fltr_act != ICE_FWD_TO_VSI ||
   3340		    hw_vsi_id != f_info->fwd_id.hw_vsi_id)
   3341			continue;
   3342
   3343		if (ether_addr_equal(mac, mac_addr)) {
   3344			mutex_unlock(rule_lock);
   3345			return true;
   3346		}
   3347	}
   3348	mutex_unlock(rule_lock);
   3349	return false;
   3350}
   3351
   3352/**
   3353 * ice_vlan_fltr_exist - does this VLAN filter exist for given VSI
   3354 * @hw: pointer to the hardware structure
   3355 * @vlan_id: VLAN ID
   3356 * @vsi_handle: check MAC filter for this VSI
   3357 */
   3358bool ice_vlan_fltr_exist(struct ice_hw *hw, u16 vlan_id, u16 vsi_handle)
   3359{
   3360	struct ice_fltr_mgmt_list_entry *entry;
   3361	struct list_head *rule_head;
   3362	struct ice_switch_info *sw;
   3363	struct mutex *rule_lock; /* Lock to protect filter rule list */
   3364	u16 hw_vsi_id;
   3365
   3366	if (vlan_id > ICE_MAX_VLAN_ID)
   3367		return false;
   3368
   3369	if (!ice_is_vsi_valid(hw, vsi_handle))
   3370		return false;
   3371
   3372	hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
   3373	sw = hw->switch_info;
   3374	rule_head = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rules;
   3375	if (!rule_head)
   3376		return false;
   3377
   3378	rule_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock;
   3379	mutex_lock(rule_lock);
   3380	list_for_each_entry(entry, rule_head, list_entry) {
   3381		struct ice_fltr_info *f_info = &entry->fltr_info;
   3382		u16 entry_vlan_id = f_info->l_data.vlan.vlan_id;
   3383		struct ice_vsi_list_map_info *map_info;
   3384
   3385		if (entry_vlan_id > ICE_MAX_VLAN_ID)
   3386			continue;
   3387
   3388		if (f_info->flag != ICE_FLTR_TX ||
   3389		    f_info->src_id != ICE_SRC_ID_VSI ||
   3390		    f_info->lkup_type != ICE_SW_LKUP_VLAN)
   3391			continue;
   3392
   3393		/* Only allowed filter action are FWD_TO_VSI/_VSI_LIST */
   3394		if (f_info->fltr_act != ICE_FWD_TO_VSI &&
   3395		    f_info->fltr_act != ICE_FWD_TO_VSI_LIST)
   3396			continue;
   3397
   3398		if (f_info->fltr_act == ICE_FWD_TO_VSI) {
   3399			if (hw_vsi_id != f_info->fwd_id.hw_vsi_id)
   3400				continue;
   3401		} else if (f_info->fltr_act == ICE_FWD_TO_VSI_LIST) {
   3402			/* If filter_action is FWD_TO_VSI_LIST, make sure
   3403			 * that VSI being checked is part of VSI list
   3404			 */
   3405			if (entry->vsi_count == 1 &&
   3406			    entry->vsi_list_info) {
   3407				map_info = entry->vsi_list_info;
   3408				if (!test_bit(vsi_handle, map_info->vsi_map))
   3409					continue;
   3410			}
   3411		}
   3412
   3413		if (vlan_id == entry_vlan_id) {
   3414			mutex_unlock(rule_lock);
   3415			return true;
   3416		}
   3417	}
   3418	mutex_unlock(rule_lock);
   3419
   3420	return false;
   3421}
   3422
   3423/**
   3424 * ice_add_mac - Add a MAC address based filter rule
   3425 * @hw: pointer to the hardware structure
   3426 * @m_list: list of MAC addresses and forwarding information
   3427 *
   3428 * IMPORTANT: When the ucast_shared flag is set to false and m_list has
   3429 * multiple unicast addresses, the function assumes that all the
   3430 * addresses are unique in a given add_mac call. It doesn't
   3431 * check for duplicates in this case, removing duplicates from a given
   3432 * list should be taken care of in the caller of this function.
   3433 */
   3434int ice_add_mac(struct ice_hw *hw, struct list_head *m_list)
   3435{
   3436	struct ice_sw_rule_lkup_rx_tx *s_rule, *r_iter;
   3437	struct ice_fltr_list_entry *m_list_itr;
   3438	struct list_head *rule_head;
   3439	u16 total_elem_left, s_rule_size;
   3440	struct ice_switch_info *sw;
   3441	struct mutex *rule_lock; /* Lock to protect filter rule list */
   3442	u16 num_unicast = 0;
   3443	int status = 0;
   3444	u8 elem_sent;
   3445
   3446	if (!m_list || !hw)
   3447		return -EINVAL;
   3448
   3449	s_rule = NULL;
   3450	sw = hw->switch_info;
   3451	rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock;
   3452	list_for_each_entry(m_list_itr, m_list, list_entry) {
   3453		u8 *add = &m_list_itr->fltr_info.l_data.mac.mac_addr[0];
   3454		u16 vsi_handle;
   3455		u16 hw_vsi_id;
   3456
   3457		m_list_itr->fltr_info.flag = ICE_FLTR_TX;
   3458		vsi_handle = m_list_itr->fltr_info.vsi_handle;
   3459		if (!ice_is_vsi_valid(hw, vsi_handle))
   3460			return -EINVAL;
   3461		hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
   3462		m_list_itr->fltr_info.fwd_id.hw_vsi_id = hw_vsi_id;
   3463		/* update the src in case it is VSI num */
   3464		if (m_list_itr->fltr_info.src_id != ICE_SRC_ID_VSI)
   3465			return -EINVAL;
   3466		m_list_itr->fltr_info.src = hw_vsi_id;
   3467		if (m_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_MAC ||
   3468		    is_zero_ether_addr(add))
   3469			return -EINVAL;
   3470		if (is_unicast_ether_addr(add) && !hw->ucast_shared) {
   3471			/* Don't overwrite the unicast address */
   3472			mutex_lock(rule_lock);
   3473			if (ice_find_rule_entry(hw, ICE_SW_LKUP_MAC,
   3474						&m_list_itr->fltr_info)) {
   3475				mutex_unlock(rule_lock);
   3476				return -EEXIST;
   3477			}
   3478			mutex_unlock(rule_lock);
   3479			num_unicast++;
   3480		} else if (is_multicast_ether_addr(add) ||
   3481			   (is_unicast_ether_addr(add) && hw->ucast_shared)) {
   3482			m_list_itr->status =
   3483				ice_add_rule_internal(hw, ICE_SW_LKUP_MAC,
   3484						      m_list_itr);
   3485			if (m_list_itr->status)
   3486				return m_list_itr->status;
   3487		}
   3488	}
   3489
   3490	mutex_lock(rule_lock);
   3491	/* Exit if no suitable entries were found for adding bulk switch rule */
   3492	if (!num_unicast) {
   3493		status = 0;
   3494		goto ice_add_mac_exit;
   3495	}
   3496
   3497	rule_head = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rules;
   3498
   3499	/* Allocate switch rule buffer for the bulk update for unicast */
   3500	s_rule_size = ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(s_rule);
   3501	s_rule = devm_kcalloc(ice_hw_to_dev(hw), num_unicast, s_rule_size,
   3502			      GFP_KERNEL);
   3503	if (!s_rule) {
   3504		status = -ENOMEM;
   3505		goto ice_add_mac_exit;
   3506	}
   3507
   3508	r_iter = s_rule;
   3509	list_for_each_entry(m_list_itr, m_list, list_entry) {
   3510		struct ice_fltr_info *f_info = &m_list_itr->fltr_info;
   3511		u8 *mac_addr = &f_info->l_data.mac.mac_addr[0];
   3512
   3513		if (is_unicast_ether_addr(mac_addr)) {
   3514			ice_fill_sw_rule(hw, &m_list_itr->fltr_info, r_iter,
   3515					 ice_aqc_opc_add_sw_rules);
   3516			r_iter = (typeof(s_rule))((u8 *)r_iter + s_rule_size);
   3517		}
   3518	}
   3519
   3520	/* Call AQ bulk switch rule update for all unicast addresses */
   3521	r_iter = s_rule;
   3522	/* Call AQ switch rule in AQ_MAX chunk */
   3523	for (total_elem_left = num_unicast; total_elem_left > 0;
   3524	     total_elem_left -= elem_sent) {
   3525		struct ice_sw_rule_lkup_rx_tx *entry = r_iter;
   3526
   3527		elem_sent = min_t(u8, total_elem_left,
   3528				  (ICE_AQ_MAX_BUF_LEN / s_rule_size));
   3529		status = ice_aq_sw_rules(hw, entry, elem_sent * s_rule_size,
   3530					 elem_sent, ice_aqc_opc_add_sw_rules,
   3531					 NULL);
   3532		if (status)
   3533			goto ice_add_mac_exit;
   3534		r_iter = (typeof(s_rule))
   3535			((u8 *)r_iter + (elem_sent * s_rule_size));
   3536	}
   3537
   3538	/* Fill up rule ID based on the value returned from FW */
   3539	r_iter = s_rule;
   3540	list_for_each_entry(m_list_itr, m_list, list_entry) {
   3541		struct ice_fltr_info *f_info = &m_list_itr->fltr_info;
   3542		u8 *mac_addr = &f_info->l_data.mac.mac_addr[0];
   3543		struct ice_fltr_mgmt_list_entry *fm_entry;
   3544
   3545		if (is_unicast_ether_addr(mac_addr)) {
   3546			f_info->fltr_rule_id = le16_to_cpu(r_iter->index);
   3547			f_info->fltr_act = ICE_FWD_TO_VSI;
   3548			/* Create an entry to track this MAC address */
   3549			fm_entry = devm_kzalloc(ice_hw_to_dev(hw),
   3550						sizeof(*fm_entry), GFP_KERNEL);
   3551			if (!fm_entry) {
   3552				status = -ENOMEM;
   3553				goto ice_add_mac_exit;
   3554			}
   3555			fm_entry->fltr_info = *f_info;
   3556			fm_entry->vsi_count = 1;
   3557			/* The book keeping entries will get removed when
   3558			 * base driver calls remove filter AQ command
   3559			 */
   3560
   3561			list_add(&fm_entry->list_entry, rule_head);
   3562			r_iter = (typeof(s_rule))((u8 *)r_iter + s_rule_size);
   3563		}
   3564	}
   3565
   3566ice_add_mac_exit:
   3567	mutex_unlock(rule_lock);
   3568	if (s_rule)
   3569		devm_kfree(ice_hw_to_dev(hw), s_rule);
   3570	return status;
   3571}
   3572
   3573/**
   3574 * ice_add_vlan_internal - Add one VLAN based filter rule
   3575 * @hw: pointer to the hardware structure
   3576 * @f_entry: filter entry containing one VLAN information
   3577 */
   3578static int
   3579ice_add_vlan_internal(struct ice_hw *hw, struct ice_fltr_list_entry *f_entry)
   3580{
   3581	struct ice_switch_info *sw = hw->switch_info;
   3582	struct ice_fltr_mgmt_list_entry *v_list_itr;
   3583	struct ice_fltr_info *new_fltr, *cur_fltr;
   3584	enum ice_sw_lkup_type lkup_type;
   3585	u16 vsi_list_id = 0, vsi_handle;
   3586	struct mutex *rule_lock; /* Lock to protect filter rule list */
   3587	int status = 0;
   3588
   3589	if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle))
   3590		return -EINVAL;
   3591
   3592	f_entry->fltr_info.fwd_id.hw_vsi_id =
   3593		ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
   3594	new_fltr = &f_entry->fltr_info;
   3595
   3596	/* VLAN ID should only be 12 bits */
   3597	if (new_fltr->l_data.vlan.vlan_id > ICE_MAX_VLAN_ID)
   3598		return -EINVAL;
   3599
   3600	if (new_fltr->src_id != ICE_SRC_ID_VSI)
   3601		return -EINVAL;
   3602
   3603	new_fltr->src = new_fltr->fwd_id.hw_vsi_id;
   3604	lkup_type = new_fltr->lkup_type;
   3605	vsi_handle = new_fltr->vsi_handle;
   3606	rule_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock;
   3607	mutex_lock(rule_lock);
   3608	v_list_itr = ice_find_rule_entry(hw, ICE_SW_LKUP_VLAN, new_fltr);
   3609	if (!v_list_itr) {
   3610		struct ice_vsi_list_map_info *map_info = NULL;
   3611
   3612		if (new_fltr->fltr_act == ICE_FWD_TO_VSI) {
   3613			/* All VLAN pruning rules use a VSI list. Check if
   3614			 * there is already a VSI list containing VSI that we
   3615			 * want to add. If found, use the same vsi_list_id for
   3616			 * this new VLAN rule or else create a new list.
   3617			 */
   3618			map_info = ice_find_vsi_list_entry(hw, ICE_SW_LKUP_VLAN,
   3619							   vsi_handle,
   3620							   &vsi_list_id);
   3621			if (!map_info) {
   3622				status = ice_create_vsi_list_rule(hw,
   3623								  &vsi_handle,
   3624								  1,
   3625								  &vsi_list_id,
   3626								  lkup_type);
   3627				if (status)
   3628					goto exit;
   3629			}
   3630			/* Convert the action to forwarding to a VSI list. */
   3631			new_fltr->fltr_act = ICE_FWD_TO_VSI_LIST;
   3632			new_fltr->fwd_id.vsi_list_id = vsi_list_id;
   3633		}
   3634
   3635		status = ice_create_pkt_fwd_rule(hw, f_entry);
   3636		if (!status) {
   3637			v_list_itr = ice_find_rule_entry(hw, ICE_SW_LKUP_VLAN,
   3638							 new_fltr);
   3639			if (!v_list_itr) {
   3640				status = -ENOENT;
   3641				goto exit;
   3642			}
   3643			/* reuse VSI list for new rule and increment ref_cnt */
   3644			if (map_info) {
   3645				v_list_itr->vsi_list_info = map_info;
   3646				map_info->ref_cnt++;
   3647			} else {
   3648				v_list_itr->vsi_list_info =
   3649					ice_create_vsi_list_map(hw, &vsi_handle,
   3650								1, vsi_list_id);
   3651			}
   3652		}
   3653	} else if (v_list_itr->vsi_list_info->ref_cnt == 1) {
   3654		/* Update existing VSI list to add new VSI ID only if it used
   3655		 * by one VLAN rule.
   3656		 */
   3657		cur_fltr = &v_list_itr->fltr_info;
   3658		status = ice_add_update_vsi_list(hw, v_list_itr, cur_fltr,
   3659						 new_fltr);
   3660	} else {
   3661		/* If VLAN rule exists and VSI list being used by this rule is
   3662		 * referenced by more than 1 VLAN rule. Then create a new VSI
   3663		 * list appending previous VSI with new VSI and update existing
   3664		 * VLAN rule to point to new VSI list ID
   3665		 */
   3666		struct ice_fltr_info tmp_fltr;
   3667		u16 vsi_handle_arr[2];
   3668		u16 cur_handle;
   3669
   3670		/* Current implementation only supports reusing VSI list with
   3671		 * one VSI count. We should never hit below condition
   3672		 */
   3673		if (v_list_itr->vsi_count > 1 &&
   3674		    v_list_itr->vsi_list_info->ref_cnt > 1) {
   3675			ice_debug(hw, ICE_DBG_SW, "Invalid configuration: Optimization to reuse VSI list with more than one VSI is not being done yet\n");
   3676			status = -EIO;
   3677			goto exit;
   3678		}
   3679
   3680		cur_handle =
   3681			find_first_bit(v_list_itr->vsi_list_info->vsi_map,
   3682				       ICE_MAX_VSI);
   3683
   3684		/* A rule already exists with the new VSI being added */
   3685		if (cur_handle == vsi_handle) {
   3686			status = -EEXIST;
   3687			goto exit;
   3688		}
   3689
   3690		vsi_handle_arr[0] = cur_handle;
   3691		vsi_handle_arr[1] = vsi_handle;
   3692		status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2,
   3693						  &vsi_list_id, lkup_type);
   3694		if (status)
   3695			goto exit;
   3696
   3697		tmp_fltr = v_list_itr->fltr_info;
   3698		tmp_fltr.fltr_rule_id = v_list_itr->fltr_info.fltr_rule_id;
   3699		tmp_fltr.fwd_id.vsi_list_id = vsi_list_id;
   3700		tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST;
   3701		/* Update the previous switch rule to a new VSI list which
   3702		 * includes current VSI that is requested
   3703		 */
   3704		status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
   3705		if (status)
   3706			goto exit;
   3707
   3708		/* before overriding VSI list map info. decrement ref_cnt of
   3709		 * previous VSI list
   3710		 */
   3711		v_list_itr->vsi_list_info->ref_cnt--;
   3712
   3713		/* now update to newly created list */
   3714		v_list_itr->fltr_info.fwd_id.vsi_list_id = vsi_list_id;
   3715		v_list_itr->vsi_list_info =
   3716			ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2,
   3717						vsi_list_id);
   3718		v_list_itr->vsi_count++;
   3719	}
   3720
   3721exit:
   3722	mutex_unlock(rule_lock);
   3723	return status;
   3724}
   3725
   3726/**
   3727 * ice_add_vlan - Add VLAN based filter rule
   3728 * @hw: pointer to the hardware structure
   3729 * @v_list: list of VLAN entries and forwarding information
   3730 */
   3731int ice_add_vlan(struct ice_hw *hw, struct list_head *v_list)
   3732{
   3733	struct ice_fltr_list_entry *v_list_itr;
   3734
   3735	if (!v_list || !hw)
   3736		return -EINVAL;
   3737
   3738	list_for_each_entry(v_list_itr, v_list, list_entry) {
   3739		if (v_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_VLAN)
   3740			return -EINVAL;
   3741		v_list_itr->fltr_info.flag = ICE_FLTR_TX;
   3742		v_list_itr->status = ice_add_vlan_internal(hw, v_list_itr);
   3743		if (v_list_itr->status)
   3744			return v_list_itr->status;
   3745	}
   3746	return 0;
   3747}
   3748
   3749/**
   3750 * ice_add_eth_mac - Add ethertype and MAC based filter rule
   3751 * @hw: pointer to the hardware structure
   3752 * @em_list: list of ether type MAC filter, MAC is optional
   3753 *
   3754 * This function requires the caller to populate the entries in
   3755 * the filter list with the necessary fields (including flags to
   3756 * indicate Tx or Rx rules).
   3757 */
   3758int ice_add_eth_mac(struct ice_hw *hw, struct list_head *em_list)
   3759{
   3760	struct ice_fltr_list_entry *em_list_itr;
   3761
   3762	if (!em_list || !hw)
   3763		return -EINVAL;
   3764
   3765	list_for_each_entry(em_list_itr, em_list, list_entry) {
   3766		enum ice_sw_lkup_type l_type =
   3767			em_list_itr->fltr_info.lkup_type;
   3768
   3769		if (l_type != ICE_SW_LKUP_ETHERTYPE_MAC &&
   3770		    l_type != ICE_SW_LKUP_ETHERTYPE)
   3771			return -EINVAL;
   3772
   3773		em_list_itr->status = ice_add_rule_internal(hw, l_type,
   3774							    em_list_itr);
   3775		if (em_list_itr->status)
   3776			return em_list_itr->status;
   3777	}
   3778	return 0;
   3779}
   3780
   3781/**
   3782 * ice_remove_eth_mac - Remove an ethertype (or MAC) based filter rule
   3783 * @hw: pointer to the hardware structure
   3784 * @em_list: list of ethertype or ethertype MAC entries
   3785 */
   3786int ice_remove_eth_mac(struct ice_hw *hw, struct list_head *em_list)
   3787{
   3788	struct ice_fltr_list_entry *em_list_itr, *tmp;
   3789
   3790	if (!em_list || !hw)
   3791		return -EINVAL;
   3792
   3793	list_for_each_entry_safe(em_list_itr, tmp, em_list, list_entry) {
   3794		enum ice_sw_lkup_type l_type =
   3795			em_list_itr->fltr_info.lkup_type;
   3796
   3797		if (l_type != ICE_SW_LKUP_ETHERTYPE_MAC &&
   3798		    l_type != ICE_SW_LKUP_ETHERTYPE)
   3799			return -EINVAL;
   3800
   3801		em_list_itr->status = ice_remove_rule_internal(hw, l_type,
   3802							       em_list_itr);
   3803		if (em_list_itr->status)
   3804			return em_list_itr->status;
   3805	}
   3806	return 0;
   3807}
   3808
   3809/**
   3810 * ice_rem_sw_rule_info
   3811 * @hw: pointer to the hardware structure
   3812 * @rule_head: pointer to the switch list structure that we want to delete
   3813 */
   3814static void
   3815ice_rem_sw_rule_info(struct ice_hw *hw, struct list_head *rule_head)
   3816{
   3817	if (!list_empty(rule_head)) {
   3818		struct ice_fltr_mgmt_list_entry *entry;
   3819		struct ice_fltr_mgmt_list_entry *tmp;
   3820
   3821		list_for_each_entry_safe(entry, tmp, rule_head, list_entry) {
   3822			list_del(&entry->list_entry);
   3823			devm_kfree(ice_hw_to_dev(hw), entry);
   3824		}
   3825	}
   3826}
   3827
   3828/**
   3829 * ice_rem_adv_rule_info
   3830 * @hw: pointer to the hardware structure
   3831 * @rule_head: pointer to the switch list structure that we want to delete
   3832 */
   3833static void
   3834ice_rem_adv_rule_info(struct ice_hw *hw, struct list_head *rule_head)
   3835{
   3836	struct ice_adv_fltr_mgmt_list_entry *tmp_entry;
   3837	struct ice_adv_fltr_mgmt_list_entry *lst_itr;
   3838
   3839	if (list_empty(rule_head))
   3840		return;
   3841
   3842	list_for_each_entry_safe(lst_itr, tmp_entry, rule_head, list_entry) {
   3843		list_del(&lst_itr->list_entry);
   3844		devm_kfree(ice_hw_to_dev(hw), lst_itr->lkups);
   3845		devm_kfree(ice_hw_to_dev(hw), lst_itr);
   3846	}
   3847}
   3848
   3849/**
   3850 * ice_cfg_dflt_vsi - change state of VSI to set/clear default
   3851 * @hw: pointer to the hardware structure
   3852 * @vsi_handle: VSI handle to set as default
   3853 * @set: true to add the above mentioned switch rule, false to remove it
   3854 * @direction: ICE_FLTR_RX or ICE_FLTR_TX
   3855 *
   3856 * add filter rule to set/unset given VSI as default VSI for the switch
   3857 * (represented by swid)
   3858 */
   3859int ice_cfg_dflt_vsi(struct ice_hw *hw, u16 vsi_handle, bool set, u8 direction)
   3860{
   3861	struct ice_sw_rule_lkup_rx_tx *s_rule;
   3862	struct ice_fltr_info f_info;
   3863	enum ice_adminq_opc opcode;
   3864	u16 s_rule_size;
   3865	u16 hw_vsi_id;
   3866	int status;
   3867
   3868	if (!ice_is_vsi_valid(hw, vsi_handle))
   3869		return -EINVAL;
   3870	hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
   3871
   3872	s_rule_size = set ? ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(s_rule) :
   3873			    ICE_SW_RULE_RX_TX_NO_HDR_SIZE(s_rule);
   3874
   3875	s_rule = devm_kzalloc(ice_hw_to_dev(hw), s_rule_size, GFP_KERNEL);
   3876	if (!s_rule)
   3877		return -ENOMEM;
   3878
   3879	memset(&f_info, 0, sizeof(f_info));
   3880
   3881	f_info.lkup_type = ICE_SW_LKUP_DFLT;
   3882	f_info.flag = direction;
   3883	f_info.fltr_act = ICE_FWD_TO_VSI;
   3884	f_info.fwd_id.hw_vsi_id = hw_vsi_id;
   3885
   3886	if (f_info.flag & ICE_FLTR_RX) {
   3887		f_info.src = hw->port_info->lport;
   3888		f_info.src_id = ICE_SRC_ID_LPORT;
   3889		if (!set)
   3890			f_info.fltr_rule_id =
   3891				hw->port_info->dflt_rx_vsi_rule_id;
   3892	} else if (f_info.flag & ICE_FLTR_TX) {
   3893		f_info.src_id = ICE_SRC_ID_VSI;
   3894		f_info.src = hw_vsi_id;
   3895		if (!set)
   3896			f_info.fltr_rule_id =
   3897				hw->port_info->dflt_tx_vsi_rule_id;
   3898	}
   3899
   3900	if (set)
   3901		opcode = ice_aqc_opc_add_sw_rules;
   3902	else
   3903		opcode = ice_aqc_opc_remove_sw_rules;
   3904
   3905	ice_fill_sw_rule(hw, &f_info, s_rule, opcode);
   3906
   3907	status = ice_aq_sw_rules(hw, s_rule, s_rule_size, 1, opcode, NULL);
   3908	if (status || !(f_info.flag & ICE_FLTR_TX_RX))
   3909		goto out;
   3910	if (set) {
   3911		u16 index = le16_to_cpu(s_rule->index);
   3912
   3913		if (f_info.flag & ICE_FLTR_TX) {
   3914			hw->port_info->dflt_tx_vsi_num = hw_vsi_id;
   3915			hw->port_info->dflt_tx_vsi_rule_id = index;
   3916		} else if (f_info.flag & ICE_FLTR_RX) {
   3917			hw->port_info->dflt_rx_vsi_num = hw_vsi_id;
   3918			hw->port_info->dflt_rx_vsi_rule_id = index;
   3919		}
   3920	} else {
   3921		if (f_info.flag & ICE_FLTR_TX) {
   3922			hw->port_info->dflt_tx_vsi_num = ICE_DFLT_VSI_INVAL;
   3923			hw->port_info->dflt_tx_vsi_rule_id = ICE_INVAL_ACT;
   3924		} else if (f_info.flag & ICE_FLTR_RX) {
   3925			hw->port_info->dflt_rx_vsi_num = ICE_DFLT_VSI_INVAL;
   3926			hw->port_info->dflt_rx_vsi_rule_id = ICE_INVAL_ACT;
   3927		}
   3928	}
   3929
   3930out:
   3931	devm_kfree(ice_hw_to_dev(hw), s_rule);
   3932	return status;
   3933}
   3934
   3935/**
   3936 * ice_find_ucast_rule_entry - Search for a unicast MAC filter rule entry
   3937 * @hw: pointer to the hardware structure
   3938 * @recp_id: lookup type for which the specified rule needs to be searched
   3939 * @f_info: rule information
   3940 *
   3941 * Helper function to search for a unicast rule entry - this is to be used
   3942 * to remove unicast MAC filter that is not shared with other VSIs on the
   3943 * PF switch.
   3944 *
   3945 * Returns pointer to entry storing the rule if found
   3946 */
   3947static struct ice_fltr_mgmt_list_entry *
   3948ice_find_ucast_rule_entry(struct ice_hw *hw, u8 recp_id,
   3949			  struct ice_fltr_info *f_info)
   3950{
   3951	struct ice_switch_info *sw = hw->switch_info;
   3952	struct ice_fltr_mgmt_list_entry *list_itr;
   3953	struct list_head *list_head;
   3954
   3955	list_head = &sw->recp_list[recp_id].filt_rules;
   3956	list_for_each_entry(list_itr, list_head, list_entry) {
   3957		if (!memcmp(&f_info->l_data, &list_itr->fltr_info.l_data,
   3958			    sizeof(f_info->l_data)) &&
   3959		    f_info->fwd_id.hw_vsi_id ==
   3960		    list_itr->fltr_info.fwd_id.hw_vsi_id &&
   3961		    f_info->flag == list_itr->fltr_info.flag)
   3962			return list_itr;
   3963	}
   3964	return NULL;
   3965}
   3966
   3967/**
   3968 * ice_remove_mac - remove a MAC address based filter rule
   3969 * @hw: pointer to the hardware structure
   3970 * @m_list: list of MAC addresses and forwarding information
   3971 *
   3972 * This function removes either a MAC filter rule or a specific VSI from a
   3973 * VSI list for a multicast MAC address.
   3974 *
   3975 * Returns -ENOENT if a given entry was not added by ice_add_mac. Caller should
   3976 * be aware that this call will only work if all the entries passed into m_list
   3977 * were added previously. It will not attempt to do a partial remove of entries
   3978 * that were found.
   3979 */
   3980int ice_remove_mac(struct ice_hw *hw, struct list_head *m_list)
   3981{
   3982	struct ice_fltr_list_entry *list_itr, *tmp;
   3983	struct mutex *rule_lock; /* Lock to protect filter rule list */
   3984
   3985	if (!m_list)
   3986		return -EINVAL;
   3987
   3988	rule_lock = &hw->switch_info->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock;
   3989	list_for_each_entry_safe(list_itr, tmp, m_list, list_entry) {
   3990		enum ice_sw_lkup_type l_type = list_itr->fltr_info.lkup_type;
   3991		u8 *add = &list_itr->fltr_info.l_data.mac.mac_addr[0];
   3992		u16 vsi_handle;
   3993
   3994		if (l_type != ICE_SW_LKUP_MAC)
   3995			return -EINVAL;
   3996
   3997		vsi_handle = list_itr->fltr_info.vsi_handle;
   3998		if (!ice_is_vsi_valid(hw, vsi_handle))
   3999			return -EINVAL;
   4000
   4001		list_itr->fltr_info.fwd_id.hw_vsi_id =
   4002					ice_get_hw_vsi_num(hw, vsi_handle);
   4003		if (is_unicast_ether_addr(add) && !hw->ucast_shared) {
   4004			/* Don't remove the unicast address that belongs to
   4005			 * another VSI on the switch, since it is not being
   4006			 * shared...
   4007			 */
   4008			mutex_lock(rule_lock);
   4009			if (!ice_find_ucast_rule_entry(hw, ICE_SW_LKUP_MAC,
   4010						       &list_itr->fltr_info)) {
   4011				mutex_unlock(rule_lock);
   4012				return -ENOENT;
   4013			}
   4014			mutex_unlock(rule_lock);
   4015		}
   4016		list_itr->status = ice_remove_rule_internal(hw,
   4017							    ICE_SW_LKUP_MAC,
   4018							    list_itr);
   4019		if (list_itr->status)
   4020			return list_itr->status;
   4021	}
   4022	return 0;
   4023}
   4024
   4025/**
   4026 * ice_remove_vlan - Remove VLAN based filter rule
   4027 * @hw: pointer to the hardware structure
   4028 * @v_list: list of VLAN entries and forwarding information
   4029 */
   4030int ice_remove_vlan(struct ice_hw *hw, struct list_head *v_list)
   4031{
   4032	struct ice_fltr_list_entry *v_list_itr, *tmp;
   4033
   4034	if (!v_list || !hw)
   4035		return -EINVAL;
   4036
   4037	list_for_each_entry_safe(v_list_itr, tmp, v_list, list_entry) {
   4038		enum ice_sw_lkup_type l_type = v_list_itr->fltr_info.lkup_type;
   4039
   4040		if (l_type != ICE_SW_LKUP_VLAN)
   4041			return -EINVAL;
   4042		v_list_itr->status = ice_remove_rule_internal(hw,
   4043							      ICE_SW_LKUP_VLAN,
   4044							      v_list_itr);
   4045		if (v_list_itr->status)
   4046			return v_list_itr->status;
   4047	}
   4048	return 0;
   4049}
   4050
   4051/**
   4052 * ice_vsi_uses_fltr - Determine if given VSI uses specified filter
   4053 * @fm_entry: filter entry to inspect
   4054 * @vsi_handle: VSI handle to compare with filter info
   4055 */
   4056static bool
   4057ice_vsi_uses_fltr(struct ice_fltr_mgmt_list_entry *fm_entry, u16 vsi_handle)
   4058{
   4059	return ((fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI &&
   4060		 fm_entry->fltr_info.vsi_handle == vsi_handle) ||
   4061		(fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI_LIST &&
   4062		 fm_entry->vsi_list_info &&
   4063		 (test_bit(vsi_handle, fm_entry->vsi_list_info->vsi_map))));
   4064}
   4065
   4066/**
   4067 * ice_add_entry_to_vsi_fltr_list - Add copy of fltr_list_entry to remove list
   4068 * @hw: pointer to the hardware structure
   4069 * @vsi_handle: VSI handle to remove filters from
   4070 * @vsi_list_head: pointer to the list to add entry to
   4071 * @fi: pointer to fltr_info of filter entry to copy & add
   4072 *
   4073 * Helper function, used when creating a list of filters to remove from
   4074 * a specific VSI. The entry added to vsi_list_head is a COPY of the
   4075 * original filter entry, with the exception of fltr_info.fltr_act and
   4076 * fltr_info.fwd_id fields. These are set such that later logic can
   4077 * extract which VSI to remove the fltr from, and pass on that information.
   4078 */
   4079static int
   4080ice_add_entry_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle,
   4081			       struct list_head *vsi_list_head,
   4082			       struct ice_fltr_info *fi)
   4083{
   4084	struct ice_fltr_list_entry *tmp;
   4085
   4086	/* this memory is freed up in the caller function
   4087	 * once filters for this VSI are removed
   4088	 */
   4089	tmp = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*tmp), GFP_KERNEL);
   4090	if (!tmp)
   4091		return -ENOMEM;
   4092
   4093	tmp->fltr_info = *fi;
   4094
   4095	/* Overwrite these fields to indicate which VSI to remove filter from,
   4096	 * so find and remove logic can extract the information from the
   4097	 * list entries. Note that original entries will still have proper
   4098	 * values.
   4099	 */
   4100	tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI;
   4101	tmp->fltr_info.vsi_handle = vsi_handle;
   4102	tmp->fltr_info.fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
   4103
   4104	list_add(&tmp->list_entry, vsi_list_head);
   4105
   4106	return 0;
   4107}
   4108
   4109/**
   4110 * ice_add_to_vsi_fltr_list - Add VSI filters to the list
   4111 * @hw: pointer to the hardware structure
   4112 * @vsi_handle: VSI handle to remove filters from
   4113 * @lkup_list_head: pointer to the list that has certain lookup type filters
   4114 * @vsi_list_head: pointer to the list pertaining to VSI with vsi_handle
   4115 *
   4116 * Locates all filters in lkup_list_head that are used by the given VSI,
   4117 * and adds COPIES of those entries to vsi_list_head (intended to be used
   4118 * to remove the listed filters).
   4119 * Note that this means all entries in vsi_list_head must be explicitly
   4120 * deallocated by the caller when done with list.
   4121 */
   4122static int
   4123ice_add_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle,
   4124			 struct list_head *lkup_list_head,
   4125			 struct list_head *vsi_list_head)
   4126{
   4127	struct ice_fltr_mgmt_list_entry *fm_entry;
   4128	int status = 0;
   4129
   4130	/* check to make sure VSI ID is valid and within boundary */
   4131	if (!ice_is_vsi_valid(hw, vsi_handle))
   4132		return -EINVAL;
   4133
   4134	list_for_each_entry(fm_entry, lkup_list_head, list_entry) {
   4135		if (!ice_vsi_uses_fltr(fm_entry, vsi_handle))
   4136			continue;
   4137
   4138		status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle,
   4139							vsi_list_head,
   4140							&fm_entry->fltr_info);
   4141		if (status)
   4142			return status;
   4143	}
   4144	return status;
   4145}
   4146
   4147/**
   4148 * ice_determine_promisc_mask
   4149 * @fi: filter info to parse
   4150 *
   4151 * Helper function to determine which ICE_PROMISC_ mask corresponds
   4152 * to given filter into.
   4153 */
   4154static u8 ice_determine_promisc_mask(struct ice_fltr_info *fi)
   4155{
   4156	u16 vid = fi->l_data.mac_vlan.vlan_id;
   4157	u8 *macaddr = fi->l_data.mac.mac_addr;
   4158	bool is_tx_fltr = false;
   4159	u8 promisc_mask = 0;
   4160
   4161	if (fi->flag == ICE_FLTR_TX)
   4162		is_tx_fltr = true;
   4163
   4164	if (is_broadcast_ether_addr(macaddr))
   4165		promisc_mask |= is_tx_fltr ?
   4166			ICE_PROMISC_BCAST_TX : ICE_PROMISC_BCAST_RX;
   4167	else if (is_multicast_ether_addr(macaddr))
   4168		promisc_mask |= is_tx_fltr ?
   4169			ICE_PROMISC_MCAST_TX : ICE_PROMISC_MCAST_RX;
   4170	else if (is_unicast_ether_addr(macaddr))
   4171		promisc_mask |= is_tx_fltr ?
   4172			ICE_PROMISC_UCAST_TX : ICE_PROMISC_UCAST_RX;
   4173	if (vid)
   4174		promisc_mask |= is_tx_fltr ?
   4175			ICE_PROMISC_VLAN_TX : ICE_PROMISC_VLAN_RX;
   4176
   4177	return promisc_mask;
   4178}
   4179
   4180/**
   4181 * ice_remove_promisc - Remove promisc based filter rules
   4182 * @hw: pointer to the hardware structure
   4183 * @recp_id: recipe ID for which the rule needs to removed
   4184 * @v_list: list of promisc entries
   4185 */
   4186static int
   4187ice_remove_promisc(struct ice_hw *hw, u8 recp_id, struct list_head *v_list)
   4188{
   4189	struct ice_fltr_list_entry *v_list_itr, *tmp;
   4190
   4191	list_for_each_entry_safe(v_list_itr, tmp, v_list, list_entry) {
   4192		v_list_itr->status =
   4193			ice_remove_rule_internal(hw, recp_id, v_list_itr);
   4194		if (v_list_itr->status)
   4195			return v_list_itr->status;
   4196	}
   4197	return 0;
   4198}
   4199
   4200/**
   4201 * ice_clear_vsi_promisc - clear specified promiscuous mode(s) for given VSI
   4202 * @hw: pointer to the hardware structure
   4203 * @vsi_handle: VSI handle to clear mode
   4204 * @promisc_mask: mask of promiscuous config bits to clear
   4205 * @vid: VLAN ID to clear VLAN promiscuous
   4206 */
   4207int
   4208ice_clear_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
   4209		      u16 vid)
   4210{
   4211	struct ice_switch_info *sw = hw->switch_info;
   4212	struct ice_fltr_list_entry *fm_entry, *tmp;
   4213	struct list_head remove_list_head;
   4214	struct ice_fltr_mgmt_list_entry *itr;
   4215	struct list_head *rule_head;
   4216	struct mutex *rule_lock;	/* Lock to protect filter rule list */
   4217	int status = 0;
   4218	u8 recipe_id;
   4219
   4220	if (!ice_is_vsi_valid(hw, vsi_handle))
   4221		return -EINVAL;
   4222
   4223	if (promisc_mask & (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX))
   4224		recipe_id = ICE_SW_LKUP_PROMISC_VLAN;
   4225	else
   4226		recipe_id = ICE_SW_LKUP_PROMISC;
   4227
   4228	rule_head = &sw->recp_list[recipe_id].filt_rules;
   4229	rule_lock = &sw->recp_list[recipe_id].filt_rule_lock;
   4230
   4231	INIT_LIST_HEAD(&remove_list_head);
   4232
   4233	mutex_lock(rule_lock);
   4234	list_for_each_entry(itr, rule_head, list_entry) {
   4235		struct ice_fltr_info *fltr_info;
   4236		u8 fltr_promisc_mask = 0;
   4237
   4238		if (!ice_vsi_uses_fltr(itr, vsi_handle))
   4239			continue;
   4240		fltr_info = &itr->fltr_info;
   4241
   4242		if (recipe_id == ICE_SW_LKUP_PROMISC_VLAN &&
   4243		    vid != fltr_info->l_data.mac_vlan.vlan_id)
   4244			continue;
   4245
   4246		fltr_promisc_mask |= ice_determine_promisc_mask(fltr_info);
   4247
   4248		/* Skip if filter is not completely specified by given mask */
   4249		if (fltr_promisc_mask & ~promisc_mask)
   4250			continue;
   4251
   4252		status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle,
   4253							&remove_list_head,
   4254							fltr_info);
   4255		if (status) {
   4256			mutex_unlock(rule_lock);
   4257			goto free_fltr_list;
   4258		}
   4259	}
   4260	mutex_unlock(rule_lock);
   4261
   4262	status = ice_remove_promisc(hw, recipe_id, &remove_list_head);
   4263
   4264free_fltr_list:
   4265	list_for_each_entry_safe(fm_entry, tmp, &remove_list_head, list_entry) {
   4266		list_del(&fm_entry->list_entry);
   4267		devm_kfree(ice_hw_to_dev(hw), fm_entry);
   4268	}
   4269
   4270	return status;
   4271}
   4272
   4273/**
   4274 * ice_set_vsi_promisc - set given VSI to given promiscuous mode(s)
   4275 * @hw: pointer to the hardware structure
   4276 * @vsi_handle: VSI handle to configure
   4277 * @promisc_mask: mask of promiscuous config bits
   4278 * @vid: VLAN ID to set VLAN promiscuous
   4279 */
   4280int
   4281ice_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, u16 vid)
   4282{
   4283	enum { UCAST_FLTR = 1, MCAST_FLTR, BCAST_FLTR };
   4284	struct ice_fltr_list_entry f_list_entry;
   4285	struct ice_fltr_info new_fltr;
   4286	bool is_tx_fltr;
   4287	int status = 0;
   4288	u16 hw_vsi_id;
   4289	int pkt_type;
   4290	u8 recipe_id;
   4291
   4292	if (!ice_is_vsi_valid(hw, vsi_handle))
   4293		return -EINVAL;
   4294	hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
   4295
   4296	memset(&new_fltr, 0, sizeof(new_fltr));
   4297
   4298	if (promisc_mask & (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX)) {
   4299		new_fltr.lkup_type = ICE_SW_LKUP_PROMISC_VLAN;
   4300		new_fltr.l_data.mac_vlan.vlan_id = vid;
   4301		recipe_id = ICE_SW_LKUP_PROMISC_VLAN;
   4302	} else {
   4303		new_fltr.lkup_type = ICE_SW_LKUP_PROMISC;
   4304		recipe_id = ICE_SW_LKUP_PROMISC;
   4305	}
   4306
   4307	/* Separate filters must be set for each direction/packet type
   4308	 * combination, so we will loop over the mask value, store the
   4309	 * individual type, and clear it out in the input mask as it
   4310	 * is found.
   4311	 */
   4312	while (promisc_mask) {
   4313		u8 *mac_addr;
   4314
   4315		pkt_type = 0;
   4316		is_tx_fltr = false;
   4317
   4318		if (promisc_mask & ICE_PROMISC_UCAST_RX) {
   4319			promisc_mask &= ~ICE_PROMISC_UCAST_RX;
   4320			pkt_type = UCAST_FLTR;
   4321		} else if (promisc_mask & ICE_PROMISC_UCAST_TX) {
   4322			promisc_mask &= ~ICE_PROMISC_UCAST_TX;
   4323			pkt_type = UCAST_FLTR;
   4324			is_tx_fltr = true;
   4325		} else if (promisc_mask & ICE_PROMISC_MCAST_RX) {
   4326			promisc_mask &= ~ICE_PROMISC_MCAST_RX;
   4327			pkt_type = MCAST_FLTR;
   4328		} else if (promisc_mask & ICE_PROMISC_MCAST_TX) {
   4329			promisc_mask &= ~ICE_PROMISC_MCAST_TX;
   4330			pkt_type = MCAST_FLTR;
   4331			is_tx_fltr = true;
   4332		} else if (promisc_mask & ICE_PROMISC_BCAST_RX) {
   4333			promisc_mask &= ~ICE_PROMISC_BCAST_RX;
   4334			pkt_type = BCAST_FLTR;
   4335		} else if (promisc_mask & ICE_PROMISC_BCAST_TX) {
   4336			promisc_mask &= ~ICE_PROMISC_BCAST_TX;
   4337			pkt_type = BCAST_FLTR;
   4338			is_tx_fltr = true;
   4339		}
   4340
   4341		/* Check for VLAN promiscuous flag */
   4342		if (promisc_mask & ICE_PROMISC_VLAN_RX) {
   4343			promisc_mask &= ~ICE_PROMISC_VLAN_RX;
   4344		} else if (promisc_mask & ICE_PROMISC_VLAN_TX) {
   4345			promisc_mask &= ~ICE_PROMISC_VLAN_TX;
   4346			is_tx_fltr = true;
   4347		}
   4348
   4349		/* Set filter DA based on packet type */
   4350		mac_addr = new_fltr.l_data.mac.mac_addr;
   4351		if (pkt_type == BCAST_FLTR) {
   4352			eth_broadcast_addr(mac_addr);
   4353		} else if (pkt_type == MCAST_FLTR ||
   4354			   pkt_type == UCAST_FLTR) {
   4355			/* Use the dummy ether header DA */
   4356			ether_addr_copy(mac_addr, dummy_eth_header);
   4357			if (pkt_type == MCAST_FLTR)
   4358				mac_addr[0] |= 0x1;	/* Set multicast bit */
   4359		}
   4360
   4361		/* Need to reset this to zero for all iterations */
   4362		new_fltr.flag = 0;
   4363		if (is_tx_fltr) {
   4364			new_fltr.flag |= ICE_FLTR_TX;
   4365			new_fltr.src = hw_vsi_id;
   4366		} else {
   4367			new_fltr.flag |= ICE_FLTR_RX;
   4368			new_fltr.src = hw->port_info->lport;
   4369		}
   4370
   4371		new_fltr.fltr_act = ICE_FWD_TO_VSI;
   4372		new_fltr.vsi_handle = vsi_handle;
   4373		new_fltr.fwd_id.hw_vsi_id = hw_vsi_id;
   4374		f_list_entry.fltr_info = new_fltr;
   4375
   4376		status = ice_add_rule_internal(hw, recipe_id, &f_list_entry);
   4377		if (status)
   4378			goto set_promisc_exit;
   4379	}
   4380
   4381set_promisc_exit:
   4382	return status;
   4383}
   4384
   4385/**
   4386 * ice_set_vlan_vsi_promisc
   4387 * @hw: pointer to the hardware structure
   4388 * @vsi_handle: VSI handle to configure
   4389 * @promisc_mask: mask of promiscuous config bits
   4390 * @rm_vlan_promisc: Clear VLANs VSI promisc mode
   4391 *
   4392 * Configure VSI with all associated VLANs to given promiscuous mode(s)
   4393 */
   4394int
   4395ice_set_vlan_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
   4396			 bool rm_vlan_promisc)
   4397{
   4398	struct ice_switch_info *sw = hw->switch_info;
   4399	struct ice_fltr_list_entry *list_itr, *tmp;
   4400	struct list_head vsi_list_head;
   4401	struct list_head *vlan_head;
   4402	struct mutex *vlan_lock; /* Lock to protect filter rule list */
   4403	u16 vlan_id;
   4404	int status;
   4405
   4406	INIT_LIST_HEAD(&vsi_list_head);
   4407	vlan_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock;
   4408	vlan_head = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rules;
   4409	mutex_lock(vlan_lock);
   4410	status = ice_add_to_vsi_fltr_list(hw, vsi_handle, vlan_head,
   4411					  &vsi_list_head);
   4412	mutex_unlock(vlan_lock);
   4413	if (status)
   4414		goto free_fltr_list;
   4415
   4416	list_for_each_entry(list_itr, &vsi_list_head, list_entry) {
   4417		vlan_id = list_itr->fltr_info.l_data.vlan.vlan_id;
   4418		if (rm_vlan_promisc)
   4419			status = ice_clear_vsi_promisc(hw, vsi_handle,
   4420						       promisc_mask, vlan_id);
   4421		else
   4422			status = ice_set_vsi_promisc(hw, vsi_handle,
   4423						     promisc_mask, vlan_id);
   4424		if (status)
   4425			break;
   4426	}
   4427
   4428free_fltr_list:
   4429	list_for_each_entry_safe(list_itr, tmp, &vsi_list_head, list_entry) {
   4430		list_del(&list_itr->list_entry);
   4431		devm_kfree(ice_hw_to_dev(hw), list_itr);
   4432	}
   4433	return status;
   4434}
   4435
   4436/**
   4437 * ice_remove_vsi_lkup_fltr - Remove lookup type filters for a VSI
   4438 * @hw: pointer to the hardware structure
   4439 * @vsi_handle: VSI handle to remove filters from
   4440 * @lkup: switch rule filter lookup type
   4441 */
   4442static void
   4443ice_remove_vsi_lkup_fltr(struct ice_hw *hw, u16 vsi_handle,
   4444			 enum ice_sw_lkup_type lkup)
   4445{
   4446	struct ice_switch_info *sw = hw->switch_info;
   4447	struct ice_fltr_list_entry *fm_entry;
   4448	struct list_head remove_list_head;
   4449	struct list_head *rule_head;
   4450	struct ice_fltr_list_entry *tmp;
   4451	struct mutex *rule_lock;	/* Lock to protect filter rule list */
   4452	int status;
   4453
   4454	INIT_LIST_HEAD(&remove_list_head);
   4455	rule_lock = &sw->recp_list[lkup].filt_rule_lock;
   4456	rule_head = &sw->recp_list[lkup].filt_rules;
   4457	mutex_lock(rule_lock);
   4458	status = ice_add_to_vsi_fltr_list(hw, vsi_handle, rule_head,
   4459					  &remove_list_head);
   4460	mutex_unlock(rule_lock);
   4461	if (status)
   4462		goto free_fltr_list;
   4463
   4464	switch (lkup) {
   4465	case ICE_SW_LKUP_MAC:
   4466		ice_remove_mac(hw, &remove_list_head);
   4467		break;
   4468	case ICE_SW_LKUP_VLAN:
   4469		ice_remove_vlan(hw, &remove_list_head);
   4470		break;
   4471	case ICE_SW_LKUP_PROMISC:
   4472	case ICE_SW_LKUP_PROMISC_VLAN:
   4473		ice_remove_promisc(hw, lkup, &remove_list_head);
   4474		break;
   4475	case ICE_SW_LKUP_MAC_VLAN:
   4476	case ICE_SW_LKUP_ETHERTYPE:
   4477	case ICE_SW_LKUP_ETHERTYPE_MAC:
   4478	case ICE_SW_LKUP_DFLT:
   4479	case ICE_SW_LKUP_LAST:
   4480	default:
   4481		ice_debug(hw, ICE_DBG_SW, "Unsupported lookup type %d\n", lkup);
   4482		break;
   4483	}
   4484
   4485free_fltr_list:
   4486	list_for_each_entry_safe(fm_entry, tmp, &remove_list_head, list_entry) {
   4487		list_del(&fm_entry->list_entry);
   4488		devm_kfree(ice_hw_to_dev(hw), fm_entry);
   4489	}
   4490}
   4491
   4492/**
   4493 * ice_remove_vsi_fltr - Remove all filters for a VSI
   4494 * @hw: pointer to the hardware structure
   4495 * @vsi_handle: VSI handle to remove filters from
   4496 */
   4497void ice_remove_vsi_fltr(struct ice_hw *hw, u16 vsi_handle)
   4498{
   4499	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_MAC);
   4500	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_MAC_VLAN);
   4501	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_PROMISC);
   4502	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_VLAN);
   4503	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_DFLT);
   4504	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_ETHERTYPE);
   4505	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_ETHERTYPE_MAC);
   4506	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_PROMISC_VLAN);
   4507}
   4508
   4509/**
   4510 * ice_alloc_res_cntr - allocating resource counter
   4511 * @hw: pointer to the hardware structure
   4512 * @type: type of resource
   4513 * @alloc_shared: if set it is shared else dedicated
   4514 * @num_items: number of entries requested for FD resource type
   4515 * @counter_id: counter index returned by AQ call
   4516 */
   4517int
   4518ice_alloc_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items,
   4519		   u16 *counter_id)
   4520{
   4521	struct ice_aqc_alloc_free_res_elem *buf;
   4522	u16 buf_len;
   4523	int status;
   4524
   4525	/* Allocate resource */
   4526	buf_len = struct_size(buf, elem, 1);
   4527	buf = kzalloc(buf_len, GFP_KERNEL);
   4528	if (!buf)
   4529		return -ENOMEM;
   4530
   4531	buf->num_elems = cpu_to_le16(num_items);
   4532	buf->res_type = cpu_to_le16(((type << ICE_AQC_RES_TYPE_S) &
   4533				      ICE_AQC_RES_TYPE_M) | alloc_shared);
   4534
   4535	status = ice_aq_alloc_free_res(hw, 1, buf, buf_len,
   4536				       ice_aqc_opc_alloc_res, NULL);
   4537	if (status)
   4538		goto exit;
   4539
   4540	*counter_id = le16_to_cpu(buf->elem[0].e.sw_resp);
   4541
   4542exit:
   4543	kfree(buf);
   4544	return status;
   4545}
   4546
   4547/**
   4548 * ice_free_res_cntr - free resource counter
   4549 * @hw: pointer to the hardware structure
   4550 * @type: type of resource
   4551 * @alloc_shared: if set it is shared else dedicated
   4552 * @num_items: number of entries to be freed for FD resource type
   4553 * @counter_id: counter ID resource which needs to be freed
   4554 */
   4555int
   4556ice_free_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items,
   4557		  u16 counter_id)
   4558{
   4559	struct ice_aqc_alloc_free_res_elem *buf;
   4560	u16 buf_len;
   4561	int status;
   4562
   4563	/* Free resource */
   4564	buf_len = struct_size(buf, elem, 1);
   4565	buf = kzalloc(buf_len, GFP_KERNEL);
   4566	if (!buf)
   4567		return -ENOMEM;
   4568
   4569	buf->num_elems = cpu_to_le16(num_items);
   4570	buf->res_type = cpu_to_le16(((type << ICE_AQC_RES_TYPE_S) &
   4571				      ICE_AQC_RES_TYPE_M) | alloc_shared);
   4572	buf->elem[0].e.sw_resp = cpu_to_le16(counter_id);
   4573
   4574	status = ice_aq_alloc_free_res(hw, 1, buf, buf_len,
   4575				       ice_aqc_opc_free_res, NULL);
   4576	if (status)
   4577		ice_debug(hw, ICE_DBG_SW, "counter resource could not be freed\n");
   4578
   4579	kfree(buf);
   4580	return status;
   4581}
   4582
   4583/* This is mapping table entry that maps every word within a given protocol
   4584 * structure to the real byte offset as per the specification of that
   4585 * protocol header.
   4586 * for example dst address is 3 words in ethertype header and corresponding
   4587 * bytes are 0, 2, 3 in the actual packet header and src address is at 4, 6, 8
   4588 * IMPORTANT: Every structure part of "ice_prot_hdr" union should have a
   4589 * matching entry describing its field. This needs to be updated if new
   4590 * structure is added to that union.
   4591 */
   4592static const struct ice_prot_ext_tbl_entry ice_prot_ext[ICE_PROTOCOL_LAST] = {
   4593	{ ICE_MAC_OFOS,		{ 0, 2, 4, 6, 8, 10, 12 } },
   4594	{ ICE_MAC_IL,		{ 0, 2, 4, 6, 8, 10, 12 } },
   4595	{ ICE_ETYPE_OL,		{ 0 } },
   4596	{ ICE_ETYPE_IL,		{ 0 } },
   4597	{ ICE_VLAN_OFOS,	{ 2, 0 } },
   4598	{ ICE_IPV4_OFOS,	{ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18 } },
   4599	{ ICE_IPV4_IL,		{ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18 } },
   4600	{ ICE_IPV6_OFOS,	{ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24,
   4601				 26, 28, 30, 32, 34, 36, 38 } },
   4602	{ ICE_IPV6_IL,		{ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24,
   4603				 26, 28, 30, 32, 34, 36, 38 } },
   4604	{ ICE_TCP_IL,		{ 0, 2 } },
   4605	{ ICE_UDP_OF,		{ 0, 2 } },
   4606	{ ICE_UDP_ILOS,		{ 0, 2 } },
   4607	{ ICE_VXLAN,		{ 8, 10, 12, 14 } },
   4608	{ ICE_GENEVE,		{ 8, 10, 12, 14 } },
   4609	{ ICE_NVGRE,		{ 0, 2, 4, 6 } },
   4610	{ ICE_GTP,		{ 8, 10, 12, 14, 16, 18, 20, 22 } },
   4611	{ ICE_GTP_NO_PAY,	{ 8, 10, 12, 14 } },
   4612};
   4613
   4614static struct ice_protocol_entry ice_prot_id_tbl[ICE_PROTOCOL_LAST] = {
   4615	{ ICE_MAC_OFOS,		ICE_MAC_OFOS_HW },
   4616	{ ICE_MAC_IL,		ICE_MAC_IL_HW },
   4617	{ ICE_ETYPE_OL,		ICE_ETYPE_OL_HW },
   4618	{ ICE_ETYPE_IL,		ICE_ETYPE_IL_HW },
   4619	{ ICE_VLAN_OFOS,	ICE_VLAN_OL_HW },
   4620	{ ICE_IPV4_OFOS,	ICE_IPV4_OFOS_HW },
   4621	{ ICE_IPV4_IL,		ICE_IPV4_IL_HW },
   4622	{ ICE_IPV6_OFOS,	ICE_IPV6_OFOS_HW },
   4623	{ ICE_IPV6_IL,		ICE_IPV6_IL_HW },
   4624	{ ICE_TCP_IL,		ICE_TCP_IL_HW },
   4625	{ ICE_UDP_OF,		ICE_UDP_OF_HW },
   4626	{ ICE_UDP_ILOS,		ICE_UDP_ILOS_HW },
   4627	{ ICE_VXLAN,		ICE_UDP_OF_HW },
   4628	{ ICE_GENEVE,		ICE_UDP_OF_HW },
   4629	{ ICE_NVGRE,		ICE_GRE_OF_HW },
   4630	{ ICE_GTP,		ICE_UDP_OF_HW },
   4631	{ ICE_GTP_NO_PAY,	ICE_UDP_ILOS_HW },
   4632};
   4633
   4634/**
   4635 * ice_find_recp - find a recipe
   4636 * @hw: pointer to the hardware structure
   4637 * @lkup_exts: extension sequence to match
   4638 * @tun_type: type of recipe tunnel
   4639 *
   4640 * Returns index of matching recipe, or ICE_MAX_NUM_RECIPES if not found.
   4641 */
   4642static u16
   4643ice_find_recp(struct ice_hw *hw, struct ice_prot_lkup_ext *lkup_exts,
   4644	      enum ice_sw_tunnel_type tun_type)
   4645{
   4646	bool refresh_required = true;
   4647	struct ice_sw_recipe *recp;
   4648	u8 i;
   4649
   4650	/* Walk through existing recipes to find a match */
   4651	recp = hw->switch_info->recp_list;
   4652	for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
   4653		/* If recipe was not created for this ID, in SW bookkeeping,
   4654		 * check if FW has an entry for this recipe. If the FW has an
   4655		 * entry update it in our SW bookkeeping and continue with the
   4656		 * matching.
   4657		 */
   4658		if (!recp[i].recp_created)
   4659			if (ice_get_recp_frm_fw(hw,
   4660						hw->switch_info->recp_list, i,
   4661						&refresh_required))
   4662				continue;
   4663
   4664		/* Skip inverse action recipes */
   4665		if (recp[i].root_buf && recp[i].root_buf->content.act_ctrl &
   4666		    ICE_AQ_RECIPE_ACT_INV_ACT)
   4667			continue;
   4668
   4669		/* if number of words we are looking for match */
   4670		if (lkup_exts->n_val_words == recp[i].lkup_exts.n_val_words) {
   4671			struct ice_fv_word *ar = recp[i].lkup_exts.fv_words;
   4672			struct ice_fv_word *be = lkup_exts->fv_words;
   4673			u16 *cr = recp[i].lkup_exts.field_mask;
   4674			u16 *de = lkup_exts->field_mask;
   4675			bool found = true;
   4676			u8 pe, qr;
   4677
   4678			/* ar, cr, and qr are related to the recipe words, while
   4679			 * be, de, and pe are related to the lookup words
   4680			 */
   4681			for (pe = 0; pe < lkup_exts->n_val_words; pe++) {
   4682				for (qr = 0; qr < recp[i].lkup_exts.n_val_words;
   4683				     qr++) {
   4684					if (ar[qr].off == be[pe].off &&
   4685					    ar[qr].prot_id == be[pe].prot_id &&
   4686					    cr[qr] == de[pe])
   4687						/* Found the "pe"th word in the
   4688						 * given recipe
   4689						 */
   4690						break;
   4691				}
   4692				/* After walking through all the words in the
   4693				 * "i"th recipe if "p"th word was not found then
   4694				 * this recipe is not what we are looking for.
   4695				 * So break out from this loop and try the next
   4696				 * recipe
   4697				 */
   4698				if (qr >= recp[i].lkup_exts.n_val_words) {
   4699					found = false;
   4700					break;
   4701				}
   4702			}
   4703			/* If for "i"th recipe the found was never set to false
   4704			 * then it means we found our match
   4705			 * Also tun type of recipe needs to be checked
   4706			 */
   4707			if (found && recp[i].tun_type == tun_type)
   4708				return i; /* Return the recipe ID */
   4709		}
   4710	}
   4711	return ICE_MAX_NUM_RECIPES;
   4712}
   4713
   4714/**
   4715 * ice_change_proto_id_to_dvm - change proto id in prot_id_tbl
   4716 *
   4717 * As protocol id for outer vlan is different in dvm and svm, if dvm is
   4718 * supported protocol array record for outer vlan has to be modified to
   4719 * reflect the value proper for DVM.
   4720 */
   4721void ice_change_proto_id_to_dvm(void)
   4722{
   4723	u8 i;
   4724
   4725	for (i = 0; i < ARRAY_SIZE(ice_prot_id_tbl); i++)
   4726		if (ice_prot_id_tbl[i].type == ICE_VLAN_OFOS &&
   4727		    ice_prot_id_tbl[i].protocol_id != ICE_VLAN_OF_HW)
   4728			ice_prot_id_tbl[i].protocol_id = ICE_VLAN_OF_HW;
   4729}
   4730
   4731/**
   4732 * ice_prot_type_to_id - get protocol ID from protocol type
   4733 * @type: protocol type
   4734 * @id: pointer to variable that will receive the ID
   4735 *
   4736 * Returns true if found, false otherwise
   4737 */
   4738static bool ice_prot_type_to_id(enum ice_protocol_type type, u8 *id)
   4739{
   4740	u8 i;
   4741
   4742	for (i = 0; i < ARRAY_SIZE(ice_prot_id_tbl); i++)
   4743		if (ice_prot_id_tbl[i].type == type) {
   4744			*id = ice_prot_id_tbl[i].protocol_id;
   4745			return true;
   4746		}
   4747	return false;
   4748}
   4749
   4750/**
   4751 * ice_fill_valid_words - count valid words
   4752 * @rule: advanced rule with lookup information
   4753 * @lkup_exts: byte offset extractions of the words that are valid
   4754 *
   4755 * calculate valid words in a lookup rule using mask value
   4756 */
   4757static u8
   4758ice_fill_valid_words(struct ice_adv_lkup_elem *rule,
   4759		     struct ice_prot_lkup_ext *lkup_exts)
   4760{
   4761	u8 j, word, prot_id, ret_val;
   4762
   4763	if (!ice_prot_type_to_id(rule->type, &prot_id))
   4764		return 0;
   4765
   4766	word = lkup_exts->n_val_words;
   4767
   4768	for (j = 0; j < sizeof(rule->m_u) / sizeof(u16); j++)
   4769		if (((u16 *)&rule->m_u)[j] &&
   4770		    rule->type < ARRAY_SIZE(ice_prot_ext)) {
   4771			/* No more space to accommodate */
   4772			if (word >= ICE_MAX_CHAIN_WORDS)
   4773				return 0;
   4774			lkup_exts->fv_words[word].off =
   4775				ice_prot_ext[rule->type].offs[j];
   4776			lkup_exts->fv_words[word].prot_id =
   4777				ice_prot_id_tbl[rule->type].protocol_id;
   4778			lkup_exts->field_mask[word] =
   4779				be16_to_cpu(((__force __be16 *)&rule->m_u)[j]);
   4780			word++;
   4781		}
   4782
   4783	ret_val = word - lkup_exts->n_val_words;
   4784	lkup_exts->n_val_words = word;
   4785
   4786	return ret_val;
   4787}
   4788
   4789/**
   4790 * ice_create_first_fit_recp_def - Create a recipe grouping
   4791 * @hw: pointer to the hardware structure
   4792 * @lkup_exts: an array of protocol header extractions
   4793 * @rg_list: pointer to a list that stores new recipe groups
   4794 * @recp_cnt: pointer to a variable that stores returned number of recipe groups
   4795 *
   4796 * Using first fit algorithm, take all the words that are still not done
   4797 * and start grouping them in 4-word groups. Each group makes up one
   4798 * recipe.
   4799 */
   4800static int
   4801ice_create_first_fit_recp_def(struct ice_hw *hw,
   4802			      struct ice_prot_lkup_ext *lkup_exts,
   4803			      struct list_head *rg_list,
   4804			      u8 *recp_cnt)
   4805{
   4806	struct ice_pref_recipe_group *grp = NULL;
   4807	u8 j;
   4808
   4809	*recp_cnt = 0;
   4810
   4811	/* Walk through every word in the rule to check if it is not done. If so
   4812	 * then this word needs to be part of a new recipe.
   4813	 */
   4814	for (j = 0; j < lkup_exts->n_val_words; j++)
   4815		if (!test_bit(j, lkup_exts->done)) {
   4816			if (!grp ||
   4817			    grp->n_val_pairs == ICE_NUM_WORDS_RECIPE) {
   4818				struct ice_recp_grp_entry *entry;
   4819
   4820				entry = devm_kzalloc(ice_hw_to_dev(hw),
   4821						     sizeof(*entry),
   4822						     GFP_KERNEL);
   4823				if (!entry)
   4824					return -ENOMEM;
   4825				list_add(&entry->l_entry, rg_list);
   4826				grp = &entry->r_group;
   4827				(*recp_cnt)++;
   4828			}
   4829
   4830			grp->pairs[grp->n_val_pairs].prot_id =
   4831				lkup_exts->fv_words[j].prot_id;
   4832			grp->pairs[grp->n_val_pairs].off =
   4833				lkup_exts->fv_words[j].off;
   4834			grp->mask[grp->n_val_pairs] = lkup_exts->field_mask[j];
   4835			grp->n_val_pairs++;
   4836		}
   4837
   4838	return 0;
   4839}
   4840
   4841/**
   4842 * ice_fill_fv_word_index - fill in the field vector indices for a recipe group
   4843 * @hw: pointer to the hardware structure
   4844 * @fv_list: field vector with the extraction sequence information
   4845 * @rg_list: recipe groupings with protocol-offset pairs
   4846 *
   4847 * Helper function to fill in the field vector indices for protocol-offset
   4848 * pairs. These indexes are then ultimately programmed into a recipe.
   4849 */
   4850static int
   4851ice_fill_fv_word_index(struct ice_hw *hw, struct list_head *fv_list,
   4852		       struct list_head *rg_list)
   4853{
   4854	struct ice_sw_fv_list_entry *fv;
   4855	struct ice_recp_grp_entry *rg;
   4856	struct ice_fv_word *fv_ext;
   4857
   4858	if (list_empty(fv_list))
   4859		return 0;
   4860
   4861	fv = list_first_entry(fv_list, struct ice_sw_fv_list_entry,
   4862			      list_entry);
   4863	fv_ext = fv->fv_ptr->ew;
   4864
   4865	list_for_each_entry(rg, rg_list, l_entry) {
   4866		u8 i;
   4867
   4868		for (i = 0; i < rg->r_group.n_val_pairs; i++) {
   4869			struct ice_fv_word *pr;
   4870			bool found = false;
   4871			u16 mask;
   4872			u8 j;
   4873
   4874			pr = &rg->r_group.pairs[i];
   4875			mask = rg->r_group.mask[i];
   4876
   4877			for (j = 0; j < hw->blk[ICE_BLK_SW].es.fvw; j++)
   4878				if (fv_ext[j].prot_id == pr->prot_id &&
   4879				    fv_ext[j].off == pr->off) {
   4880					found = true;
   4881
   4882					/* Store index of field vector */
   4883					rg->fv_idx[i] = j;
   4884					rg->fv_mask[i] = mask;
   4885					break;
   4886				}
   4887
   4888			/* Protocol/offset could not be found, caller gave an
   4889			 * invalid pair
   4890			 */
   4891			if (!found)
   4892				return -EINVAL;
   4893		}
   4894	}
   4895
   4896	return 0;
   4897}
   4898
   4899/**
   4900 * ice_find_free_recp_res_idx - find free result indexes for recipe
   4901 * @hw: pointer to hardware structure
   4902 * @profiles: bitmap of profiles that will be associated with the new recipe
   4903 * @free_idx: pointer to variable to receive the free index bitmap
   4904 *
   4905 * The algorithm used here is:
   4906 *	1. When creating a new recipe, create a set P which contains all
   4907 *	   Profiles that will be associated with our new recipe
   4908 *
   4909 *	2. For each Profile p in set P:
   4910 *	    a. Add all recipes associated with Profile p into set R
   4911 *	    b. Optional : PossibleIndexes &= profile[p].possibleIndexes
   4912 *		[initially PossibleIndexes should be 0xFFFFFFFFFFFFFFFF]
   4913 *		i. Or just assume they all have the same possible indexes:
   4914 *			44, 45, 46, 47
   4915 *			i.e., PossibleIndexes = 0x0000F00000000000
   4916 *
   4917 *	3. For each Recipe r in set R:
   4918 *	    a. UsedIndexes |= (bitwise or ) recipe[r].res_indexes
   4919 *	    b. FreeIndexes = UsedIndexes ^ PossibleIndexes
   4920 *
   4921 *	FreeIndexes will contain the bits indicating the indexes free for use,
   4922 *      then the code needs to update the recipe[r].used_result_idx_bits to
   4923 *      indicate which indexes were selected for use by this recipe.
   4924 */
   4925static u16
   4926ice_find_free_recp_res_idx(struct ice_hw *hw, const unsigned long *profiles,
   4927			   unsigned long *free_idx)
   4928{
   4929	DECLARE_BITMAP(possible_idx, ICE_MAX_FV_WORDS);
   4930	DECLARE_BITMAP(recipes, ICE_MAX_NUM_RECIPES);
   4931	DECLARE_BITMAP(used_idx, ICE_MAX_FV_WORDS);
   4932	u16 bit;
   4933
   4934	bitmap_zero(recipes, ICE_MAX_NUM_RECIPES);
   4935	bitmap_zero(used_idx, ICE_MAX_FV_WORDS);
   4936
   4937	bitmap_set(possible_idx, 0, ICE_MAX_FV_WORDS);
   4938
   4939	/* For each profile we are going to associate the recipe with, add the
   4940	 * recipes that are associated with that profile. This will give us
   4941	 * the set of recipes that our recipe may collide with. Also, determine
   4942	 * what possible result indexes are usable given this set of profiles.
   4943	 */
   4944	for_each_set_bit(bit, profiles, ICE_MAX_NUM_PROFILES) {
   4945		bitmap_or(recipes, recipes, profile_to_recipe[bit],
   4946			  ICE_MAX_NUM_RECIPES);
   4947		bitmap_and(possible_idx, possible_idx,
   4948			   hw->switch_info->prof_res_bm[bit],
   4949			   ICE_MAX_FV_WORDS);
   4950	}
   4951
   4952	/* For each recipe that our new recipe may collide with, determine
   4953	 * which indexes have been used.
   4954	 */
   4955	for_each_set_bit(bit, recipes, ICE_MAX_NUM_RECIPES)
   4956		bitmap_or(used_idx, used_idx,
   4957			  hw->switch_info->recp_list[bit].res_idxs,
   4958			  ICE_MAX_FV_WORDS);
   4959
   4960	bitmap_xor(free_idx, used_idx, possible_idx, ICE_MAX_FV_WORDS);
   4961
   4962	/* return number of free indexes */
   4963	return (u16)bitmap_weight(free_idx, ICE_MAX_FV_WORDS);
   4964}
   4965
   4966/**
   4967 * ice_add_sw_recipe - function to call AQ calls to create switch recipe
   4968 * @hw: pointer to hardware structure
   4969 * @rm: recipe management list entry
   4970 * @profiles: bitmap of profiles that will be associated.
   4971 */
   4972static int
   4973ice_add_sw_recipe(struct ice_hw *hw, struct ice_sw_recipe *rm,
   4974		  unsigned long *profiles)
   4975{
   4976	DECLARE_BITMAP(result_idx_bm, ICE_MAX_FV_WORDS);
   4977	struct ice_aqc_recipe_data_elem *tmp;
   4978	struct ice_aqc_recipe_data_elem *buf;
   4979	struct ice_recp_grp_entry *entry;
   4980	u16 free_res_idx;
   4981	u16 recipe_count;
   4982	u8 chain_idx;
   4983	u8 recps = 0;
   4984	int status;
   4985
   4986	/* When more than one recipe are required, another recipe is needed to
   4987	 * chain them together. Matching a tunnel metadata ID takes up one of
   4988	 * the match fields in the chaining recipe reducing the number of
   4989	 * chained recipes by one.
   4990	 */
   4991	 /* check number of free result indices */
   4992	bitmap_zero(result_idx_bm, ICE_MAX_FV_WORDS);
   4993	free_res_idx = ice_find_free_recp_res_idx(hw, profiles, result_idx_bm);
   4994
   4995	ice_debug(hw, ICE_DBG_SW, "Result idx slots: %d, need %d\n",
   4996		  free_res_idx, rm->n_grp_count);
   4997
   4998	if (rm->n_grp_count > 1) {
   4999		if (rm->n_grp_count > free_res_idx)
   5000			return -ENOSPC;
   5001
   5002		rm->n_grp_count++;
   5003	}
   5004
   5005	if (rm->n_grp_count > ICE_MAX_CHAIN_RECIPE)
   5006		return -ENOSPC;
   5007
   5008	tmp = kcalloc(ICE_MAX_NUM_RECIPES, sizeof(*tmp), GFP_KERNEL);
   5009	if (!tmp)
   5010		return -ENOMEM;
   5011
   5012	buf = devm_kcalloc(ice_hw_to_dev(hw), rm->n_grp_count, sizeof(*buf),
   5013			   GFP_KERNEL);
   5014	if (!buf) {
   5015		status = -ENOMEM;
   5016		goto err_mem;
   5017	}
   5018
   5019	bitmap_zero(rm->r_bitmap, ICE_MAX_NUM_RECIPES);
   5020	recipe_count = ICE_MAX_NUM_RECIPES;
   5021	status = ice_aq_get_recipe(hw, tmp, &recipe_count, ICE_SW_LKUP_MAC,
   5022				   NULL);
   5023	if (status || recipe_count == 0)
   5024		goto err_unroll;
   5025
   5026	/* Allocate the recipe resources, and configure them according to the
   5027	 * match fields from protocol headers and extracted field vectors.
   5028	 */
   5029	chain_idx = find_first_bit(result_idx_bm, ICE_MAX_FV_WORDS);
   5030	list_for_each_entry(entry, &rm->rg_list, l_entry) {
   5031		u8 i;
   5032
   5033		status = ice_alloc_recipe(hw, &entry->rid);
   5034		if (status)
   5035			goto err_unroll;
   5036
   5037		/* Clear the result index of the located recipe, as this will be
   5038		 * updated, if needed, later in the recipe creation process.
   5039		 */
   5040		tmp[0].content.result_indx = 0;
   5041
   5042		buf[recps] = tmp[0];
   5043		buf[recps].recipe_indx = (u8)entry->rid;
   5044		/* if the recipe is a non-root recipe RID should be programmed
   5045		 * as 0 for the rules to be applied correctly.
   5046		 */
   5047		buf[recps].content.rid = 0;
   5048		memset(&buf[recps].content.lkup_indx, 0,
   5049		       sizeof(buf[recps].content.lkup_indx));
   5050
   5051		/* All recipes use look-up index 0 to match switch ID. */
   5052		buf[recps].content.lkup_indx[0] = ICE_AQ_SW_ID_LKUP_IDX;
   5053		buf[recps].content.mask[0] =
   5054			cpu_to_le16(ICE_AQ_SW_ID_LKUP_MASK);
   5055		/* Setup lkup_indx 1..4 to INVALID/ignore and set the mask
   5056		 * to be 0
   5057		 */
   5058		for (i = 1; i <= ICE_NUM_WORDS_RECIPE; i++) {
   5059			buf[recps].content.lkup_indx[i] = 0x80;
   5060			buf[recps].content.mask[i] = 0;
   5061		}
   5062
   5063		for (i = 0; i < entry->r_group.n_val_pairs; i++) {
   5064			buf[recps].content.lkup_indx[i + 1] = entry->fv_idx[i];
   5065			buf[recps].content.mask[i + 1] =
   5066				cpu_to_le16(entry->fv_mask[i]);
   5067		}
   5068
   5069		if (rm->n_grp_count > 1) {
   5070			/* Checks to see if there really is a valid result index
   5071			 * that can be used.
   5072			 */
   5073			if (chain_idx >= ICE_MAX_FV_WORDS) {
   5074				ice_debug(hw, ICE_DBG_SW, "No chain index available\n");
   5075				status = -ENOSPC;
   5076				goto err_unroll;
   5077			}
   5078
   5079			entry->chain_idx = chain_idx;
   5080			buf[recps].content.result_indx =
   5081				ICE_AQ_RECIPE_RESULT_EN |
   5082				((chain_idx << ICE_AQ_RECIPE_RESULT_DATA_S) &
   5083				 ICE_AQ_RECIPE_RESULT_DATA_M);
   5084			clear_bit(chain_idx, result_idx_bm);
   5085			chain_idx = find_first_bit(result_idx_bm,
   5086						   ICE_MAX_FV_WORDS);
   5087		}
   5088
   5089		/* fill recipe dependencies */
   5090		bitmap_zero((unsigned long *)buf[recps].recipe_bitmap,
   5091			    ICE_MAX_NUM_RECIPES);
   5092		set_bit(buf[recps].recipe_indx,
   5093			(unsigned long *)buf[recps].recipe_bitmap);
   5094		buf[recps].content.act_ctrl_fwd_priority = rm->priority;
   5095		recps++;
   5096	}
   5097
   5098	if (rm->n_grp_count == 1) {
   5099		rm->root_rid = buf[0].recipe_indx;
   5100		set_bit(buf[0].recipe_indx, rm->r_bitmap);
   5101		buf[0].content.rid = rm->root_rid | ICE_AQ_RECIPE_ID_IS_ROOT;
   5102		if (sizeof(buf[0].recipe_bitmap) >= sizeof(rm->r_bitmap)) {
   5103			memcpy(buf[0].recipe_bitmap, rm->r_bitmap,
   5104			       sizeof(buf[0].recipe_bitmap));
   5105		} else {
   5106			status = -EINVAL;
   5107			goto err_unroll;
   5108		}
   5109		/* Applicable only for ROOT_RECIPE, set the fwd_priority for
   5110		 * the recipe which is getting created if specified
   5111		 * by user. Usually any advanced switch filter, which results
   5112		 * into new extraction sequence, ended up creating a new recipe
   5113		 * of type ROOT and usually recipes are associated with profiles
   5114		 * Switch rule referreing newly created recipe, needs to have
   5115		 * either/or 'fwd' or 'join' priority, otherwise switch rule
   5116		 * evaluation will not happen correctly. In other words, if
   5117		 * switch rule to be evaluated on priority basis, then recipe
   5118		 * needs to have priority, otherwise it will be evaluated last.
   5119		 */
   5120		buf[0].content.act_ctrl_fwd_priority = rm->priority;
   5121	} else {
   5122		struct ice_recp_grp_entry *last_chain_entry;
   5123		u16 rid, i;
   5124
   5125		/* Allocate the last recipe that will chain the outcomes of the
   5126		 * other recipes together
   5127		 */
   5128		status = ice_alloc_recipe(hw, &rid);
   5129		if (status)
   5130			goto err_unroll;
   5131
   5132		buf[recps].recipe_indx = (u8)rid;
   5133		buf[recps].content.rid = (u8)rid;
   5134		buf[recps].content.rid |= ICE_AQ_RECIPE_ID_IS_ROOT;
   5135		/* the new entry created should also be part of rg_list to
   5136		 * make sure we have complete recipe
   5137		 */
   5138		last_chain_entry = devm_kzalloc(ice_hw_to_dev(hw),
   5139						sizeof(*last_chain_entry),
   5140						GFP_KERNEL);
   5141		if (!last_chain_entry) {
   5142			status = -ENOMEM;
   5143			goto err_unroll;
   5144		}
   5145		last_chain_entry->rid = rid;
   5146		memset(&buf[recps].content.lkup_indx, 0,
   5147		       sizeof(buf[recps].content.lkup_indx));
   5148		/* All recipes use look-up index 0 to match switch ID. */
   5149		buf[recps].content.lkup_indx[0] = ICE_AQ_SW_ID_LKUP_IDX;
   5150		buf[recps].content.mask[0] =
   5151			cpu_to_le16(ICE_AQ_SW_ID_LKUP_MASK);
   5152		for (i = 1; i <= ICE_NUM_WORDS_RECIPE; i++) {
   5153			buf[recps].content.lkup_indx[i] =
   5154				ICE_AQ_RECIPE_LKUP_IGNORE;
   5155			buf[recps].content.mask[i] = 0;
   5156		}
   5157
   5158		i = 1;
   5159		/* update r_bitmap with the recp that is used for chaining */
   5160		set_bit(rid, rm->r_bitmap);
   5161		/* this is the recipe that chains all the other recipes so it
   5162		 * should not have a chaining ID to indicate the same
   5163		 */
   5164		last_chain_entry->chain_idx = ICE_INVAL_CHAIN_IND;
   5165		list_for_each_entry(entry, &rm->rg_list, l_entry) {
   5166			last_chain_entry->fv_idx[i] = entry->chain_idx;
   5167			buf[recps].content.lkup_indx[i] = entry->chain_idx;
   5168			buf[recps].content.mask[i++] = cpu_to_le16(0xFFFF);
   5169			set_bit(entry->rid, rm->r_bitmap);
   5170		}
   5171		list_add(&last_chain_entry->l_entry, &rm->rg_list);
   5172		if (sizeof(buf[recps].recipe_bitmap) >=
   5173		    sizeof(rm->r_bitmap)) {
   5174			memcpy(buf[recps].recipe_bitmap, rm->r_bitmap,
   5175			       sizeof(buf[recps].recipe_bitmap));
   5176		} else {
   5177			status = -EINVAL;
   5178			goto err_unroll;
   5179		}
   5180		buf[recps].content.act_ctrl_fwd_priority = rm->priority;
   5181
   5182		recps++;
   5183		rm->root_rid = (u8)rid;
   5184	}
   5185	status = ice_acquire_change_lock(hw, ICE_RES_WRITE);
   5186	if (status)
   5187		goto err_unroll;
   5188
   5189	status = ice_aq_add_recipe(hw, buf, rm->n_grp_count, NULL);
   5190	ice_release_change_lock(hw);
   5191	if (status)
   5192		goto err_unroll;
   5193
   5194	/* Every recipe that just got created add it to the recipe
   5195	 * book keeping list
   5196	 */
   5197	list_for_each_entry(entry, &rm->rg_list, l_entry) {
   5198		struct ice_switch_info *sw = hw->switch_info;
   5199		bool is_root, idx_found = false;
   5200		struct ice_sw_recipe *recp;
   5201		u16 idx, buf_idx = 0;
   5202
   5203		/* find buffer index for copying some data */
   5204		for (idx = 0; idx < rm->n_grp_count; idx++)
   5205			if (buf[idx].recipe_indx == entry->rid) {
   5206				buf_idx = idx;
   5207				idx_found = true;
   5208			}
   5209
   5210		if (!idx_found) {
   5211			status = -EIO;
   5212			goto err_unroll;
   5213		}
   5214
   5215		recp = &sw->recp_list[entry->rid];
   5216		is_root = (rm->root_rid == entry->rid);
   5217		recp->is_root = is_root;
   5218
   5219		recp->root_rid = entry->rid;
   5220		recp->big_recp = (is_root && rm->n_grp_count > 1);
   5221
   5222		memcpy(&recp->ext_words, entry->r_group.pairs,
   5223		       entry->r_group.n_val_pairs * sizeof(struct ice_fv_word));
   5224
   5225		memcpy(recp->r_bitmap, buf[buf_idx].recipe_bitmap,
   5226		       sizeof(recp->r_bitmap));
   5227
   5228		/* Copy non-result fv index values and masks to recipe. This
   5229		 * call will also update the result recipe bitmask.
   5230		 */
   5231		ice_collect_result_idx(&buf[buf_idx], recp);
   5232
   5233		/* for non-root recipes, also copy to the root, this allows
   5234		 * easier matching of a complete chained recipe
   5235		 */
   5236		if (!is_root)
   5237			ice_collect_result_idx(&buf[buf_idx],
   5238					       &sw->recp_list[rm->root_rid]);
   5239
   5240		recp->n_ext_words = entry->r_group.n_val_pairs;
   5241		recp->chain_idx = entry->chain_idx;
   5242		recp->priority = buf[buf_idx].content.act_ctrl_fwd_priority;
   5243		recp->n_grp_count = rm->n_grp_count;
   5244		recp->tun_type = rm->tun_type;
   5245		recp->recp_created = true;
   5246	}
   5247	rm->root_buf = buf;
   5248	kfree(tmp);
   5249	return status;
   5250
   5251err_unroll:
   5252err_mem:
   5253	kfree(tmp);
   5254	devm_kfree(ice_hw_to_dev(hw), buf);
   5255	return status;
   5256}
   5257
   5258/**
   5259 * ice_create_recipe_group - creates recipe group
   5260 * @hw: pointer to hardware structure
   5261 * @rm: recipe management list entry
   5262 * @lkup_exts: lookup elements
   5263 */
   5264static int
   5265ice_create_recipe_group(struct ice_hw *hw, struct ice_sw_recipe *rm,
   5266			struct ice_prot_lkup_ext *lkup_exts)
   5267{
   5268	u8 recp_count = 0;
   5269	int status;
   5270
   5271	rm->n_grp_count = 0;
   5272
   5273	/* Create recipes for words that are marked not done by packing them
   5274	 * as best fit.
   5275	 */
   5276	status = ice_create_first_fit_recp_def(hw, lkup_exts,
   5277					       &rm->rg_list, &recp_count);
   5278	if (!status) {
   5279		rm->n_grp_count += recp_count;
   5280		rm->n_ext_words = lkup_exts->n_val_words;
   5281		memcpy(&rm->ext_words, lkup_exts->fv_words,
   5282		       sizeof(rm->ext_words));
   5283		memcpy(rm->word_masks, lkup_exts->field_mask,
   5284		       sizeof(rm->word_masks));
   5285	}
   5286
   5287	return status;
   5288}
   5289
   5290/**
   5291 * ice_tun_type_match_word - determine if tun type needs a match mask
   5292 * @tun_type: tunnel type
   5293 * @mask: mask to be used for the tunnel
   5294 */
   5295static bool ice_tun_type_match_word(enum ice_sw_tunnel_type tun_type, u16 *mask)
   5296{
   5297	switch (tun_type) {
   5298	case ICE_SW_TUN_GENEVE:
   5299	case ICE_SW_TUN_VXLAN:
   5300	case ICE_SW_TUN_NVGRE:
   5301	case ICE_SW_TUN_GTPU:
   5302	case ICE_SW_TUN_GTPC:
   5303		*mask = ICE_TUN_FLAG_MASK;
   5304		return true;
   5305
   5306	default:
   5307		*mask = 0;
   5308		return false;
   5309	}
   5310}
   5311
   5312/**
   5313 * ice_add_special_words - Add words that are not protocols, such as metadata
   5314 * @rinfo: other information regarding the rule e.g. priority and action info
   5315 * @lkup_exts: lookup word structure
   5316 */
   5317static int
   5318ice_add_special_words(struct ice_adv_rule_info *rinfo,
   5319		      struct ice_prot_lkup_ext *lkup_exts)
   5320{
   5321	u16 mask;
   5322
   5323	/* If this is a tunneled packet, then add recipe index to match the
   5324	 * tunnel bit in the packet metadata flags.
   5325	 */
   5326	if (ice_tun_type_match_word(rinfo->tun_type, &mask)) {
   5327		if (lkup_exts->n_val_words < ICE_MAX_CHAIN_WORDS) {
   5328			u8 word = lkup_exts->n_val_words++;
   5329
   5330			lkup_exts->fv_words[word].prot_id = ICE_META_DATA_ID_HW;
   5331			lkup_exts->fv_words[word].off = ICE_TUN_FLAG_MDID_OFF;
   5332			lkup_exts->field_mask[word] = mask;
   5333		} else {
   5334			return -ENOSPC;
   5335		}
   5336	}
   5337
   5338	return 0;
   5339}
   5340
   5341/* ice_get_compat_fv_bitmap - Get compatible field vector bitmap for rule
   5342 * @hw: pointer to hardware structure
   5343 * @rinfo: other information regarding the rule e.g. priority and action info
   5344 * @bm: pointer to memory for returning the bitmap of field vectors
   5345 */
   5346static void
   5347ice_get_compat_fv_bitmap(struct ice_hw *hw, struct ice_adv_rule_info *rinfo,
   5348			 unsigned long *bm)
   5349{
   5350	enum ice_prof_type prof_type;
   5351
   5352	bitmap_zero(bm, ICE_MAX_NUM_PROFILES);
   5353
   5354	switch (rinfo->tun_type) {
   5355	case ICE_NON_TUN:
   5356		prof_type = ICE_PROF_NON_TUN;
   5357		break;
   5358	case ICE_ALL_TUNNELS:
   5359		prof_type = ICE_PROF_TUN_ALL;
   5360		break;
   5361	case ICE_SW_TUN_GENEVE:
   5362	case ICE_SW_TUN_VXLAN:
   5363		prof_type = ICE_PROF_TUN_UDP;
   5364		break;
   5365	case ICE_SW_TUN_NVGRE:
   5366		prof_type = ICE_PROF_TUN_GRE;
   5367		break;
   5368	case ICE_SW_TUN_GTPU:
   5369		prof_type = ICE_PROF_TUN_GTPU;
   5370		break;
   5371	case ICE_SW_TUN_GTPC:
   5372		prof_type = ICE_PROF_TUN_GTPC;
   5373		break;
   5374	case ICE_SW_TUN_AND_NON_TUN:
   5375	default:
   5376		prof_type = ICE_PROF_ALL;
   5377		break;
   5378	}
   5379
   5380	ice_get_sw_fv_bitmap(hw, prof_type, bm);
   5381}
   5382
   5383/**
   5384 * ice_add_adv_recipe - Add an advanced recipe that is not part of the default
   5385 * @hw: pointer to hardware structure
   5386 * @lkups: lookup elements or match criteria for the advanced recipe, one
   5387 *  structure per protocol header
   5388 * @lkups_cnt: number of protocols
   5389 * @rinfo: other information regarding the rule e.g. priority and action info
   5390 * @rid: return the recipe ID of the recipe created
   5391 */
   5392static int
   5393ice_add_adv_recipe(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
   5394		   u16 lkups_cnt, struct ice_adv_rule_info *rinfo, u16 *rid)
   5395{
   5396	DECLARE_BITMAP(fv_bitmap, ICE_MAX_NUM_PROFILES);
   5397	DECLARE_BITMAP(profiles, ICE_MAX_NUM_PROFILES);
   5398	struct ice_prot_lkup_ext *lkup_exts;
   5399	struct ice_recp_grp_entry *r_entry;
   5400	struct ice_sw_fv_list_entry *fvit;
   5401	struct ice_recp_grp_entry *r_tmp;
   5402	struct ice_sw_fv_list_entry *tmp;
   5403	struct ice_sw_recipe *rm;
   5404	int status = 0;
   5405	u8 i;
   5406
   5407	if (!lkups_cnt)
   5408		return -EINVAL;
   5409
   5410	lkup_exts = kzalloc(sizeof(*lkup_exts), GFP_KERNEL);
   5411	if (!lkup_exts)
   5412		return -ENOMEM;
   5413
   5414	/* Determine the number of words to be matched and if it exceeds a
   5415	 * recipe's restrictions
   5416	 */
   5417	for (i = 0; i < lkups_cnt; i++) {
   5418		u16 count;
   5419
   5420		if (lkups[i].type >= ICE_PROTOCOL_LAST) {
   5421			status = -EIO;
   5422			goto err_free_lkup_exts;
   5423		}
   5424
   5425		count = ice_fill_valid_words(&lkups[i], lkup_exts);
   5426		if (!count) {
   5427			status = -EIO;
   5428			goto err_free_lkup_exts;
   5429		}
   5430	}
   5431
   5432	rm = kzalloc(sizeof(*rm), GFP_KERNEL);
   5433	if (!rm) {
   5434		status = -ENOMEM;
   5435		goto err_free_lkup_exts;
   5436	}
   5437
   5438	/* Get field vectors that contain fields extracted from all the protocol
   5439	 * headers being programmed.
   5440	 */
   5441	INIT_LIST_HEAD(&rm->fv_list);
   5442	INIT_LIST_HEAD(&rm->rg_list);
   5443
   5444	/* Get bitmap of field vectors (profiles) that are compatible with the
   5445	 * rule request; only these will be searched in the subsequent call to
   5446	 * ice_get_sw_fv_list.
   5447	 */
   5448	ice_get_compat_fv_bitmap(hw, rinfo, fv_bitmap);
   5449
   5450	status = ice_get_sw_fv_list(hw, lkup_exts, fv_bitmap, &rm->fv_list);
   5451	if (status)
   5452		goto err_unroll;
   5453
   5454	/* Create any special protocol/offset pairs, such as looking at tunnel
   5455	 * bits by extracting metadata
   5456	 */
   5457	status = ice_add_special_words(rinfo, lkup_exts);
   5458	if (status)
   5459		goto err_free_lkup_exts;
   5460
   5461	/* Group match words into recipes using preferred recipe grouping
   5462	 * criteria.
   5463	 */
   5464	status = ice_create_recipe_group(hw, rm, lkup_exts);
   5465	if (status)
   5466		goto err_unroll;
   5467
   5468	/* set the recipe priority if specified */
   5469	rm->priority = (u8)rinfo->priority;
   5470
   5471	/* Find offsets from the field vector. Pick the first one for all the
   5472	 * recipes.
   5473	 */
   5474	status = ice_fill_fv_word_index(hw, &rm->fv_list, &rm->rg_list);
   5475	if (status)
   5476		goto err_unroll;
   5477
   5478	/* get bitmap of all profiles the recipe will be associated with */
   5479	bitmap_zero(profiles, ICE_MAX_NUM_PROFILES);
   5480	list_for_each_entry(fvit, &rm->fv_list, list_entry) {
   5481		ice_debug(hw, ICE_DBG_SW, "profile: %d\n", fvit->profile_id);
   5482		set_bit((u16)fvit->profile_id, profiles);
   5483	}
   5484
   5485	/* Look for a recipe which matches our requested fv / mask list */
   5486	*rid = ice_find_recp(hw, lkup_exts, rinfo->tun_type);
   5487	if (*rid < ICE_MAX_NUM_RECIPES)
   5488		/* Success if found a recipe that match the existing criteria */
   5489		goto err_unroll;
   5490
   5491	rm->tun_type = rinfo->tun_type;
   5492	/* Recipe we need does not exist, add a recipe */
   5493	status = ice_add_sw_recipe(hw, rm, profiles);
   5494	if (status)
   5495		goto err_unroll;
   5496
   5497	/* Associate all the recipes created with all the profiles in the
   5498	 * common field vector.
   5499	 */
   5500	list_for_each_entry(fvit, &rm->fv_list, list_entry) {
   5501		DECLARE_BITMAP(r_bitmap, ICE_MAX_NUM_RECIPES);
   5502		u16 j;
   5503
   5504		status = ice_aq_get_recipe_to_profile(hw, fvit->profile_id,
   5505						      (u8 *)r_bitmap, NULL);
   5506		if (status)
   5507			goto err_unroll;
   5508
   5509		bitmap_or(r_bitmap, r_bitmap, rm->r_bitmap,
   5510			  ICE_MAX_NUM_RECIPES);
   5511		status = ice_acquire_change_lock(hw, ICE_RES_WRITE);
   5512		if (status)
   5513			goto err_unroll;
   5514
   5515		status = ice_aq_map_recipe_to_profile(hw, fvit->profile_id,
   5516						      (u8 *)r_bitmap,
   5517						      NULL);
   5518		ice_release_change_lock(hw);
   5519
   5520		if (status)
   5521			goto err_unroll;
   5522
   5523		/* Update profile to recipe bitmap array */
   5524		bitmap_copy(profile_to_recipe[fvit->profile_id], r_bitmap,
   5525			    ICE_MAX_NUM_RECIPES);
   5526
   5527		/* Update recipe to profile bitmap array */
   5528		for_each_set_bit(j, rm->r_bitmap, ICE_MAX_NUM_RECIPES)
   5529			set_bit((u16)fvit->profile_id, recipe_to_profile[j]);
   5530	}
   5531
   5532	*rid = rm->root_rid;
   5533	memcpy(&hw->switch_info->recp_list[*rid].lkup_exts, lkup_exts,
   5534	       sizeof(*lkup_exts));
   5535err_unroll:
   5536	list_for_each_entry_safe(r_entry, r_tmp, &rm->rg_list, l_entry) {
   5537		list_del(&r_entry->l_entry);
   5538		devm_kfree(ice_hw_to_dev(hw), r_entry);
   5539	}
   5540
   5541	list_for_each_entry_safe(fvit, tmp, &rm->fv_list, list_entry) {
   5542		list_del(&fvit->list_entry);
   5543		devm_kfree(ice_hw_to_dev(hw), fvit);
   5544	}
   5545
   5546	if (rm->root_buf)
   5547		devm_kfree(ice_hw_to_dev(hw), rm->root_buf);
   5548
   5549	kfree(rm);
   5550
   5551err_free_lkup_exts:
   5552	kfree(lkup_exts);
   5553
   5554	return status;
   5555}
   5556
   5557/**
   5558 * ice_find_dummy_packet - find dummy packet
   5559 *
   5560 * @lkups: lookup elements or match criteria for the advanced recipe, one
   5561 *	   structure per protocol header
   5562 * @lkups_cnt: number of protocols
   5563 * @tun_type: tunnel type
   5564 *
   5565 * Returns the &ice_dummy_pkt_profile corresponding to these lookup params.
   5566 */
   5567static const struct ice_dummy_pkt_profile *
   5568ice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
   5569		      enum ice_sw_tunnel_type tun_type)
   5570{
   5571	const struct ice_dummy_pkt_profile *ret = ice_dummy_pkt_profiles;
   5572	u32 match = 0;
   5573	u16 i;
   5574
   5575	switch (tun_type) {
   5576	case ICE_SW_TUN_GTPC:
   5577		match |= ICE_PKT_TUN_GTPC;
   5578		break;
   5579	case ICE_SW_TUN_GTPU:
   5580		match |= ICE_PKT_TUN_GTPU;
   5581		break;
   5582	case ICE_SW_TUN_NVGRE:
   5583		match |= ICE_PKT_TUN_NVGRE;
   5584		break;
   5585	case ICE_SW_TUN_GENEVE:
   5586	case ICE_SW_TUN_VXLAN:
   5587		match |= ICE_PKT_TUN_UDP;
   5588		break;
   5589	default:
   5590		break;
   5591	}
   5592
   5593	for (i = 0; i < lkups_cnt; i++) {
   5594		if (lkups[i].type == ICE_UDP_ILOS)
   5595			match |= ICE_PKT_INNER_UDP;
   5596		else if (lkups[i].type == ICE_TCP_IL)
   5597			match |= ICE_PKT_INNER_TCP;
   5598		else if (lkups[i].type == ICE_IPV6_OFOS)
   5599			match |= ICE_PKT_OUTER_IPV6;
   5600		else if (lkups[i].type == ICE_VLAN_OFOS)
   5601			match |= ICE_PKT_VLAN;
   5602		else if (lkups[i].type == ICE_ETYPE_OL &&
   5603			 lkups[i].h_u.ethertype.ethtype_id ==
   5604				cpu_to_be16(ICE_IPV6_ETHER_ID) &&
   5605			 lkups[i].m_u.ethertype.ethtype_id ==
   5606				cpu_to_be16(0xFFFF))
   5607			match |= ICE_PKT_OUTER_IPV6;
   5608		else if (lkups[i].type == ICE_ETYPE_IL &&
   5609			 lkups[i].h_u.ethertype.ethtype_id ==
   5610				cpu_to_be16(ICE_IPV6_ETHER_ID) &&
   5611			 lkups[i].m_u.ethertype.ethtype_id ==
   5612				cpu_to_be16(0xFFFF))
   5613			match |= ICE_PKT_INNER_IPV6;
   5614		else if (lkups[i].type == ICE_IPV6_IL)
   5615			match |= ICE_PKT_INNER_IPV6;
   5616		else if (lkups[i].type == ICE_GTP_NO_PAY)
   5617			match |= ICE_PKT_GTP_NOPAY;
   5618	}
   5619
   5620	while (ret->match && (match & ret->match) != ret->match)
   5621		ret++;
   5622
   5623	return ret;
   5624}
   5625
   5626/**
   5627 * ice_fill_adv_dummy_packet - fill a dummy packet with given match criteria
   5628 *
   5629 * @lkups: lookup elements or match criteria for the advanced recipe, one
   5630 *	   structure per protocol header
   5631 * @lkups_cnt: number of protocols
   5632 * @s_rule: stores rule information from the match criteria
   5633 * @profile: dummy packet profile (the template, its size and header offsets)
   5634 */
   5635static int
   5636ice_fill_adv_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
   5637			  struct ice_sw_rule_lkup_rx_tx *s_rule,
   5638			  const struct ice_dummy_pkt_profile *profile)
   5639{
   5640	u8 *pkt;
   5641	u16 i;
   5642
   5643	/* Start with a packet with a pre-defined/dummy content. Then, fill
   5644	 * in the header values to be looked up or matched.
   5645	 */
   5646	pkt = s_rule->hdr_data;
   5647
   5648	memcpy(pkt, profile->pkt, profile->pkt_len);
   5649
   5650	for (i = 0; i < lkups_cnt; i++) {
   5651		const struct ice_dummy_pkt_offsets *offsets = profile->offsets;
   5652		enum ice_protocol_type type;
   5653		u16 offset = 0, len = 0, j;
   5654		bool found = false;
   5655
   5656		/* find the start of this layer; it should be found since this
   5657		 * was already checked when search for the dummy packet
   5658		 */
   5659		type = lkups[i].type;
   5660		for (j = 0; offsets[j].type != ICE_PROTOCOL_LAST; j++) {
   5661			if (type == offsets[j].type) {
   5662				offset = offsets[j].offset;
   5663				found = true;
   5664				break;
   5665			}
   5666		}
   5667		/* this should never happen in a correct calling sequence */
   5668		if (!found)
   5669			return -EINVAL;
   5670
   5671		switch (lkups[i].type) {
   5672		case ICE_MAC_OFOS:
   5673		case ICE_MAC_IL:
   5674			len = sizeof(struct ice_ether_hdr);
   5675			break;
   5676		case ICE_ETYPE_OL:
   5677		case ICE_ETYPE_IL:
   5678			len = sizeof(struct ice_ethtype_hdr);
   5679			break;
   5680		case ICE_VLAN_OFOS:
   5681			len = sizeof(struct ice_vlan_hdr);
   5682			break;
   5683		case ICE_IPV4_OFOS:
   5684		case ICE_IPV4_IL:
   5685			len = sizeof(struct ice_ipv4_hdr);
   5686			break;
   5687		case ICE_IPV6_OFOS:
   5688		case ICE_IPV6_IL:
   5689			len = sizeof(struct ice_ipv6_hdr);
   5690			break;
   5691		case ICE_TCP_IL:
   5692		case ICE_UDP_OF:
   5693		case ICE_UDP_ILOS:
   5694			len = sizeof(struct ice_l4_hdr);
   5695			break;
   5696		case ICE_SCTP_IL:
   5697			len = sizeof(struct ice_sctp_hdr);
   5698			break;
   5699		case ICE_NVGRE:
   5700			len = sizeof(struct ice_nvgre_hdr);
   5701			break;
   5702		case ICE_VXLAN:
   5703		case ICE_GENEVE:
   5704			len = sizeof(struct ice_udp_tnl_hdr);
   5705			break;
   5706		case ICE_GTP_NO_PAY:
   5707		case ICE_GTP:
   5708			len = sizeof(struct ice_udp_gtp_hdr);
   5709			break;
   5710		default:
   5711			return -EINVAL;
   5712		}
   5713
   5714		/* the length should be a word multiple */
   5715		if (len % ICE_BYTES_PER_WORD)
   5716			return -EIO;
   5717
   5718		/* We have the offset to the header start, the length, the
   5719		 * caller's header values and mask. Use this information to
   5720		 * copy the data into the dummy packet appropriately based on
   5721		 * the mask. Note that we need to only write the bits as
   5722		 * indicated by the mask to make sure we don't improperly write
   5723		 * over any significant packet data.
   5724		 */
   5725		for (j = 0; j < len / sizeof(u16); j++) {
   5726			u16 *ptr = (u16 *)(pkt + offset);
   5727			u16 mask = lkups[i].m_raw[j];
   5728
   5729			if (!mask)
   5730				continue;
   5731
   5732			ptr[j] = (ptr[j] & ~mask) | (lkups[i].h_raw[j] & mask);
   5733		}
   5734	}
   5735
   5736	s_rule->hdr_len = cpu_to_le16(profile->pkt_len);
   5737
   5738	return 0;
   5739}
   5740
   5741/**
   5742 * ice_fill_adv_packet_tun - fill dummy packet with udp tunnel port
   5743 * @hw: pointer to the hardware structure
   5744 * @tun_type: tunnel type
   5745 * @pkt: dummy packet to fill in
   5746 * @offsets: offset info for the dummy packet
   5747 */
   5748static int
   5749ice_fill_adv_packet_tun(struct ice_hw *hw, enum ice_sw_tunnel_type tun_type,
   5750			u8 *pkt, const struct ice_dummy_pkt_offsets *offsets)
   5751{
   5752	u16 open_port, i;
   5753
   5754	switch (tun_type) {
   5755	case ICE_SW_TUN_VXLAN:
   5756		if (!ice_get_open_tunnel_port(hw, &open_port, TNL_VXLAN))
   5757			return -EIO;
   5758		break;
   5759	case ICE_SW_TUN_GENEVE:
   5760		if (!ice_get_open_tunnel_port(hw, &open_port, TNL_GENEVE))
   5761			return -EIO;
   5762		break;
   5763	default:
   5764		/* Nothing needs to be done for this tunnel type */
   5765		return 0;
   5766	}
   5767
   5768	/* Find the outer UDP protocol header and insert the port number */
   5769	for (i = 0; offsets[i].type != ICE_PROTOCOL_LAST; i++) {
   5770		if (offsets[i].type == ICE_UDP_OF) {
   5771			struct ice_l4_hdr *hdr;
   5772			u16 offset;
   5773
   5774			offset = offsets[i].offset;
   5775			hdr = (struct ice_l4_hdr *)&pkt[offset];
   5776			hdr->dst_port = cpu_to_be16(open_port);
   5777
   5778			return 0;
   5779		}
   5780	}
   5781
   5782	return -EIO;
   5783}
   5784
   5785/**
   5786 * ice_find_adv_rule_entry - Search a rule entry
   5787 * @hw: pointer to the hardware structure
   5788 * @lkups: lookup elements or match criteria for the advanced recipe, one
   5789 *	   structure per protocol header
   5790 * @lkups_cnt: number of protocols
   5791 * @recp_id: recipe ID for which we are finding the rule
   5792 * @rinfo: other information regarding the rule e.g. priority and action info
   5793 *
   5794 * Helper function to search for a given advance rule entry
   5795 * Returns pointer to entry storing the rule if found
   5796 */
   5797static struct ice_adv_fltr_mgmt_list_entry *
   5798ice_find_adv_rule_entry(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
   5799			u16 lkups_cnt, u16 recp_id,
   5800			struct ice_adv_rule_info *rinfo)
   5801{
   5802	struct ice_adv_fltr_mgmt_list_entry *list_itr;
   5803	struct ice_switch_info *sw = hw->switch_info;
   5804	int i;
   5805
   5806	list_for_each_entry(list_itr, &sw->recp_list[recp_id].filt_rules,
   5807			    list_entry) {
   5808		bool lkups_matched = true;
   5809
   5810		if (lkups_cnt != list_itr->lkups_cnt)
   5811			continue;
   5812		for (i = 0; i < list_itr->lkups_cnt; i++)
   5813			if (memcmp(&list_itr->lkups[i], &lkups[i],
   5814				   sizeof(*lkups))) {
   5815				lkups_matched = false;
   5816				break;
   5817			}
   5818		if (rinfo->sw_act.flag == list_itr->rule_info.sw_act.flag &&
   5819		    rinfo->tun_type == list_itr->rule_info.tun_type &&
   5820		    lkups_matched)
   5821			return list_itr;
   5822	}
   5823	return NULL;
   5824}
   5825
   5826/**
   5827 * ice_adv_add_update_vsi_list
   5828 * @hw: pointer to the hardware structure
   5829 * @m_entry: pointer to current adv filter management list entry
   5830 * @cur_fltr: filter information from the book keeping entry
   5831 * @new_fltr: filter information with the new VSI to be added
   5832 *
   5833 * Call AQ command to add or update previously created VSI list with new VSI.
   5834 *
   5835 * Helper function to do book keeping associated with adding filter information
   5836 * The algorithm to do the booking keeping is described below :
   5837 * When a VSI needs to subscribe to a given advanced filter
   5838 *	if only one VSI has been added till now
   5839 *		Allocate a new VSI list and add two VSIs
   5840 *		to this list using switch rule command
   5841 *		Update the previously created switch rule with the
   5842 *		newly created VSI list ID
   5843 *	if a VSI list was previously created
   5844 *		Add the new VSI to the previously created VSI list set
   5845 *		using the update switch rule command
   5846 */
   5847static int
   5848ice_adv_add_update_vsi_list(struct ice_hw *hw,
   5849			    struct ice_adv_fltr_mgmt_list_entry *m_entry,
   5850			    struct ice_adv_rule_info *cur_fltr,
   5851			    struct ice_adv_rule_info *new_fltr)
   5852{
   5853	u16 vsi_list_id = 0;
   5854	int status;
   5855
   5856	if (cur_fltr->sw_act.fltr_act == ICE_FWD_TO_Q ||
   5857	    cur_fltr->sw_act.fltr_act == ICE_FWD_TO_QGRP ||
   5858	    cur_fltr->sw_act.fltr_act == ICE_DROP_PACKET)
   5859		return -EOPNOTSUPP;
   5860
   5861	if ((new_fltr->sw_act.fltr_act == ICE_FWD_TO_Q ||
   5862	     new_fltr->sw_act.fltr_act == ICE_FWD_TO_QGRP) &&
   5863	    (cur_fltr->sw_act.fltr_act == ICE_FWD_TO_VSI ||
   5864	     cur_fltr->sw_act.fltr_act == ICE_FWD_TO_VSI_LIST))
   5865		return -EOPNOTSUPP;
   5866
   5867	if (m_entry->vsi_count < 2 && !m_entry->vsi_list_info) {
   5868		 /* Only one entry existed in the mapping and it was not already
   5869		  * a part of a VSI list. So, create a VSI list with the old and
   5870		  * new VSIs.
   5871		  */
   5872		struct ice_fltr_info tmp_fltr;
   5873		u16 vsi_handle_arr[2];
   5874
   5875		/* A rule already exists with the new VSI being added */
   5876		if (cur_fltr->sw_act.fwd_id.hw_vsi_id ==
   5877		    new_fltr->sw_act.fwd_id.hw_vsi_id)
   5878			return -EEXIST;
   5879
   5880		vsi_handle_arr[0] = cur_fltr->sw_act.vsi_handle;
   5881		vsi_handle_arr[1] = new_fltr->sw_act.vsi_handle;
   5882		status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2,
   5883						  &vsi_list_id,
   5884						  ICE_SW_LKUP_LAST);
   5885		if (status)
   5886			return status;
   5887
   5888		memset(&tmp_fltr, 0, sizeof(tmp_fltr));
   5889		tmp_fltr.flag = m_entry->rule_info.sw_act.flag;
   5890		tmp_fltr.fltr_rule_id = cur_fltr->fltr_rule_id;
   5891		tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST;
   5892		tmp_fltr.fwd_id.vsi_list_id = vsi_list_id;
   5893		tmp_fltr.lkup_type = ICE_SW_LKUP_LAST;
   5894
   5895		/* Update the previous switch rule of "forward to VSI" to
   5896		 * "fwd to VSI list"
   5897		 */
   5898		status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
   5899		if (status)
   5900			return status;
   5901
   5902		cur_fltr->sw_act.fwd_id.vsi_list_id = vsi_list_id;
   5903		cur_fltr->sw_act.fltr_act = ICE_FWD_TO_VSI_LIST;
   5904		m_entry->vsi_list_info =
   5905			ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2,
   5906						vsi_list_id);
   5907	} else {
   5908		u16 vsi_handle = new_fltr->sw_act.vsi_handle;
   5909
   5910		if (!m_entry->vsi_list_info)
   5911			return -EIO;
   5912
   5913		/* A rule already exists with the new VSI being added */
   5914		if (test_bit(vsi_handle, m_entry->vsi_list_info->vsi_map))
   5915			return 0;
   5916
   5917		/* Update the previously created VSI list set with
   5918		 * the new VSI ID passed in
   5919		 */
   5920		vsi_list_id = cur_fltr->sw_act.fwd_id.vsi_list_id;
   5921
   5922		status = ice_update_vsi_list_rule(hw, &vsi_handle, 1,
   5923						  vsi_list_id, false,
   5924						  ice_aqc_opc_update_sw_rules,
   5925						  ICE_SW_LKUP_LAST);
   5926		/* update VSI list mapping info with new VSI ID */
   5927		if (!status)
   5928			set_bit(vsi_handle, m_entry->vsi_list_info->vsi_map);
   5929	}
   5930	if (!status)
   5931		m_entry->vsi_count++;
   5932	return status;
   5933}
   5934
   5935/**
   5936 * ice_add_adv_rule - helper function to create an advanced switch rule
   5937 * @hw: pointer to the hardware structure
   5938 * @lkups: information on the words that needs to be looked up. All words
   5939 * together makes one recipe
   5940 * @lkups_cnt: num of entries in the lkups array
   5941 * @rinfo: other information related to the rule that needs to be programmed
   5942 * @added_entry: this will return recipe_id, rule_id and vsi_handle. should be
   5943 *               ignored is case of error.
   5944 *
   5945 * This function can program only 1 rule at a time. The lkups is used to
   5946 * describe the all the words that forms the "lookup" portion of the recipe.
   5947 * These words can span multiple protocols. Callers to this function need to
   5948 * pass in a list of protocol headers with lookup information along and mask
   5949 * that determines which words are valid from the given protocol header.
   5950 * rinfo describes other information related to this rule such as forwarding
   5951 * IDs, priority of this rule, etc.
   5952 */
   5953int
   5954ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
   5955		 u16 lkups_cnt, struct ice_adv_rule_info *rinfo,
   5956		 struct ice_rule_query_data *added_entry)
   5957{
   5958	struct ice_adv_fltr_mgmt_list_entry *m_entry, *adv_fltr = NULL;
   5959	struct ice_sw_rule_lkup_rx_tx *s_rule = NULL;
   5960	const struct ice_dummy_pkt_profile *profile;
   5961	u16 rid = 0, i, rule_buf_sz, vsi_handle;
   5962	struct list_head *rule_head;
   5963	struct ice_switch_info *sw;
   5964	u16 word_cnt;
   5965	u32 act = 0;
   5966	int status;
   5967	u8 q_rgn;
   5968
   5969	/* Initialize profile to result index bitmap */
   5970	if (!hw->switch_info->prof_res_bm_init) {
   5971		hw->switch_info->prof_res_bm_init = 1;
   5972		ice_init_prof_result_bm(hw);
   5973	}
   5974
   5975	if (!lkups_cnt)
   5976		return -EINVAL;
   5977
   5978	/* get # of words we need to match */
   5979	word_cnt = 0;
   5980	for (i = 0; i < lkups_cnt; i++) {
   5981		u16 j;
   5982
   5983		for (j = 0; j < ARRAY_SIZE(lkups->m_raw); j++)
   5984			if (lkups[i].m_raw[j])
   5985				word_cnt++;
   5986	}
   5987
   5988	if (!word_cnt)
   5989		return -EINVAL;
   5990
   5991	if (word_cnt > ICE_MAX_CHAIN_WORDS)
   5992		return -ENOSPC;
   5993
   5994	/* locate a dummy packet */
   5995	profile = ice_find_dummy_packet(lkups, lkups_cnt, rinfo->tun_type);
   5996
   5997	if (!(rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI ||
   5998	      rinfo->sw_act.fltr_act == ICE_FWD_TO_Q ||
   5999	      rinfo->sw_act.fltr_act == ICE_FWD_TO_QGRP ||
   6000	      rinfo->sw_act.fltr_act == ICE_DROP_PACKET))
   6001		return -EIO;
   6002
   6003	vsi_handle = rinfo->sw_act.vsi_handle;
   6004	if (!ice_is_vsi_valid(hw, vsi_handle))
   6005		return -EINVAL;
   6006
   6007	if (rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI)
   6008		rinfo->sw_act.fwd_id.hw_vsi_id =
   6009			ice_get_hw_vsi_num(hw, vsi_handle);
   6010	if (rinfo->sw_act.flag & ICE_FLTR_TX)
   6011		rinfo->sw_act.src = ice_get_hw_vsi_num(hw, vsi_handle);
   6012
   6013	status = ice_add_adv_recipe(hw, lkups, lkups_cnt, rinfo, &rid);
   6014	if (status)
   6015		return status;
   6016	m_entry = ice_find_adv_rule_entry(hw, lkups, lkups_cnt, rid, rinfo);
   6017	if (m_entry) {
   6018		/* we have to add VSI to VSI_LIST and increment vsi_count.
   6019		 * Also Update VSI list so that we can change forwarding rule
   6020		 * if the rule already exists, we will check if it exists with
   6021		 * same vsi_id, if not then add it to the VSI list if it already
   6022		 * exists if not then create a VSI list and add the existing VSI
   6023		 * ID and the new VSI ID to the list
   6024		 * We will add that VSI to the list
   6025		 */
   6026		status = ice_adv_add_update_vsi_list(hw, m_entry,
   6027						     &m_entry->rule_info,
   6028						     rinfo);
   6029		if (added_entry) {
   6030			added_entry->rid = rid;
   6031			added_entry->rule_id = m_entry->rule_info.fltr_rule_id;
   6032			added_entry->vsi_handle = rinfo->sw_act.vsi_handle;
   6033		}
   6034		return status;
   6035	}
   6036	rule_buf_sz = ICE_SW_RULE_RX_TX_HDR_SIZE(s_rule, profile->pkt_len);
   6037	s_rule = kzalloc(rule_buf_sz, GFP_KERNEL);
   6038	if (!s_rule)
   6039		return -ENOMEM;
   6040	if (!rinfo->flags_info.act_valid) {
   6041		act |= ICE_SINGLE_ACT_LAN_ENABLE;
   6042		act |= ICE_SINGLE_ACT_LB_ENABLE;
   6043	} else {
   6044		act |= rinfo->flags_info.act & (ICE_SINGLE_ACT_LAN_ENABLE |
   6045						ICE_SINGLE_ACT_LB_ENABLE);
   6046	}
   6047
   6048	switch (rinfo->sw_act.fltr_act) {
   6049	case ICE_FWD_TO_VSI:
   6050		act |= (rinfo->sw_act.fwd_id.hw_vsi_id <<
   6051			ICE_SINGLE_ACT_VSI_ID_S) & ICE_SINGLE_ACT_VSI_ID_M;
   6052		act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_VALID_BIT;
   6053		break;
   6054	case ICE_FWD_TO_Q:
   6055		act |= ICE_SINGLE_ACT_TO_Q;
   6056		act |= (rinfo->sw_act.fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) &
   6057		       ICE_SINGLE_ACT_Q_INDEX_M;
   6058		break;
   6059	case ICE_FWD_TO_QGRP:
   6060		q_rgn = rinfo->sw_act.qgrp_size > 0 ?
   6061			(u8)ilog2(rinfo->sw_act.qgrp_size) : 0;
   6062		act |= ICE_SINGLE_ACT_TO_Q;
   6063		act |= (rinfo->sw_act.fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) &
   6064		       ICE_SINGLE_ACT_Q_INDEX_M;
   6065		act |= (q_rgn << ICE_SINGLE_ACT_Q_REGION_S) &
   6066		       ICE_SINGLE_ACT_Q_REGION_M;
   6067		break;
   6068	case ICE_DROP_PACKET:
   6069		act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_DROP |
   6070		       ICE_SINGLE_ACT_VALID_BIT;
   6071		break;
   6072	default:
   6073		status = -EIO;
   6074		goto err_ice_add_adv_rule;
   6075	}
   6076
   6077	/* set the rule LOOKUP type based on caller specified 'Rx'
   6078	 * instead of hardcoding it to be either LOOKUP_TX/RX
   6079	 *
   6080	 * for 'Rx' set the source to be the port number
   6081	 * for 'Tx' set the source to be the source HW VSI number (determined
   6082	 * by caller)
   6083	 */
   6084	if (rinfo->rx) {
   6085		s_rule->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_RX);
   6086		s_rule->src = cpu_to_le16(hw->port_info->lport);
   6087	} else {
   6088		s_rule->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_TX);
   6089		s_rule->src = cpu_to_le16(rinfo->sw_act.src);
   6090	}
   6091
   6092	s_rule->recipe_id = cpu_to_le16(rid);
   6093	s_rule->act = cpu_to_le32(act);
   6094
   6095	status = ice_fill_adv_dummy_packet(lkups, lkups_cnt, s_rule, profile);
   6096	if (status)
   6097		goto err_ice_add_adv_rule;
   6098
   6099	if (rinfo->tun_type != ICE_NON_TUN &&
   6100	    rinfo->tun_type != ICE_SW_TUN_AND_NON_TUN) {
   6101		status = ice_fill_adv_packet_tun(hw, rinfo->tun_type,
   6102						 s_rule->hdr_data,
   6103						 profile->offsets);
   6104		if (status)
   6105			goto err_ice_add_adv_rule;
   6106	}
   6107
   6108	status = ice_aq_sw_rules(hw, (struct ice_aqc_sw_rules *)s_rule,
   6109				 rule_buf_sz, 1, ice_aqc_opc_add_sw_rules,
   6110				 NULL);
   6111	if (status)
   6112		goto err_ice_add_adv_rule;
   6113	adv_fltr = devm_kzalloc(ice_hw_to_dev(hw),
   6114				sizeof(struct ice_adv_fltr_mgmt_list_entry),
   6115				GFP_KERNEL);
   6116	if (!adv_fltr) {
   6117		status = -ENOMEM;
   6118		goto err_ice_add_adv_rule;
   6119	}
   6120
   6121	adv_fltr->lkups = devm_kmemdup(ice_hw_to_dev(hw), lkups,
   6122				       lkups_cnt * sizeof(*lkups), GFP_KERNEL);
   6123	if (!adv_fltr->lkups) {
   6124		status = -ENOMEM;
   6125		goto err_ice_add_adv_rule;
   6126	}
   6127
   6128	adv_fltr->lkups_cnt = lkups_cnt;
   6129	adv_fltr->rule_info = *rinfo;
   6130	adv_fltr->rule_info.fltr_rule_id = le16_to_cpu(s_rule->index);
   6131	sw = hw->switch_info;
   6132	sw->recp_list[rid].adv_rule = true;
   6133	rule_head = &sw->recp_list[rid].filt_rules;
   6134
   6135	if (rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI)
   6136		adv_fltr->vsi_count = 1;
   6137
   6138	/* Add rule entry to book keeping list */
   6139	list_add(&adv_fltr->list_entry, rule_head);
   6140	if (added_entry) {
   6141		added_entry->rid = rid;
   6142		added_entry->rule_id = adv_fltr->rule_info.fltr_rule_id;
   6143		added_entry->vsi_handle = rinfo->sw_act.vsi_handle;
   6144	}
   6145err_ice_add_adv_rule:
   6146	if (status && adv_fltr) {
   6147		devm_kfree(ice_hw_to_dev(hw), adv_fltr->lkups);
   6148		devm_kfree(ice_hw_to_dev(hw), adv_fltr);
   6149	}
   6150
   6151	kfree(s_rule);
   6152
   6153	return status;
   6154}
   6155
   6156/**
   6157 * ice_replay_vsi_fltr - Replay filters for requested VSI
   6158 * @hw: pointer to the hardware structure
   6159 * @vsi_handle: driver VSI handle
   6160 * @recp_id: Recipe ID for which rules need to be replayed
   6161 * @list_head: list for which filters need to be replayed
   6162 *
   6163 * Replays the filter of recipe recp_id for a VSI represented via vsi_handle.
   6164 * It is required to pass valid VSI handle.
   6165 */
   6166static int
   6167ice_replay_vsi_fltr(struct ice_hw *hw, u16 vsi_handle, u8 recp_id,
   6168		    struct list_head *list_head)
   6169{
   6170	struct ice_fltr_mgmt_list_entry *itr;
   6171	int status = 0;
   6172	u16 hw_vsi_id;
   6173
   6174	if (list_empty(list_head))
   6175		return status;
   6176	hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
   6177
   6178	list_for_each_entry(itr, list_head, list_entry) {
   6179		struct ice_fltr_list_entry f_entry;
   6180
   6181		f_entry.fltr_info = itr->fltr_info;
   6182		if (itr->vsi_count < 2 && recp_id != ICE_SW_LKUP_VLAN &&
   6183		    itr->fltr_info.vsi_handle == vsi_handle) {
   6184			/* update the src in case it is VSI num */
   6185			if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI)
   6186				f_entry.fltr_info.src = hw_vsi_id;
   6187			status = ice_add_rule_internal(hw, recp_id, &f_entry);
   6188			if (status)
   6189				goto end;
   6190			continue;
   6191		}
   6192		if (!itr->vsi_list_info ||
   6193		    !test_bit(vsi_handle, itr->vsi_list_info->vsi_map))
   6194			continue;
   6195		/* Clearing it so that the logic can add it back */
   6196		clear_bit(vsi_handle, itr->vsi_list_info->vsi_map);
   6197		f_entry.fltr_info.vsi_handle = vsi_handle;
   6198		f_entry.fltr_info.fltr_act = ICE_FWD_TO_VSI;
   6199		/* update the src in case it is VSI num */
   6200		if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI)
   6201			f_entry.fltr_info.src = hw_vsi_id;
   6202		if (recp_id == ICE_SW_LKUP_VLAN)
   6203			status = ice_add_vlan_internal(hw, &f_entry);
   6204		else
   6205			status = ice_add_rule_internal(hw, recp_id, &f_entry);
   6206		if (status)
   6207			goto end;
   6208	}
   6209end:
   6210	return status;
   6211}
   6212
   6213/**
   6214 * ice_adv_rem_update_vsi_list
   6215 * @hw: pointer to the hardware structure
   6216 * @vsi_handle: VSI handle of the VSI to remove
   6217 * @fm_list: filter management entry for which the VSI list management needs to
   6218 *	     be done
   6219 */
   6220static int
   6221ice_adv_rem_update_vsi_list(struct ice_hw *hw, u16 vsi_handle,
   6222			    struct ice_adv_fltr_mgmt_list_entry *fm_list)
   6223{
   6224	struct ice_vsi_list_map_info *vsi_list_info;
   6225	enum ice_sw_lkup_type lkup_type;
   6226	u16 vsi_list_id;
   6227	int status;
   6228
   6229	if (fm_list->rule_info.sw_act.fltr_act != ICE_FWD_TO_VSI_LIST ||
   6230	    fm_list->vsi_count == 0)
   6231		return -EINVAL;
   6232
   6233	/* A rule with the VSI being removed does not exist */
   6234	if (!test_bit(vsi_handle, fm_list->vsi_list_info->vsi_map))
   6235		return -ENOENT;
   6236
   6237	lkup_type = ICE_SW_LKUP_LAST;
   6238	vsi_list_id = fm_list->rule_info.sw_act.fwd_id.vsi_list_id;
   6239	status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, vsi_list_id, true,
   6240					  ice_aqc_opc_update_sw_rules,
   6241					  lkup_type);
   6242	if (status)
   6243		return status;
   6244
   6245	fm_list->vsi_count--;
   6246	clear_bit(vsi_handle, fm_list->vsi_list_info->vsi_map);
   6247	vsi_list_info = fm_list->vsi_list_info;
   6248	if (fm_list->vsi_count == 1) {
   6249		struct ice_fltr_info tmp_fltr;
   6250		u16 rem_vsi_handle;
   6251
   6252		rem_vsi_handle = find_first_bit(vsi_list_info->vsi_map,
   6253						ICE_MAX_VSI);
   6254		if (!ice_is_vsi_valid(hw, rem_vsi_handle))
   6255			return -EIO;
   6256
   6257		/* Make sure VSI list is empty before removing it below */
   6258		status = ice_update_vsi_list_rule(hw, &rem_vsi_handle, 1,
   6259						  vsi_list_id, true,
   6260						  ice_aqc_opc_update_sw_rules,
   6261						  lkup_type);
   6262		if (status)
   6263			return status;
   6264
   6265		memset(&tmp_fltr, 0, sizeof(tmp_fltr));
   6266		tmp_fltr.flag = fm_list->rule_info.sw_act.flag;
   6267		tmp_fltr.fltr_rule_id = fm_list->rule_info.fltr_rule_id;
   6268		fm_list->rule_info.sw_act.fltr_act = ICE_FWD_TO_VSI;
   6269		tmp_fltr.fltr_act = ICE_FWD_TO_VSI;
   6270		tmp_fltr.fwd_id.hw_vsi_id =
   6271			ice_get_hw_vsi_num(hw, rem_vsi_handle);
   6272		fm_list->rule_info.sw_act.fwd_id.hw_vsi_id =
   6273			ice_get_hw_vsi_num(hw, rem_vsi_handle);
   6274		fm_list->rule_info.sw_act.vsi_handle = rem_vsi_handle;
   6275
   6276		/* Update the previous switch rule of "MAC forward to VSI" to
   6277		 * "MAC fwd to VSI list"
   6278		 */
   6279		status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
   6280		if (status) {
   6281			ice_debug(hw, ICE_DBG_SW, "Failed to update pkt fwd rule to FWD_TO_VSI on HW VSI %d, error %d\n",
   6282				  tmp_fltr.fwd_id.hw_vsi_id, status);
   6283			return status;
   6284		}
   6285		fm_list->vsi_list_info->ref_cnt--;
   6286
   6287		/* Remove the VSI list since it is no longer used */
   6288		status = ice_remove_vsi_list_rule(hw, vsi_list_id, lkup_type);
   6289		if (status) {
   6290			ice_debug(hw, ICE_DBG_SW, "Failed to remove VSI list %d, error %d\n",
   6291				  vsi_list_id, status);
   6292			return status;
   6293		}
   6294
   6295		list_del(&vsi_list_info->list_entry);
   6296		devm_kfree(ice_hw_to_dev(hw), vsi_list_info);
   6297		fm_list->vsi_list_info = NULL;
   6298	}
   6299
   6300	return status;
   6301}
   6302
   6303/**
   6304 * ice_rem_adv_rule - removes existing advanced switch rule
   6305 * @hw: pointer to the hardware structure
   6306 * @lkups: information on the words that needs to be looked up. All words
   6307 *         together makes one recipe
   6308 * @lkups_cnt: num of entries in the lkups array
   6309 * @rinfo: Its the pointer to the rule information for the rule
   6310 *
   6311 * This function can be used to remove 1 rule at a time. The lkups is
   6312 * used to describe all the words that forms the "lookup" portion of the
   6313 * rule. These words can span multiple protocols. Callers to this function
   6314 * need to pass in a list of protocol headers with lookup information along
   6315 * and mask that determines which words are valid from the given protocol
   6316 * header. rinfo describes other information related to this rule such as
   6317 * forwarding IDs, priority of this rule, etc.
   6318 */
   6319static int
   6320ice_rem_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
   6321		 u16 lkups_cnt, struct ice_adv_rule_info *rinfo)
   6322{
   6323	struct ice_adv_fltr_mgmt_list_entry *list_elem;
   6324	struct ice_prot_lkup_ext lkup_exts;
   6325	bool remove_rule = false;
   6326	struct mutex *rule_lock; /* Lock to protect filter rule list */
   6327	u16 i, rid, vsi_handle;
   6328	int status = 0;
   6329
   6330	memset(&lkup_exts, 0, sizeof(lkup_exts));
   6331	for (i = 0; i < lkups_cnt; i++) {
   6332		u16 count;
   6333
   6334		if (lkups[i].type >= ICE_PROTOCOL_LAST)
   6335			return -EIO;
   6336
   6337		count = ice_fill_valid_words(&lkups[i], &lkup_exts);
   6338		if (!count)
   6339			return -EIO;
   6340	}
   6341
   6342	/* Create any special protocol/offset pairs, such as looking at tunnel
   6343	 * bits by extracting metadata
   6344	 */
   6345	status = ice_add_special_words(rinfo, &lkup_exts);
   6346	if (status)
   6347		return status;
   6348
   6349	rid = ice_find_recp(hw, &lkup_exts, rinfo->tun_type);
   6350	/* If did not find a recipe that match the existing criteria */
   6351	if (rid == ICE_MAX_NUM_RECIPES)
   6352		return -EINVAL;
   6353
   6354	rule_lock = &hw->switch_info->recp_list[rid].filt_rule_lock;
   6355	list_elem = ice_find_adv_rule_entry(hw, lkups, lkups_cnt, rid, rinfo);
   6356	/* the rule is already removed */
   6357	if (!list_elem)
   6358		return 0;
   6359	mutex_lock(rule_lock);
   6360	if (list_elem->rule_info.sw_act.fltr_act != ICE_FWD_TO_VSI_LIST) {
   6361		remove_rule = true;
   6362	} else if (list_elem->vsi_count > 1) {
   6363		remove_rule = false;
   6364		vsi_handle = rinfo->sw_act.vsi_handle;
   6365		status = ice_adv_rem_update_vsi_list(hw, vsi_handle, list_elem);
   6366	} else {
   6367		vsi_handle = rinfo->sw_act.vsi_handle;
   6368		status = ice_adv_rem_update_vsi_list(hw, vsi_handle, list_elem);
   6369		if (status) {
   6370			mutex_unlock(rule_lock);
   6371			return status;
   6372		}
   6373		if (list_elem->vsi_count == 0)
   6374			remove_rule = true;
   6375	}
   6376	mutex_unlock(rule_lock);
   6377	if (remove_rule) {
   6378		struct ice_sw_rule_lkup_rx_tx *s_rule;
   6379		u16 rule_buf_sz;
   6380
   6381		rule_buf_sz = ICE_SW_RULE_RX_TX_NO_HDR_SIZE(s_rule);
   6382		s_rule = kzalloc(rule_buf_sz, GFP_KERNEL);
   6383		if (!s_rule)
   6384			return -ENOMEM;
   6385		s_rule->act = 0;
   6386		s_rule->index = cpu_to_le16(list_elem->rule_info.fltr_rule_id);
   6387		s_rule->hdr_len = 0;
   6388		status = ice_aq_sw_rules(hw, (struct ice_aqc_sw_rules *)s_rule,
   6389					 rule_buf_sz, 1,
   6390					 ice_aqc_opc_remove_sw_rules, NULL);
   6391		if (!status || status == -ENOENT) {
   6392			struct ice_switch_info *sw = hw->switch_info;
   6393
   6394			mutex_lock(rule_lock);
   6395			list_del(&list_elem->list_entry);
   6396			devm_kfree(ice_hw_to_dev(hw), list_elem->lkups);
   6397			devm_kfree(ice_hw_to_dev(hw), list_elem);
   6398			mutex_unlock(rule_lock);
   6399			if (list_empty(&sw->recp_list[rid].filt_rules))
   6400				sw->recp_list[rid].adv_rule = false;
   6401		}
   6402		kfree(s_rule);
   6403	}
   6404	return status;
   6405}
   6406
   6407/**
   6408 * ice_rem_adv_rule_by_id - removes existing advanced switch rule by ID
   6409 * @hw: pointer to the hardware structure
   6410 * @remove_entry: data struct which holds rule_id, VSI handle and recipe ID
   6411 *
   6412 * This function is used to remove 1 rule at a time. The removal is based on
   6413 * the remove_entry parameter. This function will remove rule for a given
   6414 * vsi_handle with a given rule_id which is passed as parameter in remove_entry
   6415 */
   6416int
   6417ice_rem_adv_rule_by_id(struct ice_hw *hw,
   6418		       struct ice_rule_query_data *remove_entry)
   6419{
   6420	struct ice_adv_fltr_mgmt_list_entry *list_itr;
   6421	struct list_head *list_head;
   6422	struct ice_adv_rule_info rinfo;
   6423	struct ice_switch_info *sw;
   6424
   6425	sw = hw->switch_info;
   6426	if (!sw->recp_list[remove_entry->rid].recp_created)
   6427		return -EINVAL;
   6428	list_head = &sw->recp_list[remove_entry->rid].filt_rules;
   6429	list_for_each_entry(list_itr, list_head, list_entry) {
   6430		if (list_itr->rule_info.fltr_rule_id ==
   6431		    remove_entry->rule_id) {
   6432			rinfo = list_itr->rule_info;
   6433			rinfo.sw_act.vsi_handle = remove_entry->vsi_handle;
   6434			return ice_rem_adv_rule(hw, list_itr->lkups,
   6435						list_itr->lkups_cnt, &rinfo);
   6436		}
   6437	}
   6438	/* either list is empty or unable to find rule */
   6439	return -ENOENT;
   6440}
   6441
   6442/**
   6443 * ice_rem_adv_rule_for_vsi - removes existing advanced switch rules for a
   6444 *                            given VSI handle
   6445 * @hw: pointer to the hardware structure
   6446 * @vsi_handle: VSI handle for which we are supposed to remove all the rules.
   6447 *
   6448 * This function is used to remove all the rules for a given VSI and as soon
   6449 * as removing a rule fails, it will return immediately with the error code,
   6450 * else it will return success.
   6451 */
   6452int ice_rem_adv_rule_for_vsi(struct ice_hw *hw, u16 vsi_handle)
   6453{
   6454	struct ice_adv_fltr_mgmt_list_entry *list_itr, *tmp_entry;
   6455	struct ice_vsi_list_map_info *map_info;
   6456	struct ice_adv_rule_info rinfo;
   6457	struct list_head *list_head;
   6458	struct ice_switch_info *sw;
   6459	int status;
   6460	u8 rid;
   6461
   6462	sw = hw->switch_info;
   6463	for (rid = 0; rid < ICE_MAX_NUM_RECIPES; rid++) {
   6464		if (!sw->recp_list[rid].recp_created)
   6465			continue;
   6466		if (!sw->recp_list[rid].adv_rule)
   6467			continue;
   6468
   6469		list_head = &sw->recp_list[rid].filt_rules;
   6470		list_for_each_entry_safe(list_itr, tmp_entry, list_head,
   6471					 list_entry) {
   6472			rinfo = list_itr->rule_info;
   6473
   6474			if (rinfo.sw_act.fltr_act == ICE_FWD_TO_VSI_LIST) {
   6475				map_info = list_itr->vsi_list_info;
   6476				if (!map_info)
   6477					continue;
   6478
   6479				if (!test_bit(vsi_handle, map_info->vsi_map))
   6480					continue;
   6481			} else if (rinfo.sw_act.vsi_handle != vsi_handle) {
   6482				continue;
   6483			}
   6484
   6485			rinfo.sw_act.vsi_handle = vsi_handle;
   6486			status = ice_rem_adv_rule(hw, list_itr->lkups,
   6487						  list_itr->lkups_cnt, &rinfo);
   6488			if (status)
   6489				return status;
   6490		}
   6491	}
   6492	return 0;
   6493}
   6494
   6495/**
   6496 * ice_replay_vsi_adv_rule - Replay advanced rule for requested VSI
   6497 * @hw: pointer to the hardware structure
   6498 * @vsi_handle: driver VSI handle
   6499 * @list_head: list for which filters need to be replayed
   6500 *
   6501 * Replay the advanced rule for the given VSI.
   6502 */
   6503static int
   6504ice_replay_vsi_adv_rule(struct ice_hw *hw, u16 vsi_handle,
   6505			struct list_head *list_head)
   6506{
   6507	struct ice_rule_query_data added_entry = { 0 };
   6508	struct ice_adv_fltr_mgmt_list_entry *adv_fltr;
   6509	int status = 0;
   6510
   6511	if (list_empty(list_head))
   6512		return status;
   6513	list_for_each_entry(adv_fltr, list_head, list_entry) {
   6514		struct ice_adv_rule_info *rinfo = &adv_fltr->rule_info;
   6515		u16 lk_cnt = adv_fltr->lkups_cnt;
   6516
   6517		if (vsi_handle != rinfo->sw_act.vsi_handle)
   6518			continue;
   6519		status = ice_add_adv_rule(hw, adv_fltr->lkups, lk_cnt, rinfo,
   6520					  &added_entry);
   6521		if (status)
   6522			break;
   6523	}
   6524	return status;
   6525}
   6526
   6527/**
   6528 * ice_replay_vsi_all_fltr - replay all filters stored in bookkeeping lists
   6529 * @hw: pointer to the hardware structure
   6530 * @vsi_handle: driver VSI handle
   6531 *
   6532 * Replays filters for requested VSI via vsi_handle.
   6533 */
   6534int ice_replay_vsi_all_fltr(struct ice_hw *hw, u16 vsi_handle)
   6535{
   6536	struct ice_switch_info *sw = hw->switch_info;
   6537	int status;
   6538	u8 i;
   6539
   6540	for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
   6541		struct list_head *head;
   6542
   6543		head = &sw->recp_list[i].filt_replay_rules;
   6544		if (!sw->recp_list[i].adv_rule)
   6545			status = ice_replay_vsi_fltr(hw, vsi_handle, i, head);
   6546		else
   6547			status = ice_replay_vsi_adv_rule(hw, vsi_handle, head);
   6548		if (status)
   6549			return status;
   6550	}
   6551	return status;
   6552}
   6553
   6554/**
   6555 * ice_rm_all_sw_replay_rule_info - deletes filter replay rules
   6556 * @hw: pointer to the HW struct
   6557 *
   6558 * Deletes the filter replay rules.
   6559 */
   6560void ice_rm_all_sw_replay_rule_info(struct ice_hw *hw)
   6561{
   6562	struct ice_switch_info *sw = hw->switch_info;
   6563	u8 i;
   6564
   6565	if (!sw)
   6566		return;
   6567
   6568	for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
   6569		if (!list_empty(&sw->recp_list[i].filt_replay_rules)) {
   6570			struct list_head *l_head;
   6571
   6572			l_head = &sw->recp_list[i].filt_replay_rules;
   6573			if (!sw->recp_list[i].adv_rule)
   6574				ice_rem_sw_rule_info(hw, l_head);
   6575			else
   6576				ice_rem_adv_rule_info(hw, l_head);
   6577		}
   6578	}
   6579}