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