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