Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : *
3 : : * Copyright(c) 2019-2021 Xilinx, Inc.
4 : : */
5 : :
6 : : #include "efx.h"
7 : : #include "efx_impl.h"
8 : :
9 : :
10 : : #if EFSYS_OPT_MAE
11 : :
12 : : static __checkReturn efx_rc_t
13 : 0 : efx_mae_get_capabilities(
14 : : __in efx_nic_t *enp)
15 : : {
16 : : efx_mcdi_req_t req;
17 : 0 : EFX_MCDI_DECLARE_BUF(payload,
18 : : MC_CMD_MAE_GET_CAPS_IN_LEN,
19 : : MC_CMD_MAE_GET_CAPS_V2_OUT_LEN);
20 : 0 : struct efx_mae_s *maep = enp->en_maep;
21 : : efx_rc_t rc;
22 : :
23 : 0 : req.emr_cmd = MC_CMD_MAE_GET_CAPS;
24 : 0 : req.emr_in_buf = payload;
25 : 0 : req.emr_in_length = MC_CMD_MAE_GET_CAPS_IN_LEN;
26 : 0 : req.emr_out_buf = payload;
27 : 0 : req.emr_out_length = MC_CMD_MAE_GET_CAPS_V2_OUT_LEN;
28 : :
29 : 0 : efx_mcdi_execute(enp, &req);
30 : :
31 [ # # ]: 0 : if (req.emr_rc != 0) {
32 : : rc = req.emr_rc;
33 : 0 : goto fail1;
34 : : }
35 : :
36 [ # # ]: 0 : if (req.emr_out_length_used < MC_CMD_MAE_GET_CAPS_OUT_LEN) {
37 : : rc = EMSGSIZE;
38 : 0 : goto fail2;
39 : : }
40 : :
41 : 0 : maep->em_max_n_outer_prios =
42 : 0 : MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_OUTER_PRIOS);
43 : :
44 : 0 : maep->em_max_n_action_prios =
45 : 0 : MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_ACTION_PRIOS);
46 : :
47 : 0 : maep->em_encap_types_supported = 0;
48 : :
49 [ # # ]: 0 : if (MCDI_OUT_DWORD_FIELD(req, MAE_GET_CAPS_OUT_ENCAP_TYPES_SUPPORTED,
50 : : MAE_GET_CAPS_OUT_ENCAP_TYPE_VXLAN) != 0) {
51 : 0 : maep->em_encap_types_supported |=
52 : : (1U << EFX_TUNNEL_PROTOCOL_VXLAN);
53 : : }
54 : :
55 : 0 : if (MCDI_OUT_DWORD_FIELD(req, MAE_GET_CAPS_OUT_ENCAP_TYPES_SUPPORTED,
56 [ # # ]: 0 : MAE_GET_CAPS_OUT_ENCAP_TYPE_GENEVE) != 0) {
57 : 0 : maep->em_encap_types_supported |=
58 : : (1U << EFX_TUNNEL_PROTOCOL_GENEVE);
59 : : }
60 : :
61 : 0 : if (MCDI_OUT_DWORD_FIELD(req, MAE_GET_CAPS_OUT_ENCAP_TYPES_SUPPORTED,
62 [ # # ]: 0 : MAE_GET_CAPS_OUT_ENCAP_TYPE_NVGRE) != 0) {
63 : 0 : maep->em_encap_types_supported |=
64 : : (1U << EFX_TUNNEL_PROTOCOL_NVGRE);
65 : : }
66 : :
67 : 0 : maep->em_max_nfields =
68 : 0 : MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_MATCH_FIELD_COUNT);
69 : :
70 : 0 : maep->em_max_n_action_counters =
71 : 0 : MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_AR_COUNTERS);
72 : :
73 [ # # ]: 0 : if (req.emr_out_length_used >= MC_CMD_MAE_GET_CAPS_V2_OUT_LEN) {
74 : 0 : maep->em_max_n_conntrack_counters =
75 : 0 : MCDI_OUT_DWORD(req, MAE_GET_CAPS_V2_OUT_CT_COUNTERS);
76 : : } else {
77 : 0 : maep->em_max_n_conntrack_counters = 0;
78 : : }
79 : :
80 : : return (0);
81 : :
82 : : fail2:
83 : : EFSYS_PROBE(fail2);
84 : : fail1:
85 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
86 : : return (rc);
87 : : }
88 : :
89 : : static __checkReturn efx_rc_t
90 : 0 : efx_mae_get_outer_rule_caps(
91 : : __in efx_nic_t *enp,
92 : : __in unsigned int field_ncaps,
93 : : __out_ecount(field_ncaps) efx_mae_field_cap_t *field_caps)
94 : : {
95 : : efx_mcdi_req_t req;
96 : 0 : EFX_MCDI_DECLARE_BUF(payload,
97 : : MC_CMD_MAE_GET_OR_CAPS_IN_LEN,
98 : : MC_CMD_MAE_GET_OR_CAPS_OUT_LENMAX_MCDI2);
99 : : unsigned int mcdi_field_ncaps;
100 : : unsigned int i;
101 : : efx_rc_t rc;
102 : :
103 [ # # ]: 0 : if (MC_CMD_MAE_GET_OR_CAPS_OUT_LEN(field_ncaps) >
104 : : MC_CMD_MAE_GET_OR_CAPS_OUT_LENMAX_MCDI2) {
105 : : rc = EINVAL;
106 : 0 : goto fail1;
107 : : }
108 : :
109 : 0 : req.emr_cmd = MC_CMD_MAE_GET_OR_CAPS;
110 : 0 : req.emr_in_buf = payload;
111 : 0 : req.emr_in_length = MC_CMD_MAE_GET_OR_CAPS_IN_LEN;
112 : 0 : req.emr_out_buf = payload;
113 : 0 : req.emr_out_length = MC_CMD_MAE_GET_OR_CAPS_OUT_LEN(field_ncaps);
114 : :
115 : 0 : efx_mcdi_execute(enp, &req);
116 : :
117 [ # # ]: 0 : if (req.emr_rc != 0) {
118 : : rc = req.emr_rc;
119 : 0 : goto fail2;
120 : : }
121 : :
122 [ # # ]: 0 : if (req.emr_out_length_used < MC_CMD_MAE_GET_OR_CAPS_OUT_LENMIN) {
123 : : rc = EMSGSIZE;
124 : 0 : goto fail3;
125 : : }
126 : :
127 : 0 : mcdi_field_ncaps = MCDI_OUT_DWORD(req, MAE_GET_OR_CAPS_OUT_COUNT);
128 : :
129 : 0 : if (req.emr_out_length_used <
130 [ # # ]: 0 : MC_CMD_MAE_GET_OR_CAPS_OUT_LEN(mcdi_field_ncaps)) {
131 : : rc = EMSGSIZE;
132 : 0 : goto fail4;
133 : : }
134 : :
135 [ # # ]: 0 : if (mcdi_field_ncaps > field_ncaps) {
136 : : rc = EMSGSIZE;
137 : 0 : goto fail5;
138 : : }
139 : :
140 [ # # ]: 0 : for (i = 0; i < mcdi_field_ncaps; ++i) {
141 : : uint32_t match_flag;
142 : : uint32_t mask_flag;
143 : :
144 : 0 : field_caps[i].emfc_support = MCDI_OUT_INDEXED_DWORD_FIELD(req,
145 : : MAE_GET_OR_CAPS_OUT_FIELD_FLAGS, i,
146 : : MAE_FIELD_FLAGS_SUPPORT_STATUS);
147 : :
148 : 0 : match_flag = MCDI_OUT_INDEXED_DWORD_FIELD(req,
149 : : MAE_GET_OR_CAPS_OUT_FIELD_FLAGS, i,
150 : : MAE_FIELD_FLAGS_MATCH_AFFECTS_CLASS);
151 : :
152 : 0 : field_caps[i].emfc_match_affects_class =
153 : 0 : (match_flag != 0) ? B_TRUE : B_FALSE;
154 : :
155 : 0 : mask_flag = MCDI_OUT_INDEXED_DWORD_FIELD(req,
156 : : MAE_GET_OR_CAPS_OUT_FIELD_FLAGS, i,
157 : : MAE_FIELD_FLAGS_MASK_AFFECTS_CLASS);
158 : :
159 : 0 : field_caps[i].emfc_mask_affects_class =
160 : 0 : (mask_flag != 0) ? B_TRUE : B_FALSE;
161 : : }
162 : :
163 : : return (0);
164 : :
165 : : fail5:
166 : : EFSYS_PROBE(fail5);
167 : : fail4:
168 : : EFSYS_PROBE(fail4);
169 : : fail3:
170 : : EFSYS_PROBE(fail3);
171 : : fail2:
172 : : EFSYS_PROBE(fail2);
173 : : fail1:
174 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
175 : : return (rc);
176 : : }
177 : :
178 : : static __checkReturn efx_rc_t
179 : 0 : efx_mae_get_action_rule_caps(
180 : : __in efx_nic_t *enp,
181 : : __in unsigned int field_ncaps,
182 : : __out_ecount(field_ncaps) efx_mae_field_cap_t *field_caps)
183 : : {
184 : : efx_mcdi_req_t req;
185 : 0 : EFX_MCDI_DECLARE_BUF(payload,
186 : : MC_CMD_MAE_GET_AR_CAPS_IN_LEN,
187 : : MC_CMD_MAE_GET_AR_CAPS_OUT_LENMAX_MCDI2);
188 : : unsigned int mcdi_field_ncaps;
189 : : unsigned int i;
190 : : efx_rc_t rc;
191 : :
192 [ # # ]: 0 : if (MC_CMD_MAE_GET_AR_CAPS_OUT_LEN(field_ncaps) >
193 : : MC_CMD_MAE_GET_AR_CAPS_OUT_LENMAX_MCDI2) {
194 : : rc = EINVAL;
195 : 0 : goto fail1;
196 : : }
197 : :
198 : 0 : req.emr_cmd = MC_CMD_MAE_GET_AR_CAPS;
199 : 0 : req.emr_in_buf = payload;
200 : 0 : req.emr_in_length = MC_CMD_MAE_GET_AR_CAPS_IN_LEN;
201 : 0 : req.emr_out_buf = payload;
202 : 0 : req.emr_out_length = MC_CMD_MAE_GET_AR_CAPS_OUT_LEN(field_ncaps);
203 : :
204 : 0 : efx_mcdi_execute(enp, &req);
205 : :
206 [ # # ]: 0 : if (req.emr_rc != 0) {
207 : : rc = req.emr_rc;
208 : 0 : goto fail2;
209 : : }
210 : :
211 [ # # ]: 0 : if (req.emr_out_length_used < MC_CMD_MAE_GET_AR_CAPS_OUT_LENMIN) {
212 : : rc = EMSGSIZE;
213 : 0 : goto fail3;
214 : : }
215 : :
216 : 0 : mcdi_field_ncaps = MCDI_OUT_DWORD(req, MAE_GET_AR_CAPS_OUT_COUNT);
217 : :
218 : 0 : if (req.emr_out_length_used <
219 [ # # ]: 0 : MC_CMD_MAE_GET_AR_CAPS_OUT_LEN(mcdi_field_ncaps)) {
220 : : rc = EMSGSIZE;
221 : 0 : goto fail4;
222 : : }
223 : :
224 [ # # ]: 0 : if (mcdi_field_ncaps > field_ncaps) {
225 : : rc = EMSGSIZE;
226 : 0 : goto fail5;
227 : : }
228 : :
229 [ # # ]: 0 : for (i = 0; i < mcdi_field_ncaps; ++i) {
230 : : uint32_t match_flag;
231 : : uint32_t mask_flag;
232 : :
233 : 0 : field_caps[i].emfc_support = MCDI_OUT_INDEXED_DWORD_FIELD(req,
234 : : MAE_GET_AR_CAPS_OUT_FIELD_FLAGS, i,
235 : : MAE_FIELD_FLAGS_SUPPORT_STATUS);
236 : :
237 : 0 : match_flag = MCDI_OUT_INDEXED_DWORD_FIELD(req,
238 : : MAE_GET_AR_CAPS_OUT_FIELD_FLAGS, i,
239 : : MAE_FIELD_FLAGS_MATCH_AFFECTS_CLASS);
240 : :
241 : 0 : field_caps[i].emfc_match_affects_class =
242 : 0 : (match_flag != 0) ? B_TRUE : B_FALSE;
243 : :
244 : 0 : mask_flag = MCDI_OUT_INDEXED_DWORD_FIELD(req,
245 : : MAE_GET_AR_CAPS_OUT_FIELD_FLAGS, i,
246 : : MAE_FIELD_FLAGS_MASK_AFFECTS_CLASS);
247 : :
248 : 0 : field_caps[i].emfc_mask_affects_class =
249 : 0 : (mask_flag != 0) ? B_TRUE : B_FALSE;
250 : : }
251 : :
252 : : return (0);
253 : :
254 : : fail5:
255 : : EFSYS_PROBE(fail5);
256 : : fail4:
257 : : EFSYS_PROBE(fail4);
258 : : fail3:
259 : : EFSYS_PROBE(fail3);
260 : : fail2:
261 : : EFSYS_PROBE(fail2);
262 : : fail1:
263 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
264 : : return (rc);
265 : : }
266 : :
267 : : __checkReturn efx_rc_t
268 : 0 : efx_mae_init(
269 : : __in efx_nic_t *enp)
270 : : {
271 : 0 : const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
272 : : efx_mae_field_cap_t *or_fcaps;
273 : : size_t or_fcaps_size;
274 : : efx_mae_field_cap_t *ar_fcaps;
275 : : size_t ar_fcaps_size;
276 : : efx_mae_t *maep;
277 : : efx_rc_t rc;
278 : :
279 [ # # ]: 0 : if (encp->enc_mae_supported == B_FALSE) {
280 : : rc = ENOTSUP;
281 : 0 : goto fail1;
282 : : }
283 : :
284 : 0 : EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (*maep), maep);
285 [ # # ]: 0 : if (maep == NULL) {
286 : : rc = ENOMEM;
287 : 0 : goto fail2;
288 : : }
289 : :
290 : 0 : enp->en_maep = maep;
291 : :
292 : 0 : rc = efx_mae_get_capabilities(enp);
293 [ # # ]: 0 : if (rc != 0)
294 : 0 : goto fail3;
295 : :
296 : 0 : or_fcaps_size = maep->em_max_nfields * sizeof (*or_fcaps);
297 : 0 : EFSYS_KMEM_ALLOC(enp->en_esip, or_fcaps_size, or_fcaps);
298 [ # # ]: 0 : if (or_fcaps == NULL) {
299 : : rc = ENOMEM;
300 : 0 : goto fail4;
301 : : }
302 : :
303 : 0 : maep->em_outer_rule_field_caps_size = or_fcaps_size;
304 : 0 : maep->em_outer_rule_field_caps = or_fcaps;
305 : :
306 : 0 : rc = efx_mae_get_outer_rule_caps(enp, maep->em_max_nfields, or_fcaps);
307 [ # # ]: 0 : if (rc != 0)
308 : 0 : goto fail5;
309 : :
310 : 0 : ar_fcaps_size = maep->em_max_nfields * sizeof (*ar_fcaps);
311 : 0 : EFSYS_KMEM_ALLOC(enp->en_esip, ar_fcaps_size, ar_fcaps);
312 [ # # ]: 0 : if (ar_fcaps == NULL) {
313 : : rc = ENOMEM;
314 : 0 : goto fail6;
315 : : }
316 : :
317 : 0 : maep->em_action_rule_field_caps_size = ar_fcaps_size;
318 : 0 : maep->em_action_rule_field_caps = ar_fcaps;
319 : :
320 : 0 : rc = efx_mae_get_action_rule_caps(enp, maep->em_max_nfields, ar_fcaps);
321 [ # # ]: 0 : if (rc != 0)
322 : 0 : goto fail7;
323 : :
324 : : return (0);
325 : :
326 : : fail7:
327 : : EFSYS_PROBE(fail5);
328 : 0 : EFSYS_KMEM_FREE(enp->en_esip, ar_fcaps_size, ar_fcaps);
329 : 0 : fail6:
330 : : EFSYS_PROBE(fail4);
331 : 0 : fail5:
332 : : EFSYS_PROBE(fail5);
333 : 0 : EFSYS_KMEM_FREE(enp->en_esip, or_fcaps_size, or_fcaps);
334 : 0 : fail4:
335 : : EFSYS_PROBE(fail4);
336 : 0 : fail3:
337 : : EFSYS_PROBE(fail3);
338 : 0 : EFSYS_KMEM_FREE(enp->en_esip, sizeof (struct efx_mae_s), enp->en_maep);
339 : 0 : enp->en_maep = NULL;
340 : : fail2:
341 : : EFSYS_PROBE(fail2);
342 : : fail1:
343 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
344 : : return (rc);
345 : : }
346 : :
347 : : void
348 : 0 : efx_mae_fini(
349 : : __in efx_nic_t *enp)
350 : : {
351 : 0 : const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
352 : 0 : efx_mae_t *maep = enp->en_maep;
353 : :
354 [ # # ]: 0 : if (encp->enc_mae_supported == B_FALSE)
355 : : return;
356 : :
357 : 0 : EFSYS_KMEM_FREE(enp->en_esip, maep->em_action_rule_field_caps_size,
358 : : maep->em_action_rule_field_caps);
359 : 0 : EFSYS_KMEM_FREE(enp->en_esip, maep->em_outer_rule_field_caps_size,
360 : : maep->em_outer_rule_field_caps);
361 : 0 : EFSYS_KMEM_FREE(enp->en_esip, sizeof (*maep), maep);
362 : 0 : enp->en_maep = NULL;
363 : : }
364 : :
365 : : __checkReturn efx_rc_t
366 : 0 : efx_mae_get_limits(
367 : : __in efx_nic_t *enp,
368 : : __out efx_mae_limits_t *emlp)
369 : : {
370 : 0 : const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
371 : 0 : struct efx_mae_s *maep = enp->en_maep;
372 : : efx_rc_t rc;
373 : :
374 [ # # ]: 0 : if (encp->enc_mae_supported == B_FALSE) {
375 : : rc = ENOTSUP;
376 : 0 : goto fail1;
377 : : }
378 : :
379 : 0 : emlp->eml_max_n_outer_prios = maep->em_max_n_outer_prios;
380 : 0 : emlp->eml_max_n_action_prios = maep->em_max_n_action_prios;
381 : 0 : emlp->eml_encap_types_supported = maep->em_encap_types_supported;
382 : 0 : emlp->eml_encap_header_size_limit =
383 : : MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_MAXNUM_MCDI2;
384 : 0 : emlp->eml_max_n_action_counters = maep->em_max_n_action_counters;
385 : 0 : emlp->eml_max_n_conntrack_counters = maep->em_max_n_conntrack_counters;
386 : :
387 : 0 : return (0);
388 : :
389 : : fail1:
390 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
391 : 0 : return (rc);
392 : : }
393 : :
394 : : __checkReturn efx_rc_t
395 : 0 : efx_mae_match_spec_init(
396 : : __in efx_nic_t *enp,
397 : : __in efx_mae_rule_type_t type,
398 : : __in uint32_t prio,
399 : : __out efx_mae_match_spec_t **specp)
400 : : {
401 : : efx_mae_match_spec_t *spec;
402 : : efx_rc_t rc;
403 : :
404 [ # # ]: 0 : switch (type) {
405 : : case EFX_MAE_RULE_OUTER:
406 : : break;
407 : : case EFX_MAE_RULE_ACTION:
408 : : break;
409 : 0 : default:
410 : : rc = ENOTSUP;
411 : 0 : goto fail1;
412 : : }
413 : :
414 : 0 : EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (*spec), spec);
415 [ # # ]: 0 : if (spec == NULL) {
416 : : rc = ENOMEM;
417 : 0 : goto fail2;
418 : : }
419 : :
420 : 0 : spec->emms_type = type;
421 : 0 : spec->emms_prio = prio;
422 : :
423 : 0 : *specp = spec;
424 : :
425 : 0 : return (0);
426 : :
427 : : fail2:
428 : : EFSYS_PROBE(fail2);
429 : : fail1:
430 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
431 : : return (rc);
432 : : }
433 : :
434 : : void
435 : 0 : efx_mae_match_spec_fini(
436 : : __in efx_nic_t *enp,
437 : : __in efx_mae_match_spec_t *spec)
438 : : {
439 : 0 : EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec), spec);
440 : 0 : }
441 : :
442 : : /* Named identifiers which are valid indices to efx_mae_field_cap_t */
443 : : typedef enum efx_mae_field_cap_id_e {
444 : : EFX_MAE_FIELD_ID_INGRESS_MPORT_SELECTOR = MAE_FIELD_INGRESS_PORT,
445 : : EFX_MAE_FIELD_ID_ETHER_TYPE_BE = MAE_FIELD_ETHER_TYPE,
446 : : EFX_MAE_FIELD_ID_ETH_SADDR_BE = MAE_FIELD_ETH_SADDR,
447 : : EFX_MAE_FIELD_ID_ETH_DADDR_BE = MAE_FIELD_ETH_DADDR,
448 : : EFX_MAE_FIELD_ID_VLAN0_TCI_BE = MAE_FIELD_VLAN0_TCI,
449 : : EFX_MAE_FIELD_ID_VLAN0_PROTO_BE = MAE_FIELD_VLAN0_PROTO,
450 : : EFX_MAE_FIELD_ID_VLAN1_TCI_BE = MAE_FIELD_VLAN1_TCI,
451 : : EFX_MAE_FIELD_ID_VLAN1_PROTO_BE = MAE_FIELD_VLAN1_PROTO,
452 : : EFX_MAE_FIELD_ID_SRC_IP4_BE = MAE_FIELD_SRC_IP4,
453 : : EFX_MAE_FIELD_ID_DST_IP4_BE = MAE_FIELD_DST_IP4,
454 : : EFX_MAE_FIELD_ID_IP_PROTO = MAE_FIELD_IP_PROTO,
455 : : EFX_MAE_FIELD_ID_IP_TOS = MAE_FIELD_IP_TOS,
456 : : EFX_MAE_FIELD_ID_IP_TTL = MAE_FIELD_IP_TTL,
457 : : EFX_MAE_FIELD_ID_SRC_IP6_BE = MAE_FIELD_SRC_IP6,
458 : : EFX_MAE_FIELD_ID_DST_IP6_BE = MAE_FIELD_DST_IP6,
459 : : EFX_MAE_FIELD_ID_L4_SPORT_BE = MAE_FIELD_L4_SPORT,
460 : : EFX_MAE_FIELD_ID_L4_DPORT_BE = MAE_FIELD_L4_DPORT,
461 : : EFX_MAE_FIELD_ID_TCP_FLAGS_BE = MAE_FIELD_TCP_FLAGS,
462 : : EFX_MAE_FIELD_ID_ENC_ETHER_TYPE_BE = MAE_FIELD_ENC_ETHER_TYPE,
463 : : EFX_MAE_FIELD_ID_ENC_ETH_SADDR_BE = MAE_FIELD_ENC_ETH_SADDR,
464 : : EFX_MAE_FIELD_ID_ENC_ETH_DADDR_BE = MAE_FIELD_ENC_ETH_DADDR,
465 : : EFX_MAE_FIELD_ID_ENC_VLAN0_TCI_BE = MAE_FIELD_ENC_VLAN0_TCI,
466 : : EFX_MAE_FIELD_ID_ENC_VLAN0_PROTO_BE = MAE_FIELD_ENC_VLAN0_PROTO,
467 : : EFX_MAE_FIELD_ID_ENC_VLAN1_TCI_BE = MAE_FIELD_ENC_VLAN1_TCI,
468 : : EFX_MAE_FIELD_ID_ENC_VLAN1_PROTO_BE = MAE_FIELD_ENC_VLAN1_PROTO,
469 : : EFX_MAE_FIELD_ID_ENC_SRC_IP4_BE = MAE_FIELD_ENC_SRC_IP4,
470 : : EFX_MAE_FIELD_ID_ENC_DST_IP4_BE = MAE_FIELD_ENC_DST_IP4,
471 : : EFX_MAE_FIELD_ID_ENC_IP_PROTO = MAE_FIELD_ENC_IP_PROTO,
472 : : EFX_MAE_FIELD_ID_ENC_IP_TOS = MAE_FIELD_ENC_IP_TOS,
473 : : EFX_MAE_FIELD_ID_ENC_IP_TTL = MAE_FIELD_ENC_IP_TTL,
474 : : EFX_MAE_FIELD_ID_ENC_SRC_IP6_BE = MAE_FIELD_ENC_SRC_IP6,
475 : : EFX_MAE_FIELD_ID_ENC_DST_IP6_BE = MAE_FIELD_ENC_DST_IP6,
476 : : EFX_MAE_FIELD_ID_ENC_L4_SPORT_BE = MAE_FIELD_ENC_L4_SPORT,
477 : : EFX_MAE_FIELD_ID_ENC_L4_DPORT_BE = MAE_FIELD_ENC_L4_DPORT,
478 : : EFX_MAE_FIELD_ID_ENC_VNET_ID_BE = MAE_FIELD_ENC_VNET_ID,
479 : : EFX_MAE_FIELD_ID_OUTER_RULE_ID = MAE_FIELD_OUTER_RULE_ID,
480 : : EFX_MAE_FIELD_ID_HAS_OVLAN = MAE_FIELD_HAS_OVLAN,
481 : : EFX_MAE_FIELD_ID_HAS_IVLAN = MAE_FIELD_HAS_IVLAN,
482 : : EFX_MAE_FIELD_ID_ENC_HAS_OVLAN = MAE_FIELD_ENC_HAS_OVLAN,
483 : : EFX_MAE_FIELD_ID_ENC_HAS_IVLAN = MAE_FIELD_ENC_HAS_IVLAN,
484 : : EFX_MAE_FIELD_ID_RECIRC_ID = MAE_FIELD_RECIRC_ID,
485 : : EFX_MAE_FIELD_ID_CT_MARK = MAE_FIELD_CT_MARK,
486 : : EFX_MAE_FIELD_ID_IS_IP_FRAG = MAE_FIELD_IS_IP_FRAG,
487 : : EFX_MAE_FIELD_ID_IP_FIRST_FRAG = MAE_FIELD_IP_FIRST_FRAG,
488 : :
489 : : EFX_MAE_FIELD_CAP_NIDS
490 : : } efx_mae_field_cap_id_t;
491 : :
492 : : typedef enum efx_mae_field_endianness_e {
493 : : EFX_MAE_FIELD_LE = 0,
494 : : EFX_MAE_FIELD_BE,
495 : :
496 : : EFX_MAE_FIELD_ENDIANNESS_NTYPES
497 : : } efx_mae_field_endianness_t;
498 : :
499 : : /*
500 : : * The following structure is a means to describe an MAE field.
501 : : * The information in it is meant to be used internally by
502 : : * APIs for addressing a given field in a mask-value pairs
503 : : * structure and for validation purposes.
504 : : *
505 : : * A field may have an alternative one. This structure
506 : : * has additional members to reference the alternative
507 : : * field's mask. See efx_mae_match_spec_is_valid().
508 : : */
509 : : typedef struct efx_mae_mv_desc_s {
510 : : efx_mae_field_cap_id_t emmd_field_cap_id;
511 : :
512 : : size_t emmd_value_size;
513 : : size_t emmd_value_offset;
514 : : size_t emmd_mask_size;
515 : : size_t emmd_mask_offset;
516 : :
517 : : /*
518 : : * Having the alternative field's mask size set to 0
519 : : * means that there's no alternative field specified.
520 : : */
521 : : size_t emmd_alt_mask_size;
522 : : size_t emmd_alt_mask_offset;
523 : :
524 : : /* Primary field and the alternative one are of the same endianness. */
525 : : efx_mae_field_endianness_t emmd_endianness;
526 : : } efx_mae_mv_desc_t;
527 : :
528 : : /* Indices to this array are provided by efx_mae_field_id_t */
529 : : static const efx_mae_mv_desc_t __efx_mae_action_rule_mv_desc_set[] = {
530 : : #define EFX_MAE_MV_DESC(_name, _endianness) \
531 : : [EFX_MAE_FIELD_##_name] = \
532 : : { \
533 : : EFX_MAE_FIELD_ID_##_name, \
534 : : MAE_FIELD_MASK_VALUE_PAIRS_V2_##_name##_LEN, \
535 : : MAE_FIELD_MASK_VALUE_PAIRS_V2_##_name##_OFST, \
536 : : MAE_FIELD_MASK_VALUE_PAIRS_V2_##_name##_MASK_LEN, \
537 : : MAE_FIELD_MASK_VALUE_PAIRS_V2_##_name##_MASK_OFST, \
538 : : 0, 0 /* no alternative field */, \
539 : : _endianness \
540 : : }
541 : :
542 : : EFX_MAE_MV_DESC(INGRESS_MPORT_SELECTOR, EFX_MAE_FIELD_LE),
543 : : EFX_MAE_MV_DESC(ETHER_TYPE_BE, EFX_MAE_FIELD_BE),
544 : : EFX_MAE_MV_DESC(ETH_SADDR_BE, EFX_MAE_FIELD_BE),
545 : : EFX_MAE_MV_DESC(ETH_DADDR_BE, EFX_MAE_FIELD_BE),
546 : : EFX_MAE_MV_DESC(VLAN0_TCI_BE, EFX_MAE_FIELD_BE),
547 : : EFX_MAE_MV_DESC(VLAN0_PROTO_BE, EFX_MAE_FIELD_BE),
548 : : EFX_MAE_MV_DESC(VLAN1_TCI_BE, EFX_MAE_FIELD_BE),
549 : : EFX_MAE_MV_DESC(VLAN1_PROTO_BE, EFX_MAE_FIELD_BE),
550 : : EFX_MAE_MV_DESC(SRC_IP4_BE, EFX_MAE_FIELD_BE),
551 : : EFX_MAE_MV_DESC(DST_IP4_BE, EFX_MAE_FIELD_BE),
552 : : EFX_MAE_MV_DESC(IP_PROTO, EFX_MAE_FIELD_BE),
553 : : EFX_MAE_MV_DESC(IP_TOS, EFX_MAE_FIELD_BE),
554 : : EFX_MAE_MV_DESC(IP_TTL, EFX_MAE_FIELD_BE),
555 : : EFX_MAE_MV_DESC(SRC_IP6_BE, EFX_MAE_FIELD_BE),
556 : : EFX_MAE_MV_DESC(DST_IP6_BE, EFX_MAE_FIELD_BE),
557 : : EFX_MAE_MV_DESC(L4_SPORT_BE, EFX_MAE_FIELD_BE),
558 : : EFX_MAE_MV_DESC(L4_DPORT_BE, EFX_MAE_FIELD_BE),
559 : : EFX_MAE_MV_DESC(TCP_FLAGS_BE, EFX_MAE_FIELD_BE),
560 : : EFX_MAE_MV_DESC(ENC_VNET_ID_BE, EFX_MAE_FIELD_BE),
561 : : EFX_MAE_MV_DESC(OUTER_RULE_ID, EFX_MAE_FIELD_LE),
562 : : EFX_MAE_MV_DESC(RECIRC_ID, EFX_MAE_FIELD_LE),
563 : : EFX_MAE_MV_DESC(CT_MARK, EFX_MAE_FIELD_LE),
564 : :
565 : : #undef EFX_MAE_MV_DESC
566 : : };
567 : :
568 : : /* Indices to this array are provided by efx_mae_field_id_t */
569 : : static const efx_mae_mv_desc_t __efx_mae_outer_rule_mv_desc_set[] = {
570 : : #define EFX_MAE_MV_DESC(_name, _endianness) \
571 : : [EFX_MAE_FIELD_##_name] = \
572 : : { \
573 : : EFX_MAE_FIELD_ID_##_name, \
574 : : MAE_ENC_FIELD_PAIRS_##_name##_LEN, \
575 : : MAE_ENC_FIELD_PAIRS_##_name##_OFST, \
576 : : MAE_ENC_FIELD_PAIRS_##_name##_MASK_LEN, \
577 : : MAE_ENC_FIELD_PAIRS_##_name##_MASK_OFST, \
578 : : 0, 0 /* no alternative field */, \
579 : : _endianness \
580 : : }
581 : :
582 : : /* Same as EFX_MAE_MV_DESC(), but also indicates an alternative field. */
583 : : #define EFX_MAE_MV_DESC_ALT(_name, _alt_name, _endianness) \
584 : : [EFX_MAE_FIELD_##_name] = \
585 : : { \
586 : : EFX_MAE_FIELD_ID_##_name, \
587 : : MAE_ENC_FIELD_PAIRS_##_name##_LEN, \
588 : : MAE_ENC_FIELD_PAIRS_##_name##_OFST, \
589 : : MAE_ENC_FIELD_PAIRS_##_name##_MASK_LEN, \
590 : : MAE_ENC_FIELD_PAIRS_##_name##_MASK_OFST, \
591 : : MAE_ENC_FIELD_PAIRS_##_alt_name##_MASK_LEN, \
592 : : MAE_ENC_FIELD_PAIRS_##_alt_name##_MASK_OFST, \
593 : : _endianness \
594 : : }
595 : :
596 : : EFX_MAE_MV_DESC(INGRESS_MPORT_SELECTOR, EFX_MAE_FIELD_LE),
597 : : EFX_MAE_MV_DESC(ENC_ETHER_TYPE_BE, EFX_MAE_FIELD_BE),
598 : : EFX_MAE_MV_DESC(ENC_ETH_SADDR_BE, EFX_MAE_FIELD_BE),
599 : : EFX_MAE_MV_DESC(ENC_ETH_DADDR_BE, EFX_MAE_FIELD_BE),
600 : : EFX_MAE_MV_DESC(ENC_VLAN0_TCI_BE, EFX_MAE_FIELD_BE),
601 : : EFX_MAE_MV_DESC(ENC_VLAN0_PROTO_BE, EFX_MAE_FIELD_BE),
602 : : EFX_MAE_MV_DESC(ENC_VLAN1_TCI_BE, EFX_MAE_FIELD_BE),
603 : : EFX_MAE_MV_DESC(ENC_VLAN1_PROTO_BE, EFX_MAE_FIELD_BE),
604 : : EFX_MAE_MV_DESC_ALT(ENC_SRC_IP4_BE, ENC_SRC_IP6_BE, EFX_MAE_FIELD_BE),
605 : : EFX_MAE_MV_DESC_ALT(ENC_DST_IP4_BE, ENC_DST_IP6_BE, EFX_MAE_FIELD_BE),
606 : : EFX_MAE_MV_DESC(ENC_IP_PROTO, EFX_MAE_FIELD_BE),
607 : : EFX_MAE_MV_DESC(ENC_IP_TOS, EFX_MAE_FIELD_BE),
608 : : EFX_MAE_MV_DESC(ENC_IP_TTL, EFX_MAE_FIELD_BE),
609 : : EFX_MAE_MV_DESC_ALT(ENC_SRC_IP6_BE, ENC_SRC_IP4_BE, EFX_MAE_FIELD_BE),
610 : : EFX_MAE_MV_DESC_ALT(ENC_DST_IP6_BE, ENC_DST_IP4_BE, EFX_MAE_FIELD_BE),
611 : : EFX_MAE_MV_DESC(ENC_L4_SPORT_BE, EFX_MAE_FIELD_BE),
612 : : EFX_MAE_MV_DESC(ENC_L4_DPORT_BE, EFX_MAE_FIELD_BE),
613 : :
614 : : #undef EFX_MAE_MV_DESC_ALT
615 : : #undef EFX_MAE_MV_DESC
616 : : };
617 : :
618 : : /*
619 : : * The following structure is a means to describe an MAE bit.
620 : : * The information in it is meant to be used internally by
621 : : * APIs for addressing a given flag in a mask-value pairs
622 : : * structure and for validation purposes.
623 : : */
624 : : typedef struct efx_mae_mv_bit_desc_s {
625 : : /*
626 : : * Arrays using this struct are indexed by field IDs.
627 : : * Fields which aren't meant to be referenced by these
628 : : * arrays comprise gaps (invalid entries). Below field
629 : : * helps to identify such entries.
630 : : */
631 : : boolean_t emmbd_entry_is_valid;
632 : : efx_mae_field_cap_id_t emmbd_bit_cap_id;
633 : : size_t emmbd_value_ofst;
634 : : unsigned int emmbd_value_lbn;
635 : : size_t emmbd_mask_ofst;
636 : : unsigned int emmbd_mask_lbn;
637 : : } efx_mae_mv_bit_desc_t;
638 : :
639 : : static const efx_mae_mv_bit_desc_t __efx_mae_outer_rule_mv_bit_desc_set[] = {
640 : : #define EFX_MAE_MV_BIT_DESC(_name) \
641 : : [EFX_MAE_FIELD_##_name] = \
642 : : { \
643 : : B_TRUE, \
644 : : EFX_MAE_FIELD_ID_##_name, \
645 : : MAE_ENC_FIELD_PAIRS_##_name##_OFST, \
646 : : MAE_ENC_FIELD_PAIRS_##_name##_LBN, \
647 : : MAE_ENC_FIELD_PAIRS_##_name##_MASK_OFST, \
648 : : MAE_ENC_FIELD_PAIRS_##_name##_MASK_LBN, \
649 : : }
650 : :
651 : : EFX_MAE_MV_BIT_DESC(ENC_HAS_OVLAN),
652 : : EFX_MAE_MV_BIT_DESC(ENC_HAS_IVLAN),
653 : :
654 : : #undef EFX_MAE_MV_BIT_DESC
655 : : };
656 : :
657 : : static const efx_mae_mv_bit_desc_t __efx_mae_action_rule_mv_bit_desc_set[] = {
658 : : #define EFX_MAE_MV_BIT_DESC(_name) \
659 : : [EFX_MAE_FIELD_##_name] = \
660 : : { \
661 : : B_TRUE, \
662 : : EFX_MAE_FIELD_ID_##_name, \
663 : : MAE_FIELD_MASK_VALUE_PAIRS_V2_FLAGS_OFST, \
664 : : MAE_FIELD_MASK_VALUE_PAIRS_V2_##_name##_LBN, \
665 : : MAE_FIELD_MASK_VALUE_PAIRS_V2_FLAGS_MASK_OFST, \
666 : : MAE_FIELD_MASK_VALUE_PAIRS_V2_##_name##_LBN, \
667 : : }
668 : :
669 : : EFX_MAE_MV_BIT_DESC(HAS_OVLAN),
670 : : EFX_MAE_MV_BIT_DESC(HAS_IVLAN),
671 : : EFX_MAE_MV_BIT_DESC(ENC_HAS_OVLAN),
672 : : EFX_MAE_MV_BIT_DESC(ENC_HAS_IVLAN),
673 : : EFX_MAE_MV_BIT_DESC(IS_IP_FRAG),
674 : : EFX_MAE_MV_BIT_DESC(IP_FIRST_FRAG),
675 : :
676 : : #undef EFX_MAE_MV_BIT_DESC
677 : : };
678 : :
679 : : __checkReturn efx_rc_t
680 : 0 : efx_mae_mport_invalid(
681 : : __out efx_mport_sel_t *mportp)
682 : : {
683 : : efx_dword_t dword;
684 : : efx_rc_t rc;
685 : :
686 [ # # ]: 0 : if (mportp == NULL) {
687 : : rc = EINVAL;
688 : 0 : goto fail1;
689 : : }
690 : :
691 : : EFX_POPULATE_DWORD_1(dword,
692 : : MAE_MPORT_SELECTOR_TYPE, MAE_MPORT_SELECTOR_TYPE_INVALID);
693 : :
694 : : memset(mportp, 0, sizeof (*mportp));
695 : 0 : mportp->sel = dword.ed_u32[0];
696 : :
697 : 0 : return (0);
698 : :
699 : : fail1:
700 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
701 : 0 : return (rc);
702 : : }
703 : :
704 : : __checkReturn efx_rc_t
705 : 0 : efx_mae_mport_by_phy_port(
706 : : __in uint32_t phy_port,
707 : : __out efx_mport_sel_t *mportp)
708 : : {
709 : : efx_dword_t dword;
710 : : efx_rc_t rc;
711 : :
712 [ # # ]: 0 : if (phy_port > EFX_MASK32(MAE_MPORT_SELECTOR_PPORT_ID)) {
713 : : rc = EINVAL;
714 : 0 : goto fail1;
715 : : }
716 : :
717 : 0 : EFX_POPULATE_DWORD_2(dword,
718 : : MAE_MPORT_SELECTOR_TYPE, MAE_MPORT_SELECTOR_TYPE_PPORT,
719 : : MAE_MPORT_SELECTOR_PPORT_ID, phy_port);
720 : :
721 : : memset(mportp, 0, sizeof (*mportp));
722 : : /*
723 : : * The constructed DWORD is little-endian,
724 : : * but the resulting value is meant to be
725 : : * passed to MCDIs, where it will undergo
726 : : * host-order to little endian conversion.
727 : : */
728 : 0 : mportp->sel = EFX_DWORD_FIELD(dword, EFX_DWORD_0);
729 : :
730 : 0 : return (0);
731 : :
732 : : fail1:
733 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
734 : 0 : return (rc);
735 : : }
736 : :
737 : : __checkReturn efx_rc_t
738 : 0 : efx_mae_mport_by_pcie_function(
739 : : __in uint32_t pf,
740 : : __in uint32_t vf,
741 : : __out efx_mport_sel_t *mportp)
742 : : {
743 : : efx_dword_t dword;
744 : : efx_rc_t rc;
745 : :
746 : 0 : rc = efx_mae_mport_by_pcie_mh_function(EFX_PCIE_INTERFACE_CALLER,
747 : : pf, vf, mportp);
748 [ # # ]: 0 : if (rc != 0)
749 : 0 : goto fail1;
750 : :
751 : : return (0);
752 : :
753 : : fail1:
754 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
755 : 0 : return (rc);
756 : : }
757 : :
758 : : static __checkReturn efx_rc_t
759 : : efx_mae_intf_to_selector(
760 : : __in efx_pcie_interface_t intf,
761 : : __out uint32_t *selector_intfp)
762 : : {
763 : : efx_rc_t rc;
764 : :
765 : : switch (intf) {
766 : : case EFX_PCIE_INTERFACE_HOST_PRIMARY:
767 : : EFX_STATIC_ASSERT(MAE_MPORT_SELECTOR_HOST_PRIMARY <=
768 : : EFX_MASK32(MAE_MPORT_SELECTOR_FUNC_INTF_ID));
769 : : *selector_intfp = MAE_MPORT_SELECTOR_HOST_PRIMARY;
770 : : break;
771 : : case EFX_PCIE_INTERFACE_NIC_EMBEDDED:
772 : : EFX_STATIC_ASSERT(MAE_MPORT_SELECTOR_NIC_EMBEDDED <=
773 : : EFX_MASK32(MAE_MPORT_SELECTOR_FUNC_INTF_ID));
774 : : *selector_intfp = MAE_MPORT_SELECTOR_NIC_EMBEDDED;
775 : : break;
776 : : case EFX_PCIE_INTERFACE_CALLER:
777 : : EFX_STATIC_ASSERT(MAE_MPORT_SELECTOR_CALLER_INTF <=
778 : : EFX_MASK32(MAE_MPORT_SELECTOR_FUNC_INTF_ID));
779 : : *selector_intfp = MAE_MPORT_SELECTOR_CALLER_INTF;
780 : : break;
781 : 0 : default:
782 : : rc = EINVAL;
783 : 0 : goto fail1;
784 : : }
785 : :
786 : : return (0);
787 : :
788 : : fail1:
789 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
790 : : return (rc);
791 : : }
792 : :
793 : : __checkReturn efx_rc_t
794 [ # # ]: 0 : efx_mae_mport_by_pcie_mh_function(
795 : : __in efx_pcie_interface_t intf,
796 : : __in uint32_t pf,
797 : : __in uint32_t vf,
798 : : __out efx_mport_sel_t *mportp)
799 : : {
800 : : uint32_t selector_intf;
801 : : efx_dword_t dword;
802 : : efx_rc_t rc;
803 : :
804 : : EFX_STATIC_ASSERT(EFX_PCI_VF_INVALID ==
805 : : MAE_MPORT_SELECTOR_FUNC_VF_ID_NULL);
806 : :
807 : : rc = efx_mae_intf_to_selector(intf, &selector_intf);
808 : : if (rc != 0)
809 : 0 : goto fail1;
810 : :
811 [ # # ]: 0 : if (pf > EFX_MASK32(MAE_MPORT_SELECTOR_FUNC_MH_PF_ID)) {
812 : : rc = EINVAL;
813 : 0 : goto fail2;
814 : : }
815 : :
816 [ # # ]: 0 : if (vf > EFX_MASK32(MAE_MPORT_SELECTOR_FUNC_VF_ID)) {
817 : : rc = EINVAL;
818 : 0 : goto fail3;
819 : : }
820 : :
821 : :
822 : 0 : EFX_POPULATE_DWORD_4(dword,
823 : : MAE_MPORT_SELECTOR_TYPE, MAE_MPORT_SELECTOR_TYPE_MH_FUNC,
824 : : MAE_MPORT_SELECTOR_FUNC_INTF_ID, selector_intf,
825 : : MAE_MPORT_SELECTOR_FUNC_MH_PF_ID, pf,
826 : : MAE_MPORT_SELECTOR_FUNC_VF_ID, vf);
827 : :
828 : : memset(mportp, 0, sizeof (*mportp));
829 : 0 : mportp->sel = dword.ed_u32[0];
830 : :
831 : 0 : return (0);
832 : :
833 : : fail3:
834 : : EFSYS_PROBE(fail3);
835 : : fail2:
836 : : EFSYS_PROBE(fail2);
837 : : fail1:
838 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
839 : : return (rc);
840 : : }
841 : :
842 : : static __checkReturn efx_rc_t
843 : 0 : efx_mcdi_mae_mport_lookup(
844 : : __in efx_nic_t *enp,
845 : : __in const efx_mport_sel_t *mport_selectorp,
846 : : __out efx_mport_id_t *mport_idp)
847 : : {
848 : : efx_mcdi_req_t req;
849 : 0 : EFX_MCDI_DECLARE_BUF(payload,
850 : : MC_CMD_MAE_MPORT_LOOKUP_IN_LEN,
851 : : MC_CMD_MAE_MPORT_LOOKUP_OUT_LEN);
852 : : efx_rc_t rc;
853 : :
854 : 0 : req.emr_cmd = MC_CMD_MAE_MPORT_LOOKUP;
855 : 0 : req.emr_in_buf = payload;
856 : 0 : req.emr_in_length = MC_CMD_MAE_MPORT_LOOKUP_IN_LEN;
857 : 0 : req.emr_out_buf = payload;
858 : 0 : req.emr_out_length = MC_CMD_MAE_MPORT_LOOKUP_OUT_LEN;
859 : :
860 : 0 : MCDI_IN_SET_DWORD(req, MAE_MPORT_LOOKUP_IN_MPORT_SELECTOR,
861 : : mport_selectorp->sel);
862 : :
863 : 0 : efx_mcdi_execute(enp, &req);
864 : :
865 [ # # ]: 0 : if (req.emr_rc != 0) {
866 : : rc = req.emr_rc;
867 : 0 : goto fail1;
868 : : }
869 : :
870 : 0 : mport_idp->id = MCDI_OUT_DWORD(req, MAE_MPORT_LOOKUP_OUT_MPORT_ID);
871 : :
872 : 0 : return (0);
873 : :
874 : : fail1:
875 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
876 : 0 : return (rc);
877 : : }
878 : :
879 : : __checkReturn efx_rc_t
880 : 0 : efx_mae_mport_id_by_selector(
881 : : __in efx_nic_t *enp,
882 : : __in const efx_mport_sel_t *mport_selectorp,
883 : : __out efx_mport_id_t *mport_idp)
884 : : {
885 : 0 : const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
886 : : efx_rc_t rc;
887 : :
888 [ # # ]: 0 : if (encp->enc_mae_supported == B_FALSE) {
889 : : rc = ENOTSUP;
890 : 0 : goto fail1;
891 : : }
892 : :
893 : 0 : rc = efx_mcdi_mae_mport_lookup(enp, mport_selectorp, mport_idp);
894 [ # # ]: 0 : if (rc != 0)
895 : 0 : goto fail2;
896 : :
897 : : return (0);
898 : :
899 : : fail2:
900 : : EFSYS_PROBE(fail2);
901 : : fail1:
902 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
903 : : return (rc);
904 : : }
905 : :
906 : : __checkReturn efx_rc_t
907 : 0 : efx_mae_match_spec_recirc_id_set(
908 : : __in efx_mae_match_spec_t *spec,
909 : : __in uint8_t recirc_id)
910 : : {
911 : 0 : uint8_t full_mask = UINT8_MAX;
912 : : const uint8_t *vp;
913 : : const uint8_t *mp;
914 : : efx_rc_t rc;
915 : :
916 : : vp = (const uint8_t *)&recirc_id;
917 : : mp = (const uint8_t *)&full_mask;
918 : :
919 : 0 : rc = efx_mae_match_spec_field_set(spec, EFX_MAE_FIELD_RECIRC_ID,
920 : : sizeof (recirc_id), vp,
921 : : sizeof (full_mask), mp);
922 [ # # ]: 0 : if (rc != 0)
923 : 0 : goto fail1;
924 : :
925 : : return (0);
926 : :
927 : : fail1:
928 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
929 : 0 : return (rc);
930 : : }
931 : :
932 : : __checkReturn efx_rc_t
933 : 0 : efx_mae_match_spec_ct_mark_set(
934 : : __in efx_mae_match_spec_t *spec,
935 : : __in uint32_t ct_mark)
936 : : {
937 : 0 : uint32_t full_mask = UINT32_MAX;
938 : : const uint8_t *vp;
939 : : const uint8_t *mp;
940 : : efx_rc_t rc;
941 : :
942 : : mp = (const uint8_t *)&full_mask;
943 : : vp = (const uint8_t *)&ct_mark;
944 : :
945 : 0 : rc = efx_mae_match_spec_field_set(spec, EFX_MAE_FIELD_CT_MARK,
946 : : sizeof (ct_mark), vp,
947 : : sizeof (full_mask), mp);
948 [ # # ]: 0 : if (rc != 0)
949 : 0 : goto fail1;
950 : :
951 : : return (0);
952 : :
953 : : fail1:
954 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
955 : 0 : return (rc);
956 : : }
957 : :
958 : : __checkReturn efx_rc_t
959 : 0 : efx_mae_mport_by_id(
960 : : __in const efx_mport_id_t *mport_idp,
961 : : __out efx_mport_sel_t *mportp)
962 : : {
963 : : efx_dword_t dword;
964 : :
965 : 0 : EFX_POPULATE_DWORD_2(dword,
966 : : MAE_MPORT_SELECTOR_TYPE, MAE_MPORT_SELECTOR_TYPE_MPORT_ID,
967 : : MAE_MPORT_SELECTOR_MPORT_ID, mport_idp->id);
968 : :
969 : : memset(mportp, 0, sizeof (*mportp));
970 : 0 : mportp->sel = __LE_TO_CPU_32(dword.ed_u32[0]);
971 : :
972 : 0 : return (0);
973 : : }
974 : :
975 : : __checkReturn efx_rc_t
976 : 0 : efx_mae_match_spec_field_set(
977 : : __in efx_mae_match_spec_t *spec,
978 : : __in efx_mae_field_id_t field_id,
979 : : __in size_t value_size,
980 : : __in_bcount(value_size) const uint8_t *value,
981 : : __in size_t mask_size,
982 : : __in_bcount(mask_size) const uint8_t *mask)
983 : : {
984 : : const efx_mae_mv_desc_t *descp;
985 : : unsigned int desc_set_nentries;
986 : : uint8_t *mvp;
987 : : efx_rc_t rc;
988 : :
989 [ # # # ]: 0 : switch (spec->emms_type) {
990 : 0 : case EFX_MAE_RULE_OUTER:
991 : : desc_set_nentries =
992 : : EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_desc_set);
993 : 0 : descp = &__efx_mae_outer_rule_mv_desc_set[field_id];
994 : 0 : mvp = spec->emms_mask_value_pairs.outer;
995 : 0 : break;
996 : 0 : case EFX_MAE_RULE_ACTION:
997 : : desc_set_nentries =
998 : : EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_desc_set);
999 : 0 : descp = &__efx_mae_action_rule_mv_desc_set[field_id];
1000 : 0 : mvp = spec->emms_mask_value_pairs.action;
1001 : 0 : break;
1002 : 0 : default:
1003 : : rc = ENOTSUP;
1004 : 0 : goto fail1;
1005 : : }
1006 : :
1007 [ # # ]: 0 : if ((unsigned int)field_id >= desc_set_nentries) {
1008 : : rc = EINVAL;
1009 : 0 : goto fail2;
1010 : : }
1011 : :
1012 [ # # ]: 0 : if (descp->emmd_mask_size == 0) {
1013 : : /* The ID points to a gap in the array of field descriptors. */
1014 : : rc = EINVAL;
1015 : 0 : goto fail3;
1016 : : }
1017 : :
1018 [ # # ]: 0 : if (value_size != descp->emmd_value_size) {
1019 : : rc = EINVAL;
1020 : 0 : goto fail4;
1021 : : }
1022 : :
1023 [ # # ]: 0 : if (mask_size != descp->emmd_mask_size) {
1024 : : rc = EINVAL;
1025 : 0 : goto fail5;
1026 : : }
1027 : :
1028 [ # # ]: 0 : if (descp->emmd_endianness == EFX_MAE_FIELD_BE) {
1029 : : unsigned int i;
1030 : :
1031 : : /*
1032 : : * The mask/value are in network (big endian) order.
1033 : : * The MCDI request field is also big endian.
1034 : : */
1035 : :
1036 [ # # ]: 0 : EFSYS_ASSERT3U(value_size, ==, mask_size);
1037 : :
1038 [ # # ]: 0 : for (i = 0; i < value_size; ++i) {
1039 : 0 : uint8_t *v_bytep = mvp + descp->emmd_value_offset + i;
1040 : 0 : uint8_t *m_bytep = mvp + descp->emmd_mask_offset + i;
1041 : :
1042 : : /*
1043 : : * Apply the mask (which may be all-zeros) to the value.
1044 : : *
1045 : : * If this API is provided with some value to set for a
1046 : : * given field in one specification and with some other
1047 : : * value to set for this field in another specification,
1048 : : * then, if the two masks are all-zeros, the field will
1049 : : * avoid being counted as a mismatch when comparing the
1050 : : * specifications using efx_mae_match_specs_equal() API.
1051 : : */
1052 : 0 : *v_bytep = value[i] & mask[i];
1053 : 0 : *m_bytep = mask[i];
1054 : : }
1055 : : } else {
1056 : : efx_dword_t dword;
1057 : :
1058 : : /*
1059 : : * The mask/value are in host byte order.
1060 : : * The MCDI request field is little endian.
1061 : : */
1062 [ # # # ]: 0 : switch (value_size) {
1063 : 0 : case 4:
1064 : 0 : EFX_POPULATE_DWORD_1(dword,
1065 : : EFX_DWORD_0, *(const uint32_t *)value);
1066 : :
1067 : 0 : memcpy(mvp + descp->emmd_value_offset,
1068 : : &dword, sizeof (dword));
1069 : : break;
1070 : 0 : case 1:
1071 : 0 : memcpy(mvp + descp->emmd_value_offset,
1072 : : value, 1);
1073 : : break;
1074 : : default:
1075 : 0 : EFSYS_ASSERT(B_FALSE);
1076 : : }
1077 : :
1078 [ # # # ]: 0 : switch (mask_size) {
1079 : 0 : case 4:
1080 : 0 : EFX_POPULATE_DWORD_1(dword,
1081 : : EFX_DWORD_0, *(const uint32_t *)mask);
1082 : :
1083 : 0 : memcpy(mvp + descp->emmd_mask_offset,
1084 : : &dword, sizeof (dword));
1085 : : break;
1086 : 0 : case 1:
1087 : 0 : memcpy(mvp + descp->emmd_mask_offset,
1088 : : mask, 1);
1089 : : break;
1090 : : default:
1091 : 0 : EFSYS_ASSERT(B_FALSE);
1092 : : }
1093 : : }
1094 : :
1095 : : return (0);
1096 : :
1097 : : fail5:
1098 : : EFSYS_PROBE(fail5);
1099 : : fail4:
1100 : : EFSYS_PROBE(fail4);
1101 : : fail3:
1102 : : EFSYS_PROBE(fail3);
1103 : : fail2:
1104 : : EFSYS_PROBE(fail2);
1105 : : fail1:
1106 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
1107 : : return (rc);
1108 : : }
1109 : :
1110 : : __checkReturn efx_rc_t
1111 : 0 : efx_mae_match_spec_field_get(
1112 : : __in const efx_mae_match_spec_t *spec,
1113 : : __in efx_mae_field_id_t field_id,
1114 : : __in size_t value_size,
1115 : : __out_bcount_opt(value_size) uint8_t *value,
1116 : : __in size_t mask_size,
1117 : : __out_bcount_opt(mask_size) uint8_t *mask)
1118 : : {
1119 : : const efx_mae_mv_desc_t *descp;
1120 : : unsigned int desc_set_nentries;
1121 : : const uint8_t *mvp;
1122 : : efx_rc_t rc;
1123 : :
1124 [ # # # ]: 0 : switch (spec->emms_type) {
1125 : 0 : case EFX_MAE_RULE_OUTER:
1126 : : desc_set_nentries =
1127 : : EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_desc_set);
1128 : 0 : descp = &__efx_mae_outer_rule_mv_desc_set[field_id];
1129 : 0 : mvp = spec->emms_mask_value_pairs.outer;
1130 : 0 : break;
1131 : 0 : case EFX_MAE_RULE_ACTION:
1132 : : desc_set_nentries =
1133 : : EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_desc_set);
1134 : 0 : descp = &__efx_mae_action_rule_mv_desc_set[field_id];
1135 : 0 : mvp = spec->emms_mask_value_pairs.action;
1136 : 0 : break;
1137 : 0 : default:
1138 : : rc = ENOTSUP;
1139 : 0 : goto fail1;
1140 : : }
1141 : :
1142 [ # # ]: 0 : if ((unsigned int)field_id >= desc_set_nentries) {
1143 : : rc = EINVAL;
1144 : 0 : goto fail2;
1145 : : }
1146 : :
1147 [ # # ]: 0 : if (descp->emmd_mask_size == 0) {
1148 : : /* The ID points to a gap in the array of field descriptors. */
1149 : : rc = EINVAL;
1150 : 0 : goto fail3;
1151 : : }
1152 : :
1153 [ # # # # ]: 0 : if (value != NULL && value_size != descp->emmd_value_size) {
1154 : : rc = EINVAL;
1155 : 0 : goto fail4;
1156 : : }
1157 : :
1158 [ # # # # ]: 0 : if (mask != NULL && mask_size != descp->emmd_mask_size) {
1159 : : rc = EINVAL;
1160 : 0 : goto fail5;
1161 : : }
1162 : :
1163 [ # # ]: 0 : if (value == NULL && value_size != 0) {
1164 : : rc = EINVAL;
1165 : 0 : goto fail6;
1166 : : }
1167 : :
1168 [ # # ]: 0 : if (mask == NULL && mask_size != 0) {
1169 : : rc = EINVAL;
1170 : 0 : goto fail7;
1171 : : }
1172 : :
1173 [ # # ]: 0 : if (descp->emmd_endianness == EFX_MAE_FIELD_BE) {
1174 : : /*
1175 : : * The MCDI request field is in network (big endian) order.
1176 : : * The mask/value are also big endian.
1177 : : */
1178 : 0 : memcpy(value, mvp + descp->emmd_value_offset, value_size);
1179 : 0 : memcpy(mask, mvp + descp->emmd_mask_offset, mask_size);
1180 : : } else {
1181 : : efx_dword_t dword;
1182 : :
1183 : : /*
1184 : : * The MCDI request field is little endian.
1185 : : * The mask/value are in host byte order.
1186 : : */
1187 [ # # # # ]: 0 : switch (value_size) {
1188 : 0 : case 4:
1189 : 0 : memcpy(&dword, mvp + descp->emmd_value_offset,
1190 : : sizeof (dword));
1191 : :
1192 : 0 : *(uint32_t *)value =
1193 : : EFX_DWORD_FIELD(dword, EFX_DWORD_0);
1194 : 0 : break;
1195 : 0 : case 1:
1196 : 0 : memcpy(value, mvp + descp->emmd_value_offset, 1);
1197 : : break;
1198 : : case 0:
1199 : : break;
1200 : : default:
1201 : 0 : EFSYS_ASSERT(B_FALSE);
1202 : : }
1203 : :
1204 [ # # # # ]: 0 : switch (mask_size) {
1205 : 0 : case 4:
1206 : 0 : memcpy(&dword, mvp + descp->emmd_mask_offset,
1207 : : sizeof (dword));
1208 : :
1209 : 0 : *(uint32_t *)mask =
1210 : : EFX_DWORD_FIELD(dword, EFX_DWORD_0);
1211 : 0 : break;
1212 : 0 : case 1:
1213 : 0 : memcpy(mask, mvp + descp->emmd_mask_offset, 1);
1214 : : break;
1215 : : case 0:
1216 : : break;
1217 : : default:
1218 : 0 : EFSYS_ASSERT(B_FALSE);
1219 : : }
1220 : : }
1221 : :
1222 : : return (0);
1223 : :
1224 : : fail7:
1225 : : EFSYS_PROBE(fail7);
1226 : : fail6:
1227 : : EFSYS_PROBE(fail6);
1228 : : fail5:
1229 : : EFSYS_PROBE(fail5);
1230 : : fail4:
1231 : : EFSYS_PROBE(fail4);
1232 : : fail3:
1233 : : EFSYS_PROBE(fail3);
1234 : : fail2:
1235 : : EFSYS_PROBE(fail2);
1236 : : fail1:
1237 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
1238 : : return (rc);
1239 : : }
1240 : :
1241 : : __checkReturn efx_rc_t
1242 : 0 : efx_mae_match_spec_bit_set(
1243 : : __in efx_mae_match_spec_t *spec,
1244 : : __in efx_mae_field_id_t field_id,
1245 : : __in boolean_t value)
1246 : : {
1247 : : const efx_mae_mv_bit_desc_t *bit_descp;
1248 : : unsigned int bit_desc_set_nentries;
1249 : : unsigned int byte_idx;
1250 : : unsigned int bit_idx;
1251 : : uint8_t *mvp;
1252 : : efx_rc_t rc;
1253 : :
1254 [ # # # ]: 0 : switch (spec->emms_type) {
1255 : 0 : case EFX_MAE_RULE_OUTER:
1256 : : bit_desc_set_nentries =
1257 : : EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_bit_desc_set);
1258 : 0 : bit_descp = &__efx_mae_outer_rule_mv_bit_desc_set[field_id];
1259 : 0 : mvp = spec->emms_mask_value_pairs.outer;
1260 : 0 : break;
1261 : 0 : case EFX_MAE_RULE_ACTION:
1262 : : bit_desc_set_nentries =
1263 : : EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_bit_desc_set);
1264 : 0 : bit_descp = &__efx_mae_action_rule_mv_bit_desc_set[field_id];
1265 : 0 : mvp = spec->emms_mask_value_pairs.action;
1266 : 0 : break;
1267 : 0 : default:
1268 : : rc = ENOTSUP;
1269 : 0 : goto fail1;
1270 : : }
1271 : :
1272 [ # # ]: 0 : if ((unsigned int)field_id >= bit_desc_set_nentries) {
1273 : : rc = EINVAL;
1274 : 0 : goto fail2;
1275 : : }
1276 : :
1277 [ # # ]: 0 : if (bit_descp->emmbd_entry_is_valid == B_FALSE) {
1278 : : rc = EINVAL;
1279 : 0 : goto fail3;
1280 : : }
1281 : :
1282 : 0 : byte_idx = bit_descp->emmbd_value_ofst + bit_descp->emmbd_value_lbn / 8;
1283 : 0 : bit_idx = bit_descp->emmbd_value_lbn % 8;
1284 : :
1285 [ # # ]: 0 : if (value != B_FALSE)
1286 : 0 : mvp[byte_idx] |= (1U << bit_idx);
1287 : : else
1288 : 0 : mvp[byte_idx] &= ~(1U << bit_idx);
1289 : :
1290 : 0 : byte_idx = bit_descp->emmbd_mask_ofst + bit_descp->emmbd_mask_lbn / 8;
1291 : 0 : bit_idx = bit_descp->emmbd_mask_lbn % 8;
1292 : 0 : mvp[byte_idx] |= (1U << bit_idx);
1293 : :
1294 : 0 : return (0);
1295 : :
1296 : : fail3:
1297 : : EFSYS_PROBE(fail3);
1298 : : fail2:
1299 : : EFSYS_PROBE(fail2);
1300 : : fail1:
1301 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
1302 : : return (rc);
1303 : : }
1304 : :
1305 : : __checkReturn efx_rc_t
1306 : 0 : efx_mae_match_spec_mport_set(
1307 : : __in efx_mae_match_spec_t *spec,
1308 : : __in const efx_mport_sel_t *valuep,
1309 : : __in_opt const efx_mport_sel_t *maskp)
1310 : : {
1311 : 0 : uint32_t full_mask = UINT32_MAX;
1312 : : const uint8_t *vp;
1313 : : const uint8_t *mp;
1314 : : efx_rc_t rc;
1315 : :
1316 [ # # ]: 0 : if (valuep == NULL) {
1317 : : rc = EINVAL;
1318 : 0 : goto fail1;
1319 : : }
1320 : :
1321 : 0 : vp = (const uint8_t *)&valuep->sel;
1322 [ # # ]: 0 : if (maskp != NULL)
1323 : 0 : mp = (const uint8_t *)&maskp->sel;
1324 : : else
1325 : : mp = (const uint8_t *)&full_mask;
1326 : :
1327 : 0 : rc = efx_mae_match_spec_field_set(spec,
1328 : : EFX_MAE_FIELD_INGRESS_MPORT_SELECTOR,
1329 : : sizeof (valuep->sel), vp, sizeof (maskp->sel), mp);
1330 [ # # ]: 0 : if (rc != 0)
1331 : 0 : goto fail2;
1332 : :
1333 : : return (0);
1334 : :
1335 : : fail2:
1336 : : EFSYS_PROBE(fail2);
1337 : : fail1:
1338 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
1339 : : return (rc);
1340 : : }
1341 : :
1342 : : __checkReturn efx_rc_t
1343 : 0 : efx_mae_match_spec_clone(
1344 : : __in efx_nic_t *enp,
1345 : : __in efx_mae_match_spec_t *orig,
1346 : : __out efx_mae_match_spec_t **clonep)
1347 : : {
1348 : : efx_mae_match_spec_t *clone;
1349 : : efx_rc_t rc;
1350 : :
1351 : 0 : EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (*clone), clone);
1352 [ # # ]: 0 : if (clone == NULL) {
1353 : : rc = ENOMEM;
1354 : 0 : goto fail1;
1355 : : }
1356 : :
1357 : : memcpy(clone, orig, sizeof (efx_mae_match_spec_t));
1358 : :
1359 : 0 : *clonep = clone;
1360 : :
1361 : 0 : return (0);
1362 : :
1363 : : fail1:
1364 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
1365 : 0 : return (rc);
1366 : : }
1367 : :
1368 : : __checkReturn boolean_t
1369 : 0 : efx_mae_match_specs_equal(
1370 : : __in const efx_mae_match_spec_t *left,
1371 : : __in const efx_mae_match_spec_t *right)
1372 : : {
1373 : 0 : return ((memcmp(left, right, sizeof (*left)) == 0) ? B_TRUE : B_FALSE);
1374 : : }
1375 : :
1376 : : #define EFX_MASK_BIT_IS_SET(_mask, _mask_page_nbits, _bit) \
1377 : : ((_mask)[(_bit) / (_mask_page_nbits)] & \
1378 : : (1ULL << ((_bit) & ((_mask_page_nbits) - 1))))
1379 : :
1380 : : static boolean_t
1381 : : efx_mask_is_prefix(
1382 : : __in size_t mask_nbytes,
1383 : : __in_bcount(mask_nbytes) const uint8_t *maskp)
1384 : : {
1385 : : boolean_t prev_bit_is_set = B_TRUE;
1386 : : unsigned int i;
1387 : :
1388 [ # # ]: 0 : for (i = 0; i < 8 * mask_nbytes; ++i) {
1389 : 0 : boolean_t bit_is_set = EFX_MASK_BIT_IS_SET(maskp, 8, i);
1390 : :
1391 [ # # ]: 0 : if (!prev_bit_is_set && bit_is_set)
1392 : : return B_FALSE;
1393 : :
1394 : : prev_bit_is_set = bit_is_set;
1395 : : }
1396 : :
1397 : : return B_TRUE;
1398 : : }
1399 : :
1400 : : static boolean_t
1401 : : efx_mask_is_all_ones(
1402 : : __in size_t mask_nbytes,
1403 : : __in_bcount(mask_nbytes) const uint8_t *maskp)
1404 : : {
1405 : : unsigned int i;
1406 : : uint8_t t = ~0;
1407 : :
1408 [ # # # # : 0 : for (i = 0; i < mask_nbytes; ++i)
# # ]
1409 : 0 : t &= maskp[i];
1410 : :
1411 : 0 : return (t == (uint8_t)(~0));
1412 : : }
1413 : :
1414 : : static boolean_t
1415 : : efx_mask_is_all_zeros(
1416 : : __in size_t mask_nbytes,
1417 : : __in_bcount(mask_nbytes) const uint8_t *maskp)
1418 : : {
1419 : : unsigned int i;
1420 : : uint8_t t = 0;
1421 : :
1422 [ # # # # : 0 : for (i = 0; i < mask_nbytes; ++i)
# # ]
1423 : 0 : t |= maskp[i];
1424 : :
1425 : 0 : return (t == 0);
1426 : : }
1427 : :
1428 : : __checkReturn boolean_t
1429 : 0 : efx_mae_match_spec_is_valid(
1430 : : __in efx_nic_t *enp,
1431 : : __in const efx_mae_match_spec_t *spec)
1432 : : {
1433 : 0 : efx_mae_t *maep = enp->en_maep;
1434 : 0 : unsigned int field_ncaps = maep->em_max_nfields;
1435 : : const efx_mae_field_cap_t *field_caps;
1436 : : const efx_mae_mv_desc_t *desc_setp;
1437 : : unsigned int desc_set_nentries;
1438 : : const efx_mae_mv_bit_desc_t *bit_desc_setp;
1439 : : unsigned int bit_desc_set_nentries;
1440 : : boolean_t is_valid = B_TRUE;
1441 : : efx_mae_field_id_t field_id;
1442 : : const uint8_t *mvp;
1443 : :
1444 [ # # # ]: 0 : switch (spec->emms_type) {
1445 : 0 : case EFX_MAE_RULE_OUTER:
1446 : 0 : field_caps = maep->em_outer_rule_field_caps;
1447 : : desc_setp = __efx_mae_outer_rule_mv_desc_set;
1448 : : desc_set_nentries =
1449 : : EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_desc_set);
1450 : : bit_desc_setp = __efx_mae_outer_rule_mv_bit_desc_set;
1451 : : bit_desc_set_nentries =
1452 : : EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_bit_desc_set);
1453 : 0 : mvp = spec->emms_mask_value_pairs.outer;
1454 : 0 : break;
1455 : 0 : case EFX_MAE_RULE_ACTION:
1456 : 0 : field_caps = maep->em_action_rule_field_caps;
1457 : : desc_setp = __efx_mae_action_rule_mv_desc_set;
1458 : : desc_set_nentries =
1459 : : EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_desc_set);
1460 : : bit_desc_setp = __efx_mae_action_rule_mv_bit_desc_set;
1461 : : bit_desc_set_nentries =
1462 : : EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_bit_desc_set);
1463 : 0 : mvp = spec->emms_mask_value_pairs.action;
1464 : 0 : break;
1465 : : default:
1466 : : return (B_FALSE);
1467 : : }
1468 : :
1469 [ # # ]: 0 : if (field_caps == NULL)
1470 : : return (B_FALSE);
1471 : :
1472 [ # # ]: 0 : for (field_id = 0; (unsigned int)field_id < desc_set_nentries;
1473 : 0 : ++field_id) {
1474 : 0 : const efx_mae_mv_desc_t *descp = &desc_setp[field_id];
1475 : 0 : efx_mae_field_cap_id_t field_cap_id = descp->emmd_field_cap_id;
1476 : 0 : const uint8_t *alt_m_buf = mvp + descp->emmd_alt_mask_offset;
1477 : 0 : const uint8_t *m_buf = mvp + descp->emmd_mask_offset;
1478 : 0 : size_t alt_m_size = descp->emmd_alt_mask_size;
1479 : 0 : size_t m_size = descp->emmd_mask_size;
1480 : :
1481 [ # # ]: 0 : if (m_size == 0)
1482 : 0 : continue; /* Skip array gap */
1483 : :
1484 [ # # ]: 0 : if ((unsigned int)field_cap_id >= field_ncaps) {
1485 : : /*
1486 : : * The FW has not reported capability status for
1487 : : * this field. Make sure that its mask is zeroed.
1488 : : */
1489 : : is_valid = efx_mask_is_all_zeros(m_size, m_buf);
1490 [ # # ]: 0 : if (is_valid != B_FALSE)
1491 : 0 : continue;
1492 : : else
1493 : : break;
1494 : : }
1495 : :
1496 [ # # # # : 0 : switch (field_caps[field_cap_id].emfc_support) {
# ]
1497 : : case MAE_FIELD_SUPPORTED_MATCH_MASK:
1498 : : is_valid = B_TRUE;
1499 : : break;
1500 : : case MAE_FIELD_SUPPORTED_MATCH_PREFIX:
1501 : : is_valid = efx_mask_is_prefix(m_size, m_buf);
1502 : : break;
1503 : : case MAE_FIELD_SUPPORTED_MATCH_OPTIONAL:
1504 [ # # # # ]: 0 : is_valid = (efx_mask_is_all_ones(m_size, m_buf) ||
1505 : : efx_mask_is_all_zeros(m_size, m_buf));
1506 : 0 : break;
1507 : : case MAE_FIELD_SUPPORTED_MATCH_ALWAYS:
1508 : : is_valid = efx_mask_is_all_ones(m_size, m_buf);
1509 : :
1510 [ # # ]: 0 : if ((is_valid == B_FALSE) && (alt_m_size != 0)) {
1511 : : /*
1512 : : * This field has an alternative one. The FW
1513 : : * reports ALWAYS for both implying that one
1514 : : * of them is required to have all-ones mask.
1515 : : *
1516 : : * The primary field's mask is incorrect; go
1517 : : * on to check that of the alternative field.
1518 : : */
1519 : : is_valid = efx_mask_is_all_ones(alt_m_size,
1520 : : alt_m_buf);
1521 : : }
1522 : : break;
1523 : : case MAE_FIELD_SUPPORTED_MATCH_NEVER:
1524 : : case MAE_FIELD_UNSUPPORTED:
1525 : : default:
1526 : : is_valid = efx_mask_is_all_zeros(m_size, m_buf);
1527 : 0 : break;
1528 : : }
1529 : :
1530 [ # # ]: 0 : if (is_valid == B_FALSE)
1531 : : return (B_FALSE);
1532 : : }
1533 : :
1534 [ # # ]: 0 : for (field_id = 0; (unsigned int)field_id < bit_desc_set_nentries;
1535 : 0 : ++field_id) {
1536 : 0 : const efx_mae_mv_bit_desc_t *bit_descp =
1537 : 0 : &bit_desc_setp[field_id];
1538 : 0 : unsigned int byte_idx =
1539 : 0 : bit_descp->emmbd_mask_ofst +
1540 : 0 : bit_descp->emmbd_mask_lbn / 8;
1541 : 0 : unsigned int bit_idx =
1542 : : bit_descp->emmbd_mask_lbn % 8;
1543 : 0 : efx_mae_field_cap_id_t bit_cap_id =
1544 : : bit_descp->emmbd_bit_cap_id;
1545 : :
1546 [ # # ]: 0 : if (bit_descp->emmbd_entry_is_valid == B_FALSE)
1547 : 0 : continue; /* Skip array gap */
1548 : :
1549 [ # # ]: 0 : if ((unsigned int)bit_cap_id >= field_ncaps) {
1550 : : /* No capability for this bit = unsupported. */
1551 : 0 : is_valid = ((mvp[byte_idx] & (1U << bit_idx)) == 0);
1552 [ # # ]: 0 : if (is_valid == B_FALSE)
1553 : : break;
1554 : : else
1555 : 0 : continue;
1556 : : }
1557 : :
1558 [ # # # ]: 0 : switch (field_caps[bit_cap_id].emfc_support) {
1559 : : case MAE_FIELD_SUPPORTED_MATCH_OPTIONAL:
1560 : : is_valid = B_TRUE;
1561 : : break;
1562 : 0 : case MAE_FIELD_SUPPORTED_MATCH_ALWAYS:
1563 : 0 : is_valid = ((mvp[byte_idx] & (1U << bit_idx)) != 0);
1564 : 0 : break;
1565 : 0 : case MAE_FIELD_SUPPORTED_MATCH_NEVER:
1566 : : case MAE_FIELD_UNSUPPORTED:
1567 : : default:
1568 : 0 : is_valid = ((mvp[byte_idx] & (1U << bit_idx)) == 0);
1569 : 0 : break;
1570 : : }
1571 : :
1572 [ # # ]: 0 : if (is_valid == B_FALSE)
1573 : : break;
1574 : : }
1575 : :
1576 : : return (is_valid);
1577 : : }
1578 : :
1579 : : __checkReturn efx_rc_t
1580 : 0 : efx_mae_action_set_spec_init(
1581 : : __in efx_nic_t *enp,
1582 : : __out efx_mae_actions_t **specp)
1583 : : {
1584 : 0 : const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
1585 : : efx_mae_actions_t *spec;
1586 : : efx_rc_t rc;
1587 : :
1588 : 0 : EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (*spec), spec);
1589 [ # # ]: 0 : if (spec == NULL) {
1590 : : rc = ENOMEM;
1591 : 0 : goto fail1;
1592 : : }
1593 : :
1594 : 0 : efx_mae_action_set_clear_fw_rsrc_ids(spec);
1595 : :
1596 : : /*
1597 : : * Helpers which populate v2 actions must reject them when v2 is not
1598 : : * supported. As they have no EFX NIC argument, save v2 status here.
1599 : : */
1600 : 0 : spec->ema_v2_is_supported = encp->enc_mae_aset_v2_supported;
1601 : :
1602 : 0 : *specp = spec;
1603 : :
1604 : 0 : return (0);
1605 : :
1606 : : fail1:
1607 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
1608 : 0 : return (rc);
1609 : : }
1610 : :
1611 : : void
1612 : 0 : efx_mae_action_set_spec_fini(
1613 : : __in efx_nic_t *enp,
1614 : : __in efx_mae_actions_t *spec)
1615 : : {
1616 : 0 : EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec), spec);
1617 : 0 : }
1618 : :
1619 : : static __checkReturn efx_rc_t
1620 : 0 : efx_mae_action_set_no_op(
1621 : : __in efx_mae_actions_t *spec,
1622 : : __in size_t arg_size,
1623 : : __in_bcount(arg_size) const uint8_t *arg)
1624 : : {
1625 : : efx_rc_t rc;
1626 : :
1627 : : _NOTE(ARGUNUSED(spec))
1628 : :
1629 [ # # ]: 0 : if (arg_size != 0) {
1630 : : rc = EINVAL;
1631 : 0 : goto fail1;
1632 : : }
1633 : :
1634 [ # # ]: 0 : if (arg != NULL) {
1635 : : rc = EINVAL;
1636 : 0 : goto fail2;
1637 : : }
1638 : :
1639 : : /* This action does not have any arguments, so do nothing here. */
1640 : :
1641 : : return (0);
1642 : :
1643 : : fail2:
1644 : : EFSYS_PROBE(fail2);
1645 : 0 : fail1:
1646 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
1647 : : return (rc);
1648 : : }
1649 : :
1650 : : static __checkReturn efx_rc_t
1651 : 0 : efx_mae_action_set_add_vlan_pop(
1652 : : __in efx_mae_actions_t *spec,
1653 : : __in size_t arg_size,
1654 : : __in_bcount(arg_size) const uint8_t *arg)
1655 : : {
1656 : : efx_rc_t rc;
1657 : :
1658 [ # # ]: 0 : if (arg_size != 0) {
1659 : : rc = EINVAL;
1660 : 0 : goto fail1;
1661 : : }
1662 : :
1663 [ # # ]: 0 : if (arg != NULL) {
1664 : : rc = EINVAL;
1665 : 0 : goto fail2;
1666 : : }
1667 : :
1668 [ # # ]: 0 : if (spec->ema_n_vlan_tags_to_pop == EFX_MAE_VLAN_POP_MAX_NTAGS) {
1669 : : rc = ENOTSUP;
1670 : 0 : goto fail3;
1671 : : }
1672 : :
1673 : 0 : ++spec->ema_n_vlan_tags_to_pop;
1674 : :
1675 : 0 : return (0);
1676 : :
1677 : : fail3:
1678 : : EFSYS_PROBE(fail3);
1679 : : fail2:
1680 : : EFSYS_PROBE(fail2);
1681 : : fail1:
1682 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
1683 : : return (rc);
1684 : : }
1685 : :
1686 : : static __checkReturn efx_rc_t
1687 : 0 : efx_mae_action_set_add_vlan_push(
1688 : : __in efx_mae_actions_t *spec,
1689 : : __in size_t arg_size,
1690 : : __in_bcount(arg_size) const uint8_t *arg)
1691 : : {
1692 : 0 : unsigned int n_tags = spec->ema_n_vlan_tags_to_push;
1693 : : efx_rc_t rc;
1694 : :
1695 [ # # ]: 0 : if (arg_size != sizeof (*spec->ema_vlan_push_descs)) {
1696 : : rc = EINVAL;
1697 : 0 : goto fail1;
1698 : : }
1699 : :
1700 [ # # ]: 0 : if (arg == NULL) {
1701 : : rc = EINVAL;
1702 : 0 : goto fail2;
1703 : : }
1704 : :
1705 [ # # ]: 0 : if (n_tags == EFX_MAE_VLAN_PUSH_MAX_NTAGS) {
1706 : : rc = ENOTSUP;
1707 : 0 : goto fail3;
1708 : : }
1709 : :
1710 : 0 : memcpy(&spec->ema_vlan_push_descs[n_tags], arg, arg_size);
1711 : 0 : ++(spec->ema_n_vlan_tags_to_push);
1712 : :
1713 : 0 : return (0);
1714 : :
1715 : : fail3:
1716 : : EFSYS_PROBE(fail3);
1717 : : fail2:
1718 : : EFSYS_PROBE(fail2);
1719 : : fail1:
1720 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
1721 : : return (rc);
1722 : : }
1723 : :
1724 : : static __checkReturn efx_rc_t
1725 : 0 : efx_mae_action_set_add_count(
1726 : : __in efx_mae_actions_t *spec,
1727 : : __in size_t arg_size,
1728 : : __in_bcount(arg_size) const uint8_t *arg)
1729 : : {
1730 : : efx_rc_t rc;
1731 : :
1732 : : EFX_STATIC_ASSERT(EFX_MAE_RSRC_ID_INVALID ==
1733 : : MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_NULL);
1734 : :
1735 : : /*
1736 : : * Preparing an action set spec to update a counter requires
1737 : : * two steps: first add this action to the action spec, and then
1738 : : * add the counter ID to the spec. This allows validity checking
1739 : : * and resource allocation to be done separately.
1740 : : *
1741 : : * In order to fill in the counter ID, the caller is supposed to invoke
1742 : : * efx_mae_action_set_fill_in_counter_id(). If they do not do that,
1743 : : * efx_mae_action_set_alloc() invocation will throw an error.
1744 : : *
1745 : : * For now, no arguments are supposed to be handled.
1746 : : */
1747 : :
1748 [ # # ]: 0 : if (arg_size != 0) {
1749 : : rc = EINVAL;
1750 : 0 : goto fail1;
1751 : : }
1752 : :
1753 [ # # ]: 0 : if (arg != NULL) {
1754 : : rc = EINVAL;
1755 : 0 : goto fail2;
1756 : : }
1757 : :
1758 : 0 : ++(spec->ema_n_count_actions);
1759 : :
1760 : 0 : return (0);
1761 : :
1762 : : fail2:
1763 : : EFSYS_PROBE(fail2);
1764 : 0 : fail1:
1765 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
1766 : : return (rc);
1767 : : }
1768 : :
1769 : : static __checkReturn efx_rc_t
1770 : 0 : efx_mae_action_set_add_mark(
1771 : : __in efx_mae_actions_t *spec,
1772 : : __in size_t arg_size,
1773 : : __in_bcount(arg_size) const uint8_t *arg)
1774 : : {
1775 : : efx_rc_t rc;
1776 : :
1777 [ # # ]: 0 : if (arg_size != sizeof (spec->ema_mark_value)) {
1778 : : rc = EINVAL;
1779 : 0 : goto fail1;
1780 : : }
1781 : :
1782 [ # # ]: 0 : if (arg == NULL) {
1783 : : rc = EINVAL;
1784 : 0 : goto fail2;
1785 : : }
1786 : :
1787 : 0 : memcpy(&spec->ema_mark_value, arg, arg_size);
1788 : :
1789 : 0 : return (0);
1790 : :
1791 : : fail2:
1792 : : EFSYS_PROBE(fail2);
1793 : 0 : fail1:
1794 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
1795 : : return (rc);
1796 : : }
1797 : :
1798 : : static __checkReturn efx_rc_t
1799 : 0 : efx_mae_action_set_add_deliver(
1800 : : __in efx_mae_actions_t *spec,
1801 : : __in size_t arg_size,
1802 : : __in_bcount(arg_size) const uint8_t *arg)
1803 : : {
1804 : : efx_rc_t rc;
1805 : :
1806 [ # # ]: 0 : if (arg_size != sizeof (spec->ema_deliver_mport)) {
1807 : : rc = EINVAL;
1808 : 0 : goto fail1;
1809 : : }
1810 : :
1811 [ # # ]: 0 : if (arg == NULL) {
1812 : : rc = EINVAL;
1813 : 0 : goto fail2;
1814 : : }
1815 : :
1816 : 0 : memcpy(&spec->ema_deliver_mport, arg, arg_size);
1817 : :
1818 : 0 : return (0);
1819 : :
1820 : : fail2:
1821 : : EFSYS_PROBE(fail2);
1822 : 0 : fail1:
1823 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
1824 : : return (rc);
1825 : : }
1826 : :
1827 : : typedef struct efx_mae_action_desc_s {
1828 : : /* Action specific handler */
1829 : : efx_rc_t (*emad_add)(efx_mae_actions_t *,
1830 : : size_t, const uint8_t *);
1831 : : } efx_mae_action_desc_t;
1832 : :
1833 : : static const efx_mae_action_desc_t efx_mae_actions[EFX_MAE_NACTIONS] = {
1834 : : [EFX_MAE_ACTION_DECAP] = {
1835 : : .emad_add = efx_mae_action_set_no_op
1836 : : },
1837 : : [EFX_MAE_ACTION_VLAN_POP] = {
1838 : : .emad_add = efx_mae_action_set_add_vlan_pop
1839 : : },
1840 : : [EFX_MAE_ACTION_SET_DST_MAC] = {
1841 : : .emad_add = efx_mae_action_set_no_op
1842 : : },
1843 : : [EFX_MAE_ACTION_SET_SRC_MAC] = {
1844 : : .emad_add = efx_mae_action_set_no_op
1845 : : },
1846 : : [EFX_MAE_ACTION_DECR_IP_TTL] = {
1847 : : .emad_add = efx_mae_action_set_no_op
1848 : : },
1849 : : [EFX_MAE_ACTION_NAT] = {
1850 : : .emad_add = efx_mae_action_set_no_op
1851 : : },
1852 : : [EFX_MAE_ACTION_VLAN_PUSH] = {
1853 : : .emad_add = efx_mae_action_set_add_vlan_push
1854 : : },
1855 : : [EFX_MAE_ACTION_ENCAP] = {
1856 : : .emad_add = efx_mae_action_set_no_op
1857 : : },
1858 : : [EFX_MAE_ACTION_COUNT] = {
1859 : : .emad_add = efx_mae_action_set_add_count
1860 : : },
1861 : : [EFX_MAE_ACTION_FLAG] = {
1862 : : .emad_add = efx_mae_action_set_no_op
1863 : : },
1864 : : [EFX_MAE_ACTION_MARK] = {
1865 : : .emad_add = efx_mae_action_set_add_mark
1866 : : },
1867 : : [EFX_MAE_ACTION_DELIVER] = {
1868 : : .emad_add = efx_mae_action_set_add_deliver
1869 : : }
1870 : : };
1871 : :
1872 : : static const uint32_t efx_mae_action_ordered_map =
1873 : : (1U << EFX_MAE_ACTION_DECAP) |
1874 : : (1U << EFX_MAE_ACTION_VLAN_POP) |
1875 : : (1U << EFX_MAE_ACTION_SET_DST_MAC) |
1876 : : (1U << EFX_MAE_ACTION_SET_SRC_MAC) |
1877 : : (1U << EFX_MAE_ACTION_DECR_IP_TTL) |
1878 : : (1U << EFX_MAE_ACTION_NAT) |
1879 : : (1U << EFX_MAE_ACTION_VLAN_PUSH) |
1880 : : /*
1881 : : * HW will conduct action COUNT after
1882 : : * the matching packet has been modified by
1883 : : * length-affecting actions except for ENCAP.
1884 : : */
1885 : : (1U << EFX_MAE_ACTION_COUNT) |
1886 : : (1U << EFX_MAE_ACTION_ENCAP) |
1887 : : (1U << EFX_MAE_ACTION_FLAG) |
1888 : : (1U << EFX_MAE_ACTION_MARK) |
1889 : : (1U << EFX_MAE_ACTION_DELIVER);
1890 : :
1891 : : /*
1892 : : * These actions must not be added after DELIVER, but
1893 : : * they can have any place among the rest of
1894 : : * strictly ordered actions.
1895 : : */
1896 : : static const uint32_t efx_mae_action_nonstrict_map =
1897 : : (1U << EFX_MAE_ACTION_COUNT) |
1898 : : (1U << EFX_MAE_ACTION_FLAG) |
1899 : : (1U << EFX_MAE_ACTION_MARK);
1900 : :
1901 : : static const uint32_t efx_mae_action_repeat_map =
1902 : : (1U << EFX_MAE_ACTION_VLAN_POP) |
1903 : : (1U << EFX_MAE_ACTION_VLAN_PUSH) |
1904 : : (1U << EFX_MAE_ACTION_COUNT);
1905 : :
1906 : : /*
1907 : : * Add an action to an action set.
1908 : : *
1909 : : * This has to be invoked in the desired action order.
1910 : : * An out-of-order action request will be turned down.
1911 : : */
1912 : : static __checkReturn efx_rc_t
1913 : 0 : efx_mae_action_set_spec_populate(
1914 : : __in efx_mae_actions_t *spec,
1915 : : __in efx_mae_action_t type,
1916 : : __in size_t arg_size,
1917 : : __in_bcount(arg_size) const uint8_t *arg)
1918 : : {
1919 : : uint32_t action_mask;
1920 : : efx_rc_t rc;
1921 : :
1922 : : EFX_STATIC_ASSERT(EFX_MAE_NACTIONS <=
1923 : : (sizeof (efx_mae_action_ordered_map) * 8));
1924 : : EFX_STATIC_ASSERT(EFX_MAE_NACTIONS <=
1925 : : (sizeof (efx_mae_action_repeat_map) * 8));
1926 : :
1927 : : EFX_STATIC_ASSERT(EFX_MAE_ACTION_DELIVER + 1 == EFX_MAE_NACTIONS);
1928 : : EFX_STATIC_ASSERT(EFX_MAE_ACTION_FLAG + 1 == EFX_MAE_ACTION_MARK);
1929 : : EFX_STATIC_ASSERT(EFX_MAE_ACTION_MARK + 1 == EFX_MAE_ACTION_DELIVER);
1930 : :
1931 [ # # ]: 0 : if (type >= EFX_ARRAY_SIZE(efx_mae_actions)) {
1932 : : rc = EINVAL;
1933 : 0 : goto fail1;
1934 : : }
1935 : :
1936 : 0 : action_mask = (1U << type);
1937 : :
1938 [ # # ]: 0 : if ((spec->ema_actions & action_mask) != 0) {
1939 : : /* The action set already contains this action. */
1940 [ # # ]: 0 : if ((efx_mae_action_repeat_map & action_mask) == 0) {
1941 : : /* Cannot add another non-repeatable action. */
1942 : : rc = ENOTSUP;
1943 : 0 : goto fail2;
1944 : : }
1945 : : }
1946 : :
1947 : : if ((efx_mae_action_ordered_map & action_mask) != 0) {
1948 : : uint32_t strict_ordered_map =
1949 : : efx_mae_action_ordered_map & ~efx_mae_action_nonstrict_map;
1950 : 0 : uint32_t later_actions_mask =
1951 : 0 : strict_ordered_map & ~(action_mask | (action_mask - 1));
1952 : :
1953 [ # # ]: 0 : if ((spec->ema_actions & later_actions_mask) != 0) {
1954 : : /* Cannot add an action after later ordered actions. */
1955 : : rc = ENOTSUP;
1956 : 0 : goto fail3;
1957 : : }
1958 : : }
1959 : :
1960 [ # # ]: 0 : if (efx_mae_actions[type].emad_add != NULL) {
1961 : 0 : rc = efx_mae_actions[type].emad_add(spec, arg_size, arg);
1962 [ # # ]: 0 : if (rc != 0)
1963 : 0 : goto fail4;
1964 : : }
1965 : :
1966 : 0 : spec->ema_actions |= action_mask;
1967 : :
1968 : 0 : return (0);
1969 : :
1970 : : fail4:
1971 : : EFSYS_PROBE(fail4);
1972 : : fail3:
1973 : : EFSYS_PROBE(fail3);
1974 : : fail2:
1975 : : EFSYS_PROBE(fail2);
1976 : : fail1:
1977 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
1978 : : return (rc);
1979 : : }
1980 : :
1981 : : __checkReturn efx_rc_t
1982 : 0 : efx_mae_action_set_populate_decap(
1983 : : __in efx_mae_actions_t *spec)
1984 : : {
1985 : 0 : return (efx_mae_action_set_spec_populate(spec,
1986 : : EFX_MAE_ACTION_DECAP, 0, NULL));
1987 : : }
1988 : :
1989 : : __checkReturn efx_rc_t
1990 : 0 : efx_mae_action_set_populate_vlan_pop(
1991 : : __in efx_mae_actions_t *spec)
1992 : : {
1993 : 0 : return (efx_mae_action_set_spec_populate(spec,
1994 : : EFX_MAE_ACTION_VLAN_POP, 0, NULL));
1995 : : }
1996 : :
1997 : : __checkReturn efx_rc_t
1998 : 0 : efx_mae_action_set_populate_set_dst_mac(
1999 : : __in efx_mae_actions_t *spec)
2000 : : {
2001 : : efx_rc_t rc;
2002 : :
2003 [ # # ]: 0 : if (spec->ema_v2_is_supported == B_FALSE) {
2004 : : rc = ENOTSUP;
2005 : 0 : goto fail1;
2006 : : }
2007 : :
2008 : 0 : return (efx_mae_action_set_spec_populate(spec,
2009 : : EFX_MAE_ACTION_SET_DST_MAC, 0, NULL));
2010 : :
2011 : : fail1:
2012 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
2013 : 0 : return (rc);
2014 : : }
2015 : :
2016 : : __checkReturn efx_rc_t
2017 : 0 : efx_mae_action_set_populate_set_src_mac(
2018 : : __in efx_mae_actions_t *spec)
2019 : : {
2020 : : efx_rc_t rc;
2021 : :
2022 [ # # ]: 0 : if (spec->ema_v2_is_supported == B_FALSE) {
2023 : : rc = ENOTSUP;
2024 : 0 : goto fail1;
2025 : : }
2026 : :
2027 : 0 : return (efx_mae_action_set_spec_populate(spec,
2028 : : EFX_MAE_ACTION_SET_SRC_MAC, 0, NULL));
2029 : :
2030 : : fail1:
2031 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
2032 : 0 : return (rc);
2033 : : }
2034 : :
2035 : : __checkReturn efx_rc_t
2036 : 0 : efx_mae_action_set_populate_decr_ip_ttl(
2037 : : __in efx_mae_actions_t *spec)
2038 : : {
2039 : : efx_rc_t rc;
2040 : :
2041 [ # # ]: 0 : if (spec->ema_v2_is_supported == B_FALSE) {
2042 : : rc = ENOTSUP;
2043 : 0 : goto fail1;
2044 : : }
2045 : :
2046 : 0 : return (efx_mae_action_set_spec_populate(spec,
2047 : : EFX_MAE_ACTION_DECR_IP_TTL, 0, NULL));
2048 : :
2049 : : fail1:
2050 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
2051 : 0 : return (rc);
2052 : : }
2053 : :
2054 : : __checkReturn efx_rc_t
2055 : 0 : efx_mae_action_set_populate_nat(
2056 : : __in efx_mae_actions_t *spec)
2057 : : {
2058 : 0 : return (efx_mae_action_set_spec_populate(spec,
2059 : : EFX_MAE_ACTION_NAT, 0, NULL));
2060 : : }
2061 : :
2062 : : __checkReturn efx_rc_t
2063 : 0 : efx_mae_action_set_populate_vlan_push(
2064 : : __in efx_mae_actions_t *spec,
2065 : : __in uint16_t tpid_be,
2066 : : __in uint16_t tci_be)
2067 : : {
2068 : : efx_mae_action_vlan_push_t action;
2069 : : const uint8_t *arg = (const uint8_t *)&action;
2070 : :
2071 : 0 : action.emavp_tpid_be = tpid_be;
2072 : 0 : action.emavp_tci_be = tci_be;
2073 : :
2074 : 0 : return (efx_mae_action_set_spec_populate(spec,
2075 : : EFX_MAE_ACTION_VLAN_PUSH, sizeof (action), arg));
2076 : : }
2077 : :
2078 : : __checkReturn efx_rc_t
2079 : 0 : efx_mae_action_set_populate_encap(
2080 : : __in efx_mae_actions_t *spec)
2081 : : {
2082 : : /*
2083 : : * There is no argument to pass encap. header ID, thus, one does not
2084 : : * need to allocate an encap. header while parsing application input.
2085 : : * This is useful since building an action set may be done simply to
2086 : : * validate a rule, whilst resource allocation usually consumes time.
2087 : : */
2088 : 0 : return (efx_mae_action_set_spec_populate(spec,
2089 : : EFX_MAE_ACTION_ENCAP, 0, NULL));
2090 : : }
2091 : :
2092 : : __checkReturn efx_rc_t
2093 : 0 : efx_mae_action_set_populate_count(
2094 : : __in efx_mae_actions_t *spec)
2095 : : {
2096 : : /*
2097 : : * There is no argument to pass counter ID, thus, one does not
2098 : : * need to allocate a counter while parsing application input.
2099 : : * This is useful since building an action set may be done simply to
2100 : : * validate a rule, whilst resource allocation usually consumes time.
2101 : : */
2102 : 0 : return (efx_mae_action_set_spec_populate(spec,
2103 : : EFX_MAE_ACTION_COUNT, 0, NULL));
2104 : : }
2105 : :
2106 : : __checkReturn efx_rc_t
2107 : 0 : efx_mae_action_set_populate_flag(
2108 : : __in efx_mae_actions_t *spec)
2109 : : {
2110 : 0 : return (efx_mae_action_set_spec_populate(spec,
2111 : : EFX_MAE_ACTION_FLAG, 0, NULL));
2112 : : }
2113 : :
2114 : : __checkReturn efx_rc_t
2115 : 0 : efx_mae_action_set_populate_mark(
2116 : : __in efx_mae_actions_t *spec,
2117 : : __in uint32_t mark_value)
2118 : : {
2119 : : const uint8_t *arg = (const uint8_t *)&mark_value;
2120 : :
2121 : 0 : return (efx_mae_action_set_spec_populate(spec,
2122 : : EFX_MAE_ACTION_MARK, sizeof (mark_value), arg));
2123 : : }
2124 : :
2125 : : void
2126 : 0 : efx_mae_action_set_populate_mark_reset(
2127 : : __in efx_mae_actions_t *spec)
2128 : : {
2129 : : uint32_t action_mask = (1U << EFX_MAE_ACTION_MARK);
2130 : :
2131 [ # # ]: 0 : if ((spec->ema_actions & action_mask) == 0) {
2132 : 0 : spec->ema_actions |= action_mask;
2133 : 0 : spec->ema_mark_value = 0;
2134 : : }
2135 : 0 : }
2136 : :
2137 : : __checkReturn efx_rc_t
2138 : 0 : efx_mae_action_set_populate_deliver(
2139 : : __in efx_mae_actions_t *spec,
2140 : : __in const efx_mport_sel_t *mportp)
2141 : : {
2142 : : const uint8_t *arg;
2143 : : efx_rc_t rc;
2144 : :
2145 [ # # ]: 0 : if (mportp == NULL) {
2146 : : rc = EINVAL;
2147 : 0 : goto fail1;
2148 : : }
2149 : :
2150 : 0 : arg = (const uint8_t *)&mportp->sel;
2151 : :
2152 : 0 : return (efx_mae_action_set_spec_populate(spec,
2153 : : EFX_MAE_ACTION_DELIVER, sizeof (mportp->sel), arg));
2154 : :
2155 : : fail1:
2156 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
2157 : 0 : return (rc);
2158 : : }
2159 : :
2160 : : __checkReturn efx_rc_t
2161 : 0 : efx_mae_action_set_populate_drop(
2162 : : __in efx_mae_actions_t *spec)
2163 : : {
2164 : : efx_mport_sel_t mport;
2165 : : const uint8_t *arg;
2166 : : efx_dword_t dword;
2167 : :
2168 : : EFX_POPULATE_DWORD_1(dword,
2169 : : MAE_MPORT_SELECTOR_FLAT, MAE_MPORT_SELECTOR_NULL);
2170 : :
2171 : : /*
2172 : : * The constructed DWORD is little-endian,
2173 : : * but the resulting value is meant to be
2174 : : * passed to MCDIs, where it will undergo
2175 : : * host-order to little endian conversion.
2176 : : */
2177 : 0 : mport.sel = EFX_DWORD_FIELD(dword, EFX_DWORD_0);
2178 : :
2179 : : arg = (const uint8_t *)&mport.sel;
2180 : :
2181 : 0 : return (efx_mae_action_set_spec_populate(spec,
2182 : : EFX_MAE_ACTION_DELIVER, sizeof (mport.sel), arg));
2183 : : }
2184 : :
2185 : : __checkReturn boolean_t
2186 : 0 : efx_mae_action_set_specs_equal(
2187 : : __in const efx_mae_actions_t *left,
2188 : : __in const efx_mae_actions_t *right)
2189 : : {
2190 : : size_t cmp_size = EFX_FIELD_OFFSET(efx_mae_actions_t, ema_rsrc);
2191 : :
2192 : : /*
2193 : : * An action set specification consists of two parts. The first part
2194 : : * indicates what actions are included in the action set, as well as
2195 : : * extra quantitative values (in example, the number of VLAN tags to
2196 : : * push). The second part comprises resource IDs used by the actions.
2197 : : *
2198 : : * A resource, in example, a counter, is allocated from the hardware
2199 : : * by the client, and it's the client who is responsible for keeping
2200 : : * track of allocated resources and comparing resource IDs if needed.
2201 : : *
2202 : : * In this API, don't compare resource IDs in the two specifications.
2203 : : */
2204 : :
2205 : 0 : return ((memcmp(left, right, cmp_size) == 0) ? B_TRUE : B_FALSE);
2206 : : }
2207 : :
2208 : : __checkReturn efx_rc_t
2209 : 0 : efx_mae_match_specs_class_cmp(
2210 : : __in efx_nic_t *enp,
2211 : : __in const efx_mae_match_spec_t *left,
2212 : : __in const efx_mae_match_spec_t *right,
2213 : : __out boolean_t *have_same_classp)
2214 : : {
2215 : 0 : efx_mae_t *maep = enp->en_maep;
2216 : 0 : unsigned int field_ncaps = maep->em_max_nfields;
2217 : : const efx_mae_field_cap_t *field_caps;
2218 : : const efx_mae_mv_desc_t *desc_setp;
2219 : : unsigned int desc_set_nentries;
2220 : : const efx_mae_mv_bit_desc_t *bit_desc_setp;
2221 : : unsigned int bit_desc_set_nentries;
2222 : : boolean_t have_same_class = B_TRUE;
2223 : : efx_mae_field_id_t field_id;
2224 : : const uint8_t *mvpl;
2225 : : const uint8_t *mvpr;
2226 : : efx_rc_t rc;
2227 : :
2228 [ # # # ]: 0 : switch (left->emms_type) {
2229 : 0 : case EFX_MAE_RULE_OUTER:
2230 : 0 : field_caps = maep->em_outer_rule_field_caps;
2231 : : desc_setp = __efx_mae_outer_rule_mv_desc_set;
2232 : : desc_set_nentries =
2233 : : EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_desc_set);
2234 : : bit_desc_setp = __efx_mae_outer_rule_mv_bit_desc_set;
2235 : : bit_desc_set_nentries =
2236 : : EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_bit_desc_set);
2237 : 0 : mvpl = left->emms_mask_value_pairs.outer;
2238 : 0 : mvpr = right->emms_mask_value_pairs.outer;
2239 : 0 : break;
2240 : 0 : case EFX_MAE_RULE_ACTION:
2241 : 0 : field_caps = maep->em_action_rule_field_caps;
2242 : : desc_setp = __efx_mae_action_rule_mv_desc_set;
2243 : : desc_set_nentries =
2244 : : EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_desc_set);
2245 : : bit_desc_setp = __efx_mae_action_rule_mv_bit_desc_set;
2246 : : bit_desc_set_nentries =
2247 : : EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_bit_desc_set);
2248 : 0 : mvpl = left->emms_mask_value_pairs.action;
2249 : 0 : mvpr = right->emms_mask_value_pairs.action;
2250 : 0 : break;
2251 : 0 : default:
2252 : : rc = ENOTSUP;
2253 : 0 : goto fail1;
2254 : : }
2255 : :
2256 [ # # ]: 0 : if (field_caps == NULL) {
2257 : : rc = EAGAIN;
2258 : 0 : goto fail2;
2259 : : }
2260 : :
2261 [ # # ]: 0 : if (left->emms_type != right->emms_type ||
2262 [ # # ]: 0 : left->emms_prio != right->emms_prio) {
2263 : : /*
2264 : : * Rules of different types can never map to the same class.
2265 : : *
2266 : : * The FW can support some set of match criteria for one
2267 : : * priority and not support the very same set for
2268 : : * another priority. Thus, two rules which have
2269 : : * different priorities can never map to
2270 : : * the same class.
2271 : : */
2272 : 0 : *have_same_classp = B_FALSE;
2273 : 0 : return (0);
2274 : : }
2275 : :
2276 [ # # ]: 0 : for (field_id = 0; (unsigned int)field_id < desc_set_nentries;
2277 : 0 : ++field_id) {
2278 : 0 : const efx_mae_mv_desc_t *descp = &desc_setp[field_id];
2279 : 0 : efx_mae_field_cap_id_t field_cap_id = descp->emmd_field_cap_id;
2280 : 0 : const uint8_t *lmaskp = mvpl + descp->emmd_mask_offset;
2281 : 0 : const uint8_t *rmaskp = mvpr + descp->emmd_mask_offset;
2282 : 0 : size_t mask_size = descp->emmd_mask_size;
2283 : 0 : const uint8_t *lvalp = mvpl + descp->emmd_value_offset;
2284 : 0 : const uint8_t *rvalp = mvpr + descp->emmd_value_offset;
2285 : 0 : size_t value_size = descp->emmd_value_size;
2286 : :
2287 [ # # ]: 0 : if (mask_size == 0)
2288 : 0 : continue; /* Skip array gap */
2289 : :
2290 [ # # ]: 0 : if ((unsigned int)field_cap_id >= field_ncaps) {
2291 : : /*
2292 : : * The FW has not reported capability status for this
2293 : : * field. It's unknown whether any difference between
2294 : : * the two masks / values affects the class. The only
2295 : : * case when the class must be the same is when these
2296 : : * mask-value pairs match. Otherwise, report mismatch.
2297 : : */
2298 [ # # ]: 0 : if ((memcmp(lmaskp, rmaskp, mask_size) == 0) &&
2299 [ # # ]: 0 : (memcmp(lvalp, rvalp, value_size) == 0))
2300 : 0 : continue;
2301 : : else
2302 : : break;
2303 : : }
2304 : :
2305 [ # # ]: 0 : if (field_caps[field_cap_id].emfc_mask_affects_class) {
2306 [ # # ]: 0 : if (memcmp(lmaskp, rmaskp, mask_size) != 0) {
2307 : : have_same_class = B_FALSE;
2308 : : break;
2309 : : }
2310 : : }
2311 : :
2312 [ # # ]: 0 : if (field_caps[field_cap_id].emfc_match_affects_class) {
2313 [ # # ]: 0 : if (memcmp(lvalp, rvalp, value_size) != 0) {
2314 : : have_same_class = B_FALSE;
2315 : : break;
2316 : : }
2317 : : }
2318 : : }
2319 : :
2320 [ # # ]: 0 : if (have_same_class == B_FALSE)
2321 : 0 : goto done;
2322 : :
2323 [ # # ]: 0 : for (field_id = 0; (unsigned int)field_id < bit_desc_set_nentries;
2324 : 0 : ++field_id) {
2325 : 0 : const efx_mae_mv_bit_desc_t *bit_descp =
2326 : 0 : &bit_desc_setp[field_id];
2327 : 0 : efx_mae_field_cap_id_t bit_cap_id =
2328 : : bit_descp->emmbd_bit_cap_id;
2329 : : unsigned int byte_idx;
2330 : : unsigned int bit_idx;
2331 : :
2332 [ # # ]: 0 : if (bit_descp->emmbd_entry_is_valid == B_FALSE)
2333 : 0 : continue; /* Skip array gap */
2334 : :
2335 [ # # ]: 0 : if ((unsigned int)bit_cap_id >= field_ncaps)
2336 : : break;
2337 : :
2338 : 0 : byte_idx =
2339 : 0 : bit_descp->emmbd_mask_ofst +
2340 : 0 : bit_descp->emmbd_mask_lbn / 8;
2341 : 0 : bit_idx =
2342 : : bit_descp->emmbd_mask_lbn % 8;
2343 : :
2344 [ # # ]: 0 : if (field_caps[bit_cap_id].emfc_mask_affects_class &&
2345 : 0 : (mvpl[byte_idx] & (1U << bit_idx)) !=
2346 [ # # ]: 0 : (mvpr[byte_idx] & (1U << bit_idx))) {
2347 : : have_same_class = B_FALSE;
2348 : : break;
2349 : : }
2350 : :
2351 : 0 : byte_idx =
2352 : 0 : bit_descp->emmbd_value_ofst +
2353 : 0 : bit_descp->emmbd_value_lbn / 8;
2354 : 0 : bit_idx =
2355 : : bit_descp->emmbd_value_lbn % 8;
2356 : :
2357 [ # # ]: 0 : if (field_caps[bit_cap_id].emfc_match_affects_class &&
2358 : 0 : (mvpl[byte_idx] & (1U << bit_idx)) !=
2359 [ # # ]: 0 : (mvpr[byte_idx] & (1U << bit_idx))) {
2360 : : have_same_class = B_FALSE;
2361 : : break;
2362 : : }
2363 : : }
2364 : :
2365 : 0 : done:
2366 : 0 : *have_same_classp = have_same_class;
2367 : :
2368 : 0 : return (0);
2369 : :
2370 : : fail2:
2371 : : EFSYS_PROBE(fail2);
2372 : : fail1:
2373 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
2374 : : return (rc);
2375 : : }
2376 : :
2377 : : __checkReturn efx_rc_t
2378 : 0 : efx_mae_outer_rule_recirc_id_set(
2379 : : __in efx_mae_match_spec_t *spec,
2380 : : __in uint8_t recirc_id)
2381 : : {
2382 : : efx_rc_t rc;
2383 : :
2384 [ # # ]: 0 : if (spec->emms_type != EFX_MAE_RULE_OUTER) {
2385 : : rc = EINVAL;
2386 : 0 : goto fail1;
2387 : : }
2388 : :
2389 : 0 : spec->emms_outer_rule_recirc_id = recirc_id;
2390 : :
2391 : 0 : return (0);
2392 : :
2393 : : fail1:
2394 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
2395 : 0 : return (rc);
2396 : : }
2397 : :
2398 : : __checkReturn efx_rc_t
2399 : 0 : efx_mae_outer_rule_do_ct_set(
2400 : : __in efx_mae_match_spec_t *spec)
2401 : : {
2402 : : efx_rc_t rc;
2403 : :
2404 [ # # ]: 0 : if (spec->emms_type != EFX_MAE_RULE_OUTER) {
2405 : : rc = EINVAL;
2406 : 0 : goto fail1;
2407 : : }
2408 : :
2409 : 0 : spec->emms_outer_rule_do_ct = B_TRUE;
2410 : :
2411 : 0 : return (0);
2412 : :
2413 : : fail1:
2414 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
2415 : 0 : return (rc);
2416 : : }
2417 : :
2418 : : __checkReturn efx_rc_t
2419 : 0 : efx_mae_outer_rule_insert(
2420 : : __in efx_nic_t *enp,
2421 : : __in const efx_mae_match_spec_t *spec,
2422 : : __in efx_tunnel_protocol_t encap_type,
2423 : : __out efx_mae_rule_id_t *or_idp)
2424 : : {
2425 : 0 : const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
2426 : : efx_mcdi_req_t req;
2427 : 0 : EFX_MCDI_DECLARE_BUF(payload,
2428 : : MC_CMD_MAE_OUTER_RULE_INSERT_IN_LENMAX_MCDI2,
2429 : : MC_CMD_MAE_OUTER_RULE_INSERT_OUT_LEN);
2430 : : uint32_t encap_type_mcdi;
2431 : : efx_mae_rule_id_t or_id;
2432 : : size_t offset;
2433 : : uint8_t do_ct;
2434 : : efx_rc_t rc;
2435 : :
2436 : : EFX_STATIC_ASSERT(sizeof (or_idp->id) ==
2437 : : MC_CMD_MAE_OUTER_RULE_INSERT_OUT_OR_ID_LEN);
2438 : :
2439 : : EFX_STATIC_ASSERT(EFX_MAE_RSRC_ID_INVALID ==
2440 : : MC_CMD_MAE_OUTER_RULE_INSERT_OUT_OUTER_RULE_ID_NULL);
2441 : :
2442 [ # # ]: 0 : if (encp->enc_mae_supported == B_FALSE) {
2443 : : rc = ENOTSUP;
2444 : 0 : goto fail1;
2445 : : }
2446 : :
2447 [ # # ]: 0 : if (spec->emms_type != EFX_MAE_RULE_OUTER) {
2448 : : rc = EINVAL;
2449 : 0 : goto fail2;
2450 : : }
2451 : :
2452 : : switch (encap_type) {
2453 : : case EFX_TUNNEL_PROTOCOL_NONE:
2454 : : encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_NONE;
2455 : : break;
2456 : : case EFX_TUNNEL_PROTOCOL_VXLAN:
2457 : : encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_VXLAN;
2458 : : break;
2459 : : case EFX_TUNNEL_PROTOCOL_GENEVE:
2460 : : encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_GENEVE;
2461 : : break;
2462 : : case EFX_TUNNEL_PROTOCOL_NVGRE:
2463 : : encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_NVGRE;
2464 : : break;
2465 : 0 : default:
2466 : : rc = ENOTSUP;
2467 : 0 : goto fail3;
2468 : : }
2469 : :
2470 : 0 : req.emr_cmd = MC_CMD_MAE_OUTER_RULE_INSERT;
2471 : 0 : req.emr_in_buf = payload;
2472 : 0 : req.emr_in_length = MC_CMD_MAE_OUTER_RULE_INSERT_IN_LENMAX_MCDI2;
2473 : 0 : req.emr_out_buf = payload;
2474 : 0 : req.emr_out_length = MC_CMD_MAE_OUTER_RULE_INSERT_OUT_LEN;
2475 : :
2476 : 0 : MCDI_IN_SET_DWORD(req,
2477 : : MAE_OUTER_RULE_INSERT_IN_ENCAP_TYPE, encap_type_mcdi);
2478 : :
2479 : 0 : MCDI_IN_SET_DWORD(req, MAE_OUTER_RULE_INSERT_IN_PRIO, spec->emms_prio);
2480 : :
2481 : : /*
2482 : : * Mask-value pairs have been stored in the byte order needed for the
2483 : : * MCDI request and are thus safe to be copied directly to the buffer.
2484 : : * The library cares about byte order in efx_mae_match_spec_field_set().
2485 : : */
2486 : : EFX_STATIC_ASSERT(sizeof (spec->emms_mask_value_pairs.outer) >=
2487 : : MAE_ENC_FIELD_PAIRS_LEN);
2488 : : offset = MC_CMD_MAE_OUTER_RULE_INSERT_IN_FIELD_MATCH_CRITERIA_OFST;
2489 [ # # ]: 0 : memcpy(payload + offset, spec->emms_mask_value_pairs.outer,
2490 : : MAE_ENC_FIELD_PAIRS_LEN);
2491 : :
2492 : 0 : MCDI_IN_SET_DWORD_FIELD(req, MAE_OUTER_RULE_INSERT_IN_LOOKUP_CONTROL,
2493 : : MAE_OUTER_RULE_INSERT_IN_RECIRC_ID,
2494 : : spec->emms_outer_rule_recirc_id);
2495 : :
2496 [ # # ]: 0 : do_ct = (spec->emms_outer_rule_do_ct == B_FALSE) ? 0 : 1;
2497 : :
2498 : 0 : MCDI_IN_SET_DWORD_FIELD(req, MAE_OUTER_RULE_INSERT_IN_LOOKUP_CONTROL,
2499 : : MAE_OUTER_RULE_INSERT_IN_DO_CT, do_ct);
2500 : :
2501 : 0 : efx_mcdi_execute(enp, &req);
2502 : :
2503 [ # # ]: 0 : if (req.emr_rc != 0) {
2504 : : rc = req.emr_rc;
2505 : 0 : goto fail4;
2506 : : }
2507 : :
2508 [ # # ]: 0 : if (req.emr_out_length_used < MC_CMD_MAE_OUTER_RULE_INSERT_OUT_LEN) {
2509 : : rc = EMSGSIZE;
2510 : 0 : goto fail5;
2511 : : }
2512 : :
2513 : 0 : or_id.id = MCDI_OUT_DWORD(req, MAE_OUTER_RULE_INSERT_OUT_OR_ID);
2514 [ # # ]: 0 : if (or_id.id == EFX_MAE_RSRC_ID_INVALID) {
2515 : : rc = ENOENT;
2516 : 0 : goto fail6;
2517 : : }
2518 : :
2519 : 0 : or_idp->id = or_id.id;
2520 : :
2521 : 0 : return (0);
2522 : :
2523 : : fail6:
2524 : : EFSYS_PROBE(fail6);
2525 : : fail5:
2526 : : EFSYS_PROBE(fail5);
2527 : : fail4:
2528 : : EFSYS_PROBE(fail4);
2529 : : fail3:
2530 : : EFSYS_PROBE(fail3);
2531 : : fail2:
2532 : : EFSYS_PROBE(fail2);
2533 : : fail1:
2534 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
2535 : : return (rc);
2536 : : }
2537 : :
2538 : : __checkReturn efx_rc_t
2539 : 0 : efx_mae_outer_rule_remove(
2540 : : __in efx_nic_t *enp,
2541 : : __in const efx_mae_rule_id_t *or_idp)
2542 : : {
2543 : 0 : const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
2544 : : efx_mcdi_req_t req;
2545 : 0 : EFX_MCDI_DECLARE_BUF(payload,
2546 : : MC_CMD_MAE_OUTER_RULE_REMOVE_IN_LEN(1),
2547 : : MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_LEN(1));
2548 : : efx_rc_t rc;
2549 : :
2550 [ # # ]: 0 : if (encp->enc_mae_supported == B_FALSE) {
2551 : : rc = ENOTSUP;
2552 : 0 : goto fail1;
2553 : : }
2554 : :
2555 : 0 : req.emr_cmd = MC_CMD_MAE_OUTER_RULE_REMOVE;
2556 : 0 : req.emr_in_buf = payload;
2557 : 0 : req.emr_in_length = MC_CMD_MAE_OUTER_RULE_REMOVE_IN_LEN(1);
2558 : 0 : req.emr_out_buf = payload;
2559 : 0 : req.emr_out_length = MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_LEN(1);
2560 : :
2561 : 0 : MCDI_IN_SET_DWORD(req, MAE_OUTER_RULE_REMOVE_IN_OR_ID, or_idp->id);
2562 : :
2563 : 0 : efx_mcdi_execute(enp, &req);
2564 : :
2565 [ # # ]: 0 : if (req.emr_rc != 0) {
2566 : : rc = req.emr_rc;
2567 : 0 : goto fail2;
2568 : : }
2569 : :
2570 [ # # ]: 0 : if (req.emr_out_length_used < MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_LENMIN) {
2571 : : rc = EMSGSIZE;
2572 : 0 : goto fail3;
2573 : : }
2574 : :
2575 : 0 : if (MCDI_OUT_DWORD(req, MAE_OUTER_RULE_REMOVE_OUT_REMOVED_OR_ID) !=
2576 [ # # ]: 0 : or_idp->id) {
2577 : : /* Firmware failed to remove the outer rule. */
2578 : : rc = EAGAIN;
2579 : 0 : goto fail4;
2580 : : }
2581 : :
2582 : : return (0);
2583 : :
2584 : : fail4:
2585 : : EFSYS_PROBE(fail4);
2586 : : fail3:
2587 : : EFSYS_PROBE(fail3);
2588 : : fail2:
2589 : : EFSYS_PROBE(fail2);
2590 : : fail1:
2591 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
2592 : : return (rc);
2593 : : }
2594 : :
2595 : : __checkReturn efx_rc_t
2596 : 0 : efx_mae_match_spec_outer_rule_id_set(
2597 : : __in efx_mae_match_spec_t *spec,
2598 : : __in const efx_mae_rule_id_t *or_idp)
2599 : : {
2600 : 0 : uint32_t full_mask = UINT32_MAX;
2601 : : efx_rc_t rc;
2602 : :
2603 [ # # ]: 0 : if (spec->emms_type != EFX_MAE_RULE_ACTION) {
2604 : : rc = EINVAL;
2605 : 0 : goto fail1;
2606 : : }
2607 : :
2608 [ # # ]: 0 : if (or_idp == NULL) {
2609 : : rc = EINVAL;
2610 : 0 : goto fail2;
2611 : : }
2612 : :
2613 : 0 : rc = efx_mae_match_spec_field_set(spec, EFX_MAE_FIELD_OUTER_RULE_ID,
2614 : 0 : sizeof (or_idp->id), (const uint8_t *)&or_idp->id,
2615 : : sizeof (full_mask), (const uint8_t *)&full_mask);
2616 [ # # ]: 0 : if (rc != 0)
2617 : 0 : goto fail3;
2618 : :
2619 : : return (0);
2620 : :
2621 : : fail3:
2622 : : EFSYS_PROBE(fail3);
2623 : : fail2:
2624 : : EFSYS_PROBE(fail2);
2625 : : fail1:
2626 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
2627 : : return (rc);
2628 : : }
2629 : :
2630 : : __checkReturn efx_rc_t
2631 : 0 : efx_mae_mac_addr_alloc(
2632 : : __in efx_nic_t *enp,
2633 : : __in uint8_t addr_bytes[EFX_MAC_ADDR_LEN],
2634 : : __out efx_mae_mac_id_t *mac_idp)
2635 : : {
2636 : 0 : const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
2637 : : efx_mcdi_req_t req;
2638 : 0 : EFX_MCDI_DECLARE_BUF(payload,
2639 : : MC_CMD_MAE_MAC_ADDR_ALLOC_IN_LEN,
2640 : : MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_LEN);
2641 : : efx_mae_mac_id_t mac_id;
2642 : : efx_rc_t rc;
2643 : :
2644 : : EFX_STATIC_ASSERT(sizeof (mac_idp->id) ==
2645 : : MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_LEN);
2646 : :
2647 : : EFX_STATIC_ASSERT(EFX_MAE_RSRC_ID_INVALID ==
2648 : : MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL);
2649 : :
2650 [ # # ]: 0 : if (encp->enc_mae_supported == B_FALSE) {
2651 : : rc = ENOTSUP;
2652 : 0 : goto fail1;
2653 : : }
2654 : :
2655 [ # # ]: 0 : if (encp->enc_mae_aset_v2_supported == B_FALSE) {
2656 : : rc = ENOTSUP;
2657 : 0 : goto fail2;
2658 : : }
2659 : :
2660 : 0 : req.emr_cmd = MC_CMD_MAE_MAC_ADDR_ALLOC;
2661 : 0 : req.emr_in_buf = payload;
2662 : 0 : req.emr_in_length = MC_CMD_MAE_MAC_ADDR_ALLOC_IN_LEN;
2663 : 0 : req.emr_out_buf = payload;
2664 : 0 : req.emr_out_length = MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_LEN;
2665 : :
2666 : : memcpy(payload + MC_CMD_MAE_MAC_ADDR_ALLOC_IN_MAC_ADDR_OFST,
2667 : : addr_bytes, EFX_MAC_ADDR_LEN);
2668 : :
2669 : 0 : efx_mcdi_execute(enp, &req);
2670 : :
2671 [ # # ]: 0 : if (req.emr_rc != 0) {
2672 : : rc = req.emr_rc;
2673 : 0 : goto fail3;
2674 : : }
2675 : :
2676 [ # # ]: 0 : if (req.emr_out_length_used < MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_LEN) {
2677 : : rc = EMSGSIZE;
2678 : 0 : goto fail4;
2679 : : }
2680 : :
2681 : 0 : mac_id.id = MCDI_OUT_DWORD(req, MAE_MAC_ADDR_ALLOC_OUT_MAC_ID);
2682 [ # # ]: 0 : if (mac_id.id == EFX_MAE_RSRC_ID_INVALID) {
2683 : : rc = ENOENT;
2684 : 0 : goto fail5;
2685 : : }
2686 : :
2687 : 0 : mac_idp->id = mac_id.id;
2688 : :
2689 : 0 : return (0);
2690 : :
2691 : : fail5:
2692 : : EFSYS_PROBE(fail5);
2693 : : fail4:
2694 : : EFSYS_PROBE(fail4);
2695 : : fail3:
2696 : : EFSYS_PROBE(fail3);
2697 : : fail2:
2698 : : EFSYS_PROBE(fail2);
2699 : : fail1:
2700 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
2701 : : return (rc);
2702 : : }
2703 : :
2704 : : __checkReturn efx_rc_t
2705 : 0 : efx_mae_mac_addr_free(
2706 : : __in efx_nic_t *enp,
2707 : : __in const efx_mae_mac_id_t *mac_idp)
2708 : : {
2709 : 0 : const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
2710 : : efx_mcdi_req_t req;
2711 : 0 : EFX_MCDI_DECLARE_BUF(payload,
2712 : : MC_CMD_MAE_MAC_ADDR_FREE_IN_LEN(1),
2713 : : MC_CMD_MAE_MAC_ADDR_FREE_OUT_LEN(1));
2714 : : efx_rc_t rc;
2715 : :
2716 [ # # ]: 0 : if (encp->enc_mae_supported == B_FALSE) {
2717 : : rc = ENOTSUP;
2718 : 0 : goto fail1;
2719 : : }
2720 : :
2721 [ # # ]: 0 : if (encp->enc_mae_aset_v2_supported == B_FALSE) {
2722 : : rc = ENOTSUP;
2723 : 0 : goto fail2;
2724 : : }
2725 : :
2726 : 0 : req.emr_cmd = MC_CMD_MAE_MAC_ADDR_FREE;
2727 : 0 : req.emr_in_buf = payload;
2728 : 0 : req.emr_in_length = MC_CMD_MAE_MAC_ADDR_FREE_IN_LEN(1);
2729 : 0 : req.emr_out_buf = payload;
2730 : 0 : req.emr_out_length = MC_CMD_MAE_MAC_ADDR_FREE_OUT_LEN(1);
2731 : :
2732 : 0 : MCDI_IN_SET_DWORD(req, MAE_MAC_ADDR_FREE_IN_MAC_ID, mac_idp->id);
2733 : :
2734 : 0 : efx_mcdi_execute(enp, &req);
2735 : :
2736 [ # # ]: 0 : if (req.emr_rc != 0) {
2737 : : rc = req.emr_rc;
2738 : 0 : goto fail3;
2739 : : }
2740 : :
2741 [ # # ]: 0 : if (req.emr_out_length_used < MC_CMD_MAE_MAC_ADDR_FREE_OUT_LEN(1)) {
2742 : : rc = EMSGSIZE;
2743 : 0 : goto fail4;
2744 : : }
2745 : :
2746 : 0 : if (MCDI_OUT_DWORD(req, MAE_MAC_ADDR_FREE_OUT_FREED_MAC_ID) !=
2747 [ # # ]: 0 : mac_idp->id) {
2748 : : /* Firmware failed to remove the MAC address entry. */
2749 : : rc = EAGAIN;
2750 : 0 : goto fail5;
2751 : : }
2752 : :
2753 : : return (0);
2754 : :
2755 : : fail5:
2756 : : EFSYS_PROBE(fail5);
2757 : : fail4:
2758 : : EFSYS_PROBE(fail4);
2759 : : fail3:
2760 : : EFSYS_PROBE(fail3);
2761 : : fail2:
2762 : : EFSYS_PROBE(fail2);
2763 : : fail1:
2764 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
2765 : : return (rc);
2766 : : }
2767 : :
2768 : : __checkReturn efx_rc_t
2769 : 0 : efx_mae_action_set_fill_in_dst_mac_id(
2770 : : __in efx_mae_actions_t *spec,
2771 : : __in const efx_mae_mac_id_t *mac_idp)
2772 : : {
2773 : : efx_rc_t rc;
2774 : :
2775 [ # # ]: 0 : if ((spec->ema_actions & (1U << EFX_MAE_ACTION_SET_DST_MAC)) == 0) {
2776 : : /*
2777 : : * The caller has not intended to have this action originally,
2778 : : * hence, they cannot indicate the MAC address entry ID.
2779 : : */
2780 : : rc = EINVAL;
2781 : 0 : goto fail1;
2782 : : }
2783 : :
2784 [ # # ]: 0 : if (spec->ema_rsrc.emar_dst_mac_id.id != EFX_MAE_RSRC_ID_INVALID) {
2785 : : /* An attempt to indicate the MAC address entry ID twice. */
2786 : : rc = EINVAL;
2787 : 0 : goto fail2;
2788 : : }
2789 : :
2790 [ # # ]: 0 : if (mac_idp->id == EFX_MAE_RSRC_ID_INVALID) {
2791 : : rc = EINVAL;
2792 : 0 : goto fail3;
2793 : : }
2794 : :
2795 : 0 : spec->ema_rsrc.emar_dst_mac_id.id = mac_idp->id;
2796 : :
2797 : 0 : return (0);
2798 : :
2799 : : fail3:
2800 : : EFSYS_PROBE(fail3);
2801 : 0 : fail2:
2802 : : EFSYS_PROBE(fail2);
2803 : 0 : fail1:
2804 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
2805 : : return (rc);
2806 : : }
2807 : :
2808 : : __checkReturn efx_rc_t
2809 : 0 : efx_mae_action_set_fill_in_src_mac_id(
2810 : : __in efx_mae_actions_t *spec,
2811 : : __in const efx_mae_mac_id_t *mac_idp)
2812 : : {
2813 : : efx_rc_t rc;
2814 : :
2815 [ # # ]: 0 : if ((spec->ema_actions & (1U << EFX_MAE_ACTION_SET_SRC_MAC)) == 0) {
2816 : : /*
2817 : : * The caller has not intended to have this action originally,
2818 : : * hence, they cannot indicate the MAC address entry ID.
2819 : : */
2820 : : rc = EINVAL;
2821 : 0 : goto fail1;
2822 : : }
2823 : :
2824 [ # # ]: 0 : if (spec->ema_rsrc.emar_src_mac_id.id != EFX_MAE_RSRC_ID_INVALID) {
2825 : : /* An attempt to indicate the MAC address entry ID twice. */
2826 : : rc = EINVAL;
2827 : 0 : goto fail2;
2828 : : }
2829 : :
2830 [ # # ]: 0 : if (mac_idp->id == EFX_MAE_RSRC_ID_INVALID) {
2831 : : rc = EINVAL;
2832 : 0 : goto fail3;
2833 : : }
2834 : :
2835 : 0 : spec->ema_rsrc.emar_src_mac_id.id = mac_idp->id;
2836 : :
2837 : 0 : return (0);
2838 : :
2839 : : fail3:
2840 : : EFSYS_PROBE(fail3);
2841 : 0 : fail2:
2842 : : EFSYS_PROBE(fail2);
2843 : 0 : fail1:
2844 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
2845 : : return (rc);
2846 : : }
2847 : :
2848 : : __checkReturn efx_rc_t
2849 : 0 : efx_mae_encap_header_alloc(
2850 : : __in efx_nic_t *enp,
2851 : : __in efx_tunnel_protocol_t encap_type,
2852 : : __in_bcount(header_size) uint8_t *header_data,
2853 : : __in size_t header_size,
2854 : : __out efx_mae_eh_id_t *eh_idp)
2855 : : {
2856 : 0 : const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
2857 : : efx_mcdi_req_t req;
2858 : 0 : EFX_MCDI_DECLARE_BUF(payload,
2859 : : MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_LENMAX_MCDI2,
2860 : : MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_LEN);
2861 : : uint32_t encap_type_mcdi;
2862 : : efx_mae_eh_id_t eh_id;
2863 : : efx_rc_t rc;
2864 : :
2865 : : EFX_STATIC_ASSERT(sizeof (eh_idp->id) ==
2866 : : MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID_LEN);
2867 : :
2868 : : EFX_STATIC_ASSERT(EFX_MAE_RSRC_ID_INVALID ==
2869 : : MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID_NULL);
2870 : :
2871 [ # # ]: 0 : if (encp->enc_mae_supported == B_FALSE) {
2872 : : rc = ENOTSUP;
2873 : 0 : goto fail1;
2874 : : }
2875 : :
2876 : : switch (encap_type) {
2877 : : case EFX_TUNNEL_PROTOCOL_NONE:
2878 : : encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_NONE;
2879 : : break;
2880 : : case EFX_TUNNEL_PROTOCOL_VXLAN:
2881 : : encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_VXLAN;
2882 : : break;
2883 : : case EFX_TUNNEL_PROTOCOL_GENEVE:
2884 : : encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_GENEVE;
2885 : : break;
2886 : : case EFX_TUNNEL_PROTOCOL_NVGRE:
2887 : : encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_NVGRE;
2888 : : break;
2889 : 0 : default:
2890 : : rc = ENOTSUP;
2891 : 0 : goto fail2;
2892 : : }
2893 : :
2894 [ # # ]: 0 : if (header_size >
2895 : : MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_MAXNUM_MCDI2) {
2896 : : rc = EINVAL;
2897 : 0 : goto fail3;
2898 : : }
2899 : :
2900 : 0 : req.emr_cmd = MC_CMD_MAE_ENCAP_HEADER_ALLOC;
2901 : 0 : req.emr_in_buf = payload;
2902 : 0 : req.emr_in_length = MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_LEN(header_size);
2903 : 0 : req.emr_out_buf = payload;
2904 : 0 : req.emr_out_length = MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_LEN;
2905 : :
2906 : 0 : MCDI_IN_SET_DWORD(req,
2907 : : MAE_ENCAP_HEADER_ALLOC_IN_ENCAP_TYPE, encap_type_mcdi);
2908 : :
2909 : : memcpy(payload + MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_OFST,
2910 : : header_data, header_size);
2911 : :
2912 : 0 : efx_mcdi_execute(enp, &req);
2913 : :
2914 [ # # ]: 0 : if (req.emr_rc != 0) {
2915 : : rc = req.emr_rc;
2916 : 0 : goto fail4;
2917 : : }
2918 : :
2919 [ # # ]: 0 : if (req.emr_out_length_used < MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_LEN) {
2920 : : rc = EMSGSIZE;
2921 : 0 : goto fail5;
2922 : : }
2923 : :
2924 : 0 : eh_id.id = MCDI_OUT_DWORD(req,
2925 : : MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID);
2926 : :
2927 [ # # ]: 0 : if (eh_id.id == EFX_MAE_RSRC_ID_INVALID) {
2928 : : rc = ENOENT;
2929 : 0 : goto fail6;
2930 : : }
2931 : :
2932 : 0 : eh_idp->id = eh_id.id;
2933 : :
2934 : 0 : return (0);
2935 : :
2936 : : fail6:
2937 : : EFSYS_PROBE(fail6);
2938 : : fail5:
2939 : : EFSYS_PROBE(fail5);
2940 : : fail4:
2941 : : EFSYS_PROBE(fail4);
2942 : : fail3:
2943 : : EFSYS_PROBE(fail3);
2944 : : fail2:
2945 : : EFSYS_PROBE(fail2);
2946 : : fail1:
2947 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
2948 : : return (rc);
2949 : : }
2950 : :
2951 : : __checkReturn efx_rc_t
2952 : 0 : efx_mae_encap_header_update(
2953 : : __in efx_nic_t *enp,
2954 : : __in efx_mae_eh_id_t *eh_idp,
2955 : : __in efx_tunnel_protocol_t encap_type,
2956 : : __in_bcount(header_size) const uint8_t *header_data,
2957 : : __in size_t header_size)
2958 : : {
2959 : 0 : const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
2960 : : efx_mcdi_req_t req;
2961 : 0 : EFX_MCDI_DECLARE_BUF(payload,
2962 : : MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_LENMAX_MCDI2,
2963 : : MC_CMD_MAE_ENCAP_HEADER_UPDATE_OUT_LEN);
2964 : : uint32_t encap_type_mcdi;
2965 : : efx_rc_t rc;
2966 : :
2967 [ # # ]: 0 : if (encp->enc_mae_supported == B_FALSE) {
2968 : : rc = ENOTSUP;
2969 : 0 : goto fail1;
2970 : : }
2971 : :
2972 : : switch (encap_type) {
2973 : : case EFX_TUNNEL_PROTOCOL_NONE:
2974 : : encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_NONE;
2975 : : break;
2976 : : case EFX_TUNNEL_PROTOCOL_VXLAN:
2977 : : encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_VXLAN;
2978 : : break;
2979 : : case EFX_TUNNEL_PROTOCOL_GENEVE:
2980 : : encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_GENEVE;
2981 : : break;
2982 : : case EFX_TUNNEL_PROTOCOL_NVGRE:
2983 : : encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_NVGRE;
2984 : : break;
2985 : 0 : default:
2986 : : rc = ENOTSUP;
2987 : 0 : goto fail2;
2988 : : }
2989 : :
2990 [ # # ]: 0 : if (header_size >
2991 : : MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_HDR_DATA_MAXNUM_MCDI2) {
2992 : : rc = EINVAL;
2993 : 0 : goto fail3;
2994 : : }
2995 : :
2996 : 0 : req.emr_cmd = MC_CMD_MAE_ENCAP_HEADER_UPDATE;
2997 : 0 : req.emr_in_buf = payload;
2998 : 0 : req.emr_in_length = MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_LEN(header_size);
2999 : 0 : req.emr_out_buf = payload;
3000 : 0 : req.emr_out_length = MC_CMD_MAE_ENCAP_HEADER_UPDATE_OUT_LEN;
3001 : :
3002 : 0 : MCDI_IN_SET_DWORD(req,
3003 : : MAE_ENCAP_HEADER_UPDATE_IN_EH_ID, eh_idp->id);
3004 : :
3005 : 0 : MCDI_IN_SET_DWORD(req,
3006 : : MAE_ENCAP_HEADER_UPDATE_IN_ENCAP_TYPE, encap_type_mcdi);
3007 : :
3008 : : memcpy(MCDI_IN2(req, uint8_t, MAE_ENCAP_HEADER_UPDATE_IN_HDR_DATA),
3009 : : header_data, header_size);
3010 : :
3011 : 0 : efx_mcdi_execute(enp, &req);
3012 : :
3013 [ # # ]: 0 : if (req.emr_rc != 0) {
3014 : : rc = req.emr_rc;
3015 : 0 : goto fail4;
3016 : : }
3017 : :
3018 : : return (0);
3019 : :
3020 : : fail4:
3021 : : EFSYS_PROBE(fail4);
3022 : : fail3:
3023 : : EFSYS_PROBE(fail3);
3024 : : fail2:
3025 : : EFSYS_PROBE(fail2);
3026 : : fail1:
3027 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
3028 : : return (rc);
3029 : : }
3030 : :
3031 : : __checkReturn efx_rc_t
3032 : 0 : efx_mae_encap_header_free(
3033 : : __in efx_nic_t *enp,
3034 : : __in const efx_mae_eh_id_t *eh_idp)
3035 : : {
3036 : 0 : const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
3037 : : efx_mcdi_req_t req;
3038 : 0 : EFX_MCDI_DECLARE_BUF(payload,
3039 : : MC_CMD_MAE_ENCAP_HEADER_FREE_IN_LEN(1),
3040 : : MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_LEN(1));
3041 : : efx_rc_t rc;
3042 : :
3043 [ # # ]: 0 : if (encp->enc_mae_supported == B_FALSE) {
3044 : : rc = ENOTSUP;
3045 : 0 : goto fail1;
3046 : : }
3047 : :
3048 : 0 : req.emr_cmd = MC_CMD_MAE_ENCAP_HEADER_FREE;
3049 : 0 : req.emr_in_buf = payload;
3050 : 0 : req.emr_in_length = MC_CMD_MAE_ENCAP_HEADER_FREE_IN_LEN(1);
3051 : 0 : req.emr_out_buf = payload;
3052 : 0 : req.emr_out_length = MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_LEN(1);
3053 : :
3054 : 0 : MCDI_IN_SET_DWORD(req, MAE_ENCAP_HEADER_FREE_IN_EH_ID, eh_idp->id);
3055 : :
3056 : 0 : efx_mcdi_execute(enp, &req);
3057 : :
3058 [ # # ]: 0 : if (req.emr_rc != 0) {
3059 : : rc = req.emr_rc;
3060 : 0 : goto fail2;
3061 : : }
3062 : :
3063 : 0 : if (MCDI_OUT_DWORD(req, MAE_ENCAP_HEADER_FREE_OUT_FREED_EH_ID) !=
3064 [ # # ]: 0 : eh_idp->id) {
3065 : : /* Firmware failed to remove the encap. header. */
3066 : : rc = EAGAIN;
3067 : 0 : goto fail3;
3068 : : }
3069 : :
3070 : : return (0);
3071 : :
3072 : : fail3:
3073 : : EFSYS_PROBE(fail3);
3074 : : fail2:
3075 : : EFSYS_PROBE(fail2);
3076 : : fail1:
3077 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
3078 : : return (rc);
3079 : : }
3080 : :
3081 : : __checkReturn efx_rc_t
3082 : 0 : efx_mae_action_set_fill_in_eh_id(
3083 : : __in efx_mae_actions_t *spec,
3084 : : __in const efx_mae_eh_id_t *eh_idp)
3085 : : {
3086 : : efx_rc_t rc;
3087 : :
3088 [ # # ]: 0 : if ((spec->ema_actions & (1U << EFX_MAE_ACTION_ENCAP)) == 0) {
3089 : : /*
3090 : : * The caller has not intended to have action ENCAP originally,
3091 : : * hence, this attempt to indicate encap. header ID is invalid.
3092 : : */
3093 : : rc = EINVAL;
3094 : 0 : goto fail1;
3095 : : }
3096 : :
3097 [ # # ]: 0 : if (spec->ema_rsrc.emar_eh_id.id != EFX_MAE_RSRC_ID_INVALID) {
3098 : : /* The caller attempts to indicate encap. header ID twice. */
3099 : : rc = EINVAL;
3100 : 0 : goto fail2;
3101 : : }
3102 : :
3103 [ # # ]: 0 : if (eh_idp->id == EFX_MAE_RSRC_ID_INVALID) {
3104 : : rc = EINVAL;
3105 : 0 : goto fail3;
3106 : : }
3107 : :
3108 : 0 : spec->ema_rsrc.emar_eh_id.id = eh_idp->id;
3109 : :
3110 : 0 : return (0);
3111 : :
3112 : : fail3:
3113 : : EFSYS_PROBE(fail3);
3114 : 0 : fail2:
3115 : : EFSYS_PROBE(fail2);
3116 : 0 : fail1:
3117 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
3118 : : return (rc);
3119 : : }
3120 : :
3121 : : __checkReturn efx_rc_t
3122 : 0 : efx_mae_action_set_alloc(
3123 : : __in efx_nic_t *enp,
3124 : : __in const efx_mae_actions_t *spec,
3125 : : __out efx_mae_aset_id_t *aset_idp)
3126 : : {
3127 : 0 : const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
3128 : : efx_mcdi_req_t req;
3129 : 0 : EFX_MCDI_DECLARE_BUF(payload,
3130 : : MC_CMD_MAE_ACTION_SET_ALLOC_IN_LEN,
3131 : : MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN);
3132 : : efx_mae_aset_id_t aset_id;
3133 : : efx_rc_t rc;
3134 : :
3135 [ # # ]: 0 : if (encp->enc_mae_supported == B_FALSE) {
3136 : : rc = ENOTSUP;
3137 : 0 : goto fail1;
3138 : : }
3139 : :
3140 [ # # ]: 0 : if ((spec->ema_actions & (1U << EFX_MAE_ACTION_SET_DST_MAC)) != 0 &&
3141 [ # # ]: 0 : spec->ema_rsrc.emar_dst_mac_id.id == EFX_MAE_RSRC_ID_INVALID) {
3142 : : rc = EINVAL;
3143 : 0 : goto fail2;
3144 : : }
3145 : :
3146 [ # # ]: 0 : if ((spec->ema_actions & (1U << EFX_MAE_ACTION_SET_SRC_MAC)) != 0 &&
3147 [ # # ]: 0 : spec->ema_rsrc.emar_src_mac_id.id == EFX_MAE_RSRC_ID_INVALID) {
3148 : : rc = EINVAL;
3149 : 0 : goto fail3;
3150 : : }
3151 : :
3152 [ # # ]: 0 : if ((spec->ema_actions & (1U << EFX_MAE_ACTION_ENCAP)) != 0 &&
3153 [ # # ]: 0 : spec->ema_rsrc.emar_eh_id.id == EFX_MAE_RSRC_ID_INVALID) {
3154 : : rc = EINVAL;
3155 : 0 : goto fail4;
3156 : : }
3157 : :
3158 [ # # ]: 0 : if (spec->ema_n_count_actions == 1 &&
3159 [ # # ]: 0 : spec->ema_rsrc.emar_counter_id.id == EFX_MAE_RSRC_ID_INVALID) {
3160 : : rc = EINVAL;
3161 : 0 : goto fail5;
3162 : : }
3163 : :
3164 : 0 : req.emr_cmd = MC_CMD_MAE_ACTION_SET_ALLOC;
3165 : 0 : req.emr_in_buf = payload;
3166 : 0 : req.emr_in_length = MC_CMD_MAE_ACTION_SET_ALLOC_IN_LEN;
3167 : 0 : req.emr_out_buf = payload;
3168 : 0 : req.emr_out_length = MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN;
3169 : :
3170 : : /*
3171 : : * TODO: Remove these EFX_MAE_RSRC_ID_INVALID assignments once the
3172 : : * corresponding resource types are supported by the implementation.
3173 : : * Use proper resource ID assignments instead.
3174 : : */
3175 : 0 : MCDI_IN_SET_DWORD(req,
3176 : : MAE_ACTION_SET_ALLOC_IN_COUNTER_LIST_ID, EFX_MAE_RSRC_ID_INVALID);
3177 : :
3178 [ # # ]: 0 : if ((spec->ema_actions & (1U << EFX_MAE_ACTION_DECAP)) != 0) {
3179 : 0 : MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
3180 : : MAE_ACTION_SET_ALLOC_IN_DECAP, 1);
3181 : : }
3182 : :
3183 : 0 : MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
3184 : : MAE_ACTION_SET_ALLOC_IN_VLAN_POP, spec->ema_n_vlan_tags_to_pop);
3185 : :
3186 : 0 : MCDI_IN_SET_DWORD(req, MAE_ACTION_SET_ALLOC_IN_DST_MAC_ID,
3187 : : spec->ema_rsrc.emar_dst_mac_id.id);
3188 : :
3189 : 0 : MCDI_IN_SET_DWORD(req, MAE_ACTION_SET_ALLOC_IN_SRC_MAC_ID,
3190 : : spec->ema_rsrc.emar_src_mac_id.id);
3191 : :
3192 [ # # ]: 0 : if ((spec->ema_actions & (1U << EFX_MAE_ACTION_DECR_IP_TTL)) != 0) {
3193 : 0 : MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
3194 : : MAE_ACTION_SET_ALLOC_IN_DO_DECR_IP_TTL, 1);
3195 : : }
3196 : :
3197 [ # # ]: 0 : if ((spec->ema_actions & (1U << EFX_MAE_ACTION_NAT)) != 0) {
3198 : 0 : MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
3199 : : MAE_ACTION_SET_ALLOC_IN_DO_NAT, 1);
3200 : : }
3201 : :
3202 [ # # ]: 0 : if (spec->ema_n_vlan_tags_to_push > 0) {
3203 : : unsigned int outer_tag_idx;
3204 : :
3205 : 0 : MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
3206 : : MAE_ACTION_SET_ALLOC_IN_VLAN_PUSH,
3207 : : spec->ema_n_vlan_tags_to_push);
3208 : :
3209 [ # # ]: 0 : if (spec->ema_n_vlan_tags_to_push ==
3210 : : EFX_MAE_VLAN_PUSH_MAX_NTAGS) {
3211 : 0 : MCDI_IN_SET_WORD(req,
3212 : : MAE_ACTION_SET_ALLOC_IN_VLAN1_PROTO_BE,
3213 : : spec->ema_vlan_push_descs[0].emavp_tpid_be);
3214 : 0 : MCDI_IN_SET_WORD(req,
3215 : : MAE_ACTION_SET_ALLOC_IN_VLAN1_TCI_BE,
3216 : : spec->ema_vlan_push_descs[0].emavp_tci_be);
3217 : : }
3218 : :
3219 : 0 : outer_tag_idx = spec->ema_n_vlan_tags_to_push - 1;
3220 : :
3221 : 0 : MCDI_IN_SET_WORD(req, MAE_ACTION_SET_ALLOC_IN_VLAN0_PROTO_BE,
3222 : : spec->ema_vlan_push_descs[outer_tag_idx].emavp_tpid_be);
3223 : 0 : MCDI_IN_SET_WORD(req, MAE_ACTION_SET_ALLOC_IN_VLAN0_TCI_BE,
3224 : : spec->ema_vlan_push_descs[outer_tag_idx].emavp_tci_be);
3225 : : }
3226 : :
3227 : 0 : MCDI_IN_SET_DWORD(req, MAE_ACTION_SET_ALLOC_IN_ENCAP_HEADER_ID,
3228 : : spec->ema_rsrc.emar_eh_id.id);
3229 : 0 : MCDI_IN_SET_DWORD(req, MAE_ACTION_SET_ALLOC_IN_COUNTER_ID,
3230 : : spec->ema_rsrc.emar_counter_id.id);
3231 : :
3232 [ # # ]: 0 : if ((spec->ema_actions & (1U << EFX_MAE_ACTION_FLAG)) != 0) {
3233 : 0 : MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
3234 : : MAE_ACTION_SET_ALLOC_IN_FLAG, 1);
3235 : : }
3236 : :
3237 [ # # ]: 0 : if ((spec->ema_actions & (1U << EFX_MAE_ACTION_MARK)) != 0) {
3238 : 0 : MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
3239 : : MAE_ACTION_SET_ALLOC_IN_MARK, 1);
3240 : :
3241 : 0 : MCDI_IN_SET_DWORD(req,
3242 : : MAE_ACTION_SET_ALLOC_IN_MARK_VALUE, spec->ema_mark_value);
3243 : : }
3244 : :
3245 : 0 : MCDI_IN_SET_DWORD(req,
3246 : : MAE_ACTION_SET_ALLOC_IN_DELIVER, spec->ema_deliver_mport.sel);
3247 : :
3248 : 0 : efx_mcdi_execute(enp, &req);
3249 : :
3250 [ # # ]: 0 : if (req.emr_rc != 0) {
3251 : : rc = req.emr_rc;
3252 : 0 : goto fail6;
3253 : : }
3254 : :
3255 [ # # ]: 0 : if (req.emr_out_length_used < MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN) {
3256 : : rc = EMSGSIZE;
3257 : 0 : goto fail7;
3258 : : }
3259 : :
3260 : 0 : aset_id.id = MCDI_OUT_DWORD(req, MAE_ACTION_SET_ALLOC_OUT_AS_ID);
3261 [ # # ]: 0 : if (aset_id.id == EFX_MAE_RSRC_ID_INVALID) {
3262 : : rc = ENOENT;
3263 : 0 : goto fail8;
3264 : : }
3265 : :
3266 : 0 : aset_idp->id = aset_id.id;
3267 : :
3268 : 0 : return (0);
3269 : :
3270 : : fail8:
3271 : : EFSYS_PROBE(fail8);
3272 : : fail7:
3273 : : EFSYS_PROBE(fail7);
3274 : : fail6:
3275 : : EFSYS_PROBE(fail6);
3276 : : fail5:
3277 : : EFSYS_PROBE(fail5);
3278 : : fail4:
3279 : : EFSYS_PROBE(fail4);
3280 : : fail3:
3281 : : EFSYS_PROBE(fail3);
3282 : : fail2:
3283 : : EFSYS_PROBE(fail2);
3284 : : fail1:
3285 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
3286 : : return (rc);
3287 : : }
3288 : :
3289 : : __checkReturn unsigned int
3290 : 0 : efx_mae_action_set_get_nb_count(
3291 : : __in const efx_mae_actions_t *spec)
3292 : : {
3293 : 0 : return (spec->ema_n_count_actions);
3294 : : }
3295 : :
3296 : : __checkReturn efx_rc_t
3297 : 0 : efx_mae_action_set_fill_in_counter_id(
3298 : : __in efx_mae_actions_t *spec,
3299 : : __in const efx_counter_t *counter_idp)
3300 : : {
3301 : : efx_rc_t rc;
3302 : :
3303 [ # # ]: 0 : if ((spec->ema_actions & (1U << EFX_MAE_ACTION_COUNT)) == 0) {
3304 : : /*
3305 : : * Invalid to add counter ID if spec does not have COUNT action.
3306 : : */
3307 : : rc = EINVAL;
3308 : 0 : goto fail1;
3309 : : }
3310 : :
3311 [ # # ]: 0 : if (spec->ema_n_count_actions != 1) {
3312 : : /*
3313 : : * Having multiple COUNT actions in the spec requires a counter
3314 : : * list to be used. This API must only be used for a single
3315 : : * counter per spec. Turn down the request as inappropriate.
3316 : : */
3317 : : rc = EINVAL;
3318 : 0 : goto fail2;
3319 : : }
3320 : :
3321 [ # # ]: 0 : if (spec->ema_rsrc.emar_counter_id.id != EFX_MAE_RSRC_ID_INVALID) {
3322 : : /* The caller attempts to indicate counter ID twice. */
3323 : : rc = EALREADY;
3324 : 0 : goto fail3;
3325 : : }
3326 : :
3327 [ # # ]: 0 : if (counter_idp->id == EFX_MAE_RSRC_ID_INVALID) {
3328 : : rc = EINVAL;
3329 : 0 : goto fail4;
3330 : : }
3331 : :
3332 : 0 : spec->ema_rsrc.emar_counter_id.id = counter_idp->id;
3333 : :
3334 : 0 : return (0);
3335 : :
3336 : : fail4:
3337 : : EFSYS_PROBE(fail4);
3338 : : fail3:
3339 : : EFSYS_PROBE(fail3);
3340 : : fail2:
3341 : : EFSYS_PROBE(fail2);
3342 : : fail1:
3343 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
3344 : : return (rc);
3345 : : }
3346 : :
3347 : : void
3348 : 0 : efx_mae_action_set_clear_fw_rsrc_ids(
3349 : : __in efx_mae_actions_t *spec)
3350 : : {
3351 : 0 : spec->ema_rsrc.emar_dst_mac_id.id = EFX_MAE_RSRC_ID_INVALID;
3352 : 0 : spec->ema_rsrc.emar_src_mac_id.id = EFX_MAE_RSRC_ID_INVALID;
3353 : 0 : spec->ema_rsrc.emar_eh_id.id = EFX_MAE_RSRC_ID_INVALID;
3354 : 0 : spec->ema_rsrc.emar_counter_id.id = EFX_MAE_RSRC_ID_INVALID;
3355 : 0 : }
3356 : :
3357 : : __checkReturn efx_rc_t
3358 : 0 : efx_mae_counters_alloc_type(
3359 : : __in efx_nic_t *enp,
3360 : : __in efx_counter_type_t type,
3361 : : __in uint32_t n_counters,
3362 : : __out uint32_t *n_allocatedp,
3363 : : __out_ecount(n_counters) efx_counter_t *countersp,
3364 : : __out_opt uint32_t *gen_countp)
3365 : : {
3366 : 0 : EFX_MCDI_DECLARE_BUF(payload,
3367 : : MC_CMD_MAE_COUNTER_ALLOC_V2_IN_LEN,
3368 : : MC_CMD_MAE_COUNTER_ALLOC_OUT_LENMAX_MCDI2);
3369 : 0 : efx_mae_t *maep = enp->en_maep;
3370 : : uint32_t max_n_counters;
3371 : : uint32_t n_allocated;
3372 : : efx_mcdi_req_t req;
3373 : : unsigned int i;
3374 : : efx_rc_t rc;
3375 : :
3376 : : EFX_STATIC_ASSERT(EFX_COUNTER_TYPE_ACTION == MAE_COUNTER_TYPE_AR);
3377 : : EFX_STATIC_ASSERT(EFX_COUNTER_TYPE_CONNTRACK == MAE_COUNTER_TYPE_CT);
3378 : :
3379 [ # # # ]: 0 : switch (type) {
3380 : 0 : case EFX_COUNTER_TYPE_ACTION:
3381 : 0 : max_n_counters = maep->em_max_n_action_counters;
3382 : 0 : break;
3383 : 0 : case EFX_COUNTER_TYPE_CONNTRACK:
3384 : 0 : max_n_counters = maep->em_max_n_conntrack_counters;
3385 : 0 : break;
3386 : 0 : default:
3387 : : rc = EINVAL;
3388 : 0 : goto fail1;
3389 : : }
3390 : :
3391 [ # # ]: 0 : if (n_counters > max_n_counters ||
3392 [ # # ]: 0 : n_counters < MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MINNUM ||
3393 : : n_counters > MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MAXNUM_MCDI2) {
3394 : : rc = EINVAL;
3395 : 0 : goto fail2;
3396 : : }
3397 : :
3398 : 0 : req.emr_cmd = MC_CMD_MAE_COUNTER_ALLOC;
3399 : 0 : req.emr_in_buf = payload;
3400 : 0 : req.emr_in_length = MC_CMD_MAE_COUNTER_ALLOC_V2_IN_LEN;
3401 : 0 : req.emr_out_buf = payload;
3402 : 0 : req.emr_out_length = MC_CMD_MAE_COUNTER_ALLOC_OUT_LEN(n_counters);
3403 : :
3404 : 0 : MCDI_IN_SET_DWORD(req, MAE_COUNTER_ALLOC_IN_REQUESTED_COUNT,
3405 : : n_counters);
3406 : :
3407 : 0 : MCDI_IN_SET_DWORD(req, MAE_COUNTER_ALLOC_V2_IN_COUNTER_TYPE, type);
3408 : :
3409 : 0 : efx_mcdi_execute(enp, &req);
3410 : :
3411 [ # # ]: 0 : if (req.emr_rc != 0) {
3412 : : rc = req.emr_rc;
3413 : 0 : goto fail3;
3414 : : }
3415 : :
3416 [ # # ]: 0 : if (req.emr_out_length_used < MC_CMD_MAE_COUNTER_ALLOC_OUT_LENMIN) {
3417 : : rc = EMSGSIZE;
3418 : 0 : goto fail4;
3419 : : }
3420 : :
3421 : 0 : n_allocated = MCDI_OUT_DWORD(req,
3422 : : MAE_COUNTER_ALLOC_OUT_COUNTER_ID_COUNT);
3423 [ # # ]: 0 : if (n_allocated < MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MINNUM) {
3424 : : rc = EFAULT;
3425 : 0 : goto fail5;
3426 : : }
3427 : :
3428 [ # # ]: 0 : for (i = 0; i < n_allocated; i++) {
3429 : 0 : countersp[i].id = MCDI_OUT_INDEXED_DWORD(req,
3430 : : MAE_COUNTER_ALLOC_OUT_COUNTER_ID, i);
3431 : : }
3432 : :
3433 [ # # ]: 0 : if (gen_countp != NULL) {
3434 : 0 : *gen_countp = MCDI_OUT_DWORD(req,
3435 : : MAE_COUNTER_ALLOC_OUT_GENERATION_COUNT);
3436 : : }
3437 : :
3438 : 0 : *n_allocatedp = n_allocated;
3439 : :
3440 : 0 : return (0);
3441 : :
3442 : : fail5:
3443 : : EFSYS_PROBE(fail5);
3444 : : fail4:
3445 : : EFSYS_PROBE(fail4);
3446 : : fail3:
3447 : : EFSYS_PROBE(fail3);
3448 : : fail2:
3449 : : EFSYS_PROBE(fail2);
3450 : : fail1:
3451 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
3452 : :
3453 : : return (rc);
3454 : : }
3455 : :
3456 : : __checkReturn efx_rc_t
3457 : 0 : efx_mae_counters_alloc(
3458 : : __in efx_nic_t *enp,
3459 : : __in uint32_t n_counters,
3460 : : __out uint32_t *n_allocatedp,
3461 : : __out_ecount(n_counters) efx_counter_t *countersp,
3462 : : __out_opt uint32_t *gen_countp)
3463 : : {
3464 : : efx_rc_t rc;
3465 : :
3466 : 0 : rc = efx_mae_counters_alloc_type(enp, EFX_COUNTER_TYPE_ACTION,
3467 : : n_counters, n_allocatedp,
3468 : : countersp, gen_countp);
3469 [ # # ]: 0 : if (rc != 0)
3470 : 0 : goto fail1;
3471 : :
3472 : : return (0);
3473 : :
3474 : : fail1:
3475 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
3476 : 0 : return (rc);
3477 : : }
3478 : :
3479 : : __checkReturn efx_rc_t
3480 : 0 : efx_mae_counters_free_type(
3481 : : __in efx_nic_t *enp,
3482 : : __in efx_counter_type_t type,
3483 : : __in uint32_t n_counters,
3484 : : __out uint32_t *n_freedp,
3485 : : __in_ecount(n_counters) const efx_counter_t *countersp,
3486 : : __out_opt uint32_t *gen_countp)
3487 : : {
3488 : 0 : EFX_MCDI_DECLARE_BUF(payload,
3489 : : MC_CMD_MAE_COUNTER_FREE_V2_IN_LEN,
3490 : : MC_CMD_MAE_COUNTER_FREE_OUT_LENMAX_MCDI2);
3491 : 0 : efx_mae_t *maep = enp->en_maep;
3492 : : uint32_t max_n_counters;
3493 : : efx_mcdi_req_t req;
3494 : : uint32_t n_freed;
3495 : : unsigned int i;
3496 : : efx_rc_t rc;
3497 : :
3498 [ # # # ]: 0 : switch (type) {
3499 : 0 : case EFX_COUNTER_TYPE_ACTION:
3500 : 0 : max_n_counters = maep->em_max_n_action_counters;
3501 : 0 : break;
3502 : 0 : case EFX_COUNTER_TYPE_CONNTRACK:
3503 : 0 : max_n_counters = maep->em_max_n_conntrack_counters;
3504 : 0 : break;
3505 : 0 : default:
3506 : : rc = EINVAL;
3507 : 0 : goto fail1;
3508 : : }
3509 : :
3510 [ # # ]: 0 : if (n_counters > max_n_counters ||
3511 [ # # ]: 0 : n_counters < MC_CMD_MAE_COUNTER_FREE_V2_IN_FREE_COUNTER_ID_MINNUM ||
3512 : : n_counters >
3513 : : MC_CMD_MAE_COUNTER_FREE_V2_IN_FREE_COUNTER_ID_MAXNUM_MCDI2) {
3514 : : rc = EINVAL;
3515 : 0 : goto fail2;
3516 : : }
3517 : :
3518 : 0 : req.emr_cmd = MC_CMD_MAE_COUNTER_FREE;
3519 : 0 : req.emr_in_buf = payload;
3520 : 0 : req.emr_in_length = MC_CMD_MAE_COUNTER_FREE_V2_IN_LEN;
3521 : 0 : req.emr_out_buf = payload;
3522 : 0 : req.emr_out_length = MC_CMD_MAE_COUNTER_FREE_OUT_LEN(n_counters);
3523 : :
3524 [ # # ]: 0 : for (i = 0; i < n_counters; i++) {
3525 : 0 : MCDI_IN_SET_INDEXED_DWORD(req,
3526 : : MAE_COUNTER_FREE_IN_FREE_COUNTER_ID, i, countersp[i].id);
3527 : : }
3528 : 0 : MCDI_IN_SET_DWORD(req, MAE_COUNTER_FREE_IN_COUNTER_ID_COUNT,
3529 : : n_counters);
3530 : :
3531 : 0 : MCDI_IN_SET_DWORD(req, MAE_COUNTER_FREE_V2_IN_COUNTER_TYPE, type);
3532 : :
3533 : 0 : efx_mcdi_execute(enp, &req);
3534 : :
3535 [ # # ]: 0 : if (req.emr_rc != 0) {
3536 : : rc = req.emr_rc;
3537 : 0 : goto fail3;
3538 : : }
3539 : :
3540 [ # # ]: 0 : if (req.emr_out_length_used < MC_CMD_MAE_COUNTER_FREE_OUT_LENMIN) {
3541 : : rc = EMSGSIZE;
3542 : 0 : goto fail4;
3543 : : }
3544 : :
3545 : 0 : n_freed = MCDI_OUT_DWORD(req, MAE_COUNTER_FREE_OUT_COUNTER_ID_COUNT);
3546 : :
3547 [ # # ]: 0 : if (n_freed < MC_CMD_MAE_COUNTER_FREE_OUT_FREED_COUNTER_ID_MINNUM) {
3548 : : rc = EFAULT;
3549 : 0 : goto fail5;
3550 : : }
3551 : :
3552 [ # # ]: 0 : if (gen_countp != NULL) {
3553 : 0 : *gen_countp = MCDI_OUT_DWORD(req,
3554 : : MAE_COUNTER_FREE_OUT_GENERATION_COUNT);
3555 : : }
3556 : :
3557 : 0 : *n_freedp = n_freed;
3558 : :
3559 : 0 : return (0);
3560 : :
3561 : : fail5:
3562 : : EFSYS_PROBE(fail5);
3563 : : fail4:
3564 : : EFSYS_PROBE(fail4);
3565 : : fail3:
3566 : : EFSYS_PROBE(fail3);
3567 : : fail2:
3568 : : EFSYS_PROBE(fail2);
3569 : : fail1:
3570 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
3571 : :
3572 : : return (rc);
3573 : : }
3574 : :
3575 : : __checkReturn efx_rc_t
3576 : 0 : efx_mae_counters_free(
3577 : : __in efx_nic_t *enp,
3578 : : __in uint32_t n_counters,
3579 : : __out uint32_t *n_freedp,
3580 : : __in_ecount(n_counters) const efx_counter_t *countersp,
3581 : : __out_opt uint32_t *gen_countp)
3582 : : {
3583 : : efx_rc_t rc;
3584 : :
3585 : 0 : rc = efx_mae_counters_free_type(enp, EFX_COUNTER_TYPE_ACTION,
3586 : : n_counters, n_freedp,
3587 : : countersp, gen_countp);
3588 [ # # ]: 0 : if (rc != 0)
3589 : 0 : goto fail1;
3590 : :
3591 : : return (0);
3592 : :
3593 : : fail1:
3594 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
3595 : 0 : return (rc);
3596 : : }
3597 : :
3598 : : __checkReturn efx_rc_t
3599 : 0 : efx_mae_counters_stream_start(
3600 : : __in efx_nic_t *enp,
3601 : : __in uint16_t rxq_id,
3602 : : __in uint16_t packet_size,
3603 : : __in uint32_t flags_in,
3604 : : __out uint32_t *flags_out)
3605 : : {
3606 : : efx_mcdi_req_t req;
3607 : : EFX_MCDI_DECLARE_BUF(payload,
3608 : : MC_CMD_MAE_COUNTERS_STREAM_START_V2_IN_LEN,
3609 : : MC_CMD_MAE_COUNTERS_STREAM_START_OUT_LEN);
3610 : 0 : struct efx_mae_s *maep = enp->en_maep;
3611 : : uint32_t counter_types;
3612 : : efx_rc_t rc;
3613 : :
3614 : : EFX_STATIC_ASSERT(EFX_MAE_COUNTERS_STREAM_IN_ZERO_SQUASH_DISABLE ==
3615 : : 1U << MC_CMD_MAE_COUNTERS_STREAM_START_IN_ZERO_SQUASH_DISABLE_LBN);
3616 : :
3617 : : EFX_STATIC_ASSERT(EFX_MAE_COUNTERS_STREAM_OUT_USES_CREDITS ==
3618 : : 1U << MC_CMD_MAE_COUNTERS_STREAM_START_OUT_USES_CREDITS_LBN);
3619 : :
3620 : 0 : req.emr_cmd = MC_CMD_MAE_COUNTERS_STREAM_START;
3621 : 0 : req.emr_in_buf = payload;
3622 : 0 : req.emr_in_length = MC_CMD_MAE_COUNTERS_STREAM_START_V2_IN_LEN;
3623 : 0 : req.emr_out_buf = payload;
3624 : 0 : req.emr_out_length = MC_CMD_MAE_COUNTERS_STREAM_START_OUT_LEN;
3625 : :
3626 : 0 : MCDI_IN_SET_WORD(req, MAE_COUNTERS_STREAM_START_IN_QID, rxq_id);
3627 : 0 : MCDI_IN_SET_WORD(req, MAE_COUNTERS_STREAM_START_IN_PACKET_SIZE,
3628 : : packet_size);
3629 : 0 : MCDI_IN_SET_DWORD(req, MAE_COUNTERS_STREAM_START_IN_FLAGS, flags_in);
3630 : :
3631 : : counter_types = (1U << MAE_COUNTER_TYPE_AR);
3632 : :
3633 [ # # ]: 0 : if (maep->em_max_n_conntrack_counters != 0)
3634 : : counter_types |= (1U << MAE_COUNTER_TYPE_CT);
3635 : :
3636 : 0 : MCDI_IN_SET_DWORD(req,
3637 : : MAE_COUNTERS_STREAM_START_V2_IN_COUNTER_TYPES_MASK,
3638 : : counter_types);
3639 : :
3640 : 0 : efx_mcdi_execute(enp, &req);
3641 : :
3642 [ # # ]: 0 : if (req.emr_rc != 0) {
3643 : : rc = req.emr_rc;
3644 : 0 : goto fail1;
3645 : : }
3646 : :
3647 [ # # ]: 0 : if (req.emr_out_length_used <
3648 : : MC_CMD_MAE_COUNTERS_STREAM_START_OUT_LEN) {
3649 : : rc = EMSGSIZE;
3650 : 0 : goto fail2;
3651 : : }
3652 : :
3653 : 0 : *flags_out = MCDI_OUT_DWORD(req, MAE_COUNTERS_STREAM_START_OUT_FLAGS);
3654 : :
3655 : 0 : return (0);
3656 : :
3657 : : fail2:
3658 : : EFSYS_PROBE(fail2);
3659 : : fail1:
3660 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
3661 : :
3662 : : return (rc);
3663 : : }
3664 : :
3665 : : __checkReturn efx_rc_t
3666 : 0 : efx_mae_counters_stream_stop(
3667 : : __in efx_nic_t *enp,
3668 : : __in uint16_t rxq_id,
3669 : : __out_opt uint32_t *gen_countp)
3670 : : {
3671 : : efx_mcdi_req_t req;
3672 : 0 : EFX_MCDI_DECLARE_BUF(payload, MC_CMD_MAE_COUNTERS_STREAM_STOP_IN_LEN,
3673 : : MC_CMD_MAE_COUNTERS_STREAM_STOP_OUT_LEN);
3674 : : efx_rc_t rc;
3675 : :
3676 : 0 : req.emr_cmd = MC_CMD_MAE_COUNTERS_STREAM_STOP;
3677 : 0 : req.emr_in_buf = payload;
3678 : 0 : req.emr_in_length = MC_CMD_MAE_COUNTERS_STREAM_STOP_IN_LEN;
3679 : 0 : req.emr_out_buf = payload;
3680 : 0 : req.emr_out_length = MC_CMD_MAE_COUNTERS_STREAM_STOP_OUT_LEN;
3681 : :
3682 : 0 : MCDI_IN_SET_WORD(req, MAE_COUNTERS_STREAM_STOP_IN_QID, rxq_id);
3683 : :
3684 : 0 : efx_mcdi_execute(enp, &req);
3685 : :
3686 [ # # ]: 0 : if (req.emr_rc != 0) {
3687 : : rc = req.emr_rc;
3688 : 0 : goto fail1;
3689 : : }
3690 : :
3691 [ # # ]: 0 : if (req.emr_out_length_used <
3692 : : MC_CMD_MAE_COUNTERS_STREAM_STOP_OUT_LEN) {
3693 : : rc = EMSGSIZE;
3694 : 0 : goto fail2;
3695 : : }
3696 : :
3697 [ # # ]: 0 : if (gen_countp != NULL) {
3698 : 0 : *gen_countp = MCDI_OUT_DWORD(req,
3699 : : MAE_COUNTERS_STREAM_STOP_OUT_GENERATION_COUNT);
3700 : : }
3701 : :
3702 : : return (0);
3703 : :
3704 : : fail2:
3705 : : EFSYS_PROBE(fail2);
3706 : : fail1:
3707 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
3708 : :
3709 : : return (rc);
3710 : : }
3711 : :
3712 : : __checkReturn efx_rc_t
3713 : 0 : efx_mae_counters_stream_give_credits(
3714 : : __in efx_nic_t *enp,
3715 : : __in uint32_t n_credits)
3716 : : {
3717 : : efx_mcdi_req_t req;
3718 : 0 : EFX_MCDI_DECLARE_BUF(payload,
3719 : : MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS_IN_LEN,
3720 : : MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS_OUT_LEN);
3721 : : efx_rc_t rc;
3722 : :
3723 : 0 : req.emr_cmd = MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS;
3724 : 0 : req.emr_in_buf = payload;
3725 : 0 : req.emr_in_length = MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS_IN_LEN;
3726 : 0 : req.emr_out_buf = payload;
3727 : 0 : req.emr_out_length = MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS_OUT_LEN;
3728 : :
3729 : 0 : MCDI_IN_SET_DWORD(req, MAE_COUNTERS_STREAM_GIVE_CREDITS_IN_NUM_CREDITS,
3730 : : n_credits);
3731 : :
3732 : 0 : efx_mcdi_execute(enp, &req);
3733 : :
3734 [ # # ]: 0 : if (req.emr_rc != 0) {
3735 : : rc = req.emr_rc;
3736 : 0 : goto fail1;
3737 : : }
3738 : :
3739 : : return (0);
3740 : :
3741 : : fail1:
3742 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
3743 : :
3744 : 0 : return (rc);
3745 : : }
3746 : :
3747 : : __checkReturn efx_rc_t
3748 : 0 : efx_mae_action_set_free(
3749 : : __in efx_nic_t *enp,
3750 : : __in const efx_mae_aset_id_t *aset_idp)
3751 : : {
3752 : 0 : const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
3753 : : efx_mcdi_req_t req;
3754 : 0 : EFX_MCDI_DECLARE_BUF(payload,
3755 : : MC_CMD_MAE_ACTION_SET_FREE_IN_LEN(1),
3756 : : MC_CMD_MAE_ACTION_SET_FREE_OUT_LEN(1));
3757 : : efx_rc_t rc;
3758 : :
3759 [ # # ]: 0 : if (encp->enc_mae_supported == B_FALSE) {
3760 : : rc = ENOTSUP;
3761 : 0 : goto fail1;
3762 : : }
3763 : :
3764 : 0 : req.emr_cmd = MC_CMD_MAE_ACTION_SET_FREE;
3765 : 0 : req.emr_in_buf = payload;
3766 : 0 : req.emr_in_length = MC_CMD_MAE_ACTION_SET_FREE_IN_LEN(1);
3767 : 0 : req.emr_out_buf = payload;
3768 : 0 : req.emr_out_length = MC_CMD_MAE_ACTION_SET_FREE_OUT_LEN(1);
3769 : :
3770 : 0 : MCDI_IN_SET_DWORD(req, MAE_ACTION_SET_FREE_IN_AS_ID, aset_idp->id);
3771 : :
3772 : 0 : efx_mcdi_execute(enp, &req);
3773 : :
3774 [ # # ]: 0 : if (req.emr_rc != 0) {
3775 : : rc = req.emr_rc;
3776 : 0 : goto fail2;
3777 : : }
3778 : :
3779 [ # # ]: 0 : if (req.emr_out_length_used < MC_CMD_MAE_ACTION_SET_FREE_OUT_LENMIN) {
3780 : : rc = EMSGSIZE;
3781 : 0 : goto fail3;
3782 : : }
3783 : :
3784 : 0 : if (MCDI_OUT_DWORD(req, MAE_ACTION_SET_FREE_OUT_FREED_AS_ID) !=
3785 [ # # ]: 0 : aset_idp->id) {
3786 : : /* Firmware failed to free the action set. */
3787 : : rc = EAGAIN;
3788 : 0 : goto fail4;
3789 : : }
3790 : :
3791 : : return (0);
3792 : :
3793 : : fail4:
3794 : : EFSYS_PROBE(fail4);
3795 : : fail3:
3796 : : EFSYS_PROBE(fail3);
3797 : : fail2:
3798 : : EFSYS_PROBE(fail2);
3799 : : fail1:
3800 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
3801 : : return (rc);
3802 : : }
3803 : :
3804 : : __checkReturn efx_rc_t
3805 : 0 : efx_mae_action_rule_insert(
3806 : : __in efx_nic_t *enp,
3807 : : __in const efx_mae_match_spec_t *spec,
3808 : : __in const efx_mae_aset_list_id_t *asl_idp,
3809 : : __in const efx_mae_aset_id_t *as_idp,
3810 : : __out efx_mae_rule_id_t *ar_idp)
3811 : : {
3812 : 0 : const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
3813 : : efx_mcdi_req_t req;
3814 : 0 : EFX_MCDI_DECLARE_BUF(payload,
3815 : : MC_CMD_MAE_ACTION_RULE_INSERT_IN_LENMAX_MCDI2,
3816 : : MC_CMD_MAE_ACTION_RULE_INSERT_OUT_LEN);
3817 : : efx_oword_t *rule_response;
3818 : : efx_mae_rule_id_t ar_id;
3819 : : size_t offset;
3820 : : efx_rc_t rc;
3821 : :
3822 : : EFX_STATIC_ASSERT(sizeof (ar_idp->id) ==
3823 : : MC_CMD_MAE_ACTION_RULE_INSERT_OUT_AR_ID_LEN);
3824 : :
3825 : : EFX_STATIC_ASSERT(EFX_MAE_RSRC_ID_INVALID ==
3826 : : MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL);
3827 : :
3828 [ # # ]: 0 : if (encp->enc_mae_supported == B_FALSE) {
3829 : : rc = ENOTSUP;
3830 : 0 : goto fail1;
3831 : : }
3832 : :
3833 [ # # ]: 0 : if (spec->emms_type != EFX_MAE_RULE_ACTION ||
3834 [ # # ]: 0 : (asl_idp != NULL && as_idp != NULL) ||
3835 [ # # ]: 0 : (asl_idp == NULL && as_idp == NULL)) {
3836 : : rc = EINVAL;
3837 : 0 : goto fail2;
3838 : : }
3839 : :
3840 : 0 : req.emr_cmd = MC_CMD_MAE_ACTION_RULE_INSERT;
3841 : 0 : req.emr_in_buf = payload;
3842 : 0 : req.emr_in_length = MC_CMD_MAE_ACTION_RULE_INSERT_IN_LENMAX_MCDI2;
3843 : 0 : req.emr_out_buf = payload;
3844 : 0 : req.emr_out_length = MC_CMD_MAE_ACTION_RULE_INSERT_OUT_LEN;
3845 : :
3846 : : EFX_STATIC_ASSERT(sizeof (*rule_response) <=
3847 : : MC_CMD_MAE_ACTION_RULE_INSERT_IN_RESPONSE_LEN);
3848 : : offset = MC_CMD_MAE_ACTION_RULE_INSERT_IN_RESPONSE_OFST;
3849 : : rule_response = (efx_oword_t *)(payload + offset);
3850 [ # # # # ]: 0 : EFX_POPULATE_OWORD_3(*rule_response,
3851 : : MAE_ACTION_RULE_RESPONSE_ASL_ID,
3852 : : (asl_idp != NULL) ? asl_idp->id : EFX_MAE_RSRC_ID_INVALID,
3853 : : MAE_ACTION_RULE_RESPONSE_AS_ID,
3854 : : (as_idp != NULL) ? as_idp->id : EFX_MAE_RSRC_ID_INVALID,
3855 : : MAE_ACTION_RULE_RESPONSE_COUNTER_ID, EFX_MAE_RSRC_ID_INVALID);
3856 : :
3857 : 0 : MCDI_IN_SET_DWORD(req, MAE_ACTION_RULE_INSERT_IN_PRIO, spec->emms_prio);
3858 : :
3859 : : /*
3860 : : * Mask-value pairs have been stored in the byte order needed for the
3861 : : * MCDI request and are thus safe to be copied directly to the buffer.
3862 : : */
3863 : : EFX_STATIC_ASSERT(sizeof (spec->emms_mask_value_pairs.action) >=
3864 : : MAE_FIELD_MASK_VALUE_PAIRS_V2_LEN);
3865 : : offset = MC_CMD_MAE_ACTION_RULE_INSERT_IN_MATCH_CRITERIA_OFST;
3866 : 0 : memcpy(payload + offset, spec->emms_mask_value_pairs.action,
3867 : : MAE_FIELD_MASK_VALUE_PAIRS_V2_LEN);
3868 : :
3869 : 0 : efx_mcdi_execute(enp, &req);
3870 : :
3871 [ # # ]: 0 : if (req.emr_rc != 0) {
3872 : : rc = req.emr_rc;
3873 : 0 : goto fail3;
3874 : : }
3875 : :
3876 [ # # ]: 0 : if (req.emr_out_length_used < MC_CMD_MAE_ACTION_RULE_INSERT_OUT_LEN) {
3877 : : rc = EMSGSIZE;
3878 : 0 : goto fail4;
3879 : : }
3880 : :
3881 : 0 : ar_id.id = MCDI_OUT_DWORD(req, MAE_ACTION_RULE_INSERT_OUT_AR_ID);
3882 [ # # ]: 0 : if (ar_id.id == EFX_MAE_RSRC_ID_INVALID) {
3883 : : rc = ENOENT;
3884 : 0 : goto fail5;
3885 : : }
3886 : :
3887 : 0 : ar_idp->id = ar_id.id;
3888 : :
3889 : 0 : return (0);
3890 : :
3891 : : fail5:
3892 : : EFSYS_PROBE(fail5);
3893 : : fail4:
3894 : : EFSYS_PROBE(fail4);
3895 : : fail3:
3896 : : EFSYS_PROBE(fail3);
3897 : : fail2:
3898 : : EFSYS_PROBE(fail2);
3899 : : fail1:
3900 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
3901 : : return (rc);
3902 : : }
3903 : :
3904 : : __checkReturn efx_rc_t
3905 : 0 : efx_mae_action_rule_remove(
3906 : : __in efx_nic_t *enp,
3907 : : __in const efx_mae_rule_id_t *ar_idp)
3908 : : {
3909 : 0 : const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
3910 : : efx_mcdi_req_t req;
3911 : 0 : EFX_MCDI_DECLARE_BUF(payload,
3912 : : MC_CMD_MAE_ACTION_RULE_DELETE_IN_LEN(1),
3913 : : MC_CMD_MAE_ACTION_RULE_DELETE_OUT_LEN(1));
3914 : : efx_rc_t rc;
3915 : :
3916 [ # # ]: 0 : if (encp->enc_mae_supported == B_FALSE) {
3917 : : rc = ENOTSUP;
3918 : 0 : goto fail1;
3919 : : }
3920 : :
3921 : 0 : req.emr_cmd = MC_CMD_MAE_ACTION_RULE_DELETE;
3922 : 0 : req.emr_in_buf = payload;
3923 : 0 : req.emr_in_length = MC_CMD_MAE_ACTION_RULE_DELETE_IN_LEN(1);
3924 : 0 : req.emr_out_buf = payload;
3925 : 0 : req.emr_out_length = MC_CMD_MAE_ACTION_RULE_DELETE_OUT_LEN(1);
3926 : :
3927 : 0 : MCDI_IN_SET_DWORD(req, MAE_ACTION_RULE_DELETE_IN_AR_ID, ar_idp->id);
3928 : :
3929 : 0 : efx_mcdi_execute(enp, &req);
3930 : :
3931 [ # # ]: 0 : if (req.emr_rc != 0) {
3932 : : rc = req.emr_rc;
3933 : 0 : goto fail2;
3934 : : }
3935 : :
3936 [ # # ]: 0 : if (req.emr_out_length_used <
3937 : : MC_CMD_MAE_ACTION_RULE_DELETE_OUT_LENMIN) {
3938 : : rc = EMSGSIZE;
3939 : 0 : goto fail3;
3940 : : }
3941 : :
3942 : 0 : if (MCDI_OUT_DWORD(req, MAE_ACTION_RULE_DELETE_OUT_DELETED_AR_ID) !=
3943 [ # # ]: 0 : ar_idp->id) {
3944 : : /* Firmware failed to delete the action rule. */
3945 : : rc = EAGAIN;
3946 : 0 : goto fail4;
3947 : : }
3948 : :
3949 : : return (0);
3950 : :
3951 : : fail4:
3952 : : EFSYS_PROBE(fail4);
3953 : : fail3:
3954 : : EFSYS_PROBE(fail3);
3955 : : fail2:
3956 : : EFSYS_PROBE(fail2);
3957 : : fail1:
3958 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
3959 : : return (rc);
3960 : : }
3961 : :
3962 : : __checkReturn efx_rc_t
3963 : 0 : efx_mcdi_mport_alloc_alias(
3964 : : __in efx_nic_t *enp,
3965 : : __out efx_mport_id_t *mportp,
3966 : : __out_opt uint32_t *labelp)
3967 : : {
3968 : 0 : const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
3969 : : efx_mcdi_req_t req;
3970 : 0 : EFX_MCDI_DECLARE_BUF(payload,
3971 : : MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN_LEN,
3972 : : MC_CMD_MAE_MPORT_ALLOC_ALIAS_OUT_LEN);
3973 : : efx_rc_t rc;
3974 : :
3975 [ # # ]: 0 : if (encp->enc_mae_supported == B_FALSE) {
3976 : : rc = ENOTSUP;
3977 : 0 : goto fail1;
3978 : : }
3979 : :
3980 : 0 : req.emr_cmd = MC_CMD_MAE_MPORT_ALLOC;
3981 : 0 : req.emr_in_buf = payload;
3982 : 0 : req.emr_in_length = MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN_LEN;
3983 : 0 : req.emr_out_buf = payload;
3984 : 0 : req.emr_out_length = MC_CMD_MAE_MPORT_ALLOC_ALIAS_OUT_LEN;
3985 : :
3986 : 0 : MCDI_IN_SET_DWORD(req, MAE_MPORT_ALLOC_IN_TYPE,
3987 : : MC_CMD_MAE_MPORT_ALLOC_IN_MPORT_TYPE_ALIAS);
3988 : 0 : MCDI_IN_SET_DWORD(req, MAE_MPORT_ALLOC_ALIAS_IN_DELIVER_MPORT,
3989 : : MAE_MPORT_SELECTOR_ASSIGNED);
3990 : :
3991 : 0 : efx_mcdi_execute(enp, &req);
3992 : :
3993 [ # # ]: 0 : if (req.emr_rc != 0) {
3994 : : rc = req.emr_rc;
3995 : 0 : goto fail2;
3996 : : }
3997 : :
3998 : 0 : mportp->id = MCDI_OUT_DWORD(req, MAE_MPORT_ALLOC_OUT_MPORT_ID);
3999 [ # # ]: 0 : if (labelp != NULL)
4000 : 0 : *labelp = MCDI_OUT_DWORD(req, MAE_MPORT_ALLOC_ALIAS_OUT_LABEL);
4001 : :
4002 : : return (0);
4003 : :
4004 : : fail2:
4005 : : EFSYS_PROBE(fail2);
4006 : : fail1:
4007 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
4008 : : return (rc);
4009 : : }
4010 : :
4011 : : __checkReturn efx_rc_t
4012 : 0 : efx_mae_mport_free(
4013 : : __in efx_nic_t *enp,
4014 : : __in const efx_mport_id_t *mportp)
4015 : : {
4016 : 0 : const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
4017 : : efx_mcdi_req_t req;
4018 : 0 : EFX_MCDI_DECLARE_BUF(payload,
4019 : : MC_CMD_MAE_MPORT_FREE_IN_LEN,
4020 : : MC_CMD_MAE_MPORT_FREE_OUT_LEN);
4021 : : efx_rc_t rc;
4022 : :
4023 [ # # ]: 0 : if (encp->enc_mae_supported == B_FALSE) {
4024 : : rc = ENOTSUP;
4025 : 0 : goto fail1;
4026 : : }
4027 : :
4028 : 0 : req.emr_cmd = MC_CMD_MAE_MPORT_FREE;
4029 : 0 : req.emr_in_buf = payload;
4030 : 0 : req.emr_in_length = MC_CMD_MAE_MPORT_FREE_IN_LEN;
4031 : 0 : req.emr_out_buf = payload;
4032 : 0 : req.emr_out_length = MC_CMD_MAE_MPORT_FREE_OUT_LEN;
4033 : :
4034 : 0 : MCDI_IN_SET_DWORD(req, MAE_MPORT_FREE_IN_MPORT_ID, mportp->id);
4035 : :
4036 : 0 : efx_mcdi_execute(enp, &req);
4037 : :
4038 [ # # ]: 0 : if (req.emr_rc != 0) {
4039 : : rc = req.emr_rc;
4040 : 0 : goto fail2;
4041 : : }
4042 : :
4043 : : return (0);
4044 : :
4045 : : fail2:
4046 : : EFSYS_PROBE(fail2);
4047 : : fail1:
4048 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
4049 : : return (rc);
4050 : : }
4051 : :
4052 : : static __checkReturn efx_rc_t
4053 [ # # # # ]: 0 : efx_mae_read_mport_journal_single(
4054 : : __in uint8_t *entry_buf,
4055 : : __out efx_mport_desc_t *desc)
4056 : : {
4057 : : uint32_t pcie_intf;
4058 : : efx_rc_t rc;
4059 : :
4060 : : memset(desc, 0, sizeof (*desc));
4061 : :
4062 : 0 : desc->emd_id.id = MCDI_STRUCT_DWORD(entry_buf,
4063 : : MAE_MPORT_DESC_V2_MPORT_ID);
4064 : :
4065 : 0 : desc->emd_can_receive_on = MCDI_STRUCT_DWORD_FIELD(entry_buf,
4066 : : MAE_MPORT_DESC_V2_FLAGS,
4067 : : MAE_MPORT_DESC_V2_CAN_RECEIVE_ON);
4068 : :
4069 : 0 : desc->emd_can_deliver_to = MCDI_STRUCT_DWORD_FIELD(entry_buf,
4070 : : MAE_MPORT_DESC_V2_FLAGS,
4071 : : MAE_MPORT_DESC_V2_CAN_DELIVER_TO);
4072 : :
4073 : 0 : desc->emd_can_delete = MCDI_STRUCT_DWORD_FIELD(entry_buf,
4074 : : MAE_MPORT_DESC_V2_FLAGS,
4075 : : MAE_MPORT_DESC_V2_CAN_DELETE);
4076 : :
4077 : 0 : desc->emd_zombie = MCDI_STRUCT_DWORD_FIELD(entry_buf,
4078 : : MAE_MPORT_DESC_V2_FLAGS,
4079 : : MAE_MPORT_DESC_V2_IS_ZOMBIE);
4080 : :
4081 : 0 : desc->emd_type = MCDI_STRUCT_DWORD(entry_buf,
4082 : : MAE_MPORT_DESC_V2_MPORT_TYPE);
4083 : :
4084 : : /*
4085 : : * We can't check everything here. If some additional checks are
4086 : : * required, they should be performed by the callback function.
4087 : : */
4088 [ # # # # ]: 0 : switch (desc->emd_type) {
4089 : 0 : case EFX_MPORT_TYPE_NET_PORT:
4090 : 0 : desc->emd_net_port.ep_index =
4091 : 0 : MCDI_STRUCT_DWORD(entry_buf,
4092 : : MAE_MPORT_DESC_V2_NET_PORT_IDX);
4093 : 0 : break;
4094 : 0 : case EFX_MPORT_TYPE_ALIAS:
4095 : 0 : desc->emd_alias.ea_target_mport_id.id =
4096 : 0 : MCDI_STRUCT_DWORD(entry_buf,
4097 : : MAE_MPORT_DESC_V2_ALIAS_DELIVER_MPORT_ID);
4098 : 0 : break;
4099 : 0 : case EFX_MPORT_TYPE_VNIC:
4100 : 0 : desc->emd_vnic.ev_client_type =
4101 : 0 : MCDI_STRUCT_DWORD(entry_buf,
4102 : : MAE_MPORT_DESC_V2_VNIC_CLIENT_TYPE);
4103 [ # # ]: 0 : if (desc->emd_vnic.ev_client_type !=
4104 : : EFX_MPORT_VNIC_CLIENT_FUNCTION)
4105 : : break;
4106 : :
4107 : 0 : pcie_intf = MCDI_STRUCT_DWORD(entry_buf,
4108 : : MAE_MPORT_DESC_V2_VNIC_FUNCTION_INTERFACE);
4109 : 0 : rc = efx_mcdi_intf_from_pcie(pcie_intf,
4110 : : &desc->emd_vnic.ev_intf);
4111 [ # # ]: 0 : if (rc != 0)
4112 : 0 : goto fail1;
4113 : :
4114 : 0 : desc->emd_vnic.ev_pf = MCDI_STRUCT_WORD(entry_buf,
4115 : : MAE_MPORT_DESC_V2_VNIC_FUNCTION_PF_IDX);
4116 : 0 : desc->emd_vnic.ev_vf = MCDI_STRUCT_WORD(entry_buf,
4117 : : MAE_MPORT_DESC_V2_VNIC_FUNCTION_VF_IDX);
4118 : 0 : desc->emd_vnic.ev_handle = MCDI_STRUCT_DWORD(entry_buf,
4119 : : MAE_MPORT_DESC_V2_VNIC_CLIENT_HANDLE);
4120 : 0 : break;
4121 : 0 : default:
4122 : : rc = EINVAL;
4123 : 0 : goto fail2;
4124 : : }
4125 : :
4126 : : return (0);
4127 : :
4128 : : fail2:
4129 : : EFSYS_PROBE(fail2);
4130 : : fail1:
4131 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
4132 : : return (rc);
4133 : : }
4134 : :
4135 : : static __checkReturn efx_rc_t
4136 : 0 : efx_mae_read_mport_journal_batch(
4137 : : __in efx_nic_t *enp,
4138 : : __in efx_mae_read_mport_journal_cb *cbp,
4139 : : __in void *cb_datap,
4140 : : __out uint32_t *morep)
4141 : : {
4142 : : efx_mcdi_req_t req;
4143 : 0 : EFX_MCDI_DECLARE_BUF(payload,
4144 : : MC_CMD_MAE_MPORT_READ_JOURNAL_IN_LEN,
4145 : : MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_LENMAX_MCDI2);
4146 : : uint32_t n_entries;
4147 : : uint32_t entry_sz;
4148 : : uint8_t *entry_buf;
4149 : : unsigned int i;
4150 : : efx_rc_t rc;
4151 : :
4152 : : EFX_STATIC_ASSERT(EFX_MPORT_TYPE_NET_PORT ==
4153 : : MAE_MPORT_DESC_V2_MPORT_TYPE_NET_PORT);
4154 : : EFX_STATIC_ASSERT(EFX_MPORT_TYPE_ALIAS ==
4155 : : MAE_MPORT_DESC_V2_MPORT_TYPE_ALIAS);
4156 : : EFX_STATIC_ASSERT(EFX_MPORT_TYPE_VNIC ==
4157 : : MAE_MPORT_DESC_V2_MPORT_TYPE_VNIC);
4158 : :
4159 : : EFX_STATIC_ASSERT(EFX_MPORT_VNIC_CLIENT_FUNCTION ==
4160 : : MAE_MPORT_DESC_V2_VNIC_CLIENT_TYPE_FUNCTION);
4161 : : EFX_STATIC_ASSERT(EFX_MPORT_VNIC_CLIENT_PLUGIN ==
4162 : : MAE_MPORT_DESC_V2_VNIC_CLIENT_TYPE_PLUGIN);
4163 : :
4164 [ # # ]: 0 : if (cbp == NULL) {
4165 : : rc = EINVAL;
4166 : 0 : goto fail1;
4167 : : }
4168 : :
4169 : 0 : req.emr_cmd = MC_CMD_MAE_MPORT_READ_JOURNAL;
4170 : 0 : req.emr_in_buf = payload;
4171 : 0 : req.emr_in_length = MC_CMD_MAE_MPORT_READ_JOURNAL_IN_LEN;
4172 : 0 : req.emr_out_buf = payload;
4173 : 0 : req.emr_out_length = MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_LENMAX_MCDI2;
4174 : :
4175 : : MCDI_IN_SET_DWORD(req, MAE_MPORT_READ_JOURNAL_IN_FLAGS, 0);
4176 : :
4177 : 0 : efx_mcdi_execute(enp, &req);
4178 : :
4179 [ # # ]: 0 : if (req.emr_rc != 0) {
4180 : : rc = req.emr_rc;
4181 : 0 : goto fail2;
4182 : : }
4183 : :
4184 [ # # ]: 0 : if (req.emr_out_length_used <
4185 : : MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_LENMIN) {
4186 : : rc = EMSGSIZE;
4187 : 0 : goto fail3;
4188 : : }
4189 : :
4190 [ # # ]: 0 : if (morep != NULL) {
4191 : 0 : *morep = MCDI_OUT_DWORD_FIELD(req,
4192 : : MAE_MPORT_READ_JOURNAL_OUT_FLAGS,
4193 : : MAE_MPORT_READ_JOURNAL_OUT_MORE);
4194 : : }
4195 : 0 : n_entries = MCDI_OUT_DWORD(req,
4196 : : MAE_MPORT_READ_JOURNAL_OUT_MPORT_DESC_COUNT);
4197 : 0 : entry_sz = MCDI_OUT_DWORD(req,
4198 : : MAE_MPORT_READ_JOURNAL_OUT_SIZEOF_MPORT_DESC);
4199 : 0 : entry_buf = MCDI_OUT2(req, uint8_t,
4200 : : MAE_MPORT_READ_JOURNAL_OUT_MPORT_DESC_DATA);
4201 : :
4202 [ # # ]: 0 : if (entry_sz < MAE_MPORT_DESC_V2_VNIC_CLIENT_HANDLE_OFST +
4203 : : MAE_MPORT_DESC_V2_VNIC_CLIENT_HANDLE_LEN) {
4204 : : rc = EINVAL;
4205 : 0 : goto fail4;
4206 : : }
4207 [ # # ]: 0 : if (n_entries * entry_sz / entry_sz != n_entries) {
4208 : : rc = EINVAL;
4209 : 0 : goto fail5;
4210 : : }
4211 : 0 : if (req.emr_out_length_used !=
4212 [ # # ]: 0 : MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_LENMIN + n_entries * entry_sz) {
4213 : : rc = EINVAL;
4214 : 0 : goto fail6;
4215 : : }
4216 : :
4217 [ # # ]: 0 : for (i = 0; i < n_entries; i++) {
4218 : : efx_mport_desc_t desc;
4219 : :
4220 : 0 : rc = efx_mae_read_mport_journal_single(entry_buf, &desc);
4221 [ # # ]: 0 : if (rc != 0)
4222 : 0 : continue;
4223 : :
4224 : 0 : (*cbp)(cb_datap, &desc, sizeof (desc));
4225 : 0 : entry_buf += entry_sz;
4226 : : }
4227 : :
4228 : : return (0);
4229 : :
4230 : : fail6:
4231 : : EFSYS_PROBE(fail6);
4232 : : fail5:
4233 : : EFSYS_PROBE(fail5);
4234 : : fail4:
4235 : : EFSYS_PROBE(fail4);
4236 : : fail3:
4237 : : EFSYS_PROBE(fail3);
4238 : : fail2:
4239 : : EFSYS_PROBE(fail2);
4240 : : fail1:
4241 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
4242 : : return (rc);
4243 : : }
4244 : :
4245 : : __checkReturn efx_rc_t
4246 : 0 : efx_mae_read_mport_journal(
4247 : : __in efx_nic_t *enp,
4248 : : __in efx_mae_read_mport_journal_cb *cbp,
4249 : : __in void *cb_datap)
4250 : : {
4251 : 0 : const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
4252 : 0 : uint32_t more = 0;
4253 : : efx_rc_t rc;
4254 : :
4255 [ # # ]: 0 : if (encp->enc_mae_supported == B_FALSE) {
4256 : : rc = ENOTSUP;
4257 : 0 : goto fail1;
4258 : : }
4259 : :
4260 : : do {
4261 : 0 : rc = efx_mae_read_mport_journal_batch(enp, cbp, cb_datap,
4262 : : &more);
4263 [ # # ]: 0 : if (rc != 0)
4264 : 0 : goto fail2;
4265 [ # # ]: 0 : } while (more != 0);
4266 : :
4267 : : return (0);
4268 : :
4269 : : fail2:
4270 : : EFSYS_PROBE(fail2);
4271 : : fail1:
4272 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
4273 : : return (rc);
4274 : : }
4275 : :
4276 : : __checkReturn efx_rc_t
4277 : 0 : efx_mae_action_set_replay(
4278 : : __in efx_nic_t *enp,
4279 : : __in const efx_mae_actions_t *spec_orig,
4280 : : __out efx_mae_actions_t **spec_clonep)
4281 : : {
4282 : 0 : const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
4283 : : efx_mae_actions_t *spec_clone;
4284 : : efx_rc_t rc;
4285 : :
4286 : 0 : EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (*spec_clone), spec_clone);
4287 [ # # ]: 0 : if (spec_clone == NULL) {
4288 : : rc = ENOMEM;
4289 : 0 : goto fail1;
4290 : : }
4291 : :
4292 : 0 : *spec_clone = *spec_orig;
4293 : :
4294 : 0 : spec_clone->ema_rsrc.emar_counter_id.id = EFX_MAE_RSRC_ID_INVALID;
4295 : 0 : spec_clone->ema_actions &= ~(1U << EFX_MAE_ACTION_COUNT);
4296 : 0 : spec_clone->ema_n_count_actions = 0;
4297 : :
4298 : 0 : (void)efx_mae_mport_invalid(&spec_clone->ema_deliver_mport);
4299 : 0 : spec_clone->ema_actions &= ~(1U << EFX_MAE_ACTION_DELIVER);
4300 : :
4301 : 0 : *spec_clonep = spec_clone;
4302 : :
4303 : 0 : return (0);
4304 : :
4305 : : fail1:
4306 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
4307 : 0 : return (rc);
4308 : : }
4309 : :
4310 : : __checkReturn efx_rc_t
4311 : 0 : efx_mae_action_set_list_alloc(
4312 : : __in efx_nic_t *enp,
4313 : : __in unsigned int n_asets,
4314 : : __in_ecount(n_asets) const efx_mae_aset_id_t *aset_ids,
4315 : : __out efx_mae_aset_list_id_t *aset_list_idp)
4316 : : {
4317 : 0 : const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
4318 : 0 : EFX_MCDI_DECLARE_BUF(payload,
4319 : : MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_LENMAX_MCDI2,
4320 : : MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_LEN);
4321 : : efx_mae_aset_list_id_t aset_list_id;
4322 : : efx_mcdi_req_t req;
4323 : : efx_rc_t rc;
4324 : :
4325 : : EFX_STATIC_ASSERT(EFX_MAE_ACTION_SET_LIST_MAX_NENTRIES ==
4326 : : MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_AS_IDS_MAXNUM_MCDI2);
4327 : :
4328 : : EFX_STATIC_ASSERT(EFX_MAE_RSRC_ID_INVALID ==
4329 : : MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_ACTION_SET_LIST_ID_NULL);
4330 : :
4331 : : EFX_STATIC_ASSERT(sizeof (aset_list_idp->id) ==
4332 : : MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_ASL_ID_LEN);
4333 : :
4334 [ # # ]: 0 : if (encp->enc_mae_supported == B_FALSE) {
4335 : : rc = ENOTSUP;
4336 : 0 : goto fail1;
4337 : : }
4338 : :
4339 [ # # ]: 0 : if (MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_LEN(n_asets) >
4340 : : MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_LENMAX_MCDI2) {
4341 : : rc = EINVAL;
4342 : 0 : goto fail2;
4343 : : }
4344 : :
4345 : 0 : req.emr_cmd = MC_CMD_MAE_ACTION_SET_LIST_ALLOC;
4346 : 0 : req.emr_in_buf = payload;
4347 : 0 : req.emr_in_length = MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_LEN(n_asets);
4348 : 0 : req.emr_out_buf = payload;
4349 : 0 : req.emr_out_length = MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_LEN;
4350 : :
4351 : 0 : MCDI_IN_SET_DWORD(req,
4352 : : MAE_ACTION_SET_LIST_ALLOC_IN_COUNT, n_asets);
4353 : :
4354 : 0 : memcpy(MCDI_IN2(req, uint8_t, MAE_ACTION_SET_LIST_ALLOC_IN_AS_IDS),
4355 : : aset_ids, n_asets * sizeof (*aset_ids));
4356 : :
4357 : 0 : efx_mcdi_execute(enp, &req);
4358 : :
4359 [ # # ]: 0 : if (req.emr_rc != 0) {
4360 : : rc = req.emr_rc;
4361 : 0 : goto fail3;
4362 : : }
4363 : :
4364 [ # # ]: 0 : if (req.emr_out_length_used < MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_LEN) {
4365 : : rc = EMSGSIZE;
4366 : 0 : goto fail4;
4367 : : }
4368 : :
4369 : : aset_list_id.id =
4370 : 0 : MCDI_OUT_DWORD(req, MAE_ACTION_SET_LIST_ALLOC_OUT_ASL_ID);
4371 [ # # ]: 0 : if (aset_list_id.id == EFX_MAE_RSRC_ID_INVALID) {
4372 : : rc = ENOENT;
4373 : 0 : goto fail5;
4374 : : }
4375 : :
4376 : 0 : aset_list_idp->id = aset_list_id.id;
4377 : :
4378 : 0 : return (0);
4379 : :
4380 : : fail5:
4381 : : EFSYS_PROBE(fail5);
4382 : : fail4:
4383 : : EFSYS_PROBE(fail4);
4384 : : fail3:
4385 : : EFSYS_PROBE(fail3);
4386 : : fail2:
4387 : : EFSYS_PROBE(fail2);
4388 : : fail1:
4389 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
4390 : : return (rc);
4391 : : }
4392 : :
4393 : : __checkReturn efx_rc_t
4394 : 0 : efx_mae_action_set_list_free(
4395 : : __in efx_nic_t *enp,
4396 : : __in const efx_mae_aset_list_id_t *aset_list_idp)
4397 : : {
4398 : 0 : const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
4399 : 0 : EFX_MCDI_DECLARE_BUF(payload,
4400 : : MC_CMD_MAE_ACTION_SET_LIST_FREE_IN_LEN(1),
4401 : : MC_CMD_MAE_ACTION_SET_LIST_FREE_OUT_LEN(1));
4402 : : efx_mcdi_req_t req;
4403 : : efx_rc_t rc;
4404 : :
4405 [ # # ]: 0 : if (encp->enc_mae_supported == B_FALSE) {
4406 : : rc = ENOTSUP;
4407 : 0 : goto fail1;
4408 : : }
4409 : :
4410 : 0 : req.emr_cmd = MC_CMD_MAE_ACTION_SET_LIST_FREE;
4411 : 0 : req.emr_in_buf = payload;
4412 : 0 : req.emr_in_length = MC_CMD_MAE_ACTION_SET_LIST_FREE_IN_LEN(1);
4413 : 0 : req.emr_out_buf = payload;
4414 : 0 : req.emr_out_length = MC_CMD_MAE_ACTION_SET_LIST_FREE_OUT_LEN(1);
4415 : :
4416 : 0 : MCDI_IN_SET_DWORD(req,
4417 : : MAE_ACTION_SET_LIST_FREE_IN_ASL_ID, aset_list_idp->id);
4418 : :
4419 : 0 : efx_mcdi_execute(enp, &req);
4420 : :
4421 [ # # ]: 0 : if (req.emr_rc != 0) {
4422 : : rc = req.emr_rc;
4423 : 0 : goto fail2;
4424 : : }
4425 : :
4426 [ # # ]: 0 : if (req.emr_out_length_used < MC_CMD_MAE_ACTION_SET_LIST_FREE_OUT_LENMIN) {
4427 : : rc = EMSGSIZE;
4428 : 0 : goto fail3;
4429 : : }
4430 : :
4431 : 0 : if (MCDI_OUT_DWORD(req, MAE_ACTION_SET_LIST_FREE_OUT_FREED_ASL_ID) !=
4432 [ # # ]: 0 : aset_list_idp->id) {
4433 : : /* Firmware failed to free the action set list. */
4434 : : rc = EAGAIN;
4435 : 0 : goto fail4;
4436 : : }
4437 : :
4438 : : return (0);
4439 : :
4440 : : fail4:
4441 : : EFSYS_PROBE(fail4);
4442 : : fail3:
4443 : : EFSYS_PROBE(fail3);
4444 : : fail2:
4445 : : EFSYS_PROBE(fail2);
4446 : : fail1:
4447 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
4448 : : return (rc);
4449 : : }
4450 : :
4451 : : #endif /* EFSYS_OPT_MAE */
|