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