1 /* SPDX-License-Identifier: BSD-3-Clause
3 * Copyright(c) 2019-2021 Xilinx, Inc.
12 static __checkReturn efx_rc_t
13 efx_mae_get_capabilities(
17 EFX_MCDI_DECLARE_BUF(payload,
18 MC_CMD_MAE_GET_CAPS_IN_LEN,
19 MC_CMD_MAE_GET_CAPS_OUT_LEN);
20 struct efx_mae_s *maep = enp->en_maep;
23 req.emr_cmd = MC_CMD_MAE_GET_CAPS;
24 req.emr_in_buf = payload;
25 req.emr_in_length = MC_CMD_MAE_GET_CAPS_IN_LEN;
26 req.emr_out_buf = payload;
27 req.emr_out_length = MC_CMD_MAE_GET_CAPS_OUT_LEN;
29 efx_mcdi_execute(enp, &req);
31 if (req.emr_rc != 0) {
36 if (req.emr_out_length_used < MC_CMD_MAE_GET_CAPS_OUT_LEN) {
41 maep->em_max_n_outer_prios =
42 MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_OUTER_PRIOS);
44 maep->em_max_n_action_prios =
45 MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_ACTION_PRIOS);
47 maep->em_encap_types_supported = 0;
49 if (MCDI_OUT_DWORD_FIELD(req, MAE_GET_CAPS_OUT_ENCAP_TYPES_SUPPORTED,
50 MAE_GET_CAPS_OUT_ENCAP_TYPE_VXLAN) != 0) {
51 maep->em_encap_types_supported |=
52 (1U << EFX_TUNNEL_PROTOCOL_VXLAN);
55 if (MCDI_OUT_DWORD_FIELD(req, MAE_GET_CAPS_OUT_ENCAP_TYPES_SUPPORTED,
56 MAE_GET_CAPS_OUT_ENCAP_TYPE_GENEVE) != 0) {
57 maep->em_encap_types_supported |=
58 (1U << EFX_TUNNEL_PROTOCOL_GENEVE);
61 if (MCDI_OUT_DWORD_FIELD(req, MAE_GET_CAPS_OUT_ENCAP_TYPES_SUPPORTED,
62 MAE_GET_CAPS_OUT_ENCAP_TYPE_NVGRE) != 0) {
63 maep->em_encap_types_supported |=
64 (1U << EFX_TUNNEL_PROTOCOL_NVGRE);
67 maep->em_max_nfields =
68 MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_MATCH_FIELD_COUNT);
70 maep->em_max_ncounters =
71 MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_COUNTERS);
78 EFSYS_PROBE1(fail1, efx_rc_t, rc);
82 static __checkReturn efx_rc_t
83 efx_mae_get_outer_rule_caps(
85 __in unsigned int field_ncaps,
86 __out_ecount(field_ncaps) efx_mae_field_cap_t *field_caps)
89 EFX_MCDI_DECLARE_BUF(payload,
90 MC_CMD_MAE_GET_OR_CAPS_IN_LEN,
91 MC_CMD_MAE_GET_OR_CAPS_OUT_LENMAX_MCDI2);
92 unsigned int mcdi_field_ncaps;
96 if (MC_CMD_MAE_GET_OR_CAPS_OUT_LEN(field_ncaps) >
97 MC_CMD_MAE_GET_OR_CAPS_OUT_LENMAX_MCDI2) {
102 req.emr_cmd = MC_CMD_MAE_GET_OR_CAPS;
103 req.emr_in_buf = payload;
104 req.emr_in_length = MC_CMD_MAE_GET_OR_CAPS_IN_LEN;
105 req.emr_out_buf = payload;
106 req.emr_out_length = MC_CMD_MAE_GET_OR_CAPS_OUT_LEN(field_ncaps);
108 efx_mcdi_execute(enp, &req);
110 if (req.emr_rc != 0) {
115 if (req.emr_out_length_used < MC_CMD_MAE_GET_OR_CAPS_OUT_LENMIN) {
120 mcdi_field_ncaps = MCDI_OUT_DWORD(req, MAE_GET_OR_CAPS_OUT_COUNT);
122 if (req.emr_out_length_used <
123 MC_CMD_MAE_GET_OR_CAPS_OUT_LEN(mcdi_field_ncaps)) {
128 if (mcdi_field_ncaps > field_ncaps) {
133 for (i = 0; i < mcdi_field_ncaps; ++i) {
137 field_caps[i].emfc_support = MCDI_OUT_INDEXED_DWORD_FIELD(req,
138 MAE_GET_OR_CAPS_OUT_FIELD_FLAGS, i,
139 MAE_FIELD_FLAGS_SUPPORT_STATUS);
141 match_flag = MCDI_OUT_INDEXED_DWORD_FIELD(req,
142 MAE_GET_OR_CAPS_OUT_FIELD_FLAGS, i,
143 MAE_FIELD_FLAGS_MATCH_AFFECTS_CLASS);
145 field_caps[i].emfc_match_affects_class =
146 (match_flag != 0) ? B_TRUE : B_FALSE;
148 mask_flag = MCDI_OUT_INDEXED_DWORD_FIELD(req,
149 MAE_GET_OR_CAPS_OUT_FIELD_FLAGS, i,
150 MAE_FIELD_FLAGS_MASK_AFFECTS_CLASS);
152 field_caps[i].emfc_mask_affects_class =
153 (mask_flag != 0) ? B_TRUE : B_FALSE;
167 EFSYS_PROBE1(fail1, efx_rc_t, rc);
171 static __checkReturn efx_rc_t
172 efx_mae_get_action_rule_caps(
174 __in unsigned int field_ncaps,
175 __out_ecount(field_ncaps) efx_mae_field_cap_t *field_caps)
178 EFX_MCDI_DECLARE_BUF(payload,
179 MC_CMD_MAE_GET_AR_CAPS_IN_LEN,
180 MC_CMD_MAE_GET_AR_CAPS_OUT_LENMAX_MCDI2);
181 unsigned int mcdi_field_ncaps;
185 if (MC_CMD_MAE_GET_AR_CAPS_OUT_LEN(field_ncaps) >
186 MC_CMD_MAE_GET_AR_CAPS_OUT_LENMAX_MCDI2) {
191 req.emr_cmd = MC_CMD_MAE_GET_AR_CAPS;
192 req.emr_in_buf = payload;
193 req.emr_in_length = MC_CMD_MAE_GET_AR_CAPS_IN_LEN;
194 req.emr_out_buf = payload;
195 req.emr_out_length = MC_CMD_MAE_GET_AR_CAPS_OUT_LEN(field_ncaps);
197 efx_mcdi_execute(enp, &req);
199 if (req.emr_rc != 0) {
204 if (req.emr_out_length_used < MC_CMD_MAE_GET_AR_CAPS_OUT_LENMIN) {
209 mcdi_field_ncaps = MCDI_OUT_DWORD(req, MAE_GET_AR_CAPS_OUT_COUNT);
211 if (req.emr_out_length_used <
212 MC_CMD_MAE_GET_AR_CAPS_OUT_LEN(mcdi_field_ncaps)) {
217 if (mcdi_field_ncaps > field_ncaps) {
222 for (i = 0; i < mcdi_field_ncaps; ++i) {
226 field_caps[i].emfc_support = MCDI_OUT_INDEXED_DWORD_FIELD(req,
227 MAE_GET_AR_CAPS_OUT_FIELD_FLAGS, i,
228 MAE_FIELD_FLAGS_SUPPORT_STATUS);
230 match_flag = MCDI_OUT_INDEXED_DWORD_FIELD(req,
231 MAE_GET_AR_CAPS_OUT_FIELD_FLAGS, i,
232 MAE_FIELD_FLAGS_MATCH_AFFECTS_CLASS);
234 field_caps[i].emfc_match_affects_class =
235 (match_flag != 0) ? B_TRUE : B_FALSE;
237 mask_flag = MCDI_OUT_INDEXED_DWORD_FIELD(req,
238 MAE_GET_AR_CAPS_OUT_FIELD_FLAGS, i,
239 MAE_FIELD_FLAGS_MASK_AFFECTS_CLASS);
241 field_caps[i].emfc_mask_affects_class =
242 (mask_flag != 0) ? B_TRUE : B_FALSE;
256 EFSYS_PROBE1(fail1, efx_rc_t, rc);
260 __checkReturn efx_rc_t
264 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
265 efx_mae_field_cap_t *or_fcaps;
266 size_t or_fcaps_size;
267 efx_mae_field_cap_t *ar_fcaps;
268 size_t ar_fcaps_size;
272 if (encp->enc_mae_supported == B_FALSE) {
277 EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (*maep), maep);
285 rc = efx_mae_get_capabilities(enp);
289 or_fcaps_size = maep->em_max_nfields * sizeof (*or_fcaps);
290 EFSYS_KMEM_ALLOC(enp->en_esip, or_fcaps_size, or_fcaps);
291 if (or_fcaps == NULL) {
296 maep->em_outer_rule_field_caps_size = or_fcaps_size;
297 maep->em_outer_rule_field_caps = or_fcaps;
299 rc = efx_mae_get_outer_rule_caps(enp, maep->em_max_nfields, or_fcaps);
303 ar_fcaps_size = maep->em_max_nfields * sizeof (*ar_fcaps);
304 EFSYS_KMEM_ALLOC(enp->en_esip, ar_fcaps_size, ar_fcaps);
305 if (ar_fcaps == NULL) {
310 maep->em_action_rule_field_caps_size = ar_fcaps_size;
311 maep->em_action_rule_field_caps = ar_fcaps;
313 rc = efx_mae_get_action_rule_caps(enp, maep->em_max_nfields, ar_fcaps);
321 EFSYS_KMEM_FREE(enp->en_esip, ar_fcaps_size, ar_fcaps);
326 EFSYS_KMEM_FREE(enp->en_esip, or_fcaps_size, or_fcaps);
331 EFSYS_KMEM_FREE(enp->en_esip, sizeof (struct efx_mae_s), enp->en_maep);
336 EFSYS_PROBE1(fail1, efx_rc_t, rc);
344 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
345 efx_mae_t *maep = enp->en_maep;
347 if (encp->enc_mae_supported == B_FALSE)
350 EFSYS_KMEM_FREE(enp->en_esip, maep->em_action_rule_field_caps_size,
351 maep->em_action_rule_field_caps);
352 EFSYS_KMEM_FREE(enp->en_esip, maep->em_outer_rule_field_caps_size,
353 maep->em_outer_rule_field_caps);
354 EFSYS_KMEM_FREE(enp->en_esip, sizeof (*maep), maep);
358 __checkReturn efx_rc_t
361 __out efx_mae_limits_t *emlp)
363 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
364 struct efx_mae_s *maep = enp->en_maep;
367 if (encp->enc_mae_supported == B_FALSE) {
372 emlp->eml_max_n_outer_prios = maep->em_max_n_outer_prios;
373 emlp->eml_max_n_action_prios = maep->em_max_n_action_prios;
374 emlp->eml_encap_types_supported = maep->em_encap_types_supported;
375 emlp->eml_encap_header_size_limit =
376 MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_MAXNUM_MCDI2;
377 emlp->eml_max_n_counters = maep->em_max_ncounters;
382 EFSYS_PROBE1(fail1, efx_rc_t, rc);
386 __checkReturn efx_rc_t
387 efx_mae_match_spec_init(
389 __in efx_mae_rule_type_t type,
391 __out efx_mae_match_spec_t **specp)
393 efx_mae_match_spec_t *spec;
397 case EFX_MAE_RULE_OUTER:
399 case EFX_MAE_RULE_ACTION:
406 EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (*spec), spec);
412 spec->emms_type = type;
413 spec->emms_prio = prio;
422 EFSYS_PROBE1(fail1, efx_rc_t, rc);
427 efx_mae_match_spec_fini(
429 __in efx_mae_match_spec_t *spec)
431 EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec), spec);
434 /* Named identifiers which are valid indices to efx_mae_field_cap_t */
435 typedef enum efx_mae_field_cap_id_e {
436 EFX_MAE_FIELD_ID_INGRESS_MPORT_SELECTOR = MAE_FIELD_INGRESS_PORT,
437 EFX_MAE_FIELD_ID_ETHER_TYPE_BE = MAE_FIELD_ETHER_TYPE,
438 EFX_MAE_FIELD_ID_ETH_SADDR_BE = MAE_FIELD_ETH_SADDR,
439 EFX_MAE_FIELD_ID_ETH_DADDR_BE = MAE_FIELD_ETH_DADDR,
440 EFX_MAE_FIELD_ID_VLAN0_TCI_BE = MAE_FIELD_VLAN0_TCI,
441 EFX_MAE_FIELD_ID_VLAN0_PROTO_BE = MAE_FIELD_VLAN0_PROTO,
442 EFX_MAE_FIELD_ID_VLAN1_TCI_BE = MAE_FIELD_VLAN1_TCI,
443 EFX_MAE_FIELD_ID_VLAN1_PROTO_BE = MAE_FIELD_VLAN1_PROTO,
444 EFX_MAE_FIELD_ID_SRC_IP4_BE = MAE_FIELD_SRC_IP4,
445 EFX_MAE_FIELD_ID_DST_IP4_BE = MAE_FIELD_DST_IP4,
446 EFX_MAE_FIELD_ID_IP_PROTO = MAE_FIELD_IP_PROTO,
447 EFX_MAE_FIELD_ID_IP_TOS = MAE_FIELD_IP_TOS,
448 EFX_MAE_FIELD_ID_IP_TTL = MAE_FIELD_IP_TTL,
449 EFX_MAE_FIELD_ID_SRC_IP6_BE = MAE_FIELD_SRC_IP6,
450 EFX_MAE_FIELD_ID_DST_IP6_BE = MAE_FIELD_DST_IP6,
451 EFX_MAE_FIELD_ID_L4_SPORT_BE = MAE_FIELD_L4_SPORT,
452 EFX_MAE_FIELD_ID_L4_DPORT_BE = MAE_FIELD_L4_DPORT,
453 EFX_MAE_FIELD_ID_TCP_FLAGS_BE = MAE_FIELD_TCP_FLAGS,
454 EFX_MAE_FIELD_ID_ENC_ETHER_TYPE_BE = MAE_FIELD_ENC_ETHER_TYPE,
455 EFX_MAE_FIELD_ID_ENC_ETH_SADDR_BE = MAE_FIELD_ENC_ETH_SADDR,
456 EFX_MAE_FIELD_ID_ENC_ETH_DADDR_BE = MAE_FIELD_ENC_ETH_DADDR,
457 EFX_MAE_FIELD_ID_ENC_VLAN0_TCI_BE = MAE_FIELD_ENC_VLAN0_TCI,
458 EFX_MAE_FIELD_ID_ENC_VLAN0_PROTO_BE = MAE_FIELD_ENC_VLAN0_PROTO,
459 EFX_MAE_FIELD_ID_ENC_VLAN1_TCI_BE = MAE_FIELD_ENC_VLAN1_TCI,
460 EFX_MAE_FIELD_ID_ENC_VLAN1_PROTO_BE = MAE_FIELD_ENC_VLAN1_PROTO,
461 EFX_MAE_FIELD_ID_ENC_SRC_IP4_BE = MAE_FIELD_ENC_SRC_IP4,
462 EFX_MAE_FIELD_ID_ENC_DST_IP4_BE = MAE_FIELD_ENC_DST_IP4,
463 EFX_MAE_FIELD_ID_ENC_IP_PROTO = MAE_FIELD_ENC_IP_PROTO,
464 EFX_MAE_FIELD_ID_ENC_IP_TOS = MAE_FIELD_ENC_IP_TOS,
465 EFX_MAE_FIELD_ID_ENC_IP_TTL = MAE_FIELD_ENC_IP_TTL,
466 EFX_MAE_FIELD_ID_ENC_SRC_IP6_BE = MAE_FIELD_ENC_SRC_IP6,
467 EFX_MAE_FIELD_ID_ENC_DST_IP6_BE = MAE_FIELD_ENC_DST_IP6,
468 EFX_MAE_FIELD_ID_ENC_L4_SPORT_BE = MAE_FIELD_ENC_L4_SPORT,
469 EFX_MAE_FIELD_ID_ENC_L4_DPORT_BE = MAE_FIELD_ENC_L4_DPORT,
470 EFX_MAE_FIELD_ID_ENC_VNET_ID_BE = MAE_FIELD_ENC_VNET_ID,
471 EFX_MAE_FIELD_ID_OUTER_RULE_ID = MAE_FIELD_OUTER_RULE_ID,
472 EFX_MAE_FIELD_ID_HAS_OVLAN = MAE_FIELD_HAS_OVLAN,
473 EFX_MAE_FIELD_ID_HAS_IVLAN = MAE_FIELD_HAS_IVLAN,
474 EFX_MAE_FIELD_ID_ENC_HAS_OVLAN = MAE_FIELD_ENC_HAS_OVLAN,
475 EFX_MAE_FIELD_ID_ENC_HAS_IVLAN = MAE_FIELD_ENC_HAS_IVLAN,
477 EFX_MAE_FIELD_CAP_NIDS
478 } efx_mae_field_cap_id_t;
480 typedef enum efx_mae_field_endianness_e {
481 EFX_MAE_FIELD_LE = 0,
484 EFX_MAE_FIELD_ENDIANNESS_NTYPES
485 } efx_mae_field_endianness_t;
488 * The following structure is a means to describe an MAE field.
489 * The information in it is meant to be used internally by
490 * APIs for addressing a given field in a mask-value pairs
491 * structure and for validation purposes.
493 * A field may have an alternative one. This structure
494 * has additional members to reference the alternative
495 * field's mask. See efx_mae_match_spec_is_valid().
497 typedef struct efx_mae_mv_desc_s {
498 efx_mae_field_cap_id_t emmd_field_cap_id;
500 size_t emmd_value_size;
501 size_t emmd_value_offset;
502 size_t emmd_mask_size;
503 size_t emmd_mask_offset;
506 * Having the alternative field's mask size set to 0
507 * means that there's no alternative field specified.
509 size_t emmd_alt_mask_size;
510 size_t emmd_alt_mask_offset;
512 /* Primary field and the alternative one are of the same endianness. */
513 efx_mae_field_endianness_t emmd_endianness;
516 /* Indices to this array are provided by efx_mae_field_id_t */
517 static const efx_mae_mv_desc_t __efx_mae_action_rule_mv_desc_set[] = {
518 #define EFX_MAE_MV_DESC(_name, _endianness) \
519 [EFX_MAE_FIELD_##_name] = \
521 EFX_MAE_FIELD_ID_##_name, \
522 MAE_FIELD_MASK_VALUE_PAIRS_##_name##_LEN, \
523 MAE_FIELD_MASK_VALUE_PAIRS_##_name##_OFST, \
524 MAE_FIELD_MASK_VALUE_PAIRS_##_name##_MASK_LEN, \
525 MAE_FIELD_MASK_VALUE_PAIRS_##_name##_MASK_OFST, \
526 0, 0 /* no alternative field */, \
530 EFX_MAE_MV_DESC(INGRESS_MPORT_SELECTOR, EFX_MAE_FIELD_LE),
531 EFX_MAE_MV_DESC(ETHER_TYPE_BE, EFX_MAE_FIELD_BE),
532 EFX_MAE_MV_DESC(ETH_SADDR_BE, EFX_MAE_FIELD_BE),
533 EFX_MAE_MV_DESC(ETH_DADDR_BE, EFX_MAE_FIELD_BE),
534 EFX_MAE_MV_DESC(VLAN0_TCI_BE, EFX_MAE_FIELD_BE),
535 EFX_MAE_MV_DESC(VLAN0_PROTO_BE, EFX_MAE_FIELD_BE),
536 EFX_MAE_MV_DESC(VLAN1_TCI_BE, EFX_MAE_FIELD_BE),
537 EFX_MAE_MV_DESC(VLAN1_PROTO_BE, EFX_MAE_FIELD_BE),
538 EFX_MAE_MV_DESC(SRC_IP4_BE, EFX_MAE_FIELD_BE),
539 EFX_MAE_MV_DESC(DST_IP4_BE, EFX_MAE_FIELD_BE),
540 EFX_MAE_MV_DESC(IP_PROTO, EFX_MAE_FIELD_BE),
541 EFX_MAE_MV_DESC(IP_TOS, EFX_MAE_FIELD_BE),
542 EFX_MAE_MV_DESC(IP_TTL, EFX_MAE_FIELD_BE),
543 EFX_MAE_MV_DESC(SRC_IP6_BE, EFX_MAE_FIELD_BE),
544 EFX_MAE_MV_DESC(DST_IP6_BE, EFX_MAE_FIELD_BE),
545 EFX_MAE_MV_DESC(L4_SPORT_BE, EFX_MAE_FIELD_BE),
546 EFX_MAE_MV_DESC(L4_DPORT_BE, EFX_MAE_FIELD_BE),
547 EFX_MAE_MV_DESC(TCP_FLAGS_BE, EFX_MAE_FIELD_BE),
548 EFX_MAE_MV_DESC(ENC_VNET_ID_BE, EFX_MAE_FIELD_BE),
549 EFX_MAE_MV_DESC(OUTER_RULE_ID, EFX_MAE_FIELD_LE),
551 #undef EFX_MAE_MV_DESC
554 /* Indices to this array are provided by efx_mae_field_id_t */
555 static const efx_mae_mv_desc_t __efx_mae_outer_rule_mv_desc_set[] = {
556 #define EFX_MAE_MV_DESC(_name, _endianness) \
557 [EFX_MAE_FIELD_##_name] = \
559 EFX_MAE_FIELD_ID_##_name, \
560 MAE_ENC_FIELD_PAIRS_##_name##_LEN, \
561 MAE_ENC_FIELD_PAIRS_##_name##_OFST, \
562 MAE_ENC_FIELD_PAIRS_##_name##_MASK_LEN, \
563 MAE_ENC_FIELD_PAIRS_##_name##_MASK_OFST, \
564 0, 0 /* no alternative field */, \
568 /* Same as EFX_MAE_MV_DESC(), but also indicates an alternative field. */
569 #define EFX_MAE_MV_DESC_ALT(_name, _alt_name, _endianness) \
570 [EFX_MAE_FIELD_##_name] = \
572 EFX_MAE_FIELD_ID_##_name, \
573 MAE_ENC_FIELD_PAIRS_##_name##_LEN, \
574 MAE_ENC_FIELD_PAIRS_##_name##_OFST, \
575 MAE_ENC_FIELD_PAIRS_##_name##_MASK_LEN, \
576 MAE_ENC_FIELD_PAIRS_##_name##_MASK_OFST, \
577 MAE_ENC_FIELD_PAIRS_##_alt_name##_MASK_LEN, \
578 MAE_ENC_FIELD_PAIRS_##_alt_name##_MASK_OFST, \
582 EFX_MAE_MV_DESC(INGRESS_MPORT_SELECTOR, EFX_MAE_FIELD_LE),
583 EFX_MAE_MV_DESC(ENC_ETHER_TYPE_BE, EFX_MAE_FIELD_BE),
584 EFX_MAE_MV_DESC(ENC_ETH_SADDR_BE, EFX_MAE_FIELD_BE),
585 EFX_MAE_MV_DESC(ENC_ETH_DADDR_BE, EFX_MAE_FIELD_BE),
586 EFX_MAE_MV_DESC(ENC_VLAN0_TCI_BE, EFX_MAE_FIELD_BE),
587 EFX_MAE_MV_DESC(ENC_VLAN0_PROTO_BE, EFX_MAE_FIELD_BE),
588 EFX_MAE_MV_DESC(ENC_VLAN1_TCI_BE, EFX_MAE_FIELD_BE),
589 EFX_MAE_MV_DESC(ENC_VLAN1_PROTO_BE, EFX_MAE_FIELD_BE),
590 EFX_MAE_MV_DESC_ALT(ENC_SRC_IP4_BE, ENC_SRC_IP6_BE, EFX_MAE_FIELD_BE),
591 EFX_MAE_MV_DESC_ALT(ENC_DST_IP4_BE, ENC_DST_IP6_BE, EFX_MAE_FIELD_BE),
592 EFX_MAE_MV_DESC(ENC_IP_PROTO, EFX_MAE_FIELD_BE),
593 EFX_MAE_MV_DESC(ENC_IP_TOS, EFX_MAE_FIELD_BE),
594 EFX_MAE_MV_DESC(ENC_IP_TTL, EFX_MAE_FIELD_BE),
595 EFX_MAE_MV_DESC_ALT(ENC_SRC_IP6_BE, ENC_SRC_IP4_BE, EFX_MAE_FIELD_BE),
596 EFX_MAE_MV_DESC_ALT(ENC_DST_IP6_BE, ENC_DST_IP4_BE, EFX_MAE_FIELD_BE),
597 EFX_MAE_MV_DESC(ENC_L4_SPORT_BE, EFX_MAE_FIELD_BE),
598 EFX_MAE_MV_DESC(ENC_L4_DPORT_BE, EFX_MAE_FIELD_BE),
600 #undef EFX_MAE_MV_DESC_ALT
601 #undef EFX_MAE_MV_DESC
605 * The following structure is a means to describe an MAE bit.
606 * The information in it is meant to be used internally by
607 * APIs for addressing a given flag in a mask-value pairs
608 * structure and for validation purposes.
610 typedef struct efx_mae_mv_bit_desc_s {
612 * Arrays using this struct are indexed by field IDs.
613 * Fields which aren't meant to be referenced by these
614 * arrays comprise gaps (invalid entries). Below field
615 * helps to identify such entries.
617 boolean_t emmbd_entry_is_valid;
618 efx_mae_field_cap_id_t emmbd_bit_cap_id;
619 size_t emmbd_value_ofst;
620 unsigned int emmbd_value_lbn;
621 size_t emmbd_mask_ofst;
622 unsigned int emmbd_mask_lbn;
623 } efx_mae_mv_bit_desc_t;
625 static const efx_mae_mv_bit_desc_t __efx_mae_outer_rule_mv_bit_desc_set[] = {
626 #define EFX_MAE_MV_BIT_DESC(_name) \
627 [EFX_MAE_FIELD_##_name] = \
630 EFX_MAE_FIELD_ID_##_name, \
631 MAE_ENC_FIELD_PAIRS_##_name##_OFST, \
632 MAE_ENC_FIELD_PAIRS_##_name##_LBN, \
633 MAE_ENC_FIELD_PAIRS_##_name##_MASK_OFST, \
634 MAE_ENC_FIELD_PAIRS_##_name##_MASK_LBN, \
637 EFX_MAE_MV_BIT_DESC(ENC_HAS_OVLAN),
638 EFX_MAE_MV_BIT_DESC(ENC_HAS_IVLAN),
640 #undef EFX_MAE_MV_BIT_DESC
643 static const efx_mae_mv_bit_desc_t __efx_mae_action_rule_mv_bit_desc_set[] = {
644 #define EFX_MAE_MV_BIT_DESC(_name) \
645 [EFX_MAE_FIELD_##_name] = \
648 EFX_MAE_FIELD_ID_##_name, \
649 MAE_FIELD_MASK_VALUE_PAIRS_V2_FLAGS_OFST, \
650 MAE_FIELD_MASK_VALUE_PAIRS_V2_##_name##_LBN, \
651 MAE_FIELD_MASK_VALUE_PAIRS_V2_FLAGS_MASK_OFST, \
652 MAE_FIELD_MASK_VALUE_PAIRS_V2_##_name##_LBN, \
655 EFX_MAE_MV_BIT_DESC(HAS_OVLAN),
656 EFX_MAE_MV_BIT_DESC(HAS_IVLAN),
657 EFX_MAE_MV_BIT_DESC(ENC_HAS_OVLAN),
658 EFX_MAE_MV_BIT_DESC(ENC_HAS_IVLAN),
660 #undef EFX_MAE_MV_BIT_DESC
663 __checkReturn efx_rc_t
664 efx_mae_mport_invalid(
665 __out efx_mport_sel_t *mportp)
670 if (mportp == NULL) {
675 EFX_POPULATE_DWORD_1(dword,
676 MAE_MPORT_SELECTOR_TYPE, MAE_MPORT_SELECTOR_TYPE_INVALID);
678 memset(mportp, 0, sizeof (*mportp));
679 mportp->sel = dword.ed_u32[0];
684 EFSYS_PROBE1(fail1, efx_rc_t, rc);
688 __checkReturn efx_rc_t
689 efx_mae_mport_by_phy_port(
690 __in uint32_t phy_port,
691 __out efx_mport_sel_t *mportp)
696 if (phy_port > EFX_MASK32(MAE_MPORT_SELECTOR_PPORT_ID)) {
701 EFX_POPULATE_DWORD_2(dword,
702 MAE_MPORT_SELECTOR_TYPE, MAE_MPORT_SELECTOR_TYPE_PPORT,
703 MAE_MPORT_SELECTOR_PPORT_ID, phy_port);
705 memset(mportp, 0, sizeof (*mportp));
707 * The constructed DWORD is little-endian,
708 * but the resulting value is meant to be
709 * passed to MCDIs, where it will undergo
710 * host-order to little endian conversion.
712 mportp->sel = EFX_DWORD_FIELD(dword, EFX_DWORD_0);
717 EFSYS_PROBE1(fail1, efx_rc_t, rc);
721 __checkReturn efx_rc_t
722 efx_mae_mport_by_pcie_function(
725 __out efx_mport_sel_t *mportp)
730 EFX_STATIC_ASSERT(EFX_PCI_VF_INVALID ==
731 MAE_MPORT_SELECTOR_FUNC_VF_ID_NULL);
733 if (pf > EFX_MASK32(MAE_MPORT_SELECTOR_FUNC_PF_ID)) {
738 if (vf > EFX_MASK32(MAE_MPORT_SELECTOR_FUNC_VF_ID)) {
743 EFX_POPULATE_DWORD_3(dword,
744 MAE_MPORT_SELECTOR_TYPE, MAE_MPORT_SELECTOR_TYPE_FUNC,
745 MAE_MPORT_SELECTOR_FUNC_PF_ID, pf,
746 MAE_MPORT_SELECTOR_FUNC_VF_ID, vf);
748 memset(mportp, 0, sizeof (*mportp));
750 * The constructed DWORD is little-endian,
751 * but the resulting value is meant to be
752 * passed to MCDIs, where it will undergo
753 * host-order to little endian conversion.
755 mportp->sel = EFX_DWORD_FIELD(dword, EFX_DWORD_0);
762 EFSYS_PROBE1(fail1, efx_rc_t, rc);
766 static __checkReturn efx_rc_t
767 efx_mcdi_mae_mport_lookup(
769 __in const efx_mport_sel_t *mport_selectorp,
770 __out efx_mport_id_t *mport_idp)
773 EFX_MCDI_DECLARE_BUF(payload,
774 MC_CMD_MAE_MPORT_LOOKUP_IN_LEN,
775 MC_CMD_MAE_MPORT_LOOKUP_OUT_LEN);
778 req.emr_cmd = MC_CMD_MAE_MPORT_LOOKUP;
779 req.emr_in_buf = payload;
780 req.emr_in_length = MC_CMD_MAE_MPORT_LOOKUP_IN_LEN;
781 req.emr_out_buf = payload;
782 req.emr_out_length = MC_CMD_MAE_MPORT_LOOKUP_OUT_LEN;
784 MCDI_IN_SET_DWORD(req, MAE_MPORT_LOOKUP_IN_MPORT_SELECTOR,
785 mport_selectorp->sel);
787 efx_mcdi_execute(enp, &req);
789 if (req.emr_rc != 0) {
794 mport_idp->id = MCDI_OUT_DWORD(req, MAE_MPORT_LOOKUP_OUT_MPORT_ID);
799 EFSYS_PROBE1(fail1, efx_rc_t, rc);
803 __checkReturn efx_rc_t
804 efx_mae_mport_id_by_selector(
806 __in const efx_mport_sel_t *mport_selectorp,
807 __out efx_mport_id_t *mport_idp)
809 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
812 if (encp->enc_mae_supported == B_FALSE) {
817 rc = efx_mcdi_mae_mport_lookup(enp, mport_selectorp, mport_idp);
826 EFSYS_PROBE1(fail1, efx_rc_t, rc);
830 __checkReturn efx_rc_t
832 __in const efx_mport_id_t *mport_idp,
833 __out efx_mport_sel_t *mportp)
837 EFX_POPULATE_DWORD_2(dword,
838 MAE_MPORT_SELECTOR_TYPE, MAE_MPORT_SELECTOR_TYPE_MPORT_ID,
839 MAE_MPORT_SELECTOR_MPORT_ID, mport_idp->id);
841 memset(mportp, 0, sizeof (*mportp));
842 mportp->sel = __LE_TO_CPU_32(dword.ed_u32[0]);
847 __checkReturn efx_rc_t
848 efx_mae_match_spec_field_set(
849 __in efx_mae_match_spec_t *spec,
850 __in efx_mae_field_id_t field_id,
851 __in size_t value_size,
852 __in_bcount(value_size) const uint8_t *value,
853 __in size_t mask_size,
854 __in_bcount(mask_size) const uint8_t *mask)
856 const efx_mae_mv_desc_t *descp;
857 unsigned int desc_set_nentries;
861 switch (spec->emms_type) {
862 case EFX_MAE_RULE_OUTER:
864 EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_desc_set);
865 descp = &__efx_mae_outer_rule_mv_desc_set[field_id];
866 mvp = spec->emms_mask_value_pairs.outer;
868 case EFX_MAE_RULE_ACTION:
870 EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_desc_set);
871 descp = &__efx_mae_action_rule_mv_desc_set[field_id];
872 mvp = spec->emms_mask_value_pairs.action;
879 if ((unsigned int)field_id >= desc_set_nentries) {
884 if (descp->emmd_mask_size == 0) {
885 /* The ID points to a gap in the array of field descriptors. */
890 if (value_size != descp->emmd_value_size) {
895 if (mask_size != descp->emmd_mask_size) {
900 if (descp->emmd_endianness == EFX_MAE_FIELD_BE) {
904 * The mask/value are in network (big endian) order.
905 * The MCDI request field is also big endian.
908 EFSYS_ASSERT3U(value_size, ==, mask_size);
910 for (i = 0; i < value_size; ++i) {
911 uint8_t *v_bytep = mvp + descp->emmd_value_offset + i;
912 uint8_t *m_bytep = mvp + descp->emmd_mask_offset + i;
915 * Apply the mask (which may be all-zeros) to the value.
917 * If this API is provided with some value to set for a
918 * given field in one specification and with some other
919 * value to set for this field in another specification,
920 * then, if the two masks are all-zeros, the field will
921 * avoid being counted as a mismatch when comparing the
922 * specifications using efx_mae_match_specs_equal() API.
924 *v_bytep = value[i] & mask[i];
931 * The mask/value are in host byte order.
932 * The MCDI request field is little endian.
934 switch (value_size) {
936 EFX_POPULATE_DWORD_1(dword,
937 EFX_DWORD_0, *(const uint32_t *)value);
939 memcpy(mvp + descp->emmd_value_offset,
940 &dword, sizeof (dword));
943 EFSYS_ASSERT(B_FALSE);
948 EFX_POPULATE_DWORD_1(dword,
949 EFX_DWORD_0, *(const uint32_t *)mask);
951 memcpy(mvp + descp->emmd_mask_offset,
952 &dword, sizeof (dword));
955 EFSYS_ASSERT(B_FALSE);
970 EFSYS_PROBE1(fail1, efx_rc_t, rc);
974 __checkReturn efx_rc_t
975 efx_mae_match_spec_bit_set(
976 __in efx_mae_match_spec_t *spec,
977 __in efx_mae_field_id_t field_id,
978 __in boolean_t value)
980 const efx_mae_mv_bit_desc_t *bit_descp;
981 unsigned int bit_desc_set_nentries;
982 unsigned int byte_idx;
983 unsigned int bit_idx;
987 switch (spec->emms_type) {
988 case EFX_MAE_RULE_OUTER:
989 bit_desc_set_nentries =
990 EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_bit_desc_set);
991 bit_descp = &__efx_mae_outer_rule_mv_bit_desc_set[field_id];
992 mvp = spec->emms_mask_value_pairs.outer;
994 case EFX_MAE_RULE_ACTION:
995 bit_desc_set_nentries =
996 EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_bit_desc_set);
997 bit_descp = &__efx_mae_action_rule_mv_bit_desc_set[field_id];
998 mvp = spec->emms_mask_value_pairs.action;
1005 if ((unsigned int)field_id >= bit_desc_set_nentries) {
1010 if (bit_descp->emmbd_entry_is_valid == B_FALSE) {
1015 byte_idx = bit_descp->emmbd_value_ofst + bit_descp->emmbd_value_lbn / 8;
1016 bit_idx = bit_descp->emmbd_value_lbn % 8;
1018 if (value != B_FALSE)
1019 mvp[byte_idx] |= (1U << bit_idx);
1021 mvp[byte_idx] &= ~(1U << bit_idx);
1023 byte_idx = bit_descp->emmbd_mask_ofst + bit_descp->emmbd_mask_lbn / 8;
1024 bit_idx = bit_descp->emmbd_mask_lbn % 8;
1025 mvp[byte_idx] |= (1U << bit_idx);
1034 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1038 __checkReturn efx_rc_t
1039 efx_mae_match_spec_mport_set(
1040 __in efx_mae_match_spec_t *spec,
1041 __in const efx_mport_sel_t *valuep,
1042 __in_opt const efx_mport_sel_t *maskp)
1044 uint32_t full_mask = UINT32_MAX;
1049 if (valuep == NULL) {
1054 vp = (const uint8_t *)&valuep->sel;
1056 mp = (const uint8_t *)&maskp->sel;
1058 mp = (const uint8_t *)&full_mask;
1060 rc = efx_mae_match_spec_field_set(spec,
1061 EFX_MAE_FIELD_INGRESS_MPORT_SELECTOR,
1062 sizeof (valuep->sel), vp, sizeof (maskp->sel), mp);
1071 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1075 __checkReturn boolean_t
1076 efx_mae_match_specs_equal(
1077 __in const efx_mae_match_spec_t *left,
1078 __in const efx_mae_match_spec_t *right)
1080 return ((memcmp(left, right, sizeof (*left)) == 0) ? B_TRUE : B_FALSE);
1083 #define EFX_MASK_BIT_IS_SET(_mask, _mask_page_nbits, _bit) \
1084 ((_mask)[(_bit) / (_mask_page_nbits)] & \
1085 (1ULL << ((_bit) & ((_mask_page_nbits) - 1))))
1089 __in size_t mask_nbytes,
1090 __in_bcount(mask_nbytes) const uint8_t *maskp)
1092 boolean_t prev_bit_is_set = B_TRUE;
1095 for (i = 0; i < 8 * mask_nbytes; ++i) {
1096 boolean_t bit_is_set = EFX_MASK_BIT_IS_SET(maskp, 8, i);
1098 if (!prev_bit_is_set && bit_is_set)
1101 prev_bit_is_set = bit_is_set;
1108 efx_mask_is_all_ones(
1109 __in size_t mask_nbytes,
1110 __in_bcount(mask_nbytes) const uint8_t *maskp)
1115 for (i = 0; i < mask_nbytes; ++i)
1118 return (t == (uint8_t)(~0));
1122 efx_mask_is_all_zeros(
1123 __in size_t mask_nbytes,
1124 __in_bcount(mask_nbytes) const uint8_t *maskp)
1129 for (i = 0; i < mask_nbytes; ++i)
1135 __checkReturn boolean_t
1136 efx_mae_match_spec_is_valid(
1137 __in efx_nic_t *enp,
1138 __in const efx_mae_match_spec_t *spec)
1140 efx_mae_t *maep = enp->en_maep;
1141 unsigned int field_ncaps = maep->em_max_nfields;
1142 const efx_mae_field_cap_t *field_caps;
1143 const efx_mae_mv_desc_t *desc_setp;
1144 unsigned int desc_set_nentries;
1145 const efx_mae_mv_bit_desc_t *bit_desc_setp;
1146 unsigned int bit_desc_set_nentries;
1147 boolean_t is_valid = B_TRUE;
1148 efx_mae_field_id_t field_id;
1151 switch (spec->emms_type) {
1152 case EFX_MAE_RULE_OUTER:
1153 field_caps = maep->em_outer_rule_field_caps;
1154 desc_setp = __efx_mae_outer_rule_mv_desc_set;
1156 EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_desc_set);
1157 bit_desc_setp = __efx_mae_outer_rule_mv_bit_desc_set;
1158 bit_desc_set_nentries =
1159 EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_bit_desc_set);
1160 mvp = spec->emms_mask_value_pairs.outer;
1162 case EFX_MAE_RULE_ACTION:
1163 field_caps = maep->em_action_rule_field_caps;
1164 desc_setp = __efx_mae_action_rule_mv_desc_set;
1166 EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_desc_set);
1167 bit_desc_setp = __efx_mae_action_rule_mv_bit_desc_set;
1168 bit_desc_set_nentries =
1169 EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_bit_desc_set);
1170 mvp = spec->emms_mask_value_pairs.action;
1176 if (field_caps == NULL)
1179 for (field_id = 0; (unsigned int)field_id < desc_set_nentries;
1181 const efx_mae_mv_desc_t *descp = &desc_setp[field_id];
1182 efx_mae_field_cap_id_t field_cap_id = descp->emmd_field_cap_id;
1183 const uint8_t *alt_m_buf = mvp + descp->emmd_alt_mask_offset;
1184 const uint8_t *m_buf = mvp + descp->emmd_mask_offset;
1185 size_t alt_m_size = descp->emmd_alt_mask_size;
1186 size_t m_size = descp->emmd_mask_size;
1189 continue; /* Skip array gap */
1191 if ((unsigned int)field_cap_id >= field_ncaps) {
1193 * The FW has not reported capability status for
1194 * this field. Make sure that its mask is zeroed.
1196 is_valid = efx_mask_is_all_zeros(m_size, m_buf);
1197 if (is_valid != B_FALSE)
1203 switch (field_caps[field_cap_id].emfc_support) {
1204 case MAE_FIELD_SUPPORTED_MATCH_MASK:
1207 case MAE_FIELD_SUPPORTED_MATCH_PREFIX:
1208 is_valid = efx_mask_is_prefix(m_size, m_buf);
1210 case MAE_FIELD_SUPPORTED_MATCH_OPTIONAL:
1211 is_valid = (efx_mask_is_all_ones(m_size, m_buf) ||
1212 efx_mask_is_all_zeros(m_size, m_buf));
1214 case MAE_FIELD_SUPPORTED_MATCH_ALWAYS:
1215 is_valid = efx_mask_is_all_ones(m_size, m_buf);
1217 if ((is_valid == B_FALSE) && (alt_m_size != 0)) {
1219 * This field has an alternative one. The FW
1220 * reports ALWAYS for both implying that one
1221 * of them is required to have all-ones mask.
1223 * The primary field's mask is incorrect; go
1224 * on to check that of the alternative field.
1226 is_valid = efx_mask_is_all_ones(alt_m_size,
1230 case MAE_FIELD_SUPPORTED_MATCH_NEVER:
1231 case MAE_FIELD_UNSUPPORTED:
1233 is_valid = efx_mask_is_all_zeros(m_size, m_buf);
1237 if (is_valid == B_FALSE)
1241 for (field_id = 0; (unsigned int)field_id < bit_desc_set_nentries;
1243 const efx_mae_mv_bit_desc_t *bit_descp =
1244 &bit_desc_setp[field_id];
1245 unsigned int byte_idx =
1246 bit_descp->emmbd_mask_ofst +
1247 bit_descp->emmbd_mask_lbn / 8;
1248 unsigned int bit_idx =
1249 bit_descp->emmbd_mask_lbn % 8;
1250 efx_mae_field_cap_id_t bit_cap_id =
1251 bit_descp->emmbd_bit_cap_id;
1253 if (bit_descp->emmbd_entry_is_valid == B_FALSE)
1254 continue; /* Skip array gap */
1256 if ((unsigned int)bit_cap_id >= field_ncaps) {
1257 /* No capability for this bit = unsupported. */
1258 is_valid = ((mvp[byte_idx] & (1U << bit_idx)) == 0);
1259 if (is_valid == B_FALSE)
1265 switch (field_caps[bit_cap_id].emfc_support) {
1266 case MAE_FIELD_SUPPORTED_MATCH_OPTIONAL:
1269 case MAE_FIELD_SUPPORTED_MATCH_ALWAYS:
1270 is_valid = ((mvp[byte_idx] & (1U << bit_idx)) != 0);
1272 case MAE_FIELD_SUPPORTED_MATCH_NEVER:
1273 case MAE_FIELD_UNSUPPORTED:
1275 is_valid = ((mvp[byte_idx] & (1U << bit_idx)) == 0);
1279 if (is_valid == B_FALSE)
1286 __checkReturn efx_rc_t
1287 efx_mae_action_set_spec_init(
1288 __in efx_nic_t *enp,
1289 __out efx_mae_actions_t **specp)
1291 efx_mae_actions_t *spec;
1294 EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (*spec), spec);
1300 spec->ema_rsrc.emar_eh_id.id = EFX_MAE_RSRC_ID_INVALID;
1301 spec->ema_rsrc.emar_counter_id.id = EFX_MAE_RSRC_ID_INVALID;
1308 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1313 efx_mae_action_set_spec_fini(
1314 __in efx_nic_t *enp,
1315 __in efx_mae_actions_t *spec)
1317 EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec), spec);
1320 static __checkReturn efx_rc_t
1321 efx_mae_action_set_add_decap(
1322 __in efx_mae_actions_t *spec,
1323 __in size_t arg_size,
1324 __in_bcount(arg_size) const uint8_t *arg)
1328 _NOTE(ARGUNUSED(spec))
1330 if (arg_size != 0) {
1340 /* This action does not have any arguments, so do nothing here. */
1347 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1351 static __checkReturn efx_rc_t
1352 efx_mae_action_set_add_vlan_pop(
1353 __in efx_mae_actions_t *spec,
1354 __in size_t arg_size,
1355 __in_bcount(arg_size) const uint8_t *arg)
1359 if (arg_size != 0) {
1369 if (spec->ema_n_vlan_tags_to_pop == EFX_MAE_VLAN_POP_MAX_NTAGS) {
1374 ++spec->ema_n_vlan_tags_to_pop;
1383 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1387 static __checkReturn efx_rc_t
1388 efx_mae_action_set_add_vlan_push(
1389 __in efx_mae_actions_t *spec,
1390 __in size_t arg_size,
1391 __in_bcount(arg_size) const uint8_t *arg)
1393 unsigned int n_tags = spec->ema_n_vlan_tags_to_push;
1396 if (arg_size != sizeof (*spec->ema_vlan_push_descs)) {
1406 if (n_tags == EFX_MAE_VLAN_PUSH_MAX_NTAGS) {
1411 memcpy(&spec->ema_vlan_push_descs[n_tags], arg, arg_size);
1412 ++(spec->ema_n_vlan_tags_to_push);
1421 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1425 static __checkReturn efx_rc_t
1426 efx_mae_action_set_add_encap(
1427 __in efx_mae_actions_t *spec,
1428 __in size_t arg_size,
1429 __in_bcount(arg_size) const uint8_t *arg)
1434 * Adding this specific action to an action set spec and setting encap.
1435 * header ID in the spec are two individual steps. This design allows
1436 * the client driver to avoid encap. header allocation when it simply
1437 * needs to check the order of actions submitted by user ("validate"),
1438 * without actually allocating an action set and inserting a rule.
1440 * For now, mark encap. header ID as invalid; the caller will invoke
1441 * efx_mae_action_set_fill_in_eh_id() to override the field prior
1442 * to action set allocation; otherwise, the allocation will fail.
1444 spec->ema_rsrc.emar_eh_id.id = EFX_MAE_RSRC_ID_INVALID;
1447 * As explained above, there are no arguments to handle here.
1448 * efx_mae_action_set_fill_in_eh_id() will take care of them.
1450 if (arg_size != 0) {
1465 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1469 static __checkReturn efx_rc_t
1470 efx_mae_action_set_add_count(
1471 __in efx_mae_actions_t *spec,
1472 __in size_t arg_size,
1473 __in_bcount(arg_size) const uint8_t *arg)
1477 EFX_STATIC_ASSERT(EFX_MAE_RSRC_ID_INVALID ==
1478 MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_NULL);
1481 * Preparing an action set spec to update a counter requires
1482 * two steps: first add this action to the action spec, and then
1483 * add the counter ID to the spec. This allows validity checking
1484 * and resource allocation to be done separately.
1485 * Mark the counter ID as invalid in the spec to ensure that the
1486 * caller must also invoke efx_mae_action_set_fill_in_counter_id()
1487 * before action set allocation.
1489 spec->ema_rsrc.emar_counter_id.id = EFX_MAE_RSRC_ID_INVALID;
1491 /* Nothing else is supposed to take place over here. */
1492 if (arg_size != 0) {
1502 ++(spec->ema_n_count_actions);
1509 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1513 static __checkReturn efx_rc_t
1514 efx_mae_action_set_add_flag(
1515 __in efx_mae_actions_t *spec,
1516 __in size_t arg_size,
1517 __in_bcount(arg_size) const uint8_t *arg)
1521 _NOTE(ARGUNUSED(spec))
1523 if (arg_size != 0) {
1533 /* This action does not have any arguments, so do nothing here. */
1540 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1544 static __checkReturn efx_rc_t
1545 efx_mae_action_set_add_mark(
1546 __in efx_mae_actions_t *spec,
1547 __in size_t arg_size,
1548 __in_bcount(arg_size) const uint8_t *arg)
1552 if (arg_size != sizeof (spec->ema_mark_value)) {
1562 memcpy(&spec->ema_mark_value, arg, arg_size);
1569 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1573 static __checkReturn efx_rc_t
1574 efx_mae_action_set_add_deliver(
1575 __in efx_mae_actions_t *spec,
1576 __in size_t arg_size,
1577 __in_bcount(arg_size) const uint8_t *arg)
1581 if (arg_size != sizeof (spec->ema_deliver_mport)) {
1591 memcpy(&spec->ema_deliver_mport, arg, arg_size);
1598 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1602 typedef struct efx_mae_action_desc_s {
1603 /* Action specific handler */
1604 efx_rc_t (*emad_add)(efx_mae_actions_t *,
1605 size_t, const uint8_t *);
1606 } efx_mae_action_desc_t;
1608 static const efx_mae_action_desc_t efx_mae_actions[EFX_MAE_NACTIONS] = {
1609 [EFX_MAE_ACTION_DECAP] = {
1610 .emad_add = efx_mae_action_set_add_decap
1612 [EFX_MAE_ACTION_VLAN_POP] = {
1613 .emad_add = efx_mae_action_set_add_vlan_pop
1615 [EFX_MAE_ACTION_VLAN_PUSH] = {
1616 .emad_add = efx_mae_action_set_add_vlan_push
1618 [EFX_MAE_ACTION_ENCAP] = {
1619 .emad_add = efx_mae_action_set_add_encap
1621 [EFX_MAE_ACTION_COUNT] = {
1622 .emad_add = efx_mae_action_set_add_count
1624 [EFX_MAE_ACTION_FLAG] = {
1625 .emad_add = efx_mae_action_set_add_flag
1627 [EFX_MAE_ACTION_MARK] = {
1628 .emad_add = efx_mae_action_set_add_mark
1630 [EFX_MAE_ACTION_DELIVER] = {
1631 .emad_add = efx_mae_action_set_add_deliver
1635 static const uint32_t efx_mae_action_ordered_map =
1636 (1U << EFX_MAE_ACTION_DECAP) |
1637 (1U << EFX_MAE_ACTION_VLAN_POP) |
1638 (1U << EFX_MAE_ACTION_VLAN_PUSH) |
1640 * HW will conduct action COUNT after
1641 * the matching packet has been modified by
1642 * length-affecting actions except for ENCAP.
1644 (1U << EFX_MAE_ACTION_COUNT) |
1645 (1U << EFX_MAE_ACTION_ENCAP) |
1646 (1U << EFX_MAE_ACTION_FLAG) |
1647 (1U << EFX_MAE_ACTION_MARK) |
1648 (1U << EFX_MAE_ACTION_DELIVER);
1651 * These actions must not be added after DELIVER, but
1652 * they can have any place among the rest of
1653 * strictly ordered actions.
1655 static const uint32_t efx_mae_action_nonstrict_map =
1656 (1U << EFX_MAE_ACTION_COUNT) |
1657 (1U << EFX_MAE_ACTION_FLAG) |
1658 (1U << EFX_MAE_ACTION_MARK);
1660 static const uint32_t efx_mae_action_repeat_map =
1661 (1U << EFX_MAE_ACTION_VLAN_POP) |
1662 (1U << EFX_MAE_ACTION_VLAN_PUSH) |
1663 (1U << EFX_MAE_ACTION_COUNT);
1666 * Add an action to an action set.
1668 * This has to be invoked in the desired action order.
1669 * An out-of-order action request will be turned down.
1671 static __checkReturn efx_rc_t
1672 efx_mae_action_set_spec_populate(
1673 __in efx_mae_actions_t *spec,
1674 __in efx_mae_action_t type,
1675 __in size_t arg_size,
1676 __in_bcount(arg_size) const uint8_t *arg)
1678 uint32_t action_mask;
1681 EFX_STATIC_ASSERT(EFX_MAE_NACTIONS <=
1682 (sizeof (efx_mae_action_ordered_map) * 8));
1683 EFX_STATIC_ASSERT(EFX_MAE_NACTIONS <=
1684 (sizeof (efx_mae_action_repeat_map) * 8));
1686 EFX_STATIC_ASSERT(EFX_MAE_ACTION_DELIVER + 1 == EFX_MAE_NACTIONS);
1687 EFX_STATIC_ASSERT(EFX_MAE_ACTION_FLAG + 1 == EFX_MAE_ACTION_MARK);
1688 EFX_STATIC_ASSERT(EFX_MAE_ACTION_MARK + 1 == EFX_MAE_ACTION_DELIVER);
1690 if (type >= EFX_ARRAY_SIZE(efx_mae_actions)) {
1695 action_mask = (1U << type);
1697 if ((spec->ema_actions & action_mask) != 0) {
1698 /* The action set already contains this action. */
1699 if ((efx_mae_action_repeat_map & action_mask) == 0) {
1700 /* Cannot add another non-repeatable action. */
1706 if ((efx_mae_action_ordered_map & action_mask) != 0) {
1707 uint32_t strict_ordered_map =
1708 efx_mae_action_ordered_map & ~efx_mae_action_nonstrict_map;
1709 uint32_t later_actions_mask =
1710 strict_ordered_map & ~(action_mask | (action_mask - 1));
1712 if ((spec->ema_actions & later_actions_mask) != 0) {
1713 /* Cannot add an action after later ordered actions. */
1719 if (efx_mae_actions[type].emad_add != NULL) {
1720 rc = efx_mae_actions[type].emad_add(spec, arg_size, arg);
1725 spec->ema_actions |= action_mask;
1736 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1740 __checkReturn efx_rc_t
1741 efx_mae_action_set_populate_decap(
1742 __in efx_mae_actions_t *spec)
1744 return (efx_mae_action_set_spec_populate(spec,
1745 EFX_MAE_ACTION_DECAP, 0, NULL));
1748 __checkReturn efx_rc_t
1749 efx_mae_action_set_populate_vlan_pop(
1750 __in efx_mae_actions_t *spec)
1752 return (efx_mae_action_set_spec_populate(spec,
1753 EFX_MAE_ACTION_VLAN_POP, 0, NULL));
1756 __checkReturn efx_rc_t
1757 efx_mae_action_set_populate_vlan_push(
1758 __in efx_mae_actions_t *spec,
1759 __in uint16_t tpid_be,
1760 __in uint16_t tci_be)
1762 efx_mae_action_vlan_push_t action;
1763 const uint8_t *arg = (const uint8_t *)&action;
1765 action.emavp_tpid_be = tpid_be;
1766 action.emavp_tci_be = tci_be;
1768 return (efx_mae_action_set_spec_populate(spec,
1769 EFX_MAE_ACTION_VLAN_PUSH, sizeof (action), arg));
1772 __checkReturn efx_rc_t
1773 efx_mae_action_set_populate_encap(
1774 __in efx_mae_actions_t *spec)
1777 * There is no argument to pass encap. header ID, thus, one does not
1778 * need to allocate an encap. header while parsing application input.
1779 * This is useful since building an action set may be done simply to
1780 * validate a rule, whilst resource allocation usually consumes time.
1782 return (efx_mae_action_set_spec_populate(spec,
1783 EFX_MAE_ACTION_ENCAP, 0, NULL));
1786 __checkReturn efx_rc_t
1787 efx_mae_action_set_populate_count(
1788 __in efx_mae_actions_t *spec)
1791 * There is no argument to pass counter ID, thus, one does not
1792 * need to allocate a counter while parsing application input.
1793 * This is useful since building an action set may be done simply to
1794 * validate a rule, whilst resource allocation usually consumes time.
1796 return (efx_mae_action_set_spec_populate(spec,
1797 EFX_MAE_ACTION_COUNT, 0, NULL));
1800 __checkReturn efx_rc_t
1801 efx_mae_action_set_populate_flag(
1802 __in efx_mae_actions_t *spec)
1804 return (efx_mae_action_set_spec_populate(spec,
1805 EFX_MAE_ACTION_FLAG, 0, NULL));
1808 __checkReturn efx_rc_t
1809 efx_mae_action_set_populate_mark(
1810 __in efx_mae_actions_t *spec,
1811 __in uint32_t mark_value)
1813 const uint8_t *arg = (const uint8_t *)&mark_value;
1815 return (efx_mae_action_set_spec_populate(spec,
1816 EFX_MAE_ACTION_MARK, sizeof (mark_value), arg));
1819 __checkReturn efx_rc_t
1820 efx_mae_action_set_populate_deliver(
1821 __in efx_mae_actions_t *spec,
1822 __in const efx_mport_sel_t *mportp)
1827 if (mportp == NULL) {
1832 arg = (const uint8_t *)&mportp->sel;
1834 return (efx_mae_action_set_spec_populate(spec,
1835 EFX_MAE_ACTION_DELIVER, sizeof (mportp->sel), arg));
1838 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1842 __checkReturn efx_rc_t
1843 efx_mae_action_set_populate_drop(
1844 __in efx_mae_actions_t *spec)
1846 efx_mport_sel_t mport;
1850 EFX_POPULATE_DWORD_1(dword,
1851 MAE_MPORT_SELECTOR_FLAT, MAE_MPORT_SELECTOR_NULL);
1854 * The constructed DWORD is little-endian,
1855 * but the resulting value is meant to be
1856 * passed to MCDIs, where it will undergo
1857 * host-order to little endian conversion.
1859 mport.sel = EFX_DWORD_FIELD(dword, EFX_DWORD_0);
1861 arg = (const uint8_t *)&mport.sel;
1863 return (efx_mae_action_set_spec_populate(spec,
1864 EFX_MAE_ACTION_DELIVER, sizeof (mport.sel), arg));
1867 __checkReturn boolean_t
1868 efx_mae_action_set_specs_equal(
1869 __in const efx_mae_actions_t *left,
1870 __in const efx_mae_actions_t *right)
1872 size_t cmp_size = EFX_FIELD_OFFSET(efx_mae_actions_t, ema_rsrc);
1875 * An action set specification consists of two parts. The first part
1876 * indicates what actions are included in the action set, as well as
1877 * extra quantitative values (in example, the number of VLAN tags to
1878 * push). The second part comprises resource IDs used by the actions.
1880 * A resource, in example, a counter, is allocated from the hardware
1881 * by the client, and it's the client who is responsible for keeping
1882 * track of allocated resources and comparing resource IDs if needed.
1884 * In this API, don't compare resource IDs in the two specifications.
1887 return ((memcmp(left, right, cmp_size) == 0) ? B_TRUE : B_FALSE);
1890 __checkReturn efx_rc_t
1891 efx_mae_match_specs_class_cmp(
1892 __in efx_nic_t *enp,
1893 __in const efx_mae_match_spec_t *left,
1894 __in const efx_mae_match_spec_t *right,
1895 __out boolean_t *have_same_classp)
1897 efx_mae_t *maep = enp->en_maep;
1898 unsigned int field_ncaps = maep->em_max_nfields;
1899 const efx_mae_field_cap_t *field_caps;
1900 const efx_mae_mv_desc_t *desc_setp;
1901 unsigned int desc_set_nentries;
1902 const efx_mae_mv_bit_desc_t *bit_desc_setp;
1903 unsigned int bit_desc_set_nentries;
1904 boolean_t have_same_class = B_TRUE;
1905 efx_mae_field_id_t field_id;
1906 const uint8_t *mvpl;
1907 const uint8_t *mvpr;
1910 switch (left->emms_type) {
1911 case EFX_MAE_RULE_OUTER:
1912 field_caps = maep->em_outer_rule_field_caps;
1913 desc_setp = __efx_mae_outer_rule_mv_desc_set;
1915 EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_desc_set);
1916 bit_desc_setp = __efx_mae_outer_rule_mv_bit_desc_set;
1917 bit_desc_set_nentries =
1918 EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_bit_desc_set);
1919 mvpl = left->emms_mask_value_pairs.outer;
1920 mvpr = right->emms_mask_value_pairs.outer;
1922 case EFX_MAE_RULE_ACTION:
1923 field_caps = maep->em_action_rule_field_caps;
1924 desc_setp = __efx_mae_action_rule_mv_desc_set;
1926 EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_desc_set);
1927 bit_desc_setp = __efx_mae_action_rule_mv_bit_desc_set;
1928 bit_desc_set_nentries =
1929 EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_bit_desc_set);
1930 mvpl = left->emms_mask_value_pairs.action;
1931 mvpr = right->emms_mask_value_pairs.action;
1938 if (field_caps == NULL) {
1943 if (left->emms_type != right->emms_type ||
1944 left->emms_prio != right->emms_prio) {
1946 * Rules of different types can never map to the same class.
1948 * The FW can support some set of match criteria for one
1949 * priority and not support the very same set for
1950 * another priority. Thus, two rules which have
1951 * different priorities can never map to
1954 *have_same_classp = B_FALSE;
1958 for (field_id = 0; (unsigned int)field_id < desc_set_nentries;
1960 const efx_mae_mv_desc_t *descp = &desc_setp[field_id];
1961 efx_mae_field_cap_id_t field_cap_id = descp->emmd_field_cap_id;
1962 const uint8_t *lmaskp = mvpl + descp->emmd_mask_offset;
1963 const uint8_t *rmaskp = mvpr + descp->emmd_mask_offset;
1964 size_t mask_size = descp->emmd_mask_size;
1965 const uint8_t *lvalp = mvpl + descp->emmd_value_offset;
1966 const uint8_t *rvalp = mvpr + descp->emmd_value_offset;
1967 size_t value_size = descp->emmd_value_size;
1970 continue; /* Skip array gap */
1972 if ((unsigned int)field_cap_id >= field_ncaps) {
1974 * The FW has not reported capability status for this
1975 * field. It's unknown whether any difference between
1976 * the two masks / values affects the class. The only
1977 * case when the class must be the same is when these
1978 * mask-value pairs match. Otherwise, report mismatch.
1980 if ((memcmp(lmaskp, rmaskp, mask_size) == 0) &&
1981 (memcmp(lvalp, rvalp, value_size) == 0))
1987 if (field_caps[field_cap_id].emfc_mask_affects_class) {
1988 if (memcmp(lmaskp, rmaskp, mask_size) != 0) {
1989 have_same_class = B_FALSE;
1994 if (field_caps[field_cap_id].emfc_match_affects_class) {
1995 if (memcmp(lvalp, rvalp, value_size) != 0) {
1996 have_same_class = B_FALSE;
2002 if (have_same_class == B_FALSE)
2005 for (field_id = 0; (unsigned int)field_id < bit_desc_set_nentries;
2007 const efx_mae_mv_bit_desc_t *bit_descp =
2008 &bit_desc_setp[field_id];
2009 efx_mae_field_cap_id_t bit_cap_id =
2010 bit_descp->emmbd_bit_cap_id;
2011 unsigned int byte_idx;
2012 unsigned int bit_idx;
2014 if (bit_descp->emmbd_entry_is_valid == B_FALSE)
2015 continue; /* Skip array gap */
2017 if ((unsigned int)bit_cap_id >= field_ncaps)
2021 bit_descp->emmbd_mask_ofst +
2022 bit_descp->emmbd_mask_lbn / 8;
2024 bit_descp->emmbd_mask_lbn % 8;
2026 if (field_caps[bit_cap_id].emfc_mask_affects_class &&
2027 (mvpl[byte_idx] & (1U << bit_idx)) !=
2028 (mvpr[byte_idx] & (1U << bit_idx))) {
2029 have_same_class = B_FALSE;
2034 bit_descp->emmbd_value_ofst +
2035 bit_descp->emmbd_value_lbn / 8;
2037 bit_descp->emmbd_value_lbn % 8;
2039 if (field_caps[bit_cap_id].emfc_match_affects_class &&
2040 (mvpl[byte_idx] & (1U << bit_idx)) !=
2041 (mvpr[byte_idx] & (1U << bit_idx))) {
2042 have_same_class = B_FALSE;
2048 *have_same_classp = have_same_class;
2055 EFSYS_PROBE1(fail1, efx_rc_t, rc);
2059 __checkReturn efx_rc_t
2060 efx_mae_outer_rule_insert(
2061 __in efx_nic_t *enp,
2062 __in const efx_mae_match_spec_t *spec,
2063 __in efx_tunnel_protocol_t encap_type,
2064 __out efx_mae_rule_id_t *or_idp)
2066 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
2068 EFX_MCDI_DECLARE_BUF(payload,
2069 MC_CMD_MAE_OUTER_RULE_INSERT_IN_LENMAX_MCDI2,
2070 MC_CMD_MAE_OUTER_RULE_INSERT_OUT_LEN);
2071 uint32_t encap_type_mcdi;
2072 efx_mae_rule_id_t or_id;
2076 EFX_STATIC_ASSERT(sizeof (or_idp->id) ==
2077 MC_CMD_MAE_OUTER_RULE_INSERT_OUT_OR_ID_LEN);
2079 EFX_STATIC_ASSERT(EFX_MAE_RSRC_ID_INVALID ==
2080 MC_CMD_MAE_OUTER_RULE_INSERT_OUT_OUTER_RULE_ID_NULL);
2082 if (encp->enc_mae_supported == B_FALSE) {
2087 if (spec->emms_type != EFX_MAE_RULE_OUTER) {
2092 switch (encap_type) {
2093 case EFX_TUNNEL_PROTOCOL_NONE:
2094 encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_NONE;
2096 case EFX_TUNNEL_PROTOCOL_VXLAN:
2097 encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_VXLAN;
2099 case EFX_TUNNEL_PROTOCOL_GENEVE:
2100 encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_GENEVE;
2102 case EFX_TUNNEL_PROTOCOL_NVGRE:
2103 encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_NVGRE;
2110 req.emr_cmd = MC_CMD_MAE_OUTER_RULE_INSERT;
2111 req.emr_in_buf = payload;
2112 req.emr_in_length = MC_CMD_MAE_OUTER_RULE_INSERT_IN_LENMAX_MCDI2;
2113 req.emr_out_buf = payload;
2114 req.emr_out_length = MC_CMD_MAE_OUTER_RULE_INSERT_OUT_LEN;
2116 MCDI_IN_SET_DWORD(req,
2117 MAE_OUTER_RULE_INSERT_IN_ENCAP_TYPE, encap_type_mcdi);
2119 MCDI_IN_SET_DWORD(req, MAE_OUTER_RULE_INSERT_IN_PRIO, spec->emms_prio);
2122 * Mask-value pairs have been stored in the byte order needed for the
2123 * MCDI request and are thus safe to be copied directly to the buffer.
2124 * The library cares about byte order in efx_mae_match_spec_field_set().
2126 EFX_STATIC_ASSERT(sizeof (spec->emms_mask_value_pairs.outer) >=
2127 MAE_ENC_FIELD_PAIRS_LEN);
2128 offset = MC_CMD_MAE_OUTER_RULE_INSERT_IN_FIELD_MATCH_CRITERIA_OFST;
2129 memcpy(payload + offset, spec->emms_mask_value_pairs.outer,
2130 MAE_ENC_FIELD_PAIRS_LEN);
2132 efx_mcdi_execute(enp, &req);
2134 if (req.emr_rc != 0) {
2139 if (req.emr_out_length_used < MC_CMD_MAE_OUTER_RULE_INSERT_OUT_LEN) {
2144 or_id.id = MCDI_OUT_DWORD(req, MAE_OUTER_RULE_INSERT_OUT_OR_ID);
2145 if (or_id.id == EFX_MAE_RSRC_ID_INVALID) {
2150 or_idp->id = or_id.id;
2165 EFSYS_PROBE1(fail1, efx_rc_t, rc);
2169 __checkReturn efx_rc_t
2170 efx_mae_outer_rule_remove(
2171 __in efx_nic_t *enp,
2172 __in const efx_mae_rule_id_t *or_idp)
2174 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
2176 EFX_MCDI_DECLARE_BUF(payload,
2177 MC_CMD_MAE_OUTER_RULE_REMOVE_IN_LEN(1),
2178 MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_LEN(1));
2181 if (encp->enc_mae_supported == B_FALSE) {
2186 req.emr_cmd = MC_CMD_MAE_OUTER_RULE_REMOVE;
2187 req.emr_in_buf = payload;
2188 req.emr_in_length = MC_CMD_MAE_OUTER_RULE_REMOVE_IN_LEN(1);
2189 req.emr_out_buf = payload;
2190 req.emr_out_length = MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_LEN(1);
2192 MCDI_IN_SET_DWORD(req, MAE_OUTER_RULE_REMOVE_IN_OR_ID, or_idp->id);
2194 efx_mcdi_execute(enp, &req);
2196 if (req.emr_rc != 0) {
2201 if (req.emr_out_length_used < MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_LENMIN) {
2206 if (MCDI_OUT_DWORD(req, MAE_OUTER_RULE_REMOVE_OUT_REMOVED_OR_ID) !=
2208 /* Firmware failed to remove the outer rule. */
2222 EFSYS_PROBE1(fail1, efx_rc_t, rc);
2226 __checkReturn efx_rc_t
2227 efx_mae_match_spec_outer_rule_id_set(
2228 __in efx_mae_match_spec_t *spec,
2229 __in const efx_mae_rule_id_t *or_idp)
2231 uint32_t full_mask = UINT32_MAX;
2234 if (spec->emms_type != EFX_MAE_RULE_ACTION) {
2239 if (or_idp == NULL) {
2244 rc = efx_mae_match_spec_field_set(spec, EFX_MAE_FIELD_OUTER_RULE_ID,
2245 sizeof (or_idp->id), (const uint8_t *)&or_idp->id,
2246 sizeof (full_mask), (const uint8_t *)&full_mask);
2257 EFSYS_PROBE1(fail1, efx_rc_t, rc);
2261 __checkReturn efx_rc_t
2262 efx_mae_encap_header_alloc(
2263 __in efx_nic_t *enp,
2264 __in efx_tunnel_protocol_t encap_type,
2265 __in_bcount(header_size) uint8_t *header_data,
2266 __in size_t header_size,
2267 __out efx_mae_eh_id_t *eh_idp)
2269 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
2271 EFX_MCDI_DECLARE_BUF(payload,
2272 MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_LENMAX_MCDI2,
2273 MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_LEN);
2274 uint32_t encap_type_mcdi;
2275 efx_mae_eh_id_t eh_id;
2278 EFX_STATIC_ASSERT(sizeof (eh_idp->id) ==
2279 MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID_LEN);
2281 EFX_STATIC_ASSERT(EFX_MAE_RSRC_ID_INVALID ==
2282 MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID_NULL);
2284 if (encp->enc_mae_supported == B_FALSE) {
2289 switch (encap_type) {
2290 case EFX_TUNNEL_PROTOCOL_NONE:
2291 encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_NONE;
2293 case EFX_TUNNEL_PROTOCOL_VXLAN:
2294 encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_VXLAN;
2296 case EFX_TUNNEL_PROTOCOL_GENEVE:
2297 encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_GENEVE;
2299 case EFX_TUNNEL_PROTOCOL_NVGRE:
2300 encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_NVGRE;
2308 MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_MAXNUM_MCDI2) {
2313 req.emr_cmd = MC_CMD_MAE_ENCAP_HEADER_ALLOC;
2314 req.emr_in_buf = payload;
2315 req.emr_in_length = MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_LEN(header_size);
2316 req.emr_out_buf = payload;
2317 req.emr_out_length = MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_LEN;
2319 MCDI_IN_SET_DWORD(req,
2320 MAE_ENCAP_HEADER_ALLOC_IN_ENCAP_TYPE, encap_type_mcdi);
2322 memcpy(payload + MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_OFST,
2323 header_data, header_size);
2325 efx_mcdi_execute(enp, &req);
2327 if (req.emr_rc != 0) {
2332 if (req.emr_out_length_used < MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_LEN) {
2337 eh_id.id = MCDI_OUT_DWORD(req,
2338 MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID);
2340 if (eh_id.id == EFX_MAE_RSRC_ID_INVALID) {
2345 eh_idp->id = eh_id.id;
2360 EFSYS_PROBE1(fail1, efx_rc_t, rc);
2364 __checkReturn efx_rc_t
2365 efx_mae_encap_header_free(
2366 __in efx_nic_t *enp,
2367 __in const efx_mae_eh_id_t *eh_idp)
2369 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
2371 EFX_MCDI_DECLARE_BUF(payload,
2372 MC_CMD_MAE_ENCAP_HEADER_FREE_IN_LEN(1),
2373 MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_LEN(1));
2376 if (encp->enc_mae_supported == B_FALSE) {
2381 req.emr_cmd = MC_CMD_MAE_ENCAP_HEADER_FREE;
2382 req.emr_in_buf = payload;
2383 req.emr_in_length = MC_CMD_MAE_ENCAP_HEADER_FREE_IN_LEN(1);
2384 req.emr_out_buf = payload;
2385 req.emr_out_length = MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_LEN(1);
2387 MCDI_IN_SET_DWORD(req, MAE_ENCAP_HEADER_FREE_IN_EH_ID, eh_idp->id);
2389 efx_mcdi_execute(enp, &req);
2391 if (req.emr_rc != 0) {
2396 if (MCDI_OUT_DWORD(req, MAE_ENCAP_HEADER_FREE_OUT_FREED_EH_ID) !=
2398 /* Firmware failed to remove the encap. header. */
2410 EFSYS_PROBE1(fail1, efx_rc_t, rc);
2414 __checkReturn efx_rc_t
2415 efx_mae_action_set_fill_in_eh_id(
2416 __in efx_mae_actions_t *spec,
2417 __in const efx_mae_eh_id_t *eh_idp)
2421 if ((spec->ema_actions & (1U << EFX_MAE_ACTION_ENCAP)) == 0) {
2423 * The caller has not intended to have action ENCAP originally,
2424 * hence, this attempt to indicate encap. header ID is invalid.
2430 if (spec->ema_rsrc.emar_eh_id.id != EFX_MAE_RSRC_ID_INVALID) {
2431 /* The caller attempts to indicate encap. header ID twice. */
2436 if (eh_idp->id == EFX_MAE_RSRC_ID_INVALID) {
2441 spec->ema_rsrc.emar_eh_id.id = eh_idp->id;
2450 EFSYS_PROBE1(fail1, efx_rc_t, rc);
2454 __checkReturn efx_rc_t
2455 efx_mae_action_set_alloc(
2456 __in efx_nic_t *enp,
2457 __in const efx_mae_actions_t *spec,
2458 __out efx_mae_aset_id_t *aset_idp)
2460 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
2462 EFX_MCDI_DECLARE_BUF(payload,
2463 MC_CMD_MAE_ACTION_SET_ALLOC_IN_LEN,
2464 MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN);
2465 efx_mae_aset_id_t aset_id;
2468 if (encp->enc_mae_supported == B_FALSE) {
2473 req.emr_cmd = MC_CMD_MAE_ACTION_SET_ALLOC;
2474 req.emr_in_buf = payload;
2475 req.emr_in_length = MC_CMD_MAE_ACTION_SET_ALLOC_IN_LEN;
2476 req.emr_out_buf = payload;
2477 req.emr_out_length = MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN;
2480 * TODO: Remove these EFX_MAE_RSRC_ID_INVALID assignments once the
2481 * corresponding resource types are supported by the implementation.
2482 * Use proper resource ID assignments instead.
2484 MCDI_IN_SET_DWORD(req,
2485 MAE_ACTION_SET_ALLOC_IN_COUNTER_LIST_ID, EFX_MAE_RSRC_ID_INVALID);
2487 if ((spec->ema_actions & (1U << EFX_MAE_ACTION_DECAP)) != 0) {
2488 MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
2489 MAE_ACTION_SET_ALLOC_IN_DECAP, 1);
2492 MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
2493 MAE_ACTION_SET_ALLOC_IN_VLAN_POP, spec->ema_n_vlan_tags_to_pop);
2495 if (spec->ema_n_vlan_tags_to_push > 0) {
2496 unsigned int outer_tag_idx;
2498 MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
2499 MAE_ACTION_SET_ALLOC_IN_VLAN_PUSH,
2500 spec->ema_n_vlan_tags_to_push);
2502 if (spec->ema_n_vlan_tags_to_push ==
2503 EFX_MAE_VLAN_PUSH_MAX_NTAGS) {
2504 MCDI_IN_SET_WORD(req,
2505 MAE_ACTION_SET_ALLOC_IN_VLAN1_PROTO_BE,
2506 spec->ema_vlan_push_descs[0].emavp_tpid_be);
2507 MCDI_IN_SET_WORD(req,
2508 MAE_ACTION_SET_ALLOC_IN_VLAN1_TCI_BE,
2509 spec->ema_vlan_push_descs[0].emavp_tci_be);
2512 outer_tag_idx = spec->ema_n_vlan_tags_to_push - 1;
2514 MCDI_IN_SET_WORD(req, MAE_ACTION_SET_ALLOC_IN_VLAN0_PROTO_BE,
2515 spec->ema_vlan_push_descs[outer_tag_idx].emavp_tpid_be);
2516 MCDI_IN_SET_WORD(req, MAE_ACTION_SET_ALLOC_IN_VLAN0_TCI_BE,
2517 spec->ema_vlan_push_descs[outer_tag_idx].emavp_tci_be);
2520 MCDI_IN_SET_DWORD(req, MAE_ACTION_SET_ALLOC_IN_ENCAP_HEADER_ID,
2521 spec->ema_rsrc.emar_eh_id.id);
2522 MCDI_IN_SET_DWORD(req, MAE_ACTION_SET_ALLOC_IN_COUNTER_ID,
2523 spec->ema_rsrc.emar_counter_id.id);
2525 if ((spec->ema_actions & (1U << EFX_MAE_ACTION_FLAG)) != 0) {
2526 MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
2527 MAE_ACTION_SET_ALLOC_IN_FLAG, 1);
2530 if ((spec->ema_actions & (1U << EFX_MAE_ACTION_MARK)) != 0) {
2531 MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
2532 MAE_ACTION_SET_ALLOC_IN_MARK, 1);
2534 MCDI_IN_SET_DWORD(req,
2535 MAE_ACTION_SET_ALLOC_IN_MARK_VALUE, spec->ema_mark_value);
2538 MCDI_IN_SET_DWORD(req,
2539 MAE_ACTION_SET_ALLOC_IN_DELIVER, spec->ema_deliver_mport.sel);
2541 MCDI_IN_SET_DWORD(req, MAE_ACTION_SET_ALLOC_IN_SRC_MAC_ID,
2542 MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL);
2543 MCDI_IN_SET_DWORD(req, MAE_ACTION_SET_ALLOC_IN_DST_MAC_ID,
2544 MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL);
2546 efx_mcdi_execute(enp, &req);
2548 if (req.emr_rc != 0) {
2553 if (req.emr_out_length_used < MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN) {
2558 aset_id.id = MCDI_OUT_DWORD(req, MAE_ACTION_SET_ALLOC_OUT_AS_ID);
2559 if (aset_id.id == EFX_MAE_RSRC_ID_INVALID) {
2564 aset_idp->id = aset_id.id;
2575 EFSYS_PROBE1(fail1, efx_rc_t, rc);
2579 __checkReturn unsigned int
2580 efx_mae_action_set_get_nb_count(
2581 __in const efx_mae_actions_t *spec)
2583 return (spec->ema_n_count_actions);
2586 __checkReturn efx_rc_t
2587 efx_mae_action_set_fill_in_counter_id(
2588 __in efx_mae_actions_t *spec,
2589 __in const efx_counter_t *counter_idp)
2593 if ((spec->ema_actions & (1U << EFX_MAE_ACTION_COUNT)) == 0) {
2595 * Invalid to add counter ID if spec does not have COUNT action.
2601 if (spec->ema_n_count_actions != 1) {
2603 * Having multiple COUNT actions in the spec requires a counter
2604 * list to be used. This API must only be used for a single
2605 * counter per spec. Turn down the request as inappropriate.
2611 if (spec->ema_rsrc.emar_counter_id.id != EFX_MAE_RSRC_ID_INVALID) {
2612 /* The caller attempts to indicate counter ID twice. */
2617 if (counter_idp->id == EFX_MAE_RSRC_ID_INVALID) {
2622 spec->ema_rsrc.emar_counter_id.id = counter_idp->id;
2633 EFSYS_PROBE1(fail1, efx_rc_t, rc);
2637 __checkReturn efx_rc_t
2638 efx_mae_counters_alloc(
2639 __in efx_nic_t *enp,
2640 __in uint32_t n_counters,
2641 __out uint32_t *n_allocatedp,
2642 __out_ecount(n_counters) efx_counter_t *countersp,
2643 __out_opt uint32_t *gen_countp)
2645 EFX_MCDI_DECLARE_BUF(payload,
2646 MC_CMD_MAE_COUNTER_ALLOC_IN_LEN,
2647 MC_CMD_MAE_COUNTER_ALLOC_OUT_LENMAX_MCDI2);
2648 efx_mae_t *maep = enp->en_maep;
2649 uint32_t n_allocated;
2654 if (n_counters > maep->em_max_ncounters ||
2655 n_counters < MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MINNUM ||
2656 n_counters > MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MAXNUM_MCDI2) {
2661 req.emr_cmd = MC_CMD_MAE_COUNTER_ALLOC;
2662 req.emr_in_buf = payload;
2663 req.emr_in_length = MC_CMD_MAE_COUNTER_ALLOC_IN_LEN;
2664 req.emr_out_buf = payload;
2665 req.emr_out_length = MC_CMD_MAE_COUNTER_ALLOC_OUT_LEN(n_counters);
2667 MCDI_IN_SET_DWORD(req, MAE_COUNTER_ALLOC_IN_REQUESTED_COUNT,
2670 efx_mcdi_execute(enp, &req);
2672 if (req.emr_rc != 0) {
2677 if (req.emr_out_length_used < MC_CMD_MAE_COUNTER_ALLOC_OUT_LENMIN) {
2682 n_allocated = MCDI_OUT_DWORD(req,
2683 MAE_COUNTER_ALLOC_OUT_COUNTER_ID_COUNT);
2684 if (n_allocated < MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MINNUM) {
2689 for (i = 0; i < n_allocated; i++) {
2690 countersp[i].id = MCDI_OUT_INDEXED_DWORD(req,
2691 MAE_COUNTER_ALLOC_OUT_COUNTER_ID, i);
2694 if (gen_countp != NULL) {
2695 *gen_countp = MCDI_OUT_DWORD(req,
2696 MAE_COUNTER_ALLOC_OUT_GENERATION_COUNT);
2699 *n_allocatedp = n_allocated;
2710 EFSYS_PROBE1(fail1, efx_rc_t, rc);
2715 __checkReturn efx_rc_t
2716 efx_mae_counters_free(
2717 __in efx_nic_t *enp,
2718 __in uint32_t n_counters,
2719 __out uint32_t *n_freedp,
2720 __in_ecount(n_counters) const efx_counter_t *countersp,
2721 __out_opt uint32_t *gen_countp)
2723 EFX_MCDI_DECLARE_BUF(payload,
2724 MC_CMD_MAE_COUNTER_FREE_IN_LENMAX_MCDI2,
2725 MC_CMD_MAE_COUNTER_FREE_OUT_LENMAX_MCDI2);
2726 efx_mae_t *maep = enp->en_maep;
2732 if (n_counters > maep->em_max_ncounters ||
2733 n_counters < MC_CMD_MAE_COUNTER_FREE_IN_FREE_COUNTER_ID_MINNUM ||
2735 MC_CMD_MAE_COUNTER_FREE_IN_FREE_COUNTER_ID_MAXNUM_MCDI2) {
2740 req.emr_cmd = MC_CMD_MAE_COUNTER_FREE;
2741 req.emr_in_buf = payload;
2742 req.emr_in_length = MC_CMD_MAE_COUNTER_FREE_IN_LEN(n_counters);
2743 req.emr_out_buf = payload;
2744 req.emr_out_length = MC_CMD_MAE_COUNTER_FREE_OUT_LEN(n_counters);
2746 for (i = 0; i < n_counters; i++) {
2747 MCDI_IN_SET_INDEXED_DWORD(req,
2748 MAE_COUNTER_FREE_IN_FREE_COUNTER_ID, i, countersp[i].id);
2750 MCDI_IN_SET_DWORD(req, MAE_COUNTER_FREE_IN_COUNTER_ID_COUNT,
2753 efx_mcdi_execute(enp, &req);
2755 if (req.emr_rc != 0) {
2760 if (req.emr_out_length_used < MC_CMD_MAE_COUNTER_FREE_OUT_LENMIN) {
2765 n_freed = MCDI_OUT_DWORD(req, MAE_COUNTER_FREE_OUT_COUNTER_ID_COUNT);
2767 if (n_freed < MC_CMD_MAE_COUNTER_FREE_OUT_FREED_COUNTER_ID_MINNUM) {
2772 if (gen_countp != NULL) {
2773 *gen_countp = MCDI_OUT_DWORD(req,
2774 MAE_COUNTER_FREE_OUT_GENERATION_COUNT);
2777 *n_freedp = n_freed;
2788 EFSYS_PROBE1(fail1, efx_rc_t, rc);
2793 __checkReturn efx_rc_t
2794 efx_mae_counters_stream_start(
2795 __in efx_nic_t *enp,
2796 __in uint16_t rxq_id,
2797 __in uint16_t packet_size,
2798 __in uint32_t flags_in,
2799 __out uint32_t *flags_out)
2802 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_MAE_COUNTERS_STREAM_START_IN_LEN,
2803 MC_CMD_MAE_COUNTERS_STREAM_START_OUT_LEN);
2806 EFX_STATIC_ASSERT(EFX_MAE_COUNTERS_STREAM_IN_ZERO_SQUASH_DISABLE ==
2807 1U << MC_CMD_MAE_COUNTERS_STREAM_START_IN_ZERO_SQUASH_DISABLE_LBN);
2809 EFX_STATIC_ASSERT(EFX_MAE_COUNTERS_STREAM_OUT_USES_CREDITS ==
2810 1U << MC_CMD_MAE_COUNTERS_STREAM_START_OUT_USES_CREDITS_LBN);
2812 req.emr_cmd = MC_CMD_MAE_COUNTERS_STREAM_START;
2813 req.emr_in_buf = payload;
2814 req.emr_in_length = MC_CMD_MAE_COUNTERS_STREAM_START_IN_LEN;
2815 req.emr_out_buf = payload;
2816 req.emr_out_length = MC_CMD_MAE_COUNTERS_STREAM_START_OUT_LEN;
2818 MCDI_IN_SET_WORD(req, MAE_COUNTERS_STREAM_START_IN_QID, rxq_id);
2819 MCDI_IN_SET_WORD(req, MAE_COUNTERS_STREAM_START_IN_PACKET_SIZE,
2821 MCDI_IN_SET_DWORD(req, MAE_COUNTERS_STREAM_START_IN_FLAGS, flags_in);
2823 efx_mcdi_execute(enp, &req);
2825 if (req.emr_rc != 0) {
2830 if (req.emr_out_length_used <
2831 MC_CMD_MAE_COUNTERS_STREAM_START_OUT_LEN) {
2836 *flags_out = MCDI_OUT_DWORD(req, MAE_COUNTERS_STREAM_START_OUT_FLAGS);
2843 EFSYS_PROBE1(fail1, efx_rc_t, rc);
2848 __checkReturn efx_rc_t
2849 efx_mae_counters_stream_stop(
2850 __in efx_nic_t *enp,
2851 __in uint16_t rxq_id,
2852 __out_opt uint32_t *gen_countp)
2855 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_MAE_COUNTERS_STREAM_STOP_IN_LEN,
2856 MC_CMD_MAE_COUNTERS_STREAM_STOP_OUT_LEN);
2859 req.emr_cmd = MC_CMD_MAE_COUNTERS_STREAM_STOP;
2860 req.emr_in_buf = payload;
2861 req.emr_in_length = MC_CMD_MAE_COUNTERS_STREAM_STOP_IN_LEN;
2862 req.emr_out_buf = payload;
2863 req.emr_out_length = MC_CMD_MAE_COUNTERS_STREAM_STOP_OUT_LEN;
2865 MCDI_IN_SET_WORD(req, MAE_COUNTERS_STREAM_STOP_IN_QID, rxq_id);
2867 efx_mcdi_execute(enp, &req);
2869 if (req.emr_rc != 0) {
2874 if (req.emr_out_length_used <
2875 MC_CMD_MAE_COUNTERS_STREAM_STOP_OUT_LEN) {
2880 if (gen_countp != NULL) {
2881 *gen_countp = MCDI_OUT_DWORD(req,
2882 MAE_COUNTERS_STREAM_STOP_OUT_GENERATION_COUNT);
2890 EFSYS_PROBE1(fail1, efx_rc_t, rc);
2895 __checkReturn efx_rc_t
2896 efx_mae_counters_stream_give_credits(
2897 __in efx_nic_t *enp,
2898 __in uint32_t n_credits)
2901 EFX_MCDI_DECLARE_BUF(payload,
2902 MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS_IN_LEN,
2903 MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS_OUT_LEN);
2906 req.emr_cmd = MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS;
2907 req.emr_in_buf = payload;
2908 req.emr_in_length = MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS_IN_LEN;
2909 req.emr_out_buf = payload;
2910 req.emr_out_length = MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS_OUT_LEN;
2912 MCDI_IN_SET_DWORD(req, MAE_COUNTERS_STREAM_GIVE_CREDITS_IN_NUM_CREDITS,
2915 efx_mcdi_execute(enp, &req);
2917 if (req.emr_rc != 0) {
2925 EFSYS_PROBE1(fail1, efx_rc_t, rc);
2930 __checkReturn efx_rc_t
2931 efx_mae_action_set_free(
2932 __in efx_nic_t *enp,
2933 __in const efx_mae_aset_id_t *aset_idp)
2935 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
2937 EFX_MCDI_DECLARE_BUF(payload,
2938 MC_CMD_MAE_ACTION_SET_FREE_IN_LEN(1),
2939 MC_CMD_MAE_ACTION_SET_FREE_OUT_LEN(1));
2942 if (encp->enc_mae_supported == B_FALSE) {
2947 req.emr_cmd = MC_CMD_MAE_ACTION_SET_FREE;
2948 req.emr_in_buf = payload;
2949 req.emr_in_length = MC_CMD_MAE_ACTION_SET_FREE_IN_LEN(1);
2950 req.emr_out_buf = payload;
2951 req.emr_out_length = MC_CMD_MAE_ACTION_SET_FREE_OUT_LEN(1);
2953 MCDI_IN_SET_DWORD(req, MAE_ACTION_SET_FREE_IN_AS_ID, aset_idp->id);
2955 efx_mcdi_execute(enp, &req);
2957 if (req.emr_rc != 0) {
2962 if (req.emr_out_length_used < MC_CMD_MAE_ACTION_SET_FREE_OUT_LENMIN) {
2967 if (MCDI_OUT_DWORD(req, MAE_ACTION_SET_FREE_OUT_FREED_AS_ID) !=
2969 /* Firmware failed to free the action set. */
2983 EFSYS_PROBE1(fail1, efx_rc_t, rc);
2987 __checkReturn efx_rc_t
2988 efx_mae_action_rule_insert(
2989 __in efx_nic_t *enp,
2990 __in const efx_mae_match_spec_t *spec,
2991 __in const efx_mae_aset_list_id_t *asl_idp,
2992 __in const efx_mae_aset_id_t *as_idp,
2993 __out efx_mae_rule_id_t *ar_idp)
2995 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
2997 EFX_MCDI_DECLARE_BUF(payload,
2998 MC_CMD_MAE_ACTION_RULE_INSERT_IN_LENMAX_MCDI2,
2999 MC_CMD_MAE_ACTION_RULE_INSERT_OUT_LEN);
3000 efx_oword_t *rule_response;
3001 efx_mae_rule_id_t ar_id;
3005 EFX_STATIC_ASSERT(sizeof (ar_idp->id) ==
3006 MC_CMD_MAE_ACTION_RULE_INSERT_OUT_AR_ID_LEN);
3008 EFX_STATIC_ASSERT(EFX_MAE_RSRC_ID_INVALID ==
3009 MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL);
3011 if (encp->enc_mae_supported == B_FALSE) {
3016 if (spec->emms_type != EFX_MAE_RULE_ACTION ||
3017 (asl_idp != NULL && as_idp != NULL) ||
3018 (asl_idp == NULL && as_idp == NULL)) {
3023 req.emr_cmd = MC_CMD_MAE_ACTION_RULE_INSERT;
3024 req.emr_in_buf = payload;
3025 req.emr_in_length = MC_CMD_MAE_ACTION_RULE_INSERT_IN_LENMAX_MCDI2;
3026 req.emr_out_buf = payload;
3027 req.emr_out_length = MC_CMD_MAE_ACTION_RULE_INSERT_OUT_LEN;
3029 EFX_STATIC_ASSERT(sizeof (*rule_response) <=
3030 MC_CMD_MAE_ACTION_RULE_INSERT_IN_RESPONSE_LEN);
3031 offset = MC_CMD_MAE_ACTION_RULE_INSERT_IN_RESPONSE_OFST;
3032 rule_response = (efx_oword_t *)(payload + offset);
3033 EFX_POPULATE_OWORD_3(*rule_response,
3034 MAE_ACTION_RULE_RESPONSE_ASL_ID,
3035 (asl_idp != NULL) ? asl_idp->id : EFX_MAE_RSRC_ID_INVALID,
3036 MAE_ACTION_RULE_RESPONSE_AS_ID,
3037 (as_idp != NULL) ? as_idp->id : EFX_MAE_RSRC_ID_INVALID,
3038 MAE_ACTION_RULE_RESPONSE_COUNTER_ID, EFX_MAE_RSRC_ID_INVALID);
3040 MCDI_IN_SET_DWORD(req, MAE_ACTION_RULE_INSERT_IN_PRIO, spec->emms_prio);
3043 * Mask-value pairs have been stored in the byte order needed for the
3044 * MCDI request and are thus safe to be copied directly to the buffer.
3046 EFX_STATIC_ASSERT(sizeof (spec->emms_mask_value_pairs.action) >=
3047 MAE_FIELD_MASK_VALUE_PAIRS_V2_LEN);
3048 offset = MC_CMD_MAE_ACTION_RULE_INSERT_IN_MATCH_CRITERIA_OFST;
3049 memcpy(payload + offset, spec->emms_mask_value_pairs.action,
3050 MAE_FIELD_MASK_VALUE_PAIRS_V2_LEN);
3052 efx_mcdi_execute(enp, &req);
3054 if (req.emr_rc != 0) {
3059 if (req.emr_out_length_used < MC_CMD_MAE_ACTION_RULE_INSERT_OUT_LEN) {
3064 ar_id.id = MCDI_OUT_DWORD(req, MAE_ACTION_RULE_INSERT_OUT_AR_ID);
3065 if (ar_id.id == EFX_MAE_RSRC_ID_INVALID) {
3070 ar_idp->id = ar_id.id;
3083 EFSYS_PROBE1(fail1, efx_rc_t, rc);
3087 __checkReturn efx_rc_t
3088 efx_mae_action_rule_remove(
3089 __in efx_nic_t *enp,
3090 __in const efx_mae_rule_id_t *ar_idp)
3092 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
3094 EFX_MCDI_DECLARE_BUF(payload,
3095 MC_CMD_MAE_ACTION_RULE_DELETE_IN_LEN(1),
3096 MC_CMD_MAE_ACTION_RULE_DELETE_OUT_LEN(1));
3099 if (encp->enc_mae_supported == B_FALSE) {
3104 req.emr_cmd = MC_CMD_MAE_ACTION_RULE_DELETE;
3105 req.emr_in_buf = payload;
3106 req.emr_in_length = MC_CMD_MAE_ACTION_RULE_DELETE_IN_LEN(1);
3107 req.emr_out_buf = payload;
3108 req.emr_out_length = MC_CMD_MAE_ACTION_RULE_DELETE_OUT_LEN(1);
3110 MCDI_IN_SET_DWORD(req, MAE_ACTION_RULE_DELETE_IN_AR_ID, ar_idp->id);
3112 efx_mcdi_execute(enp, &req);
3114 if (req.emr_rc != 0) {
3119 if (req.emr_out_length_used <
3120 MC_CMD_MAE_ACTION_RULE_DELETE_OUT_LENMIN) {
3125 if (MCDI_OUT_DWORD(req, MAE_ACTION_RULE_DELETE_OUT_DELETED_AR_ID) !=
3127 /* Firmware failed to delete the action rule. */
3141 EFSYS_PROBE1(fail1, efx_rc_t, rc);
3145 __checkReturn efx_rc_t
3146 efx_mcdi_mport_alloc_alias(
3147 __in efx_nic_t *enp,
3148 __out efx_mport_id_t *mportp,
3149 __out_opt uint32_t *labelp)
3151 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
3153 EFX_MCDI_DECLARE_BUF(payload,
3154 MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN_LEN,
3155 MC_CMD_MAE_MPORT_ALLOC_ALIAS_OUT_LEN);
3158 if (encp->enc_mae_supported == B_FALSE) {
3163 req.emr_cmd = MC_CMD_MAE_MPORT_ALLOC;
3164 req.emr_in_buf = payload;
3165 req.emr_in_length = MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN_LEN;
3166 req.emr_out_buf = payload;
3167 req.emr_out_length = MC_CMD_MAE_MPORT_ALLOC_ALIAS_OUT_LEN;
3169 MCDI_IN_SET_DWORD(req, MAE_MPORT_ALLOC_IN_TYPE,
3170 MC_CMD_MAE_MPORT_ALLOC_IN_MPORT_TYPE_ALIAS);
3171 MCDI_IN_SET_DWORD(req, MAE_MPORT_ALLOC_ALIAS_IN_DELIVER_MPORT,
3172 MAE_MPORT_SELECTOR_ASSIGNED);
3174 efx_mcdi_execute(enp, &req);
3176 if (req.emr_rc != 0) {
3181 mportp->id = MCDI_OUT_DWORD(req, MAE_MPORT_ALLOC_OUT_MPORT_ID);
3183 *labelp = MCDI_OUT_DWORD(req, MAE_MPORT_ALLOC_ALIAS_OUT_LABEL);
3190 EFSYS_PROBE1(fail1, efx_rc_t, rc);
3194 __checkReturn efx_rc_t
3196 __in efx_nic_t *enp,
3197 __in const efx_mport_id_t *mportp)
3199 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
3201 EFX_MCDI_DECLARE_BUF(payload,
3202 MC_CMD_MAE_MPORT_FREE_IN_LEN,
3203 MC_CMD_MAE_MPORT_FREE_OUT_LEN);
3206 if (encp->enc_mae_supported == B_FALSE) {
3211 req.emr_cmd = MC_CMD_MAE_MPORT_FREE;
3212 req.emr_in_buf = payload;
3213 req.emr_in_length = MC_CMD_MAE_MPORT_FREE_IN_LEN;
3214 req.emr_out_buf = payload;
3215 req.emr_out_length = MC_CMD_MAE_MPORT_FREE_OUT_LEN;
3217 MCDI_IN_SET_DWORD(req, MAE_MPORT_FREE_IN_MPORT_ID, mportp->id);
3219 efx_mcdi_execute(enp, &req);
3221 if (req.emr_rc != 0) {
3231 EFSYS_PROBE1(fail1, efx_rc_t, rc);
3235 #endif /* EFSYS_OPT_MAE */