1bf93bf79SJacob Keller // SPDX-License-Identifier: GPL-2.0
2bf93bf79SJacob Keller /* Copyright (C) 2022, Intel Corporation. */
3bf93bf79SJacob Keller 
4bf93bf79SJacob Keller #include "ice_virtchnl.h"
5bf93bf79SJacob Keller #include "ice_vf_lib_private.h"
6bf93bf79SJacob Keller #include "ice.h"
7bf93bf79SJacob Keller #include "ice_base.h"
8bf93bf79SJacob Keller #include "ice_lib.h"
9bf93bf79SJacob Keller #include "ice_fltr.h"
10bf93bf79SJacob Keller #include "ice_virtchnl_allowlist.h"
11bf93bf79SJacob Keller #include "ice_vf_vsi_vlan_ops.h"
12bf93bf79SJacob Keller #include "ice_vlan.h"
13bf93bf79SJacob Keller #include "ice_flex_pipe.h"
14bf93bf79SJacob Keller #include "ice_dcb_lib.h"
15bf93bf79SJacob Keller 
16bf93bf79SJacob Keller #define FIELD_SELECTOR(proto_hdr_field) \
17bf93bf79SJacob Keller 		BIT((proto_hdr_field) & PROTO_HDR_FIELD_MASK)
18bf93bf79SJacob Keller 
19bf93bf79SJacob Keller struct ice_vc_hdr_match_type {
20bf93bf79SJacob Keller 	u32 vc_hdr;	/* virtchnl headers (VIRTCHNL_PROTO_HDR_XXX) */
21bf93bf79SJacob Keller 	u32 ice_hdr;	/* ice headers (ICE_FLOW_SEG_HDR_XXX) */
22bf93bf79SJacob Keller };
23bf93bf79SJacob Keller 
24bf93bf79SJacob Keller static const struct ice_vc_hdr_match_type ice_vc_hdr_list[] = {
25bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_NONE,	ICE_FLOW_SEG_HDR_NONE},
26bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_ETH,	ICE_FLOW_SEG_HDR_ETH},
27bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_S_VLAN,	ICE_FLOW_SEG_HDR_VLAN},
28bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_C_VLAN,	ICE_FLOW_SEG_HDR_VLAN},
29bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_IPV4,	ICE_FLOW_SEG_HDR_IPV4 |
30bf93bf79SJacob Keller 					ICE_FLOW_SEG_HDR_IPV_OTHER},
31bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_IPV6,	ICE_FLOW_SEG_HDR_IPV6 |
32bf93bf79SJacob Keller 					ICE_FLOW_SEG_HDR_IPV_OTHER},
33bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_TCP,	ICE_FLOW_SEG_HDR_TCP},
34bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_UDP,	ICE_FLOW_SEG_HDR_UDP},
35bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_SCTP,	ICE_FLOW_SEG_HDR_SCTP},
36bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_PPPOE,	ICE_FLOW_SEG_HDR_PPPOE},
37bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_GTPU_IP,	ICE_FLOW_SEG_HDR_GTPU_IP},
38bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_GTPU_EH,	ICE_FLOW_SEG_HDR_GTPU_EH},
39bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_GTPU_EH_PDU_DWN,
40bf93bf79SJacob Keller 					ICE_FLOW_SEG_HDR_GTPU_DWN},
41bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_GTPU_EH_PDU_UP,
42bf93bf79SJacob Keller 					ICE_FLOW_SEG_HDR_GTPU_UP},
43bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_L2TPV3,	ICE_FLOW_SEG_HDR_L2TPV3},
44bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_ESP,	ICE_FLOW_SEG_HDR_ESP},
45bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_AH,		ICE_FLOW_SEG_HDR_AH},
46bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_PFCP,	ICE_FLOW_SEG_HDR_PFCP_SESSION},
47bf93bf79SJacob Keller };
48bf93bf79SJacob Keller 
49bf93bf79SJacob Keller struct ice_vc_hash_field_match_type {
50bf93bf79SJacob Keller 	u32 vc_hdr;		/* virtchnl headers
51bf93bf79SJacob Keller 				 * (VIRTCHNL_PROTO_HDR_XXX)
52bf93bf79SJacob Keller 				 */
53bf93bf79SJacob Keller 	u32 vc_hash_field;	/* virtchnl hash fields selector
54bf93bf79SJacob Keller 				 * FIELD_SELECTOR((VIRTCHNL_PROTO_HDR_ETH_XXX))
55bf93bf79SJacob Keller 				 */
56bf93bf79SJacob Keller 	u64 ice_hash_field;	/* ice hash fields
57bf93bf79SJacob Keller 				 * (BIT_ULL(ICE_FLOW_FIELD_IDX_XXX))
58bf93bf79SJacob Keller 				 */
59bf93bf79SJacob Keller };
60bf93bf79SJacob Keller 
61bf93bf79SJacob Keller static const struct
62bf93bf79SJacob Keller ice_vc_hash_field_match_type ice_vc_hash_field_list[] = {
63bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_ETH, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_ETH_SRC),
64bf93bf79SJacob Keller 		BIT_ULL(ICE_FLOW_FIELD_IDX_ETH_SA)},
65bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_ETH, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_ETH_DST),
66bf93bf79SJacob Keller 		BIT_ULL(ICE_FLOW_FIELD_IDX_ETH_DA)},
67bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_ETH, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_ETH_SRC) |
68bf93bf79SJacob Keller 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_ETH_DST),
69bf93bf79SJacob Keller 		ICE_FLOW_HASH_ETH},
70bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_ETH,
71bf93bf79SJacob Keller 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_ETH_ETHERTYPE),
72bf93bf79SJacob Keller 		BIT_ULL(ICE_FLOW_FIELD_IDX_ETH_TYPE)},
73bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_S_VLAN,
74bf93bf79SJacob Keller 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_S_VLAN_ID),
75bf93bf79SJacob Keller 		BIT_ULL(ICE_FLOW_FIELD_IDX_S_VLAN)},
76bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_C_VLAN,
77bf93bf79SJacob Keller 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_C_VLAN_ID),
78bf93bf79SJacob Keller 		BIT_ULL(ICE_FLOW_FIELD_IDX_C_VLAN)},
79bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC),
80bf93bf79SJacob Keller 		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA)},
81bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST),
82bf93bf79SJacob Keller 		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA)},
83bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC) |
84bf93bf79SJacob Keller 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST),
85bf93bf79SJacob Keller 		ICE_FLOW_HASH_IPV4},
86bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC) |
87bf93bf79SJacob Keller 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT),
88bf93bf79SJacob Keller 		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA) |
89bf93bf79SJacob Keller 		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT)},
90bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST) |
91bf93bf79SJacob Keller 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT),
92bf93bf79SJacob Keller 		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA) |
93bf93bf79SJacob Keller 		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT)},
94bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC) |
95bf93bf79SJacob Keller 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST) |
96bf93bf79SJacob Keller 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT),
97bf93bf79SJacob Keller 		ICE_FLOW_HASH_IPV4 | BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT)},
98bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT),
99bf93bf79SJacob Keller 		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT)},
100bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_IPV6, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_SRC),
101bf93bf79SJacob Keller 		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_SA)},
102bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_IPV6, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_DST),
103bf93bf79SJacob Keller 		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_DA)},
104bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_IPV6, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_SRC) |
105bf93bf79SJacob Keller 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_DST),
106bf93bf79SJacob Keller 		ICE_FLOW_HASH_IPV6},
107bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_IPV6, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_SRC) |
108bf93bf79SJacob Keller 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PROT),
109bf93bf79SJacob Keller 		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_SA) |
110bf93bf79SJacob Keller 		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_PROT)},
111bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_IPV6, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_DST) |
112bf93bf79SJacob Keller 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PROT),
113bf93bf79SJacob Keller 		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_DA) |
114bf93bf79SJacob Keller 		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_PROT)},
115bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_IPV6, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_SRC) |
116bf93bf79SJacob Keller 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_DST) |
117bf93bf79SJacob Keller 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PROT),
118bf93bf79SJacob Keller 		ICE_FLOW_HASH_IPV6 | BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_PROT)},
119bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_IPV6, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PROT),
120bf93bf79SJacob Keller 		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_PROT)},
121bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_TCP,
122bf93bf79SJacob Keller 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_TCP_SRC_PORT),
123bf93bf79SJacob Keller 		BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_SRC_PORT)},
124bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_TCP,
125bf93bf79SJacob Keller 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_TCP_DST_PORT),
126bf93bf79SJacob Keller 		BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_DST_PORT)},
127bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_TCP,
128bf93bf79SJacob Keller 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_TCP_SRC_PORT) |
129bf93bf79SJacob Keller 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_TCP_DST_PORT),
130bf93bf79SJacob Keller 		ICE_FLOW_HASH_TCP_PORT},
131bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_UDP,
132bf93bf79SJacob Keller 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_UDP_SRC_PORT),
133bf93bf79SJacob Keller 		BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_SRC_PORT)},
134bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_UDP,
135bf93bf79SJacob Keller 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_UDP_DST_PORT),
136bf93bf79SJacob Keller 		BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_DST_PORT)},
137bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_UDP,
138bf93bf79SJacob Keller 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_UDP_SRC_PORT) |
139bf93bf79SJacob Keller 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_UDP_DST_PORT),
140bf93bf79SJacob Keller 		ICE_FLOW_HASH_UDP_PORT},
141bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_SCTP,
142bf93bf79SJacob Keller 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_SCTP_SRC_PORT),
143bf93bf79SJacob Keller 		BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT)},
144bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_SCTP,
145bf93bf79SJacob Keller 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_SCTP_DST_PORT),
146bf93bf79SJacob Keller 		BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_DST_PORT)},
147bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_SCTP,
148bf93bf79SJacob Keller 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_SCTP_SRC_PORT) |
149bf93bf79SJacob Keller 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_SCTP_DST_PORT),
150bf93bf79SJacob Keller 		ICE_FLOW_HASH_SCTP_PORT},
151bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_PPPOE,
152bf93bf79SJacob Keller 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_PPPOE_SESS_ID),
153bf93bf79SJacob Keller 		BIT_ULL(ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID)},
154bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_GTPU_IP,
155bf93bf79SJacob Keller 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_GTPU_IP_TEID),
156bf93bf79SJacob Keller 		BIT_ULL(ICE_FLOW_FIELD_IDX_GTPU_IP_TEID)},
157bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_L2TPV3,
158bf93bf79SJacob Keller 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_L2TPV3_SESS_ID),
159bf93bf79SJacob Keller 		BIT_ULL(ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID)},
160bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_ESP, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_ESP_SPI),
161bf93bf79SJacob Keller 		BIT_ULL(ICE_FLOW_FIELD_IDX_ESP_SPI)},
162bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_AH, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_AH_SPI),
163bf93bf79SJacob Keller 		BIT_ULL(ICE_FLOW_FIELD_IDX_AH_SPI)},
164bf93bf79SJacob Keller 	{VIRTCHNL_PROTO_HDR_PFCP, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_PFCP_SEID),
165bf93bf79SJacob Keller 		BIT_ULL(ICE_FLOW_FIELD_IDX_PFCP_SEID)},
166bf93bf79SJacob Keller };
167bf93bf79SJacob Keller 
168bf93bf79SJacob Keller /**
169bf93bf79SJacob Keller  * ice_vc_vf_broadcast - Broadcast a message to all VFs on PF
170bf93bf79SJacob Keller  * @pf: pointer to the PF structure
171bf93bf79SJacob Keller  * @v_opcode: operation code
172bf93bf79SJacob Keller  * @v_retval: return value
173bf93bf79SJacob Keller  * @msg: pointer to the msg buffer
174bf93bf79SJacob Keller  * @msglen: msg length
175bf93bf79SJacob Keller  */
176bf93bf79SJacob Keller static void
177bf93bf79SJacob Keller ice_vc_vf_broadcast(struct ice_pf *pf, enum virtchnl_ops v_opcode,
178bf93bf79SJacob Keller 		    enum virtchnl_status_code v_retval, u8 *msg, u16 msglen)
179bf93bf79SJacob Keller {
180bf93bf79SJacob Keller 	struct ice_hw *hw = &pf->hw;
181bf93bf79SJacob Keller 	struct ice_vf *vf;
182bf93bf79SJacob Keller 	unsigned int bkt;
183bf93bf79SJacob Keller 
184bf93bf79SJacob Keller 	mutex_lock(&pf->vfs.table_lock);
185bf93bf79SJacob Keller 	ice_for_each_vf(pf, bkt, vf) {
186bf93bf79SJacob Keller 		/* Not all vfs are enabled so skip the ones that are not */
187bf93bf79SJacob Keller 		if (!test_bit(ICE_VF_STATE_INIT, vf->vf_states) &&
188bf93bf79SJacob Keller 		    !test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states))
189bf93bf79SJacob Keller 			continue;
190bf93bf79SJacob Keller 
191bf93bf79SJacob Keller 		/* Ignore return value on purpose - a given VF may fail, but
192bf93bf79SJacob Keller 		 * we need to keep going and send to all of them
193bf93bf79SJacob Keller 		 */
194bf93bf79SJacob Keller 		ice_aq_send_msg_to_vf(hw, vf->vf_id, v_opcode, v_retval, msg,
195bf93bf79SJacob Keller 				      msglen, NULL);
196bf93bf79SJacob Keller 	}
197bf93bf79SJacob Keller 	mutex_unlock(&pf->vfs.table_lock);
198bf93bf79SJacob Keller }
199bf93bf79SJacob Keller 
200bf93bf79SJacob Keller /**
201bf93bf79SJacob Keller  * ice_set_pfe_link - Set the link speed/status of the virtchnl_pf_event
202bf93bf79SJacob Keller  * @vf: pointer to the VF structure
203bf93bf79SJacob Keller  * @pfe: pointer to the virtchnl_pf_event to set link speed/status for
204bf93bf79SJacob Keller  * @ice_link_speed: link speed specified by ICE_AQ_LINK_SPEED_*
205bf93bf79SJacob Keller  * @link_up: whether or not to set the link up/down
206bf93bf79SJacob Keller  */
207bf93bf79SJacob Keller static void
208bf93bf79SJacob Keller ice_set_pfe_link(struct ice_vf *vf, struct virtchnl_pf_event *pfe,
209bf93bf79SJacob Keller 		 int ice_link_speed, bool link_up)
210bf93bf79SJacob Keller {
211bf93bf79SJacob Keller 	if (vf->driver_caps & VIRTCHNL_VF_CAP_ADV_LINK_SPEED) {
212bf93bf79SJacob Keller 		pfe->event_data.link_event_adv.link_status = link_up;
213bf93bf79SJacob Keller 		/* Speed in Mbps */
214bf93bf79SJacob Keller 		pfe->event_data.link_event_adv.link_speed =
215bf93bf79SJacob Keller 			ice_conv_link_speed_to_virtchnl(true, ice_link_speed);
216bf93bf79SJacob Keller 	} else {
217bf93bf79SJacob Keller 		pfe->event_data.link_event.link_status = link_up;
218bf93bf79SJacob Keller 		/* Legacy method for virtchnl link speeds */
219bf93bf79SJacob Keller 		pfe->event_data.link_event.link_speed =
220bf93bf79SJacob Keller 			(enum virtchnl_link_speed)
221bf93bf79SJacob Keller 			ice_conv_link_speed_to_virtchnl(false, ice_link_speed);
222bf93bf79SJacob Keller 	}
223bf93bf79SJacob Keller }
224bf93bf79SJacob Keller 
225bf93bf79SJacob Keller /**
226bf93bf79SJacob Keller  * ice_vc_notify_vf_link_state - Inform a VF of link status
227bf93bf79SJacob Keller  * @vf: pointer to the VF structure
228bf93bf79SJacob Keller  *
229bf93bf79SJacob Keller  * send a link status message to a single VF
230bf93bf79SJacob Keller  */
231bf93bf79SJacob Keller void ice_vc_notify_vf_link_state(struct ice_vf *vf)
232bf93bf79SJacob Keller {
233bf93bf79SJacob Keller 	struct virtchnl_pf_event pfe = { 0 };
234bf93bf79SJacob Keller 	struct ice_hw *hw = &vf->pf->hw;
235bf93bf79SJacob Keller 
236bf93bf79SJacob Keller 	pfe.event = VIRTCHNL_EVENT_LINK_CHANGE;
237bf93bf79SJacob Keller 	pfe.severity = PF_EVENT_SEVERITY_INFO;
238bf93bf79SJacob Keller 
239bf93bf79SJacob Keller 	if (ice_is_vf_link_up(vf))
240bf93bf79SJacob Keller 		ice_set_pfe_link(vf, &pfe,
241bf93bf79SJacob Keller 				 hw->port_info->phy.link_info.link_speed, true);
242bf93bf79SJacob Keller 	else
243bf93bf79SJacob Keller 		ice_set_pfe_link(vf, &pfe, ICE_AQ_LINK_SPEED_UNKNOWN, false);
244bf93bf79SJacob Keller 
245bf93bf79SJacob Keller 	ice_aq_send_msg_to_vf(hw, vf->vf_id, VIRTCHNL_OP_EVENT,
246bf93bf79SJacob Keller 			      VIRTCHNL_STATUS_SUCCESS, (u8 *)&pfe,
247bf93bf79SJacob Keller 			      sizeof(pfe), NULL);
248bf93bf79SJacob Keller }
249bf93bf79SJacob Keller 
250bf93bf79SJacob Keller /**
251bf93bf79SJacob Keller  * ice_vc_notify_link_state - Inform all VFs on a PF of link status
252bf93bf79SJacob Keller  * @pf: pointer to the PF structure
253bf93bf79SJacob Keller  */
254bf93bf79SJacob Keller void ice_vc_notify_link_state(struct ice_pf *pf)
255bf93bf79SJacob Keller {
256bf93bf79SJacob Keller 	struct ice_vf *vf;
257bf93bf79SJacob Keller 	unsigned int bkt;
258bf93bf79SJacob Keller 
259bf93bf79SJacob Keller 	mutex_lock(&pf->vfs.table_lock);
260bf93bf79SJacob Keller 	ice_for_each_vf(pf, bkt, vf)
261bf93bf79SJacob Keller 		ice_vc_notify_vf_link_state(vf);
262bf93bf79SJacob Keller 	mutex_unlock(&pf->vfs.table_lock);
263bf93bf79SJacob Keller }
264bf93bf79SJacob Keller 
265bf93bf79SJacob Keller /**
266bf93bf79SJacob Keller  * ice_vc_notify_reset - Send pending reset message to all VFs
267bf93bf79SJacob Keller  * @pf: pointer to the PF structure
268bf93bf79SJacob Keller  *
269bf93bf79SJacob Keller  * indicate a pending reset to all VFs on a given PF
270bf93bf79SJacob Keller  */
271bf93bf79SJacob Keller void ice_vc_notify_reset(struct ice_pf *pf)
272bf93bf79SJacob Keller {
273bf93bf79SJacob Keller 	struct virtchnl_pf_event pfe;
274bf93bf79SJacob Keller 
275bf93bf79SJacob Keller 	if (!ice_has_vfs(pf))
276bf93bf79SJacob Keller 		return;
277bf93bf79SJacob Keller 
278bf93bf79SJacob Keller 	pfe.event = VIRTCHNL_EVENT_RESET_IMPENDING;
279bf93bf79SJacob Keller 	pfe.severity = PF_EVENT_SEVERITY_CERTAIN_DOOM;
280bf93bf79SJacob Keller 	ice_vc_vf_broadcast(pf, VIRTCHNL_OP_EVENT, VIRTCHNL_STATUS_SUCCESS,
281bf93bf79SJacob Keller 			    (u8 *)&pfe, sizeof(struct virtchnl_pf_event));
282bf93bf79SJacob Keller }
283bf93bf79SJacob Keller 
284bf93bf79SJacob Keller /**
285bf93bf79SJacob Keller  * ice_vc_send_msg_to_vf - Send message to VF
286bf93bf79SJacob Keller  * @vf: pointer to the VF info
287bf93bf79SJacob Keller  * @v_opcode: virtual channel opcode
288bf93bf79SJacob Keller  * @v_retval: virtual channel return value
289bf93bf79SJacob Keller  * @msg: pointer to the msg buffer
290bf93bf79SJacob Keller  * @msglen: msg length
291bf93bf79SJacob Keller  *
292bf93bf79SJacob Keller  * send msg to VF
293bf93bf79SJacob Keller  */
294bf93bf79SJacob Keller int
295bf93bf79SJacob Keller ice_vc_send_msg_to_vf(struct ice_vf *vf, u32 v_opcode,
296bf93bf79SJacob Keller 		      enum virtchnl_status_code v_retval, u8 *msg, u16 msglen)
297bf93bf79SJacob Keller {
298bf93bf79SJacob Keller 	struct device *dev;
299bf93bf79SJacob Keller 	struct ice_pf *pf;
300bf93bf79SJacob Keller 	int aq_ret;
301bf93bf79SJacob Keller 
302bf93bf79SJacob Keller 	pf = vf->pf;
303bf93bf79SJacob Keller 	dev = ice_pf_to_dev(pf);
304bf93bf79SJacob Keller 
305bf93bf79SJacob Keller 	aq_ret = ice_aq_send_msg_to_vf(&pf->hw, vf->vf_id, v_opcode, v_retval,
306bf93bf79SJacob Keller 				       msg, msglen, NULL);
307bf93bf79SJacob Keller 	if (aq_ret && pf->hw.mailboxq.sq_last_status != ICE_AQ_RC_ENOSYS) {
308bf93bf79SJacob Keller 		dev_info(dev, "Unable to send the message to VF %d ret %d aq_err %s\n",
309bf93bf79SJacob Keller 			 vf->vf_id, aq_ret,
310bf93bf79SJacob Keller 			 ice_aq_str(pf->hw.mailboxq.sq_last_status));
311bf93bf79SJacob Keller 		return -EIO;
312bf93bf79SJacob Keller 	}
313bf93bf79SJacob Keller 
314bf93bf79SJacob Keller 	return 0;
315bf93bf79SJacob Keller }
316bf93bf79SJacob Keller 
317bf93bf79SJacob Keller /**
318bf93bf79SJacob Keller  * ice_vc_get_ver_msg
319bf93bf79SJacob Keller  * @vf: pointer to the VF info
320bf93bf79SJacob Keller  * @msg: pointer to the msg buffer
321bf93bf79SJacob Keller  *
322bf93bf79SJacob Keller  * called from the VF to request the API version used by the PF
323bf93bf79SJacob Keller  */
324bf93bf79SJacob Keller static int ice_vc_get_ver_msg(struct ice_vf *vf, u8 *msg)
325bf93bf79SJacob Keller {
326bf93bf79SJacob Keller 	struct virtchnl_version_info info = {
327bf93bf79SJacob Keller 		VIRTCHNL_VERSION_MAJOR, VIRTCHNL_VERSION_MINOR
328bf93bf79SJacob Keller 	};
329bf93bf79SJacob Keller 
330bf93bf79SJacob Keller 	vf->vf_ver = *(struct virtchnl_version_info *)msg;
331bf93bf79SJacob Keller 	/* VFs running the 1.0 API expect to get 1.0 back or they will cry. */
332bf93bf79SJacob Keller 	if (VF_IS_V10(&vf->vf_ver))
333bf93bf79SJacob Keller 		info.minor = VIRTCHNL_VERSION_MINOR_NO_VF_CAPS;
334bf93bf79SJacob Keller 
335bf93bf79SJacob Keller 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_VERSION,
336bf93bf79SJacob Keller 				     VIRTCHNL_STATUS_SUCCESS, (u8 *)&info,
337bf93bf79SJacob Keller 				     sizeof(struct virtchnl_version_info));
338bf93bf79SJacob Keller }
339bf93bf79SJacob Keller 
340bf93bf79SJacob Keller /**
341bf93bf79SJacob Keller  * ice_vc_get_max_frame_size - get max frame size allowed for VF
342bf93bf79SJacob Keller  * @vf: VF used to determine max frame size
343bf93bf79SJacob Keller  *
344bf93bf79SJacob Keller  * Max frame size is determined based on the current port's max frame size and
345bf93bf79SJacob Keller  * whether a port VLAN is configured on this VF. The VF is not aware whether
346bf93bf79SJacob Keller  * it's in a port VLAN so the PF needs to account for this in max frame size
347bf93bf79SJacob Keller  * checks and sending the max frame size to the VF.
348bf93bf79SJacob Keller  */
349bf93bf79SJacob Keller static u16 ice_vc_get_max_frame_size(struct ice_vf *vf)
350bf93bf79SJacob Keller {
351bf93bf79SJacob Keller 	struct ice_port_info *pi = ice_vf_get_port_info(vf);
352bf93bf79SJacob Keller 	u16 max_frame_size;
353bf93bf79SJacob Keller 
354bf93bf79SJacob Keller 	max_frame_size = pi->phy.link_info.max_frame_size;
355bf93bf79SJacob Keller 
356bf93bf79SJacob Keller 	if (ice_vf_is_port_vlan_ena(vf))
357bf93bf79SJacob Keller 		max_frame_size -= VLAN_HLEN;
358bf93bf79SJacob Keller 
359bf93bf79SJacob Keller 	return max_frame_size;
360bf93bf79SJacob Keller }
361bf93bf79SJacob Keller 
362bf93bf79SJacob Keller /**
363cede04b3SMichal Swiatkowski  * ice_vc_get_vlan_caps
364cede04b3SMichal Swiatkowski  * @hw: pointer to the hw
365cede04b3SMichal Swiatkowski  * @vf: pointer to the VF info
366cede04b3SMichal Swiatkowski  * @vsi: pointer to the VSI
367cede04b3SMichal Swiatkowski  * @driver_caps: current driver caps
368cede04b3SMichal Swiatkowski  *
369cede04b3SMichal Swiatkowski  * Return 0 if there is no VLAN caps supported, or VLAN caps value
370cede04b3SMichal Swiatkowski  */
371cede04b3SMichal Swiatkowski static u32
372cede04b3SMichal Swiatkowski ice_vc_get_vlan_caps(struct ice_hw *hw, struct ice_vf *vf, struct ice_vsi *vsi,
373cede04b3SMichal Swiatkowski 		     u32 driver_caps)
374cede04b3SMichal Swiatkowski {
375cede04b3SMichal Swiatkowski 	if (ice_is_eswitch_mode_switchdev(vf->pf))
376cede04b3SMichal Swiatkowski 		/* In switchdev setting VLAN from VF isn't supported */
377cede04b3SMichal Swiatkowski 		return 0;
378cede04b3SMichal Swiatkowski 
379cede04b3SMichal Swiatkowski 	if (driver_caps & VIRTCHNL_VF_OFFLOAD_VLAN_V2) {
380cede04b3SMichal Swiatkowski 		/* VLAN offloads based on current device configuration */
381cede04b3SMichal Swiatkowski 		return VIRTCHNL_VF_OFFLOAD_VLAN_V2;
382cede04b3SMichal Swiatkowski 	} else if (driver_caps & VIRTCHNL_VF_OFFLOAD_VLAN) {
383cede04b3SMichal Swiatkowski 		/* allow VF to negotiate VIRTCHNL_VF_OFFLOAD explicitly for
384cede04b3SMichal Swiatkowski 		 * these two conditions, which amounts to guest VLAN filtering
385cede04b3SMichal Swiatkowski 		 * and offloads being based on the inner VLAN or the
386cede04b3SMichal Swiatkowski 		 * inner/single VLAN respectively and don't allow VF to
387cede04b3SMichal Swiatkowski 		 * negotiate VIRTCHNL_VF_OFFLOAD in any other cases
388cede04b3SMichal Swiatkowski 		 */
389cede04b3SMichal Swiatkowski 		if (ice_is_dvm_ena(hw) && ice_vf_is_port_vlan_ena(vf)) {
390cede04b3SMichal Swiatkowski 			return VIRTCHNL_VF_OFFLOAD_VLAN;
391cede04b3SMichal Swiatkowski 		} else if (!ice_is_dvm_ena(hw) &&
392cede04b3SMichal Swiatkowski 			   !ice_vf_is_port_vlan_ena(vf)) {
393cede04b3SMichal Swiatkowski 			/* configure backward compatible support for VFs that
394cede04b3SMichal Swiatkowski 			 * only support VIRTCHNL_VF_OFFLOAD_VLAN, the PF is
395cede04b3SMichal Swiatkowski 			 * configured in SVM, and no port VLAN is configured
396cede04b3SMichal Swiatkowski 			 */
397cede04b3SMichal Swiatkowski 			ice_vf_vsi_cfg_svm_legacy_vlan_mode(vsi);
398cede04b3SMichal Swiatkowski 			return VIRTCHNL_VF_OFFLOAD_VLAN;
399cede04b3SMichal Swiatkowski 		} else if (ice_is_dvm_ena(hw)) {
400cede04b3SMichal Swiatkowski 			/* configure software offloaded VLAN support when DVM
401cede04b3SMichal Swiatkowski 			 * is enabled, but no port VLAN is enabled
402cede04b3SMichal Swiatkowski 			 */
403cede04b3SMichal Swiatkowski 			ice_vf_vsi_cfg_dvm_legacy_vlan_mode(vsi);
404cede04b3SMichal Swiatkowski 		}
405cede04b3SMichal Swiatkowski 	}
406cede04b3SMichal Swiatkowski 
407cede04b3SMichal Swiatkowski 	return 0;
408cede04b3SMichal Swiatkowski }
409cede04b3SMichal Swiatkowski 
410cede04b3SMichal Swiatkowski /**
411bf93bf79SJacob Keller  * ice_vc_get_vf_res_msg
412bf93bf79SJacob Keller  * @vf: pointer to the VF info
413bf93bf79SJacob Keller  * @msg: pointer to the msg buffer
414bf93bf79SJacob Keller  *
415bf93bf79SJacob Keller  * called from the VF to request its resources
416bf93bf79SJacob Keller  */
417bf93bf79SJacob Keller static int ice_vc_get_vf_res_msg(struct ice_vf *vf, u8 *msg)
418bf93bf79SJacob Keller {
419bf93bf79SJacob Keller 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
420bf93bf79SJacob Keller 	struct virtchnl_vf_resource *vfres = NULL;
4215a57ee83SJacob Keller 	struct ice_hw *hw = &vf->pf->hw;
422bf93bf79SJacob Keller 	struct ice_vsi *vsi;
423bf93bf79SJacob Keller 	int len = 0;
424bf93bf79SJacob Keller 	int ret;
425bf93bf79SJacob Keller 
4265a57ee83SJacob Keller 	if (ice_check_vf_init(vf)) {
427bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
428bf93bf79SJacob Keller 		goto err;
429bf93bf79SJacob Keller 	}
430bf93bf79SJacob Keller 
431*5e7f59faSAlexander Lobakin 	len = virtchnl_struct_size(vfres, vsi_res, 0);
432bf93bf79SJacob Keller 
433bf93bf79SJacob Keller 	vfres = kzalloc(len, GFP_KERNEL);
434bf93bf79SJacob Keller 	if (!vfres) {
435bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY;
436bf93bf79SJacob Keller 		len = 0;
437bf93bf79SJacob Keller 		goto err;
438bf93bf79SJacob Keller 	}
439bf93bf79SJacob Keller 	if (VF_IS_V11(&vf->vf_ver))
440bf93bf79SJacob Keller 		vf->driver_caps = *(u32 *)msg;
441bf93bf79SJacob Keller 	else
442bf93bf79SJacob Keller 		vf->driver_caps = VIRTCHNL_VF_OFFLOAD_L2 |
443bf93bf79SJacob Keller 				  VIRTCHNL_VF_OFFLOAD_RSS_REG |
444bf93bf79SJacob Keller 				  VIRTCHNL_VF_OFFLOAD_VLAN;
445bf93bf79SJacob Keller 
446bf93bf79SJacob Keller 	vfres->vf_cap_flags = VIRTCHNL_VF_OFFLOAD_L2;
447bf93bf79SJacob Keller 	vsi = ice_get_vf_vsi(vf);
448bf93bf79SJacob Keller 	if (!vsi) {
449bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
450bf93bf79SJacob Keller 		goto err;
451bf93bf79SJacob Keller 	}
452bf93bf79SJacob Keller 
453cede04b3SMichal Swiatkowski 	vfres->vf_cap_flags |= ice_vc_get_vlan_caps(hw, vf, vsi,
454cede04b3SMichal Swiatkowski 						    vf->driver_caps);
455bf93bf79SJacob Keller 
456bf93bf79SJacob Keller 	if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_RSS_PF) {
457bf93bf79SJacob Keller 		vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_RSS_PF;
458bf93bf79SJacob Keller 	} else {
459bf93bf79SJacob Keller 		if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_RSS_AQ)
460bf93bf79SJacob Keller 			vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_RSS_AQ;
461bf93bf79SJacob Keller 		else
462bf93bf79SJacob Keller 			vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_RSS_REG;
463bf93bf79SJacob Keller 	}
464bf93bf79SJacob Keller 
465e753df8fSMichal Jaron 	if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC)
466e753df8fSMichal Jaron 		vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC;
467e753df8fSMichal Jaron 
468bf93bf79SJacob Keller 	if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_FDIR_PF)
469bf93bf79SJacob Keller 		vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_FDIR_PF;
470bf93bf79SJacob Keller 
471bf93bf79SJacob Keller 	if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2)
472bf93bf79SJacob Keller 		vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2;
473bf93bf79SJacob Keller 
474bf93bf79SJacob Keller 	if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_ENCAP)
475bf93bf79SJacob Keller 		vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_ENCAP;
476bf93bf79SJacob Keller 
477bf93bf79SJacob Keller 	if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM)
478bf93bf79SJacob Keller 		vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM;
479bf93bf79SJacob Keller 
480bf93bf79SJacob Keller 	if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_RX_POLLING)
481bf93bf79SJacob Keller 		vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_RX_POLLING;
482bf93bf79SJacob Keller 
483bf93bf79SJacob Keller 	if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_WB_ON_ITR)
484bf93bf79SJacob Keller 		vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_WB_ON_ITR;
485bf93bf79SJacob Keller 
486bf93bf79SJacob Keller 	if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_REQ_QUEUES)
487bf93bf79SJacob Keller 		vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_REQ_QUEUES;
488bf93bf79SJacob Keller 
489bf93bf79SJacob Keller 	if (vf->driver_caps & VIRTCHNL_VF_CAP_ADV_LINK_SPEED)
490bf93bf79SJacob Keller 		vfres->vf_cap_flags |= VIRTCHNL_VF_CAP_ADV_LINK_SPEED;
491bf93bf79SJacob Keller 
492bf93bf79SJacob Keller 	if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_ADV_RSS_PF)
493bf93bf79SJacob Keller 		vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_ADV_RSS_PF;
494bf93bf79SJacob Keller 
495bf93bf79SJacob Keller 	if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_USO)
496bf93bf79SJacob Keller 		vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_USO;
497bf93bf79SJacob Keller 
498bf93bf79SJacob Keller 	vfres->num_vsis = 1;
499bf93bf79SJacob Keller 	/* Tx and Rx queue are equal for VF */
500bf93bf79SJacob Keller 	vfres->num_queue_pairs = vsi->num_txq;
5015a57ee83SJacob Keller 	vfres->max_vectors = vf->pf->vfs.num_msix_per;
502bf93bf79SJacob Keller 	vfres->rss_key_size = ICE_VSIQF_HKEY_ARRAY_SIZE;
503b6143c9bSPrzemek Kitszel 	vfres->rss_lut_size = ICE_LUT_VSI_SIZE;
504bf93bf79SJacob Keller 	vfres->max_mtu = ice_vc_get_max_frame_size(vf);
505bf93bf79SJacob Keller 
506bf93bf79SJacob Keller 	vfres->vsi_res[0].vsi_id = vf->lan_vsi_num;
507bf93bf79SJacob Keller 	vfres->vsi_res[0].vsi_type = VIRTCHNL_VSI_SRIOV;
508bf93bf79SJacob Keller 	vfres->vsi_res[0].num_queue_pairs = vsi->num_txq;
509bf93bf79SJacob Keller 	ether_addr_copy(vfres->vsi_res[0].default_mac_addr,
510e0645311SJacob Keller 			vf->hw_lan_addr);
511bf93bf79SJacob Keller 
512bf93bf79SJacob Keller 	/* match guest capabilities */
513bf93bf79SJacob Keller 	vf->driver_caps = vfres->vf_cap_flags;
514bf93bf79SJacob Keller 
515bf93bf79SJacob Keller 	ice_vc_set_caps_allowlist(vf);
516bf93bf79SJacob Keller 	ice_vc_set_working_allowlist(vf);
517bf93bf79SJacob Keller 
518bf93bf79SJacob Keller 	set_bit(ICE_VF_STATE_ACTIVE, vf->vf_states);
519bf93bf79SJacob Keller 
520bf93bf79SJacob Keller err:
521bf93bf79SJacob Keller 	/* send the response back to the VF */
522bf93bf79SJacob Keller 	ret = ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_GET_VF_RESOURCES, v_ret,
523bf93bf79SJacob Keller 				    (u8 *)vfres, len);
524bf93bf79SJacob Keller 
525bf93bf79SJacob Keller 	kfree(vfres);
526bf93bf79SJacob Keller 	return ret;
527bf93bf79SJacob Keller }
528bf93bf79SJacob Keller 
529bf93bf79SJacob Keller /**
530bf93bf79SJacob Keller  * ice_vc_reset_vf_msg
531bf93bf79SJacob Keller  * @vf: pointer to the VF info
532bf93bf79SJacob Keller  *
533bf93bf79SJacob Keller  * called from the VF to reset itself,
534bf93bf79SJacob Keller  * unlike other virtchnl messages, PF driver
535bf93bf79SJacob Keller  * doesn't send the response back to the VF
536bf93bf79SJacob Keller  */
537bf93bf79SJacob Keller static void ice_vc_reset_vf_msg(struct ice_vf *vf)
538bf93bf79SJacob Keller {
539bf93bf79SJacob Keller 	if (test_bit(ICE_VF_STATE_INIT, vf->vf_states))
540bf93bf79SJacob Keller 		ice_reset_vf(vf, 0);
541bf93bf79SJacob Keller }
542bf93bf79SJacob Keller 
543bf93bf79SJacob Keller /**
544bf93bf79SJacob Keller  * ice_vc_isvalid_vsi_id
545bf93bf79SJacob Keller  * @vf: pointer to the VF info
546bf93bf79SJacob Keller  * @vsi_id: VF relative VSI ID
547bf93bf79SJacob Keller  *
548bf93bf79SJacob Keller  * check for the valid VSI ID
549bf93bf79SJacob Keller  */
550bf93bf79SJacob Keller bool ice_vc_isvalid_vsi_id(struct ice_vf *vf, u16 vsi_id)
551bf93bf79SJacob Keller {
552bf93bf79SJacob Keller 	struct ice_pf *pf = vf->pf;
553bf93bf79SJacob Keller 	struct ice_vsi *vsi;
554bf93bf79SJacob Keller 
555295819b5SMaciej Fijalkowski 	vsi = ice_find_vsi(pf, vsi_id);
556bf93bf79SJacob Keller 
557bf93bf79SJacob Keller 	return (vsi && (vsi->vf == vf));
558bf93bf79SJacob Keller }
559bf93bf79SJacob Keller 
560bf93bf79SJacob Keller /**
561bf93bf79SJacob Keller  * ice_vc_isvalid_q_id
562bf93bf79SJacob Keller  * @vf: pointer to the VF info
563bf93bf79SJacob Keller  * @vsi_id: VSI ID
564bf93bf79SJacob Keller  * @qid: VSI relative queue ID
565bf93bf79SJacob Keller  *
566bf93bf79SJacob Keller  * check for the valid queue ID
567bf93bf79SJacob Keller  */
568bf93bf79SJacob Keller static bool ice_vc_isvalid_q_id(struct ice_vf *vf, u16 vsi_id, u8 qid)
569bf93bf79SJacob Keller {
570295819b5SMaciej Fijalkowski 	struct ice_vsi *vsi = ice_find_vsi(vf->pf, vsi_id);
571bf93bf79SJacob Keller 	/* allocated Tx and Rx queues should be always equal for VF VSI */
572bf93bf79SJacob Keller 	return (vsi && (qid < vsi->alloc_txq));
573bf93bf79SJacob Keller }
574bf93bf79SJacob Keller 
575bf93bf79SJacob Keller /**
576bf93bf79SJacob Keller  * ice_vc_isvalid_ring_len
577bf93bf79SJacob Keller  * @ring_len: length of ring
578bf93bf79SJacob Keller  *
579bf93bf79SJacob Keller  * check for the valid ring count, should be multiple of ICE_REQ_DESC_MULTIPLE
580bf93bf79SJacob Keller  * or zero
581bf93bf79SJacob Keller  */
582bf93bf79SJacob Keller static bool ice_vc_isvalid_ring_len(u16 ring_len)
583bf93bf79SJacob Keller {
584bf93bf79SJacob Keller 	return ring_len == 0 ||
585bf93bf79SJacob Keller 	       (ring_len >= ICE_MIN_NUM_DESC &&
586bf93bf79SJacob Keller 		ring_len <= ICE_MAX_NUM_DESC &&
587bf93bf79SJacob Keller 		!(ring_len % ICE_REQ_DESC_MULTIPLE));
588bf93bf79SJacob Keller }
589bf93bf79SJacob Keller 
590bf93bf79SJacob Keller /**
591bf93bf79SJacob Keller  * ice_vc_validate_pattern
592bf93bf79SJacob Keller  * @vf: pointer to the VF info
593bf93bf79SJacob Keller  * @proto: virtchnl protocol headers
594bf93bf79SJacob Keller  *
595bf93bf79SJacob Keller  * validate the pattern is supported or not.
596bf93bf79SJacob Keller  *
597bf93bf79SJacob Keller  * Return: true on success, false on error.
598bf93bf79SJacob Keller  */
599bf93bf79SJacob Keller bool
600bf93bf79SJacob Keller ice_vc_validate_pattern(struct ice_vf *vf, struct virtchnl_proto_hdrs *proto)
601bf93bf79SJacob Keller {
602bf93bf79SJacob Keller 	bool is_ipv4 = false;
603bf93bf79SJacob Keller 	bool is_ipv6 = false;
604bf93bf79SJacob Keller 	bool is_udp = false;
605bf93bf79SJacob Keller 	u16 ptype = -1;
606bf93bf79SJacob Keller 	int i = 0;
607bf93bf79SJacob Keller 
608bf93bf79SJacob Keller 	while (i < proto->count &&
609bf93bf79SJacob Keller 	       proto->proto_hdr[i].type != VIRTCHNL_PROTO_HDR_NONE) {
610bf93bf79SJacob Keller 		switch (proto->proto_hdr[i].type) {
611bf93bf79SJacob Keller 		case VIRTCHNL_PROTO_HDR_ETH:
612bf93bf79SJacob Keller 			ptype = ICE_PTYPE_MAC_PAY;
613bf93bf79SJacob Keller 			break;
614bf93bf79SJacob Keller 		case VIRTCHNL_PROTO_HDR_IPV4:
615bf93bf79SJacob Keller 			ptype = ICE_PTYPE_IPV4_PAY;
616bf93bf79SJacob Keller 			is_ipv4 = true;
617bf93bf79SJacob Keller 			break;
618bf93bf79SJacob Keller 		case VIRTCHNL_PROTO_HDR_IPV6:
619bf93bf79SJacob Keller 			ptype = ICE_PTYPE_IPV6_PAY;
620bf93bf79SJacob Keller 			is_ipv6 = true;
621bf93bf79SJacob Keller 			break;
622bf93bf79SJacob Keller 		case VIRTCHNL_PROTO_HDR_UDP:
623bf93bf79SJacob Keller 			if (is_ipv4)
624bf93bf79SJacob Keller 				ptype = ICE_PTYPE_IPV4_UDP_PAY;
625bf93bf79SJacob Keller 			else if (is_ipv6)
626bf93bf79SJacob Keller 				ptype = ICE_PTYPE_IPV6_UDP_PAY;
627bf93bf79SJacob Keller 			is_udp = true;
628bf93bf79SJacob Keller 			break;
629bf93bf79SJacob Keller 		case VIRTCHNL_PROTO_HDR_TCP:
630bf93bf79SJacob Keller 			if (is_ipv4)
631bf93bf79SJacob Keller 				ptype = ICE_PTYPE_IPV4_TCP_PAY;
632bf93bf79SJacob Keller 			else if (is_ipv6)
633bf93bf79SJacob Keller 				ptype = ICE_PTYPE_IPV6_TCP_PAY;
634bf93bf79SJacob Keller 			break;
635bf93bf79SJacob Keller 		case VIRTCHNL_PROTO_HDR_SCTP:
636bf93bf79SJacob Keller 			if (is_ipv4)
637bf93bf79SJacob Keller 				ptype = ICE_PTYPE_IPV4_SCTP_PAY;
638bf93bf79SJacob Keller 			else if (is_ipv6)
639bf93bf79SJacob Keller 				ptype = ICE_PTYPE_IPV6_SCTP_PAY;
640bf93bf79SJacob Keller 			break;
641bf93bf79SJacob Keller 		case VIRTCHNL_PROTO_HDR_GTPU_IP:
642bf93bf79SJacob Keller 		case VIRTCHNL_PROTO_HDR_GTPU_EH:
643bf93bf79SJacob Keller 			if (is_ipv4)
644bf93bf79SJacob Keller 				ptype = ICE_MAC_IPV4_GTPU;
645bf93bf79SJacob Keller 			else if (is_ipv6)
646bf93bf79SJacob Keller 				ptype = ICE_MAC_IPV6_GTPU;
647bf93bf79SJacob Keller 			goto out;
648bf93bf79SJacob Keller 		case VIRTCHNL_PROTO_HDR_L2TPV3:
649bf93bf79SJacob Keller 			if (is_ipv4)
650bf93bf79SJacob Keller 				ptype = ICE_MAC_IPV4_L2TPV3;
651bf93bf79SJacob Keller 			else if (is_ipv6)
652bf93bf79SJacob Keller 				ptype = ICE_MAC_IPV6_L2TPV3;
653bf93bf79SJacob Keller 			goto out;
654bf93bf79SJacob Keller 		case VIRTCHNL_PROTO_HDR_ESP:
655bf93bf79SJacob Keller 			if (is_ipv4)
656bf93bf79SJacob Keller 				ptype = is_udp ? ICE_MAC_IPV4_NAT_T_ESP :
657bf93bf79SJacob Keller 						ICE_MAC_IPV4_ESP;
658bf93bf79SJacob Keller 			else if (is_ipv6)
659bf93bf79SJacob Keller 				ptype = is_udp ? ICE_MAC_IPV6_NAT_T_ESP :
660bf93bf79SJacob Keller 						ICE_MAC_IPV6_ESP;
661bf93bf79SJacob Keller 			goto out;
662bf93bf79SJacob Keller 		case VIRTCHNL_PROTO_HDR_AH:
663bf93bf79SJacob Keller 			if (is_ipv4)
664bf93bf79SJacob Keller 				ptype = ICE_MAC_IPV4_AH;
665bf93bf79SJacob Keller 			else if (is_ipv6)
666bf93bf79SJacob Keller 				ptype = ICE_MAC_IPV6_AH;
667bf93bf79SJacob Keller 			goto out;
668bf93bf79SJacob Keller 		case VIRTCHNL_PROTO_HDR_PFCP:
669bf93bf79SJacob Keller 			if (is_ipv4)
670bf93bf79SJacob Keller 				ptype = ICE_MAC_IPV4_PFCP_SESSION;
671bf93bf79SJacob Keller 			else if (is_ipv6)
672bf93bf79SJacob Keller 				ptype = ICE_MAC_IPV6_PFCP_SESSION;
673bf93bf79SJacob Keller 			goto out;
674bf93bf79SJacob Keller 		default:
675bf93bf79SJacob Keller 			break;
676bf93bf79SJacob Keller 		}
677bf93bf79SJacob Keller 		i++;
678bf93bf79SJacob Keller 	}
679bf93bf79SJacob Keller 
680bf93bf79SJacob Keller out:
681bf93bf79SJacob Keller 	return ice_hw_ptype_ena(&vf->pf->hw, ptype);
682bf93bf79SJacob Keller }
683bf93bf79SJacob Keller 
684bf93bf79SJacob Keller /**
685bf93bf79SJacob Keller  * ice_vc_parse_rss_cfg - parses hash fields and headers from
686bf93bf79SJacob Keller  * a specific virtchnl RSS cfg
687bf93bf79SJacob Keller  * @hw: pointer to the hardware
688bf93bf79SJacob Keller  * @rss_cfg: pointer to the virtchnl RSS cfg
689bf93bf79SJacob Keller  * @addl_hdrs: pointer to the protocol header fields (ICE_FLOW_SEG_HDR_*)
690bf93bf79SJacob Keller  * to configure
691bf93bf79SJacob Keller  * @hash_flds: pointer to the hash bit fields (ICE_FLOW_HASH_*) to configure
692bf93bf79SJacob Keller  *
693bf93bf79SJacob Keller  * Return true if all the protocol header and hash fields in the RSS cfg could
694bf93bf79SJacob Keller  * be parsed, else return false
695bf93bf79SJacob Keller  *
696bf93bf79SJacob Keller  * This function parses the virtchnl RSS cfg to be the intended
697bf93bf79SJacob Keller  * hash fields and the intended header for RSS configuration
698bf93bf79SJacob Keller  */
699bf93bf79SJacob Keller static bool
700bf93bf79SJacob Keller ice_vc_parse_rss_cfg(struct ice_hw *hw, struct virtchnl_rss_cfg *rss_cfg,
701bf93bf79SJacob Keller 		     u32 *addl_hdrs, u64 *hash_flds)
702bf93bf79SJacob Keller {
703bf93bf79SJacob Keller 	const struct ice_vc_hash_field_match_type *hf_list;
704bf93bf79SJacob Keller 	const struct ice_vc_hdr_match_type *hdr_list;
705bf93bf79SJacob Keller 	int i, hf_list_len, hdr_list_len;
706bf93bf79SJacob Keller 
707bf93bf79SJacob Keller 	hf_list = ice_vc_hash_field_list;
708bf93bf79SJacob Keller 	hf_list_len = ARRAY_SIZE(ice_vc_hash_field_list);
709bf93bf79SJacob Keller 	hdr_list = ice_vc_hdr_list;
710bf93bf79SJacob Keller 	hdr_list_len = ARRAY_SIZE(ice_vc_hdr_list);
711bf93bf79SJacob Keller 
712bf93bf79SJacob Keller 	for (i = 0; i < rss_cfg->proto_hdrs.count; i++) {
713bf93bf79SJacob Keller 		struct virtchnl_proto_hdr *proto_hdr =
714bf93bf79SJacob Keller 					&rss_cfg->proto_hdrs.proto_hdr[i];
715bf93bf79SJacob Keller 		bool hdr_found = false;
716bf93bf79SJacob Keller 		int j;
717bf93bf79SJacob Keller 
718bf93bf79SJacob Keller 		/* Find matched ice headers according to virtchnl headers. */
719bf93bf79SJacob Keller 		for (j = 0; j < hdr_list_len; j++) {
720bf93bf79SJacob Keller 			struct ice_vc_hdr_match_type hdr_map = hdr_list[j];
721bf93bf79SJacob Keller 
722bf93bf79SJacob Keller 			if (proto_hdr->type == hdr_map.vc_hdr) {
723bf93bf79SJacob Keller 				*addl_hdrs |= hdr_map.ice_hdr;
724bf93bf79SJacob Keller 				hdr_found = true;
725bf93bf79SJacob Keller 			}
726bf93bf79SJacob Keller 		}
727bf93bf79SJacob Keller 
728bf93bf79SJacob Keller 		if (!hdr_found)
729bf93bf79SJacob Keller 			return false;
730bf93bf79SJacob Keller 
731bf93bf79SJacob Keller 		/* Find matched ice hash fields according to
732bf93bf79SJacob Keller 		 * virtchnl hash fields.
733bf93bf79SJacob Keller 		 */
734bf93bf79SJacob Keller 		for (j = 0; j < hf_list_len; j++) {
735bf93bf79SJacob Keller 			struct ice_vc_hash_field_match_type hf_map = hf_list[j];
736bf93bf79SJacob Keller 
737bf93bf79SJacob Keller 			if (proto_hdr->type == hf_map.vc_hdr &&
738bf93bf79SJacob Keller 			    proto_hdr->field_selector == hf_map.vc_hash_field) {
739bf93bf79SJacob Keller 				*hash_flds |= hf_map.ice_hash_field;
740bf93bf79SJacob Keller 				break;
741bf93bf79SJacob Keller 			}
742bf93bf79SJacob Keller 		}
743bf93bf79SJacob Keller 	}
744bf93bf79SJacob Keller 
745bf93bf79SJacob Keller 	return true;
746bf93bf79SJacob Keller }
747bf93bf79SJacob Keller 
748bf93bf79SJacob Keller /**
749bf93bf79SJacob Keller  * ice_vf_adv_rss_offload_ena - determine if capabilities support advanced
750bf93bf79SJacob Keller  * RSS offloads
751bf93bf79SJacob Keller  * @caps: VF driver negotiated capabilities
752bf93bf79SJacob Keller  *
753bf93bf79SJacob Keller  * Return true if VIRTCHNL_VF_OFFLOAD_ADV_RSS_PF capability is set,
754bf93bf79SJacob Keller  * else return false
755bf93bf79SJacob Keller  */
756bf93bf79SJacob Keller static bool ice_vf_adv_rss_offload_ena(u32 caps)
757bf93bf79SJacob Keller {
758bf93bf79SJacob Keller 	return !!(caps & VIRTCHNL_VF_OFFLOAD_ADV_RSS_PF);
759bf93bf79SJacob Keller }
760bf93bf79SJacob Keller 
761bf93bf79SJacob Keller /**
762bf93bf79SJacob Keller  * ice_vc_handle_rss_cfg
763bf93bf79SJacob Keller  * @vf: pointer to the VF info
764bf93bf79SJacob Keller  * @msg: pointer to the message buffer
765bf93bf79SJacob Keller  * @add: add a RSS config if true, otherwise delete a RSS config
766bf93bf79SJacob Keller  *
767bf93bf79SJacob Keller  * This function adds/deletes a RSS config
768bf93bf79SJacob Keller  */
769bf93bf79SJacob Keller static int ice_vc_handle_rss_cfg(struct ice_vf *vf, u8 *msg, bool add)
770bf93bf79SJacob Keller {
771bf93bf79SJacob Keller 	u32 v_opcode = add ? VIRTCHNL_OP_ADD_RSS_CFG : VIRTCHNL_OP_DEL_RSS_CFG;
772bf93bf79SJacob Keller 	struct virtchnl_rss_cfg *rss_cfg = (struct virtchnl_rss_cfg *)msg;
773bf93bf79SJacob Keller 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
774bf93bf79SJacob Keller 	struct device *dev = ice_pf_to_dev(vf->pf);
775bf93bf79SJacob Keller 	struct ice_hw *hw = &vf->pf->hw;
776bf93bf79SJacob Keller 	struct ice_vsi *vsi;
777bf93bf79SJacob Keller 
778bf93bf79SJacob Keller 	if (!test_bit(ICE_FLAG_RSS_ENA, vf->pf->flags)) {
779bf93bf79SJacob Keller 		dev_dbg(dev, "VF %d attempting to configure RSS, but RSS is not supported by the PF\n",
780bf93bf79SJacob Keller 			vf->vf_id);
781bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_NOT_SUPPORTED;
782bf93bf79SJacob Keller 		goto error_param;
783bf93bf79SJacob Keller 	}
784bf93bf79SJacob Keller 
785bf93bf79SJacob Keller 	if (!ice_vf_adv_rss_offload_ena(vf->driver_caps)) {
786bf93bf79SJacob Keller 		dev_dbg(dev, "VF %d attempting to configure RSS, but Advanced RSS offload is not supported\n",
787bf93bf79SJacob Keller 			vf->vf_id);
788bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
789bf93bf79SJacob Keller 		goto error_param;
790bf93bf79SJacob Keller 	}
791bf93bf79SJacob Keller 
792bf93bf79SJacob Keller 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
793bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
794bf93bf79SJacob Keller 		goto error_param;
795bf93bf79SJacob Keller 	}
796bf93bf79SJacob Keller 
797bf93bf79SJacob Keller 	if (rss_cfg->proto_hdrs.count > VIRTCHNL_MAX_NUM_PROTO_HDRS ||
798bf93bf79SJacob Keller 	    rss_cfg->rss_algorithm < VIRTCHNL_RSS_ALG_TOEPLITZ_ASYMMETRIC ||
799bf93bf79SJacob Keller 	    rss_cfg->rss_algorithm > VIRTCHNL_RSS_ALG_XOR_SYMMETRIC) {
800bf93bf79SJacob Keller 		dev_dbg(dev, "VF %d attempting to configure RSS, but RSS configuration is not valid\n",
801bf93bf79SJacob Keller 			vf->vf_id);
802bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
803bf93bf79SJacob Keller 		goto error_param;
804bf93bf79SJacob Keller 	}
805bf93bf79SJacob Keller 
806bf93bf79SJacob Keller 	vsi = ice_get_vf_vsi(vf);
807bf93bf79SJacob Keller 	if (!vsi) {
808bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
809bf93bf79SJacob Keller 		goto error_param;
810bf93bf79SJacob Keller 	}
811bf93bf79SJacob Keller 
812bf93bf79SJacob Keller 	if (!ice_vc_validate_pattern(vf, &rss_cfg->proto_hdrs)) {
813bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
814bf93bf79SJacob Keller 		goto error_param;
815bf93bf79SJacob Keller 	}
816bf93bf79SJacob Keller 
817bf93bf79SJacob Keller 	if (rss_cfg->rss_algorithm == VIRTCHNL_RSS_ALG_R_ASYMMETRIC) {
818bf93bf79SJacob Keller 		struct ice_vsi_ctx *ctx;
819bf93bf79SJacob Keller 		u8 lut_type, hash_type;
820bf93bf79SJacob Keller 		int status;
821bf93bf79SJacob Keller 
822bf93bf79SJacob Keller 		lut_type = ICE_AQ_VSI_Q_OPT_RSS_LUT_VSI;
823bf93bf79SJacob Keller 		hash_type = add ? ICE_AQ_VSI_Q_OPT_RSS_XOR :
824bf93bf79SJacob Keller 				ICE_AQ_VSI_Q_OPT_RSS_TPLZ;
825bf93bf79SJacob Keller 
826bf93bf79SJacob Keller 		ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
827bf93bf79SJacob Keller 		if (!ctx) {
828bf93bf79SJacob Keller 			v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY;
829bf93bf79SJacob Keller 			goto error_param;
830bf93bf79SJacob Keller 		}
831bf93bf79SJacob Keller 
832bf93bf79SJacob Keller 		ctx->info.q_opt_rss = ((lut_type <<
833bf93bf79SJacob Keller 					ICE_AQ_VSI_Q_OPT_RSS_LUT_S) &
834bf93bf79SJacob Keller 				       ICE_AQ_VSI_Q_OPT_RSS_LUT_M) |
835bf93bf79SJacob Keller 				       (hash_type &
836bf93bf79SJacob Keller 					ICE_AQ_VSI_Q_OPT_RSS_HASH_M);
837bf93bf79SJacob Keller 
838bf93bf79SJacob Keller 		/* Preserve existing queueing option setting */
839bf93bf79SJacob Keller 		ctx->info.q_opt_rss |= (vsi->info.q_opt_rss &
840bf93bf79SJacob Keller 					  ICE_AQ_VSI_Q_OPT_RSS_GBL_LUT_M);
841bf93bf79SJacob Keller 		ctx->info.q_opt_tc = vsi->info.q_opt_tc;
842bf93bf79SJacob Keller 		ctx->info.q_opt_flags = vsi->info.q_opt_rss;
843bf93bf79SJacob Keller 
844bf93bf79SJacob Keller 		ctx->info.valid_sections =
845bf93bf79SJacob Keller 				cpu_to_le16(ICE_AQ_VSI_PROP_Q_OPT_VALID);
846bf93bf79SJacob Keller 
847bf93bf79SJacob Keller 		status = ice_update_vsi(hw, vsi->idx, ctx, NULL);
848bf93bf79SJacob Keller 		if (status) {
849bf93bf79SJacob Keller 			dev_err(dev, "update VSI for RSS failed, err %d aq_err %s\n",
850bf93bf79SJacob Keller 				status, ice_aq_str(hw->adminq.sq_last_status));
851bf93bf79SJacob Keller 			v_ret = VIRTCHNL_STATUS_ERR_PARAM;
852bf93bf79SJacob Keller 		} else {
853bf93bf79SJacob Keller 			vsi->info.q_opt_rss = ctx->info.q_opt_rss;
854bf93bf79SJacob Keller 		}
855bf93bf79SJacob Keller 
856bf93bf79SJacob Keller 		kfree(ctx);
857bf93bf79SJacob Keller 	} else {
858bf93bf79SJacob Keller 		u32 addl_hdrs = ICE_FLOW_SEG_HDR_NONE;
859bf93bf79SJacob Keller 		u64 hash_flds = ICE_HASH_INVALID;
860bf93bf79SJacob Keller 
861bf93bf79SJacob Keller 		if (!ice_vc_parse_rss_cfg(hw, rss_cfg, &addl_hdrs,
862bf93bf79SJacob Keller 					  &hash_flds)) {
863bf93bf79SJacob Keller 			v_ret = VIRTCHNL_STATUS_ERR_PARAM;
864bf93bf79SJacob Keller 			goto error_param;
865bf93bf79SJacob Keller 		}
866bf93bf79SJacob Keller 
867bf93bf79SJacob Keller 		if (add) {
868bf93bf79SJacob Keller 			if (ice_add_rss_cfg(hw, vsi->idx, hash_flds,
869bf93bf79SJacob Keller 					    addl_hdrs)) {
870bf93bf79SJacob Keller 				v_ret = VIRTCHNL_STATUS_ERR_PARAM;
871bf93bf79SJacob Keller 				dev_err(dev, "ice_add_rss_cfg failed for vsi = %d, v_ret = %d\n",
872bf93bf79SJacob Keller 					vsi->vsi_num, v_ret);
873bf93bf79SJacob Keller 			}
874bf93bf79SJacob Keller 		} else {
875bf93bf79SJacob Keller 			int status;
876bf93bf79SJacob Keller 
877bf93bf79SJacob Keller 			status = ice_rem_rss_cfg(hw, vsi->idx, hash_flds,
878bf93bf79SJacob Keller 						 addl_hdrs);
879bf93bf79SJacob Keller 			/* We just ignore -ENOENT, because if two configurations
880bf93bf79SJacob Keller 			 * share the same profile remove one of them actually
881bf93bf79SJacob Keller 			 * removes both, since the profile is deleted.
882bf93bf79SJacob Keller 			 */
883bf93bf79SJacob Keller 			if (status && status != -ENOENT) {
884bf93bf79SJacob Keller 				v_ret = VIRTCHNL_STATUS_ERR_PARAM;
885bf93bf79SJacob Keller 				dev_err(dev, "ice_rem_rss_cfg failed for VF ID:%d, error:%d\n",
886bf93bf79SJacob Keller 					vf->vf_id, status);
887bf93bf79SJacob Keller 			}
888bf93bf79SJacob Keller 		}
889bf93bf79SJacob Keller 	}
890bf93bf79SJacob Keller 
891bf93bf79SJacob Keller error_param:
892bf93bf79SJacob Keller 	return ice_vc_send_msg_to_vf(vf, v_opcode, v_ret, NULL, 0);
893bf93bf79SJacob Keller }
894bf93bf79SJacob Keller 
895bf93bf79SJacob Keller /**
896bf93bf79SJacob Keller  * ice_vc_config_rss_key
897bf93bf79SJacob Keller  * @vf: pointer to the VF info
898bf93bf79SJacob Keller  * @msg: pointer to the msg buffer
899bf93bf79SJacob Keller  *
900bf93bf79SJacob Keller  * Configure the VF's RSS key
901bf93bf79SJacob Keller  */
902bf93bf79SJacob Keller static int ice_vc_config_rss_key(struct ice_vf *vf, u8 *msg)
903bf93bf79SJacob Keller {
904bf93bf79SJacob Keller 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
905bf93bf79SJacob Keller 	struct virtchnl_rss_key *vrk =
906bf93bf79SJacob Keller 		(struct virtchnl_rss_key *)msg;
907bf93bf79SJacob Keller 	struct ice_vsi *vsi;
908bf93bf79SJacob Keller 
909bf93bf79SJacob Keller 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
910bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
911bf93bf79SJacob Keller 		goto error_param;
912bf93bf79SJacob Keller 	}
913bf93bf79SJacob Keller 
914bf93bf79SJacob Keller 	if (!ice_vc_isvalid_vsi_id(vf, vrk->vsi_id)) {
915bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
916bf93bf79SJacob Keller 		goto error_param;
917bf93bf79SJacob Keller 	}
918bf93bf79SJacob Keller 
919bf93bf79SJacob Keller 	if (vrk->key_len != ICE_VSIQF_HKEY_ARRAY_SIZE) {
920bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
921bf93bf79SJacob Keller 		goto error_param;
922bf93bf79SJacob Keller 	}
923bf93bf79SJacob Keller 
924bf93bf79SJacob Keller 	if (!test_bit(ICE_FLAG_RSS_ENA, vf->pf->flags)) {
925bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
926bf93bf79SJacob Keller 		goto error_param;
927bf93bf79SJacob Keller 	}
928bf93bf79SJacob Keller 
929bf93bf79SJacob Keller 	vsi = ice_get_vf_vsi(vf);
930bf93bf79SJacob Keller 	if (!vsi) {
931bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
932bf93bf79SJacob Keller 		goto error_param;
933bf93bf79SJacob Keller 	}
934bf93bf79SJacob Keller 
935bf93bf79SJacob Keller 	if (ice_set_rss_key(vsi, vrk->key))
936bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR;
937bf93bf79SJacob Keller error_param:
938bf93bf79SJacob Keller 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_RSS_KEY, v_ret,
939bf93bf79SJacob Keller 				     NULL, 0);
940bf93bf79SJacob Keller }
941bf93bf79SJacob Keller 
942bf93bf79SJacob Keller /**
943bf93bf79SJacob Keller  * ice_vc_config_rss_lut
944bf93bf79SJacob Keller  * @vf: pointer to the VF info
945bf93bf79SJacob Keller  * @msg: pointer to the msg buffer
946bf93bf79SJacob Keller  *
947bf93bf79SJacob Keller  * Configure the VF's RSS LUT
948bf93bf79SJacob Keller  */
949bf93bf79SJacob Keller static int ice_vc_config_rss_lut(struct ice_vf *vf, u8 *msg)
950bf93bf79SJacob Keller {
951bf93bf79SJacob Keller 	struct virtchnl_rss_lut *vrl = (struct virtchnl_rss_lut *)msg;
952bf93bf79SJacob Keller 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
953bf93bf79SJacob Keller 	struct ice_vsi *vsi;
954bf93bf79SJacob Keller 
955bf93bf79SJacob Keller 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
956bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
957bf93bf79SJacob Keller 		goto error_param;
958bf93bf79SJacob Keller 	}
959bf93bf79SJacob Keller 
960bf93bf79SJacob Keller 	if (!ice_vc_isvalid_vsi_id(vf, vrl->vsi_id)) {
961bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
962bf93bf79SJacob Keller 		goto error_param;
963bf93bf79SJacob Keller 	}
964bf93bf79SJacob Keller 
965b6143c9bSPrzemek Kitszel 	if (vrl->lut_entries != ICE_LUT_VSI_SIZE) {
966bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
967bf93bf79SJacob Keller 		goto error_param;
968bf93bf79SJacob Keller 	}
969bf93bf79SJacob Keller 
970bf93bf79SJacob Keller 	if (!test_bit(ICE_FLAG_RSS_ENA, vf->pf->flags)) {
971bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
972bf93bf79SJacob Keller 		goto error_param;
973bf93bf79SJacob Keller 	}
974bf93bf79SJacob Keller 
975bf93bf79SJacob Keller 	vsi = ice_get_vf_vsi(vf);
976bf93bf79SJacob Keller 	if (!vsi) {
977bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
978bf93bf79SJacob Keller 		goto error_param;
979bf93bf79SJacob Keller 	}
980bf93bf79SJacob Keller 
981b6143c9bSPrzemek Kitszel 	if (ice_set_rss_lut(vsi, vrl->lut, ICE_LUT_VSI_SIZE))
982bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR;
983bf93bf79SJacob Keller error_param:
984bf93bf79SJacob Keller 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_RSS_LUT, v_ret,
985bf93bf79SJacob Keller 				     NULL, 0);
986bf93bf79SJacob Keller }
987bf93bf79SJacob Keller 
988bf93bf79SJacob Keller /**
989bf93bf79SJacob Keller  * ice_vc_cfg_promiscuous_mode_msg
990bf93bf79SJacob Keller  * @vf: pointer to the VF info
991bf93bf79SJacob Keller  * @msg: pointer to the msg buffer
992bf93bf79SJacob Keller  *
993bf93bf79SJacob Keller  * called from the VF to configure VF VSIs promiscuous mode
994bf93bf79SJacob Keller  */
995bf93bf79SJacob Keller static int ice_vc_cfg_promiscuous_mode_msg(struct ice_vf *vf, u8 *msg)
996bf93bf79SJacob Keller {
997bf93bf79SJacob Keller 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
998bf93bf79SJacob Keller 	bool rm_promisc, alluni = false, allmulti = false;
999bf93bf79SJacob Keller 	struct virtchnl_promisc_info *info =
1000bf93bf79SJacob Keller 	    (struct virtchnl_promisc_info *)msg;
1001bf93bf79SJacob Keller 	struct ice_vsi_vlan_ops *vlan_ops;
1002bf93bf79SJacob Keller 	int mcast_err = 0, ucast_err = 0;
1003bf93bf79SJacob Keller 	struct ice_pf *pf = vf->pf;
1004bf93bf79SJacob Keller 	struct ice_vsi *vsi;
1005d7393425SMichal Wilczynski 	u8 mcast_m, ucast_m;
1006bf93bf79SJacob Keller 	struct device *dev;
1007bf93bf79SJacob Keller 	int ret = 0;
1008bf93bf79SJacob Keller 
1009bf93bf79SJacob Keller 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
1010bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1011bf93bf79SJacob Keller 		goto error_param;
1012bf93bf79SJacob Keller 	}
1013bf93bf79SJacob Keller 
1014bf93bf79SJacob Keller 	if (!ice_vc_isvalid_vsi_id(vf, info->vsi_id)) {
1015bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1016bf93bf79SJacob Keller 		goto error_param;
1017bf93bf79SJacob Keller 	}
1018bf93bf79SJacob Keller 
1019bf93bf79SJacob Keller 	vsi = ice_get_vf_vsi(vf);
1020bf93bf79SJacob Keller 	if (!vsi) {
1021bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1022bf93bf79SJacob Keller 		goto error_param;
1023bf93bf79SJacob Keller 	}
1024bf93bf79SJacob Keller 
1025bf93bf79SJacob Keller 	dev = ice_pf_to_dev(pf);
1026bf93bf79SJacob Keller 	if (!ice_is_vf_trusted(vf)) {
1027bf93bf79SJacob Keller 		dev_err(dev, "Unprivileged VF %d is attempting to configure promiscuous mode\n",
1028bf93bf79SJacob Keller 			vf->vf_id);
1029bf93bf79SJacob Keller 		/* Leave v_ret alone, lie to the VF on purpose. */
1030bf93bf79SJacob Keller 		goto error_param;
1031bf93bf79SJacob Keller 	}
1032bf93bf79SJacob Keller 
1033bf93bf79SJacob Keller 	if (info->flags & FLAG_VF_UNICAST_PROMISC)
1034bf93bf79SJacob Keller 		alluni = true;
1035bf93bf79SJacob Keller 
1036bf93bf79SJacob Keller 	if (info->flags & FLAG_VF_MULTICAST_PROMISC)
1037bf93bf79SJacob Keller 		allmulti = true;
1038bf93bf79SJacob Keller 
1039bf93bf79SJacob Keller 	rm_promisc = !allmulti && !alluni;
1040bf93bf79SJacob Keller 
1041bf93bf79SJacob Keller 	vlan_ops = ice_get_compat_vsi_vlan_ops(vsi);
1042bf93bf79SJacob Keller 	if (rm_promisc)
1043bf93bf79SJacob Keller 		ret = vlan_ops->ena_rx_filtering(vsi);
1044bf93bf79SJacob Keller 	else
1045bf93bf79SJacob Keller 		ret = vlan_ops->dis_rx_filtering(vsi);
1046bf93bf79SJacob Keller 	if (ret) {
1047bf93bf79SJacob Keller 		dev_err(dev, "Failed to configure VLAN pruning in promiscuous mode\n");
1048bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1049bf93bf79SJacob Keller 		goto error_param;
1050bf93bf79SJacob Keller 	}
1051bf93bf79SJacob Keller 
1052a419526dSMichal Wilczynski 	ice_vf_get_promisc_masks(vf, vsi, &ucast_m, &mcast_m);
1053bf93bf79SJacob Keller 
1054d7393425SMichal Wilczynski 	if (!test_bit(ICE_FLAG_VF_TRUE_PROMISC_ENA, pf->flags)) {
1055d7393425SMichal Wilczynski 		if (alluni) {
1056d7393425SMichal Wilczynski 			/* in this case we're turning on promiscuous mode */
1057d7393425SMichal Wilczynski 			ret = ice_set_dflt_vsi(vsi);
1058d7393425SMichal Wilczynski 		} else {
1059d7393425SMichal Wilczynski 			/* in this case we're turning off promiscuous mode */
1060d7393425SMichal Wilczynski 			if (ice_is_dflt_vsi_in_use(vsi->port_info))
1061d7393425SMichal Wilczynski 				ret = ice_clear_dflt_vsi(vsi);
1062d7393425SMichal Wilczynski 		}
1063d7393425SMichal Wilczynski 
1064d7393425SMichal Wilczynski 		/* in this case we're turning on/off only
1065d7393425SMichal Wilczynski 		 * allmulticast
1066bf93bf79SJacob Keller 		 */
1067d7393425SMichal Wilczynski 		if (allmulti)
1068d7393425SMichal Wilczynski 			mcast_err = ice_vf_set_vsi_promisc(vf, vsi, mcast_m);
1069d7393425SMichal Wilczynski 		else
1070d7393425SMichal Wilczynski 			mcast_err = ice_vf_clear_vsi_promisc(vf, vsi, mcast_m);
1071bf93bf79SJacob Keller 
1072bf93bf79SJacob Keller 		if (ret) {
1073d7393425SMichal Wilczynski 			dev_err(dev, "Turning on/off promiscuous mode for VF %d failed, error: %d\n",
1074d7393425SMichal Wilczynski 				vf->vf_id, ret);
1075bf93bf79SJacob Keller 			v_ret = VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR;
1076bf93bf79SJacob Keller 			goto error_param;
1077bf93bf79SJacob Keller 		}
1078bf93bf79SJacob Keller 	} else {
1079bf93bf79SJacob Keller 		if (alluni)
1080bf93bf79SJacob Keller 			ucast_err = ice_vf_set_vsi_promisc(vf, vsi, ucast_m);
1081bf93bf79SJacob Keller 		else
1082bf93bf79SJacob Keller 			ucast_err = ice_vf_clear_vsi_promisc(vf, vsi, ucast_m);
1083bf93bf79SJacob Keller 
1084bf93bf79SJacob Keller 		if (allmulti)
1085bf93bf79SJacob Keller 			mcast_err = ice_vf_set_vsi_promisc(vf, vsi, mcast_m);
1086bf93bf79SJacob Keller 		else
1087bf93bf79SJacob Keller 			mcast_err = ice_vf_clear_vsi_promisc(vf, vsi, mcast_m);
1088bf93bf79SJacob Keller 
1089bf93bf79SJacob Keller 		if (ucast_err || mcast_err)
1090bf93bf79SJacob Keller 			v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1091bf93bf79SJacob Keller 	}
1092bf93bf79SJacob Keller 
1093bf93bf79SJacob Keller 	if (!mcast_err) {
1094bf93bf79SJacob Keller 		if (allmulti &&
1095bf93bf79SJacob Keller 		    !test_and_set_bit(ICE_VF_STATE_MC_PROMISC, vf->vf_states))
1096bf93bf79SJacob Keller 			dev_info(dev, "VF %u successfully set multicast promiscuous mode\n",
1097bf93bf79SJacob Keller 				 vf->vf_id);
1098bf93bf79SJacob Keller 		else if (!allmulti &&
1099bf93bf79SJacob Keller 			 test_and_clear_bit(ICE_VF_STATE_MC_PROMISC,
1100bf93bf79SJacob Keller 					    vf->vf_states))
1101bf93bf79SJacob Keller 			dev_info(dev, "VF %u successfully unset multicast promiscuous mode\n",
1102bf93bf79SJacob Keller 				 vf->vf_id);
1103d7393425SMichal Wilczynski 	} else {
1104d7393425SMichal Wilczynski 		dev_err(dev, "Error while modifying multicast promiscuous mode for VF %u, error: %d\n",
1105d7393425SMichal Wilczynski 			vf->vf_id, mcast_err);
1106bf93bf79SJacob Keller 	}
1107bf93bf79SJacob Keller 
1108bf93bf79SJacob Keller 	if (!ucast_err) {
1109bf93bf79SJacob Keller 		if (alluni &&
1110bf93bf79SJacob Keller 		    !test_and_set_bit(ICE_VF_STATE_UC_PROMISC, vf->vf_states))
1111bf93bf79SJacob Keller 			dev_info(dev, "VF %u successfully set unicast promiscuous mode\n",
1112bf93bf79SJacob Keller 				 vf->vf_id);
1113bf93bf79SJacob Keller 		else if (!alluni &&
1114bf93bf79SJacob Keller 			 test_and_clear_bit(ICE_VF_STATE_UC_PROMISC,
1115bf93bf79SJacob Keller 					    vf->vf_states))
1116bf93bf79SJacob Keller 			dev_info(dev, "VF %u successfully unset unicast promiscuous mode\n",
1117bf93bf79SJacob Keller 				 vf->vf_id);
1118d7393425SMichal Wilczynski 	} else {
1119d7393425SMichal Wilczynski 		dev_err(dev, "Error while modifying unicast promiscuous mode for VF %u, error: %d\n",
1120d7393425SMichal Wilczynski 			vf->vf_id, ucast_err);
1121bf93bf79SJacob Keller 	}
1122bf93bf79SJacob Keller 
1123bf93bf79SJacob Keller error_param:
1124bf93bf79SJacob Keller 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE,
1125bf93bf79SJacob Keller 				     v_ret, NULL, 0);
1126bf93bf79SJacob Keller }
1127bf93bf79SJacob Keller 
1128bf93bf79SJacob Keller /**
1129bf93bf79SJacob Keller  * ice_vc_get_stats_msg
1130bf93bf79SJacob Keller  * @vf: pointer to the VF info
1131bf93bf79SJacob Keller  * @msg: pointer to the msg buffer
1132bf93bf79SJacob Keller  *
1133bf93bf79SJacob Keller  * called from the VF to get VSI stats
1134bf93bf79SJacob Keller  */
1135bf93bf79SJacob Keller static int ice_vc_get_stats_msg(struct ice_vf *vf, u8 *msg)
1136bf93bf79SJacob Keller {
1137bf93bf79SJacob Keller 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
1138bf93bf79SJacob Keller 	struct virtchnl_queue_select *vqs =
1139bf93bf79SJacob Keller 		(struct virtchnl_queue_select *)msg;
1140bf93bf79SJacob Keller 	struct ice_eth_stats stats = { 0 };
1141bf93bf79SJacob Keller 	struct ice_vsi *vsi;
1142bf93bf79SJacob Keller 
1143bf93bf79SJacob Keller 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
1144bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1145bf93bf79SJacob Keller 		goto error_param;
1146bf93bf79SJacob Keller 	}
1147bf93bf79SJacob Keller 
1148bf93bf79SJacob Keller 	if (!ice_vc_isvalid_vsi_id(vf, vqs->vsi_id)) {
1149bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1150bf93bf79SJacob Keller 		goto error_param;
1151bf93bf79SJacob Keller 	}
1152bf93bf79SJacob Keller 
1153bf93bf79SJacob Keller 	vsi = ice_get_vf_vsi(vf);
1154bf93bf79SJacob Keller 	if (!vsi) {
1155bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1156bf93bf79SJacob Keller 		goto error_param;
1157bf93bf79SJacob Keller 	}
1158bf93bf79SJacob Keller 
1159bf93bf79SJacob Keller 	ice_update_eth_stats(vsi);
1160bf93bf79SJacob Keller 
1161bf93bf79SJacob Keller 	stats = vsi->eth_stats;
1162bf93bf79SJacob Keller 
1163bf93bf79SJacob Keller error_param:
1164bf93bf79SJacob Keller 	/* send the response to the VF */
1165bf93bf79SJacob Keller 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_GET_STATS, v_ret,
1166bf93bf79SJacob Keller 				     (u8 *)&stats, sizeof(stats));
1167bf93bf79SJacob Keller }
1168bf93bf79SJacob Keller 
1169bf93bf79SJacob Keller /**
1170bf93bf79SJacob Keller  * ice_vc_validate_vqs_bitmaps - validate Rx/Tx queue bitmaps from VIRTCHNL
1171bf93bf79SJacob Keller  * @vqs: virtchnl_queue_select structure containing bitmaps to validate
1172bf93bf79SJacob Keller  *
1173bf93bf79SJacob Keller  * Return true on successful validation, else false
1174bf93bf79SJacob Keller  */
1175bf93bf79SJacob Keller static bool ice_vc_validate_vqs_bitmaps(struct virtchnl_queue_select *vqs)
1176bf93bf79SJacob Keller {
1177bf93bf79SJacob Keller 	if ((!vqs->rx_queues && !vqs->tx_queues) ||
1178bf93bf79SJacob Keller 	    vqs->rx_queues >= BIT(ICE_MAX_RSS_QS_PER_VF) ||
1179bf93bf79SJacob Keller 	    vqs->tx_queues >= BIT(ICE_MAX_RSS_QS_PER_VF))
1180bf93bf79SJacob Keller 		return false;
1181bf93bf79SJacob Keller 
1182bf93bf79SJacob Keller 	return true;
1183bf93bf79SJacob Keller }
1184bf93bf79SJacob Keller 
1185bf93bf79SJacob Keller /**
1186bf93bf79SJacob Keller  * ice_vf_ena_txq_interrupt - enable Tx queue interrupt via QINT_TQCTL
1187bf93bf79SJacob Keller  * @vsi: VSI of the VF to configure
1188bf93bf79SJacob Keller  * @q_idx: VF queue index used to determine the queue in the PF's space
1189bf93bf79SJacob Keller  */
1190bf93bf79SJacob Keller static void ice_vf_ena_txq_interrupt(struct ice_vsi *vsi, u32 q_idx)
1191bf93bf79SJacob Keller {
1192bf93bf79SJacob Keller 	struct ice_hw *hw = &vsi->back->hw;
1193bf93bf79SJacob Keller 	u32 pfq = vsi->txq_map[q_idx];
1194bf93bf79SJacob Keller 	u32 reg;
1195bf93bf79SJacob Keller 
1196bf93bf79SJacob Keller 	reg = rd32(hw, QINT_TQCTL(pfq));
1197bf93bf79SJacob Keller 
1198bf93bf79SJacob Keller 	/* MSI-X index 0 in the VF's space is always for the OICR, which means
1199bf93bf79SJacob Keller 	 * this is most likely a poll mode VF driver, so don't enable an
1200bf93bf79SJacob Keller 	 * interrupt that was never configured via VIRTCHNL_OP_CONFIG_IRQ_MAP
1201bf93bf79SJacob Keller 	 */
1202bf93bf79SJacob Keller 	if (!(reg & QINT_TQCTL_MSIX_INDX_M))
1203bf93bf79SJacob Keller 		return;
1204bf93bf79SJacob Keller 
1205bf93bf79SJacob Keller 	wr32(hw, QINT_TQCTL(pfq), reg | QINT_TQCTL_CAUSE_ENA_M);
1206bf93bf79SJacob Keller }
1207bf93bf79SJacob Keller 
1208bf93bf79SJacob Keller /**
1209bf93bf79SJacob Keller  * ice_vf_ena_rxq_interrupt - enable Tx queue interrupt via QINT_RQCTL
1210bf93bf79SJacob Keller  * @vsi: VSI of the VF to configure
1211bf93bf79SJacob Keller  * @q_idx: VF queue index used to determine the queue in the PF's space
1212bf93bf79SJacob Keller  */
1213bf93bf79SJacob Keller static void ice_vf_ena_rxq_interrupt(struct ice_vsi *vsi, u32 q_idx)
1214bf93bf79SJacob Keller {
1215bf93bf79SJacob Keller 	struct ice_hw *hw = &vsi->back->hw;
1216bf93bf79SJacob Keller 	u32 pfq = vsi->rxq_map[q_idx];
1217bf93bf79SJacob Keller 	u32 reg;
1218bf93bf79SJacob Keller 
1219bf93bf79SJacob Keller 	reg = rd32(hw, QINT_RQCTL(pfq));
1220bf93bf79SJacob Keller 
1221bf93bf79SJacob Keller 	/* MSI-X index 0 in the VF's space is always for the OICR, which means
1222bf93bf79SJacob Keller 	 * this is most likely a poll mode VF driver, so don't enable an
1223bf93bf79SJacob Keller 	 * interrupt that was never configured via VIRTCHNL_OP_CONFIG_IRQ_MAP
1224bf93bf79SJacob Keller 	 */
1225bf93bf79SJacob Keller 	if (!(reg & QINT_RQCTL_MSIX_INDX_M))
1226bf93bf79SJacob Keller 		return;
1227bf93bf79SJacob Keller 
1228bf93bf79SJacob Keller 	wr32(hw, QINT_RQCTL(pfq), reg | QINT_RQCTL_CAUSE_ENA_M);
1229bf93bf79SJacob Keller }
1230bf93bf79SJacob Keller 
1231bf93bf79SJacob Keller /**
1232bf93bf79SJacob Keller  * ice_vc_ena_qs_msg
1233bf93bf79SJacob Keller  * @vf: pointer to the VF info
1234bf93bf79SJacob Keller  * @msg: pointer to the msg buffer
1235bf93bf79SJacob Keller  *
1236bf93bf79SJacob Keller  * called from the VF to enable all or specific queue(s)
1237bf93bf79SJacob Keller  */
1238bf93bf79SJacob Keller static int ice_vc_ena_qs_msg(struct ice_vf *vf, u8 *msg)
1239bf93bf79SJacob Keller {
1240bf93bf79SJacob Keller 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
1241bf93bf79SJacob Keller 	struct virtchnl_queue_select *vqs =
1242bf93bf79SJacob Keller 	    (struct virtchnl_queue_select *)msg;
1243bf93bf79SJacob Keller 	struct ice_vsi *vsi;
1244bf93bf79SJacob Keller 	unsigned long q_map;
1245bf93bf79SJacob Keller 	u16 vf_q_id;
1246bf93bf79SJacob Keller 
1247bf93bf79SJacob Keller 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
1248bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1249bf93bf79SJacob Keller 		goto error_param;
1250bf93bf79SJacob Keller 	}
1251bf93bf79SJacob Keller 
1252bf93bf79SJacob Keller 	if (!ice_vc_isvalid_vsi_id(vf, vqs->vsi_id)) {
1253bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1254bf93bf79SJacob Keller 		goto error_param;
1255bf93bf79SJacob Keller 	}
1256bf93bf79SJacob Keller 
1257bf93bf79SJacob Keller 	if (!ice_vc_validate_vqs_bitmaps(vqs)) {
1258bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1259bf93bf79SJacob Keller 		goto error_param;
1260bf93bf79SJacob Keller 	}
1261bf93bf79SJacob Keller 
1262bf93bf79SJacob Keller 	vsi = ice_get_vf_vsi(vf);
1263bf93bf79SJacob Keller 	if (!vsi) {
1264bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1265bf93bf79SJacob Keller 		goto error_param;
1266bf93bf79SJacob Keller 	}
1267bf93bf79SJacob Keller 
1268bf93bf79SJacob Keller 	/* Enable only Rx rings, Tx rings were enabled by the FW when the
1269bf93bf79SJacob Keller 	 * Tx queue group list was configured and the context bits were
1270bf93bf79SJacob Keller 	 * programmed using ice_vsi_cfg_txqs
1271bf93bf79SJacob Keller 	 */
1272bf93bf79SJacob Keller 	q_map = vqs->rx_queues;
1273bf93bf79SJacob Keller 	for_each_set_bit(vf_q_id, &q_map, ICE_MAX_RSS_QS_PER_VF) {
1274bf93bf79SJacob Keller 		if (!ice_vc_isvalid_q_id(vf, vqs->vsi_id, vf_q_id)) {
1275bf93bf79SJacob Keller 			v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1276bf93bf79SJacob Keller 			goto error_param;
1277bf93bf79SJacob Keller 		}
1278bf93bf79SJacob Keller 
1279bf93bf79SJacob Keller 		/* Skip queue if enabled */
1280bf93bf79SJacob Keller 		if (test_bit(vf_q_id, vf->rxq_ena))
1281bf93bf79SJacob Keller 			continue;
1282bf93bf79SJacob Keller 
1283bf93bf79SJacob Keller 		if (ice_vsi_ctrl_one_rx_ring(vsi, true, vf_q_id, true)) {
1284bf93bf79SJacob Keller 			dev_err(ice_pf_to_dev(vsi->back), "Failed to enable Rx ring %d on VSI %d\n",
1285bf93bf79SJacob Keller 				vf_q_id, vsi->vsi_num);
1286bf93bf79SJacob Keller 			v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1287bf93bf79SJacob Keller 			goto error_param;
1288bf93bf79SJacob Keller 		}
1289bf93bf79SJacob Keller 
1290bf93bf79SJacob Keller 		ice_vf_ena_rxq_interrupt(vsi, vf_q_id);
1291bf93bf79SJacob Keller 		set_bit(vf_q_id, vf->rxq_ena);
1292bf93bf79SJacob Keller 	}
1293bf93bf79SJacob Keller 
1294bf93bf79SJacob Keller 	q_map = vqs->tx_queues;
1295bf93bf79SJacob Keller 	for_each_set_bit(vf_q_id, &q_map, ICE_MAX_RSS_QS_PER_VF) {
1296bf93bf79SJacob Keller 		if (!ice_vc_isvalid_q_id(vf, vqs->vsi_id, vf_q_id)) {
1297bf93bf79SJacob Keller 			v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1298bf93bf79SJacob Keller 			goto error_param;
1299bf93bf79SJacob Keller 		}
1300bf93bf79SJacob Keller 
1301bf93bf79SJacob Keller 		/* Skip queue if enabled */
1302bf93bf79SJacob Keller 		if (test_bit(vf_q_id, vf->txq_ena))
1303bf93bf79SJacob Keller 			continue;
1304bf93bf79SJacob Keller 
1305bf93bf79SJacob Keller 		ice_vf_ena_txq_interrupt(vsi, vf_q_id);
1306bf93bf79SJacob Keller 		set_bit(vf_q_id, vf->txq_ena);
1307bf93bf79SJacob Keller 	}
1308bf93bf79SJacob Keller 
1309bf93bf79SJacob Keller 	/* Set flag to indicate that queues are enabled */
1310bf93bf79SJacob Keller 	if (v_ret == VIRTCHNL_STATUS_SUCCESS)
1311bf93bf79SJacob Keller 		set_bit(ICE_VF_STATE_QS_ENA, vf->vf_states);
1312bf93bf79SJacob Keller 
1313bf93bf79SJacob Keller error_param:
1314bf93bf79SJacob Keller 	/* send the response to the VF */
1315bf93bf79SJacob Keller 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_ENABLE_QUEUES, v_ret,
1316bf93bf79SJacob Keller 				     NULL, 0);
1317bf93bf79SJacob Keller }
1318bf93bf79SJacob Keller 
1319bf93bf79SJacob Keller /**
13206096dae9SAnatolii Gerasymenko  * ice_vf_vsi_dis_single_txq - disable a single Tx queue
13216096dae9SAnatolii Gerasymenko  * @vf: VF to disable queue for
13226096dae9SAnatolii Gerasymenko  * @vsi: VSI for the VF
13236096dae9SAnatolii Gerasymenko  * @q_id: VF relative (0-based) queue ID
13246096dae9SAnatolii Gerasymenko  *
13256096dae9SAnatolii Gerasymenko  * Attempt to disable the Tx queue passed in. If the Tx queue was successfully
13266096dae9SAnatolii Gerasymenko  * disabled then clear q_id bit in the enabled queues bitmap and return
13276096dae9SAnatolii Gerasymenko  * success. Otherwise return error.
13286096dae9SAnatolii Gerasymenko  */
13296096dae9SAnatolii Gerasymenko static int
13306096dae9SAnatolii Gerasymenko ice_vf_vsi_dis_single_txq(struct ice_vf *vf, struct ice_vsi *vsi, u16 q_id)
13316096dae9SAnatolii Gerasymenko {
13326096dae9SAnatolii Gerasymenko 	struct ice_txq_meta txq_meta = { 0 };
13336096dae9SAnatolii Gerasymenko 	struct ice_tx_ring *ring;
13346096dae9SAnatolii Gerasymenko 	int err;
13356096dae9SAnatolii Gerasymenko 
13366096dae9SAnatolii Gerasymenko 	if (!test_bit(q_id, vf->txq_ena))
13376096dae9SAnatolii Gerasymenko 		dev_dbg(ice_pf_to_dev(vsi->back), "Queue %u on VSI %u is not enabled, but stopping it anyway\n",
13386096dae9SAnatolii Gerasymenko 			q_id, vsi->vsi_num);
13396096dae9SAnatolii Gerasymenko 
13406096dae9SAnatolii Gerasymenko 	ring = vsi->tx_rings[q_id];
13416096dae9SAnatolii Gerasymenko 	if (!ring)
13426096dae9SAnatolii Gerasymenko 		return -EINVAL;
13436096dae9SAnatolii Gerasymenko 
13446096dae9SAnatolii Gerasymenko 	ice_fill_txq_meta(vsi, ring, &txq_meta);
13456096dae9SAnatolii Gerasymenko 
13466096dae9SAnatolii Gerasymenko 	err = ice_vsi_stop_tx_ring(vsi, ICE_NO_RESET, vf->vf_id, ring, &txq_meta);
13476096dae9SAnatolii Gerasymenko 	if (err) {
13486096dae9SAnatolii Gerasymenko 		dev_err(ice_pf_to_dev(vsi->back), "Failed to stop Tx ring %d on VSI %d\n",
13496096dae9SAnatolii Gerasymenko 			q_id, vsi->vsi_num);
13506096dae9SAnatolii Gerasymenko 		return err;
13516096dae9SAnatolii Gerasymenko 	}
13526096dae9SAnatolii Gerasymenko 
13536096dae9SAnatolii Gerasymenko 	/* Clear enabled queues flag */
13546096dae9SAnatolii Gerasymenko 	clear_bit(q_id, vf->txq_ena);
13556096dae9SAnatolii Gerasymenko 
13566096dae9SAnatolii Gerasymenko 	return 0;
13576096dae9SAnatolii Gerasymenko }
13586096dae9SAnatolii Gerasymenko 
13596096dae9SAnatolii Gerasymenko /**
1360bf93bf79SJacob Keller  * ice_vc_dis_qs_msg
1361bf93bf79SJacob Keller  * @vf: pointer to the VF info
1362bf93bf79SJacob Keller  * @msg: pointer to the msg buffer
1363bf93bf79SJacob Keller  *
13646096dae9SAnatolii Gerasymenko  * called from the VF to disable all or specific queue(s)
1365bf93bf79SJacob Keller  */
1366bf93bf79SJacob Keller static int ice_vc_dis_qs_msg(struct ice_vf *vf, u8 *msg)
1367bf93bf79SJacob Keller {
1368bf93bf79SJacob Keller 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
1369bf93bf79SJacob Keller 	struct virtchnl_queue_select *vqs =
1370bf93bf79SJacob Keller 	    (struct virtchnl_queue_select *)msg;
1371bf93bf79SJacob Keller 	struct ice_vsi *vsi;
1372bf93bf79SJacob Keller 	unsigned long q_map;
1373bf93bf79SJacob Keller 	u16 vf_q_id;
1374bf93bf79SJacob Keller 
1375bf93bf79SJacob Keller 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states) &&
1376bf93bf79SJacob Keller 	    !test_bit(ICE_VF_STATE_QS_ENA, vf->vf_states)) {
1377bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1378bf93bf79SJacob Keller 		goto error_param;
1379bf93bf79SJacob Keller 	}
1380bf93bf79SJacob Keller 
1381bf93bf79SJacob Keller 	if (!ice_vc_isvalid_vsi_id(vf, vqs->vsi_id)) {
1382bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1383bf93bf79SJacob Keller 		goto error_param;
1384bf93bf79SJacob Keller 	}
1385bf93bf79SJacob Keller 
1386bf93bf79SJacob Keller 	if (!ice_vc_validate_vqs_bitmaps(vqs)) {
1387bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1388bf93bf79SJacob Keller 		goto error_param;
1389bf93bf79SJacob Keller 	}
1390bf93bf79SJacob Keller 
1391bf93bf79SJacob Keller 	vsi = ice_get_vf_vsi(vf);
1392bf93bf79SJacob Keller 	if (!vsi) {
1393bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1394bf93bf79SJacob Keller 		goto error_param;
1395bf93bf79SJacob Keller 	}
1396bf93bf79SJacob Keller 
1397bf93bf79SJacob Keller 	if (vqs->tx_queues) {
1398bf93bf79SJacob Keller 		q_map = vqs->tx_queues;
1399bf93bf79SJacob Keller 
1400bf93bf79SJacob Keller 		for_each_set_bit(vf_q_id, &q_map, ICE_MAX_RSS_QS_PER_VF) {
1401bf93bf79SJacob Keller 			if (!ice_vc_isvalid_q_id(vf, vqs->vsi_id, vf_q_id)) {
1402bf93bf79SJacob Keller 				v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1403bf93bf79SJacob Keller 				goto error_param;
1404bf93bf79SJacob Keller 			}
1405bf93bf79SJacob Keller 
14066096dae9SAnatolii Gerasymenko 			if (ice_vf_vsi_dis_single_txq(vf, vsi, vf_q_id)) {
1407bf93bf79SJacob Keller 				v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1408bf93bf79SJacob Keller 				goto error_param;
1409bf93bf79SJacob Keller 			}
1410bf93bf79SJacob Keller 		}
1411bf93bf79SJacob Keller 	}
1412bf93bf79SJacob Keller 
1413bf93bf79SJacob Keller 	q_map = vqs->rx_queues;
1414bf93bf79SJacob Keller 	/* speed up Rx queue disable by batching them if possible */
1415bf93bf79SJacob Keller 	if (q_map &&
1416bf93bf79SJacob Keller 	    bitmap_equal(&q_map, vf->rxq_ena, ICE_MAX_RSS_QS_PER_VF)) {
1417bf93bf79SJacob Keller 		if (ice_vsi_stop_all_rx_rings(vsi)) {
1418bf93bf79SJacob Keller 			dev_err(ice_pf_to_dev(vsi->back), "Failed to stop all Rx rings on VSI %d\n",
1419bf93bf79SJacob Keller 				vsi->vsi_num);
1420bf93bf79SJacob Keller 			v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1421bf93bf79SJacob Keller 			goto error_param;
1422bf93bf79SJacob Keller 		}
1423bf93bf79SJacob Keller 
1424bf93bf79SJacob Keller 		bitmap_zero(vf->rxq_ena, ICE_MAX_RSS_QS_PER_VF);
1425bf93bf79SJacob Keller 	} else if (q_map) {
1426bf93bf79SJacob Keller 		for_each_set_bit(vf_q_id, &q_map, ICE_MAX_RSS_QS_PER_VF) {
1427bf93bf79SJacob Keller 			if (!ice_vc_isvalid_q_id(vf, vqs->vsi_id, vf_q_id)) {
1428bf93bf79SJacob Keller 				v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1429bf93bf79SJacob Keller 				goto error_param;
1430bf93bf79SJacob Keller 			}
1431bf93bf79SJacob Keller 
1432bf93bf79SJacob Keller 			/* Skip queue if not enabled */
1433bf93bf79SJacob Keller 			if (!test_bit(vf_q_id, vf->rxq_ena))
1434bf93bf79SJacob Keller 				continue;
1435bf93bf79SJacob Keller 
1436bf93bf79SJacob Keller 			if (ice_vsi_ctrl_one_rx_ring(vsi, false, vf_q_id,
1437bf93bf79SJacob Keller 						     true)) {
1438bf93bf79SJacob Keller 				dev_err(ice_pf_to_dev(vsi->back), "Failed to stop Rx ring %d on VSI %d\n",
1439bf93bf79SJacob Keller 					vf_q_id, vsi->vsi_num);
1440bf93bf79SJacob Keller 				v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1441bf93bf79SJacob Keller 				goto error_param;
1442bf93bf79SJacob Keller 			}
1443bf93bf79SJacob Keller 
1444bf93bf79SJacob Keller 			/* Clear enabled queues flag */
1445bf93bf79SJacob Keller 			clear_bit(vf_q_id, vf->rxq_ena);
1446bf93bf79SJacob Keller 		}
1447bf93bf79SJacob Keller 	}
1448bf93bf79SJacob Keller 
1449bf93bf79SJacob Keller 	/* Clear enabled queues flag */
1450bf93bf79SJacob Keller 	if (v_ret == VIRTCHNL_STATUS_SUCCESS && ice_vf_has_no_qs_ena(vf))
1451bf93bf79SJacob Keller 		clear_bit(ICE_VF_STATE_QS_ENA, vf->vf_states);
1452bf93bf79SJacob Keller 
1453bf93bf79SJacob Keller error_param:
1454bf93bf79SJacob Keller 	/* send the response to the VF */
1455bf93bf79SJacob Keller 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_DISABLE_QUEUES, v_ret,
1456bf93bf79SJacob Keller 				     NULL, 0);
1457bf93bf79SJacob Keller }
1458bf93bf79SJacob Keller 
1459bf93bf79SJacob Keller /**
1460bf93bf79SJacob Keller  * ice_cfg_interrupt
1461bf93bf79SJacob Keller  * @vf: pointer to the VF info
1462bf93bf79SJacob Keller  * @vsi: the VSI being configured
1463bf93bf79SJacob Keller  * @vector_id: vector ID
1464bf93bf79SJacob Keller  * @map: vector map for mapping vectors to queues
1465bf93bf79SJacob Keller  * @q_vector: structure for interrupt vector
1466bf93bf79SJacob Keller  * configure the IRQ to queue map
1467bf93bf79SJacob Keller  */
1468bf93bf79SJacob Keller static int
1469bf93bf79SJacob Keller ice_cfg_interrupt(struct ice_vf *vf, struct ice_vsi *vsi, u16 vector_id,
1470bf93bf79SJacob Keller 		  struct virtchnl_vector_map *map,
1471bf93bf79SJacob Keller 		  struct ice_q_vector *q_vector)
1472bf93bf79SJacob Keller {
1473bf93bf79SJacob Keller 	u16 vsi_q_id, vsi_q_id_idx;
1474bf93bf79SJacob Keller 	unsigned long qmap;
1475bf93bf79SJacob Keller 
1476bf93bf79SJacob Keller 	q_vector->num_ring_rx = 0;
1477bf93bf79SJacob Keller 	q_vector->num_ring_tx = 0;
1478bf93bf79SJacob Keller 
1479bf93bf79SJacob Keller 	qmap = map->rxq_map;
1480bf93bf79SJacob Keller 	for_each_set_bit(vsi_q_id_idx, &qmap, ICE_MAX_RSS_QS_PER_VF) {
1481bf93bf79SJacob Keller 		vsi_q_id = vsi_q_id_idx;
1482bf93bf79SJacob Keller 
1483bf93bf79SJacob Keller 		if (!ice_vc_isvalid_q_id(vf, vsi->vsi_num, vsi_q_id))
1484bf93bf79SJacob Keller 			return VIRTCHNL_STATUS_ERR_PARAM;
1485bf93bf79SJacob Keller 
1486bf93bf79SJacob Keller 		q_vector->num_ring_rx++;
1487bf93bf79SJacob Keller 		q_vector->rx.itr_idx = map->rxitr_idx;
1488bf93bf79SJacob Keller 		vsi->rx_rings[vsi_q_id]->q_vector = q_vector;
1489bf93bf79SJacob Keller 		ice_cfg_rxq_interrupt(vsi, vsi_q_id, vector_id,
1490bf93bf79SJacob Keller 				      q_vector->rx.itr_idx);
1491bf93bf79SJacob Keller 	}
1492bf93bf79SJacob Keller 
1493bf93bf79SJacob Keller 	qmap = map->txq_map;
1494bf93bf79SJacob Keller 	for_each_set_bit(vsi_q_id_idx, &qmap, ICE_MAX_RSS_QS_PER_VF) {
1495bf93bf79SJacob Keller 		vsi_q_id = vsi_q_id_idx;
1496bf93bf79SJacob Keller 
1497bf93bf79SJacob Keller 		if (!ice_vc_isvalid_q_id(vf, vsi->vsi_num, vsi_q_id))
1498bf93bf79SJacob Keller 			return VIRTCHNL_STATUS_ERR_PARAM;
1499bf93bf79SJacob Keller 
1500bf93bf79SJacob Keller 		q_vector->num_ring_tx++;
1501bf93bf79SJacob Keller 		q_vector->tx.itr_idx = map->txitr_idx;
1502bf93bf79SJacob Keller 		vsi->tx_rings[vsi_q_id]->q_vector = q_vector;
1503bf93bf79SJacob Keller 		ice_cfg_txq_interrupt(vsi, vsi_q_id, vector_id,
1504bf93bf79SJacob Keller 				      q_vector->tx.itr_idx);
1505bf93bf79SJacob Keller 	}
1506bf93bf79SJacob Keller 
1507bf93bf79SJacob Keller 	return VIRTCHNL_STATUS_SUCCESS;
1508bf93bf79SJacob Keller }
1509bf93bf79SJacob Keller 
1510bf93bf79SJacob Keller /**
1511bf93bf79SJacob Keller  * ice_vc_cfg_irq_map_msg
1512bf93bf79SJacob Keller  * @vf: pointer to the VF info
1513bf93bf79SJacob Keller  * @msg: pointer to the msg buffer
1514bf93bf79SJacob Keller  *
1515bf93bf79SJacob Keller  * called from the VF to configure the IRQ to queue map
1516bf93bf79SJacob Keller  */
1517bf93bf79SJacob Keller static int ice_vc_cfg_irq_map_msg(struct ice_vf *vf, u8 *msg)
1518bf93bf79SJacob Keller {
1519bf93bf79SJacob Keller 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
1520bf93bf79SJacob Keller 	u16 num_q_vectors_mapped, vsi_id, vector_id;
1521bf93bf79SJacob Keller 	struct virtchnl_irq_map_info *irqmap_info;
1522bf93bf79SJacob Keller 	struct virtchnl_vector_map *map;
1523bf93bf79SJacob Keller 	struct ice_pf *pf = vf->pf;
1524bf93bf79SJacob Keller 	struct ice_vsi *vsi;
1525bf93bf79SJacob Keller 	int i;
1526bf93bf79SJacob Keller 
1527bf93bf79SJacob Keller 	irqmap_info = (struct virtchnl_irq_map_info *)msg;
1528bf93bf79SJacob Keller 	num_q_vectors_mapped = irqmap_info->num_vectors;
1529bf93bf79SJacob Keller 
1530bf93bf79SJacob Keller 	/* Check to make sure number of VF vectors mapped is not greater than
1531bf93bf79SJacob Keller 	 * number of VF vectors originally allocated, and check that
1532bf93bf79SJacob Keller 	 * there is actually at least a single VF queue vector mapped
1533bf93bf79SJacob Keller 	 */
1534bf93bf79SJacob Keller 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states) ||
1535bf93bf79SJacob Keller 	    pf->vfs.num_msix_per < num_q_vectors_mapped ||
1536bf93bf79SJacob Keller 	    !num_q_vectors_mapped) {
1537bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1538bf93bf79SJacob Keller 		goto error_param;
1539bf93bf79SJacob Keller 	}
1540bf93bf79SJacob Keller 
1541bf93bf79SJacob Keller 	vsi = ice_get_vf_vsi(vf);
1542bf93bf79SJacob Keller 	if (!vsi) {
1543bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1544bf93bf79SJacob Keller 		goto error_param;
1545bf93bf79SJacob Keller 	}
1546bf93bf79SJacob Keller 
1547bf93bf79SJacob Keller 	for (i = 0; i < num_q_vectors_mapped; i++) {
1548bf93bf79SJacob Keller 		struct ice_q_vector *q_vector;
1549bf93bf79SJacob Keller 
1550bf93bf79SJacob Keller 		map = &irqmap_info->vecmap[i];
1551bf93bf79SJacob Keller 
1552bf93bf79SJacob Keller 		vector_id = map->vector_id;
1553bf93bf79SJacob Keller 		vsi_id = map->vsi_id;
1554bf93bf79SJacob Keller 		/* vector_id is always 0-based for each VF, and can never be
1555bf93bf79SJacob Keller 		 * larger than or equal to the max allowed interrupts per VF
1556bf93bf79SJacob Keller 		 */
1557bf93bf79SJacob Keller 		if (!(vector_id < pf->vfs.num_msix_per) ||
1558bf93bf79SJacob Keller 		    !ice_vc_isvalid_vsi_id(vf, vsi_id) ||
1559bf93bf79SJacob Keller 		    (!vector_id && (map->rxq_map || map->txq_map))) {
1560bf93bf79SJacob Keller 			v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1561bf93bf79SJacob Keller 			goto error_param;
1562bf93bf79SJacob Keller 		}
1563bf93bf79SJacob Keller 
1564bf93bf79SJacob Keller 		/* No need to map VF miscellaneous or rogue vector */
1565bf93bf79SJacob Keller 		if (!vector_id)
1566bf93bf79SJacob Keller 			continue;
1567bf93bf79SJacob Keller 
1568bf93bf79SJacob Keller 		/* Subtract non queue vector from vector_id passed by VF
1569bf93bf79SJacob Keller 		 * to get actual number of VSI queue vector array index
1570bf93bf79SJacob Keller 		 */
1571bf93bf79SJacob Keller 		q_vector = vsi->q_vectors[vector_id - ICE_NONQ_VECS_VF];
1572bf93bf79SJacob Keller 		if (!q_vector) {
1573bf93bf79SJacob Keller 			v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1574bf93bf79SJacob Keller 			goto error_param;
1575bf93bf79SJacob Keller 		}
1576bf93bf79SJacob Keller 
1577bf93bf79SJacob Keller 		/* lookout for the invalid queue index */
1578bf93bf79SJacob Keller 		v_ret = (enum virtchnl_status_code)
1579bf93bf79SJacob Keller 			ice_cfg_interrupt(vf, vsi, vector_id, map, q_vector);
1580bf93bf79SJacob Keller 		if (v_ret)
1581bf93bf79SJacob Keller 			goto error_param;
1582bf93bf79SJacob Keller 	}
1583bf93bf79SJacob Keller 
1584bf93bf79SJacob Keller error_param:
1585bf93bf79SJacob Keller 	/* send the response to the VF */
1586bf93bf79SJacob Keller 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_IRQ_MAP, v_ret,
1587bf93bf79SJacob Keller 				     NULL, 0);
1588bf93bf79SJacob Keller }
1589bf93bf79SJacob Keller 
1590bf93bf79SJacob Keller /**
1591bf93bf79SJacob Keller  * ice_vc_cfg_qs_msg
1592bf93bf79SJacob Keller  * @vf: pointer to the VF info
1593bf93bf79SJacob Keller  * @msg: pointer to the msg buffer
1594bf93bf79SJacob Keller  *
1595bf93bf79SJacob Keller  * called from the VF to configure the Rx/Tx queues
1596bf93bf79SJacob Keller  */
1597bf93bf79SJacob Keller static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg)
1598bf93bf79SJacob Keller {
1599bf93bf79SJacob Keller 	struct virtchnl_vsi_queue_config_info *qci =
1600bf93bf79SJacob Keller 	    (struct virtchnl_vsi_queue_config_info *)msg;
1601bf93bf79SJacob Keller 	struct virtchnl_queue_pair_info *qpi;
1602bf93bf79SJacob Keller 	struct ice_pf *pf = vf->pf;
1603bf93bf79SJacob Keller 	struct ice_vsi *vsi;
1604be2af714SPrzemyslaw Patynowski 	int i = -1, q_idx;
1605bf93bf79SJacob Keller 
1606be2af714SPrzemyslaw Patynowski 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states))
1607bf93bf79SJacob Keller 		goto error_param;
1608bf93bf79SJacob Keller 
1609be2af714SPrzemyslaw Patynowski 	if (!ice_vc_isvalid_vsi_id(vf, qci->vsi_id))
1610bf93bf79SJacob Keller 		goto error_param;
1611bf93bf79SJacob Keller 
1612bf93bf79SJacob Keller 	vsi = ice_get_vf_vsi(vf);
1613be2af714SPrzemyslaw Patynowski 	if (!vsi)
1614bf93bf79SJacob Keller 		goto error_param;
1615bf93bf79SJacob Keller 
1616bf93bf79SJacob Keller 	if (qci->num_queue_pairs > ICE_MAX_RSS_QS_PER_VF ||
1617bf93bf79SJacob Keller 	    qci->num_queue_pairs > min_t(u16, vsi->alloc_txq, vsi->alloc_rxq)) {
1618bf93bf79SJacob Keller 		dev_err(ice_pf_to_dev(pf), "VF-%d requesting more than supported number of queues: %d\n",
1619bf93bf79SJacob Keller 			vf->vf_id, min_t(u16, vsi->alloc_txq, vsi->alloc_rxq));
1620bf93bf79SJacob Keller 		goto error_param;
1621bf93bf79SJacob Keller 	}
1622bf93bf79SJacob Keller 
1623bf93bf79SJacob Keller 	for (i = 0; i < qci->num_queue_pairs; i++) {
1624bf93bf79SJacob Keller 		qpi = &qci->qpair[i];
1625bf93bf79SJacob Keller 		if (qpi->txq.vsi_id != qci->vsi_id ||
1626bf93bf79SJacob Keller 		    qpi->rxq.vsi_id != qci->vsi_id ||
1627bf93bf79SJacob Keller 		    qpi->rxq.queue_id != qpi->txq.queue_id ||
1628bf93bf79SJacob Keller 		    qpi->txq.headwb_enabled ||
1629bf93bf79SJacob Keller 		    !ice_vc_isvalid_ring_len(qpi->txq.ring_len) ||
1630bf93bf79SJacob Keller 		    !ice_vc_isvalid_ring_len(qpi->rxq.ring_len) ||
1631bf93bf79SJacob Keller 		    !ice_vc_isvalid_q_id(vf, qci->vsi_id, qpi->txq.queue_id)) {
1632bf93bf79SJacob Keller 			goto error_param;
1633bf93bf79SJacob Keller 		}
1634bf93bf79SJacob Keller 
1635bf93bf79SJacob Keller 		q_idx = qpi->rxq.queue_id;
1636bf93bf79SJacob Keller 
1637bf93bf79SJacob Keller 		/* make sure selected "q_idx" is in valid range of queues
1638bf93bf79SJacob Keller 		 * for selected "vsi"
1639bf93bf79SJacob Keller 		 */
1640bf93bf79SJacob Keller 		if (q_idx >= vsi->alloc_txq || q_idx >= vsi->alloc_rxq) {
1641bf93bf79SJacob Keller 			goto error_param;
1642bf93bf79SJacob Keller 		}
1643bf93bf79SJacob Keller 
1644bf93bf79SJacob Keller 		/* copy Tx queue info from VF into VSI */
1645bf93bf79SJacob Keller 		if (qpi->txq.ring_len > 0) {
1646bf93bf79SJacob Keller 			vsi->tx_rings[i]->dma = qpi->txq.dma_ring_addr;
1647bf93bf79SJacob Keller 			vsi->tx_rings[i]->count = qpi->txq.ring_len;
16486096dae9SAnatolii Gerasymenko 
16496096dae9SAnatolii Gerasymenko 			/* Disable any existing queue first */
1650be2af714SPrzemyslaw Patynowski 			if (ice_vf_vsi_dis_single_txq(vf, vsi, q_idx))
16516096dae9SAnatolii Gerasymenko 				goto error_param;
16526096dae9SAnatolii Gerasymenko 
16536096dae9SAnatolii Gerasymenko 			/* Configure a queue with the requested settings */
1654bf93bf79SJacob Keller 			if (ice_vsi_cfg_single_txq(vsi, vsi->tx_rings, q_idx)) {
1655be2af714SPrzemyslaw Patynowski 				dev_warn(ice_pf_to_dev(pf), "VF-%d failed to configure TX queue %d\n",
1656be2af714SPrzemyslaw Patynowski 					 vf->vf_id, i);
1657bf93bf79SJacob Keller 				goto error_param;
1658bf93bf79SJacob Keller 			}
1659bf93bf79SJacob Keller 		}
1660bf93bf79SJacob Keller 
1661bf93bf79SJacob Keller 		/* copy Rx queue info from VF into VSI */
1662bf93bf79SJacob Keller 		if (qpi->rxq.ring_len > 0) {
1663bf93bf79SJacob Keller 			u16 max_frame_size = ice_vc_get_max_frame_size(vf);
1664c7cb9dfcSMarcin Szycik 			u32 rxdid;
1665bf93bf79SJacob Keller 
1666bf93bf79SJacob Keller 			vsi->rx_rings[i]->dma = qpi->rxq.dma_ring_addr;
1667bf93bf79SJacob Keller 			vsi->rx_rings[i]->count = qpi->rxq.ring_len;
1668bf93bf79SJacob Keller 
1669bf93bf79SJacob Keller 			if (qpi->rxq.databuffer_size != 0 &&
1670bf93bf79SJacob Keller 			    (qpi->rxq.databuffer_size > ((16 * 1024) - 128) ||
1671be2af714SPrzemyslaw Patynowski 			     qpi->rxq.databuffer_size < 1024))
1672bf93bf79SJacob Keller 				goto error_param;
1673bf93bf79SJacob Keller 			vsi->rx_buf_len = qpi->rxq.databuffer_size;
1674bf93bf79SJacob Keller 			vsi->rx_rings[i]->rx_buf_len = vsi->rx_buf_len;
1675bf93bf79SJacob Keller 			if (qpi->rxq.max_pkt_size > max_frame_size ||
1676be2af714SPrzemyslaw Patynowski 			    qpi->rxq.max_pkt_size < 64)
1677bf93bf79SJacob Keller 				goto error_param;
1678bf93bf79SJacob Keller 
1679bf93bf79SJacob Keller 			vsi->max_frame = qpi->rxq.max_pkt_size;
1680bf93bf79SJacob Keller 			/* add space for the port VLAN since the VF driver is
1681bf93bf79SJacob Keller 			 * not expected to account for it in the MTU
1682bf93bf79SJacob Keller 			 * calculation
1683bf93bf79SJacob Keller 			 */
1684bf93bf79SJacob Keller 			if (ice_vf_is_port_vlan_ena(vf))
1685bf93bf79SJacob Keller 				vsi->max_frame += VLAN_HLEN;
1686bf93bf79SJacob Keller 
1687bf93bf79SJacob Keller 			if (ice_vsi_cfg_single_rxq(vsi, q_idx)) {
1688be2af714SPrzemyslaw Patynowski 				dev_warn(ice_pf_to_dev(pf), "VF-%d failed to configure RX queue %d\n",
1689be2af714SPrzemyslaw Patynowski 					 vf->vf_id, i);
1690bf93bf79SJacob Keller 				goto error_param;
1691bf93bf79SJacob Keller 			}
1692e753df8fSMichal Jaron 
1693c7cb9dfcSMarcin Szycik 			/* If Rx flex desc is supported, select RXDID for Rx
1694c7cb9dfcSMarcin Szycik 			 * queues. Otherwise, use legacy 32byte descriptor
1695c7cb9dfcSMarcin Szycik 			 * format. Legacy 16byte descriptor is not supported.
1696c7cb9dfcSMarcin Szycik 			 * If this RXDID is selected, return error.
1697e753df8fSMichal Jaron 			 */
1698c7cb9dfcSMarcin Szycik 			if (vf->driver_caps &
1699c7cb9dfcSMarcin Szycik 			    VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC) {
1700c7cb9dfcSMarcin Szycik 				rxdid = qpi->rxq.rxdid;
1701e753df8fSMichal Jaron 				if (!(BIT(rxdid) & pf->supported_rxdids))
1702e753df8fSMichal Jaron 					goto error_param;
1703e753df8fSMichal Jaron 			} else {
1704e753df8fSMichal Jaron 				rxdid = ICE_RXDID_LEGACY_1;
1705e753df8fSMichal Jaron 			}
1706e753df8fSMichal Jaron 
1707c7cb9dfcSMarcin Szycik 			ice_write_qrxflxp_cntxt(&vsi->back->hw,
1708c7cb9dfcSMarcin Szycik 						vsi->rxq_map[q_idx],
1709c7cb9dfcSMarcin Szycik 						rxdid, 0x03, false);
1710c7cb9dfcSMarcin Szycik 		}
1711bf93bf79SJacob Keller 	}
1712bf93bf79SJacob Keller 
1713bf93bf79SJacob Keller 	/* send the response to the VF */
1714be2af714SPrzemyslaw Patynowski 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_VSI_QUEUES,
1715be2af714SPrzemyslaw Patynowski 				     VIRTCHNL_STATUS_SUCCESS, NULL, 0);
1716be2af714SPrzemyslaw Patynowski error_param:
1717be2af714SPrzemyslaw Patynowski 	/* disable whatever we can */
1718be2af714SPrzemyslaw Patynowski 	for (; i >= 0; i--) {
1719be2af714SPrzemyslaw Patynowski 		if (ice_vsi_ctrl_one_rx_ring(vsi, false, i, true))
1720be2af714SPrzemyslaw Patynowski 			dev_err(ice_pf_to_dev(pf), "VF-%d could not disable RX queue %d\n",
1721be2af714SPrzemyslaw Patynowski 				vf->vf_id, i);
1722be2af714SPrzemyslaw Patynowski 		if (ice_vf_vsi_dis_single_txq(vf, vsi, i))
1723be2af714SPrzemyslaw Patynowski 			dev_err(ice_pf_to_dev(pf), "VF-%d could not disable TX queue %d\n",
1724be2af714SPrzemyslaw Patynowski 				vf->vf_id, i);
1725be2af714SPrzemyslaw Patynowski 	}
1726be2af714SPrzemyslaw Patynowski 
1727ec5a6c5fSDave Ertman 	ice_lag_move_new_vf_nodes(vf);
1728ec5a6c5fSDave Ertman 
1729be2af714SPrzemyslaw Patynowski 	/* send the response to the VF */
1730be2af714SPrzemyslaw Patynowski 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_VSI_QUEUES,
1731be2af714SPrzemyslaw Patynowski 				     VIRTCHNL_STATUS_ERR_PARAM, NULL, 0);
1732bf93bf79SJacob Keller }
1733bf93bf79SJacob Keller 
1734bf93bf79SJacob Keller /**
1735bf93bf79SJacob Keller  * ice_can_vf_change_mac
1736bf93bf79SJacob Keller  * @vf: pointer to the VF info
1737bf93bf79SJacob Keller  *
1738bf93bf79SJacob Keller  * Return true if the VF is allowed to change its MAC filters, false otherwise
1739bf93bf79SJacob Keller  */
1740bf93bf79SJacob Keller static bool ice_can_vf_change_mac(struct ice_vf *vf)
1741bf93bf79SJacob Keller {
1742bf93bf79SJacob Keller 	/* If the VF MAC address has been set administratively (via the
1743bf93bf79SJacob Keller 	 * ndo_set_vf_mac command), then deny permission to the VF to
1744bf93bf79SJacob Keller 	 * add/delete unicast MAC addresses, unless the VF is trusted
1745bf93bf79SJacob Keller 	 */
1746bf93bf79SJacob Keller 	if (vf->pf_set_mac && !ice_is_vf_trusted(vf))
1747bf93bf79SJacob Keller 		return false;
1748bf93bf79SJacob Keller 
1749bf93bf79SJacob Keller 	return true;
1750bf93bf79SJacob Keller }
1751bf93bf79SJacob Keller 
1752bf93bf79SJacob Keller /**
1753bf93bf79SJacob Keller  * ice_vc_ether_addr_type - get type of virtchnl_ether_addr
1754bf93bf79SJacob Keller  * @vc_ether_addr: used to extract the type
1755bf93bf79SJacob Keller  */
1756bf93bf79SJacob Keller static u8
1757bf93bf79SJacob Keller ice_vc_ether_addr_type(struct virtchnl_ether_addr *vc_ether_addr)
1758bf93bf79SJacob Keller {
1759bf93bf79SJacob Keller 	return (vc_ether_addr->type & VIRTCHNL_ETHER_ADDR_TYPE_MASK);
1760bf93bf79SJacob Keller }
1761bf93bf79SJacob Keller 
1762bf93bf79SJacob Keller /**
1763bf93bf79SJacob Keller  * ice_is_vc_addr_legacy - check if the MAC address is from an older VF
1764bf93bf79SJacob Keller  * @vc_ether_addr: VIRTCHNL structure that contains MAC and type
1765bf93bf79SJacob Keller  */
1766bf93bf79SJacob Keller static bool
1767bf93bf79SJacob Keller ice_is_vc_addr_legacy(struct virtchnl_ether_addr *vc_ether_addr)
1768bf93bf79SJacob Keller {
1769bf93bf79SJacob Keller 	u8 type = ice_vc_ether_addr_type(vc_ether_addr);
1770bf93bf79SJacob Keller 
1771bf93bf79SJacob Keller 	return (type == VIRTCHNL_ETHER_ADDR_LEGACY);
1772bf93bf79SJacob Keller }
1773bf93bf79SJacob Keller 
1774bf93bf79SJacob Keller /**
1775bf93bf79SJacob Keller  * ice_is_vc_addr_primary - check if the MAC address is the VF's primary MAC
1776bf93bf79SJacob Keller  * @vc_ether_addr: VIRTCHNL structure that contains MAC and type
1777bf93bf79SJacob Keller  *
1778bf93bf79SJacob Keller  * This function should only be called when the MAC address in
1779bf93bf79SJacob Keller  * virtchnl_ether_addr is a valid unicast MAC
1780bf93bf79SJacob Keller  */
1781bf93bf79SJacob Keller static bool
1782bf93bf79SJacob Keller ice_is_vc_addr_primary(struct virtchnl_ether_addr __maybe_unused *vc_ether_addr)
1783bf93bf79SJacob Keller {
1784bf93bf79SJacob Keller 	u8 type = ice_vc_ether_addr_type(vc_ether_addr);
1785bf93bf79SJacob Keller 
1786bf93bf79SJacob Keller 	return (type == VIRTCHNL_ETHER_ADDR_PRIMARY);
1787bf93bf79SJacob Keller }
1788bf93bf79SJacob Keller 
1789bf93bf79SJacob Keller /**
1790bf93bf79SJacob Keller  * ice_vfhw_mac_add - update the VF's cached hardware MAC if allowed
1791bf93bf79SJacob Keller  * @vf: VF to update
1792bf93bf79SJacob Keller  * @vc_ether_addr: structure from VIRTCHNL with MAC to add
1793bf93bf79SJacob Keller  */
1794bf93bf79SJacob Keller static void
1795bf93bf79SJacob Keller ice_vfhw_mac_add(struct ice_vf *vf, struct virtchnl_ether_addr *vc_ether_addr)
1796bf93bf79SJacob Keller {
1797bf93bf79SJacob Keller 	u8 *mac_addr = vc_ether_addr->addr;
1798bf93bf79SJacob Keller 
1799bf93bf79SJacob Keller 	if (!is_valid_ether_addr(mac_addr))
1800bf93bf79SJacob Keller 		return;
1801bf93bf79SJacob Keller 
1802bf93bf79SJacob Keller 	/* only allow legacy VF drivers to set the device and hardware MAC if it
1803bf93bf79SJacob Keller 	 * is zero and allow new VF drivers to set the hardware MAC if the type
1804bf93bf79SJacob Keller 	 * was correctly specified over VIRTCHNL
1805bf93bf79SJacob Keller 	 */
1806bf93bf79SJacob Keller 	if ((ice_is_vc_addr_legacy(vc_ether_addr) &&
1807e0645311SJacob Keller 	     is_zero_ether_addr(vf->hw_lan_addr)) ||
1808bf93bf79SJacob Keller 	    ice_is_vc_addr_primary(vc_ether_addr)) {
1809e0645311SJacob Keller 		ether_addr_copy(vf->dev_lan_addr, mac_addr);
1810e0645311SJacob Keller 		ether_addr_copy(vf->hw_lan_addr, mac_addr);
1811bf93bf79SJacob Keller 	}
1812bf93bf79SJacob Keller 
1813bf93bf79SJacob Keller 	/* hardware and device MACs are already set, but its possible that the
1814bf93bf79SJacob Keller 	 * VF driver sent the VIRTCHNL_OP_ADD_ETH_ADDR message before the
1815bf93bf79SJacob Keller 	 * VIRTCHNL_OP_DEL_ETH_ADDR when trying to update its MAC, so save it
1816bf93bf79SJacob Keller 	 * away for the legacy VF driver case as it will be updated in the
1817bf93bf79SJacob Keller 	 * delete flow for this case
1818bf93bf79SJacob Keller 	 */
1819bf93bf79SJacob Keller 	if (ice_is_vc_addr_legacy(vc_ether_addr)) {
1820bf93bf79SJacob Keller 		ether_addr_copy(vf->legacy_last_added_umac.addr,
1821bf93bf79SJacob Keller 				mac_addr);
1822bf93bf79SJacob Keller 		vf->legacy_last_added_umac.time_modified = jiffies;
1823bf93bf79SJacob Keller 	}
1824bf93bf79SJacob Keller }
1825bf93bf79SJacob Keller 
1826bf93bf79SJacob Keller /**
1827bf93bf79SJacob Keller  * ice_vc_add_mac_addr - attempt to add the MAC address passed in
1828bf93bf79SJacob Keller  * @vf: pointer to the VF info
1829bf93bf79SJacob Keller  * @vsi: pointer to the VF's VSI
1830bf93bf79SJacob Keller  * @vc_ether_addr: VIRTCHNL MAC address structure used to add MAC
1831bf93bf79SJacob Keller  */
1832bf93bf79SJacob Keller static int
1833bf93bf79SJacob Keller ice_vc_add_mac_addr(struct ice_vf *vf, struct ice_vsi *vsi,
1834bf93bf79SJacob Keller 		    struct virtchnl_ether_addr *vc_ether_addr)
1835bf93bf79SJacob Keller {
1836bf93bf79SJacob Keller 	struct device *dev = ice_pf_to_dev(vf->pf);
1837bf93bf79SJacob Keller 	u8 *mac_addr = vc_ether_addr->addr;
1838bf93bf79SJacob Keller 	int ret;
1839bf93bf79SJacob Keller 
1840bf93bf79SJacob Keller 	/* device MAC already added */
1841e0645311SJacob Keller 	if (ether_addr_equal(mac_addr, vf->dev_lan_addr))
1842bf93bf79SJacob Keller 		return 0;
1843bf93bf79SJacob Keller 
1844bf93bf79SJacob Keller 	if (is_unicast_ether_addr(mac_addr) && !ice_can_vf_change_mac(vf)) {
1845bf93bf79SJacob Keller 		dev_err(dev, "VF attempting to override administratively set MAC address, bring down and up the VF interface to resume normal operation\n");
1846bf93bf79SJacob Keller 		return -EPERM;
1847bf93bf79SJacob Keller 	}
1848bf93bf79SJacob Keller 
1849bf93bf79SJacob Keller 	ret = ice_fltr_add_mac(vsi, mac_addr, ICE_FWD_TO_VSI);
1850bf93bf79SJacob Keller 	if (ret == -EEXIST) {
1851bf93bf79SJacob Keller 		dev_dbg(dev, "MAC %pM already exists for VF %d\n", mac_addr,
1852bf93bf79SJacob Keller 			vf->vf_id);
1853bf93bf79SJacob Keller 		/* don't return since we might need to update
1854bf93bf79SJacob Keller 		 * the primary MAC in ice_vfhw_mac_add() below
1855bf93bf79SJacob Keller 		 */
1856bf93bf79SJacob Keller 	} else if (ret) {
1857bf93bf79SJacob Keller 		dev_err(dev, "Failed to add MAC %pM for VF %d\n, error %d\n",
1858bf93bf79SJacob Keller 			mac_addr, vf->vf_id, ret);
1859bf93bf79SJacob Keller 		return ret;
1860bf93bf79SJacob Keller 	} else {
1861bf93bf79SJacob Keller 		vf->num_mac++;
1862bf93bf79SJacob Keller 	}
1863bf93bf79SJacob Keller 
1864bf93bf79SJacob Keller 	ice_vfhw_mac_add(vf, vc_ether_addr);
1865bf93bf79SJacob Keller 
1866bf93bf79SJacob Keller 	return ret;
1867bf93bf79SJacob Keller }
1868bf93bf79SJacob Keller 
1869bf93bf79SJacob Keller /**
1870bf93bf79SJacob Keller  * ice_is_legacy_umac_expired - check if last added legacy unicast MAC expired
1871bf93bf79SJacob Keller  * @last_added_umac: structure used to check expiration
1872bf93bf79SJacob Keller  */
1873bf93bf79SJacob Keller static bool ice_is_legacy_umac_expired(struct ice_time_mac *last_added_umac)
1874bf93bf79SJacob Keller {
1875bf93bf79SJacob Keller #define ICE_LEGACY_VF_MAC_CHANGE_EXPIRE_TIME	msecs_to_jiffies(3000)
1876bf93bf79SJacob Keller 	return time_is_before_jiffies(last_added_umac->time_modified +
1877bf93bf79SJacob Keller 				      ICE_LEGACY_VF_MAC_CHANGE_EXPIRE_TIME);
1878bf93bf79SJacob Keller }
1879bf93bf79SJacob Keller 
1880bf93bf79SJacob Keller /**
1881bf93bf79SJacob Keller  * ice_update_legacy_cached_mac - update cached hardware MAC for legacy VF
1882bf93bf79SJacob Keller  * @vf: VF to update
1883bf93bf79SJacob Keller  * @vc_ether_addr: structure from VIRTCHNL with MAC to check
1884bf93bf79SJacob Keller  *
1885bf93bf79SJacob Keller  * only update cached hardware MAC for legacy VF drivers on delete
1886bf93bf79SJacob Keller  * because we cannot guarantee order/type of MAC from the VF driver
1887bf93bf79SJacob Keller  */
1888bf93bf79SJacob Keller static void
1889bf93bf79SJacob Keller ice_update_legacy_cached_mac(struct ice_vf *vf,
1890bf93bf79SJacob Keller 			     struct virtchnl_ether_addr *vc_ether_addr)
1891bf93bf79SJacob Keller {
1892bf93bf79SJacob Keller 	if (!ice_is_vc_addr_legacy(vc_ether_addr) ||
1893bf93bf79SJacob Keller 	    ice_is_legacy_umac_expired(&vf->legacy_last_added_umac))
1894bf93bf79SJacob Keller 		return;
1895bf93bf79SJacob Keller 
1896e0645311SJacob Keller 	ether_addr_copy(vf->dev_lan_addr, vf->legacy_last_added_umac.addr);
1897e0645311SJacob Keller 	ether_addr_copy(vf->hw_lan_addr, vf->legacy_last_added_umac.addr);
1898bf93bf79SJacob Keller }
1899bf93bf79SJacob Keller 
1900bf93bf79SJacob Keller /**
1901bf93bf79SJacob Keller  * ice_vfhw_mac_del - update the VF's cached hardware MAC if allowed
1902bf93bf79SJacob Keller  * @vf: VF to update
1903bf93bf79SJacob Keller  * @vc_ether_addr: structure from VIRTCHNL with MAC to delete
1904bf93bf79SJacob Keller  */
1905bf93bf79SJacob Keller static void
1906bf93bf79SJacob Keller ice_vfhw_mac_del(struct ice_vf *vf, struct virtchnl_ether_addr *vc_ether_addr)
1907bf93bf79SJacob Keller {
1908bf93bf79SJacob Keller 	u8 *mac_addr = vc_ether_addr->addr;
1909bf93bf79SJacob Keller 
1910bf93bf79SJacob Keller 	if (!is_valid_ether_addr(mac_addr) ||
1911e0645311SJacob Keller 	    !ether_addr_equal(vf->dev_lan_addr, mac_addr))
1912bf93bf79SJacob Keller 		return;
1913bf93bf79SJacob Keller 
1914bf93bf79SJacob Keller 	/* allow the device MAC to be repopulated in the add flow and don't
1915e0645311SJacob Keller 	 * clear the hardware MAC (i.e. hw_lan_addr) here as that is meant
1916bf93bf79SJacob Keller 	 * to be persistent on VM reboot and across driver unload/load, which
1917bf93bf79SJacob Keller 	 * won't work if we clear the hardware MAC here
1918bf93bf79SJacob Keller 	 */
1919e0645311SJacob Keller 	eth_zero_addr(vf->dev_lan_addr);
1920bf93bf79SJacob Keller 
1921bf93bf79SJacob Keller 	ice_update_legacy_cached_mac(vf, vc_ether_addr);
1922bf93bf79SJacob Keller }
1923bf93bf79SJacob Keller 
1924bf93bf79SJacob Keller /**
1925bf93bf79SJacob Keller  * ice_vc_del_mac_addr - attempt to delete the MAC address passed in
1926bf93bf79SJacob Keller  * @vf: pointer to the VF info
1927bf93bf79SJacob Keller  * @vsi: pointer to the VF's VSI
1928bf93bf79SJacob Keller  * @vc_ether_addr: VIRTCHNL MAC address structure used to delete MAC
1929bf93bf79SJacob Keller  */
1930bf93bf79SJacob Keller static int
1931bf93bf79SJacob Keller ice_vc_del_mac_addr(struct ice_vf *vf, struct ice_vsi *vsi,
1932bf93bf79SJacob Keller 		    struct virtchnl_ether_addr *vc_ether_addr)
1933bf93bf79SJacob Keller {
1934bf93bf79SJacob Keller 	struct device *dev = ice_pf_to_dev(vf->pf);
1935bf93bf79SJacob Keller 	u8 *mac_addr = vc_ether_addr->addr;
1936bf93bf79SJacob Keller 	int status;
1937bf93bf79SJacob Keller 
1938bf93bf79SJacob Keller 	if (!ice_can_vf_change_mac(vf) &&
1939e0645311SJacob Keller 	    ether_addr_equal(vf->dev_lan_addr, mac_addr))
1940bf93bf79SJacob Keller 		return 0;
1941bf93bf79SJacob Keller 
1942bf93bf79SJacob Keller 	status = ice_fltr_remove_mac(vsi, mac_addr, ICE_FWD_TO_VSI);
1943bf93bf79SJacob Keller 	if (status == -ENOENT) {
1944bf93bf79SJacob Keller 		dev_err(dev, "MAC %pM does not exist for VF %d\n", mac_addr,
1945bf93bf79SJacob Keller 			vf->vf_id);
1946bf93bf79SJacob Keller 		return -ENOENT;
1947bf93bf79SJacob Keller 	} else if (status) {
1948bf93bf79SJacob Keller 		dev_err(dev, "Failed to delete MAC %pM for VF %d, error %d\n",
1949bf93bf79SJacob Keller 			mac_addr, vf->vf_id, status);
1950bf93bf79SJacob Keller 		return -EIO;
1951bf93bf79SJacob Keller 	}
1952bf93bf79SJacob Keller 
1953bf93bf79SJacob Keller 	ice_vfhw_mac_del(vf, vc_ether_addr);
1954bf93bf79SJacob Keller 
1955bf93bf79SJacob Keller 	vf->num_mac--;
1956bf93bf79SJacob Keller 
1957bf93bf79SJacob Keller 	return 0;
1958bf93bf79SJacob Keller }
1959bf93bf79SJacob Keller 
1960bf93bf79SJacob Keller /**
1961bf93bf79SJacob Keller  * ice_vc_handle_mac_addr_msg
1962bf93bf79SJacob Keller  * @vf: pointer to the VF info
1963bf93bf79SJacob Keller  * @msg: pointer to the msg buffer
1964bf93bf79SJacob Keller  * @set: true if MAC filters are being set, false otherwise
1965bf93bf79SJacob Keller  *
1966bf93bf79SJacob Keller  * add guest MAC address filter
1967bf93bf79SJacob Keller  */
1968bf93bf79SJacob Keller static int
1969bf93bf79SJacob Keller ice_vc_handle_mac_addr_msg(struct ice_vf *vf, u8 *msg, bool set)
1970bf93bf79SJacob Keller {
1971bf93bf79SJacob Keller 	int (*ice_vc_cfg_mac)
1972bf93bf79SJacob Keller 		(struct ice_vf *vf, struct ice_vsi *vsi,
1973bf93bf79SJacob Keller 		 struct virtchnl_ether_addr *virtchnl_ether_addr);
1974bf93bf79SJacob Keller 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
1975bf93bf79SJacob Keller 	struct virtchnl_ether_addr_list *al =
1976bf93bf79SJacob Keller 	    (struct virtchnl_ether_addr_list *)msg;
1977bf93bf79SJacob Keller 	struct ice_pf *pf = vf->pf;
1978bf93bf79SJacob Keller 	enum virtchnl_ops vc_op;
1979bf93bf79SJacob Keller 	struct ice_vsi *vsi;
1980bf93bf79SJacob Keller 	int i;
1981bf93bf79SJacob Keller 
1982bf93bf79SJacob Keller 	if (set) {
1983bf93bf79SJacob Keller 		vc_op = VIRTCHNL_OP_ADD_ETH_ADDR;
1984bf93bf79SJacob Keller 		ice_vc_cfg_mac = ice_vc_add_mac_addr;
1985bf93bf79SJacob Keller 	} else {
1986bf93bf79SJacob Keller 		vc_op = VIRTCHNL_OP_DEL_ETH_ADDR;
1987bf93bf79SJacob Keller 		ice_vc_cfg_mac = ice_vc_del_mac_addr;
1988bf93bf79SJacob Keller 	}
1989bf93bf79SJacob Keller 
1990bf93bf79SJacob Keller 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states) ||
1991bf93bf79SJacob Keller 	    !ice_vc_isvalid_vsi_id(vf, al->vsi_id)) {
1992bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1993bf93bf79SJacob Keller 		goto handle_mac_exit;
1994bf93bf79SJacob Keller 	}
1995bf93bf79SJacob Keller 
1996bf93bf79SJacob Keller 	/* If this VF is not privileged, then we can't add more than a
1997bf93bf79SJacob Keller 	 * limited number of addresses. Check to make sure that the
1998bf93bf79SJacob Keller 	 * additions do not push us over the limit.
1999bf93bf79SJacob Keller 	 */
2000bf93bf79SJacob Keller 	if (set && !ice_is_vf_trusted(vf) &&
2001bf93bf79SJacob Keller 	    (vf->num_mac + al->num_elements) > ICE_MAX_MACADDR_PER_VF) {
2002bf93bf79SJacob Keller 		dev_err(ice_pf_to_dev(pf), "Can't add more MAC addresses, because VF-%d is not trusted, switch the VF to trusted mode in order to add more functionalities\n",
2003bf93bf79SJacob Keller 			vf->vf_id);
2004bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2005bf93bf79SJacob Keller 		goto handle_mac_exit;
2006bf93bf79SJacob Keller 	}
2007bf93bf79SJacob Keller 
2008bf93bf79SJacob Keller 	vsi = ice_get_vf_vsi(vf);
2009bf93bf79SJacob Keller 	if (!vsi) {
2010bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2011bf93bf79SJacob Keller 		goto handle_mac_exit;
2012bf93bf79SJacob Keller 	}
2013bf93bf79SJacob Keller 
2014bf93bf79SJacob Keller 	for (i = 0; i < al->num_elements; i++) {
2015bf93bf79SJacob Keller 		u8 *mac_addr = al->list[i].addr;
2016bf93bf79SJacob Keller 		int result;
2017bf93bf79SJacob Keller 
2018bf93bf79SJacob Keller 		if (is_broadcast_ether_addr(mac_addr) ||
2019bf93bf79SJacob Keller 		    is_zero_ether_addr(mac_addr))
2020bf93bf79SJacob Keller 			continue;
2021bf93bf79SJacob Keller 
2022bf93bf79SJacob Keller 		result = ice_vc_cfg_mac(vf, vsi, &al->list[i]);
2023bf93bf79SJacob Keller 		if (result == -EEXIST || result == -ENOENT) {
2024bf93bf79SJacob Keller 			continue;
2025bf93bf79SJacob Keller 		} else if (result) {
2026bf93bf79SJacob Keller 			v_ret = VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR;
2027bf93bf79SJacob Keller 			goto handle_mac_exit;
2028bf93bf79SJacob Keller 		}
2029bf93bf79SJacob Keller 	}
2030bf93bf79SJacob Keller 
2031bf93bf79SJacob Keller handle_mac_exit:
2032bf93bf79SJacob Keller 	/* send the response to the VF */
2033bf93bf79SJacob Keller 	return ice_vc_send_msg_to_vf(vf, vc_op, v_ret, NULL, 0);
2034bf93bf79SJacob Keller }
2035bf93bf79SJacob Keller 
2036bf93bf79SJacob Keller /**
2037bf93bf79SJacob Keller  * ice_vc_add_mac_addr_msg
2038bf93bf79SJacob Keller  * @vf: pointer to the VF info
2039bf93bf79SJacob Keller  * @msg: pointer to the msg buffer
2040bf93bf79SJacob Keller  *
2041bf93bf79SJacob Keller  * add guest MAC address filter
2042bf93bf79SJacob Keller  */
2043bf93bf79SJacob Keller static int ice_vc_add_mac_addr_msg(struct ice_vf *vf, u8 *msg)
2044bf93bf79SJacob Keller {
2045bf93bf79SJacob Keller 	return ice_vc_handle_mac_addr_msg(vf, msg, true);
2046bf93bf79SJacob Keller }
2047bf93bf79SJacob Keller 
2048bf93bf79SJacob Keller /**
2049bf93bf79SJacob Keller  * ice_vc_del_mac_addr_msg
2050bf93bf79SJacob Keller  * @vf: pointer to the VF info
2051bf93bf79SJacob Keller  * @msg: pointer to the msg buffer
2052bf93bf79SJacob Keller  *
2053bf93bf79SJacob Keller  * remove guest MAC address filter
2054bf93bf79SJacob Keller  */
2055bf93bf79SJacob Keller static int ice_vc_del_mac_addr_msg(struct ice_vf *vf, u8 *msg)
2056bf93bf79SJacob Keller {
2057bf93bf79SJacob Keller 	return ice_vc_handle_mac_addr_msg(vf, msg, false);
2058bf93bf79SJacob Keller }
2059bf93bf79SJacob Keller 
2060bf93bf79SJacob Keller /**
2061bf93bf79SJacob Keller  * ice_vc_request_qs_msg
2062bf93bf79SJacob Keller  * @vf: pointer to the VF info
2063bf93bf79SJacob Keller  * @msg: pointer to the msg buffer
2064bf93bf79SJacob Keller  *
2065bf93bf79SJacob Keller  * VFs get a default number of queues but can use this message to request a
2066bf93bf79SJacob Keller  * different number. If the request is successful, PF will reset the VF and
2067bf93bf79SJacob Keller  * return 0. If unsuccessful, PF will send message informing VF of number of
2068bf93bf79SJacob Keller  * available queue pairs via virtchnl message response to VF.
2069bf93bf79SJacob Keller  */
2070bf93bf79SJacob Keller static int ice_vc_request_qs_msg(struct ice_vf *vf, u8 *msg)
2071bf93bf79SJacob Keller {
2072bf93bf79SJacob Keller 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
2073bf93bf79SJacob Keller 	struct virtchnl_vf_res_request *vfres =
2074bf93bf79SJacob Keller 		(struct virtchnl_vf_res_request *)msg;
2075bf93bf79SJacob Keller 	u16 req_queues = vfres->num_queue_pairs;
2076bf93bf79SJacob Keller 	struct ice_pf *pf = vf->pf;
2077bf93bf79SJacob Keller 	u16 max_allowed_vf_queues;
2078bf93bf79SJacob Keller 	u16 tx_rx_queue_left;
2079bf93bf79SJacob Keller 	struct device *dev;
2080bf93bf79SJacob Keller 	u16 cur_queues;
2081bf93bf79SJacob Keller 
2082bf93bf79SJacob Keller 	dev = ice_pf_to_dev(pf);
2083bf93bf79SJacob Keller 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
2084bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2085bf93bf79SJacob Keller 		goto error_param;
2086bf93bf79SJacob Keller 	}
2087bf93bf79SJacob Keller 
2088bf93bf79SJacob Keller 	cur_queues = vf->num_vf_qs;
2089bf93bf79SJacob Keller 	tx_rx_queue_left = min_t(u16, ice_get_avail_txq_count(pf),
2090bf93bf79SJacob Keller 				 ice_get_avail_rxq_count(pf));
2091bf93bf79SJacob Keller 	max_allowed_vf_queues = tx_rx_queue_left + cur_queues;
2092bf93bf79SJacob Keller 	if (!req_queues) {
2093bf93bf79SJacob Keller 		dev_err(dev, "VF %d tried to request 0 queues. Ignoring.\n",
2094bf93bf79SJacob Keller 			vf->vf_id);
2095bf93bf79SJacob Keller 	} else if (req_queues > ICE_MAX_RSS_QS_PER_VF) {
2096bf93bf79SJacob Keller 		dev_err(dev, "VF %d tried to request more than %d queues.\n",
2097bf93bf79SJacob Keller 			vf->vf_id, ICE_MAX_RSS_QS_PER_VF);
2098bf93bf79SJacob Keller 		vfres->num_queue_pairs = ICE_MAX_RSS_QS_PER_VF;
2099bf93bf79SJacob Keller 	} else if (req_queues > cur_queues &&
2100bf93bf79SJacob Keller 		   req_queues - cur_queues > tx_rx_queue_left) {
2101bf93bf79SJacob Keller 		dev_warn(dev, "VF %d requested %u more queues, but only %u left.\n",
2102bf93bf79SJacob Keller 			 vf->vf_id, req_queues - cur_queues, tx_rx_queue_left);
2103bf93bf79SJacob Keller 		vfres->num_queue_pairs = min_t(u16, max_allowed_vf_queues,
2104bf93bf79SJacob Keller 					       ICE_MAX_RSS_QS_PER_VF);
2105bf93bf79SJacob Keller 	} else {
2106bf93bf79SJacob Keller 		/* request is successful, then reset VF */
2107bf93bf79SJacob Keller 		vf->num_req_qs = req_queues;
2108bf93bf79SJacob Keller 		ice_reset_vf(vf, ICE_VF_RESET_NOTIFY);
2109bf93bf79SJacob Keller 		dev_info(dev, "VF %d granted request of %u queues.\n",
2110bf93bf79SJacob Keller 			 vf->vf_id, req_queues);
2111bf93bf79SJacob Keller 		return 0;
2112bf93bf79SJacob Keller 	}
2113bf93bf79SJacob Keller 
2114bf93bf79SJacob Keller error_param:
2115bf93bf79SJacob Keller 	/* send the response to the VF */
2116bf93bf79SJacob Keller 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_REQUEST_QUEUES,
2117bf93bf79SJacob Keller 				     v_ret, (u8 *)vfres, sizeof(*vfres));
2118bf93bf79SJacob Keller }
2119bf93bf79SJacob Keller 
2120bf93bf79SJacob Keller /**
2121bf93bf79SJacob Keller  * ice_vf_vlan_offload_ena - determine if capabilities support VLAN offloads
2122bf93bf79SJacob Keller  * @caps: VF driver negotiated capabilities
2123bf93bf79SJacob Keller  *
2124bf93bf79SJacob Keller  * Return true if VIRTCHNL_VF_OFFLOAD_VLAN capability is set, else return false
2125bf93bf79SJacob Keller  */
2126bf93bf79SJacob Keller static bool ice_vf_vlan_offload_ena(u32 caps)
2127bf93bf79SJacob Keller {
2128bf93bf79SJacob Keller 	return !!(caps & VIRTCHNL_VF_OFFLOAD_VLAN);
2129bf93bf79SJacob Keller }
2130bf93bf79SJacob Keller 
2131bf93bf79SJacob Keller /**
2132bf93bf79SJacob Keller  * ice_is_vlan_promisc_allowed - check if VLAN promiscuous config is allowed
2133bf93bf79SJacob Keller  * @vf: VF used to determine if VLAN promiscuous config is allowed
2134bf93bf79SJacob Keller  */
2135bf93bf79SJacob Keller static bool ice_is_vlan_promisc_allowed(struct ice_vf *vf)
2136bf93bf79SJacob Keller {
2137bf93bf79SJacob Keller 	if ((test_bit(ICE_VF_STATE_UC_PROMISC, vf->vf_states) ||
2138bf93bf79SJacob Keller 	     test_bit(ICE_VF_STATE_MC_PROMISC, vf->vf_states)) &&
2139bf93bf79SJacob Keller 	    test_bit(ICE_FLAG_VF_TRUE_PROMISC_ENA, vf->pf->flags))
2140bf93bf79SJacob Keller 		return true;
2141bf93bf79SJacob Keller 
2142bf93bf79SJacob Keller 	return false;
2143bf93bf79SJacob Keller }
2144bf93bf79SJacob Keller 
2145bf93bf79SJacob Keller /**
2146bf93bf79SJacob Keller  * ice_vf_ena_vlan_promisc - Enable Tx/Rx VLAN promiscuous for the VLAN
2147bf93bf79SJacob Keller  * @vsi: VF's VSI used to enable VLAN promiscuous mode
2148bf93bf79SJacob Keller  * @vlan: VLAN used to enable VLAN promiscuous
2149bf93bf79SJacob Keller  *
2150bf93bf79SJacob Keller  * This function should only be called if VLAN promiscuous mode is allowed,
2151bf93bf79SJacob Keller  * which can be determined via ice_is_vlan_promisc_allowed().
2152bf93bf79SJacob Keller  */
2153bf93bf79SJacob Keller static int ice_vf_ena_vlan_promisc(struct ice_vsi *vsi, struct ice_vlan *vlan)
2154bf93bf79SJacob Keller {
2155bf93bf79SJacob Keller 	u8 promisc_m = ICE_PROMISC_VLAN_TX | ICE_PROMISC_VLAN_RX;
2156bf93bf79SJacob Keller 	int status;
2157bf93bf79SJacob Keller 
2158bf93bf79SJacob Keller 	status = ice_fltr_set_vsi_promisc(&vsi->back->hw, vsi->idx, promisc_m,
2159bf93bf79SJacob Keller 					  vlan->vid);
2160bf93bf79SJacob Keller 	if (status && status != -EEXIST)
2161bf93bf79SJacob Keller 		return status;
2162bf93bf79SJacob Keller 
2163bf93bf79SJacob Keller 	return 0;
2164bf93bf79SJacob Keller }
2165bf93bf79SJacob Keller 
2166bf93bf79SJacob Keller /**
2167bf93bf79SJacob Keller  * ice_vf_dis_vlan_promisc - Disable Tx/Rx VLAN promiscuous for the VLAN
2168bf93bf79SJacob Keller  * @vsi: VF's VSI used to disable VLAN promiscuous mode for
2169bf93bf79SJacob Keller  * @vlan: VLAN used to disable VLAN promiscuous
2170bf93bf79SJacob Keller  *
2171bf93bf79SJacob Keller  * This function should only be called if VLAN promiscuous mode is allowed,
2172bf93bf79SJacob Keller  * which can be determined via ice_is_vlan_promisc_allowed().
2173bf93bf79SJacob Keller  */
2174bf93bf79SJacob Keller static int ice_vf_dis_vlan_promisc(struct ice_vsi *vsi, struct ice_vlan *vlan)
2175bf93bf79SJacob Keller {
2176bf93bf79SJacob Keller 	u8 promisc_m = ICE_PROMISC_VLAN_TX | ICE_PROMISC_VLAN_RX;
2177bf93bf79SJacob Keller 	int status;
2178bf93bf79SJacob Keller 
2179bf93bf79SJacob Keller 	status = ice_fltr_clear_vsi_promisc(&vsi->back->hw, vsi->idx, promisc_m,
2180bf93bf79SJacob Keller 					    vlan->vid);
2181bf93bf79SJacob Keller 	if (status && status != -ENOENT)
2182bf93bf79SJacob Keller 		return status;
2183bf93bf79SJacob Keller 
2184bf93bf79SJacob Keller 	return 0;
2185bf93bf79SJacob Keller }
2186bf93bf79SJacob Keller 
2187bf93bf79SJacob Keller /**
2188bf93bf79SJacob Keller  * ice_vf_has_max_vlans - check if VF already has the max allowed VLAN filters
2189bf93bf79SJacob Keller  * @vf: VF to check against
2190bf93bf79SJacob Keller  * @vsi: VF's VSI
2191bf93bf79SJacob Keller  *
2192bf93bf79SJacob Keller  * If the VF is trusted then the VF is allowed to add as many VLANs as it
2193bf93bf79SJacob Keller  * wants to, so return false.
2194bf93bf79SJacob Keller  *
2195bf93bf79SJacob Keller  * When the VF is untrusted compare the number of non-zero VLANs + 1 to the max
2196bf93bf79SJacob Keller  * allowed VLANs for an untrusted VF. Return the result of this comparison.
2197bf93bf79SJacob Keller  */
2198bf93bf79SJacob Keller static bool ice_vf_has_max_vlans(struct ice_vf *vf, struct ice_vsi *vsi)
2199bf93bf79SJacob Keller {
2200bf93bf79SJacob Keller 	if (ice_is_vf_trusted(vf))
2201bf93bf79SJacob Keller 		return false;
2202bf93bf79SJacob Keller 
2203bf93bf79SJacob Keller #define ICE_VF_ADDED_VLAN_ZERO_FLTRS	1
2204bf93bf79SJacob Keller 	return ((ice_vsi_num_non_zero_vlans(vsi) +
2205bf93bf79SJacob Keller 		ICE_VF_ADDED_VLAN_ZERO_FLTRS) >= ICE_MAX_VLAN_PER_VF);
2206bf93bf79SJacob Keller }
2207bf93bf79SJacob Keller 
2208bf93bf79SJacob Keller /**
2209bf93bf79SJacob Keller  * ice_vc_process_vlan_msg
2210bf93bf79SJacob Keller  * @vf: pointer to the VF info
2211bf93bf79SJacob Keller  * @msg: pointer to the msg buffer
2212bf93bf79SJacob Keller  * @add_v: Add VLAN if true, otherwise delete VLAN
2213bf93bf79SJacob Keller  *
2214bf93bf79SJacob Keller  * Process virtchnl op to add or remove programmed guest VLAN ID
2215bf93bf79SJacob Keller  */
2216bf93bf79SJacob Keller static int ice_vc_process_vlan_msg(struct ice_vf *vf, u8 *msg, bool add_v)
2217bf93bf79SJacob Keller {
2218bf93bf79SJacob Keller 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
2219bf93bf79SJacob Keller 	struct virtchnl_vlan_filter_list *vfl =
2220bf93bf79SJacob Keller 	    (struct virtchnl_vlan_filter_list *)msg;
2221bf93bf79SJacob Keller 	struct ice_pf *pf = vf->pf;
2222bf93bf79SJacob Keller 	bool vlan_promisc = false;
2223bf93bf79SJacob Keller 	struct ice_vsi *vsi;
2224bf93bf79SJacob Keller 	struct device *dev;
2225bf93bf79SJacob Keller 	int status = 0;
2226bf93bf79SJacob Keller 	int i;
2227bf93bf79SJacob Keller 
2228bf93bf79SJacob Keller 	dev = ice_pf_to_dev(pf);
2229bf93bf79SJacob Keller 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
2230bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2231bf93bf79SJacob Keller 		goto error_param;
2232bf93bf79SJacob Keller 	}
2233bf93bf79SJacob Keller 
2234bf93bf79SJacob Keller 	if (!ice_vf_vlan_offload_ena(vf->driver_caps)) {
2235bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2236bf93bf79SJacob Keller 		goto error_param;
2237bf93bf79SJacob Keller 	}
2238bf93bf79SJacob Keller 
2239bf93bf79SJacob Keller 	if (!ice_vc_isvalid_vsi_id(vf, vfl->vsi_id)) {
2240bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2241bf93bf79SJacob Keller 		goto error_param;
2242bf93bf79SJacob Keller 	}
2243bf93bf79SJacob Keller 
2244bf93bf79SJacob Keller 	for (i = 0; i < vfl->num_elements; i++) {
2245bf93bf79SJacob Keller 		if (vfl->vlan_id[i] >= VLAN_N_VID) {
2246bf93bf79SJacob Keller 			v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2247bf93bf79SJacob Keller 			dev_err(dev, "invalid VF VLAN id %d\n",
2248bf93bf79SJacob Keller 				vfl->vlan_id[i]);
2249bf93bf79SJacob Keller 			goto error_param;
2250bf93bf79SJacob Keller 		}
2251bf93bf79SJacob Keller 	}
2252bf93bf79SJacob Keller 
2253bf93bf79SJacob Keller 	vsi = ice_get_vf_vsi(vf);
2254bf93bf79SJacob Keller 	if (!vsi) {
2255bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2256bf93bf79SJacob Keller 		goto error_param;
2257bf93bf79SJacob Keller 	}
2258bf93bf79SJacob Keller 
2259bf93bf79SJacob Keller 	if (add_v && ice_vf_has_max_vlans(vf, vsi)) {
2260bf93bf79SJacob Keller 		dev_info(dev, "VF-%d is not trusted, switch the VF to trusted mode, in order to add more VLAN addresses\n",
2261bf93bf79SJacob Keller 			 vf->vf_id);
2262bf93bf79SJacob Keller 		/* There is no need to let VF know about being not trusted,
2263bf93bf79SJacob Keller 		 * so we can just return success message here
2264bf93bf79SJacob Keller 		 */
2265bf93bf79SJacob Keller 		goto error_param;
2266bf93bf79SJacob Keller 	}
2267bf93bf79SJacob Keller 
2268bf93bf79SJacob Keller 	/* in DVM a VF can add/delete inner VLAN filters when
2269bf93bf79SJacob Keller 	 * VIRTCHNL_VF_OFFLOAD_VLAN is negotiated, so only reject in SVM
2270bf93bf79SJacob Keller 	 */
2271bf93bf79SJacob Keller 	if (ice_vf_is_port_vlan_ena(vf) && !ice_is_dvm_ena(&pf->hw)) {
2272bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2273bf93bf79SJacob Keller 		goto error_param;
2274bf93bf79SJacob Keller 	}
2275bf93bf79SJacob Keller 
2276bf93bf79SJacob Keller 	/* in DVM VLAN promiscuous is based on the outer VLAN, which would be
2277bf93bf79SJacob Keller 	 * the port VLAN if VIRTCHNL_VF_OFFLOAD_VLAN was negotiated, so only
2278bf93bf79SJacob Keller 	 * allow vlan_promisc = true in SVM and if no port VLAN is configured
2279bf93bf79SJacob Keller 	 */
2280bf93bf79SJacob Keller 	vlan_promisc = ice_is_vlan_promisc_allowed(vf) &&
2281bf93bf79SJacob Keller 		!ice_is_dvm_ena(&pf->hw) &&
2282bf93bf79SJacob Keller 		!ice_vf_is_port_vlan_ena(vf);
2283bf93bf79SJacob Keller 
2284bf93bf79SJacob Keller 	if (add_v) {
2285bf93bf79SJacob Keller 		for (i = 0; i < vfl->num_elements; i++) {
2286bf93bf79SJacob Keller 			u16 vid = vfl->vlan_id[i];
2287bf93bf79SJacob Keller 			struct ice_vlan vlan;
2288bf93bf79SJacob Keller 
2289bf93bf79SJacob Keller 			if (ice_vf_has_max_vlans(vf, vsi)) {
2290bf93bf79SJacob Keller 				dev_info(dev, "VF-%d is not trusted, switch the VF to trusted mode, in order to add more VLAN addresses\n",
2291bf93bf79SJacob Keller 					 vf->vf_id);
2292bf93bf79SJacob Keller 				/* There is no need to let VF know about being
2293bf93bf79SJacob Keller 				 * not trusted, so we can just return success
2294bf93bf79SJacob Keller 				 * message here as well.
2295bf93bf79SJacob Keller 				 */
2296bf93bf79SJacob Keller 				goto error_param;
2297bf93bf79SJacob Keller 			}
2298bf93bf79SJacob Keller 
2299bf93bf79SJacob Keller 			/* we add VLAN 0 by default for each VF so we can enable
2300bf93bf79SJacob Keller 			 * Tx VLAN anti-spoof without triggering MDD events so
2301bf93bf79SJacob Keller 			 * we don't need to add it again here
2302bf93bf79SJacob Keller 			 */
2303bf93bf79SJacob Keller 			if (!vid)
2304bf93bf79SJacob Keller 				continue;
2305bf93bf79SJacob Keller 
2306bf93bf79SJacob Keller 			vlan = ICE_VLAN(ETH_P_8021Q, vid, 0);
2307bf93bf79SJacob Keller 			status = vsi->inner_vlan_ops.add_vlan(vsi, &vlan);
2308bf93bf79SJacob Keller 			if (status) {
2309bf93bf79SJacob Keller 				v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2310bf93bf79SJacob Keller 				goto error_param;
2311bf93bf79SJacob Keller 			}
2312bf93bf79SJacob Keller 
2313bf93bf79SJacob Keller 			/* Enable VLAN filtering on first non-zero VLAN */
2314bf93bf79SJacob Keller 			if (!vlan_promisc && vid && !ice_is_dvm_ena(&pf->hw)) {
2315664d4646SSylwester Dziedziuch 				if (vf->spoofchk) {
2316664d4646SSylwester Dziedziuch 					status = vsi->inner_vlan_ops.ena_tx_filtering(vsi);
2317664d4646SSylwester Dziedziuch 					if (status) {
2318664d4646SSylwester Dziedziuch 						v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2319664d4646SSylwester Dziedziuch 						dev_err(dev, "Enable VLAN anti-spoofing on VLAN ID: %d failed error-%d\n",
2320664d4646SSylwester Dziedziuch 							vid, status);
2321664d4646SSylwester Dziedziuch 						goto error_param;
2322664d4646SSylwester Dziedziuch 					}
2323664d4646SSylwester Dziedziuch 				}
2324bf93bf79SJacob Keller 				if (vsi->inner_vlan_ops.ena_rx_filtering(vsi)) {
2325bf93bf79SJacob Keller 					v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2326bf93bf79SJacob Keller 					dev_err(dev, "Enable VLAN pruning on VLAN ID: %d failed error-%d\n",
2327bf93bf79SJacob Keller 						vid, status);
2328bf93bf79SJacob Keller 					goto error_param;
2329bf93bf79SJacob Keller 				}
2330bf93bf79SJacob Keller 			} else if (vlan_promisc) {
2331bf93bf79SJacob Keller 				status = ice_vf_ena_vlan_promisc(vsi, &vlan);
2332bf93bf79SJacob Keller 				if (status) {
2333bf93bf79SJacob Keller 					v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2334bf93bf79SJacob Keller 					dev_err(dev, "Enable Unicast/multicast promiscuous mode on VLAN ID:%d failed error-%d\n",
2335bf93bf79SJacob Keller 						vid, status);
2336bf93bf79SJacob Keller 				}
2337bf93bf79SJacob Keller 			}
2338bf93bf79SJacob Keller 		}
2339bf93bf79SJacob Keller 	} else {
2340bf93bf79SJacob Keller 		/* In case of non_trusted VF, number of VLAN elements passed
2341bf93bf79SJacob Keller 		 * to PF for removal might be greater than number of VLANs
2342bf93bf79SJacob Keller 		 * filter programmed for that VF - So, use actual number of
2343bf93bf79SJacob Keller 		 * VLANS added earlier with add VLAN opcode. In order to avoid
2344bf93bf79SJacob Keller 		 * removing VLAN that doesn't exist, which result to sending
2345bf93bf79SJacob Keller 		 * erroneous failed message back to the VF
2346bf93bf79SJacob Keller 		 */
2347bf93bf79SJacob Keller 		int num_vf_vlan;
2348bf93bf79SJacob Keller 
2349bf93bf79SJacob Keller 		num_vf_vlan = vsi->num_vlan;
2350bf93bf79SJacob Keller 		for (i = 0; i < vfl->num_elements && i < num_vf_vlan; i++) {
2351bf93bf79SJacob Keller 			u16 vid = vfl->vlan_id[i];
2352bf93bf79SJacob Keller 			struct ice_vlan vlan;
2353bf93bf79SJacob Keller 
2354bf93bf79SJacob Keller 			/* we add VLAN 0 by default for each VF so we can enable
2355bf93bf79SJacob Keller 			 * Tx VLAN anti-spoof without triggering MDD events so
2356bf93bf79SJacob Keller 			 * we don't want a VIRTCHNL request to remove it
2357bf93bf79SJacob Keller 			 */
2358bf93bf79SJacob Keller 			if (!vid)
2359bf93bf79SJacob Keller 				continue;
2360bf93bf79SJacob Keller 
2361bf93bf79SJacob Keller 			vlan = ICE_VLAN(ETH_P_8021Q, vid, 0);
2362bf93bf79SJacob Keller 			status = vsi->inner_vlan_ops.del_vlan(vsi, &vlan);
2363bf93bf79SJacob Keller 			if (status) {
2364bf93bf79SJacob Keller 				v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2365bf93bf79SJacob Keller 				goto error_param;
2366bf93bf79SJacob Keller 			}
2367bf93bf79SJacob Keller 
2368bf93bf79SJacob Keller 			/* Disable VLAN filtering when only VLAN 0 is left */
2369664d4646SSylwester Dziedziuch 			if (!ice_vsi_has_non_zero_vlans(vsi)) {
2370664d4646SSylwester Dziedziuch 				vsi->inner_vlan_ops.dis_tx_filtering(vsi);
2371bf93bf79SJacob Keller 				vsi->inner_vlan_ops.dis_rx_filtering(vsi);
2372664d4646SSylwester Dziedziuch 			}
2373bf93bf79SJacob Keller 
2374bf93bf79SJacob Keller 			if (vlan_promisc)
2375bf93bf79SJacob Keller 				ice_vf_dis_vlan_promisc(vsi, &vlan);
2376bf93bf79SJacob Keller 		}
2377bf93bf79SJacob Keller 	}
2378bf93bf79SJacob Keller 
2379bf93bf79SJacob Keller error_param:
2380bf93bf79SJacob Keller 	/* send the response to the VF */
2381bf93bf79SJacob Keller 	if (add_v)
2382bf93bf79SJacob Keller 		return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_ADD_VLAN, v_ret,
2383bf93bf79SJacob Keller 					     NULL, 0);
2384bf93bf79SJacob Keller 	else
2385bf93bf79SJacob Keller 		return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_DEL_VLAN, v_ret,
2386bf93bf79SJacob Keller 					     NULL, 0);
2387bf93bf79SJacob Keller }
2388bf93bf79SJacob Keller 
2389bf93bf79SJacob Keller /**
2390bf93bf79SJacob Keller  * ice_vc_add_vlan_msg
2391bf93bf79SJacob Keller  * @vf: pointer to the VF info
2392bf93bf79SJacob Keller  * @msg: pointer to the msg buffer
2393bf93bf79SJacob Keller  *
2394bf93bf79SJacob Keller  * Add and program guest VLAN ID
2395bf93bf79SJacob Keller  */
2396bf93bf79SJacob Keller static int ice_vc_add_vlan_msg(struct ice_vf *vf, u8 *msg)
2397bf93bf79SJacob Keller {
2398bf93bf79SJacob Keller 	return ice_vc_process_vlan_msg(vf, msg, true);
2399bf93bf79SJacob Keller }
2400bf93bf79SJacob Keller 
2401bf93bf79SJacob Keller /**
2402bf93bf79SJacob Keller  * ice_vc_remove_vlan_msg
2403bf93bf79SJacob Keller  * @vf: pointer to the VF info
2404bf93bf79SJacob Keller  * @msg: pointer to the msg buffer
2405bf93bf79SJacob Keller  *
2406bf93bf79SJacob Keller  * remove programmed guest VLAN ID
2407bf93bf79SJacob Keller  */
2408bf93bf79SJacob Keller static int ice_vc_remove_vlan_msg(struct ice_vf *vf, u8 *msg)
2409bf93bf79SJacob Keller {
2410bf93bf79SJacob Keller 	return ice_vc_process_vlan_msg(vf, msg, false);
2411bf93bf79SJacob Keller }
2412bf93bf79SJacob Keller 
2413bf93bf79SJacob Keller /**
2414bf93bf79SJacob Keller  * ice_vc_ena_vlan_stripping
2415bf93bf79SJacob Keller  * @vf: pointer to the VF info
2416bf93bf79SJacob Keller  *
2417bf93bf79SJacob Keller  * Enable VLAN header stripping for a given VF
2418bf93bf79SJacob Keller  */
2419bf93bf79SJacob Keller static int ice_vc_ena_vlan_stripping(struct ice_vf *vf)
2420bf93bf79SJacob Keller {
2421bf93bf79SJacob Keller 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
2422bf93bf79SJacob Keller 	struct ice_vsi *vsi;
2423bf93bf79SJacob Keller 
2424bf93bf79SJacob Keller 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
2425bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2426bf93bf79SJacob Keller 		goto error_param;
2427bf93bf79SJacob Keller 	}
2428bf93bf79SJacob Keller 
2429bf93bf79SJacob Keller 	if (!ice_vf_vlan_offload_ena(vf->driver_caps)) {
2430bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2431bf93bf79SJacob Keller 		goto error_param;
2432bf93bf79SJacob Keller 	}
2433bf93bf79SJacob Keller 
2434bf93bf79SJacob Keller 	vsi = ice_get_vf_vsi(vf);
2435baeb705fSJacob Keller 	if (!vsi) {
2436baeb705fSJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2437baeb705fSJacob Keller 		goto error_param;
2438baeb705fSJacob Keller 	}
2439baeb705fSJacob Keller 
2440bf93bf79SJacob Keller 	if (vsi->inner_vlan_ops.ena_stripping(vsi, ETH_P_8021Q))
2441bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2442bf93bf79SJacob Keller 
2443bf93bf79SJacob Keller error_param:
2444bf93bf79SJacob Keller 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_ENABLE_VLAN_STRIPPING,
2445bf93bf79SJacob Keller 				     v_ret, NULL, 0);
2446bf93bf79SJacob Keller }
2447bf93bf79SJacob Keller 
2448bf93bf79SJacob Keller /**
2449bf93bf79SJacob Keller  * ice_vc_dis_vlan_stripping
2450bf93bf79SJacob Keller  * @vf: pointer to the VF info
2451bf93bf79SJacob Keller  *
2452bf93bf79SJacob Keller  * Disable VLAN header stripping for a given VF
2453bf93bf79SJacob Keller  */
2454bf93bf79SJacob Keller static int ice_vc_dis_vlan_stripping(struct ice_vf *vf)
2455bf93bf79SJacob Keller {
2456bf93bf79SJacob Keller 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
2457bf93bf79SJacob Keller 	struct ice_vsi *vsi;
2458bf93bf79SJacob Keller 
2459bf93bf79SJacob Keller 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
2460bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2461bf93bf79SJacob Keller 		goto error_param;
2462bf93bf79SJacob Keller 	}
2463bf93bf79SJacob Keller 
2464bf93bf79SJacob Keller 	if (!ice_vf_vlan_offload_ena(vf->driver_caps)) {
2465bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2466bf93bf79SJacob Keller 		goto error_param;
2467bf93bf79SJacob Keller 	}
2468bf93bf79SJacob Keller 
2469bf93bf79SJacob Keller 	vsi = ice_get_vf_vsi(vf);
2470bf93bf79SJacob Keller 	if (!vsi) {
2471bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2472bf93bf79SJacob Keller 		goto error_param;
2473bf93bf79SJacob Keller 	}
2474bf93bf79SJacob Keller 
2475bf93bf79SJacob Keller 	if (vsi->inner_vlan_ops.dis_stripping(vsi))
2476bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2477bf93bf79SJacob Keller 
2478bf93bf79SJacob Keller error_param:
2479bf93bf79SJacob Keller 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_DISABLE_VLAN_STRIPPING,
2480bf93bf79SJacob Keller 				     v_ret, NULL, 0);
2481bf93bf79SJacob Keller }
2482bf93bf79SJacob Keller 
2483bf93bf79SJacob Keller /**
2484e384cf35SMd Fahad Iqbal Polash  * ice_vc_get_rss_hena - return the RSS HENA bits allowed by the hardware
2485e384cf35SMd Fahad Iqbal Polash  * @vf: pointer to the VF info
2486e384cf35SMd Fahad Iqbal Polash  */
2487e384cf35SMd Fahad Iqbal Polash static int ice_vc_get_rss_hena(struct ice_vf *vf)
2488e384cf35SMd Fahad Iqbal Polash {
2489e384cf35SMd Fahad Iqbal Polash 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
2490e384cf35SMd Fahad Iqbal Polash 	struct virtchnl_rss_hena *vrh = NULL;
2491e384cf35SMd Fahad Iqbal Polash 	int len = 0, ret;
2492e384cf35SMd Fahad Iqbal Polash 
2493e384cf35SMd Fahad Iqbal Polash 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
2494e384cf35SMd Fahad Iqbal Polash 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2495e384cf35SMd Fahad Iqbal Polash 		goto err;
2496e384cf35SMd Fahad Iqbal Polash 	}
2497e384cf35SMd Fahad Iqbal Polash 
2498e384cf35SMd Fahad Iqbal Polash 	if (!test_bit(ICE_FLAG_RSS_ENA, vf->pf->flags)) {
2499e384cf35SMd Fahad Iqbal Polash 		dev_err(ice_pf_to_dev(vf->pf), "RSS not supported by PF\n");
2500e384cf35SMd Fahad Iqbal Polash 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2501e384cf35SMd Fahad Iqbal Polash 		goto err;
2502e384cf35SMd Fahad Iqbal Polash 	}
2503e384cf35SMd Fahad Iqbal Polash 
2504e384cf35SMd Fahad Iqbal Polash 	len = sizeof(struct virtchnl_rss_hena);
2505e384cf35SMd Fahad Iqbal Polash 	vrh = kzalloc(len, GFP_KERNEL);
2506e384cf35SMd Fahad Iqbal Polash 	if (!vrh) {
2507e384cf35SMd Fahad Iqbal Polash 		v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY;
2508e384cf35SMd Fahad Iqbal Polash 		len = 0;
2509e384cf35SMd Fahad Iqbal Polash 		goto err;
2510e384cf35SMd Fahad Iqbal Polash 	}
2511e384cf35SMd Fahad Iqbal Polash 
2512e384cf35SMd Fahad Iqbal Polash 	vrh->hena = ICE_DEFAULT_RSS_HENA;
2513e384cf35SMd Fahad Iqbal Polash err:
2514e384cf35SMd Fahad Iqbal Polash 	/* send the response back to the VF */
2515e384cf35SMd Fahad Iqbal Polash 	ret = ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_GET_RSS_HENA_CAPS, v_ret,
2516e384cf35SMd Fahad Iqbal Polash 				    (u8 *)vrh, len);
2517e384cf35SMd Fahad Iqbal Polash 	kfree(vrh);
2518e384cf35SMd Fahad Iqbal Polash 	return ret;
2519e384cf35SMd Fahad Iqbal Polash }
2520e384cf35SMd Fahad Iqbal Polash 
2521e384cf35SMd Fahad Iqbal Polash /**
2522e384cf35SMd Fahad Iqbal Polash  * ice_vc_set_rss_hena - set RSS HENA bits for the VF
2523e384cf35SMd Fahad Iqbal Polash  * @vf: pointer to the VF info
2524e384cf35SMd Fahad Iqbal Polash  * @msg: pointer to the msg buffer
2525e384cf35SMd Fahad Iqbal Polash  */
2526e384cf35SMd Fahad Iqbal Polash static int ice_vc_set_rss_hena(struct ice_vf *vf, u8 *msg)
2527e384cf35SMd Fahad Iqbal Polash {
2528e384cf35SMd Fahad Iqbal Polash 	struct virtchnl_rss_hena *vrh = (struct virtchnl_rss_hena *)msg;
2529e384cf35SMd Fahad Iqbal Polash 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
2530e384cf35SMd Fahad Iqbal Polash 	struct ice_pf *pf = vf->pf;
2531e384cf35SMd Fahad Iqbal Polash 	struct ice_vsi *vsi;
2532e384cf35SMd Fahad Iqbal Polash 	struct device *dev;
2533e384cf35SMd Fahad Iqbal Polash 	int status;
2534e384cf35SMd Fahad Iqbal Polash 
2535e384cf35SMd Fahad Iqbal Polash 	dev = ice_pf_to_dev(pf);
2536e384cf35SMd Fahad Iqbal Polash 
2537e384cf35SMd Fahad Iqbal Polash 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
2538e384cf35SMd Fahad Iqbal Polash 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2539e384cf35SMd Fahad Iqbal Polash 		goto err;
2540e384cf35SMd Fahad Iqbal Polash 	}
2541e384cf35SMd Fahad Iqbal Polash 
2542e384cf35SMd Fahad Iqbal Polash 	if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) {
2543e384cf35SMd Fahad Iqbal Polash 		dev_err(dev, "RSS not supported by PF\n");
2544e384cf35SMd Fahad Iqbal Polash 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2545e384cf35SMd Fahad Iqbal Polash 		goto err;
2546e384cf35SMd Fahad Iqbal Polash 	}
2547e384cf35SMd Fahad Iqbal Polash 
2548e384cf35SMd Fahad Iqbal Polash 	vsi = ice_get_vf_vsi(vf);
2549e384cf35SMd Fahad Iqbal Polash 	if (!vsi) {
2550e384cf35SMd Fahad Iqbal Polash 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2551e384cf35SMd Fahad Iqbal Polash 		goto err;
2552e384cf35SMd Fahad Iqbal Polash 	}
2553e384cf35SMd Fahad Iqbal Polash 
2554e384cf35SMd Fahad Iqbal Polash 	/* clear all previously programmed RSS configuration to allow VF drivers
2555e384cf35SMd Fahad Iqbal Polash 	 * the ability to customize the RSS configuration and/or completely
2556e384cf35SMd Fahad Iqbal Polash 	 * disable RSS
2557e384cf35SMd Fahad Iqbal Polash 	 */
2558e384cf35SMd Fahad Iqbal Polash 	status = ice_rem_vsi_rss_cfg(&pf->hw, vsi->idx);
2559e384cf35SMd Fahad Iqbal Polash 	if (status && !vrh->hena) {
2560e384cf35SMd Fahad Iqbal Polash 		/* only report failure to clear the current RSS configuration if
2561e384cf35SMd Fahad Iqbal Polash 		 * that was clearly the VF's intention (i.e. vrh->hena = 0)
2562e384cf35SMd Fahad Iqbal Polash 		 */
2563e384cf35SMd Fahad Iqbal Polash 		v_ret = ice_err_to_virt_err(status);
2564e384cf35SMd Fahad Iqbal Polash 		goto err;
2565e384cf35SMd Fahad Iqbal Polash 	} else if (status) {
2566e384cf35SMd Fahad Iqbal Polash 		/* allow the VF to update the RSS configuration even on failure
2567e384cf35SMd Fahad Iqbal Polash 		 * to clear the current RSS confguration in an attempt to keep
2568e384cf35SMd Fahad Iqbal Polash 		 * RSS in a working state
2569e384cf35SMd Fahad Iqbal Polash 		 */
2570e384cf35SMd Fahad Iqbal Polash 		dev_warn(dev, "Failed to clear the RSS configuration for VF %u\n",
2571e384cf35SMd Fahad Iqbal Polash 			 vf->vf_id);
2572e384cf35SMd Fahad Iqbal Polash 	}
2573e384cf35SMd Fahad Iqbal Polash 
2574e384cf35SMd Fahad Iqbal Polash 	if (vrh->hena) {
2575e384cf35SMd Fahad Iqbal Polash 		status = ice_add_avf_rss_cfg(&pf->hw, vsi->idx, vrh->hena);
2576e384cf35SMd Fahad Iqbal Polash 		v_ret = ice_err_to_virt_err(status);
2577e384cf35SMd Fahad Iqbal Polash 	}
2578e384cf35SMd Fahad Iqbal Polash 
2579e384cf35SMd Fahad Iqbal Polash 	/* send the response to the VF */
2580e384cf35SMd Fahad Iqbal Polash err:
2581e384cf35SMd Fahad Iqbal Polash 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_SET_RSS_HENA, v_ret,
2582e384cf35SMd Fahad Iqbal Polash 				     NULL, 0);
2583e384cf35SMd Fahad Iqbal Polash }
2584e384cf35SMd Fahad Iqbal Polash 
2585e384cf35SMd Fahad Iqbal Polash /**
2586e753df8fSMichal Jaron  * ice_vc_query_rxdid - query RXDID supported by DDP package
2587e753df8fSMichal Jaron  * @vf: pointer to VF info
2588e753df8fSMichal Jaron  *
2589e753df8fSMichal Jaron  * Called from VF to query a bitmap of supported flexible
2590e753df8fSMichal Jaron  * descriptor RXDIDs of a DDP package.
2591e753df8fSMichal Jaron  */
2592e753df8fSMichal Jaron static int ice_vc_query_rxdid(struct ice_vf *vf)
2593e753df8fSMichal Jaron {
2594e753df8fSMichal Jaron 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
2595e753df8fSMichal Jaron 	struct virtchnl_supported_rxdids *rxdid = NULL;
2596e753df8fSMichal Jaron 	struct ice_hw *hw = &vf->pf->hw;
2597e753df8fSMichal Jaron 	struct ice_pf *pf = vf->pf;
2598e753df8fSMichal Jaron 	int len = 0;
2599e753df8fSMichal Jaron 	int ret, i;
2600e753df8fSMichal Jaron 	u32 regval;
2601e753df8fSMichal Jaron 
2602e753df8fSMichal Jaron 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
2603e753df8fSMichal Jaron 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2604e753df8fSMichal Jaron 		goto err;
2605e753df8fSMichal Jaron 	}
2606e753df8fSMichal Jaron 
2607e753df8fSMichal Jaron 	if (!(vf->driver_caps & VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC)) {
2608e753df8fSMichal Jaron 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2609e753df8fSMichal Jaron 		goto err;
2610e753df8fSMichal Jaron 	}
2611e753df8fSMichal Jaron 
2612e753df8fSMichal Jaron 	len = sizeof(struct virtchnl_supported_rxdids);
2613e753df8fSMichal Jaron 	rxdid = kzalloc(len, GFP_KERNEL);
2614e753df8fSMichal Jaron 	if (!rxdid) {
2615e753df8fSMichal Jaron 		v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY;
2616e753df8fSMichal Jaron 		len = 0;
2617e753df8fSMichal Jaron 		goto err;
2618e753df8fSMichal Jaron 	}
2619e753df8fSMichal Jaron 
2620e753df8fSMichal Jaron 	/* Read flexiflag registers to determine whether the
2621e753df8fSMichal Jaron 	 * corresponding RXDID is configured and supported or not.
2622e753df8fSMichal Jaron 	 * Since Legacy 16byte descriptor format is not supported,
2623e753df8fSMichal Jaron 	 * start from Legacy 32byte descriptor.
2624e753df8fSMichal Jaron 	 */
2625e753df8fSMichal Jaron 	for (i = ICE_RXDID_LEGACY_1; i < ICE_FLEX_DESC_RXDID_MAX_NUM; i++) {
2626e753df8fSMichal Jaron 		regval = rd32(hw, GLFLXP_RXDID_FLAGS(i, 0));
2627e753df8fSMichal Jaron 		if ((regval >> GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_S)
2628e753df8fSMichal Jaron 			& GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_M)
2629e753df8fSMichal Jaron 			rxdid->supported_rxdids |= BIT(i);
2630e753df8fSMichal Jaron 	}
2631e753df8fSMichal Jaron 
2632e753df8fSMichal Jaron 	pf->supported_rxdids = rxdid->supported_rxdids;
2633e753df8fSMichal Jaron 
2634e753df8fSMichal Jaron err:
2635e753df8fSMichal Jaron 	ret = ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_GET_SUPPORTED_RXDIDS,
2636e753df8fSMichal Jaron 				    v_ret, (u8 *)rxdid, len);
2637e753df8fSMichal Jaron 	kfree(rxdid);
2638e753df8fSMichal Jaron 	return ret;
2639e753df8fSMichal Jaron }
2640e753df8fSMichal Jaron 
2641e753df8fSMichal Jaron /**
2642bf93bf79SJacob Keller  * ice_vf_init_vlan_stripping - enable/disable VLAN stripping on initialization
2643bf93bf79SJacob Keller  * @vf: VF to enable/disable VLAN stripping for on initialization
2644bf93bf79SJacob Keller  *
2645bf93bf79SJacob Keller  * Set the default for VLAN stripping based on whether a port VLAN is configured
2646bf93bf79SJacob Keller  * and the current VLAN mode of the device.
2647bf93bf79SJacob Keller  */
2648bf93bf79SJacob Keller static int ice_vf_init_vlan_stripping(struct ice_vf *vf)
2649bf93bf79SJacob Keller {
2650bf93bf79SJacob Keller 	struct ice_vsi *vsi = ice_get_vf_vsi(vf);
2651bf93bf79SJacob Keller 
2652bf93bf79SJacob Keller 	if (!vsi)
2653bf93bf79SJacob Keller 		return -EINVAL;
2654bf93bf79SJacob Keller 
2655bf93bf79SJacob Keller 	/* don't modify stripping if port VLAN is configured in SVM since the
2656bf93bf79SJacob Keller 	 * port VLAN is based on the inner/single VLAN in SVM
2657bf93bf79SJacob Keller 	 */
2658bf93bf79SJacob Keller 	if (ice_vf_is_port_vlan_ena(vf) && !ice_is_dvm_ena(&vsi->back->hw))
2659bf93bf79SJacob Keller 		return 0;
2660bf93bf79SJacob Keller 
2661bf93bf79SJacob Keller 	if (ice_vf_vlan_offload_ena(vf->driver_caps))
2662bf93bf79SJacob Keller 		return vsi->inner_vlan_ops.ena_stripping(vsi, ETH_P_8021Q);
2663bf93bf79SJacob Keller 	else
2664bf93bf79SJacob Keller 		return vsi->inner_vlan_ops.dis_stripping(vsi);
2665bf93bf79SJacob Keller }
2666bf93bf79SJacob Keller 
2667bf93bf79SJacob Keller static u16 ice_vc_get_max_vlan_fltrs(struct ice_vf *vf)
2668bf93bf79SJacob Keller {
2669bf93bf79SJacob Keller 	if (vf->trusted)
2670bf93bf79SJacob Keller 		return VLAN_N_VID;
2671bf93bf79SJacob Keller 	else
2672bf93bf79SJacob Keller 		return ICE_MAX_VLAN_PER_VF;
2673bf93bf79SJacob Keller }
2674bf93bf79SJacob Keller 
2675bf93bf79SJacob Keller /**
2676bf93bf79SJacob Keller  * ice_vf_outer_vlan_not_allowed - check if outer VLAN can be used
2677bf93bf79SJacob Keller  * @vf: VF that being checked for
2678bf93bf79SJacob Keller  *
2679bf93bf79SJacob Keller  * When the device is in double VLAN mode, check whether or not the outer VLAN
2680bf93bf79SJacob Keller  * is allowed.
2681bf93bf79SJacob Keller  */
2682bf93bf79SJacob Keller static bool ice_vf_outer_vlan_not_allowed(struct ice_vf *vf)
2683bf93bf79SJacob Keller {
2684bf93bf79SJacob Keller 	if (ice_vf_is_port_vlan_ena(vf))
2685bf93bf79SJacob Keller 		return true;
2686bf93bf79SJacob Keller 
2687bf93bf79SJacob Keller 	return false;
2688bf93bf79SJacob Keller }
2689bf93bf79SJacob Keller 
2690bf93bf79SJacob Keller /**
2691bf93bf79SJacob Keller  * ice_vc_set_dvm_caps - set VLAN capabilities when the device is in DVM
2692bf93bf79SJacob Keller  * @vf: VF that capabilities are being set for
2693bf93bf79SJacob Keller  * @caps: VLAN capabilities to populate
2694bf93bf79SJacob Keller  *
2695bf93bf79SJacob Keller  * Determine VLAN capabilities support based on whether a port VLAN is
2696bf93bf79SJacob Keller  * configured. If a port VLAN is configured then the VF should use the inner
2697bf93bf79SJacob Keller  * filtering/offload capabilities since the port VLAN is using the outer VLAN
2698bf93bf79SJacob Keller  * capabilies.
2699bf93bf79SJacob Keller  */
2700bf93bf79SJacob Keller static void
2701bf93bf79SJacob Keller ice_vc_set_dvm_caps(struct ice_vf *vf, struct virtchnl_vlan_caps *caps)
2702bf93bf79SJacob Keller {
2703bf93bf79SJacob Keller 	struct virtchnl_vlan_supported_caps *supported_caps;
2704bf93bf79SJacob Keller 
2705bf93bf79SJacob Keller 	if (ice_vf_outer_vlan_not_allowed(vf)) {
2706bf93bf79SJacob Keller 		/* until support for inner VLAN filtering is added when a port
2707bf93bf79SJacob Keller 		 * VLAN is configured, only support software offloaded inner
2708bf93bf79SJacob Keller 		 * VLANs when a port VLAN is confgured in DVM
2709bf93bf79SJacob Keller 		 */
2710bf93bf79SJacob Keller 		supported_caps = &caps->filtering.filtering_support;
2711bf93bf79SJacob Keller 		supported_caps->inner = VIRTCHNL_VLAN_UNSUPPORTED;
2712bf93bf79SJacob Keller 
2713bf93bf79SJacob Keller 		supported_caps = &caps->offloads.stripping_support;
2714bf93bf79SJacob Keller 		supported_caps->inner = VIRTCHNL_VLAN_ETHERTYPE_8100 |
2715bf93bf79SJacob Keller 					VIRTCHNL_VLAN_TOGGLE |
2716bf93bf79SJacob Keller 					VIRTCHNL_VLAN_TAG_LOCATION_L2TAG1;
2717bf93bf79SJacob Keller 		supported_caps->outer = VIRTCHNL_VLAN_UNSUPPORTED;
2718bf93bf79SJacob Keller 
2719bf93bf79SJacob Keller 		supported_caps = &caps->offloads.insertion_support;
2720bf93bf79SJacob Keller 		supported_caps->inner = VIRTCHNL_VLAN_ETHERTYPE_8100 |
2721bf93bf79SJacob Keller 					VIRTCHNL_VLAN_TOGGLE |
2722bf93bf79SJacob Keller 					VIRTCHNL_VLAN_TAG_LOCATION_L2TAG1;
2723bf93bf79SJacob Keller 		supported_caps->outer = VIRTCHNL_VLAN_UNSUPPORTED;
2724bf93bf79SJacob Keller 
2725bf93bf79SJacob Keller 		caps->offloads.ethertype_init = VIRTCHNL_VLAN_ETHERTYPE_8100;
2726bf93bf79SJacob Keller 		caps->offloads.ethertype_match =
2727bf93bf79SJacob Keller 			VIRTCHNL_ETHERTYPE_STRIPPING_MATCHES_INSERTION;
2728bf93bf79SJacob Keller 	} else {
2729bf93bf79SJacob Keller 		supported_caps = &caps->filtering.filtering_support;
2730bf93bf79SJacob Keller 		supported_caps->inner = VIRTCHNL_VLAN_UNSUPPORTED;
2731bf93bf79SJacob Keller 		supported_caps->outer = VIRTCHNL_VLAN_ETHERTYPE_8100 |
2732bf93bf79SJacob Keller 					VIRTCHNL_VLAN_ETHERTYPE_88A8 |
2733bf93bf79SJacob Keller 					VIRTCHNL_VLAN_ETHERTYPE_9100 |
2734bf93bf79SJacob Keller 					VIRTCHNL_VLAN_ETHERTYPE_AND;
2735bf93bf79SJacob Keller 		caps->filtering.ethertype_init = VIRTCHNL_VLAN_ETHERTYPE_8100 |
2736bf93bf79SJacob Keller 						 VIRTCHNL_VLAN_ETHERTYPE_88A8 |
2737bf93bf79SJacob Keller 						 VIRTCHNL_VLAN_ETHERTYPE_9100;
2738bf93bf79SJacob Keller 
2739bf93bf79SJacob Keller 		supported_caps = &caps->offloads.stripping_support;
2740bf93bf79SJacob Keller 		supported_caps->inner = VIRTCHNL_VLAN_TOGGLE |
2741bf93bf79SJacob Keller 					VIRTCHNL_VLAN_ETHERTYPE_8100 |
2742bf93bf79SJacob Keller 					VIRTCHNL_VLAN_TAG_LOCATION_L2TAG1;
2743bf93bf79SJacob Keller 		supported_caps->outer = VIRTCHNL_VLAN_TOGGLE |
2744bf93bf79SJacob Keller 					VIRTCHNL_VLAN_ETHERTYPE_8100 |
2745bf93bf79SJacob Keller 					VIRTCHNL_VLAN_ETHERTYPE_88A8 |
2746bf93bf79SJacob Keller 					VIRTCHNL_VLAN_ETHERTYPE_9100 |
2747bf93bf79SJacob Keller 					VIRTCHNL_VLAN_ETHERTYPE_XOR |
2748bf93bf79SJacob Keller 					VIRTCHNL_VLAN_TAG_LOCATION_L2TAG2_2;
2749bf93bf79SJacob Keller 
2750bf93bf79SJacob Keller 		supported_caps = &caps->offloads.insertion_support;
2751bf93bf79SJacob Keller 		supported_caps->inner = VIRTCHNL_VLAN_TOGGLE |
2752bf93bf79SJacob Keller 					VIRTCHNL_VLAN_ETHERTYPE_8100 |
2753bf93bf79SJacob Keller 					VIRTCHNL_VLAN_TAG_LOCATION_L2TAG1;
2754bf93bf79SJacob Keller 		supported_caps->outer = VIRTCHNL_VLAN_TOGGLE |
2755bf93bf79SJacob Keller 					VIRTCHNL_VLAN_ETHERTYPE_8100 |
2756bf93bf79SJacob Keller 					VIRTCHNL_VLAN_ETHERTYPE_88A8 |
2757bf93bf79SJacob Keller 					VIRTCHNL_VLAN_ETHERTYPE_9100 |
2758bf93bf79SJacob Keller 					VIRTCHNL_VLAN_ETHERTYPE_XOR |
2759bf93bf79SJacob Keller 					VIRTCHNL_VLAN_TAG_LOCATION_L2TAG2;
2760bf93bf79SJacob Keller 
2761bf93bf79SJacob Keller 		caps->offloads.ethertype_init = VIRTCHNL_VLAN_ETHERTYPE_8100;
2762bf93bf79SJacob Keller 
2763bf93bf79SJacob Keller 		caps->offloads.ethertype_match =
2764bf93bf79SJacob Keller 			VIRTCHNL_ETHERTYPE_STRIPPING_MATCHES_INSERTION;
2765bf93bf79SJacob Keller 	}
2766bf93bf79SJacob Keller 
2767bf93bf79SJacob Keller 	caps->filtering.max_filters = ice_vc_get_max_vlan_fltrs(vf);
2768bf93bf79SJacob Keller }
2769bf93bf79SJacob Keller 
2770bf93bf79SJacob Keller /**
2771bf93bf79SJacob Keller  * ice_vc_set_svm_caps - set VLAN capabilities when the device is in SVM
2772bf93bf79SJacob Keller  * @vf: VF that capabilities are being set for
2773bf93bf79SJacob Keller  * @caps: VLAN capabilities to populate
2774bf93bf79SJacob Keller  *
2775bf93bf79SJacob Keller  * Determine VLAN capabilities support based on whether a port VLAN is
2776bf93bf79SJacob Keller  * configured. If a port VLAN is configured then the VF does not have any VLAN
2777bf93bf79SJacob Keller  * filtering or offload capabilities since the port VLAN is using the inner VLAN
2778bf93bf79SJacob Keller  * capabilities in single VLAN mode (SVM). Otherwise allow the VF to use inner
2779bf93bf79SJacob Keller  * VLAN fitlering and offload capabilities.
2780bf93bf79SJacob Keller  */
2781bf93bf79SJacob Keller static void
2782bf93bf79SJacob Keller ice_vc_set_svm_caps(struct ice_vf *vf, struct virtchnl_vlan_caps *caps)
2783bf93bf79SJacob Keller {
2784bf93bf79SJacob Keller 	struct virtchnl_vlan_supported_caps *supported_caps;
2785bf93bf79SJacob Keller 
2786bf93bf79SJacob Keller 	if (ice_vf_is_port_vlan_ena(vf)) {
2787bf93bf79SJacob Keller 		supported_caps = &caps->filtering.filtering_support;
2788bf93bf79SJacob Keller 		supported_caps->inner = VIRTCHNL_VLAN_UNSUPPORTED;
2789bf93bf79SJacob Keller 		supported_caps->outer = VIRTCHNL_VLAN_UNSUPPORTED;
2790bf93bf79SJacob Keller 
2791bf93bf79SJacob Keller 		supported_caps = &caps->offloads.stripping_support;
2792bf93bf79SJacob Keller 		supported_caps->inner = VIRTCHNL_VLAN_UNSUPPORTED;
2793bf93bf79SJacob Keller 		supported_caps->outer = VIRTCHNL_VLAN_UNSUPPORTED;
2794bf93bf79SJacob Keller 
2795bf93bf79SJacob Keller 		supported_caps = &caps->offloads.insertion_support;
2796bf93bf79SJacob Keller 		supported_caps->inner = VIRTCHNL_VLAN_UNSUPPORTED;
2797bf93bf79SJacob Keller 		supported_caps->outer = VIRTCHNL_VLAN_UNSUPPORTED;
2798bf93bf79SJacob Keller 
2799bf93bf79SJacob Keller 		caps->offloads.ethertype_init = VIRTCHNL_VLAN_UNSUPPORTED;
2800bf93bf79SJacob Keller 		caps->offloads.ethertype_match = VIRTCHNL_VLAN_UNSUPPORTED;
2801bf93bf79SJacob Keller 		caps->filtering.max_filters = 0;
2802bf93bf79SJacob Keller 	} else {
2803bf93bf79SJacob Keller 		supported_caps = &caps->filtering.filtering_support;
2804bf93bf79SJacob Keller 		supported_caps->inner = VIRTCHNL_VLAN_ETHERTYPE_8100;
2805bf93bf79SJacob Keller 		supported_caps->outer = VIRTCHNL_VLAN_UNSUPPORTED;
2806bf93bf79SJacob Keller 		caps->filtering.ethertype_init = VIRTCHNL_VLAN_ETHERTYPE_8100;
2807bf93bf79SJacob Keller 
2808bf93bf79SJacob Keller 		supported_caps = &caps->offloads.stripping_support;
2809bf93bf79SJacob Keller 		supported_caps->inner = VIRTCHNL_VLAN_ETHERTYPE_8100 |
2810bf93bf79SJacob Keller 					VIRTCHNL_VLAN_TOGGLE |
2811bf93bf79SJacob Keller 					VIRTCHNL_VLAN_TAG_LOCATION_L2TAG1;
2812bf93bf79SJacob Keller 		supported_caps->outer = VIRTCHNL_VLAN_UNSUPPORTED;
2813bf93bf79SJacob Keller 
2814bf93bf79SJacob Keller 		supported_caps = &caps->offloads.insertion_support;
2815bf93bf79SJacob Keller 		supported_caps->inner = VIRTCHNL_VLAN_ETHERTYPE_8100 |
2816bf93bf79SJacob Keller 					VIRTCHNL_VLAN_TOGGLE |
2817bf93bf79SJacob Keller 					VIRTCHNL_VLAN_TAG_LOCATION_L2TAG1;
2818bf93bf79SJacob Keller 		supported_caps->outer = VIRTCHNL_VLAN_UNSUPPORTED;
2819bf93bf79SJacob Keller 
2820bf93bf79SJacob Keller 		caps->offloads.ethertype_init = VIRTCHNL_VLAN_ETHERTYPE_8100;
2821bf93bf79SJacob Keller 		caps->offloads.ethertype_match =
2822bf93bf79SJacob Keller 			VIRTCHNL_ETHERTYPE_STRIPPING_MATCHES_INSERTION;
2823bf93bf79SJacob Keller 		caps->filtering.max_filters = ice_vc_get_max_vlan_fltrs(vf);
2824bf93bf79SJacob Keller 	}
2825bf93bf79SJacob Keller }
2826bf93bf79SJacob Keller 
2827bf93bf79SJacob Keller /**
2828bf93bf79SJacob Keller  * ice_vc_get_offload_vlan_v2_caps - determine VF's VLAN capabilities
2829bf93bf79SJacob Keller  * @vf: VF to determine VLAN capabilities for
2830bf93bf79SJacob Keller  *
2831bf93bf79SJacob Keller  * This will only be called if the VF and PF successfully negotiated
2832bf93bf79SJacob Keller  * VIRTCHNL_VF_OFFLOAD_VLAN_V2.
2833bf93bf79SJacob Keller  *
2834bf93bf79SJacob Keller  * Set VLAN capabilities based on the current VLAN mode and whether a port VLAN
2835bf93bf79SJacob Keller  * is configured or not.
2836bf93bf79SJacob Keller  */
2837bf93bf79SJacob Keller static int ice_vc_get_offload_vlan_v2_caps(struct ice_vf *vf)
2838bf93bf79SJacob Keller {
2839bf93bf79SJacob Keller 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
2840bf93bf79SJacob Keller 	struct virtchnl_vlan_caps *caps = NULL;
2841bf93bf79SJacob Keller 	int err, len = 0;
2842bf93bf79SJacob Keller 
2843bf93bf79SJacob Keller 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
2844bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2845bf93bf79SJacob Keller 		goto out;
2846bf93bf79SJacob Keller 	}
2847bf93bf79SJacob Keller 
2848bf93bf79SJacob Keller 	caps = kzalloc(sizeof(*caps), GFP_KERNEL);
2849bf93bf79SJacob Keller 	if (!caps) {
2850bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY;
2851bf93bf79SJacob Keller 		goto out;
2852bf93bf79SJacob Keller 	}
2853bf93bf79SJacob Keller 	len = sizeof(*caps);
2854bf93bf79SJacob Keller 
2855bf93bf79SJacob Keller 	if (ice_is_dvm_ena(&vf->pf->hw))
2856bf93bf79SJacob Keller 		ice_vc_set_dvm_caps(vf, caps);
2857bf93bf79SJacob Keller 	else
2858bf93bf79SJacob Keller 		ice_vc_set_svm_caps(vf, caps);
2859bf93bf79SJacob Keller 
2860bf93bf79SJacob Keller 	/* store negotiated caps to prevent invalid VF messages */
2861bf93bf79SJacob Keller 	memcpy(&vf->vlan_v2_caps, caps, sizeof(*caps));
2862bf93bf79SJacob Keller 
2863bf93bf79SJacob Keller out:
2864bf93bf79SJacob Keller 	err = ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS,
2865bf93bf79SJacob Keller 				    v_ret, (u8 *)caps, len);
2866bf93bf79SJacob Keller 	kfree(caps);
2867bf93bf79SJacob Keller 	return err;
2868bf93bf79SJacob Keller }
2869bf93bf79SJacob Keller 
2870bf93bf79SJacob Keller /**
2871bf93bf79SJacob Keller  * ice_vc_validate_vlan_tpid - validate VLAN TPID
2872bf93bf79SJacob Keller  * @filtering_caps: negotiated/supported VLAN filtering capabilities
2873bf93bf79SJacob Keller  * @tpid: VLAN TPID used for validation
2874bf93bf79SJacob Keller  *
2875bf93bf79SJacob Keller  * Convert the VLAN TPID to a VIRTCHNL_VLAN_ETHERTYPE_* and then compare against
2876bf93bf79SJacob Keller  * the negotiated/supported filtering caps to see if the VLAN TPID is valid.
2877bf93bf79SJacob Keller  */
2878bf93bf79SJacob Keller static bool ice_vc_validate_vlan_tpid(u16 filtering_caps, u16 tpid)
2879bf93bf79SJacob Keller {
2880bf93bf79SJacob Keller 	enum virtchnl_vlan_support vlan_ethertype = VIRTCHNL_VLAN_UNSUPPORTED;
2881bf93bf79SJacob Keller 
2882bf93bf79SJacob Keller 	switch (tpid) {
2883bf93bf79SJacob Keller 	case ETH_P_8021Q:
2884bf93bf79SJacob Keller 		vlan_ethertype = VIRTCHNL_VLAN_ETHERTYPE_8100;
2885bf93bf79SJacob Keller 		break;
2886bf93bf79SJacob Keller 	case ETH_P_8021AD:
2887bf93bf79SJacob Keller 		vlan_ethertype = VIRTCHNL_VLAN_ETHERTYPE_88A8;
2888bf93bf79SJacob Keller 		break;
2889bf93bf79SJacob Keller 	case ETH_P_QINQ1:
2890bf93bf79SJacob Keller 		vlan_ethertype = VIRTCHNL_VLAN_ETHERTYPE_9100;
2891bf93bf79SJacob Keller 		break;
2892bf93bf79SJacob Keller 	}
2893bf93bf79SJacob Keller 
2894bf93bf79SJacob Keller 	if (!(filtering_caps & vlan_ethertype))
2895bf93bf79SJacob Keller 		return false;
2896bf93bf79SJacob Keller 
2897bf93bf79SJacob Keller 	return true;
2898bf93bf79SJacob Keller }
2899bf93bf79SJacob Keller 
2900bf93bf79SJacob Keller /**
2901bf93bf79SJacob Keller  * ice_vc_is_valid_vlan - validate the virtchnl_vlan
2902bf93bf79SJacob Keller  * @vc_vlan: virtchnl_vlan to validate
2903bf93bf79SJacob Keller  *
2904bf93bf79SJacob Keller  * If the VLAN TCI and VLAN TPID are 0, then this filter is invalid, so return
2905bf93bf79SJacob Keller  * false. Otherwise return true.
2906bf93bf79SJacob Keller  */
2907bf93bf79SJacob Keller static bool ice_vc_is_valid_vlan(struct virtchnl_vlan *vc_vlan)
2908bf93bf79SJacob Keller {
2909bf93bf79SJacob Keller 	if (!vc_vlan->tci || !vc_vlan->tpid)
2910bf93bf79SJacob Keller 		return false;
2911bf93bf79SJacob Keller 
2912bf93bf79SJacob Keller 	return true;
2913bf93bf79SJacob Keller }
2914bf93bf79SJacob Keller 
2915bf93bf79SJacob Keller /**
2916bf93bf79SJacob Keller  * ice_vc_validate_vlan_filter_list - validate the filter list from the VF
2917bf93bf79SJacob Keller  * @vfc: negotiated/supported VLAN filtering capabilities
2918bf93bf79SJacob Keller  * @vfl: VLAN filter list from VF to validate
2919bf93bf79SJacob Keller  *
2920bf93bf79SJacob Keller  * Validate all of the filters in the VLAN filter list from the VF. If any of
2921bf93bf79SJacob Keller  * the checks fail then return false. Otherwise return true.
2922bf93bf79SJacob Keller  */
2923bf93bf79SJacob Keller static bool
2924bf93bf79SJacob Keller ice_vc_validate_vlan_filter_list(struct virtchnl_vlan_filtering_caps *vfc,
2925bf93bf79SJacob Keller 				 struct virtchnl_vlan_filter_list_v2 *vfl)
2926bf93bf79SJacob Keller {
2927bf93bf79SJacob Keller 	u16 i;
2928bf93bf79SJacob Keller 
2929bf93bf79SJacob Keller 	if (!vfl->num_elements)
2930bf93bf79SJacob Keller 		return false;
2931bf93bf79SJacob Keller 
2932bf93bf79SJacob Keller 	for (i = 0; i < vfl->num_elements; i++) {
2933bf93bf79SJacob Keller 		struct virtchnl_vlan_supported_caps *filtering_support =
2934bf93bf79SJacob Keller 			&vfc->filtering_support;
2935bf93bf79SJacob Keller 		struct virtchnl_vlan_filter *vlan_fltr = &vfl->filters[i];
2936bf93bf79SJacob Keller 		struct virtchnl_vlan *outer = &vlan_fltr->outer;
2937bf93bf79SJacob Keller 		struct virtchnl_vlan *inner = &vlan_fltr->inner;
2938bf93bf79SJacob Keller 
2939bf93bf79SJacob Keller 		if ((ice_vc_is_valid_vlan(outer) &&
2940bf93bf79SJacob Keller 		     filtering_support->outer == VIRTCHNL_VLAN_UNSUPPORTED) ||
2941bf93bf79SJacob Keller 		    (ice_vc_is_valid_vlan(inner) &&
2942bf93bf79SJacob Keller 		     filtering_support->inner == VIRTCHNL_VLAN_UNSUPPORTED))
2943bf93bf79SJacob Keller 			return false;
2944bf93bf79SJacob Keller 
2945bf93bf79SJacob Keller 		if ((outer->tci_mask &&
2946bf93bf79SJacob Keller 		     !(filtering_support->outer & VIRTCHNL_VLAN_FILTER_MASK)) ||
2947bf93bf79SJacob Keller 		    (inner->tci_mask &&
2948bf93bf79SJacob Keller 		     !(filtering_support->inner & VIRTCHNL_VLAN_FILTER_MASK)))
2949bf93bf79SJacob Keller 			return false;
2950bf93bf79SJacob Keller 
2951bf93bf79SJacob Keller 		if (((outer->tci & VLAN_PRIO_MASK) &&
2952bf93bf79SJacob Keller 		     !(filtering_support->outer & VIRTCHNL_VLAN_PRIO)) ||
2953bf93bf79SJacob Keller 		    ((inner->tci & VLAN_PRIO_MASK) &&
2954bf93bf79SJacob Keller 		     !(filtering_support->inner & VIRTCHNL_VLAN_PRIO)))
2955bf93bf79SJacob Keller 			return false;
2956bf93bf79SJacob Keller 
2957bf93bf79SJacob Keller 		if ((ice_vc_is_valid_vlan(outer) &&
2958bf93bf79SJacob Keller 		     !ice_vc_validate_vlan_tpid(filtering_support->outer,
2959bf93bf79SJacob Keller 						outer->tpid)) ||
2960bf93bf79SJacob Keller 		    (ice_vc_is_valid_vlan(inner) &&
2961bf93bf79SJacob Keller 		     !ice_vc_validate_vlan_tpid(filtering_support->inner,
2962bf93bf79SJacob Keller 						inner->tpid)))
2963bf93bf79SJacob Keller 			return false;
2964bf93bf79SJacob Keller 	}
2965bf93bf79SJacob Keller 
2966bf93bf79SJacob Keller 	return true;
2967bf93bf79SJacob Keller }
2968bf93bf79SJacob Keller 
2969bf93bf79SJacob Keller /**
2970bf93bf79SJacob Keller  * ice_vc_to_vlan - transform from struct virtchnl_vlan to struct ice_vlan
2971bf93bf79SJacob Keller  * @vc_vlan: struct virtchnl_vlan to transform
2972bf93bf79SJacob Keller  */
2973bf93bf79SJacob Keller static struct ice_vlan ice_vc_to_vlan(struct virtchnl_vlan *vc_vlan)
2974bf93bf79SJacob Keller {
2975bf93bf79SJacob Keller 	struct ice_vlan vlan = { 0 };
2976bf93bf79SJacob Keller 
2977bf93bf79SJacob Keller 	vlan.prio = (vc_vlan->tci & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
2978bf93bf79SJacob Keller 	vlan.vid = vc_vlan->tci & VLAN_VID_MASK;
2979bf93bf79SJacob Keller 	vlan.tpid = vc_vlan->tpid;
2980bf93bf79SJacob Keller 
2981bf93bf79SJacob Keller 	return vlan;
2982bf93bf79SJacob Keller }
2983bf93bf79SJacob Keller 
2984bf93bf79SJacob Keller /**
2985bf93bf79SJacob Keller  * ice_vc_vlan_action - action to perform on the virthcnl_vlan
2986bf93bf79SJacob Keller  * @vsi: VF's VSI used to perform the action
2987bf93bf79SJacob Keller  * @vlan_action: function to perform the action with (i.e. add/del)
2988bf93bf79SJacob Keller  * @vlan: VLAN filter to perform the action with
2989bf93bf79SJacob Keller  */
2990bf93bf79SJacob Keller static int
2991bf93bf79SJacob Keller ice_vc_vlan_action(struct ice_vsi *vsi,
2992bf93bf79SJacob Keller 		   int (*vlan_action)(struct ice_vsi *, struct ice_vlan *),
2993bf93bf79SJacob Keller 		   struct ice_vlan *vlan)
2994bf93bf79SJacob Keller {
2995bf93bf79SJacob Keller 	int err;
2996bf93bf79SJacob Keller 
2997bf93bf79SJacob Keller 	err = vlan_action(vsi, vlan);
2998bf93bf79SJacob Keller 	if (err)
2999bf93bf79SJacob Keller 		return err;
3000bf93bf79SJacob Keller 
3001bf93bf79SJacob Keller 	return 0;
3002bf93bf79SJacob Keller }
3003bf93bf79SJacob Keller 
3004bf93bf79SJacob Keller /**
3005bf93bf79SJacob Keller  * ice_vc_del_vlans - delete VLAN(s) from the virtchnl filter list
3006bf93bf79SJacob Keller  * @vf: VF used to delete the VLAN(s)
3007bf93bf79SJacob Keller  * @vsi: VF's VSI used to delete the VLAN(s)
3008bf93bf79SJacob Keller  * @vfl: virthchnl filter list used to delete the filters
3009bf93bf79SJacob Keller  */
3010bf93bf79SJacob Keller static int
3011bf93bf79SJacob Keller ice_vc_del_vlans(struct ice_vf *vf, struct ice_vsi *vsi,
3012bf93bf79SJacob Keller 		 struct virtchnl_vlan_filter_list_v2 *vfl)
3013bf93bf79SJacob Keller {
3014bf93bf79SJacob Keller 	bool vlan_promisc = ice_is_vlan_promisc_allowed(vf);
3015bf93bf79SJacob Keller 	int err;
3016bf93bf79SJacob Keller 	u16 i;
3017bf93bf79SJacob Keller 
3018bf93bf79SJacob Keller 	for (i = 0; i < vfl->num_elements; i++) {
3019bf93bf79SJacob Keller 		struct virtchnl_vlan_filter *vlan_fltr = &vfl->filters[i];
3020bf93bf79SJacob Keller 		struct virtchnl_vlan *vc_vlan;
3021bf93bf79SJacob Keller 
3022bf93bf79SJacob Keller 		vc_vlan = &vlan_fltr->outer;
3023bf93bf79SJacob Keller 		if (ice_vc_is_valid_vlan(vc_vlan)) {
3024bf93bf79SJacob Keller 			struct ice_vlan vlan = ice_vc_to_vlan(vc_vlan);
3025bf93bf79SJacob Keller 
3026bf93bf79SJacob Keller 			err = ice_vc_vlan_action(vsi,
3027bf93bf79SJacob Keller 						 vsi->outer_vlan_ops.del_vlan,
3028bf93bf79SJacob Keller 						 &vlan);
3029bf93bf79SJacob Keller 			if (err)
3030bf93bf79SJacob Keller 				return err;
3031bf93bf79SJacob Keller 
3032bf93bf79SJacob Keller 			if (vlan_promisc)
3033bf93bf79SJacob Keller 				ice_vf_dis_vlan_promisc(vsi, &vlan);
3034664d4646SSylwester Dziedziuch 
3035664d4646SSylwester Dziedziuch 			/* Disable VLAN filtering when only VLAN 0 is left */
3036664d4646SSylwester Dziedziuch 			if (!ice_vsi_has_non_zero_vlans(vsi) && ice_is_dvm_ena(&vsi->back->hw)) {
3037664d4646SSylwester Dziedziuch 				err = vsi->outer_vlan_ops.dis_tx_filtering(vsi);
3038664d4646SSylwester Dziedziuch 				if (err)
3039664d4646SSylwester Dziedziuch 					return err;
3040664d4646SSylwester Dziedziuch 			}
3041bf93bf79SJacob Keller 		}
3042bf93bf79SJacob Keller 
3043bf93bf79SJacob Keller 		vc_vlan = &vlan_fltr->inner;
3044bf93bf79SJacob Keller 		if (ice_vc_is_valid_vlan(vc_vlan)) {
3045bf93bf79SJacob Keller 			struct ice_vlan vlan = ice_vc_to_vlan(vc_vlan);
3046bf93bf79SJacob Keller 
3047bf93bf79SJacob Keller 			err = ice_vc_vlan_action(vsi,
3048bf93bf79SJacob Keller 						 vsi->inner_vlan_ops.del_vlan,
3049bf93bf79SJacob Keller 						 &vlan);
3050bf93bf79SJacob Keller 			if (err)
3051bf93bf79SJacob Keller 				return err;
3052bf93bf79SJacob Keller 
3053bf93bf79SJacob Keller 			/* no support for VLAN promiscuous on inner VLAN unless
3054bf93bf79SJacob Keller 			 * we are in Single VLAN Mode (SVM)
3055bf93bf79SJacob Keller 			 */
3056664d4646SSylwester Dziedziuch 			if (!ice_is_dvm_ena(&vsi->back->hw)) {
3057664d4646SSylwester Dziedziuch 				if (vlan_promisc)
3058bf93bf79SJacob Keller 					ice_vf_dis_vlan_promisc(vsi, &vlan);
3059664d4646SSylwester Dziedziuch 
3060664d4646SSylwester Dziedziuch 				/* Disable VLAN filtering when only VLAN 0 is left */
3061664d4646SSylwester Dziedziuch 				if (!ice_vsi_has_non_zero_vlans(vsi)) {
3062664d4646SSylwester Dziedziuch 					err = vsi->inner_vlan_ops.dis_tx_filtering(vsi);
3063664d4646SSylwester Dziedziuch 					if (err)
3064664d4646SSylwester Dziedziuch 						return err;
3065664d4646SSylwester Dziedziuch 				}
3066664d4646SSylwester Dziedziuch 			}
3067bf93bf79SJacob Keller 		}
3068bf93bf79SJacob Keller 	}
3069bf93bf79SJacob Keller 
3070bf93bf79SJacob Keller 	return 0;
3071bf93bf79SJacob Keller }
3072bf93bf79SJacob Keller 
3073bf93bf79SJacob Keller /**
3074bf93bf79SJacob Keller  * ice_vc_remove_vlan_v2_msg - virtchnl handler for VIRTCHNL_OP_DEL_VLAN_V2
3075bf93bf79SJacob Keller  * @vf: VF the message was received from
3076bf93bf79SJacob Keller  * @msg: message received from the VF
3077bf93bf79SJacob Keller  */
3078bf93bf79SJacob Keller static int ice_vc_remove_vlan_v2_msg(struct ice_vf *vf, u8 *msg)
3079bf93bf79SJacob Keller {
3080bf93bf79SJacob Keller 	struct virtchnl_vlan_filter_list_v2 *vfl =
3081bf93bf79SJacob Keller 		(struct virtchnl_vlan_filter_list_v2 *)msg;
3082bf93bf79SJacob Keller 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
3083bf93bf79SJacob Keller 	struct ice_vsi *vsi;
3084bf93bf79SJacob Keller 
3085bf93bf79SJacob Keller 	if (!ice_vc_validate_vlan_filter_list(&vf->vlan_v2_caps.filtering,
3086bf93bf79SJacob Keller 					      vfl)) {
3087bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
3088bf93bf79SJacob Keller 		goto out;
3089bf93bf79SJacob Keller 	}
3090bf93bf79SJacob Keller 
3091bf93bf79SJacob Keller 	if (!ice_vc_isvalid_vsi_id(vf, vfl->vport_id)) {
3092bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
3093bf93bf79SJacob Keller 		goto out;
3094bf93bf79SJacob Keller 	}
3095bf93bf79SJacob Keller 
3096bf93bf79SJacob Keller 	vsi = ice_get_vf_vsi(vf);
3097bf93bf79SJacob Keller 	if (!vsi) {
3098bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
3099bf93bf79SJacob Keller 		goto out;
3100bf93bf79SJacob Keller 	}
3101bf93bf79SJacob Keller 
3102bf93bf79SJacob Keller 	if (ice_vc_del_vlans(vf, vsi, vfl))
3103bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
3104bf93bf79SJacob Keller 
3105bf93bf79SJacob Keller out:
3106bf93bf79SJacob Keller 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_DEL_VLAN_V2, v_ret, NULL,
3107bf93bf79SJacob Keller 				     0);
3108bf93bf79SJacob Keller }
3109bf93bf79SJacob Keller 
3110bf93bf79SJacob Keller /**
3111bf93bf79SJacob Keller  * ice_vc_add_vlans - add VLAN(s) from the virtchnl filter list
3112bf93bf79SJacob Keller  * @vf: VF used to add the VLAN(s)
3113bf93bf79SJacob Keller  * @vsi: VF's VSI used to add the VLAN(s)
3114bf93bf79SJacob Keller  * @vfl: virthchnl filter list used to add the filters
3115bf93bf79SJacob Keller  */
3116bf93bf79SJacob Keller static int
3117bf93bf79SJacob Keller ice_vc_add_vlans(struct ice_vf *vf, struct ice_vsi *vsi,
3118bf93bf79SJacob Keller 		 struct virtchnl_vlan_filter_list_v2 *vfl)
3119bf93bf79SJacob Keller {
3120bf93bf79SJacob Keller 	bool vlan_promisc = ice_is_vlan_promisc_allowed(vf);
3121bf93bf79SJacob Keller 	int err;
3122bf93bf79SJacob Keller 	u16 i;
3123bf93bf79SJacob Keller 
3124bf93bf79SJacob Keller 	for (i = 0; i < vfl->num_elements; i++) {
3125bf93bf79SJacob Keller 		struct virtchnl_vlan_filter *vlan_fltr = &vfl->filters[i];
3126bf93bf79SJacob Keller 		struct virtchnl_vlan *vc_vlan;
3127bf93bf79SJacob Keller 
3128bf93bf79SJacob Keller 		vc_vlan = &vlan_fltr->outer;
3129bf93bf79SJacob Keller 		if (ice_vc_is_valid_vlan(vc_vlan)) {
3130bf93bf79SJacob Keller 			struct ice_vlan vlan = ice_vc_to_vlan(vc_vlan);
3131bf93bf79SJacob Keller 
3132bf93bf79SJacob Keller 			err = ice_vc_vlan_action(vsi,
3133bf93bf79SJacob Keller 						 vsi->outer_vlan_ops.add_vlan,
3134bf93bf79SJacob Keller 						 &vlan);
3135bf93bf79SJacob Keller 			if (err)
3136bf93bf79SJacob Keller 				return err;
3137bf93bf79SJacob Keller 
3138bf93bf79SJacob Keller 			if (vlan_promisc) {
3139bf93bf79SJacob Keller 				err = ice_vf_ena_vlan_promisc(vsi, &vlan);
3140bf93bf79SJacob Keller 				if (err)
3141bf93bf79SJacob Keller 					return err;
3142bf93bf79SJacob Keller 			}
3143664d4646SSylwester Dziedziuch 
3144664d4646SSylwester Dziedziuch 			/* Enable VLAN filtering on first non-zero VLAN */
3145664d4646SSylwester Dziedziuch 			if (vf->spoofchk && vlan.vid && ice_is_dvm_ena(&vsi->back->hw)) {
3146664d4646SSylwester Dziedziuch 				err = vsi->outer_vlan_ops.ena_tx_filtering(vsi);
3147664d4646SSylwester Dziedziuch 				if (err)
3148664d4646SSylwester Dziedziuch 					return err;
3149664d4646SSylwester Dziedziuch 			}
3150bf93bf79SJacob Keller 		}
3151bf93bf79SJacob Keller 
3152bf93bf79SJacob Keller 		vc_vlan = &vlan_fltr->inner;
3153bf93bf79SJacob Keller 		if (ice_vc_is_valid_vlan(vc_vlan)) {
3154bf93bf79SJacob Keller 			struct ice_vlan vlan = ice_vc_to_vlan(vc_vlan);
3155bf93bf79SJacob Keller 
3156bf93bf79SJacob Keller 			err = ice_vc_vlan_action(vsi,
3157bf93bf79SJacob Keller 						 vsi->inner_vlan_ops.add_vlan,
3158bf93bf79SJacob Keller 						 &vlan);
3159bf93bf79SJacob Keller 			if (err)
3160bf93bf79SJacob Keller 				return err;
3161bf93bf79SJacob Keller 
3162bf93bf79SJacob Keller 			/* no support for VLAN promiscuous on inner VLAN unless
3163bf93bf79SJacob Keller 			 * we are in Single VLAN Mode (SVM)
3164bf93bf79SJacob Keller 			 */
3165664d4646SSylwester Dziedziuch 			if (!ice_is_dvm_ena(&vsi->back->hw)) {
3166664d4646SSylwester Dziedziuch 				if (vlan_promisc) {
3167bf93bf79SJacob Keller 					err = ice_vf_ena_vlan_promisc(vsi, &vlan);
3168bf93bf79SJacob Keller 					if (err)
3169bf93bf79SJacob Keller 						return err;
3170bf93bf79SJacob Keller 				}
3171664d4646SSylwester Dziedziuch 
3172664d4646SSylwester Dziedziuch 				/* Enable VLAN filtering on first non-zero VLAN */
3173664d4646SSylwester Dziedziuch 				if (vf->spoofchk && vlan.vid) {
3174664d4646SSylwester Dziedziuch 					err = vsi->inner_vlan_ops.ena_tx_filtering(vsi);
3175664d4646SSylwester Dziedziuch 					if (err)
3176664d4646SSylwester Dziedziuch 						return err;
3177664d4646SSylwester Dziedziuch 				}
3178664d4646SSylwester Dziedziuch 			}
3179bf93bf79SJacob Keller 		}
3180bf93bf79SJacob Keller 	}
3181bf93bf79SJacob Keller 
3182bf93bf79SJacob Keller 	return 0;
3183bf93bf79SJacob Keller }
3184bf93bf79SJacob Keller 
3185bf93bf79SJacob Keller /**
3186bf93bf79SJacob Keller  * ice_vc_validate_add_vlan_filter_list - validate add filter list from the VF
3187bf93bf79SJacob Keller  * @vsi: VF VSI used to get number of existing VLAN filters
3188bf93bf79SJacob Keller  * @vfc: negotiated/supported VLAN filtering capabilities
3189bf93bf79SJacob Keller  * @vfl: VLAN filter list from VF to validate
3190bf93bf79SJacob Keller  *
3191bf93bf79SJacob Keller  * Validate all of the filters in the VLAN filter list from the VF during the
3192bf93bf79SJacob Keller  * VIRTCHNL_OP_ADD_VLAN_V2 opcode. If any of the checks fail then return false.
3193bf93bf79SJacob Keller  * Otherwise return true.
3194bf93bf79SJacob Keller  */
3195bf93bf79SJacob Keller static bool
3196bf93bf79SJacob Keller ice_vc_validate_add_vlan_filter_list(struct ice_vsi *vsi,
3197bf93bf79SJacob Keller 				     struct virtchnl_vlan_filtering_caps *vfc,
3198bf93bf79SJacob Keller 				     struct virtchnl_vlan_filter_list_v2 *vfl)
3199bf93bf79SJacob Keller {
32001e308c6fSPrzemyslaw Patynowski 	u16 num_requested_filters = ice_vsi_num_non_zero_vlans(vsi) +
32011e308c6fSPrzemyslaw Patynowski 		vfl->num_elements;
3202bf93bf79SJacob Keller 
3203bf93bf79SJacob Keller 	if (num_requested_filters > vfc->max_filters)
3204bf93bf79SJacob Keller 		return false;
3205bf93bf79SJacob Keller 
3206bf93bf79SJacob Keller 	return ice_vc_validate_vlan_filter_list(vfc, vfl);
3207bf93bf79SJacob Keller }
3208bf93bf79SJacob Keller 
3209bf93bf79SJacob Keller /**
3210bf93bf79SJacob Keller  * ice_vc_add_vlan_v2_msg - virtchnl handler for VIRTCHNL_OP_ADD_VLAN_V2
3211bf93bf79SJacob Keller  * @vf: VF the message was received from
3212bf93bf79SJacob Keller  * @msg: message received from the VF
3213bf93bf79SJacob Keller  */
3214bf93bf79SJacob Keller static int ice_vc_add_vlan_v2_msg(struct ice_vf *vf, u8 *msg)
3215bf93bf79SJacob Keller {
3216bf93bf79SJacob Keller 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
3217bf93bf79SJacob Keller 	struct virtchnl_vlan_filter_list_v2 *vfl =
3218bf93bf79SJacob Keller 		(struct virtchnl_vlan_filter_list_v2 *)msg;
3219bf93bf79SJacob Keller 	struct ice_vsi *vsi;
3220bf93bf79SJacob Keller 
3221bf93bf79SJacob Keller 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
3222bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
3223bf93bf79SJacob Keller 		goto out;
3224bf93bf79SJacob Keller 	}
3225bf93bf79SJacob Keller 
3226bf93bf79SJacob Keller 	if (!ice_vc_isvalid_vsi_id(vf, vfl->vport_id)) {
3227bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
3228bf93bf79SJacob Keller 		goto out;
3229bf93bf79SJacob Keller 	}
3230bf93bf79SJacob Keller 
3231bf93bf79SJacob Keller 	vsi = ice_get_vf_vsi(vf);
3232bf93bf79SJacob Keller 	if (!vsi) {
3233bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
3234bf93bf79SJacob Keller 		goto out;
3235bf93bf79SJacob Keller 	}
3236bf93bf79SJacob Keller 
3237bf93bf79SJacob Keller 	if (!ice_vc_validate_add_vlan_filter_list(vsi,
3238bf93bf79SJacob Keller 						  &vf->vlan_v2_caps.filtering,
3239bf93bf79SJacob Keller 						  vfl)) {
3240bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
3241bf93bf79SJacob Keller 		goto out;
3242bf93bf79SJacob Keller 	}
3243bf93bf79SJacob Keller 
3244bf93bf79SJacob Keller 	if (ice_vc_add_vlans(vf, vsi, vfl))
3245bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
3246bf93bf79SJacob Keller 
3247bf93bf79SJacob Keller out:
3248bf93bf79SJacob Keller 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_ADD_VLAN_V2, v_ret, NULL,
3249bf93bf79SJacob Keller 				     0);
3250bf93bf79SJacob Keller }
3251bf93bf79SJacob Keller 
3252bf93bf79SJacob Keller /**
3253bf93bf79SJacob Keller  * ice_vc_valid_vlan_setting - validate VLAN setting
3254bf93bf79SJacob Keller  * @negotiated_settings: negotiated VLAN settings during VF init
3255bf93bf79SJacob Keller  * @ethertype_setting: ethertype(s) requested for the VLAN setting
3256bf93bf79SJacob Keller  */
3257bf93bf79SJacob Keller static bool
3258bf93bf79SJacob Keller ice_vc_valid_vlan_setting(u32 negotiated_settings, u32 ethertype_setting)
3259bf93bf79SJacob Keller {
3260bf93bf79SJacob Keller 	if (ethertype_setting && !(negotiated_settings & ethertype_setting))
3261bf93bf79SJacob Keller 		return false;
3262bf93bf79SJacob Keller 
3263bf93bf79SJacob Keller 	/* only allow a single VIRTCHNL_VLAN_ETHERTYPE if
3264bf93bf79SJacob Keller 	 * VIRTHCNL_VLAN_ETHERTYPE_AND is not negotiated/supported
3265bf93bf79SJacob Keller 	 */
3266bf93bf79SJacob Keller 	if (!(negotiated_settings & VIRTCHNL_VLAN_ETHERTYPE_AND) &&
3267bf93bf79SJacob Keller 	    hweight32(ethertype_setting) > 1)
3268bf93bf79SJacob Keller 		return false;
3269bf93bf79SJacob Keller 
3270bf93bf79SJacob Keller 	/* ability to modify the VLAN setting was not negotiated */
3271bf93bf79SJacob Keller 	if (!(negotiated_settings & VIRTCHNL_VLAN_TOGGLE))
3272bf93bf79SJacob Keller 		return false;
3273bf93bf79SJacob Keller 
3274bf93bf79SJacob Keller 	return true;
3275bf93bf79SJacob Keller }
3276bf93bf79SJacob Keller 
3277bf93bf79SJacob Keller /**
3278bf93bf79SJacob Keller  * ice_vc_valid_vlan_setting_msg - validate the VLAN setting message
3279bf93bf79SJacob Keller  * @caps: negotiated VLAN settings during VF init
3280bf93bf79SJacob Keller  * @msg: message to validate
3281bf93bf79SJacob Keller  *
3282bf93bf79SJacob Keller  * Used to validate any VLAN virtchnl message sent as a
3283bf93bf79SJacob Keller  * virtchnl_vlan_setting structure. Validates the message against the
3284bf93bf79SJacob Keller  * negotiated/supported caps during VF driver init.
3285bf93bf79SJacob Keller  */
3286bf93bf79SJacob Keller static bool
3287bf93bf79SJacob Keller ice_vc_valid_vlan_setting_msg(struct virtchnl_vlan_supported_caps *caps,
3288bf93bf79SJacob Keller 			      struct virtchnl_vlan_setting *msg)
3289bf93bf79SJacob Keller {
3290bf93bf79SJacob Keller 	if ((!msg->outer_ethertype_setting &&
3291bf93bf79SJacob Keller 	     !msg->inner_ethertype_setting) ||
3292bf93bf79SJacob Keller 	    (!caps->outer && !caps->inner))
3293bf93bf79SJacob Keller 		return false;
3294bf93bf79SJacob Keller 
3295bf93bf79SJacob Keller 	if (msg->outer_ethertype_setting &&
3296bf93bf79SJacob Keller 	    !ice_vc_valid_vlan_setting(caps->outer,
3297bf93bf79SJacob Keller 				       msg->outer_ethertype_setting))
3298bf93bf79SJacob Keller 		return false;
3299bf93bf79SJacob Keller 
3300bf93bf79SJacob Keller 	if (msg->inner_ethertype_setting &&
3301bf93bf79SJacob Keller 	    !ice_vc_valid_vlan_setting(caps->inner,
3302bf93bf79SJacob Keller 				       msg->inner_ethertype_setting))
3303bf93bf79SJacob Keller 		return false;
3304bf93bf79SJacob Keller 
3305bf93bf79SJacob Keller 	return true;
3306bf93bf79SJacob Keller }
3307bf93bf79SJacob Keller 
3308bf93bf79SJacob Keller /**
3309bf93bf79SJacob Keller  * ice_vc_get_tpid - transform from VIRTCHNL_VLAN_ETHERTYPE_* to VLAN TPID
3310bf93bf79SJacob Keller  * @ethertype_setting: VIRTCHNL_VLAN_ETHERTYPE_* used to get VLAN TPID
3311bf93bf79SJacob Keller  * @tpid: VLAN TPID to populate
3312bf93bf79SJacob Keller  */
3313bf93bf79SJacob Keller static int ice_vc_get_tpid(u32 ethertype_setting, u16 *tpid)
3314bf93bf79SJacob Keller {
3315bf93bf79SJacob Keller 	switch (ethertype_setting) {
3316bf93bf79SJacob Keller 	case VIRTCHNL_VLAN_ETHERTYPE_8100:
3317bf93bf79SJacob Keller 		*tpid = ETH_P_8021Q;
3318bf93bf79SJacob Keller 		break;
3319bf93bf79SJacob Keller 	case VIRTCHNL_VLAN_ETHERTYPE_88A8:
3320bf93bf79SJacob Keller 		*tpid = ETH_P_8021AD;
3321bf93bf79SJacob Keller 		break;
3322bf93bf79SJacob Keller 	case VIRTCHNL_VLAN_ETHERTYPE_9100:
3323bf93bf79SJacob Keller 		*tpid = ETH_P_QINQ1;
3324bf93bf79SJacob Keller 		break;
3325bf93bf79SJacob Keller 	default:
3326bf93bf79SJacob Keller 		*tpid = 0;
3327bf93bf79SJacob Keller 		return -EINVAL;
3328bf93bf79SJacob Keller 	}
3329bf93bf79SJacob Keller 
3330bf93bf79SJacob Keller 	return 0;
3331bf93bf79SJacob Keller }
3332bf93bf79SJacob Keller 
3333bf93bf79SJacob Keller /**
3334bf93bf79SJacob Keller  * ice_vc_ena_vlan_offload - enable VLAN offload based on the ethertype_setting
3335bf93bf79SJacob Keller  * @vsi: VF's VSI used to enable the VLAN offload
3336bf93bf79SJacob Keller  * @ena_offload: function used to enable the VLAN offload
3337bf93bf79SJacob Keller  * @ethertype_setting: VIRTCHNL_VLAN_ETHERTYPE_* to enable offloads for
3338bf93bf79SJacob Keller  */
3339bf93bf79SJacob Keller static int
3340bf93bf79SJacob Keller ice_vc_ena_vlan_offload(struct ice_vsi *vsi,
3341bf93bf79SJacob Keller 			int (*ena_offload)(struct ice_vsi *vsi, u16 tpid),
3342bf93bf79SJacob Keller 			u32 ethertype_setting)
3343bf93bf79SJacob Keller {
3344bf93bf79SJacob Keller 	u16 tpid;
3345bf93bf79SJacob Keller 	int err;
3346bf93bf79SJacob Keller 
3347bf93bf79SJacob Keller 	err = ice_vc_get_tpid(ethertype_setting, &tpid);
3348bf93bf79SJacob Keller 	if (err)
3349bf93bf79SJacob Keller 		return err;
3350bf93bf79SJacob Keller 
3351bf93bf79SJacob Keller 	err = ena_offload(vsi, tpid);
3352bf93bf79SJacob Keller 	if (err)
3353bf93bf79SJacob Keller 		return err;
3354bf93bf79SJacob Keller 
3355bf93bf79SJacob Keller 	return 0;
3356bf93bf79SJacob Keller }
3357bf93bf79SJacob Keller 
3358bf93bf79SJacob Keller #define ICE_L2TSEL_QRX_CONTEXT_REG_IDX	3
3359bf93bf79SJacob Keller #define ICE_L2TSEL_BIT_OFFSET		23
3360bf93bf79SJacob Keller enum ice_l2tsel {
3361bf93bf79SJacob Keller 	ICE_L2TSEL_EXTRACT_FIRST_TAG_L2TAG2_2ND,
3362bf93bf79SJacob Keller 	ICE_L2TSEL_EXTRACT_FIRST_TAG_L2TAG1,
3363bf93bf79SJacob Keller };
3364bf93bf79SJacob Keller 
3365bf93bf79SJacob Keller /**
3366bf93bf79SJacob Keller  * ice_vsi_update_l2tsel - update l2tsel field for all Rx rings on this VSI
3367bf93bf79SJacob Keller  * @vsi: VSI used to update l2tsel on
3368bf93bf79SJacob Keller  * @l2tsel: l2tsel setting requested
3369bf93bf79SJacob Keller  *
3370bf93bf79SJacob Keller  * Use the l2tsel setting to update all of the Rx queue context bits for l2tsel.
3371bf93bf79SJacob Keller  * This will modify which descriptor field the first offloaded VLAN will be
3372bf93bf79SJacob Keller  * stripped into.
3373bf93bf79SJacob Keller  */
3374bf93bf79SJacob Keller static void ice_vsi_update_l2tsel(struct ice_vsi *vsi, enum ice_l2tsel l2tsel)
3375bf93bf79SJacob Keller {
3376bf93bf79SJacob Keller 	struct ice_hw *hw = &vsi->back->hw;
3377bf93bf79SJacob Keller 	u32 l2tsel_bit;
3378bf93bf79SJacob Keller 	int i;
3379bf93bf79SJacob Keller 
3380bf93bf79SJacob Keller 	if (l2tsel == ICE_L2TSEL_EXTRACT_FIRST_TAG_L2TAG2_2ND)
3381bf93bf79SJacob Keller 		l2tsel_bit = 0;
3382bf93bf79SJacob Keller 	else
3383bf93bf79SJacob Keller 		l2tsel_bit = BIT(ICE_L2TSEL_BIT_OFFSET);
3384bf93bf79SJacob Keller 
3385bf93bf79SJacob Keller 	for (i = 0; i < vsi->alloc_rxq; i++) {
3386bf93bf79SJacob Keller 		u16 pfq = vsi->rxq_map[i];
3387bf93bf79SJacob Keller 		u32 qrx_context_offset;
3388bf93bf79SJacob Keller 		u32 regval;
3389bf93bf79SJacob Keller 
3390bf93bf79SJacob Keller 		qrx_context_offset =
3391bf93bf79SJacob Keller 			QRX_CONTEXT(ICE_L2TSEL_QRX_CONTEXT_REG_IDX, pfq);
3392bf93bf79SJacob Keller 
3393bf93bf79SJacob Keller 		regval = rd32(hw, qrx_context_offset);
3394bf93bf79SJacob Keller 		regval &= ~BIT(ICE_L2TSEL_BIT_OFFSET);
3395bf93bf79SJacob Keller 		regval |= l2tsel_bit;
3396bf93bf79SJacob Keller 		wr32(hw, qrx_context_offset, regval);
3397bf93bf79SJacob Keller 	}
3398bf93bf79SJacob Keller }
3399bf93bf79SJacob Keller 
3400bf93bf79SJacob Keller /**
3401bf93bf79SJacob Keller  * ice_vc_ena_vlan_stripping_v2_msg
3402bf93bf79SJacob Keller  * @vf: VF the message was received from
3403bf93bf79SJacob Keller  * @msg: message received from the VF
3404bf93bf79SJacob Keller  *
3405bf93bf79SJacob Keller  * virthcnl handler for VIRTCHNL_OP_ENABLE_VLAN_STRIPPING_V2
3406bf93bf79SJacob Keller  */
3407bf93bf79SJacob Keller static int ice_vc_ena_vlan_stripping_v2_msg(struct ice_vf *vf, u8 *msg)
3408bf93bf79SJacob Keller {
3409bf93bf79SJacob Keller 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
3410bf93bf79SJacob Keller 	struct virtchnl_vlan_supported_caps *stripping_support;
3411bf93bf79SJacob Keller 	struct virtchnl_vlan_setting *strip_msg =
3412bf93bf79SJacob Keller 		(struct virtchnl_vlan_setting *)msg;
3413bf93bf79SJacob Keller 	u32 ethertype_setting;
3414bf93bf79SJacob Keller 	struct ice_vsi *vsi;
3415bf93bf79SJacob Keller 
3416bf93bf79SJacob Keller 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
3417bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
3418bf93bf79SJacob Keller 		goto out;
3419bf93bf79SJacob Keller 	}
3420bf93bf79SJacob Keller 
3421bf93bf79SJacob Keller 	if (!ice_vc_isvalid_vsi_id(vf, strip_msg->vport_id)) {
3422bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
3423bf93bf79SJacob Keller 		goto out;
3424bf93bf79SJacob Keller 	}
3425bf93bf79SJacob Keller 
3426bf93bf79SJacob Keller 	vsi = ice_get_vf_vsi(vf);
3427bf93bf79SJacob Keller 	if (!vsi) {
3428bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
3429bf93bf79SJacob Keller 		goto out;
3430bf93bf79SJacob Keller 	}
3431bf93bf79SJacob Keller 
3432bf93bf79SJacob Keller 	stripping_support = &vf->vlan_v2_caps.offloads.stripping_support;
3433bf93bf79SJacob Keller 	if (!ice_vc_valid_vlan_setting_msg(stripping_support, strip_msg)) {
3434bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
3435bf93bf79SJacob Keller 		goto out;
3436bf93bf79SJacob Keller 	}
3437bf93bf79SJacob Keller 
3438bf93bf79SJacob Keller 	ethertype_setting = strip_msg->outer_ethertype_setting;
3439bf93bf79SJacob Keller 	if (ethertype_setting) {
3440bf93bf79SJacob Keller 		if (ice_vc_ena_vlan_offload(vsi,
3441bf93bf79SJacob Keller 					    vsi->outer_vlan_ops.ena_stripping,
3442bf93bf79SJacob Keller 					    ethertype_setting)) {
3443bf93bf79SJacob Keller 			v_ret = VIRTCHNL_STATUS_ERR_PARAM;
3444bf93bf79SJacob Keller 			goto out;
3445bf93bf79SJacob Keller 		} else {
3446bf93bf79SJacob Keller 			enum ice_l2tsel l2tsel =
3447bf93bf79SJacob Keller 				ICE_L2TSEL_EXTRACT_FIRST_TAG_L2TAG2_2ND;
3448bf93bf79SJacob Keller 
3449bf93bf79SJacob Keller 			/* PF tells the VF that the outer VLAN tag is always
3450bf93bf79SJacob Keller 			 * extracted to VIRTCHNL_VLAN_TAG_LOCATION_L2TAG2_2 and
3451bf93bf79SJacob Keller 			 * inner is always extracted to
3452bf93bf79SJacob Keller 			 * VIRTCHNL_VLAN_TAG_LOCATION_L2TAG1. This is needed to
3453bf93bf79SJacob Keller 			 * support outer stripping so the first tag always ends
3454bf93bf79SJacob Keller 			 * up in L2TAG2_2ND and the second/inner tag, if
3455bf93bf79SJacob Keller 			 * enabled, is extracted in L2TAG1.
3456bf93bf79SJacob Keller 			 */
3457bf93bf79SJacob Keller 			ice_vsi_update_l2tsel(vsi, l2tsel);
3458bf93bf79SJacob Keller 		}
3459bf93bf79SJacob Keller 	}
3460bf93bf79SJacob Keller 
3461bf93bf79SJacob Keller 	ethertype_setting = strip_msg->inner_ethertype_setting;
3462bf93bf79SJacob Keller 	if (ethertype_setting &&
3463bf93bf79SJacob Keller 	    ice_vc_ena_vlan_offload(vsi, vsi->inner_vlan_ops.ena_stripping,
3464bf93bf79SJacob Keller 				    ethertype_setting)) {
3465bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
3466bf93bf79SJacob Keller 		goto out;
3467bf93bf79SJacob Keller 	}
3468bf93bf79SJacob Keller 
3469bf93bf79SJacob Keller out:
3470bf93bf79SJacob Keller 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_ENABLE_VLAN_STRIPPING_V2,
3471bf93bf79SJacob Keller 				     v_ret, NULL, 0);
3472bf93bf79SJacob Keller }
3473bf93bf79SJacob Keller 
3474bf93bf79SJacob Keller /**
3475bf93bf79SJacob Keller  * ice_vc_dis_vlan_stripping_v2_msg
3476bf93bf79SJacob Keller  * @vf: VF the message was received from
3477bf93bf79SJacob Keller  * @msg: message received from the VF
3478bf93bf79SJacob Keller  *
3479bf93bf79SJacob Keller  * virthcnl handler for VIRTCHNL_OP_DISABLE_VLAN_STRIPPING_V2
3480bf93bf79SJacob Keller  */
3481bf93bf79SJacob Keller static int ice_vc_dis_vlan_stripping_v2_msg(struct ice_vf *vf, u8 *msg)
3482bf93bf79SJacob Keller {
3483bf93bf79SJacob Keller 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
3484bf93bf79SJacob Keller 	struct virtchnl_vlan_supported_caps *stripping_support;
3485bf93bf79SJacob Keller 	struct virtchnl_vlan_setting *strip_msg =
3486bf93bf79SJacob Keller 		(struct virtchnl_vlan_setting *)msg;
3487bf93bf79SJacob Keller 	u32 ethertype_setting;
3488bf93bf79SJacob Keller 	struct ice_vsi *vsi;
3489bf93bf79SJacob Keller 
3490bf93bf79SJacob Keller 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
3491bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
3492bf93bf79SJacob Keller 		goto out;
3493bf93bf79SJacob Keller 	}
3494bf93bf79SJacob Keller 
3495bf93bf79SJacob Keller 	if (!ice_vc_isvalid_vsi_id(vf, strip_msg->vport_id)) {
3496bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
3497bf93bf79SJacob Keller 		goto out;
3498bf93bf79SJacob Keller 	}
3499bf93bf79SJacob Keller 
3500bf93bf79SJacob Keller 	vsi = ice_get_vf_vsi(vf);
3501bf93bf79SJacob Keller 	if (!vsi) {
3502bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
3503bf93bf79SJacob Keller 		goto out;
3504bf93bf79SJacob Keller 	}
3505bf93bf79SJacob Keller 
3506bf93bf79SJacob Keller 	stripping_support = &vf->vlan_v2_caps.offloads.stripping_support;
3507bf93bf79SJacob Keller 	if (!ice_vc_valid_vlan_setting_msg(stripping_support, strip_msg)) {
3508bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
3509bf93bf79SJacob Keller 		goto out;
3510bf93bf79SJacob Keller 	}
3511bf93bf79SJacob Keller 
3512bf93bf79SJacob Keller 	ethertype_setting = strip_msg->outer_ethertype_setting;
3513bf93bf79SJacob Keller 	if (ethertype_setting) {
3514bf93bf79SJacob Keller 		if (vsi->outer_vlan_ops.dis_stripping(vsi)) {
3515bf93bf79SJacob Keller 			v_ret = VIRTCHNL_STATUS_ERR_PARAM;
3516bf93bf79SJacob Keller 			goto out;
3517bf93bf79SJacob Keller 		} else {
3518bf93bf79SJacob Keller 			enum ice_l2tsel l2tsel =
3519bf93bf79SJacob Keller 				ICE_L2TSEL_EXTRACT_FIRST_TAG_L2TAG1;
3520bf93bf79SJacob Keller 
3521bf93bf79SJacob Keller 			/* PF tells the VF that the outer VLAN tag is always
3522bf93bf79SJacob Keller 			 * extracted to VIRTCHNL_VLAN_TAG_LOCATION_L2TAG2_2 and
3523bf93bf79SJacob Keller 			 * inner is always extracted to
3524bf93bf79SJacob Keller 			 * VIRTCHNL_VLAN_TAG_LOCATION_L2TAG1. This is needed to
3525bf93bf79SJacob Keller 			 * support inner stripping while outer stripping is
3526bf93bf79SJacob Keller 			 * disabled so that the first and only tag is extracted
3527bf93bf79SJacob Keller 			 * in L2TAG1.
3528bf93bf79SJacob Keller 			 */
3529bf93bf79SJacob Keller 			ice_vsi_update_l2tsel(vsi, l2tsel);
3530bf93bf79SJacob Keller 		}
3531bf93bf79SJacob Keller 	}
3532bf93bf79SJacob Keller 
3533bf93bf79SJacob Keller 	ethertype_setting = strip_msg->inner_ethertype_setting;
3534bf93bf79SJacob Keller 	if (ethertype_setting && vsi->inner_vlan_ops.dis_stripping(vsi)) {
3535bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
3536bf93bf79SJacob Keller 		goto out;
3537bf93bf79SJacob Keller 	}
3538bf93bf79SJacob Keller 
3539bf93bf79SJacob Keller out:
3540bf93bf79SJacob Keller 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_DISABLE_VLAN_STRIPPING_V2,
3541bf93bf79SJacob Keller 				     v_ret, NULL, 0);
3542bf93bf79SJacob Keller }
3543bf93bf79SJacob Keller 
3544bf93bf79SJacob Keller /**
3545bf93bf79SJacob Keller  * ice_vc_ena_vlan_insertion_v2_msg
3546bf93bf79SJacob Keller  * @vf: VF the message was received from
3547bf93bf79SJacob Keller  * @msg: message received from the VF
3548bf93bf79SJacob Keller  *
3549bf93bf79SJacob Keller  * virthcnl handler for VIRTCHNL_OP_ENABLE_VLAN_INSERTION_V2
3550bf93bf79SJacob Keller  */
3551bf93bf79SJacob Keller static int ice_vc_ena_vlan_insertion_v2_msg(struct ice_vf *vf, u8 *msg)
3552bf93bf79SJacob Keller {
3553bf93bf79SJacob Keller 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
3554bf93bf79SJacob Keller 	struct virtchnl_vlan_supported_caps *insertion_support;
3555bf93bf79SJacob Keller 	struct virtchnl_vlan_setting *insertion_msg =
3556bf93bf79SJacob Keller 		(struct virtchnl_vlan_setting *)msg;
3557bf93bf79SJacob Keller 	u32 ethertype_setting;
3558bf93bf79SJacob Keller 	struct ice_vsi *vsi;
3559bf93bf79SJacob Keller 
3560bf93bf79SJacob Keller 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
3561bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
3562bf93bf79SJacob Keller 		goto out;
3563bf93bf79SJacob Keller 	}
3564bf93bf79SJacob Keller 
3565bf93bf79SJacob Keller 	if (!ice_vc_isvalid_vsi_id(vf, insertion_msg->vport_id)) {
3566bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
3567bf93bf79SJacob Keller 		goto out;
3568bf93bf79SJacob Keller 	}
3569bf93bf79SJacob Keller 
3570bf93bf79SJacob Keller 	vsi = ice_get_vf_vsi(vf);
3571bf93bf79SJacob Keller 	if (!vsi) {
3572bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
3573bf93bf79SJacob Keller 		goto out;
3574bf93bf79SJacob Keller 	}
3575bf93bf79SJacob Keller 
3576bf93bf79SJacob Keller 	insertion_support = &vf->vlan_v2_caps.offloads.insertion_support;
3577bf93bf79SJacob Keller 	if (!ice_vc_valid_vlan_setting_msg(insertion_support, insertion_msg)) {
3578bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
3579bf93bf79SJacob Keller 		goto out;
3580bf93bf79SJacob Keller 	}
3581bf93bf79SJacob Keller 
3582bf93bf79SJacob Keller 	ethertype_setting = insertion_msg->outer_ethertype_setting;
3583bf93bf79SJacob Keller 	if (ethertype_setting &&
3584bf93bf79SJacob Keller 	    ice_vc_ena_vlan_offload(vsi, vsi->outer_vlan_ops.ena_insertion,
3585bf93bf79SJacob Keller 				    ethertype_setting)) {
3586bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
3587bf93bf79SJacob Keller 		goto out;
3588bf93bf79SJacob Keller 	}
3589bf93bf79SJacob Keller 
3590bf93bf79SJacob Keller 	ethertype_setting = insertion_msg->inner_ethertype_setting;
3591bf93bf79SJacob Keller 	if (ethertype_setting &&
3592bf93bf79SJacob Keller 	    ice_vc_ena_vlan_offload(vsi, vsi->inner_vlan_ops.ena_insertion,
3593bf93bf79SJacob Keller 				    ethertype_setting)) {
3594bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
3595bf93bf79SJacob Keller 		goto out;
3596bf93bf79SJacob Keller 	}
3597bf93bf79SJacob Keller 
3598bf93bf79SJacob Keller out:
3599bf93bf79SJacob Keller 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_ENABLE_VLAN_INSERTION_V2,
3600bf93bf79SJacob Keller 				     v_ret, NULL, 0);
3601bf93bf79SJacob Keller }
3602bf93bf79SJacob Keller 
3603bf93bf79SJacob Keller /**
3604bf93bf79SJacob Keller  * ice_vc_dis_vlan_insertion_v2_msg
3605bf93bf79SJacob Keller  * @vf: VF the message was received from
3606bf93bf79SJacob Keller  * @msg: message received from the VF
3607bf93bf79SJacob Keller  *
3608bf93bf79SJacob Keller  * virthcnl handler for VIRTCHNL_OP_DISABLE_VLAN_INSERTION_V2
3609bf93bf79SJacob Keller  */
3610bf93bf79SJacob Keller static int ice_vc_dis_vlan_insertion_v2_msg(struct ice_vf *vf, u8 *msg)
3611bf93bf79SJacob Keller {
3612bf93bf79SJacob Keller 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
3613bf93bf79SJacob Keller 	struct virtchnl_vlan_supported_caps *insertion_support;
3614bf93bf79SJacob Keller 	struct virtchnl_vlan_setting *insertion_msg =
3615bf93bf79SJacob Keller 		(struct virtchnl_vlan_setting *)msg;
3616bf93bf79SJacob Keller 	u32 ethertype_setting;
3617bf93bf79SJacob Keller 	struct ice_vsi *vsi;
3618bf93bf79SJacob Keller 
3619bf93bf79SJacob Keller 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
3620bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
3621bf93bf79SJacob Keller 		goto out;
3622bf93bf79SJacob Keller 	}
3623bf93bf79SJacob Keller 
3624bf93bf79SJacob Keller 	if (!ice_vc_isvalid_vsi_id(vf, insertion_msg->vport_id)) {
3625bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
3626bf93bf79SJacob Keller 		goto out;
3627bf93bf79SJacob Keller 	}
3628bf93bf79SJacob Keller 
3629bf93bf79SJacob Keller 	vsi = ice_get_vf_vsi(vf);
3630bf93bf79SJacob Keller 	if (!vsi) {
3631bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
3632bf93bf79SJacob Keller 		goto out;
3633bf93bf79SJacob Keller 	}
3634bf93bf79SJacob Keller 
3635bf93bf79SJacob Keller 	insertion_support = &vf->vlan_v2_caps.offloads.insertion_support;
3636bf93bf79SJacob Keller 	if (!ice_vc_valid_vlan_setting_msg(insertion_support, insertion_msg)) {
3637bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
3638bf93bf79SJacob Keller 		goto out;
3639bf93bf79SJacob Keller 	}
3640bf93bf79SJacob Keller 
3641bf93bf79SJacob Keller 	ethertype_setting = insertion_msg->outer_ethertype_setting;
3642bf93bf79SJacob Keller 	if (ethertype_setting && vsi->outer_vlan_ops.dis_insertion(vsi)) {
3643bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
3644bf93bf79SJacob Keller 		goto out;
3645bf93bf79SJacob Keller 	}
3646bf93bf79SJacob Keller 
3647bf93bf79SJacob Keller 	ethertype_setting = insertion_msg->inner_ethertype_setting;
3648bf93bf79SJacob Keller 	if (ethertype_setting && vsi->inner_vlan_ops.dis_insertion(vsi)) {
3649bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
3650bf93bf79SJacob Keller 		goto out;
3651bf93bf79SJacob Keller 	}
3652bf93bf79SJacob Keller 
3653bf93bf79SJacob Keller out:
3654bf93bf79SJacob Keller 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_DISABLE_VLAN_INSERTION_V2,
3655bf93bf79SJacob Keller 				     v_ret, NULL, 0);
3656bf93bf79SJacob Keller }
3657bf93bf79SJacob Keller 
3658bf93bf79SJacob Keller static const struct ice_virtchnl_ops ice_virtchnl_dflt_ops = {
3659bf93bf79SJacob Keller 	.get_ver_msg = ice_vc_get_ver_msg,
3660bf93bf79SJacob Keller 	.get_vf_res_msg = ice_vc_get_vf_res_msg,
3661bf93bf79SJacob Keller 	.reset_vf = ice_vc_reset_vf_msg,
3662bf93bf79SJacob Keller 	.add_mac_addr_msg = ice_vc_add_mac_addr_msg,
3663bf93bf79SJacob Keller 	.del_mac_addr_msg = ice_vc_del_mac_addr_msg,
3664bf93bf79SJacob Keller 	.cfg_qs_msg = ice_vc_cfg_qs_msg,
3665bf93bf79SJacob Keller 	.ena_qs_msg = ice_vc_ena_qs_msg,
3666bf93bf79SJacob Keller 	.dis_qs_msg = ice_vc_dis_qs_msg,
3667bf93bf79SJacob Keller 	.request_qs_msg = ice_vc_request_qs_msg,
3668bf93bf79SJacob Keller 	.cfg_irq_map_msg = ice_vc_cfg_irq_map_msg,
3669bf93bf79SJacob Keller 	.config_rss_key = ice_vc_config_rss_key,
3670bf93bf79SJacob Keller 	.config_rss_lut = ice_vc_config_rss_lut,
3671bf93bf79SJacob Keller 	.get_stats_msg = ice_vc_get_stats_msg,
3672bf93bf79SJacob Keller 	.cfg_promiscuous_mode_msg = ice_vc_cfg_promiscuous_mode_msg,
3673bf93bf79SJacob Keller 	.add_vlan_msg = ice_vc_add_vlan_msg,
3674bf93bf79SJacob Keller 	.remove_vlan_msg = ice_vc_remove_vlan_msg,
3675e753df8fSMichal Jaron 	.query_rxdid = ice_vc_query_rxdid,
3676e384cf35SMd Fahad Iqbal Polash 	.get_rss_hena = ice_vc_get_rss_hena,
3677e384cf35SMd Fahad Iqbal Polash 	.set_rss_hena_msg = ice_vc_set_rss_hena,
3678bf93bf79SJacob Keller 	.ena_vlan_stripping = ice_vc_ena_vlan_stripping,
3679bf93bf79SJacob Keller 	.dis_vlan_stripping = ice_vc_dis_vlan_stripping,
3680bf93bf79SJacob Keller 	.handle_rss_cfg_msg = ice_vc_handle_rss_cfg,
3681bf93bf79SJacob Keller 	.add_fdir_fltr_msg = ice_vc_add_fdir_fltr,
3682bf93bf79SJacob Keller 	.del_fdir_fltr_msg = ice_vc_del_fdir_fltr,
3683bf93bf79SJacob Keller 	.get_offload_vlan_v2_caps = ice_vc_get_offload_vlan_v2_caps,
3684bf93bf79SJacob Keller 	.add_vlan_v2_msg = ice_vc_add_vlan_v2_msg,
3685bf93bf79SJacob Keller 	.remove_vlan_v2_msg = ice_vc_remove_vlan_v2_msg,
3686bf93bf79SJacob Keller 	.ena_vlan_stripping_v2_msg = ice_vc_ena_vlan_stripping_v2_msg,
3687bf93bf79SJacob Keller 	.dis_vlan_stripping_v2_msg = ice_vc_dis_vlan_stripping_v2_msg,
3688bf93bf79SJacob Keller 	.ena_vlan_insertion_v2_msg = ice_vc_ena_vlan_insertion_v2_msg,
3689bf93bf79SJacob Keller 	.dis_vlan_insertion_v2_msg = ice_vc_dis_vlan_insertion_v2_msg,
3690bf93bf79SJacob Keller };
3691bf93bf79SJacob Keller 
3692bf93bf79SJacob Keller /**
3693bf93bf79SJacob Keller  * ice_virtchnl_set_dflt_ops - Switch to default virtchnl ops
3694bf93bf79SJacob Keller  * @vf: the VF to switch ops
3695bf93bf79SJacob Keller  */
3696bf93bf79SJacob Keller void ice_virtchnl_set_dflt_ops(struct ice_vf *vf)
3697bf93bf79SJacob Keller {
3698bf93bf79SJacob Keller 	vf->virtchnl_ops = &ice_virtchnl_dflt_ops;
3699bf93bf79SJacob Keller }
3700bf93bf79SJacob Keller 
3701bf93bf79SJacob Keller /**
3702bf93bf79SJacob Keller  * ice_vc_repr_add_mac
3703bf93bf79SJacob Keller  * @vf: pointer to VF
3704bf93bf79SJacob Keller  * @msg: virtchannel message
3705bf93bf79SJacob Keller  *
3706bf93bf79SJacob Keller  * When port representors are created, we do not add MAC rule
3707bf93bf79SJacob Keller  * to firmware, we store it so that PF could report same
3708bf93bf79SJacob Keller  * MAC as VF.
3709bf93bf79SJacob Keller  */
3710bf93bf79SJacob Keller static int ice_vc_repr_add_mac(struct ice_vf *vf, u8 *msg)
3711bf93bf79SJacob Keller {
3712bf93bf79SJacob Keller 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
3713bf93bf79SJacob Keller 	struct virtchnl_ether_addr_list *al =
3714bf93bf79SJacob Keller 	    (struct virtchnl_ether_addr_list *)msg;
3715bf93bf79SJacob Keller 	struct ice_vsi *vsi;
3716bf93bf79SJacob Keller 	struct ice_pf *pf;
3717bf93bf79SJacob Keller 	int i;
3718bf93bf79SJacob Keller 
3719bf93bf79SJacob Keller 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states) ||
3720bf93bf79SJacob Keller 	    !ice_vc_isvalid_vsi_id(vf, al->vsi_id)) {
3721bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
3722bf93bf79SJacob Keller 		goto handle_mac_exit;
3723bf93bf79SJacob Keller 	}
3724bf93bf79SJacob Keller 
3725bf93bf79SJacob Keller 	pf = vf->pf;
3726bf93bf79SJacob Keller 
3727bf93bf79SJacob Keller 	vsi = ice_get_vf_vsi(vf);
3728bf93bf79SJacob Keller 	if (!vsi) {
3729bf93bf79SJacob Keller 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
3730bf93bf79SJacob Keller 		goto handle_mac_exit;
3731bf93bf79SJacob Keller 	}
3732bf93bf79SJacob Keller 
3733bf93bf79SJacob Keller 	for (i = 0; i < al->num_elements; i++) {
3734bf93bf79SJacob Keller 		u8 *mac_addr = al->list[i].addr;
3735bf93bf79SJacob Keller 
3736bf93bf79SJacob Keller 		if (!is_unicast_ether_addr(mac_addr) ||
3737e0645311SJacob Keller 		    ether_addr_equal(mac_addr, vf->hw_lan_addr))
3738bf93bf79SJacob Keller 			continue;
3739bf93bf79SJacob Keller 
3740bf93bf79SJacob Keller 		if (vf->pf_set_mac) {
3741bf93bf79SJacob Keller 			dev_err(ice_pf_to_dev(pf), "VF attempting to override administratively set MAC address\n");
3742bf93bf79SJacob Keller 			v_ret = VIRTCHNL_STATUS_ERR_NOT_SUPPORTED;
3743bf93bf79SJacob Keller 			goto handle_mac_exit;
3744bf93bf79SJacob Keller 		}
3745bf93bf79SJacob Keller 
3746bf93bf79SJacob Keller 		ice_vfhw_mac_add(vf, &al->list[i]);
3747bf93bf79SJacob Keller 		vf->num_mac++;
3748bf93bf79SJacob Keller 		break;
3749bf93bf79SJacob Keller 	}
3750bf93bf79SJacob Keller 
3751bf93bf79SJacob Keller handle_mac_exit:
3752bf93bf79SJacob Keller 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_ADD_ETH_ADDR,
3753bf93bf79SJacob Keller 				     v_ret, NULL, 0);
3754bf93bf79SJacob Keller }
3755bf93bf79SJacob Keller 
3756bf93bf79SJacob Keller /**
3757bf93bf79SJacob Keller  * ice_vc_repr_del_mac - response with success for deleting MAC
3758bf93bf79SJacob Keller  * @vf: pointer to VF
3759bf93bf79SJacob Keller  * @msg: virtchannel message
3760bf93bf79SJacob Keller  *
3761bf93bf79SJacob Keller  * Respond with success to not break normal VF flow.
3762bf93bf79SJacob Keller  * For legacy VF driver try to update cached MAC address.
3763bf93bf79SJacob Keller  */
3764bf93bf79SJacob Keller static int
3765bf93bf79SJacob Keller ice_vc_repr_del_mac(struct ice_vf __always_unused *vf, u8 __always_unused *msg)
3766bf93bf79SJacob Keller {
3767bf93bf79SJacob Keller 	struct virtchnl_ether_addr_list *al =
3768bf93bf79SJacob Keller 		(struct virtchnl_ether_addr_list *)msg;
3769bf93bf79SJacob Keller 
3770bf93bf79SJacob Keller 	ice_update_legacy_cached_mac(vf, &al->list[0]);
3771bf93bf79SJacob Keller 
3772bf93bf79SJacob Keller 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_DEL_ETH_ADDR,
3773bf93bf79SJacob Keller 				     VIRTCHNL_STATUS_SUCCESS, NULL, 0);
3774bf93bf79SJacob Keller }
3775bf93bf79SJacob Keller 
3776bf93bf79SJacob Keller static int
3777bf93bf79SJacob Keller ice_vc_repr_cfg_promiscuous_mode(struct ice_vf *vf, u8 __always_unused *msg)
3778bf93bf79SJacob Keller {
3779bf93bf79SJacob Keller 	dev_dbg(ice_pf_to_dev(vf->pf),
3780bf93bf79SJacob Keller 		"Can't config promiscuous mode in switchdev mode for VF %d\n",
3781bf93bf79SJacob Keller 		vf->vf_id);
3782bf93bf79SJacob Keller 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE,
3783bf93bf79SJacob Keller 				     VIRTCHNL_STATUS_ERR_NOT_SUPPORTED,
3784bf93bf79SJacob Keller 				     NULL, 0);
3785bf93bf79SJacob Keller }
3786bf93bf79SJacob Keller 
3787bf93bf79SJacob Keller static const struct ice_virtchnl_ops ice_virtchnl_repr_ops = {
3788bf93bf79SJacob Keller 	.get_ver_msg = ice_vc_get_ver_msg,
3789bf93bf79SJacob Keller 	.get_vf_res_msg = ice_vc_get_vf_res_msg,
3790bf93bf79SJacob Keller 	.reset_vf = ice_vc_reset_vf_msg,
3791bf93bf79SJacob Keller 	.add_mac_addr_msg = ice_vc_repr_add_mac,
3792bf93bf79SJacob Keller 	.del_mac_addr_msg = ice_vc_repr_del_mac,
3793bf93bf79SJacob Keller 	.cfg_qs_msg = ice_vc_cfg_qs_msg,
3794bf93bf79SJacob Keller 	.ena_qs_msg = ice_vc_ena_qs_msg,
3795bf93bf79SJacob Keller 	.dis_qs_msg = ice_vc_dis_qs_msg,
3796bf93bf79SJacob Keller 	.request_qs_msg = ice_vc_request_qs_msg,
3797bf93bf79SJacob Keller 	.cfg_irq_map_msg = ice_vc_cfg_irq_map_msg,
3798bf93bf79SJacob Keller 	.config_rss_key = ice_vc_config_rss_key,
3799bf93bf79SJacob Keller 	.config_rss_lut = ice_vc_config_rss_lut,
3800bf93bf79SJacob Keller 	.get_stats_msg = ice_vc_get_stats_msg,
3801bf93bf79SJacob Keller 	.cfg_promiscuous_mode_msg = ice_vc_repr_cfg_promiscuous_mode,
3802b33de560SMichal Swiatkowski 	.add_vlan_msg = ice_vc_add_vlan_msg,
3803b33de560SMichal Swiatkowski 	.remove_vlan_msg = ice_vc_remove_vlan_msg,
3804e753df8fSMichal Jaron 	.query_rxdid = ice_vc_query_rxdid,
3805e384cf35SMd Fahad Iqbal Polash 	.get_rss_hena = ice_vc_get_rss_hena,
3806e384cf35SMd Fahad Iqbal Polash 	.set_rss_hena_msg = ice_vc_set_rss_hena,
3807b33de560SMichal Swiatkowski 	.ena_vlan_stripping = ice_vc_ena_vlan_stripping,
3808b33de560SMichal Swiatkowski 	.dis_vlan_stripping = ice_vc_dis_vlan_stripping,
3809bf93bf79SJacob Keller 	.handle_rss_cfg_msg = ice_vc_handle_rss_cfg,
3810bf93bf79SJacob Keller 	.add_fdir_fltr_msg = ice_vc_add_fdir_fltr,
3811bf93bf79SJacob Keller 	.del_fdir_fltr_msg = ice_vc_del_fdir_fltr,
3812bf93bf79SJacob Keller 	.get_offload_vlan_v2_caps = ice_vc_get_offload_vlan_v2_caps,
3813bf93bf79SJacob Keller 	.add_vlan_v2_msg = ice_vc_add_vlan_v2_msg,
3814bf93bf79SJacob Keller 	.remove_vlan_v2_msg = ice_vc_remove_vlan_v2_msg,
3815bf93bf79SJacob Keller 	.ena_vlan_stripping_v2_msg = ice_vc_ena_vlan_stripping_v2_msg,
3816bf93bf79SJacob Keller 	.dis_vlan_stripping_v2_msg = ice_vc_dis_vlan_stripping_v2_msg,
3817bf93bf79SJacob Keller 	.ena_vlan_insertion_v2_msg = ice_vc_ena_vlan_insertion_v2_msg,
3818bf93bf79SJacob Keller 	.dis_vlan_insertion_v2_msg = ice_vc_dis_vlan_insertion_v2_msg,
3819bf93bf79SJacob Keller };
3820bf93bf79SJacob Keller 
3821bf93bf79SJacob Keller /**
3822bf93bf79SJacob Keller  * ice_virtchnl_set_repr_ops - Switch to representor virtchnl ops
3823bf93bf79SJacob Keller  * @vf: the VF to switch ops
3824bf93bf79SJacob Keller  */
3825bf93bf79SJacob Keller void ice_virtchnl_set_repr_ops(struct ice_vf *vf)
3826bf93bf79SJacob Keller {
3827bf93bf79SJacob Keller 	vf->virtchnl_ops = &ice_virtchnl_repr_ops;
3828bf93bf79SJacob Keller }
3829bf93bf79SJacob Keller 
3830bf93bf79SJacob Keller /**
3831be96815cSJacob Keller  * ice_is_malicious_vf - check if this vf might be overflowing mailbox
3832be96815cSJacob Keller  * @vf: the VF to check
3833c414463aSJacob Keller  * @mbxdata: data about the state of the mailbox
3834be96815cSJacob Keller  *
3835be96815cSJacob Keller  * Detect if a given VF might be malicious and attempting to overflow the PF
3836be96815cSJacob Keller  * mailbox. If so, log a warning message and ignore this event.
3837c414463aSJacob Keller  */
3838be96815cSJacob Keller static bool
3839be96815cSJacob Keller ice_is_malicious_vf(struct ice_vf *vf, struct ice_mbx_data *mbxdata)
3840c414463aSJacob Keller {
3841c414463aSJacob Keller 	bool report_malvf = false;
3842be96815cSJacob Keller 	struct device *dev;
3843be96815cSJacob Keller 	struct ice_pf *pf;
3844c414463aSJacob Keller 	int status;
3845c414463aSJacob Keller 
3846be96815cSJacob Keller 	pf = vf->pf;
3847be96815cSJacob Keller 	dev = ice_pf_to_dev(pf);
3848c414463aSJacob Keller 
3849c414463aSJacob Keller 	if (test_bit(ICE_VF_STATE_DIS, vf->vf_states))
3850be96815cSJacob Keller 		return vf->mbx_info.malicious;
3851c414463aSJacob Keller 
3852c414463aSJacob Keller 	/* check to see if we have a newly malicious VF */
3853c414463aSJacob Keller 	status = ice_mbx_vf_state_handler(&pf->hw, mbxdata, &vf->mbx_info,
3854c414463aSJacob Keller 					  &report_malvf);
3855c414463aSJacob Keller 	if (status)
3856c414463aSJacob Keller 		dev_warn_ratelimited(dev, "Unable to check status of mailbox overflow for VF %u MAC %pM, status %d\n",
3857c414463aSJacob Keller 				     vf->vf_id, vf->dev_lan_addr, status);
3858c414463aSJacob Keller 
3859c414463aSJacob Keller 	if (report_malvf) {
3860c414463aSJacob Keller 		struct ice_vsi *pf_vsi = ice_get_main_vsi(pf);
3861c414463aSJacob Keller 		u8 zero_addr[ETH_ALEN] = {};
3862c414463aSJacob Keller 
3863c414463aSJacob Keller 		dev_warn(dev, "VF MAC %pM on PF MAC %pM is generating asynchronous messages and may be overflowing the PF message queue. Please see the Adapter User Guide for more information\n",
3864c414463aSJacob Keller 			 vf->dev_lan_addr,
3865c414463aSJacob Keller 			 pf_vsi ? pf_vsi->netdev->dev_addr : zero_addr);
3866c414463aSJacob Keller 	}
3867c414463aSJacob Keller 
3868c414463aSJacob Keller 	return vf->mbx_info.malicious;
3869c414463aSJacob Keller }
3870c414463aSJacob Keller 
3871c414463aSJacob Keller /**
3872bf93bf79SJacob Keller  * ice_vc_process_vf_msg - Process request from VF
3873bf93bf79SJacob Keller  * @pf: pointer to the PF structure
3874bf93bf79SJacob Keller  * @event: pointer to the AQ event
3875be96815cSJacob Keller  * @mbxdata: information used to detect VF attempting mailbox overflow
3876bf93bf79SJacob Keller  *
3877bf93bf79SJacob Keller  * called from the common asq/arq handler to
3878bf93bf79SJacob Keller  * process request from VF
3879bf93bf79SJacob Keller  */
3880be96815cSJacob Keller void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event,
3881be96815cSJacob Keller 			   struct ice_mbx_data *mbxdata)
3882bf93bf79SJacob Keller {
3883bf93bf79SJacob Keller 	u32 v_opcode = le32_to_cpu(event->desc.cookie_high);
3884bf93bf79SJacob Keller 	s16 vf_id = le16_to_cpu(event->desc.retval);
3885bf93bf79SJacob Keller 	const struct ice_virtchnl_ops *ops;
3886bf93bf79SJacob Keller 	u16 msglen = event->msg_len;
3887bf93bf79SJacob Keller 	u8 *msg = event->msg_buf;
3888bf93bf79SJacob Keller 	struct ice_vf *vf = NULL;
3889bf93bf79SJacob Keller 	struct device *dev;
3890bf93bf79SJacob Keller 	int err = 0;
3891bf93bf79SJacob Keller 
3892bf93bf79SJacob Keller 	dev = ice_pf_to_dev(pf);
3893bf93bf79SJacob Keller 
3894bf93bf79SJacob Keller 	vf = ice_get_vf_by_id(pf, vf_id);
3895bf93bf79SJacob Keller 	if (!vf) {
3896bf93bf79SJacob Keller 		dev_err(dev, "Unable to locate VF for message from VF ID %d, opcode %d, len %d\n",
3897bf93bf79SJacob Keller 			vf_id, v_opcode, msglen);
3898bf93bf79SJacob Keller 		return;
3899bf93bf79SJacob Keller 	}
3900bf93bf79SJacob Keller 
390177d64d28SIvan Vecera 	mutex_lock(&vf->cfg_lock);
390277d64d28SIvan Vecera 
3903be96815cSJacob Keller 	/* Check if the VF is trying to overflow the mailbox */
3904be96815cSJacob Keller 	if (ice_is_malicious_vf(vf, mbxdata))
3905be96815cSJacob Keller 		goto finish;
3906be96815cSJacob Keller 
3907bf93bf79SJacob Keller 	/* Check if VF is disabled. */
3908bf93bf79SJacob Keller 	if (test_bit(ICE_VF_STATE_DIS, vf->vf_states)) {
3909bf93bf79SJacob Keller 		err = -EPERM;
3910bf93bf79SJacob Keller 		goto error_handler;
3911bf93bf79SJacob Keller 	}
3912bf93bf79SJacob Keller 
3913bf93bf79SJacob Keller 	ops = vf->virtchnl_ops;
3914bf93bf79SJacob Keller 
3915bf93bf79SJacob Keller 	/* Perform basic checks on the msg */
3916bf93bf79SJacob Keller 	err = virtchnl_vc_validate_vf_msg(&vf->vf_ver, v_opcode, msg, msglen);
3917bf93bf79SJacob Keller 	if (err) {
3918bf93bf79SJacob Keller 		if (err == VIRTCHNL_STATUS_ERR_PARAM)
3919bf93bf79SJacob Keller 			err = -EPERM;
3920bf93bf79SJacob Keller 		else
3921bf93bf79SJacob Keller 			err = -EINVAL;
3922bf93bf79SJacob Keller 	}
3923bf93bf79SJacob Keller 
3924bf93bf79SJacob Keller error_handler:
3925bf93bf79SJacob Keller 	if (err) {
3926bf93bf79SJacob Keller 		ice_vc_send_msg_to_vf(vf, v_opcode, VIRTCHNL_STATUS_ERR_PARAM,
3927bf93bf79SJacob Keller 				      NULL, 0);
3928bf93bf79SJacob Keller 		dev_err(dev, "Invalid message from VF %d, opcode %d, len %d, error %d\n",
3929bf93bf79SJacob Keller 			vf_id, v_opcode, msglen, err);
393077d64d28SIvan Vecera 		goto finish;
3931bf93bf79SJacob Keller 	}
3932bf93bf79SJacob Keller 
3933aaf461afSIvan Vecera 	if (!ice_vc_is_opcode_allowed(vf, v_opcode)) {
3934aaf461afSIvan Vecera 		ice_vc_send_msg_to_vf(vf, v_opcode,
3935aaf461afSIvan Vecera 				      VIRTCHNL_STATUS_ERR_NOT_SUPPORTED, NULL,
3936aaf461afSIvan Vecera 				      0);
393777d64d28SIvan Vecera 		goto finish;
3938bf93bf79SJacob Keller 	}
3939bf93bf79SJacob Keller 
3940bf93bf79SJacob Keller 	switch (v_opcode) {
3941bf93bf79SJacob Keller 	case VIRTCHNL_OP_VERSION:
3942bf93bf79SJacob Keller 		err = ops->get_ver_msg(vf, msg);
3943bf93bf79SJacob Keller 		break;
3944bf93bf79SJacob Keller 	case VIRTCHNL_OP_GET_VF_RESOURCES:
3945bf93bf79SJacob Keller 		err = ops->get_vf_res_msg(vf, msg);
3946bf93bf79SJacob Keller 		if (ice_vf_init_vlan_stripping(vf))
3947bf93bf79SJacob Keller 			dev_dbg(dev, "Failed to initialize VLAN stripping for VF %d\n",
3948bf93bf79SJacob Keller 				vf->vf_id);
3949bf93bf79SJacob Keller 		ice_vc_notify_vf_link_state(vf);
3950bf93bf79SJacob Keller 		break;
3951bf93bf79SJacob Keller 	case VIRTCHNL_OP_RESET_VF:
39527255355aSDawid Wesierski 		clear_bit(ICE_VF_STATE_ACTIVE, vf->vf_states);
3953bf93bf79SJacob Keller 		ops->reset_vf(vf);
3954bf93bf79SJacob Keller 		break;
3955bf93bf79SJacob Keller 	case VIRTCHNL_OP_ADD_ETH_ADDR:
3956bf93bf79SJacob Keller 		err = ops->add_mac_addr_msg(vf, msg);
3957bf93bf79SJacob Keller 		break;
3958bf93bf79SJacob Keller 	case VIRTCHNL_OP_DEL_ETH_ADDR:
3959bf93bf79SJacob Keller 		err = ops->del_mac_addr_msg(vf, msg);
3960bf93bf79SJacob Keller 		break;
3961bf93bf79SJacob Keller 	case VIRTCHNL_OP_CONFIG_VSI_QUEUES:
3962bf93bf79SJacob Keller 		err = ops->cfg_qs_msg(vf, msg);
3963bf93bf79SJacob Keller 		break;
3964bf93bf79SJacob Keller 	case VIRTCHNL_OP_ENABLE_QUEUES:
3965bf93bf79SJacob Keller 		err = ops->ena_qs_msg(vf, msg);
3966bf93bf79SJacob Keller 		ice_vc_notify_vf_link_state(vf);
3967bf93bf79SJacob Keller 		break;
3968bf93bf79SJacob Keller 	case VIRTCHNL_OP_DISABLE_QUEUES:
3969bf93bf79SJacob Keller 		err = ops->dis_qs_msg(vf, msg);
3970bf93bf79SJacob Keller 		break;
3971bf93bf79SJacob Keller 	case VIRTCHNL_OP_REQUEST_QUEUES:
3972bf93bf79SJacob Keller 		err = ops->request_qs_msg(vf, msg);
3973bf93bf79SJacob Keller 		break;
3974bf93bf79SJacob Keller 	case VIRTCHNL_OP_CONFIG_IRQ_MAP:
3975bf93bf79SJacob Keller 		err = ops->cfg_irq_map_msg(vf, msg);
3976bf93bf79SJacob Keller 		break;
3977bf93bf79SJacob Keller 	case VIRTCHNL_OP_CONFIG_RSS_KEY:
3978bf93bf79SJacob Keller 		err = ops->config_rss_key(vf, msg);
3979bf93bf79SJacob Keller 		break;
3980bf93bf79SJacob Keller 	case VIRTCHNL_OP_CONFIG_RSS_LUT:
3981bf93bf79SJacob Keller 		err = ops->config_rss_lut(vf, msg);
3982bf93bf79SJacob Keller 		break;
3983bf93bf79SJacob Keller 	case VIRTCHNL_OP_GET_STATS:
3984bf93bf79SJacob Keller 		err = ops->get_stats_msg(vf, msg);
3985bf93bf79SJacob Keller 		break;
3986bf93bf79SJacob Keller 	case VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE:
3987bf93bf79SJacob Keller 		err = ops->cfg_promiscuous_mode_msg(vf, msg);
3988bf93bf79SJacob Keller 		break;
3989bf93bf79SJacob Keller 	case VIRTCHNL_OP_ADD_VLAN:
3990bf93bf79SJacob Keller 		err = ops->add_vlan_msg(vf, msg);
3991bf93bf79SJacob Keller 		break;
3992bf93bf79SJacob Keller 	case VIRTCHNL_OP_DEL_VLAN:
3993bf93bf79SJacob Keller 		err = ops->remove_vlan_msg(vf, msg);
3994bf93bf79SJacob Keller 		break;
3995e753df8fSMichal Jaron 	case VIRTCHNL_OP_GET_SUPPORTED_RXDIDS:
3996e753df8fSMichal Jaron 		err = ops->query_rxdid(vf);
3997e753df8fSMichal Jaron 		break;
3998e384cf35SMd Fahad Iqbal Polash 	case VIRTCHNL_OP_GET_RSS_HENA_CAPS:
3999e384cf35SMd Fahad Iqbal Polash 		err = ops->get_rss_hena(vf);
4000e384cf35SMd Fahad Iqbal Polash 		break;
4001e384cf35SMd Fahad Iqbal Polash 	case VIRTCHNL_OP_SET_RSS_HENA:
4002e384cf35SMd Fahad Iqbal Polash 		err = ops->set_rss_hena_msg(vf, msg);
4003e384cf35SMd Fahad Iqbal Polash 		break;
4004bf93bf79SJacob Keller 	case VIRTCHNL_OP_ENABLE_VLAN_STRIPPING:
4005bf93bf79SJacob Keller 		err = ops->ena_vlan_stripping(vf);
4006bf93bf79SJacob Keller 		break;
4007bf93bf79SJacob Keller 	case VIRTCHNL_OP_DISABLE_VLAN_STRIPPING:
4008bf93bf79SJacob Keller 		err = ops->dis_vlan_stripping(vf);
4009bf93bf79SJacob Keller 		break;
4010bf93bf79SJacob Keller 	case VIRTCHNL_OP_ADD_FDIR_FILTER:
4011bf93bf79SJacob Keller 		err = ops->add_fdir_fltr_msg(vf, msg);
4012bf93bf79SJacob Keller 		break;
4013bf93bf79SJacob Keller 	case VIRTCHNL_OP_DEL_FDIR_FILTER:
4014bf93bf79SJacob Keller 		err = ops->del_fdir_fltr_msg(vf, msg);
4015bf93bf79SJacob Keller 		break;
4016bf93bf79SJacob Keller 	case VIRTCHNL_OP_ADD_RSS_CFG:
4017bf93bf79SJacob Keller 		err = ops->handle_rss_cfg_msg(vf, msg, true);
4018bf93bf79SJacob Keller 		break;
4019bf93bf79SJacob Keller 	case VIRTCHNL_OP_DEL_RSS_CFG:
4020bf93bf79SJacob Keller 		err = ops->handle_rss_cfg_msg(vf, msg, false);
4021bf93bf79SJacob Keller 		break;
4022bf93bf79SJacob Keller 	case VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS:
4023bf93bf79SJacob Keller 		err = ops->get_offload_vlan_v2_caps(vf);
4024bf93bf79SJacob Keller 		break;
4025bf93bf79SJacob Keller 	case VIRTCHNL_OP_ADD_VLAN_V2:
4026bf93bf79SJacob Keller 		err = ops->add_vlan_v2_msg(vf, msg);
4027bf93bf79SJacob Keller 		break;
4028bf93bf79SJacob Keller 	case VIRTCHNL_OP_DEL_VLAN_V2:
4029bf93bf79SJacob Keller 		err = ops->remove_vlan_v2_msg(vf, msg);
4030bf93bf79SJacob Keller 		break;
4031bf93bf79SJacob Keller 	case VIRTCHNL_OP_ENABLE_VLAN_STRIPPING_V2:
4032bf93bf79SJacob Keller 		err = ops->ena_vlan_stripping_v2_msg(vf, msg);
4033bf93bf79SJacob Keller 		break;
4034bf93bf79SJacob Keller 	case VIRTCHNL_OP_DISABLE_VLAN_STRIPPING_V2:
4035bf93bf79SJacob Keller 		err = ops->dis_vlan_stripping_v2_msg(vf, msg);
4036bf93bf79SJacob Keller 		break;
4037bf93bf79SJacob Keller 	case VIRTCHNL_OP_ENABLE_VLAN_INSERTION_V2:
4038bf93bf79SJacob Keller 		err = ops->ena_vlan_insertion_v2_msg(vf, msg);
4039bf93bf79SJacob Keller 		break;
4040bf93bf79SJacob Keller 	case VIRTCHNL_OP_DISABLE_VLAN_INSERTION_V2:
4041bf93bf79SJacob Keller 		err = ops->dis_vlan_insertion_v2_msg(vf, msg);
4042bf93bf79SJacob Keller 		break;
4043bf93bf79SJacob Keller 	case VIRTCHNL_OP_UNKNOWN:
4044bf93bf79SJacob Keller 	default:
4045bf93bf79SJacob Keller 		dev_err(dev, "Unsupported opcode %d from VF %d\n", v_opcode,
4046bf93bf79SJacob Keller 			vf_id);
4047bf93bf79SJacob Keller 		err = ice_vc_send_msg_to_vf(vf, v_opcode,
4048bf93bf79SJacob Keller 					    VIRTCHNL_STATUS_ERR_NOT_SUPPORTED,
4049bf93bf79SJacob Keller 					    NULL, 0);
4050bf93bf79SJacob Keller 		break;
4051bf93bf79SJacob Keller 	}
4052bf93bf79SJacob Keller 	if (err) {
4053bf93bf79SJacob Keller 		/* Helper function cares less about error return values here
4054bf93bf79SJacob Keller 		 * as it is busy with pending work.
4055bf93bf79SJacob Keller 		 */
4056bf93bf79SJacob Keller 		dev_info(dev, "PF failed to honor VF %d, opcode %d, error %d\n",
4057bf93bf79SJacob Keller 			 vf_id, v_opcode, err);
4058bf93bf79SJacob Keller 	}
4059bf93bf79SJacob Keller 
406077d64d28SIvan Vecera finish:
4061bf93bf79SJacob Keller 	mutex_unlock(&vf->cfg_lock);
4062bf93bf79SJacob Keller 	ice_put_vf(vf);
4063bf93bf79SJacob Keller }
4064