19e7941d7SDenis Pryazhennikov /* SPDX-License-Identifier: BSD-3-Clause
29e7941d7SDenis Pryazhennikov *
39e7941d7SDenis Pryazhennikov * Copyright (c) 2023 Advanced Micro Devices, Inc.
49e7941d7SDenis Pryazhennikov */
59e7941d7SDenis Pryazhennikov
69e7941d7SDenis Pryazhennikov #include "efx.h"
79e7941d7SDenis Pryazhennikov #include "efx_impl.h"
89e7941d7SDenis Pryazhennikov
9d51545f4SDenis Pryazhennikov /* List of HW tables that have support in efx */
10d51545f4SDenis Pryazhennikov static const efx_table_id_t efx_supported_table_ids[] = {
11d51545f4SDenis Pryazhennikov EFX_TABLE_ID_CONNTRACK,
12d51545f4SDenis Pryazhennikov };
13d51545f4SDenis Pryazhennikov
149e7941d7SDenis Pryazhennikov __checkReturn efx_rc_t
efx_table_list(__in efx_nic_t * enp,__in uint32_t entry_ofst,__out_opt unsigned int * total_n_tablesp,__out_ecount_opt (n_table_ids)efx_table_id_t * table_ids,__in unsigned int n_table_ids,__out_opt unsigned int * n_table_ids_writtenp)159e7941d7SDenis Pryazhennikov efx_table_list(
169e7941d7SDenis Pryazhennikov __in efx_nic_t *enp,
179e7941d7SDenis Pryazhennikov __in uint32_t entry_ofst,
189e7941d7SDenis Pryazhennikov __out_opt unsigned int *total_n_tablesp,
199e7941d7SDenis Pryazhennikov __out_ecount_opt(n_table_ids) efx_table_id_t *table_ids,
209e7941d7SDenis Pryazhennikov __in unsigned int n_table_ids,
219e7941d7SDenis Pryazhennikov __out_opt unsigned int *n_table_ids_writtenp)
229e7941d7SDenis Pryazhennikov {
239e7941d7SDenis Pryazhennikov const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
249e7941d7SDenis Pryazhennikov unsigned int n_entries;
259e7941d7SDenis Pryazhennikov efx_mcdi_req_t req;
269e7941d7SDenis Pryazhennikov unsigned int i;
279e7941d7SDenis Pryazhennikov efx_rc_t rc;
289e7941d7SDenis Pryazhennikov EFX_MCDI_DECLARE_BUF(payload,
299e7941d7SDenis Pryazhennikov MC_CMD_TABLE_LIST_IN_LEN,
309e7941d7SDenis Pryazhennikov MC_CMD_TABLE_LIST_OUT_LENMAX_MCDI2);
319e7941d7SDenis Pryazhennikov
329e7941d7SDenis Pryazhennikov /* Ensure EFX and MCDI use same values for table IDs */
339e7941d7SDenis Pryazhennikov EFX_STATIC_ASSERT(EFX_TABLE_ID_CONNTRACK == TABLE_ID_CONNTRACK_TABLE);
349e7941d7SDenis Pryazhennikov
359e7941d7SDenis Pryazhennikov if (encp->enc_table_api_supported == B_FALSE) {
369e7941d7SDenis Pryazhennikov rc = ENOTSUP;
379e7941d7SDenis Pryazhennikov goto fail1;
389e7941d7SDenis Pryazhennikov }
399e7941d7SDenis Pryazhennikov
409e7941d7SDenis Pryazhennikov if ((n_table_ids != 0) &&
419e7941d7SDenis Pryazhennikov ((table_ids == NULL) || (n_table_ids_writtenp == NULL))) {
429e7941d7SDenis Pryazhennikov rc = EINVAL;
439e7941d7SDenis Pryazhennikov goto fail2;
449e7941d7SDenis Pryazhennikov }
459e7941d7SDenis Pryazhennikov
469e7941d7SDenis Pryazhennikov req.emr_cmd = MC_CMD_TABLE_LIST;
479e7941d7SDenis Pryazhennikov req.emr_in_buf = payload;
489e7941d7SDenis Pryazhennikov req.emr_in_length = MC_CMD_TABLE_LIST_IN_LEN;
499e7941d7SDenis Pryazhennikov req.emr_out_buf = payload;
509e7941d7SDenis Pryazhennikov req.emr_out_length = MC_CMD_TABLE_LIST_OUT_LENMAX_MCDI2;
519e7941d7SDenis Pryazhennikov
529e7941d7SDenis Pryazhennikov MCDI_IN_SET_DWORD(req, TABLE_LIST_IN_FIRST_TABLE_ID_INDEX, entry_ofst);
539e7941d7SDenis Pryazhennikov
549e7941d7SDenis Pryazhennikov efx_mcdi_execute(enp, &req);
559e7941d7SDenis Pryazhennikov
569e7941d7SDenis Pryazhennikov if (req.emr_rc != 0) {
579e7941d7SDenis Pryazhennikov rc = req.emr_rc;
589e7941d7SDenis Pryazhennikov goto fail3;
599e7941d7SDenis Pryazhennikov }
609e7941d7SDenis Pryazhennikov
619e7941d7SDenis Pryazhennikov if (req.emr_out_length_used < MC_CMD_TABLE_LIST_OUT_LENMIN) {
629e7941d7SDenis Pryazhennikov rc = EMSGSIZE;
639e7941d7SDenis Pryazhennikov goto fail4;
649e7941d7SDenis Pryazhennikov }
659e7941d7SDenis Pryazhennikov
669e7941d7SDenis Pryazhennikov if (total_n_tablesp != NULL)
679e7941d7SDenis Pryazhennikov *total_n_tablesp = MCDI_OUT_DWORD(req, TABLE_LIST_OUT_N_TABLES);
689e7941d7SDenis Pryazhennikov
699e7941d7SDenis Pryazhennikov n_entries = MC_CMD_TABLE_LIST_OUT_TABLE_ID_NUM(req.emr_out_length_used);
709e7941d7SDenis Pryazhennikov
719e7941d7SDenis Pryazhennikov if (table_ids != NULL) {
729e7941d7SDenis Pryazhennikov if (n_entries > n_table_ids) {
739e7941d7SDenis Pryazhennikov rc = ENOMEM;
749e7941d7SDenis Pryazhennikov goto fail5;
759e7941d7SDenis Pryazhennikov }
769e7941d7SDenis Pryazhennikov
779e7941d7SDenis Pryazhennikov for (i = 0; i < n_entries; i++) {
789e7941d7SDenis Pryazhennikov table_ids[i] = MCDI_OUT_INDEXED_DWORD(req,
799e7941d7SDenis Pryazhennikov TABLE_LIST_OUT_TABLE_ID, i);
809e7941d7SDenis Pryazhennikov }
819e7941d7SDenis Pryazhennikov }
829e7941d7SDenis Pryazhennikov
839e7941d7SDenis Pryazhennikov if (n_table_ids_writtenp != NULL)
849e7941d7SDenis Pryazhennikov *n_table_ids_writtenp = n_entries;
859e7941d7SDenis Pryazhennikov
869e7941d7SDenis Pryazhennikov return (0);
879e7941d7SDenis Pryazhennikov
889e7941d7SDenis Pryazhennikov fail5:
899e7941d7SDenis Pryazhennikov EFSYS_PROBE(fail5);
909e7941d7SDenis Pryazhennikov fail4:
919e7941d7SDenis Pryazhennikov EFSYS_PROBE(fail4);
929e7941d7SDenis Pryazhennikov fail3:
939e7941d7SDenis Pryazhennikov EFSYS_PROBE(fail3);
949e7941d7SDenis Pryazhennikov fail2:
959e7941d7SDenis Pryazhennikov EFSYS_PROBE(fail2);
969e7941d7SDenis Pryazhennikov fail1:
979e7941d7SDenis Pryazhennikov EFSYS_PROBE1(fail1, efx_rc_t, rc);
989e7941d7SDenis Pryazhennikov return (rc);
999e7941d7SDenis Pryazhennikov }
100d51545f4SDenis Pryazhennikov
101d51545f4SDenis Pryazhennikov __checkReturn size_t
efx_table_supported_num_get(__in void)102d51545f4SDenis Pryazhennikov efx_table_supported_num_get(
103d51545f4SDenis Pryazhennikov __in void)
104d51545f4SDenis Pryazhennikov {
105d51545f4SDenis Pryazhennikov return (EFX_ARRAY_SIZE(efx_supported_table_ids));
106d51545f4SDenis Pryazhennikov }
107d51545f4SDenis Pryazhennikov
108d51545f4SDenis Pryazhennikov __checkReturn boolean_t
efx_table_is_supported(__in efx_table_id_t table_id)109d51545f4SDenis Pryazhennikov efx_table_is_supported(
110d51545f4SDenis Pryazhennikov __in efx_table_id_t table_id)
111d51545f4SDenis Pryazhennikov {
112d51545f4SDenis Pryazhennikov size_t i;
113d51545f4SDenis Pryazhennikov
114d51545f4SDenis Pryazhennikov for (i = 0; i < efx_table_supported_num_get(); i++) {
115d51545f4SDenis Pryazhennikov if (efx_supported_table_ids[i] == table_id)
116d51545f4SDenis Pryazhennikov return (B_TRUE);
117d51545f4SDenis Pryazhennikov }
118d51545f4SDenis Pryazhennikov
119d51545f4SDenis Pryazhennikov return (B_FALSE);
120d51545f4SDenis Pryazhennikov }
121d51545f4SDenis Pryazhennikov
122d51545f4SDenis Pryazhennikov static __checkReturn efx_rc_t
efx_table_ct_desc_fields_check(__in_ecount (n_fields_descs)efx_table_field_descriptor_t * fields_descsp,__in unsigned int n_fields_descs)123d51545f4SDenis Pryazhennikov efx_table_ct_desc_fields_check(
124d51545f4SDenis Pryazhennikov __in_ecount(n_fields_descs) efx_table_field_descriptor_t *fields_descsp,
125d51545f4SDenis Pryazhennikov __in unsigned int n_fields_descs)
126d51545f4SDenis Pryazhennikov {
127d51545f4SDenis Pryazhennikov unsigned int i;
128d51545f4SDenis Pryazhennikov efx_rc_t rc;
129d51545f4SDenis Pryazhennikov
130d51545f4SDenis Pryazhennikov for (i = 0; i < n_fields_descs; i++) {
131d51545f4SDenis Pryazhennikov switch (fields_descsp[i].field_id) {
132d51545f4SDenis Pryazhennikov case EFX_TABLE_FIELD_ID_ETHER_TYPE:
133d51545f4SDenis Pryazhennikov case EFX_TABLE_FIELD_ID_SRC_IP:
134d51545f4SDenis Pryazhennikov case EFX_TABLE_FIELD_ID_DST_IP:
135d51545f4SDenis Pryazhennikov case EFX_TABLE_FIELD_ID_IP_PROTO:
136d51545f4SDenis Pryazhennikov case EFX_TABLE_FIELD_ID_SRC_PORT:
137d51545f4SDenis Pryazhennikov case EFX_TABLE_FIELD_ID_DST_PORT:
138d51545f4SDenis Pryazhennikov if (fields_descsp[i].mask_type != EFX_TABLE_FIELD_MASK_EXACT) {
139d51545f4SDenis Pryazhennikov rc = EINVAL;
140d51545f4SDenis Pryazhennikov goto fail1;
141d51545f4SDenis Pryazhennikov }
142d51545f4SDenis Pryazhennikov break;
143d51545f4SDenis Pryazhennikov /*
144d51545f4SDenis Pryazhennikov * TODO:
145d51545f4SDenis Pryazhennikov * All fields in the CT table have EXACT mask.
146d51545f4SDenis Pryazhennikov * All the response field descriptors must have the EXACT mask.
147d51545f4SDenis Pryazhennikov * In the current implementation, only the Ethertype, source and
148d51545f4SDenis Pryazhennikov * destination IP address, IP protocol, and source and destination IP
149d51545f4SDenis Pryazhennikov * are used for the lookup by the key.
150d51545f4SDenis Pryazhennikov * FW could use the NEVER mask for the fields in the key that are not
151d51545f4SDenis Pryazhennikov * used for the lookup.
152d51545f4SDenis Pryazhennikov * As an alternative, a new mask could be added for these fields,
153d51545f4SDenis Pryazhennikov * like EXACT_NOT_USED.
154d51545f4SDenis Pryazhennikov */
155d51545f4SDenis Pryazhennikov default:
156d51545f4SDenis Pryazhennikov if ((fields_descsp[i].mask_type != EFX_TABLE_FIELD_MASK_NEVER) &&
157d51545f4SDenis Pryazhennikov (fields_descsp[i].mask_type != EFX_TABLE_FIELD_MASK_EXACT)) {
158d51545f4SDenis Pryazhennikov rc = EINVAL;
159d51545f4SDenis Pryazhennikov goto fail2;
160d51545f4SDenis Pryazhennikov }
161d51545f4SDenis Pryazhennikov break;
162d51545f4SDenis Pryazhennikov }
163d51545f4SDenis Pryazhennikov }
164d51545f4SDenis Pryazhennikov
165d51545f4SDenis Pryazhennikov return (0);
166d51545f4SDenis Pryazhennikov
167d51545f4SDenis Pryazhennikov fail2:
168d51545f4SDenis Pryazhennikov EFSYS_PROBE(fail2);
169d51545f4SDenis Pryazhennikov fail1:
170d51545f4SDenis Pryazhennikov EFSYS_PROBE1(fail1, efx_rc_t, rc);
171d51545f4SDenis Pryazhennikov return (rc);
172d51545f4SDenis Pryazhennikov }
173d51545f4SDenis Pryazhennikov
174d51545f4SDenis Pryazhennikov static __checkReturn efx_rc_t
efx_table_desc_fields_check(__in efx_table_id_t table_id,__in_ecount (n_fields_descs)efx_table_field_descriptor_t * fields_descsp,__in unsigned int n_fields_descs)175d51545f4SDenis Pryazhennikov efx_table_desc_fields_check(
176d51545f4SDenis Pryazhennikov __in efx_table_id_t table_id,
177d51545f4SDenis Pryazhennikov __in_ecount(n_fields_descs) efx_table_field_descriptor_t *fields_descsp,
178d51545f4SDenis Pryazhennikov __in unsigned int n_fields_descs)
179d51545f4SDenis Pryazhennikov {
180d51545f4SDenis Pryazhennikov efx_rc_t rc;
181d51545f4SDenis Pryazhennikov
182d51545f4SDenis Pryazhennikov switch (table_id) {
183d51545f4SDenis Pryazhennikov case EFX_TABLE_ID_CONNTRACK:
184d51545f4SDenis Pryazhennikov rc = efx_table_ct_desc_fields_check(fields_descsp, n_fields_descs);
185d51545f4SDenis Pryazhennikov if (rc != 0)
186d51545f4SDenis Pryazhennikov goto fail1;
187d51545f4SDenis Pryazhennikov break;
188d51545f4SDenis Pryazhennikov default:
189d51545f4SDenis Pryazhennikov break;
190d51545f4SDenis Pryazhennikov }
191d51545f4SDenis Pryazhennikov
192d51545f4SDenis Pryazhennikov return (0);
193d51545f4SDenis Pryazhennikov
194d51545f4SDenis Pryazhennikov fail1:
195d51545f4SDenis Pryazhennikov EFSYS_PROBE1(fail1, efx_rc_t, rc);
196d51545f4SDenis Pryazhennikov return (rc);
197d51545f4SDenis Pryazhennikov }
198d51545f4SDenis Pryazhennikov
199d51545f4SDenis Pryazhennikov static void
efx_table_desc_fields_get(__in const efx_mcdi_req_t * req,__out_ecount (n_fields_descs)efx_table_field_descriptor_t * fields_descsp,__in unsigned int n_fields_descs)200d51545f4SDenis Pryazhennikov efx_table_desc_fields_get(
201d51545f4SDenis Pryazhennikov __in const efx_mcdi_req_t *req,
202d51545f4SDenis Pryazhennikov __out_ecount(n_fields_descs) efx_table_field_descriptor_t *fields_descsp,
203d51545f4SDenis Pryazhennikov __in unsigned int n_fields_descs)
204d51545f4SDenis Pryazhennikov {
205d51545f4SDenis Pryazhennikov unsigned int i;
206d51545f4SDenis Pryazhennikov
207d51545f4SDenis Pryazhennikov for (i = 0; i < n_fields_descs; i++) {
208d51545f4SDenis Pryazhennikov fields_descsp[i].field_id = (efx_table_field_id_t)
209d51545f4SDenis Pryazhennikov MCDI_OUT_INDEXED_QWORD_FIELD(*req,
210d51545f4SDenis Pryazhennikov TABLE_DESCRIPTOR_OUT_FIELDS, i, TABLE_FIELD_DESCR_FIELD_ID);
211d51545f4SDenis Pryazhennikov
212d51545f4SDenis Pryazhennikov fields_descsp[i].lbn =
213d51545f4SDenis Pryazhennikov MCDI_OUT_INDEXED_QWORD_FIELD(*req,
214d51545f4SDenis Pryazhennikov TABLE_DESCRIPTOR_OUT_FIELDS, i, TABLE_FIELD_DESCR_LBN);
215d51545f4SDenis Pryazhennikov
216d51545f4SDenis Pryazhennikov fields_descsp[i].width =
217d51545f4SDenis Pryazhennikov MCDI_OUT_INDEXED_QWORD_FIELD(*req,
218d51545f4SDenis Pryazhennikov TABLE_DESCRIPTOR_OUT_FIELDS, i, TABLE_FIELD_DESCR_WIDTH);
219d51545f4SDenis Pryazhennikov
220d51545f4SDenis Pryazhennikov fields_descsp[i].mask_type = (efx_table_field_mask_type_t)
221d51545f4SDenis Pryazhennikov MCDI_OUT_INDEXED_QWORD_FIELD(*req,
222d51545f4SDenis Pryazhennikov TABLE_DESCRIPTOR_OUT_FIELDS, i, TABLE_FIELD_DESCR_MASK_TYPE);
223d51545f4SDenis Pryazhennikov
224d51545f4SDenis Pryazhennikov fields_descsp[i].scheme =
225d51545f4SDenis Pryazhennikov MCDI_OUT_INDEXED_QWORD_FIELD(*req,
226d51545f4SDenis Pryazhennikov TABLE_DESCRIPTOR_OUT_FIELDS, i, TABLE_FIELD_DESCR_SCHEME);
227d51545f4SDenis Pryazhennikov }
228d51545f4SDenis Pryazhennikov }
229d51545f4SDenis Pryazhennikov
230d51545f4SDenis Pryazhennikov __checkReturn efx_rc_t
efx_table_describe(__in efx_nic_t * enp,__in efx_table_id_t table_id,__in uint32_t field_offset,__out_opt efx_table_descriptor_t * table_descp,__out_ecount_opt (n_field_descs)efx_table_field_descriptor_t * fields_descs,__in unsigned int n_field_descs,__out_opt unsigned int * n_field_descs_writtenp)231d51545f4SDenis Pryazhennikov efx_table_describe(
232d51545f4SDenis Pryazhennikov __in efx_nic_t *enp,
233d51545f4SDenis Pryazhennikov __in efx_table_id_t table_id,
234d51545f4SDenis Pryazhennikov __in uint32_t field_offset,
235d51545f4SDenis Pryazhennikov __out_opt efx_table_descriptor_t *table_descp,
236d51545f4SDenis Pryazhennikov __out_ecount_opt(n_field_descs) efx_table_field_descriptor_t *fields_descs,
237d51545f4SDenis Pryazhennikov __in unsigned int n_field_descs,
238d51545f4SDenis Pryazhennikov __out_opt unsigned int *n_field_descs_writtenp)
239d51545f4SDenis Pryazhennikov {
240d51545f4SDenis Pryazhennikov const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
241d51545f4SDenis Pryazhennikov unsigned int n_entries;
242d51545f4SDenis Pryazhennikov efx_mcdi_req_t req;
243d51545f4SDenis Pryazhennikov unsigned int i;
244d51545f4SDenis Pryazhennikov efx_rc_t rc;
245d51545f4SDenis Pryazhennikov EFX_MCDI_DECLARE_BUF(payload,
246d51545f4SDenis Pryazhennikov MC_CMD_TABLE_DESCRIPTOR_IN_LEN,
247d51545f4SDenis Pryazhennikov MC_CMD_TABLE_DESCRIPTOR_OUT_LENMAX_MCDI2);
248d51545f4SDenis Pryazhennikov
249d51545f4SDenis Pryazhennikov /* Ensure EFX and MCDI use same values for table types */
250d51545f4SDenis Pryazhennikov EFX_STATIC_ASSERT(EFX_TABLE_TYPE_BCAM == MC_CMD_TABLE_DESCRIPTOR_OUT_TYPE_BCAM);
251d51545f4SDenis Pryazhennikov
252d51545f4SDenis Pryazhennikov /* Ensure EFX and MCDI use same values for table fields */
253d51545f4SDenis Pryazhennikov EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_UNUSED == TABLE_FIELD_ID_UNUSED);
254d51545f4SDenis Pryazhennikov EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_COUNTER_ID == TABLE_FIELD_ID_COUNTER_ID);
255d51545f4SDenis Pryazhennikov EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_ETHER_TYPE == TABLE_FIELD_ID_ETHER_TYPE);
256d51545f4SDenis Pryazhennikov EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_SRC_IP == TABLE_FIELD_ID_SRC_IP);
257d51545f4SDenis Pryazhennikov EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_DST_IP == TABLE_FIELD_ID_DST_IP);
258d51545f4SDenis Pryazhennikov EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_IP_PROTO == TABLE_FIELD_ID_IP_PROTO);
259d51545f4SDenis Pryazhennikov EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_SRC_PORT == TABLE_FIELD_ID_SRC_PORT);
260d51545f4SDenis Pryazhennikov EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_DST_PORT == TABLE_FIELD_ID_DST_PORT);
261d51545f4SDenis Pryazhennikov EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_NAT_PORT == TABLE_FIELD_ID_NAT_PORT);
262d51545f4SDenis Pryazhennikov EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_NAT_IP == TABLE_FIELD_ID_NAT_IP);
263d51545f4SDenis Pryazhennikov EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_NAT_DIR == TABLE_FIELD_ID_NAT_DIR);
264d51545f4SDenis Pryazhennikov EFX_STATIC_ASSERT(EFX_TABLE_FIELD_ID_CT_MARK == TABLE_FIELD_ID_CT_MARK);
265d51545f4SDenis Pryazhennikov
266d51545f4SDenis Pryazhennikov if (encp->enc_table_api_supported == B_FALSE) {
267d51545f4SDenis Pryazhennikov rc = ENOTSUP;
268d51545f4SDenis Pryazhennikov goto fail1;
269d51545f4SDenis Pryazhennikov }
270d51545f4SDenis Pryazhennikov
271d51545f4SDenis Pryazhennikov if (!efx_table_is_supported(table_id)) {
272d51545f4SDenis Pryazhennikov rc = ENOTSUP;
273d51545f4SDenis Pryazhennikov goto fail2;
274d51545f4SDenis Pryazhennikov }
275d51545f4SDenis Pryazhennikov
276d51545f4SDenis Pryazhennikov if ((n_field_descs != 0) &&
277d51545f4SDenis Pryazhennikov ((fields_descs == NULL) || (n_field_descs_writtenp == NULL))) {
278d51545f4SDenis Pryazhennikov rc = EINVAL;
279d51545f4SDenis Pryazhennikov goto fail3;
280d51545f4SDenis Pryazhennikov }
281d51545f4SDenis Pryazhennikov
282d51545f4SDenis Pryazhennikov req.emr_cmd = MC_CMD_TABLE_DESCRIPTOR;
283d51545f4SDenis Pryazhennikov req.emr_in_buf = payload;
284d51545f4SDenis Pryazhennikov req.emr_in_length = MC_CMD_TABLE_DESCRIPTOR_IN_LEN;
285d51545f4SDenis Pryazhennikov req.emr_out_buf = payload;
286d51545f4SDenis Pryazhennikov req.emr_out_length = MC_CMD_TABLE_DESCRIPTOR_OUT_LENMAX_MCDI2;
287d51545f4SDenis Pryazhennikov
288d51545f4SDenis Pryazhennikov MCDI_IN_SET_DWORD(req, TABLE_DESCRIPTOR_IN_TABLE_ID, (uint32_t)table_id);
289d51545f4SDenis Pryazhennikov MCDI_IN_SET_DWORD(req, TABLE_DESCRIPTOR_IN_FIRST_FIELDS_INDEX, field_offset);
290d51545f4SDenis Pryazhennikov
291d51545f4SDenis Pryazhennikov efx_mcdi_execute(enp, &req);
292d51545f4SDenis Pryazhennikov
293d51545f4SDenis Pryazhennikov if (req.emr_rc != 0) {
294d51545f4SDenis Pryazhennikov rc = req.emr_rc;
295d51545f4SDenis Pryazhennikov goto fail4;
296d51545f4SDenis Pryazhennikov }
297d51545f4SDenis Pryazhennikov
298d51545f4SDenis Pryazhennikov if (req.emr_out_length_used < MC_CMD_TABLE_DESCRIPTOR_OUT_LENMIN) {
299d51545f4SDenis Pryazhennikov rc = EMSGSIZE;
300d51545f4SDenis Pryazhennikov goto fail5;
301d51545f4SDenis Pryazhennikov }
302d51545f4SDenis Pryazhennikov
303d51545f4SDenis Pryazhennikov if (table_descp != NULL) {
304d51545f4SDenis Pryazhennikov table_descp->type = (efx_table_type_t)MCDI_OUT_WORD(
305d51545f4SDenis Pryazhennikov req, TABLE_DESCRIPTOR_OUT_TYPE);
306d51545f4SDenis Pryazhennikov table_descp->key_width = MCDI_OUT_WORD(
307d51545f4SDenis Pryazhennikov req, TABLE_DESCRIPTOR_OUT_KEY_WIDTH);
308d51545f4SDenis Pryazhennikov table_descp->resp_width = MCDI_OUT_WORD(
309d51545f4SDenis Pryazhennikov req, TABLE_DESCRIPTOR_OUT_RESP_WIDTH);
310d51545f4SDenis Pryazhennikov table_descp->n_key_fields = MCDI_OUT_WORD(
311d51545f4SDenis Pryazhennikov req, TABLE_DESCRIPTOR_OUT_N_KEY_FIELDS);
312d51545f4SDenis Pryazhennikov table_descp->n_resp_fields = MCDI_OUT_WORD(
313d51545f4SDenis Pryazhennikov req, TABLE_DESCRIPTOR_OUT_N_RESP_FIELDS);
314d51545f4SDenis Pryazhennikov }
315d51545f4SDenis Pryazhennikov
316d51545f4SDenis Pryazhennikov n_entries = MC_CMD_TABLE_DESCRIPTOR_OUT_FIELDS_NUM(req.emr_out_length_used);
317d51545f4SDenis Pryazhennikov
318d51545f4SDenis Pryazhennikov if (fields_descs != NULL) {
319d51545f4SDenis Pryazhennikov if (n_entries > n_field_descs) {
320d51545f4SDenis Pryazhennikov rc = ENOMEM;
321d51545f4SDenis Pryazhennikov goto fail6;
322d51545f4SDenis Pryazhennikov }
323d51545f4SDenis Pryazhennikov
324d51545f4SDenis Pryazhennikov efx_table_desc_fields_get(&req, fields_descs, n_entries);
325d51545f4SDenis Pryazhennikov rc = efx_table_desc_fields_check(table_id, fields_descs, n_entries);
326d51545f4SDenis Pryazhennikov if (rc != 0)
327d51545f4SDenis Pryazhennikov goto fail7;
328d51545f4SDenis Pryazhennikov }
329d51545f4SDenis Pryazhennikov
330d51545f4SDenis Pryazhennikov if (n_field_descs_writtenp != NULL)
331d51545f4SDenis Pryazhennikov *n_field_descs_writtenp = n_entries;
332d51545f4SDenis Pryazhennikov
333d51545f4SDenis Pryazhennikov return (0);
334d51545f4SDenis Pryazhennikov
335d51545f4SDenis Pryazhennikov fail7:
336d51545f4SDenis Pryazhennikov EFSYS_PROBE(fail7);
337d51545f4SDenis Pryazhennikov fail6:
338d51545f4SDenis Pryazhennikov EFSYS_PROBE(fail6);
339d51545f4SDenis Pryazhennikov fail5:
340d51545f4SDenis Pryazhennikov EFSYS_PROBE(fail5);
341d51545f4SDenis Pryazhennikov fail4:
342d51545f4SDenis Pryazhennikov EFSYS_PROBE(fail4);
343d51545f4SDenis Pryazhennikov fail3:
344d51545f4SDenis Pryazhennikov EFSYS_PROBE(fail3);
345d51545f4SDenis Pryazhennikov fail2:
346d51545f4SDenis Pryazhennikov EFSYS_PROBE(fail2);
347d51545f4SDenis Pryazhennikov fail1:
348d51545f4SDenis Pryazhennikov EFSYS_PROBE1(fail1, efx_rc_t, rc);
349d51545f4SDenis Pryazhennikov return (rc);
350d51545f4SDenis Pryazhennikov }
3518ee47d82SDenis Pryazhennikov
3528ee47d82SDenis Pryazhennikov __checkReturn efx_rc_t
efx_table_entry_insert(__in efx_nic_t * enp,__in efx_table_id_t table_id,__in uint16_t priority,__in uint16_t mask_id,__in uint16_t key_width,__in uint16_t mask_width,__in uint16_t resp_width,__in_bcount (data_size)uint8_t * entry_datap,__in unsigned int data_size)3538ee47d82SDenis Pryazhennikov efx_table_entry_insert(
3548ee47d82SDenis Pryazhennikov __in efx_nic_t *enp,
3558ee47d82SDenis Pryazhennikov __in efx_table_id_t table_id,
3568ee47d82SDenis Pryazhennikov __in uint16_t priority,
3578ee47d82SDenis Pryazhennikov __in uint16_t mask_id,
3588ee47d82SDenis Pryazhennikov __in uint16_t key_width,
3598ee47d82SDenis Pryazhennikov __in uint16_t mask_width,
3608ee47d82SDenis Pryazhennikov __in uint16_t resp_width,
3618ee47d82SDenis Pryazhennikov __in_bcount(data_size) uint8_t *entry_datap,
3628ee47d82SDenis Pryazhennikov __in unsigned int data_size)
3638ee47d82SDenis Pryazhennikov {
3648ee47d82SDenis Pryazhennikov const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
3658ee47d82SDenis Pryazhennikov unsigned int n_dwords;
3668ee47d82SDenis Pryazhennikov efx_mcdi_req_t req;
3678ee47d82SDenis Pryazhennikov efx_rc_t rc;
3688ee47d82SDenis Pryazhennikov EFX_MCDI_DECLARE_BUF(payload,
3698ee47d82SDenis Pryazhennikov MC_CMD_TABLE_INSERT_IN_LENMAX_MCDI2,
3708ee47d82SDenis Pryazhennikov MC_CMD_TABLE_INSERT_OUT_LEN);
3718ee47d82SDenis Pryazhennikov
3728ee47d82SDenis Pryazhennikov /*
3738ee47d82SDenis Pryazhennikov * Ensure MCDI number of 32bit units matches EFX maximum possible
3748ee47d82SDenis Pryazhennikov * data in bytes.
3758ee47d82SDenis Pryazhennikov */
3768ee47d82SDenis Pryazhennikov EFX_STATIC_ASSERT((MC_CMD_TABLE_INSERT_IN_LENMAX * sizeof(uint32_t)) ==
3778ee47d82SDenis Pryazhennikov EFX_TABLE_ENTRY_LENGTH_MAX);
3788ee47d82SDenis Pryazhennikov
3798ee47d82SDenis Pryazhennikov if (encp->enc_table_api_supported == B_FALSE) {
3808ee47d82SDenis Pryazhennikov rc = ENOTSUP;
3818ee47d82SDenis Pryazhennikov goto fail1;
3828ee47d82SDenis Pryazhennikov }
3838ee47d82SDenis Pryazhennikov
3848ee47d82SDenis Pryazhennikov if ((data_size % sizeof(uint32_t)) != 0) {
3858ee47d82SDenis Pryazhennikov rc = EINVAL;
3868ee47d82SDenis Pryazhennikov goto fail2;
3878ee47d82SDenis Pryazhennikov }
3888ee47d82SDenis Pryazhennikov
3898ee47d82SDenis Pryazhennikov if ((data_size == 0) || (data_size > EFX_TABLE_ENTRY_LENGTH_MAX)) {
3908ee47d82SDenis Pryazhennikov rc = EINVAL;
3918ee47d82SDenis Pryazhennikov goto fail3;
3928ee47d82SDenis Pryazhennikov }
3938ee47d82SDenis Pryazhennikov
3948ee47d82SDenis Pryazhennikov n_dwords = data_size / sizeof(uint32_t);
3958ee47d82SDenis Pryazhennikov
3968ee47d82SDenis Pryazhennikov req.emr_cmd = MC_CMD_TABLE_INSERT;
3978ee47d82SDenis Pryazhennikov req.emr_in_buf = payload;
3988ee47d82SDenis Pryazhennikov req.emr_in_length = MC_CMD_TABLE_INSERT_IN_LEN(n_dwords);
3998ee47d82SDenis Pryazhennikov req.emr_out_buf = payload;
4008ee47d82SDenis Pryazhennikov req.emr_out_length = MC_CMD_TABLE_INSERT_OUT_LEN;
4018ee47d82SDenis Pryazhennikov
4028ee47d82SDenis Pryazhennikov MCDI_IN_SET_DWORD(req, TABLE_INSERT_IN_TABLE_ID, (uint32_t)table_id);
4038ee47d82SDenis Pryazhennikov MCDI_IN_SET_WORD(req, TABLE_INSERT_IN_PRIORITY, priority);
4048ee47d82SDenis Pryazhennikov MCDI_IN_SET_WORD(req, TABLE_INSERT_IN_MASK_ID, mask_id);
4058ee47d82SDenis Pryazhennikov MCDI_IN_SET_WORD(req, TABLE_INSERT_IN_KEY_WIDTH, key_width);
4068ee47d82SDenis Pryazhennikov MCDI_IN_SET_WORD(req, TABLE_INSERT_IN_MASK_WIDTH, mask_width);
4078ee47d82SDenis Pryazhennikov MCDI_IN_SET_WORD(req, TABLE_INSERT_IN_RESP_WIDTH, resp_width);
4088ee47d82SDenis Pryazhennikov
4098ee47d82SDenis Pryazhennikov memcpy(MCDI_IN2(req, uint8_t, TABLE_INSERT_IN_DATA), entry_datap, data_size);
4108ee47d82SDenis Pryazhennikov
4118ee47d82SDenis Pryazhennikov efx_mcdi_execute(enp, &req);
4128ee47d82SDenis Pryazhennikov
4138ee47d82SDenis Pryazhennikov if (req.emr_rc != 0) {
4148ee47d82SDenis Pryazhennikov rc = req.emr_rc;
4158ee47d82SDenis Pryazhennikov goto fail4;
4168ee47d82SDenis Pryazhennikov }
4178ee47d82SDenis Pryazhennikov
4188ee47d82SDenis Pryazhennikov return (0);
4198ee47d82SDenis Pryazhennikov
4208ee47d82SDenis Pryazhennikov fail4:
4218ee47d82SDenis Pryazhennikov EFSYS_PROBE(fail4);
4228ee47d82SDenis Pryazhennikov fail3:
4238ee47d82SDenis Pryazhennikov EFSYS_PROBE(fail3);
4248ee47d82SDenis Pryazhennikov fail2:
4258ee47d82SDenis Pryazhennikov EFSYS_PROBE(fail2);
4268ee47d82SDenis Pryazhennikov fail1:
4278ee47d82SDenis Pryazhennikov EFSYS_PROBE1(fail1, efx_rc_t, rc);
4288ee47d82SDenis Pryazhennikov return (rc);
4298ee47d82SDenis Pryazhennikov }
430*a5a8beb5SDenis Pryazhennikov
431*a5a8beb5SDenis Pryazhennikov __checkReturn efx_rc_t
efx_table_entry_delete(__in efx_nic_t * enp,__in efx_table_id_t table_id,__in uint16_t mask_id,__in uint16_t key_width,__in uint16_t mask_width,__in_bcount (data_size)uint8_t * entry_datap,__in unsigned int data_size)432*a5a8beb5SDenis Pryazhennikov efx_table_entry_delete(
433*a5a8beb5SDenis Pryazhennikov __in efx_nic_t *enp,
434*a5a8beb5SDenis Pryazhennikov __in efx_table_id_t table_id,
435*a5a8beb5SDenis Pryazhennikov __in uint16_t mask_id,
436*a5a8beb5SDenis Pryazhennikov __in uint16_t key_width,
437*a5a8beb5SDenis Pryazhennikov __in uint16_t mask_width,
438*a5a8beb5SDenis Pryazhennikov __in_bcount(data_size) uint8_t *entry_datap,
439*a5a8beb5SDenis Pryazhennikov __in unsigned int data_size)
440*a5a8beb5SDenis Pryazhennikov {
441*a5a8beb5SDenis Pryazhennikov const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
442*a5a8beb5SDenis Pryazhennikov unsigned int n_dwords;
443*a5a8beb5SDenis Pryazhennikov efx_mcdi_req_t req;
444*a5a8beb5SDenis Pryazhennikov efx_rc_t rc;
445*a5a8beb5SDenis Pryazhennikov EFX_MCDI_DECLARE_BUF(payload,
446*a5a8beb5SDenis Pryazhennikov MC_CMD_TABLE_DELETE_IN_LENMAX_MCDI2,
447*a5a8beb5SDenis Pryazhennikov MC_CMD_TABLE_DELETE_OUT_LEN);
448*a5a8beb5SDenis Pryazhennikov
449*a5a8beb5SDenis Pryazhennikov /*
450*a5a8beb5SDenis Pryazhennikov * Ensure MCDI number of 32bit units matches EFX maximum possible
451*a5a8beb5SDenis Pryazhennikov * data in bytes.
452*a5a8beb5SDenis Pryazhennikov */
453*a5a8beb5SDenis Pryazhennikov EFX_STATIC_ASSERT((MC_CMD_TABLE_DELETE_IN_LENMAX * sizeof(uint32_t)) ==
454*a5a8beb5SDenis Pryazhennikov EFX_TABLE_ENTRY_LENGTH_MAX);
455*a5a8beb5SDenis Pryazhennikov
456*a5a8beb5SDenis Pryazhennikov if (encp->enc_table_api_supported == B_FALSE) {
457*a5a8beb5SDenis Pryazhennikov rc = ENOTSUP;
458*a5a8beb5SDenis Pryazhennikov goto fail1;
459*a5a8beb5SDenis Pryazhennikov }
460*a5a8beb5SDenis Pryazhennikov
461*a5a8beb5SDenis Pryazhennikov if ((data_size % sizeof(uint32_t)) != 0) {
462*a5a8beb5SDenis Pryazhennikov rc = EINVAL;
463*a5a8beb5SDenis Pryazhennikov goto fail2;
464*a5a8beb5SDenis Pryazhennikov }
465*a5a8beb5SDenis Pryazhennikov
466*a5a8beb5SDenis Pryazhennikov if ((data_size == 0) || (data_size > EFX_TABLE_ENTRY_LENGTH_MAX)) {
467*a5a8beb5SDenis Pryazhennikov rc = EINVAL;
468*a5a8beb5SDenis Pryazhennikov goto fail3;
469*a5a8beb5SDenis Pryazhennikov }
470*a5a8beb5SDenis Pryazhennikov
471*a5a8beb5SDenis Pryazhennikov n_dwords = data_size / sizeof(uint32_t);
472*a5a8beb5SDenis Pryazhennikov
473*a5a8beb5SDenis Pryazhennikov req.emr_cmd = MC_CMD_TABLE_DELETE;
474*a5a8beb5SDenis Pryazhennikov req.emr_in_buf = payload;
475*a5a8beb5SDenis Pryazhennikov req.emr_in_length = MC_CMD_TABLE_DELETE_IN_LEN(n_dwords);
476*a5a8beb5SDenis Pryazhennikov req.emr_out_buf = payload;
477*a5a8beb5SDenis Pryazhennikov req.emr_out_length = MC_CMD_TABLE_DELETE_OUT_LEN;
478*a5a8beb5SDenis Pryazhennikov
479*a5a8beb5SDenis Pryazhennikov MCDI_IN_SET_DWORD(req, TABLE_DELETE_IN_TABLE_ID, (uint32_t)table_id);
480*a5a8beb5SDenis Pryazhennikov MCDI_IN_SET_WORD(req, TABLE_DELETE_IN_MASK_ID, mask_id);
481*a5a8beb5SDenis Pryazhennikov MCDI_IN_SET_WORD(req, TABLE_DELETE_IN_KEY_WIDTH, key_width);
482*a5a8beb5SDenis Pryazhennikov MCDI_IN_SET_WORD(req, TABLE_DELETE_IN_MASK_WIDTH, mask_width);
483*a5a8beb5SDenis Pryazhennikov
484*a5a8beb5SDenis Pryazhennikov
485*a5a8beb5SDenis Pryazhennikov memcpy(MCDI_IN2(req, uint8_t, TABLE_DELETE_IN_DATA), entry_datap, data_size);
486*a5a8beb5SDenis Pryazhennikov
487*a5a8beb5SDenis Pryazhennikov efx_mcdi_execute(enp, &req);
488*a5a8beb5SDenis Pryazhennikov
489*a5a8beb5SDenis Pryazhennikov if (req.emr_rc != 0) {
490*a5a8beb5SDenis Pryazhennikov rc = req.emr_rc;
491*a5a8beb5SDenis Pryazhennikov goto fail4;
492*a5a8beb5SDenis Pryazhennikov }
493*a5a8beb5SDenis Pryazhennikov
494*a5a8beb5SDenis Pryazhennikov return (0);
495*a5a8beb5SDenis Pryazhennikov
496*a5a8beb5SDenis Pryazhennikov fail4:
497*a5a8beb5SDenis Pryazhennikov EFSYS_PROBE(fail4);
498*a5a8beb5SDenis Pryazhennikov
499*a5a8beb5SDenis Pryazhennikov fail3:
500*a5a8beb5SDenis Pryazhennikov EFSYS_PROBE(fail3);
501*a5a8beb5SDenis Pryazhennikov fail2:
502*a5a8beb5SDenis Pryazhennikov EFSYS_PROBE(fail2);
503*a5a8beb5SDenis Pryazhennikov fail1:
504*a5a8beb5SDenis Pryazhennikov EFSYS_PROBE1(fail1, efx_rc_t, rc);
505*a5a8beb5SDenis Pryazhennikov return (rc);
506*a5a8beb5SDenis Pryazhennikov }
507