16f956d5cSIvan Malov /* SPDX-License-Identifier: BSD-3-Clause
26f956d5cSIvan Malov *
3672386c1SAndrew Rybchenko * Copyright(c) 2019-2021 Xilinx, Inc.
46f956d5cSIvan Malov */
56f956d5cSIvan Malov
66f956d5cSIvan Malov #include "efx.h"
76f956d5cSIvan Malov #include "efx_impl.h"
86f956d5cSIvan Malov
96f956d5cSIvan Malov
106f956d5cSIvan Malov #if EFSYS_OPT_MAE
116f956d5cSIvan Malov
12d761ec9fSIvan Malov static __checkReturn efx_rc_t
efx_mae_get_capabilities(__in efx_nic_t * enp)13d761ec9fSIvan Malov efx_mae_get_capabilities(
14d761ec9fSIvan Malov __in efx_nic_t *enp)
15d761ec9fSIvan Malov {
16d761ec9fSIvan Malov efx_mcdi_req_t req;
17d761ec9fSIvan Malov EFX_MCDI_DECLARE_BUF(payload,
18d761ec9fSIvan Malov MC_CMD_MAE_GET_CAPS_IN_LEN,
19f4a6d074SIvan Malov MC_CMD_MAE_GET_CAPS_V2_OUT_LEN);
20d761ec9fSIvan Malov struct efx_mae_s *maep = enp->en_maep;
21d761ec9fSIvan Malov efx_rc_t rc;
22d761ec9fSIvan Malov
23d761ec9fSIvan Malov req.emr_cmd = MC_CMD_MAE_GET_CAPS;
24d761ec9fSIvan Malov req.emr_in_buf = payload;
25d761ec9fSIvan Malov req.emr_in_length = MC_CMD_MAE_GET_CAPS_IN_LEN;
26d761ec9fSIvan Malov req.emr_out_buf = payload;
27f4a6d074SIvan Malov req.emr_out_length = MC_CMD_MAE_GET_CAPS_V2_OUT_LEN;
28d761ec9fSIvan Malov
29d761ec9fSIvan Malov efx_mcdi_execute(enp, &req);
30d761ec9fSIvan Malov
31d761ec9fSIvan Malov if (req.emr_rc != 0) {
32d761ec9fSIvan Malov rc = req.emr_rc;
33d761ec9fSIvan Malov goto fail1;
34d761ec9fSIvan Malov }
35d761ec9fSIvan Malov
36d761ec9fSIvan Malov if (req.emr_out_length_used < MC_CMD_MAE_GET_CAPS_OUT_LEN) {
37d761ec9fSIvan Malov rc = EMSGSIZE;
38d761ec9fSIvan Malov goto fail2;
39d761ec9fSIvan Malov }
40d761ec9fSIvan Malov
41891408c4SIvan Malov maep->em_max_n_outer_prios =
42891408c4SIvan Malov MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_OUTER_PRIOS);
43891408c4SIvan Malov
44d761ec9fSIvan Malov maep->em_max_n_action_prios =
45d761ec9fSIvan Malov MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_ACTION_PRIOS);
46d761ec9fSIvan Malov
47891408c4SIvan Malov maep->em_encap_types_supported = 0;
48891408c4SIvan Malov
498076e40cSIvan Malov if (MCDI_OUT_DWORD_FIELD(req, MAE_GET_CAPS_OUT_ENCAP_TYPES_SUPPORTED,
508076e40cSIvan Malov MAE_GET_CAPS_OUT_ENCAP_TYPE_VXLAN) != 0) {
51891408c4SIvan Malov maep->em_encap_types_supported |=
52891408c4SIvan Malov (1U << EFX_TUNNEL_PROTOCOL_VXLAN);
53891408c4SIvan Malov }
54891408c4SIvan Malov
558076e40cSIvan Malov if (MCDI_OUT_DWORD_FIELD(req, MAE_GET_CAPS_OUT_ENCAP_TYPES_SUPPORTED,
568076e40cSIvan Malov MAE_GET_CAPS_OUT_ENCAP_TYPE_GENEVE) != 0) {
57891408c4SIvan Malov maep->em_encap_types_supported |=
58891408c4SIvan Malov (1U << EFX_TUNNEL_PROTOCOL_GENEVE);
59891408c4SIvan Malov }
60891408c4SIvan Malov
618076e40cSIvan Malov if (MCDI_OUT_DWORD_FIELD(req, MAE_GET_CAPS_OUT_ENCAP_TYPES_SUPPORTED,
628076e40cSIvan Malov MAE_GET_CAPS_OUT_ENCAP_TYPE_NVGRE) != 0) {
63891408c4SIvan Malov maep->em_encap_types_supported |=
64891408c4SIvan Malov (1U << EFX_TUNNEL_PROTOCOL_NVGRE);
65891408c4SIvan Malov }
66891408c4SIvan Malov
6734285fd0SIvan Malov maep->em_max_nfields =
6834285fd0SIvan Malov MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_MATCH_FIELD_COUNT);
6934285fd0SIvan Malov
70d19e7dd9SIvan Malov maep->em_max_n_action_counters =
71d19e7dd9SIvan Malov MCDI_OUT_DWORD(req, MAE_GET_CAPS_OUT_AR_COUNTERS);
72bbc42f34SIgor Romanov
73f4a6d074SIvan Malov if (req.emr_out_length_used >= MC_CMD_MAE_GET_CAPS_V2_OUT_LEN) {
74f4a6d074SIvan Malov maep->em_max_n_conntrack_counters =
75f4a6d074SIvan Malov MCDI_OUT_DWORD(req, MAE_GET_CAPS_V2_OUT_CT_COUNTERS);
76f4a6d074SIvan Malov } else {
77f4a6d074SIvan Malov maep->em_max_n_conntrack_counters = 0;
78f4a6d074SIvan Malov }
79f4a6d074SIvan Malov
80d761ec9fSIvan Malov return (0);
81d761ec9fSIvan Malov
82d761ec9fSIvan Malov fail2:
83d761ec9fSIvan Malov EFSYS_PROBE(fail2);
84d761ec9fSIvan Malov fail1:
85d761ec9fSIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
86d761ec9fSIvan Malov return (rc);
87d761ec9fSIvan Malov }
88d761ec9fSIvan Malov
8934285fd0SIvan Malov static __checkReturn efx_rc_t
efx_mae_get_outer_rule_caps(__in efx_nic_t * enp,__in unsigned int field_ncaps,__out_ecount (field_ncaps)efx_mae_field_cap_t * field_caps)90ed15d7f8SIvan Malov efx_mae_get_outer_rule_caps(
91ed15d7f8SIvan Malov __in efx_nic_t *enp,
92ed15d7f8SIvan Malov __in unsigned int field_ncaps,
93ed15d7f8SIvan Malov __out_ecount(field_ncaps) efx_mae_field_cap_t *field_caps)
94ed15d7f8SIvan Malov {
95ed15d7f8SIvan Malov efx_mcdi_req_t req;
96ed15d7f8SIvan Malov EFX_MCDI_DECLARE_BUF(payload,
97ed15d7f8SIvan Malov MC_CMD_MAE_GET_OR_CAPS_IN_LEN,
98ed15d7f8SIvan Malov MC_CMD_MAE_GET_OR_CAPS_OUT_LENMAX_MCDI2);
99ed15d7f8SIvan Malov unsigned int mcdi_field_ncaps;
100ed15d7f8SIvan Malov unsigned int i;
101ed15d7f8SIvan Malov efx_rc_t rc;
102ed15d7f8SIvan Malov
103ed15d7f8SIvan Malov if (MC_CMD_MAE_GET_OR_CAPS_OUT_LEN(field_ncaps) >
104ed15d7f8SIvan Malov MC_CMD_MAE_GET_OR_CAPS_OUT_LENMAX_MCDI2) {
105ed15d7f8SIvan Malov rc = EINVAL;
106ed15d7f8SIvan Malov goto fail1;
107ed15d7f8SIvan Malov }
108ed15d7f8SIvan Malov
109ed15d7f8SIvan Malov req.emr_cmd = MC_CMD_MAE_GET_OR_CAPS;
110ed15d7f8SIvan Malov req.emr_in_buf = payload;
111ed15d7f8SIvan Malov req.emr_in_length = MC_CMD_MAE_GET_OR_CAPS_IN_LEN;
112ed15d7f8SIvan Malov req.emr_out_buf = payload;
113ed15d7f8SIvan Malov req.emr_out_length = MC_CMD_MAE_GET_OR_CAPS_OUT_LEN(field_ncaps);
114ed15d7f8SIvan Malov
115ed15d7f8SIvan Malov efx_mcdi_execute(enp, &req);
116ed15d7f8SIvan Malov
117ed15d7f8SIvan Malov if (req.emr_rc != 0) {
118ed15d7f8SIvan Malov rc = req.emr_rc;
119ed15d7f8SIvan Malov goto fail2;
120ed15d7f8SIvan Malov }
121ed15d7f8SIvan Malov
122e27950a0SAndy Moreton if (req.emr_out_length_used < MC_CMD_MAE_GET_OR_CAPS_OUT_LENMIN) {
123e27950a0SAndy Moreton rc = EMSGSIZE;
124e27950a0SAndy Moreton goto fail3;
125e27950a0SAndy Moreton }
126e27950a0SAndy Moreton
127ed15d7f8SIvan Malov mcdi_field_ncaps = MCDI_OUT_DWORD(req, MAE_GET_OR_CAPS_OUT_COUNT);
128ed15d7f8SIvan Malov
129ed15d7f8SIvan Malov if (req.emr_out_length_used <
130ed15d7f8SIvan Malov MC_CMD_MAE_GET_OR_CAPS_OUT_LEN(mcdi_field_ncaps)) {
131ed15d7f8SIvan Malov rc = EMSGSIZE;
132e27950a0SAndy Moreton goto fail4;
133ed15d7f8SIvan Malov }
134ed15d7f8SIvan Malov
135ed15d7f8SIvan Malov if (mcdi_field_ncaps > field_ncaps) {
136ed15d7f8SIvan Malov rc = EMSGSIZE;
137e27950a0SAndy Moreton goto fail5;
138ed15d7f8SIvan Malov }
139ed15d7f8SIvan Malov
140ed15d7f8SIvan Malov for (i = 0; i < mcdi_field_ncaps; ++i) {
141ed15d7f8SIvan Malov uint32_t match_flag;
142ed15d7f8SIvan Malov uint32_t mask_flag;
143ed15d7f8SIvan Malov
144ed15d7f8SIvan Malov field_caps[i].emfc_support = MCDI_OUT_INDEXED_DWORD_FIELD(req,
145ed15d7f8SIvan Malov MAE_GET_OR_CAPS_OUT_FIELD_FLAGS, i,
146ed15d7f8SIvan Malov MAE_FIELD_FLAGS_SUPPORT_STATUS);
147ed15d7f8SIvan Malov
148ed15d7f8SIvan Malov match_flag = MCDI_OUT_INDEXED_DWORD_FIELD(req,
149ed15d7f8SIvan Malov MAE_GET_OR_CAPS_OUT_FIELD_FLAGS, i,
150ed15d7f8SIvan Malov MAE_FIELD_FLAGS_MATCH_AFFECTS_CLASS);
151ed15d7f8SIvan Malov
152ed15d7f8SIvan Malov field_caps[i].emfc_match_affects_class =
153ed15d7f8SIvan Malov (match_flag != 0) ? B_TRUE : B_FALSE;
154ed15d7f8SIvan Malov
155ed15d7f8SIvan Malov mask_flag = MCDI_OUT_INDEXED_DWORD_FIELD(req,
156ed15d7f8SIvan Malov MAE_GET_OR_CAPS_OUT_FIELD_FLAGS, i,
157ed15d7f8SIvan Malov MAE_FIELD_FLAGS_MASK_AFFECTS_CLASS);
158ed15d7f8SIvan Malov
159ed15d7f8SIvan Malov field_caps[i].emfc_mask_affects_class =
160ed15d7f8SIvan Malov (mask_flag != 0) ? B_TRUE : B_FALSE;
161ed15d7f8SIvan Malov }
162ed15d7f8SIvan Malov
163ed15d7f8SIvan Malov return (0);
164ed15d7f8SIvan Malov
165e27950a0SAndy Moreton fail5:
166e27950a0SAndy Moreton EFSYS_PROBE(fail5);
167ed15d7f8SIvan Malov fail4:
168ed15d7f8SIvan Malov EFSYS_PROBE(fail4);
169ed15d7f8SIvan Malov fail3:
170ed15d7f8SIvan Malov EFSYS_PROBE(fail3);
171ed15d7f8SIvan Malov fail2:
172ed15d7f8SIvan Malov EFSYS_PROBE(fail2);
173ed15d7f8SIvan Malov fail1:
174ed15d7f8SIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
175ed15d7f8SIvan Malov return (rc);
176ed15d7f8SIvan Malov }
177ed15d7f8SIvan Malov
178ed15d7f8SIvan Malov static __checkReturn efx_rc_t
efx_mae_get_action_rule_caps(__in efx_nic_t * enp,__in unsigned int field_ncaps,__out_ecount (field_ncaps)efx_mae_field_cap_t * field_caps)17934285fd0SIvan Malov efx_mae_get_action_rule_caps(
18034285fd0SIvan Malov __in efx_nic_t *enp,
18134285fd0SIvan Malov __in unsigned int field_ncaps,
18234285fd0SIvan Malov __out_ecount(field_ncaps) efx_mae_field_cap_t *field_caps)
18334285fd0SIvan Malov {
18434285fd0SIvan Malov efx_mcdi_req_t req;
18534285fd0SIvan Malov EFX_MCDI_DECLARE_BUF(payload,
18634285fd0SIvan Malov MC_CMD_MAE_GET_AR_CAPS_IN_LEN,
18734285fd0SIvan Malov MC_CMD_MAE_GET_AR_CAPS_OUT_LENMAX_MCDI2);
18834285fd0SIvan Malov unsigned int mcdi_field_ncaps;
18934285fd0SIvan Malov unsigned int i;
19034285fd0SIvan Malov efx_rc_t rc;
19134285fd0SIvan Malov
19234285fd0SIvan Malov if (MC_CMD_MAE_GET_AR_CAPS_OUT_LEN(field_ncaps) >
19334285fd0SIvan Malov MC_CMD_MAE_GET_AR_CAPS_OUT_LENMAX_MCDI2) {
19434285fd0SIvan Malov rc = EINVAL;
19534285fd0SIvan Malov goto fail1;
19634285fd0SIvan Malov }
19734285fd0SIvan Malov
19834285fd0SIvan Malov req.emr_cmd = MC_CMD_MAE_GET_AR_CAPS;
19934285fd0SIvan Malov req.emr_in_buf = payload;
20034285fd0SIvan Malov req.emr_in_length = MC_CMD_MAE_GET_AR_CAPS_IN_LEN;
20134285fd0SIvan Malov req.emr_out_buf = payload;
20234285fd0SIvan Malov req.emr_out_length = MC_CMD_MAE_GET_AR_CAPS_OUT_LEN(field_ncaps);
20334285fd0SIvan Malov
20434285fd0SIvan Malov efx_mcdi_execute(enp, &req);
20534285fd0SIvan Malov
20634285fd0SIvan Malov if (req.emr_rc != 0) {
20734285fd0SIvan Malov rc = req.emr_rc;
20834285fd0SIvan Malov goto fail2;
20934285fd0SIvan Malov }
21034285fd0SIvan Malov
211e27950a0SAndy Moreton if (req.emr_out_length_used < MC_CMD_MAE_GET_AR_CAPS_OUT_LENMIN) {
21234285fd0SIvan Malov rc = EMSGSIZE;
21334285fd0SIvan Malov goto fail3;
21434285fd0SIvan Malov }
21534285fd0SIvan Malov
216e27950a0SAndy Moreton mcdi_field_ncaps = MCDI_OUT_DWORD(req, MAE_GET_AR_CAPS_OUT_COUNT);
217e27950a0SAndy Moreton
218e27950a0SAndy Moreton if (req.emr_out_length_used <
219e27950a0SAndy Moreton MC_CMD_MAE_GET_AR_CAPS_OUT_LEN(mcdi_field_ncaps)) {
22034285fd0SIvan Malov rc = EMSGSIZE;
22134285fd0SIvan Malov goto fail4;
22234285fd0SIvan Malov }
22334285fd0SIvan Malov
224e27950a0SAndy Moreton if (mcdi_field_ncaps > field_ncaps) {
225e27950a0SAndy Moreton rc = EMSGSIZE;
226e27950a0SAndy Moreton goto fail5;
227e27950a0SAndy Moreton }
228e27950a0SAndy Moreton
22934285fd0SIvan Malov for (i = 0; i < mcdi_field_ncaps; ++i) {
23034285fd0SIvan Malov uint32_t match_flag;
23134285fd0SIvan Malov uint32_t mask_flag;
23234285fd0SIvan Malov
23334285fd0SIvan Malov field_caps[i].emfc_support = MCDI_OUT_INDEXED_DWORD_FIELD(req,
23434285fd0SIvan Malov MAE_GET_AR_CAPS_OUT_FIELD_FLAGS, i,
23534285fd0SIvan Malov MAE_FIELD_FLAGS_SUPPORT_STATUS);
23634285fd0SIvan Malov
23734285fd0SIvan Malov match_flag = MCDI_OUT_INDEXED_DWORD_FIELD(req,
23834285fd0SIvan Malov MAE_GET_AR_CAPS_OUT_FIELD_FLAGS, i,
23934285fd0SIvan Malov MAE_FIELD_FLAGS_MATCH_AFFECTS_CLASS);
24034285fd0SIvan Malov
24134285fd0SIvan Malov field_caps[i].emfc_match_affects_class =
24234285fd0SIvan Malov (match_flag != 0) ? B_TRUE : B_FALSE;
24334285fd0SIvan Malov
24434285fd0SIvan Malov mask_flag = MCDI_OUT_INDEXED_DWORD_FIELD(req,
24534285fd0SIvan Malov MAE_GET_AR_CAPS_OUT_FIELD_FLAGS, i,
24634285fd0SIvan Malov MAE_FIELD_FLAGS_MASK_AFFECTS_CLASS);
24734285fd0SIvan Malov
24834285fd0SIvan Malov field_caps[i].emfc_mask_affects_class =
24934285fd0SIvan Malov (mask_flag != 0) ? B_TRUE : B_FALSE;
25034285fd0SIvan Malov }
25134285fd0SIvan Malov
25234285fd0SIvan Malov return (0);
25334285fd0SIvan Malov
254e27950a0SAndy Moreton fail5:
255e27950a0SAndy Moreton EFSYS_PROBE(fail5);
25634285fd0SIvan Malov fail4:
25734285fd0SIvan Malov EFSYS_PROBE(fail4);
25834285fd0SIvan Malov fail3:
25934285fd0SIvan Malov EFSYS_PROBE(fail3);
26034285fd0SIvan Malov fail2:
26134285fd0SIvan Malov EFSYS_PROBE(fail2);
26234285fd0SIvan Malov fail1:
26334285fd0SIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
26434285fd0SIvan Malov return (rc);
26534285fd0SIvan Malov }
26634285fd0SIvan Malov
2676f956d5cSIvan Malov __checkReturn efx_rc_t
efx_mae_init(__in efx_nic_t * enp)2686f956d5cSIvan Malov efx_mae_init(
2696f956d5cSIvan Malov __in efx_nic_t *enp)
2706f956d5cSIvan Malov {
2716f956d5cSIvan Malov const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
272ed15d7f8SIvan Malov efx_mae_field_cap_t *or_fcaps;
273ed15d7f8SIvan Malov size_t or_fcaps_size;
27434285fd0SIvan Malov efx_mae_field_cap_t *ar_fcaps;
27534285fd0SIvan Malov size_t ar_fcaps_size;
2766f956d5cSIvan Malov efx_mae_t *maep;
2776f956d5cSIvan Malov efx_rc_t rc;
2786f956d5cSIvan Malov
2796f956d5cSIvan Malov if (encp->enc_mae_supported == B_FALSE) {
2806f956d5cSIvan Malov rc = ENOTSUP;
2816f956d5cSIvan Malov goto fail1;
2826f956d5cSIvan Malov }
2836f956d5cSIvan Malov
2846f956d5cSIvan Malov EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (*maep), maep);
2856f956d5cSIvan Malov if (maep == NULL) {
2866f956d5cSIvan Malov rc = ENOMEM;
2876f956d5cSIvan Malov goto fail2;
2886f956d5cSIvan Malov }
2896f956d5cSIvan Malov
2906f956d5cSIvan Malov enp->en_maep = maep;
2916f956d5cSIvan Malov
292d761ec9fSIvan Malov rc = efx_mae_get_capabilities(enp);
293d761ec9fSIvan Malov if (rc != 0)
294d761ec9fSIvan Malov goto fail3;
295d761ec9fSIvan Malov
296ed15d7f8SIvan Malov or_fcaps_size = maep->em_max_nfields * sizeof (*or_fcaps);
297ed15d7f8SIvan Malov EFSYS_KMEM_ALLOC(enp->en_esip, or_fcaps_size, or_fcaps);
298ed15d7f8SIvan Malov if (or_fcaps == NULL) {
299ed15d7f8SIvan Malov rc = ENOMEM;
300ed15d7f8SIvan Malov goto fail4;
301ed15d7f8SIvan Malov }
302ed15d7f8SIvan Malov
303ed15d7f8SIvan Malov maep->em_outer_rule_field_caps_size = or_fcaps_size;
304ed15d7f8SIvan Malov maep->em_outer_rule_field_caps = or_fcaps;
305ed15d7f8SIvan Malov
306ed15d7f8SIvan Malov rc = efx_mae_get_outer_rule_caps(enp, maep->em_max_nfields, or_fcaps);
307ed15d7f8SIvan Malov if (rc != 0)
308ed15d7f8SIvan Malov goto fail5;
309ed15d7f8SIvan Malov
31034285fd0SIvan Malov ar_fcaps_size = maep->em_max_nfields * sizeof (*ar_fcaps);
31134285fd0SIvan Malov EFSYS_KMEM_ALLOC(enp->en_esip, ar_fcaps_size, ar_fcaps);
31234285fd0SIvan Malov if (ar_fcaps == NULL) {
31334285fd0SIvan Malov rc = ENOMEM;
314ed15d7f8SIvan Malov goto fail6;
31534285fd0SIvan Malov }
31634285fd0SIvan Malov
31734285fd0SIvan Malov maep->em_action_rule_field_caps_size = ar_fcaps_size;
31834285fd0SIvan Malov maep->em_action_rule_field_caps = ar_fcaps;
31934285fd0SIvan Malov
32034285fd0SIvan Malov rc = efx_mae_get_action_rule_caps(enp, maep->em_max_nfields, ar_fcaps);
32134285fd0SIvan Malov if (rc != 0)
322ed15d7f8SIvan Malov goto fail7;
32334285fd0SIvan Malov
3246f956d5cSIvan Malov return (0);
3256f956d5cSIvan Malov
326ed15d7f8SIvan Malov fail7:
32734285fd0SIvan Malov EFSYS_PROBE(fail5);
32834285fd0SIvan Malov EFSYS_KMEM_FREE(enp->en_esip, ar_fcaps_size, ar_fcaps);
329ed15d7f8SIvan Malov fail6:
330ed15d7f8SIvan Malov EFSYS_PROBE(fail4);
331ed15d7f8SIvan Malov fail5:
332ed15d7f8SIvan Malov EFSYS_PROBE(fail5);
333ed15d7f8SIvan Malov EFSYS_KMEM_FREE(enp->en_esip, or_fcaps_size, or_fcaps);
33434285fd0SIvan Malov fail4:
33534285fd0SIvan Malov EFSYS_PROBE(fail4);
336d761ec9fSIvan Malov fail3:
337d761ec9fSIvan Malov EFSYS_PROBE(fail3);
338d761ec9fSIvan Malov EFSYS_KMEM_FREE(enp->en_esip, sizeof (struct efx_mae_s), enp->en_maep);
339d761ec9fSIvan Malov enp->en_maep = NULL;
3406f956d5cSIvan Malov fail2:
3416f956d5cSIvan Malov EFSYS_PROBE(fail2);
3426f956d5cSIvan Malov fail1:
3436f956d5cSIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
3446f956d5cSIvan Malov return (rc);
3456f956d5cSIvan Malov }
3466f956d5cSIvan Malov
3476f956d5cSIvan Malov void
efx_mae_fini(__in efx_nic_t * enp)3486f956d5cSIvan Malov efx_mae_fini(
3496f956d5cSIvan Malov __in efx_nic_t *enp)
3506f956d5cSIvan Malov {
3516f956d5cSIvan Malov const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
3526f956d5cSIvan Malov efx_mae_t *maep = enp->en_maep;
3536f956d5cSIvan Malov
3546f956d5cSIvan Malov if (encp->enc_mae_supported == B_FALSE)
3556f956d5cSIvan Malov return;
3566f956d5cSIvan Malov
35734285fd0SIvan Malov EFSYS_KMEM_FREE(enp->en_esip, maep->em_action_rule_field_caps_size,
35834285fd0SIvan Malov maep->em_action_rule_field_caps);
359ed15d7f8SIvan Malov EFSYS_KMEM_FREE(enp->en_esip, maep->em_outer_rule_field_caps_size,
360ed15d7f8SIvan Malov maep->em_outer_rule_field_caps);
3616f956d5cSIvan Malov EFSYS_KMEM_FREE(enp->en_esip, sizeof (*maep), maep);
3626f956d5cSIvan Malov enp->en_maep = NULL;
3636f956d5cSIvan Malov }
3646f956d5cSIvan Malov
365d761ec9fSIvan Malov __checkReturn efx_rc_t
efx_mae_get_limits(__in efx_nic_t * enp,__out efx_mae_limits_t * emlp)366d761ec9fSIvan Malov efx_mae_get_limits(
367d761ec9fSIvan Malov __in efx_nic_t *enp,
368d761ec9fSIvan Malov __out efx_mae_limits_t *emlp)
369d761ec9fSIvan Malov {
370d761ec9fSIvan Malov const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
371d761ec9fSIvan Malov struct efx_mae_s *maep = enp->en_maep;
372d761ec9fSIvan Malov efx_rc_t rc;
373d761ec9fSIvan Malov
374d761ec9fSIvan Malov if (encp->enc_mae_supported == B_FALSE) {
375d761ec9fSIvan Malov rc = ENOTSUP;
376d761ec9fSIvan Malov goto fail1;
377d761ec9fSIvan Malov }
378d761ec9fSIvan Malov
379891408c4SIvan Malov emlp->eml_max_n_outer_prios = maep->em_max_n_outer_prios;
380d761ec9fSIvan Malov emlp->eml_max_n_action_prios = maep->em_max_n_action_prios;
381891408c4SIvan Malov emlp->eml_encap_types_supported = maep->em_encap_types_supported;
38230833168SIvan Malov emlp->eml_encap_header_size_limit =
38330833168SIvan Malov MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_MAXNUM_MCDI2;
384d19e7dd9SIvan Malov emlp->eml_max_n_action_counters = maep->em_max_n_action_counters;
385f4a6d074SIvan Malov emlp->eml_max_n_conntrack_counters = maep->em_max_n_conntrack_counters;
386d761ec9fSIvan Malov
387d761ec9fSIvan Malov return (0);
388d761ec9fSIvan Malov
389d761ec9fSIvan Malov fail1:
390d761ec9fSIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
391d761ec9fSIvan Malov return (rc);
392d761ec9fSIvan Malov }
393d761ec9fSIvan Malov
394b75eb50dSIvan Malov __checkReturn efx_rc_t
efx_mae_match_spec_init(__in efx_nic_t * enp,__in efx_mae_rule_type_t type,__in uint32_t prio,__out efx_mae_match_spec_t ** specp)395b75eb50dSIvan Malov efx_mae_match_spec_init(
396b75eb50dSIvan Malov __in efx_nic_t *enp,
397b75eb50dSIvan Malov __in efx_mae_rule_type_t type,
398b75eb50dSIvan Malov __in uint32_t prio,
399b75eb50dSIvan Malov __out efx_mae_match_spec_t **specp)
400b75eb50dSIvan Malov {
401b75eb50dSIvan Malov efx_mae_match_spec_t *spec;
402b75eb50dSIvan Malov efx_rc_t rc;
403b75eb50dSIvan Malov
404b75eb50dSIvan Malov switch (type) {
4051efc26e1SIvan Malov case EFX_MAE_RULE_OUTER:
4061efc26e1SIvan Malov break;
407b75eb50dSIvan Malov case EFX_MAE_RULE_ACTION:
408b75eb50dSIvan Malov break;
409b75eb50dSIvan Malov default:
410b75eb50dSIvan Malov rc = ENOTSUP;
411b75eb50dSIvan Malov goto fail1;
412b75eb50dSIvan Malov }
413b75eb50dSIvan Malov
414b75eb50dSIvan Malov EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (*spec), spec);
415b75eb50dSIvan Malov if (spec == NULL) {
416b75eb50dSIvan Malov rc = ENOMEM;
417b75eb50dSIvan Malov goto fail2;
418b75eb50dSIvan Malov }
419b75eb50dSIvan Malov
420b75eb50dSIvan Malov spec->emms_type = type;
421b75eb50dSIvan Malov spec->emms_prio = prio;
422b75eb50dSIvan Malov
423b75eb50dSIvan Malov *specp = spec;
424b75eb50dSIvan Malov
425b75eb50dSIvan Malov return (0);
426b75eb50dSIvan Malov
427b75eb50dSIvan Malov fail2:
428b75eb50dSIvan Malov EFSYS_PROBE(fail2);
429b75eb50dSIvan Malov fail1:
430b75eb50dSIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
431b75eb50dSIvan Malov return (rc);
432b75eb50dSIvan Malov }
433b75eb50dSIvan Malov
434b75eb50dSIvan Malov void
efx_mae_match_spec_fini(__in efx_nic_t * enp,__in efx_mae_match_spec_t * spec)435b75eb50dSIvan Malov efx_mae_match_spec_fini(
436b75eb50dSIvan Malov __in efx_nic_t *enp,
437b75eb50dSIvan Malov __in efx_mae_match_spec_t *spec)
438b75eb50dSIvan Malov {
439b75eb50dSIvan Malov EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec), spec);
440b75eb50dSIvan Malov }
441b75eb50dSIvan Malov
44234285fd0SIvan Malov /* Named identifiers which are valid indices to efx_mae_field_cap_t */
44334285fd0SIvan Malov typedef enum efx_mae_field_cap_id_e {
444370ed675SIvan Malov EFX_MAE_FIELD_ID_INGRESS_MPORT_SELECTOR = MAE_FIELD_INGRESS_PORT,
4457055abadSIvan Malov EFX_MAE_FIELD_ID_ETHER_TYPE_BE = MAE_FIELD_ETHER_TYPE,
4467055abadSIvan Malov EFX_MAE_FIELD_ID_ETH_SADDR_BE = MAE_FIELD_ETH_SADDR,
4477055abadSIvan Malov EFX_MAE_FIELD_ID_ETH_DADDR_BE = MAE_FIELD_ETH_DADDR,
4487a376918SIvan Malov EFX_MAE_FIELD_ID_VLAN0_TCI_BE = MAE_FIELD_VLAN0_TCI,
4497a376918SIvan Malov EFX_MAE_FIELD_ID_VLAN0_PROTO_BE = MAE_FIELD_VLAN0_PROTO,
4507a376918SIvan Malov EFX_MAE_FIELD_ID_VLAN1_TCI_BE = MAE_FIELD_VLAN1_TCI,
4517a376918SIvan Malov EFX_MAE_FIELD_ID_VLAN1_PROTO_BE = MAE_FIELD_VLAN1_PROTO,
452afb41254SIvan Malov EFX_MAE_FIELD_ID_SRC_IP4_BE = MAE_FIELD_SRC_IP4,
453afb41254SIvan Malov EFX_MAE_FIELD_ID_DST_IP4_BE = MAE_FIELD_DST_IP4,
454afb41254SIvan Malov EFX_MAE_FIELD_ID_IP_PROTO = MAE_FIELD_IP_PROTO,
455afb41254SIvan Malov EFX_MAE_FIELD_ID_IP_TOS = MAE_FIELD_IP_TOS,
456afb41254SIvan Malov EFX_MAE_FIELD_ID_IP_TTL = MAE_FIELD_IP_TTL,
457d6192a7cSIvan Malov EFX_MAE_FIELD_ID_SRC_IP6_BE = MAE_FIELD_SRC_IP6,
458d6192a7cSIvan Malov EFX_MAE_FIELD_ID_DST_IP6_BE = MAE_FIELD_DST_IP6,
459080845d3SIvan Malov EFX_MAE_FIELD_ID_L4_SPORT_BE = MAE_FIELD_L4_SPORT,
460080845d3SIvan Malov EFX_MAE_FIELD_ID_L4_DPORT_BE = MAE_FIELD_L4_DPORT,
461080845d3SIvan Malov EFX_MAE_FIELD_ID_TCP_FLAGS_BE = MAE_FIELD_TCP_FLAGS,
4621efc26e1SIvan Malov EFX_MAE_FIELD_ID_ENC_ETHER_TYPE_BE = MAE_FIELD_ENC_ETHER_TYPE,
4631efc26e1SIvan Malov EFX_MAE_FIELD_ID_ENC_ETH_SADDR_BE = MAE_FIELD_ENC_ETH_SADDR,
4641efc26e1SIvan Malov EFX_MAE_FIELD_ID_ENC_ETH_DADDR_BE = MAE_FIELD_ENC_ETH_DADDR,
4651efc26e1SIvan Malov EFX_MAE_FIELD_ID_ENC_VLAN0_TCI_BE = MAE_FIELD_ENC_VLAN0_TCI,
4661efc26e1SIvan Malov EFX_MAE_FIELD_ID_ENC_VLAN0_PROTO_BE = MAE_FIELD_ENC_VLAN0_PROTO,
4671efc26e1SIvan Malov EFX_MAE_FIELD_ID_ENC_VLAN1_TCI_BE = MAE_FIELD_ENC_VLAN1_TCI,
4681efc26e1SIvan Malov EFX_MAE_FIELD_ID_ENC_VLAN1_PROTO_BE = MAE_FIELD_ENC_VLAN1_PROTO,
4691efc26e1SIvan Malov EFX_MAE_FIELD_ID_ENC_SRC_IP4_BE = MAE_FIELD_ENC_SRC_IP4,
4701efc26e1SIvan Malov EFX_MAE_FIELD_ID_ENC_DST_IP4_BE = MAE_FIELD_ENC_DST_IP4,
4711efc26e1SIvan Malov EFX_MAE_FIELD_ID_ENC_IP_PROTO = MAE_FIELD_ENC_IP_PROTO,
4721efc26e1SIvan Malov EFX_MAE_FIELD_ID_ENC_IP_TOS = MAE_FIELD_ENC_IP_TOS,
4731efc26e1SIvan Malov EFX_MAE_FIELD_ID_ENC_IP_TTL = MAE_FIELD_ENC_IP_TTL,
4741efc26e1SIvan Malov EFX_MAE_FIELD_ID_ENC_SRC_IP6_BE = MAE_FIELD_ENC_SRC_IP6,
4751efc26e1SIvan Malov EFX_MAE_FIELD_ID_ENC_DST_IP6_BE = MAE_FIELD_ENC_DST_IP6,
4761efc26e1SIvan Malov EFX_MAE_FIELD_ID_ENC_L4_SPORT_BE = MAE_FIELD_ENC_L4_SPORT,
4771efc26e1SIvan Malov EFX_MAE_FIELD_ID_ENC_L4_DPORT_BE = MAE_FIELD_ENC_L4_DPORT,
4780ec6faf4SIvan Malov EFX_MAE_FIELD_ID_ENC_VNET_ID_BE = MAE_FIELD_ENC_VNET_ID,
4797a673e1aSIvan Malov EFX_MAE_FIELD_ID_OUTER_RULE_ID = MAE_FIELD_OUTER_RULE_ID,
48037907899SIvan Malov EFX_MAE_FIELD_ID_HAS_OVLAN = MAE_FIELD_HAS_OVLAN,
48137907899SIvan Malov EFX_MAE_FIELD_ID_HAS_IVLAN = MAE_FIELD_HAS_IVLAN,
48237907899SIvan Malov EFX_MAE_FIELD_ID_ENC_HAS_OVLAN = MAE_FIELD_ENC_HAS_OVLAN,
48337907899SIvan Malov EFX_MAE_FIELD_ID_ENC_HAS_IVLAN = MAE_FIELD_ENC_HAS_IVLAN,
4843a73dcfdSIvan Malov EFX_MAE_FIELD_ID_RECIRC_ID = MAE_FIELD_RECIRC_ID,
48593c5d2c6SIvan Malov EFX_MAE_FIELD_ID_CT_MARK = MAE_FIELD_CT_MARK,
486f79ce621SArtemii Morozov EFX_MAE_FIELD_ID_IS_IP_FRAG = MAE_FIELD_IS_IP_FRAG,
487f79ce621SArtemii Morozov EFX_MAE_FIELD_ID_IP_FIRST_FRAG = MAE_FIELD_IP_FIRST_FRAG,
488370ed675SIvan Malov
48934285fd0SIvan Malov EFX_MAE_FIELD_CAP_NIDS
49034285fd0SIvan Malov } efx_mae_field_cap_id_t;
49134285fd0SIvan Malov
49234285fd0SIvan Malov typedef enum efx_mae_field_endianness_e {
49334285fd0SIvan Malov EFX_MAE_FIELD_LE = 0,
49434285fd0SIvan Malov EFX_MAE_FIELD_BE,
49534285fd0SIvan Malov
49634285fd0SIvan Malov EFX_MAE_FIELD_ENDIANNESS_NTYPES
49734285fd0SIvan Malov } efx_mae_field_endianness_t;
49834285fd0SIvan Malov
49934285fd0SIvan Malov /*
50034285fd0SIvan Malov * The following structure is a means to describe an MAE field.
50134285fd0SIvan Malov * The information in it is meant to be used internally by
50234285fd0SIvan Malov * APIs for addressing a given field in a mask-value pairs
50334285fd0SIvan Malov * structure and for validation purposes.
504429ed2f9SIvan Malov *
505429ed2f9SIvan Malov * A field may have an alternative one. This structure
506429ed2f9SIvan Malov * has additional members to reference the alternative
507429ed2f9SIvan Malov * field's mask. See efx_mae_match_spec_is_valid().
50834285fd0SIvan Malov */
50934285fd0SIvan Malov typedef struct efx_mae_mv_desc_s {
51034285fd0SIvan Malov efx_mae_field_cap_id_t emmd_field_cap_id;
51134285fd0SIvan Malov
51234285fd0SIvan Malov size_t emmd_value_size;
51334285fd0SIvan Malov size_t emmd_value_offset;
51434285fd0SIvan Malov size_t emmd_mask_size;
51534285fd0SIvan Malov size_t emmd_mask_offset;
51634285fd0SIvan Malov
517429ed2f9SIvan Malov /*
518429ed2f9SIvan Malov * Having the alternative field's mask size set to 0
519429ed2f9SIvan Malov * means that there's no alternative field specified.
520429ed2f9SIvan Malov */
521429ed2f9SIvan Malov size_t emmd_alt_mask_size;
522429ed2f9SIvan Malov size_t emmd_alt_mask_offset;
523429ed2f9SIvan Malov
524429ed2f9SIvan Malov /* Primary field and the alternative one are of the same endianness. */
52534285fd0SIvan Malov efx_mae_field_endianness_t emmd_endianness;
52634285fd0SIvan Malov } efx_mae_mv_desc_t;
52734285fd0SIvan Malov
52834285fd0SIvan Malov /* Indices to this array are provided by efx_mae_field_id_t */
52934285fd0SIvan Malov static const efx_mae_mv_desc_t __efx_mae_action_rule_mv_desc_set[] = {
530370ed675SIvan Malov #define EFX_MAE_MV_DESC(_name, _endianness) \
531370ed675SIvan Malov [EFX_MAE_FIELD_##_name] = \
532370ed675SIvan Malov { \
533370ed675SIvan Malov EFX_MAE_FIELD_ID_##_name, \
5343a73dcfdSIvan Malov MAE_FIELD_MASK_VALUE_PAIRS_V2_##_name##_LEN, \
5353a73dcfdSIvan Malov MAE_FIELD_MASK_VALUE_PAIRS_V2_##_name##_OFST, \
5363a73dcfdSIvan Malov MAE_FIELD_MASK_VALUE_PAIRS_V2_##_name##_MASK_LEN, \
5373a73dcfdSIvan Malov MAE_FIELD_MASK_VALUE_PAIRS_V2_##_name##_MASK_OFST, \
538429ed2f9SIvan Malov 0, 0 /* no alternative field */, \
539370ed675SIvan Malov _endianness \
540370ed675SIvan Malov }
541370ed675SIvan Malov
542370ed675SIvan Malov EFX_MAE_MV_DESC(INGRESS_MPORT_SELECTOR, EFX_MAE_FIELD_LE),
5437055abadSIvan Malov EFX_MAE_MV_DESC(ETHER_TYPE_BE, EFX_MAE_FIELD_BE),
5447055abadSIvan Malov EFX_MAE_MV_DESC(ETH_SADDR_BE, EFX_MAE_FIELD_BE),
5457055abadSIvan Malov EFX_MAE_MV_DESC(ETH_DADDR_BE, EFX_MAE_FIELD_BE),
5467a376918SIvan Malov EFX_MAE_MV_DESC(VLAN0_TCI_BE, EFX_MAE_FIELD_BE),
5477a376918SIvan Malov EFX_MAE_MV_DESC(VLAN0_PROTO_BE, EFX_MAE_FIELD_BE),
5487a376918SIvan Malov EFX_MAE_MV_DESC(VLAN1_TCI_BE, EFX_MAE_FIELD_BE),
5497a376918SIvan Malov EFX_MAE_MV_DESC(VLAN1_PROTO_BE, EFX_MAE_FIELD_BE),
550afb41254SIvan Malov EFX_MAE_MV_DESC(SRC_IP4_BE, EFX_MAE_FIELD_BE),
551afb41254SIvan Malov EFX_MAE_MV_DESC(DST_IP4_BE, EFX_MAE_FIELD_BE),
552afb41254SIvan Malov EFX_MAE_MV_DESC(IP_PROTO, EFX_MAE_FIELD_BE),
553afb41254SIvan Malov EFX_MAE_MV_DESC(IP_TOS, EFX_MAE_FIELD_BE),
554afb41254SIvan Malov EFX_MAE_MV_DESC(IP_TTL, EFX_MAE_FIELD_BE),
555d6192a7cSIvan Malov EFX_MAE_MV_DESC(SRC_IP6_BE, EFX_MAE_FIELD_BE),
556d6192a7cSIvan Malov EFX_MAE_MV_DESC(DST_IP6_BE, EFX_MAE_FIELD_BE),
557080845d3SIvan Malov EFX_MAE_MV_DESC(L4_SPORT_BE, EFX_MAE_FIELD_BE),
558080845d3SIvan Malov EFX_MAE_MV_DESC(L4_DPORT_BE, EFX_MAE_FIELD_BE),
559080845d3SIvan Malov EFX_MAE_MV_DESC(TCP_FLAGS_BE, EFX_MAE_FIELD_BE),
5600ec6faf4SIvan Malov EFX_MAE_MV_DESC(ENC_VNET_ID_BE, EFX_MAE_FIELD_BE),
5617a673e1aSIvan Malov EFX_MAE_MV_DESC(OUTER_RULE_ID, EFX_MAE_FIELD_LE),
5623a73dcfdSIvan Malov EFX_MAE_MV_DESC(RECIRC_ID, EFX_MAE_FIELD_LE),
56393c5d2c6SIvan Malov EFX_MAE_MV_DESC(CT_MARK, EFX_MAE_FIELD_LE),
564370ed675SIvan Malov
565370ed675SIvan Malov #undef EFX_MAE_MV_DESC
56634285fd0SIvan Malov };
56734285fd0SIvan Malov
5681efc26e1SIvan Malov /* Indices to this array are provided by efx_mae_field_id_t */
5691efc26e1SIvan Malov static const efx_mae_mv_desc_t __efx_mae_outer_rule_mv_desc_set[] = {
5701efc26e1SIvan Malov #define EFX_MAE_MV_DESC(_name, _endianness) \
5711efc26e1SIvan Malov [EFX_MAE_FIELD_##_name] = \
5721efc26e1SIvan Malov { \
5731efc26e1SIvan Malov EFX_MAE_FIELD_ID_##_name, \
5741efc26e1SIvan Malov MAE_ENC_FIELD_PAIRS_##_name##_LEN, \
5751efc26e1SIvan Malov MAE_ENC_FIELD_PAIRS_##_name##_OFST, \
5761efc26e1SIvan Malov MAE_ENC_FIELD_PAIRS_##_name##_MASK_LEN, \
5771efc26e1SIvan Malov MAE_ENC_FIELD_PAIRS_##_name##_MASK_OFST, \
578429ed2f9SIvan Malov 0, 0 /* no alternative field */, \
579429ed2f9SIvan Malov _endianness \
580429ed2f9SIvan Malov }
581429ed2f9SIvan Malov
582429ed2f9SIvan Malov /* Same as EFX_MAE_MV_DESC(), but also indicates an alternative field. */
583429ed2f9SIvan Malov #define EFX_MAE_MV_DESC_ALT(_name, _alt_name, _endianness) \
584429ed2f9SIvan Malov [EFX_MAE_FIELD_##_name] = \
585429ed2f9SIvan Malov { \
586429ed2f9SIvan Malov EFX_MAE_FIELD_ID_##_name, \
587429ed2f9SIvan Malov MAE_ENC_FIELD_PAIRS_##_name##_LEN, \
588429ed2f9SIvan Malov MAE_ENC_FIELD_PAIRS_##_name##_OFST, \
589429ed2f9SIvan Malov MAE_ENC_FIELD_PAIRS_##_name##_MASK_LEN, \
590429ed2f9SIvan Malov MAE_ENC_FIELD_PAIRS_##_name##_MASK_OFST, \
591429ed2f9SIvan Malov MAE_ENC_FIELD_PAIRS_##_alt_name##_MASK_LEN, \
592429ed2f9SIvan Malov MAE_ENC_FIELD_PAIRS_##_alt_name##_MASK_OFST, \
5931efc26e1SIvan Malov _endianness \
5941efc26e1SIvan Malov }
5951efc26e1SIvan Malov
5961efc26e1SIvan Malov EFX_MAE_MV_DESC(INGRESS_MPORT_SELECTOR, EFX_MAE_FIELD_LE),
5971efc26e1SIvan Malov EFX_MAE_MV_DESC(ENC_ETHER_TYPE_BE, EFX_MAE_FIELD_BE),
5981efc26e1SIvan Malov EFX_MAE_MV_DESC(ENC_ETH_SADDR_BE, EFX_MAE_FIELD_BE),
5991efc26e1SIvan Malov EFX_MAE_MV_DESC(ENC_ETH_DADDR_BE, EFX_MAE_FIELD_BE),
6001efc26e1SIvan Malov EFX_MAE_MV_DESC(ENC_VLAN0_TCI_BE, EFX_MAE_FIELD_BE),
6011efc26e1SIvan Malov EFX_MAE_MV_DESC(ENC_VLAN0_PROTO_BE, EFX_MAE_FIELD_BE),
6021efc26e1SIvan Malov EFX_MAE_MV_DESC(ENC_VLAN1_TCI_BE, EFX_MAE_FIELD_BE),
6031efc26e1SIvan Malov EFX_MAE_MV_DESC(ENC_VLAN1_PROTO_BE, EFX_MAE_FIELD_BE),
604429ed2f9SIvan Malov EFX_MAE_MV_DESC_ALT(ENC_SRC_IP4_BE, ENC_SRC_IP6_BE, EFX_MAE_FIELD_BE),
605429ed2f9SIvan Malov EFX_MAE_MV_DESC_ALT(ENC_DST_IP4_BE, ENC_DST_IP6_BE, EFX_MAE_FIELD_BE),
6061efc26e1SIvan Malov EFX_MAE_MV_DESC(ENC_IP_PROTO, EFX_MAE_FIELD_BE),
6071efc26e1SIvan Malov EFX_MAE_MV_DESC(ENC_IP_TOS, EFX_MAE_FIELD_BE),
6081efc26e1SIvan Malov EFX_MAE_MV_DESC(ENC_IP_TTL, EFX_MAE_FIELD_BE),
609429ed2f9SIvan Malov EFX_MAE_MV_DESC_ALT(ENC_SRC_IP6_BE, ENC_SRC_IP4_BE, EFX_MAE_FIELD_BE),
610429ed2f9SIvan Malov EFX_MAE_MV_DESC_ALT(ENC_DST_IP6_BE, ENC_DST_IP4_BE, EFX_MAE_FIELD_BE),
6111efc26e1SIvan Malov EFX_MAE_MV_DESC(ENC_L4_SPORT_BE, EFX_MAE_FIELD_BE),
6121efc26e1SIvan Malov EFX_MAE_MV_DESC(ENC_L4_DPORT_BE, EFX_MAE_FIELD_BE),
6131efc26e1SIvan Malov
614429ed2f9SIvan Malov #undef EFX_MAE_MV_DESC_ALT
6151efc26e1SIvan Malov #undef EFX_MAE_MV_DESC
6161efc26e1SIvan Malov };
6171efc26e1SIvan Malov
61837907899SIvan Malov /*
61937907899SIvan Malov * The following structure is a means to describe an MAE bit.
62037907899SIvan Malov * The information in it is meant to be used internally by
62137907899SIvan Malov * APIs for addressing a given flag in a mask-value pairs
62237907899SIvan Malov * structure and for validation purposes.
62337907899SIvan Malov */
62437907899SIvan Malov typedef struct efx_mae_mv_bit_desc_s {
62537907899SIvan Malov /*
62637907899SIvan Malov * Arrays using this struct are indexed by field IDs.
62737907899SIvan Malov * Fields which aren't meant to be referenced by these
62837907899SIvan Malov * arrays comprise gaps (invalid entries). Below field
62937907899SIvan Malov * helps to identify such entries.
63037907899SIvan Malov */
63137907899SIvan Malov boolean_t emmbd_entry_is_valid;
63237907899SIvan Malov efx_mae_field_cap_id_t emmbd_bit_cap_id;
63337907899SIvan Malov size_t emmbd_value_ofst;
63437907899SIvan Malov unsigned int emmbd_value_lbn;
63537907899SIvan Malov size_t emmbd_mask_ofst;
63637907899SIvan Malov unsigned int emmbd_mask_lbn;
63737907899SIvan Malov } efx_mae_mv_bit_desc_t;
63837907899SIvan Malov
63937907899SIvan Malov static const efx_mae_mv_bit_desc_t __efx_mae_outer_rule_mv_bit_desc_set[] = {
64037907899SIvan Malov #define EFX_MAE_MV_BIT_DESC(_name) \
64137907899SIvan Malov [EFX_MAE_FIELD_##_name] = \
64237907899SIvan Malov { \
64337907899SIvan Malov B_TRUE, \
64437907899SIvan Malov EFX_MAE_FIELD_ID_##_name, \
64537907899SIvan Malov MAE_ENC_FIELD_PAIRS_##_name##_OFST, \
64637907899SIvan Malov MAE_ENC_FIELD_PAIRS_##_name##_LBN, \
64737907899SIvan Malov MAE_ENC_FIELD_PAIRS_##_name##_MASK_OFST, \
64837907899SIvan Malov MAE_ENC_FIELD_PAIRS_##_name##_MASK_LBN, \
64937907899SIvan Malov }
65037907899SIvan Malov
65137907899SIvan Malov EFX_MAE_MV_BIT_DESC(ENC_HAS_OVLAN),
65237907899SIvan Malov EFX_MAE_MV_BIT_DESC(ENC_HAS_IVLAN),
65337907899SIvan Malov
65437907899SIvan Malov #undef EFX_MAE_MV_BIT_DESC
65537907899SIvan Malov };
65637907899SIvan Malov
65737907899SIvan Malov static const efx_mae_mv_bit_desc_t __efx_mae_action_rule_mv_bit_desc_set[] = {
65837907899SIvan Malov #define EFX_MAE_MV_BIT_DESC(_name) \
65937907899SIvan Malov [EFX_MAE_FIELD_##_name] = \
66037907899SIvan Malov { \
66137907899SIvan Malov B_TRUE, \
66237907899SIvan Malov EFX_MAE_FIELD_ID_##_name, \
66337907899SIvan Malov MAE_FIELD_MASK_VALUE_PAIRS_V2_FLAGS_OFST, \
66437907899SIvan Malov MAE_FIELD_MASK_VALUE_PAIRS_V2_##_name##_LBN, \
66537907899SIvan Malov MAE_FIELD_MASK_VALUE_PAIRS_V2_FLAGS_MASK_OFST, \
66637907899SIvan Malov MAE_FIELD_MASK_VALUE_PAIRS_V2_##_name##_LBN, \
66737907899SIvan Malov }
66837907899SIvan Malov
66937907899SIvan Malov EFX_MAE_MV_BIT_DESC(HAS_OVLAN),
67037907899SIvan Malov EFX_MAE_MV_BIT_DESC(HAS_IVLAN),
67137907899SIvan Malov EFX_MAE_MV_BIT_DESC(ENC_HAS_OVLAN),
67237907899SIvan Malov EFX_MAE_MV_BIT_DESC(ENC_HAS_IVLAN),
673f79ce621SArtemii Morozov EFX_MAE_MV_BIT_DESC(IS_IP_FRAG),
674f79ce621SArtemii Morozov EFX_MAE_MV_BIT_DESC(IP_FIRST_FRAG),
67537907899SIvan Malov
67637907899SIvan Malov #undef EFX_MAE_MV_BIT_DESC
67737907899SIvan Malov };
67837907899SIvan Malov
679370ed675SIvan Malov __checkReturn efx_rc_t
efx_mae_mport_invalid(__out efx_mport_sel_t * mportp)68094ddd501SViacheslav Galaktionov efx_mae_mport_invalid(
68194ddd501SViacheslav Galaktionov __out efx_mport_sel_t *mportp)
68294ddd501SViacheslav Galaktionov {
68394ddd501SViacheslav Galaktionov efx_dword_t dword;
68494ddd501SViacheslav Galaktionov efx_rc_t rc;
68594ddd501SViacheslav Galaktionov
68694ddd501SViacheslav Galaktionov if (mportp == NULL) {
68794ddd501SViacheslav Galaktionov rc = EINVAL;
68894ddd501SViacheslav Galaktionov goto fail1;
68994ddd501SViacheslav Galaktionov }
69094ddd501SViacheslav Galaktionov
69194ddd501SViacheslav Galaktionov EFX_POPULATE_DWORD_1(dword,
69294ddd501SViacheslav Galaktionov MAE_MPORT_SELECTOR_TYPE, MAE_MPORT_SELECTOR_TYPE_INVALID);
69394ddd501SViacheslav Galaktionov
69494ddd501SViacheslav Galaktionov memset(mportp, 0, sizeof (*mportp));
69594ddd501SViacheslav Galaktionov mportp->sel = dword.ed_u32[0];
69694ddd501SViacheslav Galaktionov
69794ddd501SViacheslav Galaktionov return (0);
69894ddd501SViacheslav Galaktionov
69994ddd501SViacheslav Galaktionov fail1:
70094ddd501SViacheslav Galaktionov EFSYS_PROBE1(fail1, efx_rc_t, rc);
70194ddd501SViacheslav Galaktionov return (rc);
70294ddd501SViacheslav Galaktionov }
70394ddd501SViacheslav Galaktionov
70494ddd501SViacheslav Galaktionov __checkReturn efx_rc_t
efx_mae_mport_by_phy_port(__in uint32_t phy_port,__out efx_mport_sel_t * mportp)705370ed675SIvan Malov efx_mae_mport_by_phy_port(
706370ed675SIvan Malov __in uint32_t phy_port,
707370ed675SIvan Malov __out efx_mport_sel_t *mportp)
708370ed675SIvan Malov {
709370ed675SIvan Malov efx_dword_t dword;
710370ed675SIvan Malov efx_rc_t rc;
711370ed675SIvan Malov
712370ed675SIvan Malov if (phy_port > EFX_MASK32(MAE_MPORT_SELECTOR_PPORT_ID)) {
713370ed675SIvan Malov rc = EINVAL;
714370ed675SIvan Malov goto fail1;
715370ed675SIvan Malov }
716370ed675SIvan Malov
717370ed675SIvan Malov EFX_POPULATE_DWORD_2(dword,
718370ed675SIvan Malov MAE_MPORT_SELECTOR_TYPE, MAE_MPORT_SELECTOR_TYPE_PPORT,
719370ed675SIvan Malov MAE_MPORT_SELECTOR_PPORT_ID, phy_port);
720370ed675SIvan Malov
721370ed675SIvan Malov memset(mportp, 0, sizeof (*mportp));
722f0d58c4bSIvan Malov /*
723f0d58c4bSIvan Malov * The constructed DWORD is little-endian,
724f0d58c4bSIvan Malov * but the resulting value is meant to be
725f0d58c4bSIvan Malov * passed to MCDIs, where it will undergo
726f0d58c4bSIvan Malov * host-order to little endian conversion.
727f0d58c4bSIvan Malov */
728f0d58c4bSIvan Malov mportp->sel = EFX_DWORD_FIELD(dword, EFX_DWORD_0);
729370ed675SIvan Malov
730370ed675SIvan Malov return (0);
731370ed675SIvan Malov
732370ed675SIvan Malov fail1:
733370ed675SIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
734370ed675SIvan Malov return (rc);
735370ed675SIvan Malov }
736370ed675SIvan Malov
737370ed675SIvan Malov __checkReturn efx_rc_t
efx_mae_mport_by_pcie_function(__in uint32_t pf,__in uint32_t vf,__out efx_mport_sel_t * mportp)73809705803SIvan Malov efx_mae_mport_by_pcie_function(
73909705803SIvan Malov __in uint32_t pf,
74009705803SIvan Malov __in uint32_t vf,
74109705803SIvan Malov __out efx_mport_sel_t *mportp)
74209705803SIvan Malov {
74309705803SIvan Malov efx_dword_t dword;
74409705803SIvan Malov efx_rc_t rc;
74509705803SIvan Malov
7464917b69dSViacheslav Galaktionov rc = efx_mae_mport_by_pcie_mh_function(EFX_PCIE_INTERFACE_CALLER,
7474917b69dSViacheslav Galaktionov pf, vf, mportp);
7484917b69dSViacheslav Galaktionov if (rc != 0)
7494917b69dSViacheslav Galaktionov goto fail1;
75009705803SIvan Malov
7514917b69dSViacheslav Galaktionov return (0);
7524917b69dSViacheslav Galaktionov
7534917b69dSViacheslav Galaktionov fail1:
7544917b69dSViacheslav Galaktionov EFSYS_PROBE1(fail1, efx_rc_t, rc);
7554917b69dSViacheslav Galaktionov return (rc);
7564917b69dSViacheslav Galaktionov }
7574917b69dSViacheslav Galaktionov
7584917b69dSViacheslav Galaktionov static __checkReturn efx_rc_t
efx_mae_intf_to_selector(__in efx_pcie_interface_t intf,__out uint32_t * selector_intfp)7594917b69dSViacheslav Galaktionov efx_mae_intf_to_selector(
7604917b69dSViacheslav Galaktionov __in efx_pcie_interface_t intf,
7614917b69dSViacheslav Galaktionov __out uint32_t *selector_intfp)
7624917b69dSViacheslav Galaktionov {
7634917b69dSViacheslav Galaktionov efx_rc_t rc;
7644917b69dSViacheslav Galaktionov
7654917b69dSViacheslav Galaktionov switch (intf) {
7664917b69dSViacheslav Galaktionov case EFX_PCIE_INTERFACE_HOST_PRIMARY:
7674917b69dSViacheslav Galaktionov EFX_STATIC_ASSERT(MAE_MPORT_SELECTOR_HOST_PRIMARY <=
7684917b69dSViacheslav Galaktionov EFX_MASK32(MAE_MPORT_SELECTOR_FUNC_INTF_ID));
7694917b69dSViacheslav Galaktionov *selector_intfp = MAE_MPORT_SELECTOR_HOST_PRIMARY;
7704917b69dSViacheslav Galaktionov break;
7714917b69dSViacheslav Galaktionov case EFX_PCIE_INTERFACE_NIC_EMBEDDED:
7724917b69dSViacheslav Galaktionov EFX_STATIC_ASSERT(MAE_MPORT_SELECTOR_NIC_EMBEDDED <=
7734917b69dSViacheslav Galaktionov EFX_MASK32(MAE_MPORT_SELECTOR_FUNC_INTF_ID));
7744917b69dSViacheslav Galaktionov *selector_intfp = MAE_MPORT_SELECTOR_NIC_EMBEDDED;
7754917b69dSViacheslav Galaktionov break;
7764917b69dSViacheslav Galaktionov case EFX_PCIE_INTERFACE_CALLER:
7774917b69dSViacheslav Galaktionov EFX_STATIC_ASSERT(MAE_MPORT_SELECTOR_CALLER_INTF <=
7784917b69dSViacheslav Galaktionov EFX_MASK32(MAE_MPORT_SELECTOR_FUNC_INTF_ID));
7794917b69dSViacheslav Galaktionov *selector_intfp = MAE_MPORT_SELECTOR_CALLER_INTF;
7804917b69dSViacheslav Galaktionov break;
7814917b69dSViacheslav Galaktionov default:
78209705803SIvan Malov rc = EINVAL;
78309705803SIvan Malov goto fail1;
78409705803SIvan Malov }
78509705803SIvan Malov
7864917b69dSViacheslav Galaktionov return (0);
7874917b69dSViacheslav Galaktionov
7884917b69dSViacheslav Galaktionov fail1:
7894917b69dSViacheslav Galaktionov EFSYS_PROBE1(fail1, efx_rc_t, rc);
7904917b69dSViacheslav Galaktionov return (rc);
7914917b69dSViacheslav Galaktionov }
7924917b69dSViacheslav Galaktionov
7934917b69dSViacheslav Galaktionov __checkReturn efx_rc_t
efx_mae_mport_by_pcie_mh_function(__in efx_pcie_interface_t intf,__in uint32_t pf,__in uint32_t vf,__out efx_mport_sel_t * mportp)7944917b69dSViacheslav Galaktionov efx_mae_mport_by_pcie_mh_function(
7954917b69dSViacheslav Galaktionov __in efx_pcie_interface_t intf,
7964917b69dSViacheslav Galaktionov __in uint32_t pf,
7974917b69dSViacheslav Galaktionov __in uint32_t vf,
7984917b69dSViacheslav Galaktionov __out efx_mport_sel_t *mportp)
7994917b69dSViacheslav Galaktionov {
8004917b69dSViacheslav Galaktionov uint32_t selector_intf;
8014917b69dSViacheslav Galaktionov efx_dword_t dword;
8024917b69dSViacheslav Galaktionov efx_rc_t rc;
8034917b69dSViacheslav Galaktionov
8044917b69dSViacheslav Galaktionov EFX_STATIC_ASSERT(EFX_PCI_VF_INVALID ==
8054917b69dSViacheslav Galaktionov MAE_MPORT_SELECTOR_FUNC_VF_ID_NULL);
8064917b69dSViacheslav Galaktionov
8074917b69dSViacheslav Galaktionov rc = efx_mae_intf_to_selector(intf, &selector_intf);
8084917b69dSViacheslav Galaktionov if (rc != 0)
8094917b69dSViacheslav Galaktionov goto fail1;
8104917b69dSViacheslav Galaktionov
8114917b69dSViacheslav Galaktionov if (pf > EFX_MASK32(MAE_MPORT_SELECTOR_FUNC_MH_PF_ID)) {
81209705803SIvan Malov rc = EINVAL;
81309705803SIvan Malov goto fail2;
81409705803SIvan Malov }
81509705803SIvan Malov
8164917b69dSViacheslav Galaktionov if (vf > EFX_MASK32(MAE_MPORT_SELECTOR_FUNC_VF_ID)) {
8174917b69dSViacheslav Galaktionov rc = EINVAL;
8184917b69dSViacheslav Galaktionov goto fail3;
8194917b69dSViacheslav Galaktionov }
8204917b69dSViacheslav Galaktionov
8214917b69dSViacheslav Galaktionov
8224917b69dSViacheslav Galaktionov EFX_POPULATE_DWORD_4(dword,
8234917b69dSViacheslav Galaktionov MAE_MPORT_SELECTOR_TYPE, MAE_MPORT_SELECTOR_TYPE_MH_FUNC,
8244917b69dSViacheslav Galaktionov MAE_MPORT_SELECTOR_FUNC_INTF_ID, selector_intf,
8254917b69dSViacheslav Galaktionov MAE_MPORT_SELECTOR_FUNC_MH_PF_ID, pf,
82609705803SIvan Malov MAE_MPORT_SELECTOR_FUNC_VF_ID, vf);
82709705803SIvan Malov
82809705803SIvan Malov memset(mportp, 0, sizeof (*mportp));
8294917b69dSViacheslav Galaktionov mportp->sel = dword.ed_u32[0];
83009705803SIvan Malov
83109705803SIvan Malov return (0);
83209705803SIvan Malov
8334917b69dSViacheslav Galaktionov fail3:
8344917b69dSViacheslav Galaktionov EFSYS_PROBE(fail3);
83509705803SIvan Malov fail2:
83609705803SIvan Malov EFSYS_PROBE(fail2);
83709705803SIvan Malov fail1:
83809705803SIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
83909705803SIvan Malov return (rc);
84009705803SIvan Malov }
84109705803SIvan Malov
8424ea8bb78SIgor Romanov static __checkReturn efx_rc_t
efx_mcdi_mae_mport_lookup(__in efx_nic_t * enp,__in const efx_mport_sel_t * mport_selectorp,__out efx_mport_id_t * mport_idp)8434ea8bb78SIgor Romanov efx_mcdi_mae_mport_lookup(
8444ea8bb78SIgor Romanov __in efx_nic_t *enp,
8454ea8bb78SIgor Romanov __in const efx_mport_sel_t *mport_selectorp,
8464ea8bb78SIgor Romanov __out efx_mport_id_t *mport_idp)
8474ea8bb78SIgor Romanov {
8484ea8bb78SIgor Romanov efx_mcdi_req_t req;
8494ea8bb78SIgor Romanov EFX_MCDI_DECLARE_BUF(payload,
8504ea8bb78SIgor Romanov MC_CMD_MAE_MPORT_LOOKUP_IN_LEN,
8514ea8bb78SIgor Romanov MC_CMD_MAE_MPORT_LOOKUP_OUT_LEN);
8524ea8bb78SIgor Romanov efx_rc_t rc;
8534ea8bb78SIgor Romanov
8544ea8bb78SIgor Romanov req.emr_cmd = MC_CMD_MAE_MPORT_LOOKUP;
8554ea8bb78SIgor Romanov req.emr_in_buf = payload;
8564ea8bb78SIgor Romanov req.emr_in_length = MC_CMD_MAE_MPORT_LOOKUP_IN_LEN;
8574ea8bb78SIgor Romanov req.emr_out_buf = payload;
8584ea8bb78SIgor Romanov req.emr_out_length = MC_CMD_MAE_MPORT_LOOKUP_OUT_LEN;
8594ea8bb78SIgor Romanov
8604ea8bb78SIgor Romanov MCDI_IN_SET_DWORD(req, MAE_MPORT_LOOKUP_IN_MPORT_SELECTOR,
8614ea8bb78SIgor Romanov mport_selectorp->sel);
8624ea8bb78SIgor Romanov
8634ea8bb78SIgor Romanov efx_mcdi_execute(enp, &req);
8644ea8bb78SIgor Romanov
8654ea8bb78SIgor Romanov if (req.emr_rc != 0) {
8664ea8bb78SIgor Romanov rc = req.emr_rc;
8674ea8bb78SIgor Romanov goto fail1;
8684ea8bb78SIgor Romanov }
8694ea8bb78SIgor Romanov
8704ea8bb78SIgor Romanov mport_idp->id = MCDI_OUT_DWORD(req, MAE_MPORT_LOOKUP_OUT_MPORT_ID);
8714ea8bb78SIgor Romanov
8724ea8bb78SIgor Romanov return (0);
8734ea8bb78SIgor Romanov
8744ea8bb78SIgor Romanov fail1:
8754ea8bb78SIgor Romanov EFSYS_PROBE1(fail1, efx_rc_t, rc);
8764ea8bb78SIgor Romanov return (rc);
8774ea8bb78SIgor Romanov }
8784ea8bb78SIgor Romanov
8794ea8bb78SIgor Romanov __checkReturn efx_rc_t
efx_mae_mport_id_by_selector(__in efx_nic_t * enp,__in const efx_mport_sel_t * mport_selectorp,__out efx_mport_id_t * mport_idp)8804ea8bb78SIgor Romanov efx_mae_mport_id_by_selector(
8814ea8bb78SIgor Romanov __in efx_nic_t *enp,
8824ea8bb78SIgor Romanov __in const efx_mport_sel_t *mport_selectorp,
8834ea8bb78SIgor Romanov __out efx_mport_id_t *mport_idp)
8844ea8bb78SIgor Romanov {
8854ea8bb78SIgor Romanov const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
8864ea8bb78SIgor Romanov efx_rc_t rc;
8874ea8bb78SIgor Romanov
8884ea8bb78SIgor Romanov if (encp->enc_mae_supported == B_FALSE) {
8894ea8bb78SIgor Romanov rc = ENOTSUP;
8904ea8bb78SIgor Romanov goto fail1;
8914ea8bb78SIgor Romanov }
8924ea8bb78SIgor Romanov
8934ea8bb78SIgor Romanov rc = efx_mcdi_mae_mport_lookup(enp, mport_selectorp, mport_idp);
8944ea8bb78SIgor Romanov if (rc != 0)
8954ea8bb78SIgor Romanov goto fail2;
8964ea8bb78SIgor Romanov
8974ea8bb78SIgor Romanov return (0);
8984ea8bb78SIgor Romanov
8994ea8bb78SIgor Romanov fail2:
9004ea8bb78SIgor Romanov EFSYS_PROBE(fail2);
9014ea8bb78SIgor Romanov fail1:
9024ea8bb78SIgor Romanov EFSYS_PROBE1(fail1, efx_rc_t, rc);
9034ea8bb78SIgor Romanov return (rc);
9044ea8bb78SIgor Romanov }
9054ea8bb78SIgor Romanov
90609705803SIvan Malov __checkReturn efx_rc_t
efx_mae_match_spec_recirc_id_set(__in efx_mae_match_spec_t * spec,__in uint8_t recirc_id)9073a73dcfdSIvan Malov efx_mae_match_spec_recirc_id_set(
9083a73dcfdSIvan Malov __in efx_mae_match_spec_t *spec,
9093a73dcfdSIvan Malov __in uint8_t recirc_id)
9103a73dcfdSIvan Malov {
9113a73dcfdSIvan Malov uint8_t full_mask = UINT8_MAX;
9123a73dcfdSIvan Malov const uint8_t *vp;
9133a73dcfdSIvan Malov const uint8_t *mp;
9143a73dcfdSIvan Malov efx_rc_t rc;
9153a73dcfdSIvan Malov
9163a73dcfdSIvan Malov vp = (const uint8_t *)&recirc_id;
9173a73dcfdSIvan Malov mp = (const uint8_t *)&full_mask;
9183a73dcfdSIvan Malov
9193a73dcfdSIvan Malov rc = efx_mae_match_spec_field_set(spec, EFX_MAE_FIELD_RECIRC_ID,
9203a73dcfdSIvan Malov sizeof (recirc_id), vp,
9213a73dcfdSIvan Malov sizeof (full_mask), mp);
9223a73dcfdSIvan Malov if (rc != 0)
9233a73dcfdSIvan Malov goto fail1;
9243a73dcfdSIvan Malov
9253a73dcfdSIvan Malov return (0);
9263a73dcfdSIvan Malov
9273a73dcfdSIvan Malov fail1:
9283a73dcfdSIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
9293a73dcfdSIvan Malov return (rc);
9303a73dcfdSIvan Malov }
9313a73dcfdSIvan Malov
9323a73dcfdSIvan Malov __checkReturn efx_rc_t
efx_mae_match_spec_ct_mark_set(__in efx_mae_match_spec_t * spec,__in uint32_t ct_mark)93393c5d2c6SIvan Malov efx_mae_match_spec_ct_mark_set(
93493c5d2c6SIvan Malov __in efx_mae_match_spec_t *spec,
93593c5d2c6SIvan Malov __in uint32_t ct_mark)
93693c5d2c6SIvan Malov {
93793c5d2c6SIvan Malov uint32_t full_mask = UINT32_MAX;
93893c5d2c6SIvan Malov const uint8_t *vp;
93993c5d2c6SIvan Malov const uint8_t *mp;
94093c5d2c6SIvan Malov efx_rc_t rc;
94193c5d2c6SIvan Malov
94293c5d2c6SIvan Malov mp = (const uint8_t *)&full_mask;
94393c5d2c6SIvan Malov vp = (const uint8_t *)&ct_mark;
94493c5d2c6SIvan Malov
94593c5d2c6SIvan Malov rc = efx_mae_match_spec_field_set(spec, EFX_MAE_FIELD_CT_MARK,
94693c5d2c6SIvan Malov sizeof (ct_mark), vp,
94793c5d2c6SIvan Malov sizeof (full_mask), mp);
94893c5d2c6SIvan Malov if (rc != 0)
94993c5d2c6SIvan Malov goto fail1;
95093c5d2c6SIvan Malov
95193c5d2c6SIvan Malov return (0);
95293c5d2c6SIvan Malov
95393c5d2c6SIvan Malov fail1:
95493c5d2c6SIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
95593c5d2c6SIvan Malov return (rc);
95693c5d2c6SIvan Malov }
95793c5d2c6SIvan Malov
95893c5d2c6SIvan Malov __checkReturn efx_rc_t
efx_mae_mport_by_id(__in const efx_mport_id_t * mport_idp,__out efx_mport_sel_t * mportp)9593d6e8e45SIgor Romanov efx_mae_mport_by_id(
9603d6e8e45SIgor Romanov __in const efx_mport_id_t *mport_idp,
9613d6e8e45SIgor Romanov __out efx_mport_sel_t *mportp)
9623d6e8e45SIgor Romanov {
9633d6e8e45SIgor Romanov efx_dword_t dword;
9643d6e8e45SIgor Romanov
9653d6e8e45SIgor Romanov EFX_POPULATE_DWORD_2(dword,
9663d6e8e45SIgor Romanov MAE_MPORT_SELECTOR_TYPE, MAE_MPORT_SELECTOR_TYPE_MPORT_ID,
9673d6e8e45SIgor Romanov MAE_MPORT_SELECTOR_MPORT_ID, mport_idp->id);
9683d6e8e45SIgor Romanov
9693d6e8e45SIgor Romanov memset(mportp, 0, sizeof (*mportp));
9703d6e8e45SIgor Romanov mportp->sel = __LE_TO_CPU_32(dword.ed_u32[0]);
9713d6e8e45SIgor Romanov
9723d6e8e45SIgor Romanov return (0);
9733d6e8e45SIgor Romanov }
9743d6e8e45SIgor Romanov
9753d6e8e45SIgor Romanov __checkReturn efx_rc_t
efx_mae_match_spec_field_set(__in efx_mae_match_spec_t * spec,__in efx_mae_field_id_t field_id,__in size_t value_size,__in_bcount (value_size)const uint8_t * value,__in size_t mask_size,__in_bcount (mask_size)const uint8_t * mask)976370ed675SIvan Malov efx_mae_match_spec_field_set(
977370ed675SIvan Malov __in efx_mae_match_spec_t *spec,
978370ed675SIvan Malov __in efx_mae_field_id_t field_id,
979370ed675SIvan Malov __in size_t value_size,
980370ed675SIvan Malov __in_bcount(value_size) const uint8_t *value,
981370ed675SIvan Malov __in size_t mask_size,
982370ed675SIvan Malov __in_bcount(mask_size) const uint8_t *mask)
983370ed675SIvan Malov {
984370ed675SIvan Malov const efx_mae_mv_desc_t *descp;
985e9d5c5fbSIvan Malov unsigned int desc_set_nentries;
986370ed675SIvan Malov uint8_t *mvp;
987370ed675SIvan Malov efx_rc_t rc;
988370ed675SIvan Malov
989370ed675SIvan Malov switch (spec->emms_type) {
9901efc26e1SIvan Malov case EFX_MAE_RULE_OUTER:
991e9d5c5fbSIvan Malov desc_set_nentries =
992e9d5c5fbSIvan Malov EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_desc_set);
9931efc26e1SIvan Malov descp = &__efx_mae_outer_rule_mv_desc_set[field_id];
9941efc26e1SIvan Malov mvp = spec->emms_mask_value_pairs.outer;
9951efc26e1SIvan Malov break;
996370ed675SIvan Malov case EFX_MAE_RULE_ACTION:
997e9d5c5fbSIvan Malov desc_set_nentries =
998e9d5c5fbSIvan Malov EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_desc_set);
999370ed675SIvan Malov descp = &__efx_mae_action_rule_mv_desc_set[field_id];
1000370ed675SIvan Malov mvp = spec->emms_mask_value_pairs.action;
1001370ed675SIvan Malov break;
1002370ed675SIvan Malov default:
1003370ed675SIvan Malov rc = ENOTSUP;
1004e9d5c5fbSIvan Malov goto fail1;
1005e9d5c5fbSIvan Malov }
1006e9d5c5fbSIvan Malov
1007a0f0b03cSIvan Malov if ((unsigned int)field_id >= desc_set_nentries) {
1008e9d5c5fbSIvan Malov rc = EINVAL;
1009370ed675SIvan Malov goto fail2;
1010370ed675SIvan Malov }
1011370ed675SIvan Malov
10125da37ab5SIvan Malov if (descp->emmd_mask_size == 0) {
10135da37ab5SIvan Malov /* The ID points to a gap in the array of field descriptors. */
1014370ed675SIvan Malov rc = EINVAL;
1015370ed675SIvan Malov goto fail3;
1016370ed675SIvan Malov }
1017370ed675SIvan Malov
10185da37ab5SIvan Malov if (value_size != descp->emmd_value_size) {
1019370ed675SIvan Malov rc = EINVAL;
1020370ed675SIvan Malov goto fail4;
1021370ed675SIvan Malov }
1022370ed675SIvan Malov
10235da37ab5SIvan Malov if (mask_size != descp->emmd_mask_size) {
10245da37ab5SIvan Malov rc = EINVAL;
10255da37ab5SIvan Malov goto fail5;
10265da37ab5SIvan Malov }
10275da37ab5SIvan Malov
1028370ed675SIvan Malov if (descp->emmd_endianness == EFX_MAE_FIELD_BE) {
1029f80487b9SIvan Malov unsigned int i;
1030f80487b9SIvan Malov
1031370ed675SIvan Malov /*
1032370ed675SIvan Malov * The mask/value are in network (big endian) order.
1033370ed675SIvan Malov * The MCDI request field is also big endian.
1034370ed675SIvan Malov */
1035f80487b9SIvan Malov
1036f80487b9SIvan Malov EFSYS_ASSERT3U(value_size, ==, mask_size);
1037f80487b9SIvan Malov
1038f80487b9SIvan Malov for (i = 0; i < value_size; ++i) {
1039f80487b9SIvan Malov uint8_t *v_bytep = mvp + descp->emmd_value_offset + i;
1040f80487b9SIvan Malov uint8_t *m_bytep = mvp + descp->emmd_mask_offset + i;
1041f80487b9SIvan Malov
1042f80487b9SIvan Malov /*
1043f80487b9SIvan Malov * Apply the mask (which may be all-zeros) to the value.
1044f80487b9SIvan Malov *
1045f80487b9SIvan Malov * If this API is provided with some value to set for a
1046f80487b9SIvan Malov * given field in one specification and with some other
1047f80487b9SIvan Malov * value to set for this field in another specification,
1048f80487b9SIvan Malov * then, if the two masks are all-zeros, the field will
1049f80487b9SIvan Malov * avoid being counted as a mismatch when comparing the
1050f80487b9SIvan Malov * specifications using efx_mae_match_specs_equal() API.
1051f80487b9SIvan Malov */
1052f80487b9SIvan Malov *v_bytep = value[i] & mask[i];
1053f80487b9SIvan Malov *m_bytep = mask[i];
1054f80487b9SIvan Malov }
1055370ed675SIvan Malov } else {
1056370ed675SIvan Malov efx_dword_t dword;
1057370ed675SIvan Malov
1058370ed675SIvan Malov /*
1059370ed675SIvan Malov * The mask/value are in host byte order.
1060370ed675SIvan Malov * The MCDI request field is little endian.
1061370ed675SIvan Malov */
1062370ed675SIvan Malov switch (value_size) {
1063370ed675SIvan Malov case 4:
1064370ed675SIvan Malov EFX_POPULATE_DWORD_1(dword,
1065370ed675SIvan Malov EFX_DWORD_0, *(const uint32_t *)value);
1066370ed675SIvan Malov
1067370ed675SIvan Malov memcpy(mvp + descp->emmd_value_offset,
1068370ed675SIvan Malov &dword, sizeof (dword));
1069370ed675SIvan Malov break;
1070a3b2ade4SIvan Malov case 1:
1071a3b2ade4SIvan Malov memcpy(mvp + descp->emmd_value_offset,
1072a3b2ade4SIvan Malov value, 1);
1073a3b2ade4SIvan Malov break;
1074370ed675SIvan Malov default:
1075370ed675SIvan Malov EFSYS_ASSERT(B_FALSE);
1076370ed675SIvan Malov }
1077370ed675SIvan Malov
1078370ed675SIvan Malov switch (mask_size) {
1079370ed675SIvan Malov case 4:
1080370ed675SIvan Malov EFX_POPULATE_DWORD_1(dword,
1081370ed675SIvan Malov EFX_DWORD_0, *(const uint32_t *)mask);
1082370ed675SIvan Malov
1083370ed675SIvan Malov memcpy(mvp + descp->emmd_mask_offset,
1084370ed675SIvan Malov &dword, sizeof (dword));
1085370ed675SIvan Malov break;
1086a3b2ade4SIvan Malov case 1:
1087a3b2ade4SIvan Malov memcpy(mvp + descp->emmd_mask_offset,
1088a3b2ade4SIvan Malov mask, 1);
1089a3b2ade4SIvan Malov break;
1090370ed675SIvan Malov default:
1091370ed675SIvan Malov EFSYS_ASSERT(B_FALSE);
1092370ed675SIvan Malov }
1093370ed675SIvan Malov }
1094370ed675SIvan Malov
1095370ed675SIvan Malov return (0);
1096370ed675SIvan Malov
10975da37ab5SIvan Malov fail5:
10985da37ab5SIvan Malov EFSYS_PROBE(fail5);
1099370ed675SIvan Malov fail4:
1100370ed675SIvan Malov EFSYS_PROBE(fail4);
1101370ed675SIvan Malov fail3:
1102370ed675SIvan Malov EFSYS_PROBE(fail3);
1103370ed675SIvan Malov fail2:
1104370ed675SIvan Malov EFSYS_PROBE(fail2);
1105370ed675SIvan Malov fail1:
1106370ed675SIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
1107370ed675SIvan Malov return (rc);
1108370ed675SIvan Malov }
1109370ed675SIvan Malov
1110370ed675SIvan Malov __checkReturn efx_rc_t
efx_mae_match_spec_field_get(__in const efx_mae_match_spec_t * spec,__in efx_mae_field_id_t field_id,__in size_t value_size,__out_bcount_opt (value_size)uint8_t * value,__in size_t mask_size,__out_bcount_opt (mask_size)uint8_t * mask)1111d1b920b8SIvan Malov efx_mae_match_spec_field_get(
1112d1b920b8SIvan Malov __in const efx_mae_match_spec_t *spec,
1113d1b920b8SIvan Malov __in efx_mae_field_id_t field_id,
1114d1b920b8SIvan Malov __in size_t value_size,
1115d1b920b8SIvan Malov __out_bcount_opt(value_size) uint8_t *value,
1116d1b920b8SIvan Malov __in size_t mask_size,
1117d1b920b8SIvan Malov __out_bcount_opt(mask_size) uint8_t *mask)
1118d1b920b8SIvan Malov {
1119d1b920b8SIvan Malov const efx_mae_mv_desc_t *descp;
1120d1b920b8SIvan Malov unsigned int desc_set_nentries;
1121d1b920b8SIvan Malov const uint8_t *mvp;
1122d1b920b8SIvan Malov efx_rc_t rc;
1123d1b920b8SIvan Malov
1124d1b920b8SIvan Malov switch (spec->emms_type) {
1125d1b920b8SIvan Malov case EFX_MAE_RULE_OUTER:
1126d1b920b8SIvan Malov desc_set_nentries =
1127d1b920b8SIvan Malov EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_desc_set);
1128d1b920b8SIvan Malov descp = &__efx_mae_outer_rule_mv_desc_set[field_id];
1129d1b920b8SIvan Malov mvp = spec->emms_mask_value_pairs.outer;
1130d1b920b8SIvan Malov break;
1131d1b920b8SIvan Malov case EFX_MAE_RULE_ACTION:
1132d1b920b8SIvan Malov desc_set_nentries =
1133d1b920b8SIvan Malov EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_desc_set);
1134d1b920b8SIvan Malov descp = &__efx_mae_action_rule_mv_desc_set[field_id];
1135d1b920b8SIvan Malov mvp = spec->emms_mask_value_pairs.action;
1136d1b920b8SIvan Malov break;
1137d1b920b8SIvan Malov default:
1138d1b920b8SIvan Malov rc = ENOTSUP;
1139d1b920b8SIvan Malov goto fail1;
1140d1b920b8SIvan Malov }
1141d1b920b8SIvan Malov
1142d1b920b8SIvan Malov if ((unsigned int)field_id >= desc_set_nentries) {
1143d1b920b8SIvan Malov rc = EINVAL;
1144d1b920b8SIvan Malov goto fail2;
1145d1b920b8SIvan Malov }
1146d1b920b8SIvan Malov
1147d1b920b8SIvan Malov if (descp->emmd_mask_size == 0) {
1148d1b920b8SIvan Malov /* The ID points to a gap in the array of field descriptors. */
1149d1b920b8SIvan Malov rc = EINVAL;
1150d1b920b8SIvan Malov goto fail3;
1151d1b920b8SIvan Malov }
1152d1b920b8SIvan Malov
1153d1b920b8SIvan Malov if (value != NULL && value_size != descp->emmd_value_size) {
1154d1b920b8SIvan Malov rc = EINVAL;
1155d1b920b8SIvan Malov goto fail4;
1156d1b920b8SIvan Malov }
1157d1b920b8SIvan Malov
1158d1b920b8SIvan Malov if (mask != NULL && mask_size != descp->emmd_mask_size) {
1159d1b920b8SIvan Malov rc = EINVAL;
1160d1b920b8SIvan Malov goto fail5;
1161d1b920b8SIvan Malov }
1162d1b920b8SIvan Malov
1163d1b920b8SIvan Malov if (value == NULL && value_size != 0) {
1164d1b920b8SIvan Malov rc = EINVAL;
1165d1b920b8SIvan Malov goto fail6;
1166d1b920b8SIvan Malov }
1167d1b920b8SIvan Malov
1168d1b920b8SIvan Malov if (mask == NULL && mask_size != 0) {
1169d1b920b8SIvan Malov rc = EINVAL;
1170d1b920b8SIvan Malov goto fail7;
1171d1b920b8SIvan Malov }
1172d1b920b8SIvan Malov
1173d1b920b8SIvan Malov if (descp->emmd_endianness == EFX_MAE_FIELD_BE) {
1174d1b920b8SIvan Malov /*
1175d1b920b8SIvan Malov * The MCDI request field is in network (big endian) order.
1176d1b920b8SIvan Malov * The mask/value are also big endian.
1177d1b920b8SIvan Malov */
1178d1b920b8SIvan Malov memcpy(value, mvp + descp->emmd_value_offset, value_size);
1179d1b920b8SIvan Malov memcpy(mask, mvp + descp->emmd_mask_offset, mask_size);
1180d1b920b8SIvan Malov } else {
1181d1b920b8SIvan Malov efx_dword_t dword;
1182d1b920b8SIvan Malov
1183d1b920b8SIvan Malov /*
1184d1b920b8SIvan Malov * The MCDI request field is little endian.
1185d1b920b8SIvan Malov * The mask/value are in host byte order.
1186d1b920b8SIvan Malov */
1187d1b920b8SIvan Malov switch (value_size) {
1188d1b920b8SIvan Malov case 4:
1189d1b920b8SIvan Malov memcpy(&dword, mvp + descp->emmd_value_offset,
1190d1b920b8SIvan Malov sizeof (dword));
1191d1b920b8SIvan Malov
1192d1b920b8SIvan Malov *(uint32_t *)value =
1193d1b920b8SIvan Malov EFX_DWORD_FIELD(dword, EFX_DWORD_0);
1194d1b920b8SIvan Malov break;
1195d1b920b8SIvan Malov case 1:
1196d1b920b8SIvan Malov memcpy(value, mvp + descp->emmd_value_offset, 1);
1197d1b920b8SIvan Malov break;
1198d1b920b8SIvan Malov case 0:
1199d1b920b8SIvan Malov break;
1200d1b920b8SIvan Malov default:
1201d1b920b8SIvan Malov EFSYS_ASSERT(B_FALSE);
1202d1b920b8SIvan Malov }
1203d1b920b8SIvan Malov
1204d1b920b8SIvan Malov switch (mask_size) {
1205d1b920b8SIvan Malov case 4:
1206d1b920b8SIvan Malov memcpy(&dword, mvp + descp->emmd_mask_offset,
1207d1b920b8SIvan Malov sizeof (dword));
1208d1b920b8SIvan Malov
1209d1b920b8SIvan Malov *(uint32_t *)mask =
1210d1b920b8SIvan Malov EFX_DWORD_FIELD(dword, EFX_DWORD_0);
1211d1b920b8SIvan Malov break;
1212d1b920b8SIvan Malov case 1:
1213d1b920b8SIvan Malov memcpy(mask, mvp + descp->emmd_mask_offset, 1);
1214d1b920b8SIvan Malov break;
1215d1b920b8SIvan Malov case 0:
1216d1b920b8SIvan Malov break;
1217d1b920b8SIvan Malov default:
1218d1b920b8SIvan Malov EFSYS_ASSERT(B_FALSE);
1219d1b920b8SIvan Malov }
1220d1b920b8SIvan Malov }
1221d1b920b8SIvan Malov
1222d1b920b8SIvan Malov return (0);
1223d1b920b8SIvan Malov
1224d1b920b8SIvan Malov fail7:
1225d1b920b8SIvan Malov EFSYS_PROBE(fail7);
1226d1b920b8SIvan Malov fail6:
1227d1b920b8SIvan Malov EFSYS_PROBE(fail6);
1228d1b920b8SIvan Malov fail5:
1229d1b920b8SIvan Malov EFSYS_PROBE(fail5);
1230d1b920b8SIvan Malov fail4:
1231d1b920b8SIvan Malov EFSYS_PROBE(fail4);
1232d1b920b8SIvan Malov fail3:
1233d1b920b8SIvan Malov EFSYS_PROBE(fail3);
1234d1b920b8SIvan Malov fail2:
1235d1b920b8SIvan Malov EFSYS_PROBE(fail2);
1236d1b920b8SIvan Malov fail1:
1237d1b920b8SIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
1238d1b920b8SIvan Malov return (rc);
1239d1b920b8SIvan Malov }
1240d1b920b8SIvan Malov
1241d1b920b8SIvan Malov __checkReturn efx_rc_t
efx_mae_match_spec_bit_set(__in efx_mae_match_spec_t * spec,__in efx_mae_field_id_t field_id,__in boolean_t value)124237907899SIvan Malov efx_mae_match_spec_bit_set(
124337907899SIvan Malov __in efx_mae_match_spec_t *spec,
124437907899SIvan Malov __in efx_mae_field_id_t field_id,
124537907899SIvan Malov __in boolean_t value)
124637907899SIvan Malov {
124737907899SIvan Malov const efx_mae_mv_bit_desc_t *bit_descp;
124837907899SIvan Malov unsigned int bit_desc_set_nentries;
124937907899SIvan Malov unsigned int byte_idx;
125037907899SIvan Malov unsigned int bit_idx;
125137907899SIvan Malov uint8_t *mvp;
125237907899SIvan Malov efx_rc_t rc;
125337907899SIvan Malov
125437907899SIvan Malov switch (spec->emms_type) {
125537907899SIvan Malov case EFX_MAE_RULE_OUTER:
125637907899SIvan Malov bit_desc_set_nentries =
125737907899SIvan Malov EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_bit_desc_set);
125837907899SIvan Malov bit_descp = &__efx_mae_outer_rule_mv_bit_desc_set[field_id];
125937907899SIvan Malov mvp = spec->emms_mask_value_pairs.outer;
126037907899SIvan Malov break;
126137907899SIvan Malov case EFX_MAE_RULE_ACTION:
126237907899SIvan Malov bit_desc_set_nentries =
126337907899SIvan Malov EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_bit_desc_set);
126437907899SIvan Malov bit_descp = &__efx_mae_action_rule_mv_bit_desc_set[field_id];
126537907899SIvan Malov mvp = spec->emms_mask_value_pairs.action;
126637907899SIvan Malov break;
126737907899SIvan Malov default:
126837907899SIvan Malov rc = ENOTSUP;
126937907899SIvan Malov goto fail1;
127037907899SIvan Malov }
127137907899SIvan Malov
127237907899SIvan Malov if ((unsigned int)field_id >= bit_desc_set_nentries) {
127337907899SIvan Malov rc = EINVAL;
127437907899SIvan Malov goto fail2;
127537907899SIvan Malov }
127637907899SIvan Malov
127737907899SIvan Malov if (bit_descp->emmbd_entry_is_valid == B_FALSE) {
127837907899SIvan Malov rc = EINVAL;
127937907899SIvan Malov goto fail3;
128037907899SIvan Malov }
128137907899SIvan Malov
128237907899SIvan Malov byte_idx = bit_descp->emmbd_value_ofst + bit_descp->emmbd_value_lbn / 8;
128337907899SIvan Malov bit_idx = bit_descp->emmbd_value_lbn % 8;
128437907899SIvan Malov
128537907899SIvan Malov if (value != B_FALSE)
128637907899SIvan Malov mvp[byte_idx] |= (1U << bit_idx);
128737907899SIvan Malov else
128837907899SIvan Malov mvp[byte_idx] &= ~(1U << bit_idx);
128937907899SIvan Malov
129037907899SIvan Malov byte_idx = bit_descp->emmbd_mask_ofst + bit_descp->emmbd_mask_lbn / 8;
129137907899SIvan Malov bit_idx = bit_descp->emmbd_mask_lbn % 8;
129237907899SIvan Malov mvp[byte_idx] |= (1U << bit_idx);
129337907899SIvan Malov
129437907899SIvan Malov return (0);
129537907899SIvan Malov
129637907899SIvan Malov fail3:
129737907899SIvan Malov EFSYS_PROBE(fail3);
129837907899SIvan Malov fail2:
129937907899SIvan Malov EFSYS_PROBE(fail2);
130037907899SIvan Malov fail1:
130137907899SIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
130237907899SIvan Malov return (rc);
130337907899SIvan Malov }
130437907899SIvan Malov
130537907899SIvan Malov __checkReturn efx_rc_t
efx_mae_match_spec_mport_set(__in efx_mae_match_spec_t * spec,__in const efx_mport_sel_t * valuep,__in_opt const efx_mport_sel_t * maskp)1306370ed675SIvan Malov efx_mae_match_spec_mport_set(
1307370ed675SIvan Malov __in efx_mae_match_spec_t *spec,
1308370ed675SIvan Malov __in const efx_mport_sel_t *valuep,
1309370ed675SIvan Malov __in_opt const efx_mport_sel_t *maskp)
1310370ed675SIvan Malov {
1311370ed675SIvan Malov uint32_t full_mask = UINT32_MAX;
1312370ed675SIvan Malov const uint8_t *vp;
1313370ed675SIvan Malov const uint8_t *mp;
1314370ed675SIvan Malov efx_rc_t rc;
1315370ed675SIvan Malov
1316370ed675SIvan Malov if (valuep == NULL) {
1317370ed675SIvan Malov rc = EINVAL;
1318370ed675SIvan Malov goto fail1;
1319370ed675SIvan Malov }
1320370ed675SIvan Malov
1321370ed675SIvan Malov vp = (const uint8_t *)&valuep->sel;
1322370ed675SIvan Malov if (maskp != NULL)
1323370ed675SIvan Malov mp = (const uint8_t *)&maskp->sel;
1324370ed675SIvan Malov else
1325370ed675SIvan Malov mp = (const uint8_t *)&full_mask;
1326370ed675SIvan Malov
1327370ed675SIvan Malov rc = efx_mae_match_spec_field_set(spec,
1328370ed675SIvan Malov EFX_MAE_FIELD_INGRESS_MPORT_SELECTOR,
1329370ed675SIvan Malov sizeof (valuep->sel), vp, sizeof (maskp->sel), mp);
1330370ed675SIvan Malov if (rc != 0)
1331370ed675SIvan Malov goto fail2;
1332370ed675SIvan Malov
1333370ed675SIvan Malov return (0);
1334370ed675SIvan Malov
1335370ed675SIvan Malov fail2:
1336370ed675SIvan Malov EFSYS_PROBE(fail2);
1337370ed675SIvan Malov fail1:
1338370ed675SIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
1339370ed675SIvan Malov return (rc);
1340370ed675SIvan Malov }
1341370ed675SIvan Malov
1342c354c7c2SIvan Malov __checkReturn efx_rc_t
efx_mae_match_spec_clone(__in efx_nic_t * enp,__in efx_mae_match_spec_t * orig,__out efx_mae_match_spec_t ** clonep)1343c354c7c2SIvan Malov efx_mae_match_spec_clone(
1344c354c7c2SIvan Malov __in efx_nic_t *enp,
1345c354c7c2SIvan Malov __in efx_mae_match_spec_t *orig,
1346c354c7c2SIvan Malov __out efx_mae_match_spec_t **clonep)
1347c354c7c2SIvan Malov {
1348c354c7c2SIvan Malov efx_mae_match_spec_t *clone;
1349c354c7c2SIvan Malov efx_rc_t rc;
1350c354c7c2SIvan Malov
1351c354c7c2SIvan Malov EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (*clone), clone);
1352c354c7c2SIvan Malov if (clone == NULL) {
1353c354c7c2SIvan Malov rc = ENOMEM;
1354c354c7c2SIvan Malov goto fail1;
1355c354c7c2SIvan Malov }
1356c354c7c2SIvan Malov
1357c354c7c2SIvan Malov memcpy(clone, orig, sizeof (efx_mae_match_spec_t));
1358c354c7c2SIvan Malov
1359c354c7c2SIvan Malov *clonep = clone;
1360c354c7c2SIvan Malov
1361c354c7c2SIvan Malov return (0);
1362c354c7c2SIvan Malov
1363c354c7c2SIvan Malov fail1:
1364c354c7c2SIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
1365c354c7c2SIvan Malov return (rc);
1366c354c7c2SIvan Malov }
1367c354c7c2SIvan Malov
136836d124c3SIvan Malov __checkReturn boolean_t
efx_mae_match_specs_equal(__in const efx_mae_match_spec_t * left,__in const efx_mae_match_spec_t * right)136936d124c3SIvan Malov efx_mae_match_specs_equal(
137036d124c3SIvan Malov __in const efx_mae_match_spec_t *left,
137136d124c3SIvan Malov __in const efx_mae_match_spec_t *right)
137236d124c3SIvan Malov {
137336d124c3SIvan Malov return ((memcmp(left, right, sizeof (*left)) == 0) ? B_TRUE : B_FALSE);
137436d124c3SIvan Malov }
137536d124c3SIvan Malov
137634285fd0SIvan Malov #define EFX_MASK_BIT_IS_SET(_mask, _mask_page_nbits, _bit) \
137734285fd0SIvan Malov ((_mask)[(_bit) / (_mask_page_nbits)] & \
137834285fd0SIvan Malov (1ULL << ((_bit) & ((_mask_page_nbits) - 1))))
137934285fd0SIvan Malov
1380c87fa315SIvan Malov static boolean_t
efx_mask_is_prefix(__in size_t mask_nbytes,__in_bcount (mask_nbytes)const uint8_t * maskp)138134285fd0SIvan Malov efx_mask_is_prefix(
138234285fd0SIvan Malov __in size_t mask_nbytes,
138334285fd0SIvan Malov __in_bcount(mask_nbytes) const uint8_t *maskp)
138434285fd0SIvan Malov {
138534285fd0SIvan Malov boolean_t prev_bit_is_set = B_TRUE;
138634285fd0SIvan Malov unsigned int i;
138734285fd0SIvan Malov
138834285fd0SIvan Malov for (i = 0; i < 8 * mask_nbytes; ++i) {
138934285fd0SIvan Malov boolean_t bit_is_set = EFX_MASK_BIT_IS_SET(maskp, 8, i);
139034285fd0SIvan Malov
139134285fd0SIvan Malov if (!prev_bit_is_set && bit_is_set)
139234285fd0SIvan Malov return B_FALSE;
139334285fd0SIvan Malov
139434285fd0SIvan Malov prev_bit_is_set = bit_is_set;
139534285fd0SIvan Malov }
139634285fd0SIvan Malov
139734285fd0SIvan Malov return B_TRUE;
139834285fd0SIvan Malov }
139934285fd0SIvan Malov
1400c87fa315SIvan Malov static boolean_t
efx_mask_is_all_ones(__in size_t mask_nbytes,__in_bcount (mask_nbytes)const uint8_t * maskp)140134285fd0SIvan Malov efx_mask_is_all_ones(
140234285fd0SIvan Malov __in size_t mask_nbytes,
140334285fd0SIvan Malov __in_bcount(mask_nbytes) const uint8_t *maskp)
140434285fd0SIvan Malov {
140534285fd0SIvan Malov unsigned int i;
140634285fd0SIvan Malov uint8_t t = ~0;
140734285fd0SIvan Malov
140834285fd0SIvan Malov for (i = 0; i < mask_nbytes; ++i)
140934285fd0SIvan Malov t &= maskp[i];
141034285fd0SIvan Malov
141134285fd0SIvan Malov return (t == (uint8_t)(~0));
141234285fd0SIvan Malov }
141334285fd0SIvan Malov
1414c87fa315SIvan Malov static boolean_t
efx_mask_is_all_zeros(__in size_t mask_nbytes,__in_bcount (mask_nbytes)const uint8_t * maskp)141534285fd0SIvan Malov efx_mask_is_all_zeros(
141634285fd0SIvan Malov __in size_t mask_nbytes,
141734285fd0SIvan Malov __in_bcount(mask_nbytes) const uint8_t *maskp)
141834285fd0SIvan Malov {
141934285fd0SIvan Malov unsigned int i;
142034285fd0SIvan Malov uint8_t t = 0;
142134285fd0SIvan Malov
142234285fd0SIvan Malov for (i = 0; i < mask_nbytes; ++i)
142334285fd0SIvan Malov t |= maskp[i];
142434285fd0SIvan Malov
142534285fd0SIvan Malov return (t == 0);
142634285fd0SIvan Malov }
142734285fd0SIvan Malov
142834285fd0SIvan Malov __checkReturn boolean_t
efx_mae_match_spec_is_valid(__in efx_nic_t * enp,__in const efx_mae_match_spec_t * spec)142934285fd0SIvan Malov efx_mae_match_spec_is_valid(
143034285fd0SIvan Malov __in efx_nic_t *enp,
143134285fd0SIvan Malov __in const efx_mae_match_spec_t *spec)
143234285fd0SIvan Malov {
143334285fd0SIvan Malov efx_mae_t *maep = enp->en_maep;
143434285fd0SIvan Malov unsigned int field_ncaps = maep->em_max_nfields;
143534285fd0SIvan Malov const efx_mae_field_cap_t *field_caps;
143634285fd0SIvan Malov const efx_mae_mv_desc_t *desc_setp;
143734285fd0SIvan Malov unsigned int desc_set_nentries;
143837907899SIvan Malov const efx_mae_mv_bit_desc_t *bit_desc_setp;
143937907899SIvan Malov unsigned int bit_desc_set_nentries;
144034285fd0SIvan Malov boolean_t is_valid = B_TRUE;
144134285fd0SIvan Malov efx_mae_field_id_t field_id;
144234285fd0SIvan Malov const uint8_t *mvp;
144334285fd0SIvan Malov
144434285fd0SIvan Malov switch (spec->emms_type) {
1445ed15d7f8SIvan Malov case EFX_MAE_RULE_OUTER:
1446ed15d7f8SIvan Malov field_caps = maep->em_outer_rule_field_caps;
1447ed15d7f8SIvan Malov desc_setp = __efx_mae_outer_rule_mv_desc_set;
1448ed15d7f8SIvan Malov desc_set_nentries =
1449ed15d7f8SIvan Malov EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_desc_set);
145037907899SIvan Malov bit_desc_setp = __efx_mae_outer_rule_mv_bit_desc_set;
145137907899SIvan Malov bit_desc_set_nentries =
145237907899SIvan Malov EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_bit_desc_set);
1453ed15d7f8SIvan Malov mvp = spec->emms_mask_value_pairs.outer;
1454ed15d7f8SIvan Malov break;
145534285fd0SIvan Malov case EFX_MAE_RULE_ACTION:
145634285fd0SIvan Malov field_caps = maep->em_action_rule_field_caps;
145734285fd0SIvan Malov desc_setp = __efx_mae_action_rule_mv_desc_set;
145834285fd0SIvan Malov desc_set_nentries =
145934285fd0SIvan Malov EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_desc_set);
146037907899SIvan Malov bit_desc_setp = __efx_mae_action_rule_mv_bit_desc_set;
146137907899SIvan Malov bit_desc_set_nentries =
146237907899SIvan Malov EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_bit_desc_set);
146334285fd0SIvan Malov mvp = spec->emms_mask_value_pairs.action;
146434285fd0SIvan Malov break;
146534285fd0SIvan Malov default:
146634285fd0SIvan Malov return (B_FALSE);
146734285fd0SIvan Malov }
146834285fd0SIvan Malov
146934285fd0SIvan Malov if (field_caps == NULL)
147034285fd0SIvan Malov return (B_FALSE);
147134285fd0SIvan Malov
1472a0f0b03cSIvan Malov for (field_id = 0; (unsigned int)field_id < desc_set_nentries;
1473a0f0b03cSIvan Malov ++field_id) {
147434285fd0SIvan Malov const efx_mae_mv_desc_t *descp = &desc_setp[field_id];
147534285fd0SIvan Malov efx_mae_field_cap_id_t field_cap_id = descp->emmd_field_cap_id;
1476429ed2f9SIvan Malov const uint8_t *alt_m_buf = mvp + descp->emmd_alt_mask_offset;
147734285fd0SIvan Malov const uint8_t *m_buf = mvp + descp->emmd_mask_offset;
1478429ed2f9SIvan Malov size_t alt_m_size = descp->emmd_alt_mask_size;
147934285fd0SIvan Malov size_t m_size = descp->emmd_mask_size;
148034285fd0SIvan Malov
148134285fd0SIvan Malov if (m_size == 0)
148234285fd0SIvan Malov continue; /* Skip array gap */
148334285fd0SIvan Malov
148440f94ce9SIvan Malov if ((unsigned int)field_cap_id >= field_ncaps) {
148540f94ce9SIvan Malov /*
148640f94ce9SIvan Malov * The FW has not reported capability status for
148740f94ce9SIvan Malov * this field. Make sure that its mask is zeroed.
148840f94ce9SIvan Malov */
148940f94ce9SIvan Malov is_valid = efx_mask_is_all_zeros(m_size, m_buf);
149040f94ce9SIvan Malov if (is_valid != B_FALSE)
149140f94ce9SIvan Malov continue;
149240f94ce9SIvan Malov else
149334285fd0SIvan Malov break;
149440f94ce9SIvan Malov }
149534285fd0SIvan Malov
149634285fd0SIvan Malov switch (field_caps[field_cap_id].emfc_support) {
149734285fd0SIvan Malov case MAE_FIELD_SUPPORTED_MATCH_MASK:
149834285fd0SIvan Malov is_valid = B_TRUE;
149934285fd0SIvan Malov break;
150034285fd0SIvan Malov case MAE_FIELD_SUPPORTED_MATCH_PREFIX:
150134285fd0SIvan Malov is_valid = efx_mask_is_prefix(m_size, m_buf);
150234285fd0SIvan Malov break;
150334285fd0SIvan Malov case MAE_FIELD_SUPPORTED_MATCH_OPTIONAL:
150434285fd0SIvan Malov is_valid = (efx_mask_is_all_ones(m_size, m_buf) ||
150534285fd0SIvan Malov efx_mask_is_all_zeros(m_size, m_buf));
150634285fd0SIvan Malov break;
150734285fd0SIvan Malov case MAE_FIELD_SUPPORTED_MATCH_ALWAYS:
150834285fd0SIvan Malov is_valid = efx_mask_is_all_ones(m_size, m_buf);
1509429ed2f9SIvan Malov
1510429ed2f9SIvan Malov if ((is_valid == B_FALSE) && (alt_m_size != 0)) {
1511429ed2f9SIvan Malov /*
1512429ed2f9SIvan Malov * This field has an alternative one. The FW
1513429ed2f9SIvan Malov * reports ALWAYS for both implying that one
1514429ed2f9SIvan Malov * of them is required to have all-ones mask.
1515429ed2f9SIvan Malov *
1516429ed2f9SIvan Malov * The primary field's mask is incorrect; go
1517429ed2f9SIvan Malov * on to check that of the alternative field.
1518429ed2f9SIvan Malov */
1519429ed2f9SIvan Malov is_valid = efx_mask_is_all_ones(alt_m_size,
1520429ed2f9SIvan Malov alt_m_buf);
1521429ed2f9SIvan Malov }
152234285fd0SIvan Malov break;
152334285fd0SIvan Malov case MAE_FIELD_SUPPORTED_MATCH_NEVER:
152434285fd0SIvan Malov case MAE_FIELD_UNSUPPORTED:
152534285fd0SIvan Malov default:
152634285fd0SIvan Malov is_valid = efx_mask_is_all_zeros(m_size, m_buf);
152734285fd0SIvan Malov break;
152834285fd0SIvan Malov }
152934285fd0SIvan Malov
153034285fd0SIvan Malov if (is_valid == B_FALSE)
153137907899SIvan Malov return (B_FALSE);
153237907899SIvan Malov }
153337907899SIvan Malov
153437907899SIvan Malov for (field_id = 0; (unsigned int)field_id < bit_desc_set_nentries;
153537907899SIvan Malov ++field_id) {
153637907899SIvan Malov const efx_mae_mv_bit_desc_t *bit_descp =
153737907899SIvan Malov &bit_desc_setp[field_id];
153837907899SIvan Malov unsigned int byte_idx =
153937907899SIvan Malov bit_descp->emmbd_mask_ofst +
154037907899SIvan Malov bit_descp->emmbd_mask_lbn / 8;
154137907899SIvan Malov unsigned int bit_idx =
154237907899SIvan Malov bit_descp->emmbd_mask_lbn % 8;
154337907899SIvan Malov efx_mae_field_cap_id_t bit_cap_id =
154437907899SIvan Malov bit_descp->emmbd_bit_cap_id;
154537907899SIvan Malov
154637907899SIvan Malov if (bit_descp->emmbd_entry_is_valid == B_FALSE)
154737907899SIvan Malov continue; /* Skip array gap */
154837907899SIvan Malov
154937907899SIvan Malov if ((unsigned int)bit_cap_id >= field_ncaps) {
155037907899SIvan Malov /* No capability for this bit = unsupported. */
155137907899SIvan Malov is_valid = ((mvp[byte_idx] & (1U << bit_idx)) == 0);
155237907899SIvan Malov if (is_valid == B_FALSE)
155337907899SIvan Malov break;
155437907899SIvan Malov else
155537907899SIvan Malov continue;
155637907899SIvan Malov }
155737907899SIvan Malov
155837907899SIvan Malov switch (field_caps[bit_cap_id].emfc_support) {
155937907899SIvan Malov case MAE_FIELD_SUPPORTED_MATCH_OPTIONAL:
156037907899SIvan Malov is_valid = B_TRUE;
156137907899SIvan Malov break;
156237907899SIvan Malov case MAE_FIELD_SUPPORTED_MATCH_ALWAYS:
156337907899SIvan Malov is_valid = ((mvp[byte_idx] & (1U << bit_idx)) != 0);
156437907899SIvan Malov break;
156537907899SIvan Malov case MAE_FIELD_SUPPORTED_MATCH_NEVER:
156637907899SIvan Malov case MAE_FIELD_UNSUPPORTED:
156737907899SIvan Malov default:
156837907899SIvan Malov is_valid = ((mvp[byte_idx] & (1U << bit_idx)) == 0);
156937907899SIvan Malov break;
157037907899SIvan Malov }
157137907899SIvan Malov
157237907899SIvan Malov if (is_valid == B_FALSE)
157334285fd0SIvan Malov break;
157434285fd0SIvan Malov }
157534285fd0SIvan Malov
157634285fd0SIvan Malov return (is_valid);
157734285fd0SIvan Malov }
157834285fd0SIvan Malov
1579bb71f7e0SIvan Malov __checkReturn efx_rc_t
efx_mae_action_set_spec_init(__in efx_nic_t * enp,__out efx_mae_actions_t ** specp)1580799889baSIvan Malov efx_mae_action_set_spec_init(
1581799889baSIvan Malov __in efx_nic_t *enp,
1582799889baSIvan Malov __out efx_mae_actions_t **specp)
1583799889baSIvan Malov {
1584c6e3e6c4SIvan Malov const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
1585799889baSIvan Malov efx_mae_actions_t *spec;
1586799889baSIvan Malov efx_rc_t rc;
1587799889baSIvan Malov
1588799889baSIvan Malov EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (*spec), spec);
1589799889baSIvan Malov if (spec == NULL) {
1590799889baSIvan Malov rc = ENOMEM;
1591799889baSIvan Malov goto fail1;
1592799889baSIvan Malov }
1593799889baSIvan Malov
1594cf1e1a8eSIvan Malov efx_mae_action_set_clear_fw_rsrc_ids(spec);
15953907defaSIvan Malov
1596c6e3e6c4SIvan Malov /*
1597c6e3e6c4SIvan Malov * Helpers which populate v2 actions must reject them when v2 is not
1598c6e3e6c4SIvan Malov * supported. As they have no EFX NIC argument, save v2 status here.
1599c6e3e6c4SIvan Malov */
1600c6e3e6c4SIvan Malov spec->ema_v2_is_supported = encp->enc_mae_aset_v2_supported;
1601c6e3e6c4SIvan Malov
1602799889baSIvan Malov *specp = spec;
1603799889baSIvan Malov
1604799889baSIvan Malov return (0);
1605799889baSIvan Malov
1606799889baSIvan Malov fail1:
1607799889baSIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
1608799889baSIvan Malov return (rc);
1609799889baSIvan Malov }
1610799889baSIvan Malov
1611799889baSIvan Malov void
efx_mae_action_set_spec_fini(__in efx_nic_t * enp,__in efx_mae_actions_t * spec)1612799889baSIvan Malov efx_mae_action_set_spec_fini(
1613799889baSIvan Malov __in efx_nic_t *enp,
1614799889baSIvan Malov __in efx_mae_actions_t *spec)
1615799889baSIvan Malov {
1616799889baSIvan Malov EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec), spec);
1617799889baSIvan Malov }
1618799889baSIvan Malov
161980019097SIvan Malov static __checkReturn efx_rc_t
efx_mae_action_set_no_op(__in efx_mae_actions_t * spec,__in size_t arg_size,__in_bcount (arg_size)const uint8_t * arg)1620ecf2cb28SIvan Malov efx_mae_action_set_no_op(
16210f6b017bSIvan Malov __in efx_mae_actions_t *spec,
16220f6b017bSIvan Malov __in size_t arg_size,
16230f6b017bSIvan Malov __in_bcount(arg_size) const uint8_t *arg)
16240f6b017bSIvan Malov {
16250f6b017bSIvan Malov efx_rc_t rc;
16260f6b017bSIvan Malov
16270f6b017bSIvan Malov _NOTE(ARGUNUSED(spec))
16280f6b017bSIvan Malov
16290f6b017bSIvan Malov if (arg_size != 0) {
16300f6b017bSIvan Malov rc = EINVAL;
16310f6b017bSIvan Malov goto fail1;
16320f6b017bSIvan Malov }
16330f6b017bSIvan Malov
16340f6b017bSIvan Malov if (arg != NULL) {
16350f6b017bSIvan Malov rc = EINVAL;
16360f6b017bSIvan Malov goto fail2;
16370f6b017bSIvan Malov }
16380f6b017bSIvan Malov
16390f6b017bSIvan Malov /* This action does not have any arguments, so do nothing here. */
16400f6b017bSIvan Malov
16410f6b017bSIvan Malov return (0);
16420f6b017bSIvan Malov
16430f6b017bSIvan Malov fail2:
16440f6b017bSIvan Malov EFSYS_PROBE(fail2);
16450f6b017bSIvan Malov fail1:
16460f6b017bSIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
16470f6b017bSIvan Malov return (rc);
16480f6b017bSIvan Malov }
16490f6b017bSIvan Malov
16500f6b017bSIvan Malov static __checkReturn efx_rc_t
efx_mae_action_set_add_vlan_pop(__in efx_mae_actions_t * spec,__in size_t arg_size,__in_bcount (arg_size)const uint8_t * arg)1651616b03e0SIvan Malov efx_mae_action_set_add_vlan_pop(
1652616b03e0SIvan Malov __in efx_mae_actions_t *spec,
1653616b03e0SIvan Malov __in size_t arg_size,
1654616b03e0SIvan Malov __in_bcount(arg_size) const uint8_t *arg)
1655616b03e0SIvan Malov {
1656616b03e0SIvan Malov efx_rc_t rc;
1657616b03e0SIvan Malov
1658616b03e0SIvan Malov if (arg_size != 0) {
1659616b03e0SIvan Malov rc = EINVAL;
1660616b03e0SIvan Malov goto fail1;
1661616b03e0SIvan Malov }
1662616b03e0SIvan Malov
1663616b03e0SIvan Malov if (arg != NULL) {
1664616b03e0SIvan Malov rc = EINVAL;
1665616b03e0SIvan Malov goto fail2;
1666616b03e0SIvan Malov }
1667616b03e0SIvan Malov
1668616b03e0SIvan Malov if (spec->ema_n_vlan_tags_to_pop == EFX_MAE_VLAN_POP_MAX_NTAGS) {
1669616b03e0SIvan Malov rc = ENOTSUP;
1670616b03e0SIvan Malov goto fail3;
1671616b03e0SIvan Malov }
1672616b03e0SIvan Malov
1673616b03e0SIvan Malov ++spec->ema_n_vlan_tags_to_pop;
1674616b03e0SIvan Malov
1675616b03e0SIvan Malov return (0);
1676616b03e0SIvan Malov
1677616b03e0SIvan Malov fail3:
1678616b03e0SIvan Malov EFSYS_PROBE(fail3);
1679616b03e0SIvan Malov fail2:
1680616b03e0SIvan Malov EFSYS_PROBE(fail2);
1681616b03e0SIvan Malov fail1:
1682616b03e0SIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
1683616b03e0SIvan Malov return (rc);
1684616b03e0SIvan Malov }
1685616b03e0SIvan Malov
1686616b03e0SIvan Malov static __checkReturn efx_rc_t
efx_mae_action_set_add_vlan_push(__in efx_mae_actions_t * spec,__in size_t arg_size,__in_bcount (arg_size)const uint8_t * arg)168712cd7909SIvan Malov efx_mae_action_set_add_vlan_push(
168812cd7909SIvan Malov __in efx_mae_actions_t *spec,
168912cd7909SIvan Malov __in size_t arg_size,
169012cd7909SIvan Malov __in_bcount(arg_size) const uint8_t *arg)
169112cd7909SIvan Malov {
169212cd7909SIvan Malov unsigned int n_tags = spec->ema_n_vlan_tags_to_push;
169312cd7909SIvan Malov efx_rc_t rc;
169412cd7909SIvan Malov
169512cd7909SIvan Malov if (arg_size != sizeof (*spec->ema_vlan_push_descs)) {
169612cd7909SIvan Malov rc = EINVAL;
169712cd7909SIvan Malov goto fail1;
169812cd7909SIvan Malov }
169912cd7909SIvan Malov
170012cd7909SIvan Malov if (arg == NULL) {
170112cd7909SIvan Malov rc = EINVAL;
170212cd7909SIvan Malov goto fail2;
170312cd7909SIvan Malov }
170412cd7909SIvan Malov
170512cd7909SIvan Malov if (n_tags == EFX_MAE_VLAN_PUSH_MAX_NTAGS) {
170612cd7909SIvan Malov rc = ENOTSUP;
170712cd7909SIvan Malov goto fail3;
170812cd7909SIvan Malov }
170912cd7909SIvan Malov
171012cd7909SIvan Malov memcpy(&spec->ema_vlan_push_descs[n_tags], arg, arg_size);
171112cd7909SIvan Malov ++(spec->ema_n_vlan_tags_to_push);
171212cd7909SIvan Malov
171312cd7909SIvan Malov return (0);
171412cd7909SIvan Malov
171512cd7909SIvan Malov fail3:
171612cd7909SIvan Malov EFSYS_PROBE(fail3);
171712cd7909SIvan Malov fail2:
171812cd7909SIvan Malov EFSYS_PROBE(fail2);
171912cd7909SIvan Malov fail1:
172012cd7909SIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
172112cd7909SIvan Malov return (rc);
172212cd7909SIvan Malov }
172312cd7909SIvan Malov
172412cd7909SIvan Malov static __checkReturn efx_rc_t
efx_mae_action_set_add_count(__in efx_mae_actions_t * spec,__in size_t arg_size,__in_bcount (arg_size)const uint8_t * arg)1725238306cfSIgor Romanov efx_mae_action_set_add_count(
1726238306cfSIgor Romanov __in efx_mae_actions_t *spec,
1727238306cfSIgor Romanov __in size_t arg_size,
1728238306cfSIgor Romanov __in_bcount(arg_size) const uint8_t *arg)
1729238306cfSIgor Romanov {
1730238306cfSIgor Romanov efx_rc_t rc;
1731238306cfSIgor Romanov
1732238306cfSIgor Romanov EFX_STATIC_ASSERT(EFX_MAE_RSRC_ID_INVALID ==
1733238306cfSIgor Romanov MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_NULL);
1734238306cfSIgor Romanov
1735238306cfSIgor Romanov /*
1736238306cfSIgor Romanov * Preparing an action set spec to update a counter requires
1737238306cfSIgor Romanov * two steps: first add this action to the action spec, and then
1738238306cfSIgor Romanov * add the counter ID to the spec. This allows validity checking
1739238306cfSIgor Romanov * and resource allocation to be done separately.
1740e8745b54SIvan Malov *
1741e8745b54SIvan Malov * In order to fill in the counter ID, the caller is supposed to invoke
1742e8745b54SIvan Malov * efx_mae_action_set_fill_in_counter_id(). If they do not do that,
1743e8745b54SIvan Malov * efx_mae_action_set_alloc() invocation will throw an error.
1744e8745b54SIvan Malov *
1745e8745b54SIvan Malov * For now, no arguments are supposed to be handled.
1746238306cfSIgor Romanov */
1747238306cfSIgor Romanov
1748238306cfSIgor Romanov if (arg_size != 0) {
1749238306cfSIgor Romanov rc = EINVAL;
1750238306cfSIgor Romanov goto fail1;
1751238306cfSIgor Romanov }
1752238306cfSIgor Romanov
1753238306cfSIgor Romanov if (arg != NULL) {
1754238306cfSIgor Romanov rc = EINVAL;
1755238306cfSIgor Romanov goto fail2;
1756238306cfSIgor Romanov }
1757238306cfSIgor Romanov
1758238306cfSIgor Romanov ++(spec->ema_n_count_actions);
1759238306cfSIgor Romanov
1760238306cfSIgor Romanov return (0);
1761238306cfSIgor Romanov
1762238306cfSIgor Romanov fail2:
1763238306cfSIgor Romanov EFSYS_PROBE(fail2);
1764238306cfSIgor Romanov fail1:
1765238306cfSIgor Romanov EFSYS_PROBE1(fail1, efx_rc_t, rc);
1766238306cfSIgor Romanov return (rc);
1767238306cfSIgor Romanov }
1768238306cfSIgor Romanov
1769238306cfSIgor Romanov static __checkReturn efx_rc_t
efx_mae_action_set_add_mark(__in efx_mae_actions_t * spec,__in size_t arg_size,__in_bcount (arg_size)const uint8_t * arg)177083352289SIvan Malov efx_mae_action_set_add_mark(
177183352289SIvan Malov __in efx_mae_actions_t *spec,
177283352289SIvan Malov __in size_t arg_size,
177383352289SIvan Malov __in_bcount(arg_size) const uint8_t *arg)
177483352289SIvan Malov {
177583352289SIvan Malov efx_rc_t rc;
177683352289SIvan Malov
177783352289SIvan Malov if (arg_size != sizeof (spec->ema_mark_value)) {
177883352289SIvan Malov rc = EINVAL;
177983352289SIvan Malov goto fail1;
178083352289SIvan Malov }
178183352289SIvan Malov
178283352289SIvan Malov if (arg == NULL) {
178383352289SIvan Malov rc = EINVAL;
178483352289SIvan Malov goto fail2;
178583352289SIvan Malov }
178683352289SIvan Malov
178783352289SIvan Malov memcpy(&spec->ema_mark_value, arg, arg_size);
178883352289SIvan Malov
178983352289SIvan Malov return (0);
179083352289SIvan Malov
179183352289SIvan Malov fail2:
179283352289SIvan Malov EFSYS_PROBE(fail2);
179383352289SIvan Malov fail1:
179483352289SIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
179583352289SIvan Malov return (rc);
179683352289SIvan Malov }
179783352289SIvan Malov
179883352289SIvan Malov static __checkReturn efx_rc_t
efx_mae_action_set_add_deliver(__in efx_mae_actions_t * spec,__in size_t arg_size,__in_bcount (arg_size)const uint8_t * arg)179980019097SIvan Malov efx_mae_action_set_add_deliver(
180080019097SIvan Malov __in efx_mae_actions_t *spec,
180180019097SIvan Malov __in size_t arg_size,
180280019097SIvan Malov __in_bcount(arg_size) const uint8_t *arg)
180380019097SIvan Malov {
180480019097SIvan Malov efx_rc_t rc;
180580019097SIvan Malov
180680019097SIvan Malov if (arg_size != sizeof (spec->ema_deliver_mport)) {
180780019097SIvan Malov rc = EINVAL;
180880019097SIvan Malov goto fail1;
180980019097SIvan Malov }
181080019097SIvan Malov
181180019097SIvan Malov if (arg == NULL) {
181280019097SIvan Malov rc = EINVAL;
181380019097SIvan Malov goto fail2;
181480019097SIvan Malov }
181580019097SIvan Malov
181680019097SIvan Malov memcpy(&spec->ema_deliver_mport, arg, arg_size);
181780019097SIvan Malov
181880019097SIvan Malov return (0);
181980019097SIvan Malov
182080019097SIvan Malov fail2:
182180019097SIvan Malov EFSYS_PROBE(fail2);
182280019097SIvan Malov fail1:
182380019097SIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
182480019097SIvan Malov return (rc);
182580019097SIvan Malov }
182680019097SIvan Malov
182780019097SIvan Malov typedef struct efx_mae_action_desc_s {
182880019097SIvan Malov /* Action specific handler */
182980019097SIvan Malov efx_rc_t (*emad_add)(efx_mae_actions_t *,
183080019097SIvan Malov size_t, const uint8_t *);
183180019097SIvan Malov } efx_mae_action_desc_t;
183280019097SIvan Malov
183380019097SIvan Malov static const efx_mae_action_desc_t efx_mae_actions[EFX_MAE_NACTIONS] = {
18340f6b017bSIvan Malov [EFX_MAE_ACTION_DECAP] = {
1835ecf2cb28SIvan Malov .emad_add = efx_mae_action_set_no_op
18360f6b017bSIvan Malov },
1837616b03e0SIvan Malov [EFX_MAE_ACTION_VLAN_POP] = {
1838616b03e0SIvan Malov .emad_add = efx_mae_action_set_add_vlan_pop
1839616b03e0SIvan Malov },
184092bafeffSIvan Malov [EFX_MAE_ACTION_SET_DST_MAC] = {
184192bafeffSIvan Malov .emad_add = efx_mae_action_set_no_op
184292bafeffSIvan Malov },
184392bafeffSIvan Malov [EFX_MAE_ACTION_SET_SRC_MAC] = {
184492bafeffSIvan Malov .emad_add = efx_mae_action_set_no_op
184592bafeffSIvan Malov },
1846c6e3e6c4SIvan Malov [EFX_MAE_ACTION_DECR_IP_TTL] = {
1847c6e3e6c4SIvan Malov .emad_add = efx_mae_action_set_no_op
1848c6e3e6c4SIvan Malov },
18496cefdea5SIvan Malov [EFX_MAE_ACTION_NAT] = {
18506cefdea5SIvan Malov .emad_add = efx_mae_action_set_no_op
18516cefdea5SIvan Malov },
185212cd7909SIvan Malov [EFX_MAE_ACTION_VLAN_PUSH] = {
185312cd7909SIvan Malov .emad_add = efx_mae_action_set_add_vlan_push
185412cd7909SIvan Malov },
18553907defaSIvan Malov [EFX_MAE_ACTION_ENCAP] = {
1856ecf2cb28SIvan Malov .emad_add = efx_mae_action_set_no_op
18573907defaSIvan Malov },
1858238306cfSIgor Romanov [EFX_MAE_ACTION_COUNT] = {
1859238306cfSIgor Romanov .emad_add = efx_mae_action_set_add_count
1860238306cfSIgor Romanov },
186177da5888SIvan Malov [EFX_MAE_ACTION_FLAG] = {
1862ecf2cb28SIvan Malov .emad_add = efx_mae_action_set_no_op
186377da5888SIvan Malov },
186483352289SIvan Malov [EFX_MAE_ACTION_MARK] = {
186583352289SIvan Malov .emad_add = efx_mae_action_set_add_mark
186683352289SIvan Malov },
186780019097SIvan Malov [EFX_MAE_ACTION_DELIVER] = {
186880019097SIvan Malov .emad_add = efx_mae_action_set_add_deliver
186980019097SIvan Malov }
187080019097SIvan Malov };
187180019097SIvan Malov
187280019097SIvan Malov static const uint32_t efx_mae_action_ordered_map =
18730f6b017bSIvan Malov (1U << EFX_MAE_ACTION_DECAP) |
1874616b03e0SIvan Malov (1U << EFX_MAE_ACTION_VLAN_POP) |
187592bafeffSIvan Malov (1U << EFX_MAE_ACTION_SET_DST_MAC) |
187692bafeffSIvan Malov (1U << EFX_MAE_ACTION_SET_SRC_MAC) |
1877c6e3e6c4SIvan Malov (1U << EFX_MAE_ACTION_DECR_IP_TTL) |
18786cefdea5SIvan Malov (1U << EFX_MAE_ACTION_NAT) |
187912cd7909SIvan Malov (1U << EFX_MAE_ACTION_VLAN_PUSH) |
1880238306cfSIgor Romanov /*
1881238306cfSIgor Romanov * HW will conduct action COUNT after
1882238306cfSIgor Romanov * the matching packet has been modified by
1883238306cfSIgor Romanov * length-affecting actions except for ENCAP.
1884238306cfSIgor Romanov */
1885238306cfSIgor Romanov (1U << EFX_MAE_ACTION_COUNT) |
18863907defaSIvan Malov (1U << EFX_MAE_ACTION_ENCAP) |
188777da5888SIvan Malov (1U << EFX_MAE_ACTION_FLAG) |
188883352289SIvan Malov (1U << EFX_MAE_ACTION_MARK) |
188980019097SIvan Malov (1U << EFX_MAE_ACTION_DELIVER);
189080019097SIvan Malov
189177da5888SIvan Malov /*
189277da5888SIvan Malov * These actions must not be added after DELIVER, but
189377da5888SIvan Malov * they can have any place among the rest of
189477da5888SIvan Malov * strictly ordered actions.
189577da5888SIvan Malov */
189677da5888SIvan Malov static const uint32_t efx_mae_action_nonstrict_map =
189708b3a170SIvan Malov (1U << EFX_MAE_ACTION_COUNT) |
189883352289SIvan Malov (1U << EFX_MAE_ACTION_FLAG) |
189983352289SIvan Malov (1U << EFX_MAE_ACTION_MARK);
190077da5888SIvan Malov
1901616b03e0SIvan Malov static const uint32_t efx_mae_action_repeat_map =
190212cd7909SIvan Malov (1U << EFX_MAE_ACTION_VLAN_POP) |
1903238306cfSIgor Romanov (1U << EFX_MAE_ACTION_VLAN_PUSH) |
1904238306cfSIgor Romanov (1U << EFX_MAE_ACTION_COUNT);
190580019097SIvan Malov
190680019097SIvan Malov /*
190780019097SIvan Malov * Add an action to an action set.
190880019097SIvan Malov *
190980019097SIvan Malov * This has to be invoked in the desired action order.
191080019097SIvan Malov * An out-of-order action request will be turned down.
191180019097SIvan Malov */
191280019097SIvan Malov static __checkReturn efx_rc_t
efx_mae_action_set_spec_populate(__in efx_mae_actions_t * spec,__in efx_mae_action_t type,__in size_t arg_size,__in_bcount (arg_size)const uint8_t * arg)191380019097SIvan Malov efx_mae_action_set_spec_populate(
191480019097SIvan Malov __in efx_mae_actions_t *spec,
191580019097SIvan Malov __in efx_mae_action_t type,
191680019097SIvan Malov __in size_t arg_size,
191780019097SIvan Malov __in_bcount(arg_size) const uint8_t *arg)
191880019097SIvan Malov {
191980019097SIvan Malov uint32_t action_mask;
192080019097SIvan Malov efx_rc_t rc;
192180019097SIvan Malov
192280019097SIvan Malov EFX_STATIC_ASSERT(EFX_MAE_NACTIONS <=
192380019097SIvan Malov (sizeof (efx_mae_action_ordered_map) * 8));
192480019097SIvan Malov EFX_STATIC_ASSERT(EFX_MAE_NACTIONS <=
192580019097SIvan Malov (sizeof (efx_mae_action_repeat_map) * 8));
192680019097SIvan Malov
192780019097SIvan Malov EFX_STATIC_ASSERT(EFX_MAE_ACTION_DELIVER + 1 == EFX_MAE_NACTIONS);
192883352289SIvan Malov EFX_STATIC_ASSERT(EFX_MAE_ACTION_FLAG + 1 == EFX_MAE_ACTION_MARK);
192983352289SIvan Malov EFX_STATIC_ASSERT(EFX_MAE_ACTION_MARK + 1 == EFX_MAE_ACTION_DELIVER);
193080019097SIvan Malov
193180019097SIvan Malov if (type >= EFX_ARRAY_SIZE(efx_mae_actions)) {
193280019097SIvan Malov rc = EINVAL;
193380019097SIvan Malov goto fail1;
193480019097SIvan Malov }
193580019097SIvan Malov
193680019097SIvan Malov action_mask = (1U << type);
193780019097SIvan Malov
193880019097SIvan Malov if ((spec->ema_actions & action_mask) != 0) {
193980019097SIvan Malov /* The action set already contains this action. */
194080019097SIvan Malov if ((efx_mae_action_repeat_map & action_mask) == 0) {
194180019097SIvan Malov /* Cannot add another non-repeatable action. */
194280019097SIvan Malov rc = ENOTSUP;
194380019097SIvan Malov goto fail2;
194480019097SIvan Malov }
194580019097SIvan Malov }
194680019097SIvan Malov
194780019097SIvan Malov if ((efx_mae_action_ordered_map & action_mask) != 0) {
194877da5888SIvan Malov uint32_t strict_ordered_map =
194977da5888SIvan Malov efx_mae_action_ordered_map & ~efx_mae_action_nonstrict_map;
195080019097SIvan Malov uint32_t later_actions_mask =
195177da5888SIvan Malov strict_ordered_map & ~(action_mask | (action_mask - 1));
195280019097SIvan Malov
195380019097SIvan Malov if ((spec->ema_actions & later_actions_mask) != 0) {
195480019097SIvan Malov /* Cannot add an action after later ordered actions. */
195580019097SIvan Malov rc = ENOTSUP;
195680019097SIvan Malov goto fail3;
195780019097SIvan Malov }
195880019097SIvan Malov }
195980019097SIvan Malov
196080019097SIvan Malov if (efx_mae_actions[type].emad_add != NULL) {
196180019097SIvan Malov rc = efx_mae_actions[type].emad_add(spec, arg_size, arg);
196280019097SIvan Malov if (rc != 0)
196380019097SIvan Malov goto fail4;
196480019097SIvan Malov }
196580019097SIvan Malov
196680019097SIvan Malov spec->ema_actions |= action_mask;
196780019097SIvan Malov
196880019097SIvan Malov return (0);
196980019097SIvan Malov
197080019097SIvan Malov fail4:
197180019097SIvan Malov EFSYS_PROBE(fail4);
197280019097SIvan Malov fail3:
197380019097SIvan Malov EFSYS_PROBE(fail3);
197480019097SIvan Malov fail2:
197580019097SIvan Malov EFSYS_PROBE(fail2);
197680019097SIvan Malov fail1:
197780019097SIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
197880019097SIvan Malov return (rc);
197980019097SIvan Malov }
198080019097SIvan Malov
198180019097SIvan Malov __checkReturn efx_rc_t
efx_mae_action_set_populate_decap(__in efx_mae_actions_t * spec)19820f6b017bSIvan Malov efx_mae_action_set_populate_decap(
19830f6b017bSIvan Malov __in efx_mae_actions_t *spec)
19840f6b017bSIvan Malov {
19850f6b017bSIvan Malov return (efx_mae_action_set_spec_populate(spec,
19860f6b017bSIvan Malov EFX_MAE_ACTION_DECAP, 0, NULL));
19870f6b017bSIvan Malov }
19880f6b017bSIvan Malov
19890f6b017bSIvan Malov __checkReturn efx_rc_t
efx_mae_action_set_populate_vlan_pop(__in efx_mae_actions_t * spec)1990616b03e0SIvan Malov efx_mae_action_set_populate_vlan_pop(
1991616b03e0SIvan Malov __in efx_mae_actions_t *spec)
1992616b03e0SIvan Malov {
1993616b03e0SIvan Malov return (efx_mae_action_set_spec_populate(spec,
1994616b03e0SIvan Malov EFX_MAE_ACTION_VLAN_POP, 0, NULL));
1995616b03e0SIvan Malov }
1996616b03e0SIvan Malov
1997616b03e0SIvan Malov __checkReturn efx_rc_t
efx_mae_action_set_populate_set_dst_mac(__in efx_mae_actions_t * spec)199892bafeffSIvan Malov efx_mae_action_set_populate_set_dst_mac(
199992bafeffSIvan Malov __in efx_mae_actions_t *spec)
200092bafeffSIvan Malov {
200192bafeffSIvan Malov efx_rc_t rc;
200292bafeffSIvan Malov
200392bafeffSIvan Malov if (spec->ema_v2_is_supported == B_FALSE) {
200492bafeffSIvan Malov rc = ENOTSUP;
200592bafeffSIvan Malov goto fail1;
200692bafeffSIvan Malov }
200792bafeffSIvan Malov
200892bafeffSIvan Malov return (efx_mae_action_set_spec_populate(spec,
200992bafeffSIvan Malov EFX_MAE_ACTION_SET_DST_MAC, 0, NULL));
201092bafeffSIvan Malov
201192bafeffSIvan Malov fail1:
201292bafeffSIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
201392bafeffSIvan Malov return (rc);
201492bafeffSIvan Malov }
201592bafeffSIvan Malov
201692bafeffSIvan Malov __checkReturn efx_rc_t
efx_mae_action_set_populate_set_src_mac(__in efx_mae_actions_t * spec)201792bafeffSIvan Malov efx_mae_action_set_populate_set_src_mac(
201892bafeffSIvan Malov __in efx_mae_actions_t *spec)
201992bafeffSIvan Malov {
202092bafeffSIvan Malov efx_rc_t rc;
202192bafeffSIvan Malov
202292bafeffSIvan Malov if (spec->ema_v2_is_supported == B_FALSE) {
202392bafeffSIvan Malov rc = ENOTSUP;
202492bafeffSIvan Malov goto fail1;
202592bafeffSIvan Malov }
202692bafeffSIvan Malov
202792bafeffSIvan Malov return (efx_mae_action_set_spec_populate(spec,
202892bafeffSIvan Malov EFX_MAE_ACTION_SET_SRC_MAC, 0, NULL));
202992bafeffSIvan Malov
203092bafeffSIvan Malov fail1:
203192bafeffSIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
203292bafeffSIvan Malov return (rc);
203392bafeffSIvan Malov }
203492bafeffSIvan Malov
203592bafeffSIvan Malov __checkReturn efx_rc_t
efx_mae_action_set_populate_decr_ip_ttl(__in efx_mae_actions_t * spec)2036c6e3e6c4SIvan Malov efx_mae_action_set_populate_decr_ip_ttl(
2037c6e3e6c4SIvan Malov __in efx_mae_actions_t *spec)
2038c6e3e6c4SIvan Malov {
2039c6e3e6c4SIvan Malov efx_rc_t rc;
2040c6e3e6c4SIvan Malov
2041c6e3e6c4SIvan Malov if (spec->ema_v2_is_supported == B_FALSE) {
2042c6e3e6c4SIvan Malov rc = ENOTSUP;
2043c6e3e6c4SIvan Malov goto fail1;
2044c6e3e6c4SIvan Malov }
2045c6e3e6c4SIvan Malov
2046c6e3e6c4SIvan Malov return (efx_mae_action_set_spec_populate(spec,
2047c6e3e6c4SIvan Malov EFX_MAE_ACTION_DECR_IP_TTL, 0, NULL));
2048c6e3e6c4SIvan Malov
2049c6e3e6c4SIvan Malov fail1:
2050c6e3e6c4SIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
2051c6e3e6c4SIvan Malov return (rc);
2052c6e3e6c4SIvan Malov }
2053c6e3e6c4SIvan Malov
2054c6e3e6c4SIvan Malov __checkReturn efx_rc_t
efx_mae_action_set_populate_nat(__in efx_mae_actions_t * spec)20556cefdea5SIvan Malov efx_mae_action_set_populate_nat(
20566cefdea5SIvan Malov __in efx_mae_actions_t *spec)
20576cefdea5SIvan Malov {
20586cefdea5SIvan Malov return (efx_mae_action_set_spec_populate(spec,
20596cefdea5SIvan Malov EFX_MAE_ACTION_NAT, 0, NULL));
20606cefdea5SIvan Malov }
20616cefdea5SIvan Malov
20626cefdea5SIvan Malov __checkReturn efx_rc_t
efx_mae_action_set_populate_vlan_push(__in efx_mae_actions_t * spec,__in uint16_t tpid_be,__in uint16_t tci_be)206312cd7909SIvan Malov efx_mae_action_set_populate_vlan_push(
206412cd7909SIvan Malov __in efx_mae_actions_t *spec,
206512cd7909SIvan Malov __in uint16_t tpid_be,
206612cd7909SIvan Malov __in uint16_t tci_be)
206712cd7909SIvan Malov {
206812cd7909SIvan Malov efx_mae_action_vlan_push_t action;
206912cd7909SIvan Malov const uint8_t *arg = (const uint8_t *)&action;
207012cd7909SIvan Malov
207112cd7909SIvan Malov action.emavp_tpid_be = tpid_be;
207212cd7909SIvan Malov action.emavp_tci_be = tci_be;
207312cd7909SIvan Malov
207412cd7909SIvan Malov return (efx_mae_action_set_spec_populate(spec,
207512cd7909SIvan Malov EFX_MAE_ACTION_VLAN_PUSH, sizeof (action), arg));
207612cd7909SIvan Malov }
207712cd7909SIvan Malov
207812cd7909SIvan Malov __checkReturn efx_rc_t
efx_mae_action_set_populate_encap(__in efx_mae_actions_t * spec)20793907defaSIvan Malov efx_mae_action_set_populate_encap(
20803907defaSIvan Malov __in efx_mae_actions_t *spec)
20813907defaSIvan Malov {
20823907defaSIvan Malov /*
20833907defaSIvan Malov * There is no argument to pass encap. header ID, thus, one does not
20843907defaSIvan Malov * need to allocate an encap. header while parsing application input.
20853907defaSIvan Malov * This is useful since building an action set may be done simply to
20863907defaSIvan Malov * validate a rule, whilst resource allocation usually consumes time.
20873907defaSIvan Malov */
20883907defaSIvan Malov return (efx_mae_action_set_spec_populate(spec,
20893907defaSIvan Malov EFX_MAE_ACTION_ENCAP, 0, NULL));
20903907defaSIvan Malov }
20913907defaSIvan Malov
20923907defaSIvan Malov __checkReturn efx_rc_t
efx_mae_action_set_populate_count(__in efx_mae_actions_t * spec)2093238306cfSIgor Romanov efx_mae_action_set_populate_count(
2094238306cfSIgor Romanov __in efx_mae_actions_t *spec)
2095238306cfSIgor Romanov {
2096238306cfSIgor Romanov /*
2097238306cfSIgor Romanov * There is no argument to pass counter ID, thus, one does not
2098238306cfSIgor Romanov * need to allocate a counter while parsing application input.
2099238306cfSIgor Romanov * This is useful since building an action set may be done simply to
2100238306cfSIgor Romanov * validate a rule, whilst resource allocation usually consumes time.
2101238306cfSIgor Romanov */
2102238306cfSIgor Romanov return (efx_mae_action_set_spec_populate(spec,
2103238306cfSIgor Romanov EFX_MAE_ACTION_COUNT, 0, NULL));
2104238306cfSIgor Romanov }
2105238306cfSIgor Romanov
2106238306cfSIgor Romanov __checkReturn efx_rc_t
efx_mae_action_set_populate_flag(__in efx_mae_actions_t * spec)210777da5888SIvan Malov efx_mae_action_set_populate_flag(
210877da5888SIvan Malov __in efx_mae_actions_t *spec)
210977da5888SIvan Malov {
211077da5888SIvan Malov return (efx_mae_action_set_spec_populate(spec,
211177da5888SIvan Malov EFX_MAE_ACTION_FLAG, 0, NULL));
211277da5888SIvan Malov }
211377da5888SIvan Malov
211477da5888SIvan Malov __checkReturn efx_rc_t
efx_mae_action_set_populate_mark(__in efx_mae_actions_t * spec,__in uint32_t mark_value)211583352289SIvan Malov efx_mae_action_set_populate_mark(
211683352289SIvan Malov __in efx_mae_actions_t *spec,
211783352289SIvan Malov __in uint32_t mark_value)
211883352289SIvan Malov {
211983352289SIvan Malov const uint8_t *arg = (const uint8_t *)&mark_value;
212083352289SIvan Malov
212183352289SIvan Malov return (efx_mae_action_set_spec_populate(spec,
212283352289SIvan Malov EFX_MAE_ACTION_MARK, sizeof (mark_value), arg));
212383352289SIvan Malov }
212483352289SIvan Malov
212513d3f0d2SIvan Malov void
efx_mae_action_set_populate_mark_reset(__in efx_mae_actions_t * spec)212613d3f0d2SIvan Malov efx_mae_action_set_populate_mark_reset(
212713d3f0d2SIvan Malov __in efx_mae_actions_t *spec)
212813d3f0d2SIvan Malov {
212913d3f0d2SIvan Malov uint32_t action_mask = (1U << EFX_MAE_ACTION_MARK);
213013d3f0d2SIvan Malov
213113d3f0d2SIvan Malov if ((spec->ema_actions & action_mask) == 0) {
213213d3f0d2SIvan Malov spec->ema_actions |= action_mask;
213313d3f0d2SIvan Malov spec->ema_mark_value = 0;
213413d3f0d2SIvan Malov }
213513d3f0d2SIvan Malov }
213613d3f0d2SIvan Malov
213783352289SIvan Malov __checkReturn efx_rc_t
efx_mae_action_set_populate_deliver(__in efx_mae_actions_t * spec,__in const efx_mport_sel_t * mportp)213880019097SIvan Malov efx_mae_action_set_populate_deliver(
213980019097SIvan Malov __in efx_mae_actions_t *spec,
214080019097SIvan Malov __in const efx_mport_sel_t *mportp)
214180019097SIvan Malov {
214280019097SIvan Malov const uint8_t *arg;
214380019097SIvan Malov efx_rc_t rc;
214480019097SIvan Malov
214580019097SIvan Malov if (mportp == NULL) {
214680019097SIvan Malov rc = EINVAL;
214780019097SIvan Malov goto fail1;
214880019097SIvan Malov }
214980019097SIvan Malov
215080019097SIvan Malov arg = (const uint8_t *)&mportp->sel;
215180019097SIvan Malov
215280019097SIvan Malov return (efx_mae_action_set_spec_populate(spec,
215380019097SIvan Malov EFX_MAE_ACTION_DELIVER, sizeof (mportp->sel), arg));
215480019097SIvan Malov
215580019097SIvan Malov fail1:
215680019097SIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
215780019097SIvan Malov return (rc);
215880019097SIvan Malov }
215980019097SIvan Malov
2160bb024542SIvan Malov __checkReturn efx_rc_t
efx_mae_action_set_populate_drop(__in efx_mae_actions_t * spec)2161bb024542SIvan Malov efx_mae_action_set_populate_drop(
2162bb024542SIvan Malov __in efx_mae_actions_t *spec)
2163bb024542SIvan Malov {
2164bb024542SIvan Malov efx_mport_sel_t mport;
2165bb024542SIvan Malov const uint8_t *arg;
2166bb024542SIvan Malov efx_dword_t dword;
2167bb024542SIvan Malov
2168bb024542SIvan Malov EFX_POPULATE_DWORD_1(dword,
2169bb024542SIvan Malov MAE_MPORT_SELECTOR_FLAT, MAE_MPORT_SELECTOR_NULL);
2170bb024542SIvan Malov
2171f0d58c4bSIvan Malov /*
2172f0d58c4bSIvan Malov * The constructed DWORD is little-endian,
2173f0d58c4bSIvan Malov * but the resulting value is meant to be
2174f0d58c4bSIvan Malov * passed to MCDIs, where it will undergo
2175f0d58c4bSIvan Malov * host-order to little endian conversion.
2176f0d58c4bSIvan Malov */
2177f0d58c4bSIvan Malov mport.sel = EFX_DWORD_FIELD(dword, EFX_DWORD_0);
2178bb024542SIvan Malov
2179bb024542SIvan Malov arg = (const uint8_t *)&mport.sel;
2180bb024542SIvan Malov
2181bb024542SIvan Malov return (efx_mae_action_set_spec_populate(spec,
2182bb024542SIvan Malov EFX_MAE_ACTION_DELIVER, sizeof (mport.sel), arg));
2183bb024542SIvan Malov }
2184bb024542SIvan Malov
2185799889baSIvan Malov __checkReturn boolean_t
efx_mae_action_set_specs_equal(__in const efx_mae_actions_t * left,__in const efx_mae_actions_t * right)2186799889baSIvan Malov efx_mae_action_set_specs_equal(
2187799889baSIvan Malov __in const efx_mae_actions_t *left,
2188799889baSIvan Malov __in const efx_mae_actions_t *right)
2189799889baSIvan Malov {
21903907defaSIvan Malov size_t cmp_size = EFX_FIELD_OFFSET(efx_mae_actions_t, ema_rsrc);
21913907defaSIvan Malov
21923907defaSIvan Malov /*
21933907defaSIvan Malov * An action set specification consists of two parts. The first part
21943907defaSIvan Malov * indicates what actions are included in the action set, as well as
21953907defaSIvan Malov * extra quantitative values (in example, the number of VLAN tags to
21963907defaSIvan Malov * push). The second part comprises resource IDs used by the actions.
21973907defaSIvan Malov *
21983907defaSIvan Malov * A resource, in example, a counter, is allocated from the hardware
21993907defaSIvan Malov * by the client, and it's the client who is responsible for keeping
22003907defaSIvan Malov * track of allocated resources and comparing resource IDs if needed.
22013907defaSIvan Malov *
22023907defaSIvan Malov * In this API, don't compare resource IDs in the two specifications.
22033907defaSIvan Malov */
22043907defaSIvan Malov
22053907defaSIvan Malov return ((memcmp(left, right, cmp_size) == 0) ? B_TRUE : B_FALSE);
2206799889baSIvan Malov }
2207799889baSIvan Malov
2208799889baSIvan Malov __checkReturn efx_rc_t
efx_mae_match_specs_class_cmp(__in efx_nic_t * enp,__in const efx_mae_match_spec_t * left,__in const efx_mae_match_spec_t * right,__out boolean_t * have_same_classp)2209bb71f7e0SIvan Malov efx_mae_match_specs_class_cmp(
2210bb71f7e0SIvan Malov __in efx_nic_t *enp,
2211bb71f7e0SIvan Malov __in const efx_mae_match_spec_t *left,
2212bb71f7e0SIvan Malov __in const efx_mae_match_spec_t *right,
2213bb71f7e0SIvan Malov __out boolean_t *have_same_classp)
2214bb71f7e0SIvan Malov {
2215bb71f7e0SIvan Malov efx_mae_t *maep = enp->en_maep;
2216bb71f7e0SIvan Malov unsigned int field_ncaps = maep->em_max_nfields;
2217bb71f7e0SIvan Malov const efx_mae_field_cap_t *field_caps;
2218bb71f7e0SIvan Malov const efx_mae_mv_desc_t *desc_setp;
2219bb71f7e0SIvan Malov unsigned int desc_set_nentries;
222037907899SIvan Malov const efx_mae_mv_bit_desc_t *bit_desc_setp;
222137907899SIvan Malov unsigned int bit_desc_set_nentries;
2222bb71f7e0SIvan Malov boolean_t have_same_class = B_TRUE;
2223bb71f7e0SIvan Malov efx_mae_field_id_t field_id;
2224bb71f7e0SIvan Malov const uint8_t *mvpl;
2225bb71f7e0SIvan Malov const uint8_t *mvpr;
2226bb71f7e0SIvan Malov efx_rc_t rc;
2227bb71f7e0SIvan Malov
2228bb71f7e0SIvan Malov switch (left->emms_type) {
2229ed15d7f8SIvan Malov case EFX_MAE_RULE_OUTER:
2230ed15d7f8SIvan Malov field_caps = maep->em_outer_rule_field_caps;
2231ed15d7f8SIvan Malov desc_setp = __efx_mae_outer_rule_mv_desc_set;
2232ed15d7f8SIvan Malov desc_set_nentries =
2233ed15d7f8SIvan Malov EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_desc_set);
223437907899SIvan Malov bit_desc_setp = __efx_mae_outer_rule_mv_bit_desc_set;
223537907899SIvan Malov bit_desc_set_nentries =
223637907899SIvan Malov EFX_ARRAY_SIZE(__efx_mae_outer_rule_mv_bit_desc_set);
2237ed15d7f8SIvan Malov mvpl = left->emms_mask_value_pairs.outer;
2238ed15d7f8SIvan Malov mvpr = right->emms_mask_value_pairs.outer;
2239ed15d7f8SIvan Malov break;
2240bb71f7e0SIvan Malov case EFX_MAE_RULE_ACTION:
2241bb71f7e0SIvan Malov field_caps = maep->em_action_rule_field_caps;
2242bb71f7e0SIvan Malov desc_setp = __efx_mae_action_rule_mv_desc_set;
2243bb71f7e0SIvan Malov desc_set_nentries =
2244bb71f7e0SIvan Malov EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_desc_set);
224537907899SIvan Malov bit_desc_setp = __efx_mae_action_rule_mv_bit_desc_set;
224637907899SIvan Malov bit_desc_set_nentries =
224737907899SIvan Malov EFX_ARRAY_SIZE(__efx_mae_action_rule_mv_bit_desc_set);
2248bb71f7e0SIvan Malov mvpl = left->emms_mask_value_pairs.action;
2249bb71f7e0SIvan Malov mvpr = right->emms_mask_value_pairs.action;
2250bb71f7e0SIvan Malov break;
2251bb71f7e0SIvan Malov default:
2252bb71f7e0SIvan Malov rc = ENOTSUP;
2253bb71f7e0SIvan Malov goto fail1;
2254bb71f7e0SIvan Malov }
2255bb71f7e0SIvan Malov
2256bb71f7e0SIvan Malov if (field_caps == NULL) {
2257bb71f7e0SIvan Malov rc = EAGAIN;
2258bb71f7e0SIvan Malov goto fail2;
2259bb71f7e0SIvan Malov }
2260bb71f7e0SIvan Malov
2261bb71f7e0SIvan Malov if (left->emms_type != right->emms_type ||
2262bb71f7e0SIvan Malov left->emms_prio != right->emms_prio) {
2263bb71f7e0SIvan Malov /*
2264bb71f7e0SIvan Malov * Rules of different types can never map to the same class.
2265bb71f7e0SIvan Malov *
2266bb71f7e0SIvan Malov * The FW can support some set of match criteria for one
2267bb71f7e0SIvan Malov * priority and not support the very same set for
2268bb71f7e0SIvan Malov * another priority. Thus, two rules which have
2269bb71f7e0SIvan Malov * different priorities can never map to
2270bb71f7e0SIvan Malov * the same class.
2271bb71f7e0SIvan Malov */
2272bb71f7e0SIvan Malov *have_same_classp = B_FALSE;
2273bb71f7e0SIvan Malov return (0);
2274bb71f7e0SIvan Malov }
2275bb71f7e0SIvan Malov
2276a0f0b03cSIvan Malov for (field_id = 0; (unsigned int)field_id < desc_set_nentries;
2277a0f0b03cSIvan Malov ++field_id) {
2278bb71f7e0SIvan Malov const efx_mae_mv_desc_t *descp = &desc_setp[field_id];
2279bb71f7e0SIvan Malov efx_mae_field_cap_id_t field_cap_id = descp->emmd_field_cap_id;
2280bb71f7e0SIvan Malov const uint8_t *lmaskp = mvpl + descp->emmd_mask_offset;
2281bb71f7e0SIvan Malov const uint8_t *rmaskp = mvpr + descp->emmd_mask_offset;
2282bb71f7e0SIvan Malov size_t mask_size = descp->emmd_mask_size;
228376631541SIvan Malov const uint8_t *lvalp = mvpl + descp->emmd_value_offset;
228476631541SIvan Malov const uint8_t *rvalp = mvpr + descp->emmd_value_offset;
228576631541SIvan Malov size_t value_size = descp->emmd_value_size;
2286bb71f7e0SIvan Malov
228776631541SIvan Malov if (mask_size == 0)
228876631541SIvan Malov continue; /* Skip array gap */
228976631541SIvan Malov
229076631541SIvan Malov if ((unsigned int)field_cap_id >= field_ncaps) {
229176631541SIvan Malov /*
229276631541SIvan Malov * The FW has not reported capability status for this
229376631541SIvan Malov * field. It's unknown whether any difference between
229476631541SIvan Malov * the two masks / values affects the class. The only
229576631541SIvan Malov * case when the class must be the same is when these
229676631541SIvan Malov * mask-value pairs match. Otherwise, report mismatch.
229776631541SIvan Malov */
229876631541SIvan Malov if ((memcmp(lmaskp, rmaskp, mask_size) == 0) &&
229976631541SIvan Malov (memcmp(lvalp, rvalp, value_size) == 0))
230076631541SIvan Malov continue;
230176631541SIvan Malov else
230276631541SIvan Malov break;
230376631541SIvan Malov }
230476631541SIvan Malov
230576631541SIvan Malov if (field_caps[field_cap_id].emfc_mask_affects_class) {
2306bb71f7e0SIvan Malov if (memcmp(lmaskp, rmaskp, mask_size) != 0) {
2307bb71f7e0SIvan Malov have_same_class = B_FALSE;
2308bb71f7e0SIvan Malov break;
2309bb71f7e0SIvan Malov }
2310bb71f7e0SIvan Malov }
2311bb71f7e0SIvan Malov
2312bb71f7e0SIvan Malov if (field_caps[field_cap_id].emfc_match_affects_class) {
2313bb71f7e0SIvan Malov if (memcmp(lvalp, rvalp, value_size) != 0) {
2314bb71f7e0SIvan Malov have_same_class = B_FALSE;
2315bb71f7e0SIvan Malov break;
2316bb71f7e0SIvan Malov }
2317bb71f7e0SIvan Malov }
2318bb71f7e0SIvan Malov }
2319bb71f7e0SIvan Malov
232037907899SIvan Malov if (have_same_class == B_FALSE)
232137907899SIvan Malov goto done;
232237907899SIvan Malov
232337907899SIvan Malov for (field_id = 0; (unsigned int)field_id < bit_desc_set_nentries;
232437907899SIvan Malov ++field_id) {
232537907899SIvan Malov const efx_mae_mv_bit_desc_t *bit_descp =
232637907899SIvan Malov &bit_desc_setp[field_id];
232737907899SIvan Malov efx_mae_field_cap_id_t bit_cap_id =
232837907899SIvan Malov bit_descp->emmbd_bit_cap_id;
232937907899SIvan Malov unsigned int byte_idx;
233037907899SIvan Malov unsigned int bit_idx;
233137907899SIvan Malov
233237907899SIvan Malov if (bit_descp->emmbd_entry_is_valid == B_FALSE)
233337907899SIvan Malov continue; /* Skip array gap */
233437907899SIvan Malov
233537907899SIvan Malov if ((unsigned int)bit_cap_id >= field_ncaps)
233637907899SIvan Malov break;
233737907899SIvan Malov
233837907899SIvan Malov byte_idx =
233937907899SIvan Malov bit_descp->emmbd_mask_ofst +
234037907899SIvan Malov bit_descp->emmbd_mask_lbn / 8;
234137907899SIvan Malov bit_idx =
234237907899SIvan Malov bit_descp->emmbd_mask_lbn % 8;
234337907899SIvan Malov
234437907899SIvan Malov if (field_caps[bit_cap_id].emfc_mask_affects_class &&
234537907899SIvan Malov (mvpl[byte_idx] & (1U << bit_idx)) !=
234637907899SIvan Malov (mvpr[byte_idx] & (1U << bit_idx))) {
234737907899SIvan Malov have_same_class = B_FALSE;
234837907899SIvan Malov break;
234937907899SIvan Malov }
235037907899SIvan Malov
235137907899SIvan Malov byte_idx =
235237907899SIvan Malov bit_descp->emmbd_value_ofst +
235337907899SIvan Malov bit_descp->emmbd_value_lbn / 8;
235437907899SIvan Malov bit_idx =
235537907899SIvan Malov bit_descp->emmbd_value_lbn % 8;
235637907899SIvan Malov
235737907899SIvan Malov if (field_caps[bit_cap_id].emfc_match_affects_class &&
235837907899SIvan Malov (mvpl[byte_idx] & (1U << bit_idx)) !=
235937907899SIvan Malov (mvpr[byte_idx] & (1U << bit_idx))) {
236037907899SIvan Malov have_same_class = B_FALSE;
236137907899SIvan Malov break;
236237907899SIvan Malov }
236337907899SIvan Malov }
236437907899SIvan Malov
236537907899SIvan Malov done:
2366bb71f7e0SIvan Malov *have_same_classp = have_same_class;
2367bb71f7e0SIvan Malov
2368bb71f7e0SIvan Malov return (0);
2369bb71f7e0SIvan Malov
2370bb71f7e0SIvan Malov fail2:
2371bb71f7e0SIvan Malov EFSYS_PROBE(fail2);
2372bb71f7e0SIvan Malov fail1:
2373bb71f7e0SIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
2374bb71f7e0SIvan Malov return (rc);
2375bb71f7e0SIvan Malov }
2376bb71f7e0SIvan Malov
2377e61baa82SIvan Malov __checkReturn efx_rc_t
efx_mae_outer_rule_recirc_id_set(__in efx_mae_match_spec_t * spec,__in uint8_t recirc_id)23785cf153e7SIvan Malov efx_mae_outer_rule_recirc_id_set(
23795cf153e7SIvan Malov __in efx_mae_match_spec_t *spec,
23805cf153e7SIvan Malov __in uint8_t recirc_id)
23815cf153e7SIvan Malov {
23825cf153e7SIvan Malov efx_rc_t rc;
23835cf153e7SIvan Malov
23845cf153e7SIvan Malov if (spec->emms_type != EFX_MAE_RULE_OUTER) {
23855cf153e7SIvan Malov rc = EINVAL;
23865cf153e7SIvan Malov goto fail1;
23875cf153e7SIvan Malov }
23885cf153e7SIvan Malov
23895cf153e7SIvan Malov spec->emms_outer_rule_recirc_id = recirc_id;
23905cf153e7SIvan Malov
23915cf153e7SIvan Malov return (0);
23925cf153e7SIvan Malov
23935cf153e7SIvan Malov fail1:
23945cf153e7SIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
23955cf153e7SIvan Malov return (rc);
23965cf153e7SIvan Malov }
23975cf153e7SIvan Malov
23985cf153e7SIvan Malov __checkReturn efx_rc_t
efx_mae_outer_rule_do_ct_set(__in efx_mae_match_spec_t * spec)2399be698f34SIvan Malov efx_mae_outer_rule_do_ct_set(
2400be698f34SIvan Malov __in efx_mae_match_spec_t *spec)
2401be698f34SIvan Malov {
2402be698f34SIvan Malov efx_rc_t rc;
2403be698f34SIvan Malov
2404be698f34SIvan Malov if (spec->emms_type != EFX_MAE_RULE_OUTER) {
2405be698f34SIvan Malov rc = EINVAL;
2406be698f34SIvan Malov goto fail1;
2407be698f34SIvan Malov }
2408be698f34SIvan Malov
2409be698f34SIvan Malov spec->emms_outer_rule_do_ct = B_TRUE;
2410be698f34SIvan Malov
2411be698f34SIvan Malov return (0);
2412be698f34SIvan Malov
2413be698f34SIvan Malov fail1:
2414be698f34SIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
2415be698f34SIvan Malov return (rc);
2416be698f34SIvan Malov }
2417be698f34SIvan Malov
2418be698f34SIvan Malov __checkReturn efx_rc_t
efx_mae_outer_rule_insert(__in efx_nic_t * enp,__in const efx_mae_match_spec_t * spec,__in efx_tunnel_protocol_t encap_type,__out efx_mae_rule_id_t * or_idp)24197a673e1aSIvan Malov efx_mae_outer_rule_insert(
24207a673e1aSIvan Malov __in efx_nic_t *enp,
24217a673e1aSIvan Malov __in const efx_mae_match_spec_t *spec,
24227a673e1aSIvan Malov __in efx_tunnel_protocol_t encap_type,
24237a673e1aSIvan Malov __out efx_mae_rule_id_t *or_idp)
24247a673e1aSIvan Malov {
24257a673e1aSIvan Malov const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
24267a673e1aSIvan Malov efx_mcdi_req_t req;
24277a673e1aSIvan Malov EFX_MCDI_DECLARE_BUF(payload,
24287a673e1aSIvan Malov MC_CMD_MAE_OUTER_RULE_INSERT_IN_LENMAX_MCDI2,
24297a673e1aSIvan Malov MC_CMD_MAE_OUTER_RULE_INSERT_OUT_LEN);
24307a673e1aSIvan Malov uint32_t encap_type_mcdi;
24317a673e1aSIvan Malov efx_mae_rule_id_t or_id;
24327a673e1aSIvan Malov size_t offset;
2433be698f34SIvan Malov uint8_t do_ct;
24347a673e1aSIvan Malov efx_rc_t rc;
24357a673e1aSIvan Malov
24367a673e1aSIvan Malov EFX_STATIC_ASSERT(sizeof (or_idp->id) ==
24377a673e1aSIvan Malov MC_CMD_MAE_OUTER_RULE_INSERT_OUT_OR_ID_LEN);
24387a673e1aSIvan Malov
24397a673e1aSIvan Malov EFX_STATIC_ASSERT(EFX_MAE_RSRC_ID_INVALID ==
24407a673e1aSIvan Malov MC_CMD_MAE_OUTER_RULE_INSERT_OUT_OUTER_RULE_ID_NULL);
24417a673e1aSIvan Malov
24427a673e1aSIvan Malov if (encp->enc_mae_supported == B_FALSE) {
24437a673e1aSIvan Malov rc = ENOTSUP;
24447a673e1aSIvan Malov goto fail1;
24457a673e1aSIvan Malov }
24467a673e1aSIvan Malov
24477a673e1aSIvan Malov if (spec->emms_type != EFX_MAE_RULE_OUTER) {
24487a673e1aSIvan Malov rc = EINVAL;
24497a673e1aSIvan Malov goto fail2;
24507a673e1aSIvan Malov }
24517a673e1aSIvan Malov
24527a673e1aSIvan Malov switch (encap_type) {
24537a673e1aSIvan Malov case EFX_TUNNEL_PROTOCOL_NONE:
24547a673e1aSIvan Malov encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_NONE;
24557a673e1aSIvan Malov break;
24567a673e1aSIvan Malov case EFX_TUNNEL_PROTOCOL_VXLAN:
24577a673e1aSIvan Malov encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_VXLAN;
24587a673e1aSIvan Malov break;
24597a673e1aSIvan Malov case EFX_TUNNEL_PROTOCOL_GENEVE:
24607a673e1aSIvan Malov encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_GENEVE;
24617a673e1aSIvan Malov break;
24627a673e1aSIvan Malov case EFX_TUNNEL_PROTOCOL_NVGRE:
24637a673e1aSIvan Malov encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_NVGRE;
24647a673e1aSIvan Malov break;
24657a673e1aSIvan Malov default:
24667a673e1aSIvan Malov rc = ENOTSUP;
24677a673e1aSIvan Malov goto fail3;
24687a673e1aSIvan Malov }
24697a673e1aSIvan Malov
24707a673e1aSIvan Malov req.emr_cmd = MC_CMD_MAE_OUTER_RULE_INSERT;
24717a673e1aSIvan Malov req.emr_in_buf = payload;
24727a673e1aSIvan Malov req.emr_in_length = MC_CMD_MAE_OUTER_RULE_INSERT_IN_LENMAX_MCDI2;
24737a673e1aSIvan Malov req.emr_out_buf = payload;
24747a673e1aSIvan Malov req.emr_out_length = MC_CMD_MAE_OUTER_RULE_INSERT_OUT_LEN;
24757a673e1aSIvan Malov
24767a673e1aSIvan Malov MCDI_IN_SET_DWORD(req,
24777a673e1aSIvan Malov MAE_OUTER_RULE_INSERT_IN_ENCAP_TYPE, encap_type_mcdi);
24787a673e1aSIvan Malov
24797a673e1aSIvan Malov MCDI_IN_SET_DWORD(req, MAE_OUTER_RULE_INSERT_IN_PRIO, spec->emms_prio);
24807a673e1aSIvan Malov
24817a673e1aSIvan Malov /*
24827a673e1aSIvan Malov * Mask-value pairs have been stored in the byte order needed for the
24837a673e1aSIvan Malov * MCDI request and are thus safe to be copied directly to the buffer.
24847a673e1aSIvan Malov * The library cares about byte order in efx_mae_match_spec_field_set().
24857a673e1aSIvan Malov */
24867a673e1aSIvan Malov EFX_STATIC_ASSERT(sizeof (spec->emms_mask_value_pairs.outer) >=
24877a673e1aSIvan Malov MAE_ENC_FIELD_PAIRS_LEN);
24887a673e1aSIvan Malov offset = MC_CMD_MAE_OUTER_RULE_INSERT_IN_FIELD_MATCH_CRITERIA_OFST;
24897a673e1aSIvan Malov memcpy(payload + offset, spec->emms_mask_value_pairs.outer,
24907a673e1aSIvan Malov MAE_ENC_FIELD_PAIRS_LEN);
24917a673e1aSIvan Malov
2492b4dd34c7SIvan Malov MCDI_IN_SET_DWORD_FIELD(req, MAE_OUTER_RULE_INSERT_IN_LOOKUP_CONTROL,
2493b4dd34c7SIvan Malov MAE_OUTER_RULE_INSERT_IN_RECIRC_ID,
24945cf153e7SIvan Malov spec->emms_outer_rule_recirc_id);
24955cf153e7SIvan Malov
2496be698f34SIvan Malov do_ct = (spec->emms_outer_rule_do_ct == B_FALSE) ? 0 : 1;
2497be698f34SIvan Malov
2498be698f34SIvan Malov MCDI_IN_SET_DWORD_FIELD(req, MAE_OUTER_RULE_INSERT_IN_LOOKUP_CONTROL,
2499be698f34SIvan Malov MAE_OUTER_RULE_INSERT_IN_DO_CT, do_ct);
2500be698f34SIvan Malov
25017a673e1aSIvan Malov efx_mcdi_execute(enp, &req);
25027a673e1aSIvan Malov
25037a673e1aSIvan Malov if (req.emr_rc != 0) {
25047a673e1aSIvan Malov rc = req.emr_rc;
25057a673e1aSIvan Malov goto fail4;
25067a673e1aSIvan Malov }
25077a673e1aSIvan Malov
25087a673e1aSIvan Malov if (req.emr_out_length_used < MC_CMD_MAE_OUTER_RULE_INSERT_OUT_LEN) {
25097a673e1aSIvan Malov rc = EMSGSIZE;
25107a673e1aSIvan Malov goto fail5;
25117a673e1aSIvan Malov }
25127a673e1aSIvan Malov
25137a673e1aSIvan Malov or_id.id = MCDI_OUT_DWORD(req, MAE_OUTER_RULE_INSERT_OUT_OR_ID);
25147a673e1aSIvan Malov if (or_id.id == EFX_MAE_RSRC_ID_INVALID) {
25157a673e1aSIvan Malov rc = ENOENT;
25167a673e1aSIvan Malov goto fail6;
25177a673e1aSIvan Malov }
25187a673e1aSIvan Malov
25197a673e1aSIvan Malov or_idp->id = or_id.id;
25207a673e1aSIvan Malov
25217a673e1aSIvan Malov return (0);
25227a673e1aSIvan Malov
25237a673e1aSIvan Malov fail6:
25247a673e1aSIvan Malov EFSYS_PROBE(fail6);
25257a673e1aSIvan Malov fail5:
25267a673e1aSIvan Malov EFSYS_PROBE(fail5);
25277a673e1aSIvan Malov fail4:
25287a673e1aSIvan Malov EFSYS_PROBE(fail4);
25297a673e1aSIvan Malov fail3:
25307a673e1aSIvan Malov EFSYS_PROBE(fail3);
25317a673e1aSIvan Malov fail2:
25327a673e1aSIvan Malov EFSYS_PROBE(fail2);
25337a673e1aSIvan Malov fail1:
25347a673e1aSIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
25357a673e1aSIvan Malov return (rc);
25367a673e1aSIvan Malov }
25377a673e1aSIvan Malov
25387a673e1aSIvan Malov __checkReturn efx_rc_t
efx_mae_outer_rule_remove(__in efx_nic_t * enp,__in const efx_mae_rule_id_t * or_idp)25397a673e1aSIvan Malov efx_mae_outer_rule_remove(
25407a673e1aSIvan Malov __in efx_nic_t *enp,
25417a673e1aSIvan Malov __in const efx_mae_rule_id_t *or_idp)
25427a673e1aSIvan Malov {
25437a673e1aSIvan Malov const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
25447a673e1aSIvan Malov efx_mcdi_req_t req;
25457a673e1aSIvan Malov EFX_MCDI_DECLARE_BUF(payload,
25467a673e1aSIvan Malov MC_CMD_MAE_OUTER_RULE_REMOVE_IN_LEN(1),
25477a673e1aSIvan Malov MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_LEN(1));
25487a673e1aSIvan Malov efx_rc_t rc;
25497a673e1aSIvan Malov
25507a673e1aSIvan Malov if (encp->enc_mae_supported == B_FALSE) {
25517a673e1aSIvan Malov rc = ENOTSUP;
25527a673e1aSIvan Malov goto fail1;
25537a673e1aSIvan Malov }
25547a673e1aSIvan Malov
25557a673e1aSIvan Malov req.emr_cmd = MC_CMD_MAE_OUTER_RULE_REMOVE;
25567a673e1aSIvan Malov req.emr_in_buf = payload;
25577a673e1aSIvan Malov req.emr_in_length = MC_CMD_MAE_OUTER_RULE_REMOVE_IN_LEN(1);
25587a673e1aSIvan Malov req.emr_out_buf = payload;
25597a673e1aSIvan Malov req.emr_out_length = MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_LEN(1);
25607a673e1aSIvan Malov
25617a673e1aSIvan Malov MCDI_IN_SET_DWORD(req, MAE_OUTER_RULE_REMOVE_IN_OR_ID, or_idp->id);
25627a673e1aSIvan Malov
25637a673e1aSIvan Malov efx_mcdi_execute(enp, &req);
25647a673e1aSIvan Malov
25657a673e1aSIvan Malov if (req.emr_rc != 0) {
25667a673e1aSIvan Malov rc = req.emr_rc;
25677a673e1aSIvan Malov goto fail2;
25687a673e1aSIvan Malov }
25697a673e1aSIvan Malov
2570e27950a0SAndy Moreton if (req.emr_out_length_used < MC_CMD_MAE_OUTER_RULE_REMOVE_OUT_LENMIN) {
2571e27950a0SAndy Moreton rc = EMSGSIZE;
2572e27950a0SAndy Moreton goto fail3;
2573e27950a0SAndy Moreton }
2574e27950a0SAndy Moreton
25757a673e1aSIvan Malov if (MCDI_OUT_DWORD(req, MAE_OUTER_RULE_REMOVE_OUT_REMOVED_OR_ID) !=
25767a673e1aSIvan Malov or_idp->id) {
25777a673e1aSIvan Malov /* Firmware failed to remove the outer rule. */
25787a673e1aSIvan Malov rc = EAGAIN;
2579e27950a0SAndy Moreton goto fail4;
25807a673e1aSIvan Malov }
25817a673e1aSIvan Malov
25827a673e1aSIvan Malov return (0);
25837a673e1aSIvan Malov
2584e27950a0SAndy Moreton fail4:
2585e27950a0SAndy Moreton EFSYS_PROBE(fail4);
25867a673e1aSIvan Malov fail3:
25877a673e1aSIvan Malov EFSYS_PROBE(fail3);
25887a673e1aSIvan Malov fail2:
25897a673e1aSIvan Malov EFSYS_PROBE(fail2);
25907a673e1aSIvan Malov fail1:
25917a673e1aSIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
25927a673e1aSIvan Malov return (rc);
25937a673e1aSIvan Malov }
25947a673e1aSIvan Malov
25957a673e1aSIvan Malov __checkReturn efx_rc_t
efx_mae_match_spec_outer_rule_id_set(__in efx_mae_match_spec_t * spec,__in const efx_mae_rule_id_t * or_idp)25967a673e1aSIvan Malov efx_mae_match_spec_outer_rule_id_set(
25977a673e1aSIvan Malov __in efx_mae_match_spec_t *spec,
25987a673e1aSIvan Malov __in const efx_mae_rule_id_t *or_idp)
25997a673e1aSIvan Malov {
26007a673e1aSIvan Malov uint32_t full_mask = UINT32_MAX;
26017a673e1aSIvan Malov efx_rc_t rc;
26027a673e1aSIvan Malov
26037a673e1aSIvan Malov if (spec->emms_type != EFX_MAE_RULE_ACTION) {
26047a673e1aSIvan Malov rc = EINVAL;
26057a673e1aSIvan Malov goto fail1;
26067a673e1aSIvan Malov }
26077a673e1aSIvan Malov
26087a673e1aSIvan Malov if (or_idp == NULL) {
26097a673e1aSIvan Malov rc = EINVAL;
26107a673e1aSIvan Malov goto fail2;
26117a673e1aSIvan Malov }
26127a673e1aSIvan Malov
26137a673e1aSIvan Malov rc = efx_mae_match_spec_field_set(spec, EFX_MAE_FIELD_OUTER_RULE_ID,
26147a673e1aSIvan Malov sizeof (or_idp->id), (const uint8_t *)&or_idp->id,
26157a673e1aSIvan Malov sizeof (full_mask), (const uint8_t *)&full_mask);
26167a673e1aSIvan Malov if (rc != 0)
26177a673e1aSIvan Malov goto fail3;
26187a673e1aSIvan Malov
26197a673e1aSIvan Malov return (0);
26207a673e1aSIvan Malov
26217a673e1aSIvan Malov fail3:
26227a673e1aSIvan Malov EFSYS_PROBE(fail3);
26237a673e1aSIvan Malov fail2:
26247a673e1aSIvan Malov EFSYS_PROBE(fail2);
26257a673e1aSIvan Malov fail1:
26267a673e1aSIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
26277a673e1aSIvan Malov return (rc);
26287a673e1aSIvan Malov }
26297a673e1aSIvan Malov
26307a673e1aSIvan Malov __checkReturn efx_rc_t
efx_mae_mac_addr_alloc(__in efx_nic_t * enp,__in uint8_t addr_bytes[EFX_MAC_ADDR_LEN],__out efx_mae_mac_id_t * mac_idp)263192bafeffSIvan Malov efx_mae_mac_addr_alloc(
263292bafeffSIvan Malov __in efx_nic_t *enp,
263392bafeffSIvan Malov __in uint8_t addr_bytes[EFX_MAC_ADDR_LEN],
263492bafeffSIvan Malov __out efx_mae_mac_id_t *mac_idp)
263592bafeffSIvan Malov {
263692bafeffSIvan Malov const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
263792bafeffSIvan Malov efx_mcdi_req_t req;
263892bafeffSIvan Malov EFX_MCDI_DECLARE_BUF(payload,
263992bafeffSIvan Malov MC_CMD_MAE_MAC_ADDR_ALLOC_IN_LEN,
264092bafeffSIvan Malov MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_LEN);
264192bafeffSIvan Malov efx_mae_mac_id_t mac_id;
264292bafeffSIvan Malov efx_rc_t rc;
264392bafeffSIvan Malov
264492bafeffSIvan Malov EFX_STATIC_ASSERT(sizeof (mac_idp->id) ==
264592bafeffSIvan Malov MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_LEN);
264692bafeffSIvan Malov
264792bafeffSIvan Malov EFX_STATIC_ASSERT(EFX_MAE_RSRC_ID_INVALID ==
264892bafeffSIvan Malov MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL);
264992bafeffSIvan Malov
265092bafeffSIvan Malov if (encp->enc_mae_supported == B_FALSE) {
265192bafeffSIvan Malov rc = ENOTSUP;
265292bafeffSIvan Malov goto fail1;
265392bafeffSIvan Malov }
265492bafeffSIvan Malov
265592bafeffSIvan Malov if (encp->enc_mae_aset_v2_supported == B_FALSE) {
265692bafeffSIvan Malov rc = ENOTSUP;
265792bafeffSIvan Malov goto fail2;
265892bafeffSIvan Malov }
265992bafeffSIvan Malov
266092bafeffSIvan Malov req.emr_cmd = MC_CMD_MAE_MAC_ADDR_ALLOC;
266192bafeffSIvan Malov req.emr_in_buf = payload;
266292bafeffSIvan Malov req.emr_in_length = MC_CMD_MAE_MAC_ADDR_ALLOC_IN_LEN;
266392bafeffSIvan Malov req.emr_out_buf = payload;
266492bafeffSIvan Malov req.emr_out_length = MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_LEN;
266592bafeffSIvan Malov
266692bafeffSIvan Malov memcpy(payload + MC_CMD_MAE_MAC_ADDR_ALLOC_IN_MAC_ADDR_OFST,
266792bafeffSIvan Malov addr_bytes, EFX_MAC_ADDR_LEN);
266892bafeffSIvan Malov
266992bafeffSIvan Malov efx_mcdi_execute(enp, &req);
267092bafeffSIvan Malov
267192bafeffSIvan Malov if (req.emr_rc != 0) {
267292bafeffSIvan Malov rc = req.emr_rc;
267392bafeffSIvan Malov goto fail3;
267492bafeffSIvan Malov }
267592bafeffSIvan Malov
267692bafeffSIvan Malov if (req.emr_out_length_used < MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_LEN) {
267792bafeffSIvan Malov rc = EMSGSIZE;
267892bafeffSIvan Malov goto fail4;
267992bafeffSIvan Malov }
268092bafeffSIvan Malov
268192bafeffSIvan Malov mac_id.id = MCDI_OUT_DWORD(req, MAE_MAC_ADDR_ALLOC_OUT_MAC_ID);
268292bafeffSIvan Malov if (mac_id.id == EFX_MAE_RSRC_ID_INVALID) {
268392bafeffSIvan Malov rc = ENOENT;
268492bafeffSIvan Malov goto fail5;
268592bafeffSIvan Malov }
268692bafeffSIvan Malov
268792bafeffSIvan Malov mac_idp->id = mac_id.id;
268892bafeffSIvan Malov
268992bafeffSIvan Malov return (0);
269092bafeffSIvan Malov
269192bafeffSIvan Malov fail5:
269292bafeffSIvan Malov EFSYS_PROBE(fail5);
269392bafeffSIvan Malov fail4:
269492bafeffSIvan Malov EFSYS_PROBE(fail4);
269592bafeffSIvan Malov fail3:
269692bafeffSIvan Malov EFSYS_PROBE(fail3);
269792bafeffSIvan Malov fail2:
269892bafeffSIvan Malov EFSYS_PROBE(fail2);
269992bafeffSIvan Malov fail1:
270092bafeffSIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
270192bafeffSIvan Malov return (rc);
270292bafeffSIvan Malov }
270392bafeffSIvan Malov
270492bafeffSIvan Malov __checkReturn efx_rc_t
efx_mae_mac_addr_free(__in efx_nic_t * enp,__in const efx_mae_mac_id_t * mac_idp)270592bafeffSIvan Malov efx_mae_mac_addr_free(
270692bafeffSIvan Malov __in efx_nic_t *enp,
270792bafeffSIvan Malov __in const efx_mae_mac_id_t *mac_idp)
270892bafeffSIvan Malov {
270992bafeffSIvan Malov const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
271092bafeffSIvan Malov efx_mcdi_req_t req;
271192bafeffSIvan Malov EFX_MCDI_DECLARE_BUF(payload,
271292bafeffSIvan Malov MC_CMD_MAE_MAC_ADDR_FREE_IN_LEN(1),
271392bafeffSIvan Malov MC_CMD_MAE_MAC_ADDR_FREE_OUT_LEN(1));
271492bafeffSIvan Malov efx_rc_t rc;
271592bafeffSIvan Malov
271692bafeffSIvan Malov if (encp->enc_mae_supported == B_FALSE) {
271792bafeffSIvan Malov rc = ENOTSUP;
271892bafeffSIvan Malov goto fail1;
271992bafeffSIvan Malov }
272092bafeffSIvan Malov
272192bafeffSIvan Malov if (encp->enc_mae_aset_v2_supported == B_FALSE) {
272292bafeffSIvan Malov rc = ENOTSUP;
272392bafeffSIvan Malov goto fail2;
272492bafeffSIvan Malov }
272592bafeffSIvan Malov
272692bafeffSIvan Malov req.emr_cmd = MC_CMD_MAE_MAC_ADDR_FREE;
272792bafeffSIvan Malov req.emr_in_buf = payload;
272892bafeffSIvan Malov req.emr_in_length = MC_CMD_MAE_MAC_ADDR_FREE_IN_LEN(1);
272992bafeffSIvan Malov req.emr_out_buf = payload;
273092bafeffSIvan Malov req.emr_out_length = MC_CMD_MAE_MAC_ADDR_FREE_OUT_LEN(1);
273192bafeffSIvan Malov
273292bafeffSIvan Malov MCDI_IN_SET_DWORD(req, MAE_MAC_ADDR_FREE_IN_MAC_ID, mac_idp->id);
273392bafeffSIvan Malov
273492bafeffSIvan Malov efx_mcdi_execute(enp, &req);
273592bafeffSIvan Malov
273692bafeffSIvan Malov if (req.emr_rc != 0) {
273792bafeffSIvan Malov rc = req.emr_rc;
273892bafeffSIvan Malov goto fail3;
273992bafeffSIvan Malov }
274092bafeffSIvan Malov
274192bafeffSIvan Malov if (req.emr_out_length_used < MC_CMD_MAE_MAC_ADDR_FREE_OUT_LEN(1)) {
274292bafeffSIvan Malov rc = EMSGSIZE;
274392bafeffSIvan Malov goto fail4;
274492bafeffSIvan Malov }
274592bafeffSIvan Malov
274692bafeffSIvan Malov if (MCDI_OUT_DWORD(req, MAE_MAC_ADDR_FREE_OUT_FREED_MAC_ID) !=
274792bafeffSIvan Malov mac_idp->id) {
274892bafeffSIvan Malov /* Firmware failed to remove the MAC address entry. */
274992bafeffSIvan Malov rc = EAGAIN;
275092bafeffSIvan Malov goto fail5;
275192bafeffSIvan Malov }
275292bafeffSIvan Malov
275392bafeffSIvan Malov return (0);
275492bafeffSIvan Malov
275592bafeffSIvan Malov fail5:
275692bafeffSIvan Malov EFSYS_PROBE(fail5);
275792bafeffSIvan Malov fail4:
275892bafeffSIvan Malov EFSYS_PROBE(fail4);
275992bafeffSIvan Malov fail3:
276092bafeffSIvan Malov EFSYS_PROBE(fail3);
276192bafeffSIvan Malov fail2:
276292bafeffSIvan Malov EFSYS_PROBE(fail2);
276392bafeffSIvan Malov fail1:
276492bafeffSIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
276592bafeffSIvan Malov return (rc);
276692bafeffSIvan Malov }
276792bafeffSIvan Malov
276892bafeffSIvan Malov __checkReturn efx_rc_t
efx_mae_action_set_fill_in_dst_mac_id(__in efx_mae_actions_t * spec,__in const efx_mae_mac_id_t * mac_idp)276992bafeffSIvan Malov efx_mae_action_set_fill_in_dst_mac_id(
277092bafeffSIvan Malov __in efx_mae_actions_t *spec,
277192bafeffSIvan Malov __in const efx_mae_mac_id_t *mac_idp)
277292bafeffSIvan Malov {
277392bafeffSIvan Malov efx_rc_t rc;
277492bafeffSIvan Malov
277592bafeffSIvan Malov if ((spec->ema_actions & (1U << EFX_MAE_ACTION_SET_DST_MAC)) == 0) {
277692bafeffSIvan Malov /*
277792bafeffSIvan Malov * The caller has not intended to have this action originally,
277892bafeffSIvan Malov * hence, they cannot indicate the MAC address entry ID.
277992bafeffSIvan Malov */
278092bafeffSIvan Malov rc = EINVAL;
278192bafeffSIvan Malov goto fail1;
278292bafeffSIvan Malov }
278392bafeffSIvan Malov
278492bafeffSIvan Malov if (spec->ema_rsrc.emar_dst_mac_id.id != EFX_MAE_RSRC_ID_INVALID) {
278592bafeffSIvan Malov /* An attempt to indicate the MAC address entry ID twice. */
278692bafeffSIvan Malov rc = EINVAL;
278792bafeffSIvan Malov goto fail2;
278892bafeffSIvan Malov }
278992bafeffSIvan Malov
279092bafeffSIvan Malov if (mac_idp->id == EFX_MAE_RSRC_ID_INVALID) {
279192bafeffSIvan Malov rc = EINVAL;
279292bafeffSIvan Malov goto fail3;
279392bafeffSIvan Malov }
279492bafeffSIvan Malov
279592bafeffSIvan Malov spec->ema_rsrc.emar_dst_mac_id.id = mac_idp->id;
279692bafeffSIvan Malov
279792bafeffSIvan Malov return (0);
279892bafeffSIvan Malov
279992bafeffSIvan Malov fail3:
280092bafeffSIvan Malov EFSYS_PROBE(fail3);
280192bafeffSIvan Malov fail2:
280292bafeffSIvan Malov EFSYS_PROBE(fail2);
280392bafeffSIvan Malov fail1:
280492bafeffSIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
280592bafeffSIvan Malov return (rc);
280692bafeffSIvan Malov }
280792bafeffSIvan Malov
280892bafeffSIvan Malov __checkReturn efx_rc_t
efx_mae_action_set_fill_in_src_mac_id(__in efx_mae_actions_t * spec,__in const efx_mae_mac_id_t * mac_idp)280992bafeffSIvan Malov efx_mae_action_set_fill_in_src_mac_id(
281092bafeffSIvan Malov __in efx_mae_actions_t *spec,
281192bafeffSIvan Malov __in const efx_mae_mac_id_t *mac_idp)
281292bafeffSIvan Malov {
281392bafeffSIvan Malov efx_rc_t rc;
281492bafeffSIvan Malov
281592bafeffSIvan Malov if ((spec->ema_actions & (1U << EFX_MAE_ACTION_SET_SRC_MAC)) == 0) {
281692bafeffSIvan Malov /*
281792bafeffSIvan Malov * The caller has not intended to have this action originally,
281892bafeffSIvan Malov * hence, they cannot indicate the MAC address entry ID.
281992bafeffSIvan Malov */
282092bafeffSIvan Malov rc = EINVAL;
282192bafeffSIvan Malov goto fail1;
282292bafeffSIvan Malov }
282392bafeffSIvan Malov
282492bafeffSIvan Malov if (spec->ema_rsrc.emar_src_mac_id.id != EFX_MAE_RSRC_ID_INVALID) {
282592bafeffSIvan Malov /* An attempt to indicate the MAC address entry ID twice. */
282692bafeffSIvan Malov rc = EINVAL;
282792bafeffSIvan Malov goto fail2;
282892bafeffSIvan Malov }
282992bafeffSIvan Malov
283092bafeffSIvan Malov if (mac_idp->id == EFX_MAE_RSRC_ID_INVALID) {
283192bafeffSIvan Malov rc = EINVAL;
283292bafeffSIvan Malov goto fail3;
283392bafeffSIvan Malov }
283492bafeffSIvan Malov
283592bafeffSIvan Malov spec->ema_rsrc.emar_src_mac_id.id = mac_idp->id;
283692bafeffSIvan Malov
283792bafeffSIvan Malov return (0);
283892bafeffSIvan Malov
283992bafeffSIvan Malov fail3:
284092bafeffSIvan Malov EFSYS_PROBE(fail3);
284192bafeffSIvan Malov fail2:
284292bafeffSIvan Malov EFSYS_PROBE(fail2);
284392bafeffSIvan Malov fail1:
284492bafeffSIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
284592bafeffSIvan Malov return (rc);
284692bafeffSIvan Malov }
284792bafeffSIvan Malov
284892bafeffSIvan Malov __checkReturn efx_rc_t
efx_mae_encap_header_alloc(__in efx_nic_t * enp,__in efx_tunnel_protocol_t encap_type,__in_bcount (header_size)uint8_t * header_data,__in size_t header_size,__out efx_mae_eh_id_t * eh_idp)284930833168SIvan Malov efx_mae_encap_header_alloc(
285030833168SIvan Malov __in efx_nic_t *enp,
285130833168SIvan Malov __in efx_tunnel_protocol_t encap_type,
285230833168SIvan Malov __in_bcount(header_size) uint8_t *header_data,
285330833168SIvan Malov __in size_t header_size,
285430833168SIvan Malov __out efx_mae_eh_id_t *eh_idp)
285530833168SIvan Malov {
285630833168SIvan Malov const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
285730833168SIvan Malov efx_mcdi_req_t req;
285830833168SIvan Malov EFX_MCDI_DECLARE_BUF(payload,
285930833168SIvan Malov MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_LENMAX_MCDI2,
286030833168SIvan Malov MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_LEN);
286130833168SIvan Malov uint32_t encap_type_mcdi;
286230833168SIvan Malov efx_mae_eh_id_t eh_id;
286330833168SIvan Malov efx_rc_t rc;
286430833168SIvan Malov
286530833168SIvan Malov EFX_STATIC_ASSERT(sizeof (eh_idp->id) ==
286630833168SIvan Malov MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID_LEN);
286730833168SIvan Malov
286830833168SIvan Malov EFX_STATIC_ASSERT(EFX_MAE_RSRC_ID_INVALID ==
286930833168SIvan Malov MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID_NULL);
287030833168SIvan Malov
287130833168SIvan Malov if (encp->enc_mae_supported == B_FALSE) {
287230833168SIvan Malov rc = ENOTSUP;
287330833168SIvan Malov goto fail1;
287430833168SIvan Malov }
287530833168SIvan Malov
287630833168SIvan Malov switch (encap_type) {
287730833168SIvan Malov case EFX_TUNNEL_PROTOCOL_NONE:
287830833168SIvan Malov encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_NONE;
287930833168SIvan Malov break;
288030833168SIvan Malov case EFX_TUNNEL_PROTOCOL_VXLAN:
288130833168SIvan Malov encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_VXLAN;
288230833168SIvan Malov break;
288330833168SIvan Malov case EFX_TUNNEL_PROTOCOL_GENEVE:
288430833168SIvan Malov encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_GENEVE;
288530833168SIvan Malov break;
288630833168SIvan Malov case EFX_TUNNEL_PROTOCOL_NVGRE:
288730833168SIvan Malov encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_NVGRE;
288830833168SIvan Malov break;
288930833168SIvan Malov default:
289030833168SIvan Malov rc = ENOTSUP;
289130833168SIvan Malov goto fail2;
289230833168SIvan Malov }
289330833168SIvan Malov
289430833168SIvan Malov if (header_size >
289530833168SIvan Malov MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_MAXNUM_MCDI2) {
289630833168SIvan Malov rc = EINVAL;
289730833168SIvan Malov goto fail3;
289830833168SIvan Malov }
289930833168SIvan Malov
290030833168SIvan Malov req.emr_cmd = MC_CMD_MAE_ENCAP_HEADER_ALLOC;
290130833168SIvan Malov req.emr_in_buf = payload;
290230833168SIvan Malov req.emr_in_length = MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_LEN(header_size);
290330833168SIvan Malov req.emr_out_buf = payload;
290430833168SIvan Malov req.emr_out_length = MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_LEN;
290530833168SIvan Malov
290630833168SIvan Malov MCDI_IN_SET_DWORD(req,
290730833168SIvan Malov MAE_ENCAP_HEADER_ALLOC_IN_ENCAP_TYPE, encap_type_mcdi);
290830833168SIvan Malov
290930833168SIvan Malov memcpy(payload + MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA_OFST,
291030833168SIvan Malov header_data, header_size);
291130833168SIvan Malov
291230833168SIvan Malov efx_mcdi_execute(enp, &req);
291330833168SIvan Malov
291430833168SIvan Malov if (req.emr_rc != 0) {
291530833168SIvan Malov rc = req.emr_rc;
291630833168SIvan Malov goto fail4;
291730833168SIvan Malov }
291830833168SIvan Malov
291930833168SIvan Malov if (req.emr_out_length_used < MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_LEN) {
292030833168SIvan Malov rc = EMSGSIZE;
292130833168SIvan Malov goto fail5;
292230833168SIvan Malov }
292330833168SIvan Malov
292430833168SIvan Malov eh_id.id = MCDI_OUT_DWORD(req,
292530833168SIvan Malov MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID);
292630833168SIvan Malov
292730833168SIvan Malov if (eh_id.id == EFX_MAE_RSRC_ID_INVALID) {
292830833168SIvan Malov rc = ENOENT;
292930833168SIvan Malov goto fail6;
293030833168SIvan Malov }
293130833168SIvan Malov
293230833168SIvan Malov eh_idp->id = eh_id.id;
293330833168SIvan Malov
293430833168SIvan Malov return (0);
293530833168SIvan Malov
293630833168SIvan Malov fail6:
293730833168SIvan Malov EFSYS_PROBE(fail6);
293830833168SIvan Malov fail5:
293930833168SIvan Malov EFSYS_PROBE(fail5);
294030833168SIvan Malov fail4:
294130833168SIvan Malov EFSYS_PROBE(fail4);
294230833168SIvan Malov fail3:
294330833168SIvan Malov EFSYS_PROBE(fail3);
294430833168SIvan Malov fail2:
294530833168SIvan Malov EFSYS_PROBE(fail2);
294630833168SIvan Malov fail1:
294730833168SIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
294830833168SIvan Malov return (rc);
294930833168SIvan Malov }
295030833168SIvan Malov
295130833168SIvan Malov __checkReturn efx_rc_t
efx_mae_encap_header_update(__in efx_nic_t * enp,__in efx_mae_eh_id_t * eh_idp,__in efx_tunnel_protocol_t encap_type,__in_bcount (header_size)const uint8_t * header_data,__in size_t header_size)29528763593fSIvan Malov efx_mae_encap_header_update(
29538763593fSIvan Malov __in efx_nic_t *enp,
29548763593fSIvan Malov __in efx_mae_eh_id_t *eh_idp,
29558763593fSIvan Malov __in efx_tunnel_protocol_t encap_type,
29568763593fSIvan Malov __in_bcount(header_size) const uint8_t *header_data,
29578763593fSIvan Malov __in size_t header_size)
29588763593fSIvan Malov {
29598763593fSIvan Malov const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
29608763593fSIvan Malov efx_mcdi_req_t req;
29618763593fSIvan Malov EFX_MCDI_DECLARE_BUF(payload,
29628763593fSIvan Malov MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_LENMAX_MCDI2,
29638763593fSIvan Malov MC_CMD_MAE_ENCAP_HEADER_UPDATE_OUT_LEN);
29648763593fSIvan Malov uint32_t encap_type_mcdi;
29658763593fSIvan Malov efx_rc_t rc;
29668763593fSIvan Malov
29678763593fSIvan Malov if (encp->enc_mae_supported == B_FALSE) {
29688763593fSIvan Malov rc = ENOTSUP;
29698763593fSIvan Malov goto fail1;
29708763593fSIvan Malov }
29718763593fSIvan Malov
29728763593fSIvan Malov switch (encap_type) {
29738763593fSIvan Malov case EFX_TUNNEL_PROTOCOL_NONE:
29748763593fSIvan Malov encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_NONE;
29758763593fSIvan Malov break;
29768763593fSIvan Malov case EFX_TUNNEL_PROTOCOL_VXLAN:
29778763593fSIvan Malov encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_VXLAN;
29788763593fSIvan Malov break;
29798763593fSIvan Malov case EFX_TUNNEL_PROTOCOL_GENEVE:
29808763593fSIvan Malov encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_GENEVE;
29818763593fSIvan Malov break;
29828763593fSIvan Malov case EFX_TUNNEL_PROTOCOL_NVGRE:
29838763593fSIvan Malov encap_type_mcdi = MAE_MCDI_ENCAP_TYPE_NVGRE;
29848763593fSIvan Malov break;
29858763593fSIvan Malov default:
29868763593fSIvan Malov rc = ENOTSUP;
29878763593fSIvan Malov goto fail2;
29888763593fSIvan Malov }
29898763593fSIvan Malov
29908763593fSIvan Malov if (header_size >
29918763593fSIvan Malov MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_HDR_DATA_MAXNUM_MCDI2) {
29928763593fSIvan Malov rc = EINVAL;
29938763593fSIvan Malov goto fail3;
29948763593fSIvan Malov }
29958763593fSIvan Malov
29968763593fSIvan Malov req.emr_cmd = MC_CMD_MAE_ENCAP_HEADER_UPDATE;
29978763593fSIvan Malov req.emr_in_buf = payload;
29988763593fSIvan Malov req.emr_in_length = MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_LEN(header_size);
29998763593fSIvan Malov req.emr_out_buf = payload;
30008763593fSIvan Malov req.emr_out_length = MC_CMD_MAE_ENCAP_HEADER_UPDATE_OUT_LEN;
30018763593fSIvan Malov
30028763593fSIvan Malov MCDI_IN_SET_DWORD(req,
30038763593fSIvan Malov MAE_ENCAP_HEADER_UPDATE_IN_EH_ID, eh_idp->id);
30048763593fSIvan Malov
30058763593fSIvan Malov MCDI_IN_SET_DWORD(req,
30068763593fSIvan Malov MAE_ENCAP_HEADER_UPDATE_IN_ENCAP_TYPE, encap_type_mcdi);
30078763593fSIvan Malov
30088763593fSIvan Malov memcpy(MCDI_IN2(req, uint8_t, MAE_ENCAP_HEADER_UPDATE_IN_HDR_DATA),
30098763593fSIvan Malov header_data, header_size);
30108763593fSIvan Malov
30118763593fSIvan Malov efx_mcdi_execute(enp, &req);
30128763593fSIvan Malov
30138763593fSIvan Malov if (req.emr_rc != 0) {
30148763593fSIvan Malov rc = req.emr_rc;
30158763593fSIvan Malov goto fail4;
30168763593fSIvan Malov }
30178763593fSIvan Malov
30188763593fSIvan Malov return (0);
30198763593fSIvan Malov
30208763593fSIvan Malov fail4:
30218763593fSIvan Malov EFSYS_PROBE(fail4);
30228763593fSIvan Malov fail3:
30238763593fSIvan Malov EFSYS_PROBE(fail3);
30248763593fSIvan Malov fail2:
30258763593fSIvan Malov EFSYS_PROBE(fail2);
30268763593fSIvan Malov fail1:
30278763593fSIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
30288763593fSIvan Malov return (rc);
30298763593fSIvan Malov }
30308763593fSIvan Malov
30318763593fSIvan Malov __checkReturn efx_rc_t
efx_mae_encap_header_free(__in efx_nic_t * enp,__in const efx_mae_eh_id_t * eh_idp)303230833168SIvan Malov efx_mae_encap_header_free(
303330833168SIvan Malov __in efx_nic_t *enp,
303430833168SIvan Malov __in const efx_mae_eh_id_t *eh_idp)
303530833168SIvan Malov {
303630833168SIvan Malov const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
303730833168SIvan Malov efx_mcdi_req_t req;
303830833168SIvan Malov EFX_MCDI_DECLARE_BUF(payload,
303930833168SIvan Malov MC_CMD_MAE_ENCAP_HEADER_FREE_IN_LEN(1),
304030833168SIvan Malov MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_LEN(1));
304130833168SIvan Malov efx_rc_t rc;
304230833168SIvan Malov
304330833168SIvan Malov if (encp->enc_mae_supported == B_FALSE) {
304430833168SIvan Malov rc = ENOTSUP;
304530833168SIvan Malov goto fail1;
304630833168SIvan Malov }
304730833168SIvan Malov
304830833168SIvan Malov req.emr_cmd = MC_CMD_MAE_ENCAP_HEADER_FREE;
304930833168SIvan Malov req.emr_in_buf = payload;
305030833168SIvan Malov req.emr_in_length = MC_CMD_MAE_ENCAP_HEADER_FREE_IN_LEN(1);
305130833168SIvan Malov req.emr_out_buf = payload;
305230833168SIvan Malov req.emr_out_length = MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_LEN(1);
305330833168SIvan Malov
305430833168SIvan Malov MCDI_IN_SET_DWORD(req, MAE_ENCAP_HEADER_FREE_IN_EH_ID, eh_idp->id);
305530833168SIvan Malov
305630833168SIvan Malov efx_mcdi_execute(enp, &req);
305730833168SIvan Malov
305830833168SIvan Malov if (req.emr_rc != 0) {
305930833168SIvan Malov rc = req.emr_rc;
306030833168SIvan Malov goto fail2;
306130833168SIvan Malov }
306230833168SIvan Malov
306330833168SIvan Malov if (MCDI_OUT_DWORD(req, MAE_ENCAP_HEADER_FREE_OUT_FREED_EH_ID) !=
306430833168SIvan Malov eh_idp->id) {
306530833168SIvan Malov /* Firmware failed to remove the encap. header. */
306630833168SIvan Malov rc = EAGAIN;
306730833168SIvan Malov goto fail3;
306830833168SIvan Malov }
306930833168SIvan Malov
307030833168SIvan Malov return (0);
307130833168SIvan Malov
307230833168SIvan Malov fail3:
307330833168SIvan Malov EFSYS_PROBE(fail3);
307430833168SIvan Malov fail2:
307530833168SIvan Malov EFSYS_PROBE(fail2);
307630833168SIvan Malov fail1:
307730833168SIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
307830833168SIvan Malov return (rc);
307930833168SIvan Malov }
308030833168SIvan Malov
308130833168SIvan Malov __checkReturn efx_rc_t
efx_mae_action_set_fill_in_eh_id(__in efx_mae_actions_t * spec,__in const efx_mae_eh_id_t * eh_idp)30823907defaSIvan Malov efx_mae_action_set_fill_in_eh_id(
30833907defaSIvan Malov __in efx_mae_actions_t *spec,
30843907defaSIvan Malov __in const efx_mae_eh_id_t *eh_idp)
30853907defaSIvan Malov {
30863907defaSIvan Malov efx_rc_t rc;
30873907defaSIvan Malov
30883907defaSIvan Malov if ((spec->ema_actions & (1U << EFX_MAE_ACTION_ENCAP)) == 0) {
30893907defaSIvan Malov /*
30903907defaSIvan Malov * The caller has not intended to have action ENCAP originally,
30913907defaSIvan Malov * hence, this attempt to indicate encap. header ID is invalid.
30923907defaSIvan Malov */
30933907defaSIvan Malov rc = EINVAL;
30943907defaSIvan Malov goto fail1;
30953907defaSIvan Malov }
30963907defaSIvan Malov
30973907defaSIvan Malov if (spec->ema_rsrc.emar_eh_id.id != EFX_MAE_RSRC_ID_INVALID) {
30983907defaSIvan Malov /* The caller attempts to indicate encap. header ID twice. */
30993907defaSIvan Malov rc = EINVAL;
31003907defaSIvan Malov goto fail2;
31013907defaSIvan Malov }
31023907defaSIvan Malov
31033907defaSIvan Malov if (eh_idp->id == EFX_MAE_RSRC_ID_INVALID) {
31043907defaSIvan Malov rc = EINVAL;
31053907defaSIvan Malov goto fail3;
31063907defaSIvan Malov }
31073907defaSIvan Malov
31083907defaSIvan Malov spec->ema_rsrc.emar_eh_id.id = eh_idp->id;
31093907defaSIvan Malov
31103907defaSIvan Malov return (0);
31113907defaSIvan Malov
31123907defaSIvan Malov fail3:
31133907defaSIvan Malov EFSYS_PROBE(fail3);
31143907defaSIvan Malov fail2:
31153907defaSIvan Malov EFSYS_PROBE(fail2);
31163907defaSIvan Malov fail1:
31173907defaSIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
31183907defaSIvan Malov return (rc);
31193907defaSIvan Malov }
31203907defaSIvan Malov
31213907defaSIvan Malov __checkReturn efx_rc_t
efx_mae_action_set_alloc(__in efx_nic_t * enp,__in const efx_mae_actions_t * spec,__out efx_mae_aset_id_t * aset_idp)3122e61baa82SIvan Malov efx_mae_action_set_alloc(
3123e61baa82SIvan Malov __in efx_nic_t *enp,
3124e61baa82SIvan Malov __in const efx_mae_actions_t *spec,
3125e61baa82SIvan Malov __out efx_mae_aset_id_t *aset_idp)
3126e61baa82SIvan Malov {
3127e61baa82SIvan Malov const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
3128e61baa82SIvan Malov efx_mcdi_req_t req;
3129e61baa82SIvan Malov EFX_MCDI_DECLARE_BUF(payload,
3130e61baa82SIvan Malov MC_CMD_MAE_ACTION_SET_ALLOC_IN_LEN,
3131e61baa82SIvan Malov MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN);
3132e61baa82SIvan Malov efx_mae_aset_id_t aset_id;
3133e61baa82SIvan Malov efx_rc_t rc;
3134e61baa82SIvan Malov
3135e61baa82SIvan Malov if (encp->enc_mae_supported == B_FALSE) {
3136e61baa82SIvan Malov rc = ENOTSUP;
3137e61baa82SIvan Malov goto fail1;
3138e61baa82SIvan Malov }
3139e61baa82SIvan Malov
314092bafeffSIvan Malov if ((spec->ema_actions & (1U << EFX_MAE_ACTION_SET_DST_MAC)) != 0 &&
314192bafeffSIvan Malov spec->ema_rsrc.emar_dst_mac_id.id == EFX_MAE_RSRC_ID_INVALID) {
314292bafeffSIvan Malov rc = EINVAL;
314392bafeffSIvan Malov goto fail2;
314492bafeffSIvan Malov }
314592bafeffSIvan Malov
314692bafeffSIvan Malov if ((spec->ema_actions & (1U << EFX_MAE_ACTION_SET_SRC_MAC)) != 0 &&
314792bafeffSIvan Malov spec->ema_rsrc.emar_src_mac_id.id == EFX_MAE_RSRC_ID_INVALID) {
314892bafeffSIvan Malov rc = EINVAL;
314992bafeffSIvan Malov goto fail3;
315092bafeffSIvan Malov }
315192bafeffSIvan Malov
315297df7281SIvan Malov if ((spec->ema_actions & (1U << EFX_MAE_ACTION_ENCAP)) != 0 &&
315397df7281SIvan Malov spec->ema_rsrc.emar_eh_id.id == EFX_MAE_RSRC_ID_INVALID) {
315497df7281SIvan Malov rc = EINVAL;
315592bafeffSIvan Malov goto fail4;
315697df7281SIvan Malov }
315797df7281SIvan Malov
3158e8745b54SIvan Malov if (spec->ema_n_count_actions == 1 &&
3159e8745b54SIvan Malov spec->ema_rsrc.emar_counter_id.id == EFX_MAE_RSRC_ID_INVALID) {
3160e8745b54SIvan Malov rc = EINVAL;
316192bafeffSIvan Malov goto fail5;
3162e8745b54SIvan Malov }
3163e8745b54SIvan Malov
3164e61baa82SIvan Malov req.emr_cmd = MC_CMD_MAE_ACTION_SET_ALLOC;
3165e61baa82SIvan Malov req.emr_in_buf = payload;
3166e61baa82SIvan Malov req.emr_in_length = MC_CMD_MAE_ACTION_SET_ALLOC_IN_LEN;
3167e61baa82SIvan Malov req.emr_out_buf = payload;
3168e61baa82SIvan Malov req.emr_out_length = MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN;
3169e61baa82SIvan Malov
3170e61baa82SIvan Malov /*
3171e61baa82SIvan Malov * TODO: Remove these EFX_MAE_RSRC_ID_INVALID assignments once the
3172e61baa82SIvan Malov * corresponding resource types are supported by the implementation.
3173e61baa82SIvan Malov * Use proper resource ID assignments instead.
3174e61baa82SIvan Malov */
3175e61baa82SIvan Malov MCDI_IN_SET_DWORD(req,
3176e61baa82SIvan Malov MAE_ACTION_SET_ALLOC_IN_COUNTER_LIST_ID, EFX_MAE_RSRC_ID_INVALID);
3177e61baa82SIvan Malov
31780f6b017bSIvan Malov if ((spec->ema_actions & (1U << EFX_MAE_ACTION_DECAP)) != 0) {
31790f6b017bSIvan Malov MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
31800f6b017bSIvan Malov MAE_ACTION_SET_ALLOC_IN_DECAP, 1);
31810f6b017bSIvan Malov }
31820f6b017bSIvan Malov
3183616b03e0SIvan Malov MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
3184616b03e0SIvan Malov MAE_ACTION_SET_ALLOC_IN_VLAN_POP, spec->ema_n_vlan_tags_to_pop);
3185616b03e0SIvan Malov
318692bafeffSIvan Malov MCDI_IN_SET_DWORD(req, MAE_ACTION_SET_ALLOC_IN_DST_MAC_ID,
318792bafeffSIvan Malov spec->ema_rsrc.emar_dst_mac_id.id);
318892bafeffSIvan Malov
318992bafeffSIvan Malov MCDI_IN_SET_DWORD(req, MAE_ACTION_SET_ALLOC_IN_SRC_MAC_ID,
319092bafeffSIvan Malov spec->ema_rsrc.emar_src_mac_id.id);
319192bafeffSIvan Malov
3192c6e3e6c4SIvan Malov if ((spec->ema_actions & (1U << EFX_MAE_ACTION_DECR_IP_TTL)) != 0) {
3193c6e3e6c4SIvan Malov MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
3194c6e3e6c4SIvan Malov MAE_ACTION_SET_ALLOC_IN_DO_DECR_IP_TTL, 1);
3195c6e3e6c4SIvan Malov }
3196c6e3e6c4SIvan Malov
31976cefdea5SIvan Malov if ((spec->ema_actions & (1U << EFX_MAE_ACTION_NAT)) != 0) {
31986cefdea5SIvan Malov MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
31996cefdea5SIvan Malov MAE_ACTION_SET_ALLOC_IN_DO_NAT, 1);
32006cefdea5SIvan Malov }
32016cefdea5SIvan Malov
320212cd7909SIvan Malov if (spec->ema_n_vlan_tags_to_push > 0) {
320312cd7909SIvan Malov unsigned int outer_tag_idx;
320412cd7909SIvan Malov
320512cd7909SIvan Malov MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
320612cd7909SIvan Malov MAE_ACTION_SET_ALLOC_IN_VLAN_PUSH,
320712cd7909SIvan Malov spec->ema_n_vlan_tags_to_push);
320812cd7909SIvan Malov
320912cd7909SIvan Malov if (spec->ema_n_vlan_tags_to_push ==
321012cd7909SIvan Malov EFX_MAE_VLAN_PUSH_MAX_NTAGS) {
321112cd7909SIvan Malov MCDI_IN_SET_WORD(req,
321212cd7909SIvan Malov MAE_ACTION_SET_ALLOC_IN_VLAN1_PROTO_BE,
321312cd7909SIvan Malov spec->ema_vlan_push_descs[0].emavp_tpid_be);
321412cd7909SIvan Malov MCDI_IN_SET_WORD(req,
321512cd7909SIvan Malov MAE_ACTION_SET_ALLOC_IN_VLAN1_TCI_BE,
321612cd7909SIvan Malov spec->ema_vlan_push_descs[0].emavp_tci_be);
321712cd7909SIvan Malov }
321812cd7909SIvan Malov
321912cd7909SIvan Malov outer_tag_idx = spec->ema_n_vlan_tags_to_push - 1;
322012cd7909SIvan Malov
322112cd7909SIvan Malov MCDI_IN_SET_WORD(req, MAE_ACTION_SET_ALLOC_IN_VLAN0_PROTO_BE,
322212cd7909SIvan Malov spec->ema_vlan_push_descs[outer_tag_idx].emavp_tpid_be);
322312cd7909SIvan Malov MCDI_IN_SET_WORD(req, MAE_ACTION_SET_ALLOC_IN_VLAN0_TCI_BE,
322412cd7909SIvan Malov spec->ema_vlan_push_descs[outer_tag_idx].emavp_tci_be);
322512cd7909SIvan Malov }
322612cd7909SIvan Malov
32273907defaSIvan Malov MCDI_IN_SET_DWORD(req, MAE_ACTION_SET_ALLOC_IN_ENCAP_HEADER_ID,
32283907defaSIvan Malov spec->ema_rsrc.emar_eh_id.id);
3229238306cfSIgor Romanov MCDI_IN_SET_DWORD(req, MAE_ACTION_SET_ALLOC_IN_COUNTER_ID,
3230238306cfSIgor Romanov spec->ema_rsrc.emar_counter_id.id);
32313907defaSIvan Malov
323277da5888SIvan Malov if ((spec->ema_actions & (1U << EFX_MAE_ACTION_FLAG)) != 0) {
323377da5888SIvan Malov MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
323477da5888SIvan Malov MAE_ACTION_SET_ALLOC_IN_FLAG, 1);
323577da5888SIvan Malov }
323677da5888SIvan Malov
323783352289SIvan Malov if ((spec->ema_actions & (1U << EFX_MAE_ACTION_MARK)) != 0) {
323883352289SIvan Malov MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
323983352289SIvan Malov MAE_ACTION_SET_ALLOC_IN_MARK, 1);
324083352289SIvan Malov
324183352289SIvan Malov MCDI_IN_SET_DWORD(req,
324283352289SIvan Malov MAE_ACTION_SET_ALLOC_IN_MARK_VALUE, spec->ema_mark_value);
324383352289SIvan Malov }
324483352289SIvan Malov
3245e61baa82SIvan Malov MCDI_IN_SET_DWORD(req,
3246e61baa82SIvan Malov MAE_ACTION_SET_ALLOC_IN_DELIVER, spec->ema_deliver_mport.sel);
3247e61baa82SIvan Malov
3248e61baa82SIvan Malov efx_mcdi_execute(enp, &req);
3249e61baa82SIvan Malov
3250e61baa82SIvan Malov if (req.emr_rc != 0) {
3251e61baa82SIvan Malov rc = req.emr_rc;
325292bafeffSIvan Malov goto fail6;
3253e61baa82SIvan Malov }
3254e61baa82SIvan Malov
3255e61baa82SIvan Malov if (req.emr_out_length_used < MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN) {
3256e61baa82SIvan Malov rc = EMSGSIZE;
325792bafeffSIvan Malov goto fail7;
3258e61baa82SIvan Malov }
3259e61baa82SIvan Malov
3260e61baa82SIvan Malov aset_id.id = MCDI_OUT_DWORD(req, MAE_ACTION_SET_ALLOC_OUT_AS_ID);
3261e61baa82SIvan Malov if (aset_id.id == EFX_MAE_RSRC_ID_INVALID) {
3262e61baa82SIvan Malov rc = ENOENT;
326392bafeffSIvan Malov goto fail8;
3264e61baa82SIvan Malov }
3265e61baa82SIvan Malov
3266e61baa82SIvan Malov aset_idp->id = aset_id.id;
3267e61baa82SIvan Malov
3268e61baa82SIvan Malov return (0);
3269e61baa82SIvan Malov
327092bafeffSIvan Malov fail8:
327192bafeffSIvan Malov EFSYS_PROBE(fail8);
327292bafeffSIvan Malov fail7:
327392bafeffSIvan Malov EFSYS_PROBE(fail7);
3274e8745b54SIvan Malov fail6:
3275e8745b54SIvan Malov EFSYS_PROBE(fail6);
327697df7281SIvan Malov fail5:
327797df7281SIvan Malov EFSYS_PROBE(fail5);
3278e61baa82SIvan Malov fail4:
3279e61baa82SIvan Malov EFSYS_PROBE(fail4);
3280e61baa82SIvan Malov fail3:
3281e61baa82SIvan Malov EFSYS_PROBE(fail3);
3282e61baa82SIvan Malov fail2:
3283e61baa82SIvan Malov EFSYS_PROBE(fail2);
3284e61baa82SIvan Malov fail1:
3285e61baa82SIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
3286e61baa82SIvan Malov return (rc);
3287e61baa82SIvan Malov }
3288e61baa82SIvan Malov
3289238306cfSIgor Romanov __checkReturn unsigned int
efx_mae_action_set_get_nb_count(__in const efx_mae_actions_t * spec)3290238306cfSIgor Romanov efx_mae_action_set_get_nb_count(
3291238306cfSIgor Romanov __in const efx_mae_actions_t *spec)
3292238306cfSIgor Romanov {
3293238306cfSIgor Romanov return (spec->ema_n_count_actions);
3294238306cfSIgor Romanov }
3295238306cfSIgor Romanov
3296238306cfSIgor Romanov __checkReturn efx_rc_t
efx_mae_action_set_fill_in_counter_id(__in efx_mae_actions_t * spec,__in const efx_counter_t * counter_idp)3297238306cfSIgor Romanov efx_mae_action_set_fill_in_counter_id(
3298238306cfSIgor Romanov __in efx_mae_actions_t *spec,
3299238306cfSIgor Romanov __in const efx_counter_t *counter_idp)
3300238306cfSIgor Romanov {
3301238306cfSIgor Romanov efx_rc_t rc;
3302238306cfSIgor Romanov
3303238306cfSIgor Romanov if ((spec->ema_actions & (1U << EFX_MAE_ACTION_COUNT)) == 0) {
3304238306cfSIgor Romanov /*
3305238306cfSIgor Romanov * Invalid to add counter ID if spec does not have COUNT action.
3306238306cfSIgor Romanov */
3307238306cfSIgor Romanov rc = EINVAL;
3308238306cfSIgor Romanov goto fail1;
3309238306cfSIgor Romanov }
3310238306cfSIgor Romanov
3311238306cfSIgor Romanov if (spec->ema_n_count_actions != 1) {
3312238306cfSIgor Romanov /*
3313238306cfSIgor Romanov * Having multiple COUNT actions in the spec requires a counter
3314238306cfSIgor Romanov * list to be used. This API must only be used for a single
3315238306cfSIgor Romanov * counter per spec. Turn down the request as inappropriate.
3316238306cfSIgor Romanov */
3317238306cfSIgor Romanov rc = EINVAL;
3318238306cfSIgor Romanov goto fail2;
3319238306cfSIgor Romanov }
3320238306cfSIgor Romanov
3321238306cfSIgor Romanov if (spec->ema_rsrc.emar_counter_id.id != EFX_MAE_RSRC_ID_INVALID) {
3322238306cfSIgor Romanov /* The caller attempts to indicate counter ID twice. */
3323238306cfSIgor Romanov rc = EALREADY;
3324238306cfSIgor Romanov goto fail3;
3325238306cfSIgor Romanov }
3326238306cfSIgor Romanov
3327238306cfSIgor Romanov if (counter_idp->id == EFX_MAE_RSRC_ID_INVALID) {
3328238306cfSIgor Romanov rc = EINVAL;
3329238306cfSIgor Romanov goto fail4;
3330238306cfSIgor Romanov }
3331238306cfSIgor Romanov
3332238306cfSIgor Romanov spec->ema_rsrc.emar_counter_id.id = counter_idp->id;
3333238306cfSIgor Romanov
3334238306cfSIgor Romanov return (0);
3335238306cfSIgor Romanov
3336238306cfSIgor Romanov fail4:
3337238306cfSIgor Romanov EFSYS_PROBE(fail4);
3338238306cfSIgor Romanov fail3:
3339238306cfSIgor Romanov EFSYS_PROBE(fail3);
3340238306cfSIgor Romanov fail2:
3341238306cfSIgor Romanov EFSYS_PROBE(fail2);
3342238306cfSIgor Romanov fail1:
3343238306cfSIgor Romanov EFSYS_PROBE1(fail1, efx_rc_t, rc);
3344238306cfSIgor Romanov return (rc);
3345238306cfSIgor Romanov }
3346238306cfSIgor Romanov
3347cf1e1a8eSIvan Malov void
efx_mae_action_set_clear_fw_rsrc_ids(__in efx_mae_actions_t * spec)3348cf1e1a8eSIvan Malov efx_mae_action_set_clear_fw_rsrc_ids(
3349cf1e1a8eSIvan Malov __in efx_mae_actions_t *spec)
3350cf1e1a8eSIvan Malov {
3351cf1e1a8eSIvan Malov spec->ema_rsrc.emar_dst_mac_id.id = EFX_MAE_RSRC_ID_INVALID;
3352cf1e1a8eSIvan Malov spec->ema_rsrc.emar_src_mac_id.id = EFX_MAE_RSRC_ID_INVALID;
3353cf1e1a8eSIvan Malov spec->ema_rsrc.emar_eh_id.id = EFX_MAE_RSRC_ID_INVALID;
3354cf1e1a8eSIvan Malov spec->ema_rsrc.emar_counter_id.id = EFX_MAE_RSRC_ID_INVALID;
3355cf1e1a8eSIvan Malov }
3356cf1e1a8eSIvan Malov
3357e61baa82SIvan Malov __checkReturn efx_rc_t
efx_mae_counters_alloc_type(__in efx_nic_t * enp,__in efx_counter_type_t type,__in uint32_t n_counters,__out uint32_t * n_allocatedp,__out_ecount (n_counters)efx_counter_t * countersp,__out_opt uint32_t * gen_countp)3358d19e7dd9SIvan Malov efx_mae_counters_alloc_type(
3359bbc42f34SIgor Romanov __in efx_nic_t *enp,
3360d19e7dd9SIvan Malov __in efx_counter_type_t type,
3361bbc42f34SIgor Romanov __in uint32_t n_counters,
3362bbc42f34SIgor Romanov __out uint32_t *n_allocatedp,
3363bbc42f34SIgor Romanov __out_ecount(n_counters) efx_counter_t *countersp,
3364bbc42f34SIgor Romanov __out_opt uint32_t *gen_countp)
3365bbc42f34SIgor Romanov {
3366bbc42f34SIgor Romanov EFX_MCDI_DECLARE_BUF(payload,
3367d19e7dd9SIvan Malov MC_CMD_MAE_COUNTER_ALLOC_V2_IN_LEN,
3368bbc42f34SIgor Romanov MC_CMD_MAE_COUNTER_ALLOC_OUT_LENMAX_MCDI2);
3369bbc42f34SIgor Romanov efx_mae_t *maep = enp->en_maep;
3370d19e7dd9SIvan Malov uint32_t max_n_counters;
3371bbc42f34SIgor Romanov uint32_t n_allocated;
3372bbc42f34SIgor Romanov efx_mcdi_req_t req;
3373bbc42f34SIgor Romanov unsigned int i;
3374bbc42f34SIgor Romanov efx_rc_t rc;
3375bbc42f34SIgor Romanov
3376d19e7dd9SIvan Malov EFX_STATIC_ASSERT(EFX_COUNTER_TYPE_ACTION == MAE_COUNTER_TYPE_AR);
3377f4a6d074SIvan Malov EFX_STATIC_ASSERT(EFX_COUNTER_TYPE_CONNTRACK == MAE_COUNTER_TYPE_CT);
3378d19e7dd9SIvan Malov
3379d19e7dd9SIvan Malov switch (type) {
3380d19e7dd9SIvan Malov case EFX_COUNTER_TYPE_ACTION:
3381d19e7dd9SIvan Malov max_n_counters = maep->em_max_n_action_counters;
3382d19e7dd9SIvan Malov break;
3383f4a6d074SIvan Malov case EFX_COUNTER_TYPE_CONNTRACK:
3384f4a6d074SIvan Malov max_n_counters = maep->em_max_n_conntrack_counters;
3385f4a6d074SIvan Malov break;
3386d19e7dd9SIvan Malov default:
3387bbc42f34SIgor Romanov rc = EINVAL;
3388bbc42f34SIgor Romanov goto fail1;
3389bbc42f34SIgor Romanov }
3390bbc42f34SIgor Romanov
3391d19e7dd9SIvan Malov if (n_counters > max_n_counters ||
3392d19e7dd9SIvan Malov n_counters < MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MINNUM ||
3393d19e7dd9SIvan Malov n_counters > MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MAXNUM_MCDI2) {
3394d19e7dd9SIvan Malov rc = EINVAL;
3395d19e7dd9SIvan Malov goto fail2;
3396d19e7dd9SIvan Malov }
3397d19e7dd9SIvan Malov
3398bbc42f34SIgor Romanov req.emr_cmd = MC_CMD_MAE_COUNTER_ALLOC;
3399bbc42f34SIgor Romanov req.emr_in_buf = payload;
3400d19e7dd9SIvan Malov req.emr_in_length = MC_CMD_MAE_COUNTER_ALLOC_V2_IN_LEN;
3401bbc42f34SIgor Romanov req.emr_out_buf = payload;
3402bbc42f34SIgor Romanov req.emr_out_length = MC_CMD_MAE_COUNTER_ALLOC_OUT_LEN(n_counters);
3403bbc42f34SIgor Romanov
3404bbc42f34SIgor Romanov MCDI_IN_SET_DWORD(req, MAE_COUNTER_ALLOC_IN_REQUESTED_COUNT,
3405bbc42f34SIgor Romanov n_counters);
3406bbc42f34SIgor Romanov
3407d19e7dd9SIvan Malov MCDI_IN_SET_DWORD(req, MAE_COUNTER_ALLOC_V2_IN_COUNTER_TYPE, type);
3408d19e7dd9SIvan Malov
3409bbc42f34SIgor Romanov efx_mcdi_execute(enp, &req);
3410bbc42f34SIgor Romanov
3411bbc42f34SIgor Romanov if (req.emr_rc != 0) {
3412bbc42f34SIgor Romanov rc = req.emr_rc;
3413d19e7dd9SIvan Malov goto fail3;
3414bbc42f34SIgor Romanov }
3415bbc42f34SIgor Romanov
3416bbc42f34SIgor Romanov if (req.emr_out_length_used < MC_CMD_MAE_COUNTER_ALLOC_OUT_LENMIN) {
3417bbc42f34SIgor Romanov rc = EMSGSIZE;
3418d19e7dd9SIvan Malov goto fail4;
3419bbc42f34SIgor Romanov }
3420bbc42f34SIgor Romanov
3421bbc42f34SIgor Romanov n_allocated = MCDI_OUT_DWORD(req,
3422bbc42f34SIgor Romanov MAE_COUNTER_ALLOC_OUT_COUNTER_ID_COUNT);
3423bbc42f34SIgor Romanov if (n_allocated < MC_CMD_MAE_COUNTER_ALLOC_OUT_COUNTER_ID_MINNUM) {
3424bbc42f34SIgor Romanov rc = EFAULT;
3425d19e7dd9SIvan Malov goto fail5;
3426bbc42f34SIgor Romanov }
3427bbc42f34SIgor Romanov
3428bbc42f34SIgor Romanov for (i = 0; i < n_allocated; i++) {
3429bbc42f34SIgor Romanov countersp[i].id = MCDI_OUT_INDEXED_DWORD(req,
3430bbc42f34SIgor Romanov MAE_COUNTER_ALLOC_OUT_COUNTER_ID, i);
3431bbc42f34SIgor Romanov }
3432bbc42f34SIgor Romanov
3433bbc42f34SIgor Romanov if (gen_countp != NULL) {
3434bbc42f34SIgor Romanov *gen_countp = MCDI_OUT_DWORD(req,
3435bbc42f34SIgor Romanov MAE_COUNTER_ALLOC_OUT_GENERATION_COUNT);
3436bbc42f34SIgor Romanov }
3437bbc42f34SIgor Romanov
3438bbc42f34SIgor Romanov *n_allocatedp = n_allocated;
3439bbc42f34SIgor Romanov
3440bbc42f34SIgor Romanov return (0);
3441bbc42f34SIgor Romanov
3442d19e7dd9SIvan Malov fail5:
3443d19e7dd9SIvan Malov EFSYS_PROBE(fail5);
3444d19e7dd9SIvan Malov fail4:
3445d19e7dd9SIvan Malov EFSYS_PROBE(fail4);
3446d19e7dd9SIvan Malov fail3:
3447d19e7dd9SIvan Malov EFSYS_PROBE(fail3);
3448d19e7dd9SIvan Malov fail2:
3449d19e7dd9SIvan Malov EFSYS_PROBE(fail2);
3450d19e7dd9SIvan Malov fail1:
3451d19e7dd9SIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
3452d19e7dd9SIvan Malov
3453d19e7dd9SIvan Malov return (rc);
3454d19e7dd9SIvan Malov }
3455d19e7dd9SIvan Malov
3456d19e7dd9SIvan Malov __checkReturn efx_rc_t
efx_mae_counters_alloc(__in efx_nic_t * enp,__in uint32_t n_counters,__out uint32_t * n_allocatedp,__out_ecount (n_counters)efx_counter_t * countersp,__out_opt uint32_t * gen_countp)3457d19e7dd9SIvan Malov efx_mae_counters_alloc(
3458d19e7dd9SIvan Malov __in efx_nic_t *enp,
3459d19e7dd9SIvan Malov __in uint32_t n_counters,
3460d19e7dd9SIvan Malov __out uint32_t *n_allocatedp,
3461d19e7dd9SIvan Malov __out_ecount(n_counters) efx_counter_t *countersp,
3462d19e7dd9SIvan Malov __out_opt uint32_t *gen_countp)
3463d19e7dd9SIvan Malov {
3464d19e7dd9SIvan Malov efx_rc_t rc;
3465d19e7dd9SIvan Malov
3466d19e7dd9SIvan Malov rc = efx_mae_counters_alloc_type(enp, EFX_COUNTER_TYPE_ACTION,
3467d19e7dd9SIvan Malov n_counters, n_allocatedp,
3468d19e7dd9SIvan Malov countersp, gen_countp);
3469d19e7dd9SIvan Malov if (rc != 0)
3470d19e7dd9SIvan Malov goto fail1;
3471d19e7dd9SIvan Malov
3472d19e7dd9SIvan Malov return (0);
3473d19e7dd9SIvan Malov
3474d19e7dd9SIvan Malov fail1:
3475d19e7dd9SIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
3476d19e7dd9SIvan Malov return (rc);
3477d19e7dd9SIvan Malov }
3478d19e7dd9SIvan Malov
3479d19e7dd9SIvan Malov __checkReturn efx_rc_t
efx_mae_counters_free_type(__in efx_nic_t * enp,__in efx_counter_type_t type,__in uint32_t n_counters,__out uint32_t * n_freedp,__in_ecount (n_counters)const efx_counter_t * countersp,__out_opt uint32_t * gen_countp)3480d19e7dd9SIvan Malov efx_mae_counters_free_type(
3481d19e7dd9SIvan Malov __in efx_nic_t *enp,
3482d19e7dd9SIvan Malov __in efx_counter_type_t type,
3483d19e7dd9SIvan Malov __in uint32_t n_counters,
3484d19e7dd9SIvan Malov __out uint32_t *n_freedp,
3485d19e7dd9SIvan Malov __in_ecount(n_counters) const efx_counter_t *countersp,
3486d19e7dd9SIvan Malov __out_opt uint32_t *gen_countp)
3487d19e7dd9SIvan Malov {
3488d19e7dd9SIvan Malov EFX_MCDI_DECLARE_BUF(payload,
3489d19e7dd9SIvan Malov MC_CMD_MAE_COUNTER_FREE_V2_IN_LEN,
3490d19e7dd9SIvan Malov MC_CMD_MAE_COUNTER_FREE_OUT_LENMAX_MCDI2);
3491d19e7dd9SIvan Malov efx_mae_t *maep = enp->en_maep;
3492d19e7dd9SIvan Malov uint32_t max_n_counters;
3493d19e7dd9SIvan Malov efx_mcdi_req_t req;
3494d19e7dd9SIvan Malov uint32_t n_freed;
3495d19e7dd9SIvan Malov unsigned int i;
3496d19e7dd9SIvan Malov efx_rc_t rc;
3497d19e7dd9SIvan Malov
3498d19e7dd9SIvan Malov switch (type) {
3499d19e7dd9SIvan Malov case EFX_COUNTER_TYPE_ACTION:
3500d19e7dd9SIvan Malov max_n_counters = maep->em_max_n_action_counters;
3501d19e7dd9SIvan Malov break;
3502f4a6d074SIvan Malov case EFX_COUNTER_TYPE_CONNTRACK:
3503f4a6d074SIvan Malov max_n_counters = maep->em_max_n_conntrack_counters;
3504f4a6d074SIvan Malov break;
3505d19e7dd9SIvan Malov default:
3506d19e7dd9SIvan Malov rc = EINVAL;
3507d19e7dd9SIvan Malov goto fail1;
3508d19e7dd9SIvan Malov }
3509d19e7dd9SIvan Malov
3510d19e7dd9SIvan Malov if (n_counters > max_n_counters ||
3511d19e7dd9SIvan Malov n_counters < MC_CMD_MAE_COUNTER_FREE_V2_IN_FREE_COUNTER_ID_MINNUM ||
3512d19e7dd9SIvan Malov n_counters >
3513d19e7dd9SIvan Malov MC_CMD_MAE_COUNTER_FREE_V2_IN_FREE_COUNTER_ID_MAXNUM_MCDI2) {
3514d19e7dd9SIvan Malov rc = EINVAL;
3515d19e7dd9SIvan Malov goto fail2;
3516d19e7dd9SIvan Malov }
3517d19e7dd9SIvan Malov
3518d19e7dd9SIvan Malov req.emr_cmd = MC_CMD_MAE_COUNTER_FREE;
3519d19e7dd9SIvan Malov req.emr_in_buf = payload;
3520d19e7dd9SIvan Malov req.emr_in_length = MC_CMD_MAE_COUNTER_FREE_V2_IN_LEN;
3521d19e7dd9SIvan Malov req.emr_out_buf = payload;
3522d19e7dd9SIvan Malov req.emr_out_length = MC_CMD_MAE_COUNTER_FREE_OUT_LEN(n_counters);
3523d19e7dd9SIvan Malov
3524d19e7dd9SIvan Malov for (i = 0; i < n_counters; i++) {
3525d19e7dd9SIvan Malov MCDI_IN_SET_INDEXED_DWORD(req,
3526d19e7dd9SIvan Malov MAE_COUNTER_FREE_IN_FREE_COUNTER_ID, i, countersp[i].id);
3527d19e7dd9SIvan Malov }
3528d19e7dd9SIvan Malov MCDI_IN_SET_DWORD(req, MAE_COUNTER_FREE_IN_COUNTER_ID_COUNT,
3529d19e7dd9SIvan Malov n_counters);
3530d19e7dd9SIvan Malov
3531d19e7dd9SIvan Malov MCDI_IN_SET_DWORD(req, MAE_COUNTER_FREE_V2_IN_COUNTER_TYPE, type);
3532d19e7dd9SIvan Malov
3533d19e7dd9SIvan Malov efx_mcdi_execute(enp, &req);
3534d19e7dd9SIvan Malov
3535d19e7dd9SIvan Malov if (req.emr_rc != 0) {
3536d19e7dd9SIvan Malov rc = req.emr_rc;
3537d19e7dd9SIvan Malov goto fail3;
3538d19e7dd9SIvan Malov }
3539d19e7dd9SIvan Malov
3540d19e7dd9SIvan Malov if (req.emr_out_length_used < MC_CMD_MAE_COUNTER_FREE_OUT_LENMIN) {
3541d19e7dd9SIvan Malov rc = EMSGSIZE;
3542d19e7dd9SIvan Malov goto fail4;
3543d19e7dd9SIvan Malov }
3544d19e7dd9SIvan Malov
3545d19e7dd9SIvan Malov n_freed = MCDI_OUT_DWORD(req, MAE_COUNTER_FREE_OUT_COUNTER_ID_COUNT);
3546d19e7dd9SIvan Malov
3547d19e7dd9SIvan Malov if (n_freed < MC_CMD_MAE_COUNTER_FREE_OUT_FREED_COUNTER_ID_MINNUM) {
3548d19e7dd9SIvan Malov rc = EFAULT;
3549d19e7dd9SIvan Malov goto fail5;
3550d19e7dd9SIvan Malov }
3551d19e7dd9SIvan Malov
3552d19e7dd9SIvan Malov if (gen_countp != NULL) {
3553d19e7dd9SIvan Malov *gen_countp = MCDI_OUT_DWORD(req,
3554d19e7dd9SIvan Malov MAE_COUNTER_FREE_OUT_GENERATION_COUNT);
3555d19e7dd9SIvan Malov }
3556d19e7dd9SIvan Malov
3557d19e7dd9SIvan Malov *n_freedp = n_freed;
3558d19e7dd9SIvan Malov
3559d19e7dd9SIvan Malov return (0);
3560d19e7dd9SIvan Malov
3561d19e7dd9SIvan Malov fail5:
3562d19e7dd9SIvan Malov EFSYS_PROBE(fail5);
3563bbc42f34SIgor Romanov fail4:
3564bbc42f34SIgor Romanov EFSYS_PROBE(fail4);
3565bbc42f34SIgor Romanov fail3:
3566bbc42f34SIgor Romanov EFSYS_PROBE(fail3);
3567bbc42f34SIgor Romanov fail2:
3568bbc42f34SIgor Romanov EFSYS_PROBE(fail2);
3569bbc42f34SIgor Romanov fail1:
3570bbc42f34SIgor Romanov EFSYS_PROBE1(fail1, efx_rc_t, rc);
3571bbc42f34SIgor Romanov
3572bbc42f34SIgor Romanov return (rc);
3573bbc42f34SIgor Romanov }
3574bbc42f34SIgor Romanov
3575bbc42f34SIgor Romanov __checkReturn efx_rc_t
efx_mae_counters_free(__in efx_nic_t * enp,__in uint32_t n_counters,__out uint32_t * n_freedp,__in_ecount (n_counters)const efx_counter_t * countersp,__out_opt uint32_t * gen_countp)3576bbc42f34SIgor Romanov efx_mae_counters_free(
3577bbc42f34SIgor Romanov __in efx_nic_t *enp,
3578bbc42f34SIgor Romanov __in uint32_t n_counters,
3579bbc42f34SIgor Romanov __out uint32_t *n_freedp,
3580bbc42f34SIgor Romanov __in_ecount(n_counters) const efx_counter_t *countersp,
3581bbc42f34SIgor Romanov __out_opt uint32_t *gen_countp)
3582bbc42f34SIgor Romanov {
3583bbc42f34SIgor Romanov efx_rc_t rc;
3584bbc42f34SIgor Romanov
3585d19e7dd9SIvan Malov rc = efx_mae_counters_free_type(enp, EFX_COUNTER_TYPE_ACTION,
3586d19e7dd9SIvan Malov n_counters, n_freedp,
3587d19e7dd9SIvan Malov countersp, gen_countp);
3588d19e7dd9SIvan Malov if (rc != 0)
3589bbc42f34SIgor Romanov goto fail1;
3590bbc42f34SIgor Romanov
3591bbc42f34SIgor Romanov return (0);
3592bbc42f34SIgor Romanov
3593bbc42f34SIgor Romanov fail1:
3594bbc42f34SIgor Romanov EFSYS_PROBE1(fail1, efx_rc_t, rc);
3595c0a77efbSIgor Romanov return (rc);
3596c0a77efbSIgor Romanov }
3597c0a77efbSIgor Romanov
3598c0a77efbSIgor Romanov __checkReturn efx_rc_t
efx_mae_counters_stream_start(__in efx_nic_t * enp,__in uint16_t rxq_id,__in uint16_t packet_size,__in uint32_t flags_in,__out uint32_t * flags_out)3599c0a77efbSIgor Romanov efx_mae_counters_stream_start(
3600c0a77efbSIgor Romanov __in efx_nic_t *enp,
3601c0a77efbSIgor Romanov __in uint16_t rxq_id,
3602c0a77efbSIgor Romanov __in uint16_t packet_size,
3603c0a77efbSIgor Romanov __in uint32_t flags_in,
3604c0a77efbSIgor Romanov __out uint32_t *flags_out)
3605c0a77efbSIgor Romanov {
3606c0a77efbSIgor Romanov efx_mcdi_req_t req;
3607f4a6d074SIvan Malov EFX_MCDI_DECLARE_BUF(payload,
3608f4a6d074SIvan Malov MC_CMD_MAE_COUNTERS_STREAM_START_V2_IN_LEN,
3609c0a77efbSIgor Romanov MC_CMD_MAE_COUNTERS_STREAM_START_OUT_LEN);
3610f4a6d074SIvan Malov struct efx_mae_s *maep = enp->en_maep;
3611f4a6d074SIvan Malov uint32_t counter_types;
3612c0a77efbSIgor Romanov efx_rc_t rc;
3613c0a77efbSIgor Romanov
3614c0a77efbSIgor Romanov EFX_STATIC_ASSERT(EFX_MAE_COUNTERS_STREAM_IN_ZERO_SQUASH_DISABLE ==
3615c0a77efbSIgor Romanov 1U << MC_CMD_MAE_COUNTERS_STREAM_START_IN_ZERO_SQUASH_DISABLE_LBN);
3616c0a77efbSIgor Romanov
3617c0a77efbSIgor Romanov EFX_STATIC_ASSERT(EFX_MAE_COUNTERS_STREAM_OUT_USES_CREDITS ==
3618c0a77efbSIgor Romanov 1U << MC_CMD_MAE_COUNTERS_STREAM_START_OUT_USES_CREDITS_LBN);
3619c0a77efbSIgor Romanov
3620c0a77efbSIgor Romanov req.emr_cmd = MC_CMD_MAE_COUNTERS_STREAM_START;
3621c0a77efbSIgor Romanov req.emr_in_buf = payload;
3622f4a6d074SIvan Malov req.emr_in_length = MC_CMD_MAE_COUNTERS_STREAM_START_V2_IN_LEN;
3623c0a77efbSIgor Romanov req.emr_out_buf = payload;
3624c0a77efbSIgor Romanov req.emr_out_length = MC_CMD_MAE_COUNTERS_STREAM_START_OUT_LEN;
3625c0a77efbSIgor Romanov
3626c0a77efbSIgor Romanov MCDI_IN_SET_WORD(req, MAE_COUNTERS_STREAM_START_IN_QID, rxq_id);
3627c0a77efbSIgor Romanov MCDI_IN_SET_WORD(req, MAE_COUNTERS_STREAM_START_IN_PACKET_SIZE,
3628c0a77efbSIgor Romanov packet_size);
3629c0a77efbSIgor Romanov MCDI_IN_SET_DWORD(req, MAE_COUNTERS_STREAM_START_IN_FLAGS, flags_in);
3630c0a77efbSIgor Romanov
3631f4a6d074SIvan Malov counter_types = (1U << MAE_COUNTER_TYPE_AR);
3632f4a6d074SIvan Malov
3633f4a6d074SIvan Malov if (maep->em_max_n_conntrack_counters != 0)
3634f4a6d074SIvan Malov counter_types |= (1U << MAE_COUNTER_TYPE_CT);
3635f4a6d074SIvan Malov
3636f4a6d074SIvan Malov MCDI_IN_SET_DWORD(req,
3637f4a6d074SIvan Malov MAE_COUNTERS_STREAM_START_V2_IN_COUNTER_TYPES_MASK,
3638f4a6d074SIvan Malov counter_types);
3639f4a6d074SIvan Malov
3640c0a77efbSIgor Romanov efx_mcdi_execute(enp, &req);
3641c0a77efbSIgor Romanov
3642c0a77efbSIgor Romanov if (req.emr_rc != 0) {
3643c0a77efbSIgor Romanov rc = req.emr_rc;
3644c0a77efbSIgor Romanov goto fail1;
3645c0a77efbSIgor Romanov }
3646c0a77efbSIgor Romanov
3647c0a77efbSIgor Romanov if (req.emr_out_length_used <
3648c0a77efbSIgor Romanov MC_CMD_MAE_COUNTERS_STREAM_START_OUT_LEN) {
3649c0a77efbSIgor Romanov rc = EMSGSIZE;
3650c0a77efbSIgor Romanov goto fail2;
3651c0a77efbSIgor Romanov }
3652c0a77efbSIgor Romanov
3653c0a77efbSIgor Romanov *flags_out = MCDI_OUT_DWORD(req, MAE_COUNTERS_STREAM_START_OUT_FLAGS);
3654c0a77efbSIgor Romanov
3655c0a77efbSIgor Romanov return (0);
3656c0a77efbSIgor Romanov
3657c0a77efbSIgor Romanov fail2:
3658c0a77efbSIgor Romanov EFSYS_PROBE(fail2);
3659c0a77efbSIgor Romanov fail1:
3660c0a77efbSIgor Romanov EFSYS_PROBE1(fail1, efx_rc_t, rc);
3661c0a77efbSIgor Romanov
3662c0a77efbSIgor Romanov return (rc);
3663c0a77efbSIgor Romanov }
3664c0a77efbSIgor Romanov
3665c0a77efbSIgor Romanov __checkReturn efx_rc_t
efx_mae_counters_stream_stop(__in efx_nic_t * enp,__in uint16_t rxq_id,__out_opt uint32_t * gen_countp)3666c0a77efbSIgor Romanov efx_mae_counters_stream_stop(
3667c0a77efbSIgor Romanov __in efx_nic_t *enp,
3668c0a77efbSIgor Romanov __in uint16_t rxq_id,
3669c0a77efbSIgor Romanov __out_opt uint32_t *gen_countp)
3670c0a77efbSIgor Romanov {
3671c0a77efbSIgor Romanov efx_mcdi_req_t req;
3672c0a77efbSIgor Romanov EFX_MCDI_DECLARE_BUF(payload, MC_CMD_MAE_COUNTERS_STREAM_STOP_IN_LEN,
3673c0a77efbSIgor Romanov MC_CMD_MAE_COUNTERS_STREAM_STOP_OUT_LEN);
3674c0a77efbSIgor Romanov efx_rc_t rc;
3675c0a77efbSIgor Romanov
3676c0a77efbSIgor Romanov req.emr_cmd = MC_CMD_MAE_COUNTERS_STREAM_STOP;
3677c0a77efbSIgor Romanov req.emr_in_buf = payload;
3678c0a77efbSIgor Romanov req.emr_in_length = MC_CMD_MAE_COUNTERS_STREAM_STOP_IN_LEN;
3679c0a77efbSIgor Romanov req.emr_out_buf = payload;
3680c0a77efbSIgor Romanov req.emr_out_length = MC_CMD_MAE_COUNTERS_STREAM_STOP_OUT_LEN;
3681c0a77efbSIgor Romanov
3682c0a77efbSIgor Romanov MCDI_IN_SET_WORD(req, MAE_COUNTERS_STREAM_STOP_IN_QID, rxq_id);
3683c0a77efbSIgor Romanov
3684c0a77efbSIgor Romanov efx_mcdi_execute(enp, &req);
3685c0a77efbSIgor Romanov
3686c0a77efbSIgor Romanov if (req.emr_rc != 0) {
3687c0a77efbSIgor Romanov rc = req.emr_rc;
3688c0a77efbSIgor Romanov goto fail1;
3689c0a77efbSIgor Romanov }
3690c0a77efbSIgor Romanov
3691c0a77efbSIgor Romanov if (req.emr_out_length_used <
3692c0a77efbSIgor Romanov MC_CMD_MAE_COUNTERS_STREAM_STOP_OUT_LEN) {
3693c0a77efbSIgor Romanov rc = EMSGSIZE;
3694c0a77efbSIgor Romanov goto fail2;
3695c0a77efbSIgor Romanov }
3696c0a77efbSIgor Romanov
3697c0a77efbSIgor Romanov if (gen_countp != NULL) {
3698c0a77efbSIgor Romanov *gen_countp = MCDI_OUT_DWORD(req,
3699c0a77efbSIgor Romanov MAE_COUNTERS_STREAM_STOP_OUT_GENERATION_COUNT);
3700c0a77efbSIgor Romanov }
3701c0a77efbSIgor Romanov
3702c0a77efbSIgor Romanov return (0);
3703c0a77efbSIgor Romanov
3704c0a77efbSIgor Romanov fail2:
3705c0a77efbSIgor Romanov EFSYS_PROBE(fail2);
3706c0a77efbSIgor Romanov fail1:
3707c0a77efbSIgor Romanov EFSYS_PROBE1(fail1, efx_rc_t, rc);
3708c0a77efbSIgor Romanov
3709c0a77efbSIgor Romanov return (rc);
3710c0a77efbSIgor Romanov }
3711c0a77efbSIgor Romanov
3712c0a77efbSIgor Romanov __checkReturn efx_rc_t
efx_mae_counters_stream_give_credits(__in efx_nic_t * enp,__in uint32_t n_credits)3713c0a77efbSIgor Romanov efx_mae_counters_stream_give_credits(
3714c0a77efbSIgor Romanov __in efx_nic_t *enp,
3715c0a77efbSIgor Romanov __in uint32_t n_credits)
3716c0a77efbSIgor Romanov {
3717c0a77efbSIgor Romanov efx_mcdi_req_t req;
3718c0a77efbSIgor Romanov EFX_MCDI_DECLARE_BUF(payload,
3719c0a77efbSIgor Romanov MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS_IN_LEN,
3720c0a77efbSIgor Romanov MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS_OUT_LEN);
3721c0a77efbSIgor Romanov efx_rc_t rc;
3722c0a77efbSIgor Romanov
3723c0a77efbSIgor Romanov req.emr_cmd = MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS;
3724c0a77efbSIgor Romanov req.emr_in_buf = payload;
3725c0a77efbSIgor Romanov req.emr_in_length = MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS_IN_LEN;
3726c0a77efbSIgor Romanov req.emr_out_buf = payload;
3727c0a77efbSIgor Romanov req.emr_out_length = MC_CMD_MAE_COUNTERS_STREAM_GIVE_CREDITS_OUT_LEN;
3728c0a77efbSIgor Romanov
3729c0a77efbSIgor Romanov MCDI_IN_SET_DWORD(req, MAE_COUNTERS_STREAM_GIVE_CREDITS_IN_NUM_CREDITS,
3730c0a77efbSIgor Romanov n_credits);
3731c0a77efbSIgor Romanov
3732c0a77efbSIgor Romanov efx_mcdi_execute(enp, &req);
3733c0a77efbSIgor Romanov
3734c0a77efbSIgor Romanov if (req.emr_rc != 0) {
3735c0a77efbSIgor Romanov rc = req.emr_rc;
3736c0a77efbSIgor Romanov goto fail1;
3737c0a77efbSIgor Romanov }
3738c0a77efbSIgor Romanov
3739c0a77efbSIgor Romanov return (0);
3740c0a77efbSIgor Romanov
3741c0a77efbSIgor Romanov fail1:
3742c0a77efbSIgor Romanov EFSYS_PROBE1(fail1, efx_rc_t, rc);
3743c0a77efbSIgor Romanov
3744bbc42f34SIgor Romanov return (rc);
3745bbc42f34SIgor Romanov }
3746bbc42f34SIgor Romanov
3747bbc42f34SIgor Romanov __checkReturn efx_rc_t
efx_mae_action_set_free(__in efx_nic_t * enp,__in const efx_mae_aset_id_t * aset_idp)3748e61baa82SIvan Malov efx_mae_action_set_free(
3749e61baa82SIvan Malov __in efx_nic_t *enp,
3750e61baa82SIvan Malov __in const efx_mae_aset_id_t *aset_idp)
3751e61baa82SIvan Malov {
3752e61baa82SIvan Malov const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
3753e61baa82SIvan Malov efx_mcdi_req_t req;
3754e61baa82SIvan Malov EFX_MCDI_DECLARE_BUF(payload,
3755e61baa82SIvan Malov MC_CMD_MAE_ACTION_SET_FREE_IN_LEN(1),
3756e61baa82SIvan Malov MC_CMD_MAE_ACTION_SET_FREE_OUT_LEN(1));
3757e61baa82SIvan Malov efx_rc_t rc;
3758e61baa82SIvan Malov
3759e61baa82SIvan Malov if (encp->enc_mae_supported == B_FALSE) {
3760e61baa82SIvan Malov rc = ENOTSUP;
3761e61baa82SIvan Malov goto fail1;
3762e61baa82SIvan Malov }
3763e61baa82SIvan Malov
3764e61baa82SIvan Malov req.emr_cmd = MC_CMD_MAE_ACTION_SET_FREE;
3765e61baa82SIvan Malov req.emr_in_buf = payload;
3766e61baa82SIvan Malov req.emr_in_length = MC_CMD_MAE_ACTION_SET_FREE_IN_LEN(1);
3767e61baa82SIvan Malov req.emr_out_buf = payload;
3768e61baa82SIvan Malov req.emr_out_length = MC_CMD_MAE_ACTION_SET_FREE_OUT_LEN(1);
3769e61baa82SIvan Malov
3770e61baa82SIvan Malov MCDI_IN_SET_DWORD(req, MAE_ACTION_SET_FREE_IN_AS_ID, aset_idp->id);
3771e61baa82SIvan Malov
3772e61baa82SIvan Malov efx_mcdi_execute(enp, &req);
3773e61baa82SIvan Malov
3774e61baa82SIvan Malov if (req.emr_rc != 0) {
3775e61baa82SIvan Malov rc = req.emr_rc;
3776e61baa82SIvan Malov goto fail2;
3777e61baa82SIvan Malov }
3778e61baa82SIvan Malov
3779e27950a0SAndy Moreton if (req.emr_out_length_used < MC_CMD_MAE_ACTION_SET_FREE_OUT_LENMIN) {
3780e27950a0SAndy Moreton rc = EMSGSIZE;
3781e27950a0SAndy Moreton goto fail3;
3782e27950a0SAndy Moreton }
3783e27950a0SAndy Moreton
3784e61baa82SIvan Malov if (MCDI_OUT_DWORD(req, MAE_ACTION_SET_FREE_OUT_FREED_AS_ID) !=
3785e61baa82SIvan Malov aset_idp->id) {
3786e61baa82SIvan Malov /* Firmware failed to free the action set. */
3787e61baa82SIvan Malov rc = EAGAIN;
3788e27950a0SAndy Moreton goto fail4;
3789e61baa82SIvan Malov }
3790e61baa82SIvan Malov
3791e61baa82SIvan Malov return (0);
3792e61baa82SIvan Malov
3793e27950a0SAndy Moreton fail4:
3794e27950a0SAndy Moreton EFSYS_PROBE(fail4);
3795e61baa82SIvan Malov fail3:
3796e61baa82SIvan Malov EFSYS_PROBE(fail3);
3797e61baa82SIvan Malov fail2:
3798e61baa82SIvan Malov EFSYS_PROBE(fail2);
3799e61baa82SIvan Malov fail1:
3800e61baa82SIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
3801e61baa82SIvan Malov return (rc);
3802e61baa82SIvan Malov }
3803e61baa82SIvan Malov
3804b4fac347SIvan Malov __checkReturn efx_rc_t
efx_mae_action_rule_insert(__in efx_nic_t * enp,__in const efx_mae_match_spec_t * spec,__in const efx_mae_aset_list_id_t * asl_idp,__in const efx_mae_aset_id_t * as_idp,__out efx_mae_rule_id_t * ar_idp)3805b4fac347SIvan Malov efx_mae_action_rule_insert(
3806b4fac347SIvan Malov __in efx_nic_t *enp,
3807b4fac347SIvan Malov __in const efx_mae_match_spec_t *spec,
3808b4fac347SIvan Malov __in const efx_mae_aset_list_id_t *asl_idp,
3809b4fac347SIvan Malov __in const efx_mae_aset_id_t *as_idp,
3810b4fac347SIvan Malov __out efx_mae_rule_id_t *ar_idp)
3811b4fac347SIvan Malov {
3812b4fac347SIvan Malov const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
3813b4fac347SIvan Malov efx_mcdi_req_t req;
3814b4fac347SIvan Malov EFX_MCDI_DECLARE_BUF(payload,
3815b4fac347SIvan Malov MC_CMD_MAE_ACTION_RULE_INSERT_IN_LENMAX_MCDI2,
3816b4fac347SIvan Malov MC_CMD_MAE_ACTION_RULE_INSERT_OUT_LEN);
3817b4fac347SIvan Malov efx_oword_t *rule_response;
3818b4fac347SIvan Malov efx_mae_rule_id_t ar_id;
3819b4fac347SIvan Malov size_t offset;
3820b4fac347SIvan Malov efx_rc_t rc;
3821b4fac347SIvan Malov
3822b4fac347SIvan Malov EFX_STATIC_ASSERT(sizeof (ar_idp->id) ==
3823b4fac347SIvan Malov MC_CMD_MAE_ACTION_RULE_INSERT_OUT_AR_ID_LEN);
3824b4fac347SIvan Malov
3825b4fac347SIvan Malov EFX_STATIC_ASSERT(EFX_MAE_RSRC_ID_INVALID ==
3826b4fac347SIvan Malov MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL);
3827b4fac347SIvan Malov
3828b4fac347SIvan Malov if (encp->enc_mae_supported == B_FALSE) {
3829b4fac347SIvan Malov rc = ENOTSUP;
3830b4fac347SIvan Malov goto fail1;
3831b4fac347SIvan Malov }
3832b4fac347SIvan Malov
3833b4fac347SIvan Malov if (spec->emms_type != EFX_MAE_RULE_ACTION ||
3834b4fac347SIvan Malov (asl_idp != NULL && as_idp != NULL) ||
3835b4fac347SIvan Malov (asl_idp == NULL && as_idp == NULL)) {
3836b4fac347SIvan Malov rc = EINVAL;
3837b4fac347SIvan Malov goto fail2;
3838b4fac347SIvan Malov }
3839b4fac347SIvan Malov
3840b4fac347SIvan Malov req.emr_cmd = MC_CMD_MAE_ACTION_RULE_INSERT;
3841b4fac347SIvan Malov req.emr_in_buf = payload;
3842b4fac347SIvan Malov req.emr_in_length = MC_CMD_MAE_ACTION_RULE_INSERT_IN_LENMAX_MCDI2;
3843b4fac347SIvan Malov req.emr_out_buf = payload;
3844b4fac347SIvan Malov req.emr_out_length = MC_CMD_MAE_ACTION_RULE_INSERT_OUT_LEN;
3845b4fac347SIvan Malov
3846b4fac347SIvan Malov EFX_STATIC_ASSERT(sizeof (*rule_response) <=
3847b4fac347SIvan Malov MC_CMD_MAE_ACTION_RULE_INSERT_IN_RESPONSE_LEN);
3848b4fac347SIvan Malov offset = MC_CMD_MAE_ACTION_RULE_INSERT_IN_RESPONSE_OFST;
3849b4fac347SIvan Malov rule_response = (efx_oword_t *)(payload + offset);
3850b4fac347SIvan Malov EFX_POPULATE_OWORD_3(*rule_response,
3851b4fac347SIvan Malov MAE_ACTION_RULE_RESPONSE_ASL_ID,
3852b4fac347SIvan Malov (asl_idp != NULL) ? asl_idp->id : EFX_MAE_RSRC_ID_INVALID,
3853b4fac347SIvan Malov MAE_ACTION_RULE_RESPONSE_AS_ID,
3854b4fac347SIvan Malov (as_idp != NULL) ? as_idp->id : EFX_MAE_RSRC_ID_INVALID,
3855b4fac347SIvan Malov MAE_ACTION_RULE_RESPONSE_COUNTER_ID, EFX_MAE_RSRC_ID_INVALID);
3856b4fac347SIvan Malov
3857b4fac347SIvan Malov MCDI_IN_SET_DWORD(req, MAE_ACTION_RULE_INSERT_IN_PRIO, spec->emms_prio);
3858b4fac347SIvan Malov
3859b4fac347SIvan Malov /*
3860b4fac347SIvan Malov * Mask-value pairs have been stored in the byte order needed for the
3861b4fac347SIvan Malov * MCDI request and are thus safe to be copied directly to the buffer.
3862b4fac347SIvan Malov */
3863b4fac347SIvan Malov EFX_STATIC_ASSERT(sizeof (spec->emms_mask_value_pairs.action) >=
386437907899SIvan Malov MAE_FIELD_MASK_VALUE_PAIRS_V2_LEN);
3865b4fac347SIvan Malov offset = MC_CMD_MAE_ACTION_RULE_INSERT_IN_MATCH_CRITERIA_OFST;
3866b4fac347SIvan Malov memcpy(payload + offset, spec->emms_mask_value_pairs.action,
386737907899SIvan Malov MAE_FIELD_MASK_VALUE_PAIRS_V2_LEN);
3868b4fac347SIvan Malov
3869b4fac347SIvan Malov efx_mcdi_execute(enp, &req);
3870b4fac347SIvan Malov
3871b4fac347SIvan Malov if (req.emr_rc != 0) {
3872b4fac347SIvan Malov rc = req.emr_rc;
3873b4fac347SIvan Malov goto fail3;
3874b4fac347SIvan Malov }
3875b4fac347SIvan Malov
3876b4fac347SIvan Malov if (req.emr_out_length_used < MC_CMD_MAE_ACTION_RULE_INSERT_OUT_LEN) {
3877b4fac347SIvan Malov rc = EMSGSIZE;
3878b4fac347SIvan Malov goto fail4;
3879b4fac347SIvan Malov }
3880b4fac347SIvan Malov
3881b4fac347SIvan Malov ar_id.id = MCDI_OUT_DWORD(req, MAE_ACTION_RULE_INSERT_OUT_AR_ID);
3882b4fac347SIvan Malov if (ar_id.id == EFX_MAE_RSRC_ID_INVALID) {
3883b4fac347SIvan Malov rc = ENOENT;
3884b4fac347SIvan Malov goto fail5;
3885b4fac347SIvan Malov }
3886b4fac347SIvan Malov
3887b4fac347SIvan Malov ar_idp->id = ar_id.id;
3888b4fac347SIvan Malov
3889b4fac347SIvan Malov return (0);
3890b4fac347SIvan Malov
3891b4fac347SIvan Malov fail5:
3892b4fac347SIvan Malov EFSYS_PROBE(fail5);
3893b4fac347SIvan Malov fail4:
3894b4fac347SIvan Malov EFSYS_PROBE(fail4);
3895b4fac347SIvan Malov fail3:
3896b4fac347SIvan Malov EFSYS_PROBE(fail3);
3897b4fac347SIvan Malov fail2:
3898b4fac347SIvan Malov EFSYS_PROBE(fail2);
3899b4fac347SIvan Malov fail1:
3900b4fac347SIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
3901b4fac347SIvan Malov return (rc);
3902b4fac347SIvan Malov }
3903b4fac347SIvan Malov
3904b4fac347SIvan Malov __checkReturn efx_rc_t
efx_mae_action_rule_remove(__in efx_nic_t * enp,__in const efx_mae_rule_id_t * ar_idp)3905b4fac347SIvan Malov efx_mae_action_rule_remove(
3906b4fac347SIvan Malov __in efx_nic_t *enp,
3907b4fac347SIvan Malov __in const efx_mae_rule_id_t *ar_idp)
3908b4fac347SIvan Malov {
3909b4fac347SIvan Malov const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
3910b4fac347SIvan Malov efx_mcdi_req_t req;
3911b4fac347SIvan Malov EFX_MCDI_DECLARE_BUF(payload,
3912b4fac347SIvan Malov MC_CMD_MAE_ACTION_RULE_DELETE_IN_LEN(1),
3913b4fac347SIvan Malov MC_CMD_MAE_ACTION_RULE_DELETE_OUT_LEN(1));
3914b4fac347SIvan Malov efx_rc_t rc;
3915b4fac347SIvan Malov
3916b4fac347SIvan Malov if (encp->enc_mae_supported == B_FALSE) {
3917b4fac347SIvan Malov rc = ENOTSUP;
3918b4fac347SIvan Malov goto fail1;
3919b4fac347SIvan Malov }
3920b4fac347SIvan Malov
3921b4fac347SIvan Malov req.emr_cmd = MC_CMD_MAE_ACTION_RULE_DELETE;
3922b4fac347SIvan Malov req.emr_in_buf = payload;
3923b4fac347SIvan Malov req.emr_in_length = MC_CMD_MAE_ACTION_RULE_DELETE_IN_LEN(1);
3924b4fac347SIvan Malov req.emr_out_buf = payload;
3925b4fac347SIvan Malov req.emr_out_length = MC_CMD_MAE_ACTION_RULE_DELETE_OUT_LEN(1);
3926b4fac347SIvan Malov
3927b4fac347SIvan Malov MCDI_IN_SET_DWORD(req, MAE_ACTION_RULE_DELETE_IN_AR_ID, ar_idp->id);
3928b4fac347SIvan Malov
3929b4fac347SIvan Malov efx_mcdi_execute(enp, &req);
3930b4fac347SIvan Malov
3931b4fac347SIvan Malov if (req.emr_rc != 0) {
3932b4fac347SIvan Malov rc = req.emr_rc;
3933b4fac347SIvan Malov goto fail2;
3934b4fac347SIvan Malov }
3935b4fac347SIvan Malov
3936e27950a0SAndy Moreton if (req.emr_out_length_used <
3937e27950a0SAndy Moreton MC_CMD_MAE_ACTION_RULE_DELETE_OUT_LENMIN) {
3938e27950a0SAndy Moreton rc = EMSGSIZE;
3939e27950a0SAndy Moreton goto fail3;
3940e27950a0SAndy Moreton }
3941e27950a0SAndy Moreton
3942b4fac347SIvan Malov if (MCDI_OUT_DWORD(req, MAE_ACTION_RULE_DELETE_OUT_DELETED_AR_ID) !=
3943b4fac347SIvan Malov ar_idp->id) {
3944b4fac347SIvan Malov /* Firmware failed to delete the action rule. */
3945b4fac347SIvan Malov rc = EAGAIN;
3946e27950a0SAndy Moreton goto fail4;
3947b4fac347SIvan Malov }
3948b4fac347SIvan Malov
3949b4fac347SIvan Malov return (0);
3950b4fac347SIvan Malov
3951e27950a0SAndy Moreton fail4:
3952e27950a0SAndy Moreton EFSYS_PROBE(fail4);
3953b4fac347SIvan Malov fail3:
3954b4fac347SIvan Malov EFSYS_PROBE(fail3);
3955b4fac347SIvan Malov fail2:
3956b4fac347SIvan Malov EFSYS_PROBE(fail2);
3957b4fac347SIvan Malov fail1:
3958b4fac347SIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
3959b4fac347SIvan Malov return (rc);
3960b4fac347SIvan Malov }
3961b4fac347SIvan Malov
396292030a61SIgor Romanov __checkReturn efx_rc_t
efx_mcdi_mport_alloc_alias(__in efx_nic_t * enp,__out efx_mport_id_t * mportp,__out_opt uint32_t * labelp)396392030a61SIgor Romanov efx_mcdi_mport_alloc_alias(
396492030a61SIgor Romanov __in efx_nic_t *enp,
396592030a61SIgor Romanov __out efx_mport_id_t *mportp,
396692030a61SIgor Romanov __out_opt uint32_t *labelp)
396792030a61SIgor Romanov {
396892030a61SIgor Romanov const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
396992030a61SIgor Romanov efx_mcdi_req_t req;
397092030a61SIgor Romanov EFX_MCDI_DECLARE_BUF(payload,
397192030a61SIgor Romanov MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN_LEN,
397292030a61SIgor Romanov MC_CMD_MAE_MPORT_ALLOC_ALIAS_OUT_LEN);
397392030a61SIgor Romanov efx_rc_t rc;
397492030a61SIgor Romanov
397592030a61SIgor Romanov if (encp->enc_mae_supported == B_FALSE) {
397692030a61SIgor Romanov rc = ENOTSUP;
397792030a61SIgor Romanov goto fail1;
397892030a61SIgor Romanov }
397992030a61SIgor Romanov
398092030a61SIgor Romanov req.emr_cmd = MC_CMD_MAE_MPORT_ALLOC;
398192030a61SIgor Romanov req.emr_in_buf = payload;
398292030a61SIgor Romanov req.emr_in_length = MC_CMD_MAE_MPORT_ALLOC_ALIAS_IN_LEN;
398392030a61SIgor Romanov req.emr_out_buf = payload;
398492030a61SIgor Romanov req.emr_out_length = MC_CMD_MAE_MPORT_ALLOC_ALIAS_OUT_LEN;
398592030a61SIgor Romanov
398692030a61SIgor Romanov MCDI_IN_SET_DWORD(req, MAE_MPORT_ALLOC_IN_TYPE,
398792030a61SIgor Romanov MC_CMD_MAE_MPORT_ALLOC_IN_MPORT_TYPE_ALIAS);
398892030a61SIgor Romanov MCDI_IN_SET_DWORD(req, MAE_MPORT_ALLOC_ALIAS_IN_DELIVER_MPORT,
398992030a61SIgor Romanov MAE_MPORT_SELECTOR_ASSIGNED);
399092030a61SIgor Romanov
399192030a61SIgor Romanov efx_mcdi_execute(enp, &req);
399292030a61SIgor Romanov
399392030a61SIgor Romanov if (req.emr_rc != 0) {
399492030a61SIgor Romanov rc = req.emr_rc;
399592030a61SIgor Romanov goto fail2;
399692030a61SIgor Romanov }
399792030a61SIgor Romanov
399892030a61SIgor Romanov mportp->id = MCDI_OUT_DWORD(req, MAE_MPORT_ALLOC_OUT_MPORT_ID);
399992030a61SIgor Romanov if (labelp != NULL)
400092030a61SIgor Romanov *labelp = MCDI_OUT_DWORD(req, MAE_MPORT_ALLOC_ALIAS_OUT_LABEL);
400192030a61SIgor Romanov
400292030a61SIgor Romanov return (0);
400392030a61SIgor Romanov
400492030a61SIgor Romanov fail2:
400592030a61SIgor Romanov EFSYS_PROBE(fail2);
400692030a61SIgor Romanov fail1:
400792030a61SIgor Romanov EFSYS_PROBE1(fail1, efx_rc_t, rc);
400892030a61SIgor Romanov return (rc);
400992030a61SIgor Romanov }
401092030a61SIgor Romanov
401192030a61SIgor Romanov __checkReturn efx_rc_t
efx_mae_mport_free(__in efx_nic_t * enp,__in const efx_mport_id_t * mportp)401292030a61SIgor Romanov efx_mae_mport_free(
401392030a61SIgor Romanov __in efx_nic_t *enp,
401492030a61SIgor Romanov __in const efx_mport_id_t *mportp)
401592030a61SIgor Romanov {
401692030a61SIgor Romanov const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
401792030a61SIgor Romanov efx_mcdi_req_t req;
401892030a61SIgor Romanov EFX_MCDI_DECLARE_BUF(payload,
401992030a61SIgor Romanov MC_CMD_MAE_MPORT_FREE_IN_LEN,
402092030a61SIgor Romanov MC_CMD_MAE_MPORT_FREE_OUT_LEN);
402192030a61SIgor Romanov efx_rc_t rc;
402292030a61SIgor Romanov
402392030a61SIgor Romanov if (encp->enc_mae_supported == B_FALSE) {
402492030a61SIgor Romanov rc = ENOTSUP;
402592030a61SIgor Romanov goto fail1;
402692030a61SIgor Romanov }
402792030a61SIgor Romanov
402892030a61SIgor Romanov req.emr_cmd = MC_CMD_MAE_MPORT_FREE;
402992030a61SIgor Romanov req.emr_in_buf = payload;
403092030a61SIgor Romanov req.emr_in_length = MC_CMD_MAE_MPORT_FREE_IN_LEN;
403192030a61SIgor Romanov req.emr_out_buf = payload;
403292030a61SIgor Romanov req.emr_out_length = MC_CMD_MAE_MPORT_FREE_OUT_LEN;
403392030a61SIgor Romanov
403492030a61SIgor Romanov MCDI_IN_SET_DWORD(req, MAE_MPORT_FREE_IN_MPORT_ID, mportp->id);
403592030a61SIgor Romanov
403692030a61SIgor Romanov efx_mcdi_execute(enp, &req);
403792030a61SIgor Romanov
403892030a61SIgor Romanov if (req.emr_rc != 0) {
403992030a61SIgor Romanov rc = req.emr_rc;
404092030a61SIgor Romanov goto fail2;
404192030a61SIgor Romanov }
404292030a61SIgor Romanov
404392030a61SIgor Romanov return (0);
404492030a61SIgor Romanov
404592030a61SIgor Romanov fail2:
404692030a61SIgor Romanov EFSYS_PROBE(fail2);
404792030a61SIgor Romanov fail1:
404892030a61SIgor Romanov EFSYS_PROBE1(fail1, efx_rc_t, rc);
404992030a61SIgor Romanov return (rc);
405092030a61SIgor Romanov }
405192030a61SIgor Romanov
405223748069SViacheslav Galaktionov static __checkReturn efx_rc_t
efx_mae_read_mport_journal_single(__in uint8_t * entry_buf,__out efx_mport_desc_t * desc)405323748069SViacheslav Galaktionov efx_mae_read_mport_journal_single(
405423748069SViacheslav Galaktionov __in uint8_t *entry_buf,
405523748069SViacheslav Galaktionov __out efx_mport_desc_t *desc)
405623748069SViacheslav Galaktionov {
405723748069SViacheslav Galaktionov uint32_t pcie_intf;
405823748069SViacheslav Galaktionov efx_rc_t rc;
405923748069SViacheslav Galaktionov
406023748069SViacheslav Galaktionov memset(desc, 0, sizeof (*desc));
406123748069SViacheslav Galaktionov
406223748069SViacheslav Galaktionov desc->emd_id.id = MCDI_STRUCT_DWORD(entry_buf,
406323748069SViacheslav Galaktionov MAE_MPORT_DESC_V2_MPORT_ID);
406423748069SViacheslav Galaktionov
406523748069SViacheslav Galaktionov desc->emd_can_receive_on = MCDI_STRUCT_DWORD_FIELD(entry_buf,
406623748069SViacheslav Galaktionov MAE_MPORT_DESC_V2_FLAGS,
406723748069SViacheslav Galaktionov MAE_MPORT_DESC_V2_CAN_RECEIVE_ON);
406823748069SViacheslav Galaktionov
406923748069SViacheslav Galaktionov desc->emd_can_deliver_to = MCDI_STRUCT_DWORD_FIELD(entry_buf,
407023748069SViacheslav Galaktionov MAE_MPORT_DESC_V2_FLAGS,
407123748069SViacheslav Galaktionov MAE_MPORT_DESC_V2_CAN_DELIVER_TO);
407223748069SViacheslav Galaktionov
407323748069SViacheslav Galaktionov desc->emd_can_delete = MCDI_STRUCT_DWORD_FIELD(entry_buf,
407423748069SViacheslav Galaktionov MAE_MPORT_DESC_V2_FLAGS,
407523748069SViacheslav Galaktionov MAE_MPORT_DESC_V2_CAN_DELETE);
407623748069SViacheslav Galaktionov
407723748069SViacheslav Galaktionov desc->emd_zombie = MCDI_STRUCT_DWORD_FIELD(entry_buf,
407823748069SViacheslav Galaktionov MAE_MPORT_DESC_V2_FLAGS,
407923748069SViacheslav Galaktionov MAE_MPORT_DESC_V2_IS_ZOMBIE);
408023748069SViacheslav Galaktionov
408123748069SViacheslav Galaktionov desc->emd_type = MCDI_STRUCT_DWORD(entry_buf,
408223748069SViacheslav Galaktionov MAE_MPORT_DESC_V2_MPORT_TYPE);
408323748069SViacheslav Galaktionov
408423748069SViacheslav Galaktionov /*
408523748069SViacheslav Galaktionov * We can't check everything here. If some additional checks are
408623748069SViacheslav Galaktionov * required, they should be performed by the callback function.
408723748069SViacheslav Galaktionov */
408823748069SViacheslav Galaktionov switch (desc->emd_type) {
408923748069SViacheslav Galaktionov case EFX_MPORT_TYPE_NET_PORT:
409023748069SViacheslav Galaktionov desc->emd_net_port.ep_index =
409123748069SViacheslav Galaktionov MCDI_STRUCT_DWORD(entry_buf,
409223748069SViacheslav Galaktionov MAE_MPORT_DESC_V2_NET_PORT_IDX);
409323748069SViacheslav Galaktionov break;
409423748069SViacheslav Galaktionov case EFX_MPORT_TYPE_ALIAS:
409523748069SViacheslav Galaktionov desc->emd_alias.ea_target_mport_id.id =
409623748069SViacheslav Galaktionov MCDI_STRUCT_DWORD(entry_buf,
409723748069SViacheslav Galaktionov MAE_MPORT_DESC_V2_ALIAS_DELIVER_MPORT_ID);
409823748069SViacheslav Galaktionov break;
409923748069SViacheslav Galaktionov case EFX_MPORT_TYPE_VNIC:
410023748069SViacheslav Galaktionov desc->emd_vnic.ev_client_type =
410123748069SViacheslav Galaktionov MCDI_STRUCT_DWORD(entry_buf,
410223748069SViacheslav Galaktionov MAE_MPORT_DESC_V2_VNIC_CLIENT_TYPE);
410323748069SViacheslav Galaktionov if (desc->emd_vnic.ev_client_type !=
410423748069SViacheslav Galaktionov EFX_MPORT_VNIC_CLIENT_FUNCTION)
410523748069SViacheslav Galaktionov break;
410623748069SViacheslav Galaktionov
410723748069SViacheslav Galaktionov pcie_intf = MCDI_STRUCT_DWORD(entry_buf,
410823748069SViacheslav Galaktionov MAE_MPORT_DESC_V2_VNIC_FUNCTION_INTERFACE);
410923748069SViacheslav Galaktionov rc = efx_mcdi_intf_from_pcie(pcie_intf,
411023748069SViacheslav Galaktionov &desc->emd_vnic.ev_intf);
411123748069SViacheslav Galaktionov if (rc != 0)
411223748069SViacheslav Galaktionov goto fail1;
411323748069SViacheslav Galaktionov
411423748069SViacheslav Galaktionov desc->emd_vnic.ev_pf = MCDI_STRUCT_WORD(entry_buf,
411523748069SViacheslav Galaktionov MAE_MPORT_DESC_V2_VNIC_FUNCTION_PF_IDX);
411623748069SViacheslav Galaktionov desc->emd_vnic.ev_vf = MCDI_STRUCT_WORD(entry_buf,
411723748069SViacheslav Galaktionov MAE_MPORT_DESC_V2_VNIC_FUNCTION_VF_IDX);
411823748069SViacheslav Galaktionov desc->emd_vnic.ev_handle = MCDI_STRUCT_DWORD(entry_buf,
411923748069SViacheslav Galaktionov MAE_MPORT_DESC_V2_VNIC_CLIENT_HANDLE);
412023748069SViacheslav Galaktionov break;
412123748069SViacheslav Galaktionov default:
412223748069SViacheslav Galaktionov rc = EINVAL;
412323748069SViacheslav Galaktionov goto fail2;
412423748069SViacheslav Galaktionov }
412523748069SViacheslav Galaktionov
412623748069SViacheslav Galaktionov return (0);
412723748069SViacheslav Galaktionov
412823748069SViacheslav Galaktionov fail2:
412923748069SViacheslav Galaktionov EFSYS_PROBE(fail2);
413023748069SViacheslav Galaktionov fail1:
413123748069SViacheslav Galaktionov EFSYS_PROBE1(fail1, efx_rc_t, rc);
413223748069SViacheslav Galaktionov return (rc);
413323748069SViacheslav Galaktionov }
413423748069SViacheslav Galaktionov
413523748069SViacheslav Galaktionov static __checkReturn efx_rc_t
efx_mae_read_mport_journal_batch(__in efx_nic_t * enp,__in efx_mae_read_mport_journal_cb * cbp,__in void * cb_datap,__out uint32_t * morep)413623748069SViacheslav Galaktionov efx_mae_read_mport_journal_batch(
413723748069SViacheslav Galaktionov __in efx_nic_t *enp,
413823748069SViacheslav Galaktionov __in efx_mae_read_mport_journal_cb *cbp,
413923748069SViacheslav Galaktionov __in void *cb_datap,
414023748069SViacheslav Galaktionov __out uint32_t *morep)
414123748069SViacheslav Galaktionov {
414223748069SViacheslav Galaktionov efx_mcdi_req_t req;
414323748069SViacheslav Galaktionov EFX_MCDI_DECLARE_BUF(payload,
414423748069SViacheslav Galaktionov MC_CMD_MAE_MPORT_READ_JOURNAL_IN_LEN,
414523748069SViacheslav Galaktionov MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_LENMAX_MCDI2);
414623748069SViacheslav Galaktionov uint32_t n_entries;
414723748069SViacheslav Galaktionov uint32_t entry_sz;
414823748069SViacheslav Galaktionov uint8_t *entry_buf;
414923748069SViacheslav Galaktionov unsigned int i;
415023748069SViacheslav Galaktionov efx_rc_t rc;
415123748069SViacheslav Galaktionov
415223748069SViacheslav Galaktionov EFX_STATIC_ASSERT(EFX_MPORT_TYPE_NET_PORT ==
415323748069SViacheslav Galaktionov MAE_MPORT_DESC_V2_MPORT_TYPE_NET_PORT);
415423748069SViacheslav Galaktionov EFX_STATIC_ASSERT(EFX_MPORT_TYPE_ALIAS ==
415523748069SViacheslav Galaktionov MAE_MPORT_DESC_V2_MPORT_TYPE_ALIAS);
415623748069SViacheslav Galaktionov EFX_STATIC_ASSERT(EFX_MPORT_TYPE_VNIC ==
415723748069SViacheslav Galaktionov MAE_MPORT_DESC_V2_MPORT_TYPE_VNIC);
415823748069SViacheslav Galaktionov
415923748069SViacheslav Galaktionov EFX_STATIC_ASSERT(EFX_MPORT_VNIC_CLIENT_FUNCTION ==
416023748069SViacheslav Galaktionov MAE_MPORT_DESC_V2_VNIC_CLIENT_TYPE_FUNCTION);
416123748069SViacheslav Galaktionov EFX_STATIC_ASSERT(EFX_MPORT_VNIC_CLIENT_PLUGIN ==
416223748069SViacheslav Galaktionov MAE_MPORT_DESC_V2_VNIC_CLIENT_TYPE_PLUGIN);
416323748069SViacheslav Galaktionov
416423748069SViacheslav Galaktionov if (cbp == NULL) {
416523748069SViacheslav Galaktionov rc = EINVAL;
416623748069SViacheslav Galaktionov goto fail1;
416723748069SViacheslav Galaktionov }
416823748069SViacheslav Galaktionov
416923748069SViacheslav Galaktionov req.emr_cmd = MC_CMD_MAE_MPORT_READ_JOURNAL;
417023748069SViacheslav Galaktionov req.emr_in_buf = payload;
417123748069SViacheslav Galaktionov req.emr_in_length = MC_CMD_MAE_MPORT_READ_JOURNAL_IN_LEN;
417223748069SViacheslav Galaktionov req.emr_out_buf = payload;
417323748069SViacheslav Galaktionov req.emr_out_length = MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_LENMAX_MCDI2;
417423748069SViacheslav Galaktionov
417523748069SViacheslav Galaktionov MCDI_IN_SET_DWORD(req, MAE_MPORT_READ_JOURNAL_IN_FLAGS, 0);
417623748069SViacheslav Galaktionov
417723748069SViacheslav Galaktionov efx_mcdi_execute(enp, &req);
417823748069SViacheslav Galaktionov
417923748069SViacheslav Galaktionov if (req.emr_rc != 0) {
418023748069SViacheslav Galaktionov rc = req.emr_rc;
418123748069SViacheslav Galaktionov goto fail2;
418223748069SViacheslav Galaktionov }
418323748069SViacheslav Galaktionov
418423748069SViacheslav Galaktionov if (req.emr_out_length_used <
418523748069SViacheslav Galaktionov MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_LENMIN) {
418623748069SViacheslav Galaktionov rc = EMSGSIZE;
418723748069SViacheslav Galaktionov goto fail3;
418823748069SViacheslav Galaktionov }
418923748069SViacheslav Galaktionov
419023748069SViacheslav Galaktionov if (morep != NULL) {
419123748069SViacheslav Galaktionov *morep = MCDI_OUT_DWORD_FIELD(req,
419223748069SViacheslav Galaktionov MAE_MPORT_READ_JOURNAL_OUT_FLAGS,
419323748069SViacheslav Galaktionov MAE_MPORT_READ_JOURNAL_OUT_MORE);
419423748069SViacheslav Galaktionov }
419523748069SViacheslav Galaktionov n_entries = MCDI_OUT_DWORD(req,
419623748069SViacheslav Galaktionov MAE_MPORT_READ_JOURNAL_OUT_MPORT_DESC_COUNT);
419723748069SViacheslav Galaktionov entry_sz = MCDI_OUT_DWORD(req,
419823748069SViacheslav Galaktionov MAE_MPORT_READ_JOURNAL_OUT_SIZEOF_MPORT_DESC);
419923748069SViacheslav Galaktionov entry_buf = MCDI_OUT2(req, uint8_t,
420023748069SViacheslav Galaktionov MAE_MPORT_READ_JOURNAL_OUT_MPORT_DESC_DATA);
420123748069SViacheslav Galaktionov
420223748069SViacheslav Galaktionov if (entry_sz < MAE_MPORT_DESC_V2_VNIC_CLIENT_HANDLE_OFST +
420323748069SViacheslav Galaktionov MAE_MPORT_DESC_V2_VNIC_CLIENT_HANDLE_LEN) {
420423748069SViacheslav Galaktionov rc = EINVAL;
420523748069SViacheslav Galaktionov goto fail4;
420623748069SViacheslav Galaktionov }
420723748069SViacheslav Galaktionov if (n_entries * entry_sz / entry_sz != n_entries) {
420823748069SViacheslav Galaktionov rc = EINVAL;
420923748069SViacheslav Galaktionov goto fail5;
421023748069SViacheslav Galaktionov }
421123748069SViacheslav Galaktionov if (req.emr_out_length_used !=
421223748069SViacheslav Galaktionov MC_CMD_MAE_MPORT_READ_JOURNAL_OUT_LENMIN + n_entries * entry_sz) {
421323748069SViacheslav Galaktionov rc = EINVAL;
421423748069SViacheslav Galaktionov goto fail6;
421523748069SViacheslav Galaktionov }
421623748069SViacheslav Galaktionov
421723748069SViacheslav Galaktionov for (i = 0; i < n_entries; i++) {
421823748069SViacheslav Galaktionov efx_mport_desc_t desc;
421923748069SViacheslav Galaktionov
422023748069SViacheslav Galaktionov rc = efx_mae_read_mport_journal_single(entry_buf, &desc);
422123748069SViacheslav Galaktionov if (rc != 0)
422223748069SViacheslav Galaktionov continue;
422323748069SViacheslav Galaktionov
422423748069SViacheslav Galaktionov (*cbp)(cb_datap, &desc, sizeof (desc));
422523748069SViacheslav Galaktionov entry_buf += entry_sz;
422623748069SViacheslav Galaktionov }
422723748069SViacheslav Galaktionov
422823748069SViacheslav Galaktionov return (0);
422923748069SViacheslav Galaktionov
423023748069SViacheslav Galaktionov fail6:
423123748069SViacheslav Galaktionov EFSYS_PROBE(fail6);
423223748069SViacheslav Galaktionov fail5:
423323748069SViacheslav Galaktionov EFSYS_PROBE(fail5);
423423748069SViacheslav Galaktionov fail4:
423523748069SViacheslav Galaktionov EFSYS_PROBE(fail4);
423623748069SViacheslav Galaktionov fail3:
423723748069SViacheslav Galaktionov EFSYS_PROBE(fail3);
423823748069SViacheslav Galaktionov fail2:
423923748069SViacheslav Galaktionov EFSYS_PROBE(fail2);
424023748069SViacheslav Galaktionov fail1:
424123748069SViacheslav Galaktionov EFSYS_PROBE1(fail1, efx_rc_t, rc);
424223748069SViacheslav Galaktionov return (rc);
424323748069SViacheslav Galaktionov }
424423748069SViacheslav Galaktionov
424523748069SViacheslav Galaktionov __checkReturn efx_rc_t
efx_mae_read_mport_journal(__in efx_nic_t * enp,__in efx_mae_read_mport_journal_cb * cbp,__in void * cb_datap)424623748069SViacheslav Galaktionov efx_mae_read_mport_journal(
424723748069SViacheslav Galaktionov __in efx_nic_t *enp,
424823748069SViacheslav Galaktionov __in efx_mae_read_mport_journal_cb *cbp,
424923748069SViacheslav Galaktionov __in void *cb_datap)
425023748069SViacheslav Galaktionov {
425123748069SViacheslav Galaktionov const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
425223748069SViacheslav Galaktionov uint32_t more = 0;
425323748069SViacheslav Galaktionov efx_rc_t rc;
425423748069SViacheslav Galaktionov
425523748069SViacheslav Galaktionov if (encp->enc_mae_supported == B_FALSE) {
425623748069SViacheslav Galaktionov rc = ENOTSUP;
425723748069SViacheslav Galaktionov goto fail1;
425823748069SViacheslav Galaktionov }
425923748069SViacheslav Galaktionov
426023748069SViacheslav Galaktionov do {
426123748069SViacheslav Galaktionov rc = efx_mae_read_mport_journal_batch(enp, cbp, cb_datap,
426223748069SViacheslav Galaktionov &more);
426323748069SViacheslav Galaktionov if (rc != 0)
426423748069SViacheslav Galaktionov goto fail2;
426523748069SViacheslav Galaktionov } while (more != 0);
426623748069SViacheslav Galaktionov
426723748069SViacheslav Galaktionov return (0);
426823748069SViacheslav Galaktionov
426923748069SViacheslav Galaktionov fail2:
427023748069SViacheslav Galaktionov EFSYS_PROBE(fail2);
427123748069SViacheslav Galaktionov fail1:
427223748069SViacheslav Galaktionov EFSYS_PROBE1(fail1, efx_rc_t, rc);
427323748069SViacheslav Galaktionov return (rc);
427423748069SViacheslav Galaktionov }
427523748069SViacheslav Galaktionov
4276*002f591fSIvan Malov __checkReturn efx_rc_t
efx_mae_action_set_replay(__in efx_nic_t * enp,__in const efx_mae_actions_t * spec_orig,__out efx_mae_actions_t ** spec_clonep)4277*002f591fSIvan Malov efx_mae_action_set_replay(
4278*002f591fSIvan Malov __in efx_nic_t *enp,
4279*002f591fSIvan Malov __in const efx_mae_actions_t *spec_orig,
4280*002f591fSIvan Malov __out efx_mae_actions_t **spec_clonep)
4281*002f591fSIvan Malov {
4282*002f591fSIvan Malov const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
4283*002f591fSIvan Malov efx_mae_actions_t *spec_clone;
4284*002f591fSIvan Malov efx_rc_t rc;
4285*002f591fSIvan Malov
4286*002f591fSIvan Malov EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (*spec_clone), spec_clone);
4287*002f591fSIvan Malov if (spec_clone == NULL) {
4288*002f591fSIvan Malov rc = ENOMEM;
4289*002f591fSIvan Malov goto fail1;
4290*002f591fSIvan Malov }
4291*002f591fSIvan Malov
4292*002f591fSIvan Malov *spec_clone = *spec_orig;
4293*002f591fSIvan Malov
4294*002f591fSIvan Malov spec_clone->ema_rsrc.emar_counter_id.id = EFX_MAE_RSRC_ID_INVALID;
4295*002f591fSIvan Malov spec_clone->ema_actions &= ~(1U << EFX_MAE_ACTION_COUNT);
4296*002f591fSIvan Malov spec_clone->ema_n_count_actions = 0;
4297*002f591fSIvan Malov
4298*002f591fSIvan Malov (void)efx_mae_mport_invalid(&spec_clone->ema_deliver_mport);
4299*002f591fSIvan Malov spec_clone->ema_actions &= ~(1U << EFX_MAE_ACTION_DELIVER);
4300*002f591fSIvan Malov
4301*002f591fSIvan Malov *spec_clonep = spec_clone;
4302*002f591fSIvan Malov
4303*002f591fSIvan Malov return (0);
4304*002f591fSIvan Malov
4305*002f591fSIvan Malov fail1:
4306*002f591fSIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
4307*002f591fSIvan Malov return (rc);
4308*002f591fSIvan Malov }
4309*002f591fSIvan Malov
4310*002f591fSIvan Malov __checkReturn efx_rc_t
efx_mae_action_set_list_alloc(__in efx_nic_t * enp,__in unsigned int n_asets,__in_ecount (n_asets)const efx_mae_aset_id_t * aset_ids,__out efx_mae_aset_list_id_t * aset_list_idp)4311*002f591fSIvan Malov efx_mae_action_set_list_alloc(
4312*002f591fSIvan Malov __in efx_nic_t *enp,
4313*002f591fSIvan Malov __in unsigned int n_asets,
4314*002f591fSIvan Malov __in_ecount(n_asets) const efx_mae_aset_id_t *aset_ids,
4315*002f591fSIvan Malov __out efx_mae_aset_list_id_t *aset_list_idp)
4316*002f591fSIvan Malov {
4317*002f591fSIvan Malov const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
4318*002f591fSIvan Malov EFX_MCDI_DECLARE_BUF(payload,
4319*002f591fSIvan Malov MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_LENMAX_MCDI2,
4320*002f591fSIvan Malov MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_LEN);
4321*002f591fSIvan Malov efx_mae_aset_list_id_t aset_list_id;
4322*002f591fSIvan Malov efx_mcdi_req_t req;
4323*002f591fSIvan Malov efx_rc_t rc;
4324*002f591fSIvan Malov
4325*002f591fSIvan Malov EFX_STATIC_ASSERT(EFX_MAE_ACTION_SET_LIST_MAX_NENTRIES ==
4326*002f591fSIvan Malov MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_AS_IDS_MAXNUM_MCDI2);
4327*002f591fSIvan Malov
4328*002f591fSIvan Malov EFX_STATIC_ASSERT(EFX_MAE_RSRC_ID_INVALID ==
4329*002f591fSIvan Malov MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_ACTION_SET_LIST_ID_NULL);
4330*002f591fSIvan Malov
4331*002f591fSIvan Malov EFX_STATIC_ASSERT(sizeof (aset_list_idp->id) ==
4332*002f591fSIvan Malov MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_ASL_ID_LEN);
4333*002f591fSIvan Malov
4334*002f591fSIvan Malov if (encp->enc_mae_supported == B_FALSE) {
4335*002f591fSIvan Malov rc = ENOTSUP;
4336*002f591fSIvan Malov goto fail1;
4337*002f591fSIvan Malov }
4338*002f591fSIvan Malov
4339*002f591fSIvan Malov if (MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_LEN(n_asets) >
4340*002f591fSIvan Malov MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_LENMAX_MCDI2) {
4341*002f591fSIvan Malov rc = EINVAL;
4342*002f591fSIvan Malov goto fail2;
4343*002f591fSIvan Malov }
4344*002f591fSIvan Malov
4345*002f591fSIvan Malov req.emr_cmd = MC_CMD_MAE_ACTION_SET_LIST_ALLOC;
4346*002f591fSIvan Malov req.emr_in_buf = payload;
4347*002f591fSIvan Malov req.emr_in_length = MC_CMD_MAE_ACTION_SET_LIST_ALLOC_IN_LEN(n_asets);
4348*002f591fSIvan Malov req.emr_out_buf = payload;
4349*002f591fSIvan Malov req.emr_out_length = MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_LEN;
4350*002f591fSIvan Malov
4351*002f591fSIvan Malov MCDI_IN_SET_DWORD(req,
4352*002f591fSIvan Malov MAE_ACTION_SET_LIST_ALLOC_IN_COUNT, n_asets);
4353*002f591fSIvan Malov
4354*002f591fSIvan Malov memcpy(MCDI_IN2(req, uint8_t, MAE_ACTION_SET_LIST_ALLOC_IN_AS_IDS),
4355*002f591fSIvan Malov aset_ids, n_asets * sizeof (*aset_ids));
4356*002f591fSIvan Malov
4357*002f591fSIvan Malov efx_mcdi_execute(enp, &req);
4358*002f591fSIvan Malov
4359*002f591fSIvan Malov if (req.emr_rc != 0) {
4360*002f591fSIvan Malov rc = req.emr_rc;
4361*002f591fSIvan Malov goto fail3;
4362*002f591fSIvan Malov }
4363*002f591fSIvan Malov
4364*002f591fSIvan Malov if (req.emr_out_length_used < MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_LEN) {
4365*002f591fSIvan Malov rc = EMSGSIZE;
4366*002f591fSIvan Malov goto fail4;
4367*002f591fSIvan Malov }
4368*002f591fSIvan Malov
4369*002f591fSIvan Malov aset_list_id.id =
4370*002f591fSIvan Malov MCDI_OUT_DWORD(req, MAE_ACTION_SET_LIST_ALLOC_OUT_ASL_ID);
4371*002f591fSIvan Malov if (aset_list_id.id == EFX_MAE_RSRC_ID_INVALID) {
4372*002f591fSIvan Malov rc = ENOENT;
4373*002f591fSIvan Malov goto fail5;
4374*002f591fSIvan Malov }
4375*002f591fSIvan Malov
4376*002f591fSIvan Malov aset_list_idp->id = aset_list_id.id;
4377*002f591fSIvan Malov
4378*002f591fSIvan Malov return (0);
4379*002f591fSIvan Malov
4380*002f591fSIvan Malov fail5:
4381*002f591fSIvan Malov EFSYS_PROBE(fail5);
4382*002f591fSIvan Malov fail4:
4383*002f591fSIvan Malov EFSYS_PROBE(fail4);
4384*002f591fSIvan Malov fail3:
4385*002f591fSIvan Malov EFSYS_PROBE(fail3);
4386*002f591fSIvan Malov fail2:
4387*002f591fSIvan Malov EFSYS_PROBE(fail2);
4388*002f591fSIvan Malov fail1:
4389*002f591fSIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
4390*002f591fSIvan Malov return (rc);
4391*002f591fSIvan Malov }
4392*002f591fSIvan Malov
4393*002f591fSIvan Malov __checkReturn efx_rc_t
efx_mae_action_set_list_free(__in efx_nic_t * enp,__in const efx_mae_aset_list_id_t * aset_list_idp)4394*002f591fSIvan Malov efx_mae_action_set_list_free(
4395*002f591fSIvan Malov __in efx_nic_t *enp,
4396*002f591fSIvan Malov __in const efx_mae_aset_list_id_t *aset_list_idp)
4397*002f591fSIvan Malov {
4398*002f591fSIvan Malov const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
4399*002f591fSIvan Malov EFX_MCDI_DECLARE_BUF(payload,
4400*002f591fSIvan Malov MC_CMD_MAE_ACTION_SET_LIST_FREE_IN_LEN(1),
4401*002f591fSIvan Malov MC_CMD_MAE_ACTION_SET_LIST_FREE_OUT_LEN(1));
4402*002f591fSIvan Malov efx_mcdi_req_t req;
4403*002f591fSIvan Malov efx_rc_t rc;
4404*002f591fSIvan Malov
4405*002f591fSIvan Malov if (encp->enc_mae_supported == B_FALSE) {
4406*002f591fSIvan Malov rc = ENOTSUP;
4407*002f591fSIvan Malov goto fail1;
4408*002f591fSIvan Malov }
4409*002f591fSIvan Malov
4410*002f591fSIvan Malov req.emr_cmd = MC_CMD_MAE_ACTION_SET_LIST_FREE;
4411*002f591fSIvan Malov req.emr_in_buf = payload;
4412*002f591fSIvan Malov req.emr_in_length = MC_CMD_MAE_ACTION_SET_LIST_FREE_IN_LEN(1);
4413*002f591fSIvan Malov req.emr_out_buf = payload;
4414*002f591fSIvan Malov req.emr_out_length = MC_CMD_MAE_ACTION_SET_LIST_FREE_OUT_LEN(1);
4415*002f591fSIvan Malov
4416*002f591fSIvan Malov MCDI_IN_SET_DWORD(req,
4417*002f591fSIvan Malov MAE_ACTION_SET_LIST_FREE_IN_ASL_ID, aset_list_idp->id);
4418*002f591fSIvan Malov
4419*002f591fSIvan Malov efx_mcdi_execute(enp, &req);
4420*002f591fSIvan Malov
4421*002f591fSIvan Malov if (req.emr_rc != 0) {
4422*002f591fSIvan Malov rc = req.emr_rc;
4423*002f591fSIvan Malov goto fail2;
4424*002f591fSIvan Malov }
4425*002f591fSIvan Malov
4426*002f591fSIvan Malov if (req.emr_out_length_used < MC_CMD_MAE_ACTION_SET_LIST_FREE_OUT_LENMIN) {
4427*002f591fSIvan Malov rc = EMSGSIZE;
4428*002f591fSIvan Malov goto fail3;
4429*002f591fSIvan Malov }
4430*002f591fSIvan Malov
4431*002f591fSIvan Malov if (MCDI_OUT_DWORD(req, MAE_ACTION_SET_LIST_FREE_OUT_FREED_ASL_ID) !=
4432*002f591fSIvan Malov aset_list_idp->id) {
4433*002f591fSIvan Malov /* Firmware failed to free the action set list. */
4434*002f591fSIvan Malov rc = EAGAIN;
4435*002f591fSIvan Malov goto fail4;
4436*002f591fSIvan Malov }
4437*002f591fSIvan Malov
4438*002f591fSIvan Malov return (0);
4439*002f591fSIvan Malov
4440*002f591fSIvan Malov fail4:
4441*002f591fSIvan Malov EFSYS_PROBE(fail4);
4442*002f591fSIvan Malov fail3:
4443*002f591fSIvan Malov EFSYS_PROBE(fail3);
4444*002f591fSIvan Malov fail2:
4445*002f591fSIvan Malov EFSYS_PROBE(fail2);
4446*002f591fSIvan Malov fail1:
4447*002f591fSIvan Malov EFSYS_PROBE1(fail1, efx_rc_t, rc);
4448*002f591fSIvan Malov return (rc);
4449*002f591fSIvan Malov }
4450*002f591fSIvan Malov
44516f956d5cSIvan Malov #endif /* EFSYS_OPT_MAE */
4452