common/sfc_efx/base: support UDP tunnel operations for EF100
[dpdk.git] / drivers / common / sfc_efx / base / rhead_rx.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Copyright(c) 2019-2020 Xilinx, Inc.
4  * Copyright(c) 2018-2019 Solarflare Communications Inc.
5  */
6
7 #include "efx.h"
8 #include "efx_impl.h"
9
10
11 #if EFSYS_OPT_RIVERHEAD
12
13 /*
14  * Maximum number of Rx prefixes supported by Rx prefix choice to be
15  * returned from firmware.
16  */
17 #define RHEAD_RX_PREFIX_IDS_MAX         16
18
19 /*
20  * Default Rx prefix layout on Riverhead if FW does not support Rx
21  * prefix choice using MC_CMD_GET_RX_PREFIX_ID and query its layout
22  * using MC_CMD_QUERY_RX_PREFIX_ID.
23  *
24  * See SF-119689-TC Riverhead Host Interface section 6.4.
25  */
26 static const efx_rx_prefix_layout_t rhead_default_rx_prefix_layout = {
27         .erpl_id        = 0,
28         .erpl_length    = ESE_GZ_RX_PKT_PREFIX_LEN,
29         .erpl_fields    = {
30 #define RHEAD_RX_PREFIX_FIELD(_name, _big_endian) \
31         EFX_RX_PREFIX_FIELD(_name, ESF_GZ_RX_PREFIX_ ## _name, _big_endian)
32
33                 RHEAD_RX_PREFIX_FIELD(LENGTH, B_FALSE),
34                 RHEAD_RX_PREFIX_FIELD(RSS_HASH_VALID, B_FALSE),
35                 RHEAD_RX_PREFIX_FIELD(USER_FLAG, B_FALSE),
36                 RHEAD_RX_PREFIX_FIELD(CLASS, B_FALSE),
37                 RHEAD_RX_PREFIX_FIELD(PARTIAL_TSTAMP, B_FALSE),
38                 RHEAD_RX_PREFIX_FIELD(RSS_HASH, B_FALSE),
39                 RHEAD_RX_PREFIX_FIELD(USER_MARK, B_FALSE),
40                 RHEAD_RX_PREFIX_FIELD(INGRESS_VPORT, B_FALSE),
41                 RHEAD_RX_PREFIX_FIELD(CSUM_FRAME, B_TRUE),
42                 RHEAD_RX_PREFIX_FIELD(VLAN_STRIP_TCI, B_TRUE),
43
44 #undef  RHEAD_RX_PREFIX_FIELD
45         }
46 };
47
48         __checkReturn   efx_rc_t
49 rhead_rx_init(
50         __in            efx_nic_t *enp)
51 {
52         efx_rc_t rc;
53
54         rc = ef10_rx_init(enp);
55         if (rc != 0)
56                 goto fail1;
57
58         return (0);
59
60 fail1:
61         EFSYS_PROBE1(fail1, efx_rc_t, rc);
62         return (rc);
63 }
64
65                 void
66 rhead_rx_fini(
67         __in    efx_nic_t *enp)
68 {
69         ef10_rx_fini(enp);
70 }
71
72 #if EFSYS_OPT_RX_SCATTER
73         __checkReturn   efx_rc_t
74 rhead_rx_scatter_enable(
75         __in            efx_nic_t *enp,
76         __in            unsigned int buf_size)
77 {
78         _NOTE(ARGUNUSED(enp, buf_size))
79         /* Nothing to do here */
80         return (0);
81 }
82 #endif  /* EFSYS_OPT_RX_SCATTER */
83
84 #if EFSYS_OPT_RX_SCALE
85
86         __checkReturn   efx_rc_t
87 rhead_rx_scale_context_alloc(
88         __in            efx_nic_t *enp,
89         __in            efx_rx_scale_context_type_t type,
90         __in            uint32_t num_queues,
91         __out           uint32_t *rss_contextp)
92 {
93         efx_rc_t rc;
94
95         rc = ef10_rx_scale_context_alloc(enp, type, num_queues, rss_contextp);
96         if (rc != 0)
97                 goto fail1;
98
99         return (0);
100
101 fail1:
102         EFSYS_PROBE1(fail1, efx_rc_t, rc);
103         return (rc);
104 }
105
106         __checkReturn   efx_rc_t
107 rhead_rx_scale_context_free(
108         __in            efx_nic_t *enp,
109         __in            uint32_t rss_context)
110 {
111         efx_rc_t rc;
112
113         rc = ef10_rx_scale_context_free(enp, rss_context);
114         if (rc != 0)
115                 goto fail1;
116
117         return (0);
118
119 fail1:
120         EFSYS_PROBE1(fail1, efx_rc_t, rc);
121         return (rc);
122 }
123
124         __checkReturn   efx_rc_t
125 rhead_rx_scale_mode_set(
126         __in            efx_nic_t *enp,
127         __in            uint32_t rss_context,
128         __in            efx_rx_hash_alg_t alg,
129         __in            efx_rx_hash_type_t type,
130         __in            boolean_t insert)
131 {
132         efx_rc_t rc;
133
134         rc = ef10_rx_scale_mode_set(enp, rss_context, alg, type, insert);
135         if (rc != 0)
136                 goto fail1;
137
138         return (0);
139
140 fail1:
141         EFSYS_PROBE1(fail1, efx_rc_t, rc);
142         return (rc);
143 }
144
145         __checkReturn   efx_rc_t
146 rhead_rx_scale_key_set(
147         __in            efx_nic_t *enp,
148         __in            uint32_t rss_context,
149         __in_ecount(n)  uint8_t *key,
150         __in            size_t n)
151 {
152         efx_rc_t rc;
153
154         rc = ef10_rx_scale_key_set(enp, rss_context, key, n);
155         if (rc != 0)
156                 goto fail1;
157
158         return (0);
159
160 fail1:
161         EFSYS_PROBE1(fail1, efx_rc_t, rc);
162         return (rc);
163 }
164
165         __checkReturn   efx_rc_t
166 rhead_rx_scale_tbl_set(
167         __in            efx_nic_t *enp,
168         __in            uint32_t rss_context,
169         __in_ecount(n)  unsigned int *table,
170         __in            size_t n)
171 {
172         efx_rc_t rc;
173
174         rc = ef10_rx_scale_tbl_set(enp, rss_context, table, n);
175         if (rc != 0)
176                 goto fail1;
177
178         return (0);
179
180 fail1:
181         EFSYS_PROBE1(fail1, efx_rc_t, rc);
182         return (rc);
183 }
184
185         __checkReturn   uint32_t
186 rhead_rx_prefix_hash(
187         __in            efx_nic_t *enp,
188         __in            efx_rx_hash_alg_t func,
189         __in            uint8_t *buffer)
190 {
191         _NOTE(ARGUNUSED(enp, func, buffer))
192
193         /* FIXME implement the method for Riverhead */
194
195         return (ENOTSUP);
196 }
197
198 #endif /* EFSYS_OPT_RX_SCALE */
199
200         __checkReturn   efx_rc_t
201 rhead_rx_prefix_pktlen(
202         __in            efx_nic_t *enp,
203         __in            uint8_t *buffer,
204         __out           uint16_t *lengthp)
205 {
206         _NOTE(ARGUNUSED(enp, buffer, lengthp))
207
208         /* FIXME implement the method for Riverhead */
209
210         return (ENOTSUP);
211 }
212
213                                 void
214 rhead_rx_qpost(
215         __in                    efx_rxq_t *erp,
216         __in_ecount(ndescs)     efsys_dma_addr_t *addrp,
217         __in                    size_t size,
218         __in                    unsigned int ndescs,
219         __in                    unsigned int completed,
220         __in                    unsigned int added)
221 {
222         _NOTE(ARGUNUSED(erp, addrp, size, ndescs, completed, added))
223
224         /* FIXME implement the method for Riverhead */
225
226         EFSYS_ASSERT(B_FALSE);
227 }
228
229                         void
230 rhead_rx_qpush(
231         __in    efx_rxq_t *erp,
232         __in    unsigned int added,
233         __inout unsigned int *pushedp)
234 {
235         _NOTE(ARGUNUSED(erp, added, pushedp))
236
237         /* FIXME implement the method for Riverhead */
238
239         EFSYS_ASSERT(B_FALSE);
240 }
241
242         __checkReturn   efx_rc_t
243 rhead_rx_qflush(
244         __in    efx_rxq_t *erp)
245 {
246         efx_nic_t *enp = erp->er_enp;
247         efx_rc_t rc;
248
249         if ((rc = efx_mcdi_fini_rxq(enp, erp->er_index)) != 0)
250                 goto fail1;
251
252         return (0);
253
254 fail1:
255         /*
256          * EALREADY is not an error, but indicates that the MC has rebooted and
257          * that the RXQ has already been destroyed. Callers need to know that
258          * the RXQ flush has completed to avoid waiting until timeout for a
259          * flush done event that will not be delivered.
260          */
261         if (rc != EALREADY)
262                 EFSYS_PROBE1(fail1, efx_rc_t, rc);
263
264         return (rc);
265 }
266
267                 void
268 rhead_rx_qenable(
269         __in    efx_rxq_t *erp)
270 {
271         _NOTE(ARGUNUSED(erp))
272 }
273
274 static  __checkReturn   efx_rc_t
275 efx_mcdi_get_rx_prefix_ids(
276         __in                                    efx_nic_t *enp,
277         __in                                    uint32_t mcdi_fields_mask,
278         __in                                    unsigned int max_ids,
279         __out                                   unsigned int *nids,
280         __out_ecount_part(max_ids, *nids)       uint32_t *idsp)
281 {
282         efx_mcdi_req_t req;
283         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_RX_PREFIX_ID_IN_LEN,
284                 MC_CMD_GET_RX_PREFIX_ID_OUT_LENMAX);
285         efx_rc_t rc;
286         uint32_t num;
287
288         req.emr_cmd = MC_CMD_GET_RX_PREFIX_ID;
289         req.emr_in_buf = payload;
290         req.emr_in_length = MC_CMD_GET_RX_PREFIX_ID_IN_LEN;
291         req.emr_out_buf = payload;
292         req.emr_out_length = MC_CMD_GET_RX_PREFIX_ID_OUT_LENMAX;
293
294         MCDI_IN_SET_DWORD(req, GET_RX_PREFIX_ID_IN_FIELDS, mcdi_fields_mask);
295
296         efx_mcdi_execute(enp, &req);
297
298         if (req.emr_rc != 0) {
299                 rc = req.emr_rc;
300                 goto fail1;
301         }
302
303         if (req.emr_out_length_used < MC_CMD_GET_RX_PREFIX_ID_OUT_LENMIN) {
304                 rc = EMSGSIZE;
305                 goto fail2;
306         }
307
308         num = MCDI_OUT_DWORD(req, GET_RX_PREFIX_ID_OUT_NUM_RX_PREFIX_IDS);
309
310         if (req.emr_out_length_used != MC_CMD_GET_RX_PREFIX_ID_OUT_LEN(num)) {
311                 rc = EMSGSIZE;
312                 goto fail3;
313         }
314
315         *nids = MIN(num, max_ids);
316
317         EFX_STATIC_ASSERT(sizeof (idsp[0]) ==
318             MC_CMD_GET_RX_PREFIX_ID_OUT_RX_PREFIX_ID_LEN);
319         memcpy(idsp,
320             MCDI_OUT2(req, uint32_t, GET_RX_PREFIX_ID_OUT_RX_PREFIX_ID),
321             *nids * sizeof (idsp[0]));
322
323         return (0);
324
325 fail3:
326         EFSYS_PROBE(fail3);
327 fail2:
328         EFSYS_PROBE(fail2);
329 fail1:
330         EFSYS_PROBE1(fail1, efx_rc_t, rc);
331
332         return (rc);
333 }
334
335 static  __checkReturn   efx_rx_prefix_field_t
336 efx_mcdi_rx_prefix_field_map(unsigned int mcdi_idx)
337 {
338         static const efx_rx_prefix_field_t efx_mcdi_to_rx_prefix_field[] = {
339 #define EFX_MCDI_TO_RX_PREFIX_FIELD(_field) \
340         [RX_PREFIX_FIELD_INFO_ ## _field] = EFX_RX_PREFIX_FIELD_ ## _field
341
342                 EFX_MCDI_TO_RX_PREFIX_FIELD(LENGTH),
343                 EFX_MCDI_TO_RX_PREFIX_FIELD(RSS_HASH_VALID),
344                 EFX_MCDI_TO_RX_PREFIX_FIELD(USER_FLAG),
345                 EFX_MCDI_TO_RX_PREFIX_FIELD(CLASS),
346                 EFX_MCDI_TO_RX_PREFIX_FIELD(PARTIAL_TSTAMP),
347                 EFX_MCDI_TO_RX_PREFIX_FIELD(RSS_HASH),
348                 EFX_MCDI_TO_RX_PREFIX_FIELD(USER_MARK),
349                 EFX_MCDI_TO_RX_PREFIX_FIELD(INGRESS_VPORT),
350                 EFX_MCDI_TO_RX_PREFIX_FIELD(CSUM_FRAME),
351                 EFX_MCDI_TO_RX_PREFIX_FIELD(VLAN_STRIP_TCI),
352
353 #undef  EFX_MCDI_TO_RX_PREFIX_FIELD
354         };
355
356         if (mcdi_idx >= EFX_ARRAY_SIZE(efx_mcdi_to_rx_prefix_field))
357                 return (EFX_RX_PREFIX_NFIELDS);
358
359         return (efx_mcdi_to_rx_prefix_field[mcdi_idx]);
360 }
361
362 static  __checkReturn   int
363 efx_rx_prefix_field_map_to_mcdi(
364         __in            efx_rx_prefix_field_t field)
365 {
366         static const int efx_rx_prefix_field_to_mcdi[] = {
367                 [EFX_RX_PREFIX_FIELD_LENGTH] =
368                         EFX_LOW_BIT(MC_CMD_GET_RX_PREFIX_ID_IN_LENGTH),
369                 [EFX_RX_PREFIX_FIELD_ORIG_LENGTH] = -1,
370                 [EFX_RX_PREFIX_FIELD_CLASS] =
371                         EFX_LOW_BIT(MC_CMD_GET_RX_PREFIX_ID_IN_CLASS),
372                 [EFX_RX_PREFIX_FIELD_RSS_HASH] =
373                         EFX_LOW_BIT(MC_CMD_GET_RX_PREFIX_ID_IN_RSS_HASH),
374                 [EFX_RX_PREFIX_FIELD_RSS_HASH_VALID] =
375                         EFX_LOW_BIT(MC_CMD_GET_RX_PREFIX_ID_IN_RSS_HASH_VALID),
376                 [EFX_RX_PREFIX_FIELD_PARTIAL_TSTAMP] =
377                         EFX_LOW_BIT(MC_CMD_GET_RX_PREFIX_ID_IN_PARTIAL_TSTAMP),
378                 [EFX_RX_PREFIX_FIELD_VLAN_STRIP_TCI] =
379                         EFX_LOW_BIT(MC_CMD_GET_RX_PREFIX_ID_IN_VLAN_STRIP_TCI),
380                 [EFX_RX_PREFIX_FIELD_INNER_VLAN_STRIP_TCI] = -1,
381                 [EFX_RX_PREFIX_FIELD_USER_FLAG] =
382                         EFX_LOW_BIT(MC_CMD_GET_RX_PREFIX_ID_IN_USER_FLAG),
383                 [EFX_RX_PREFIX_FIELD_USER_MARK] =
384                         EFX_LOW_BIT(MC_CMD_GET_RX_PREFIX_ID_IN_USER_MARK),
385                 [EFX_RX_PREFIX_FIELD_USER_MARK_VALID] = -1,
386                 [EFX_RX_PREFIX_FIELD_CSUM_FRAME] =
387                         EFX_LOW_BIT(MC_CMD_GET_RX_PREFIX_ID_IN_CSUM_FRAME),
388                 [EFX_RX_PREFIX_FIELD_INGRESS_VPORT] =
389                         EFX_LOW_BIT(MC_CMD_GET_RX_PREFIX_ID_IN_INGRESS_VPORT),
390         };
391
392         if (field >= EFX_ARRAY_SIZE(efx_rx_prefix_field_to_mcdi))
393                 return (-1);
394
395         return (efx_rx_prefix_field_to_mcdi[field]);
396 }
397
398 static  __checkReturn   efx_rc_t
399 efx_rx_prefix_fields_mask_to_mcdi(
400         __in            uint32_t fields_mask,
401         __out           uint32_t *mcdi_fields_maskp)
402 {
403         uint32_t mcdi_fields_mask = 0;
404         unsigned int i;
405
406         for (i = 0; i < EFX_RX_PREFIX_NFIELDS; ++i) {
407                 if (fields_mask & (1U << i)) {
408                         int mcdi_field = efx_rx_prefix_field_map_to_mcdi(i);
409
410                         if (mcdi_field < 0)
411                                 return (EINVAL);
412
413                         mcdi_fields_mask |= (1U << mcdi_field);
414                 }
415         }
416
417         *mcdi_fields_maskp = mcdi_fields_mask;
418         return (0);
419 }
420
421 static  __checkReturn   efx_rc_t
422 efx_mcdi_query_rx_prefix_id(
423         __in            efx_nic_t *enp,
424         __in            uint32_t prefix_id,
425         __out           efx_rx_prefix_layout_t *erplp)
426 {
427         efx_mcdi_req_t req;
428         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_QUERY_RX_PREFIX_ID_IN_LEN,
429                 MC_CMD_QUERY_RX_PREFIX_ID_OUT_LENMAX);
430         efx_rc_t rc;
431         size_t response_len;
432         const efx_dword_t *resp;
433         const efx_dword_t *finfo;
434         unsigned int num_fields;
435         unsigned int mcdi_field;
436         efx_rx_prefix_field_t field;
437         unsigned int i;
438
439         req.emr_cmd = MC_CMD_QUERY_RX_PREFIX_ID;
440         req.emr_in_buf = payload;
441         req.emr_in_length = MC_CMD_QUERY_RX_PREFIX_ID_IN_LEN;
442         req.emr_out_buf = payload;
443         req.emr_out_length = MC_CMD_QUERY_RX_PREFIX_ID_OUT_LENMAX;
444
445         MCDI_IN_SET_DWORD(req, QUERY_RX_PREFIX_ID_IN_RX_PREFIX_ID, prefix_id);
446
447         efx_mcdi_execute(enp, &req);
448
449         if (req.emr_rc != 0) {
450                 rc = req.emr_rc;
451                 goto fail1;
452         }
453
454         if (req.emr_out_length_used < MC_CMD_QUERY_RX_PREFIX_ID_OUT_LENMIN) {
455                 rc = EMSGSIZE;
456                 goto fail2;
457         }
458
459         if (MCDI_OUT_BYTE(req, QUERY_RX_PREFIX_ID_OUT_RESPONSE_TYPE) !=
460             MC_CMD_QUERY_RX_PREFIX_ID_OUT_RESPONSE_TYPE_FIXED) {
461                 rc = ENOTSUP;
462                 goto fail3;
463         }
464
465         EFX_STATIC_ASSERT(MC_CMD_QUERY_RX_PREFIX_ID_OUT_LENMIN >=
466             MC_CMD_QUERY_RX_PREFIX_ID_OUT_RESPONSE_OFST);
467         response_len = req.emr_out_length_used -
468             MC_CMD_QUERY_RX_PREFIX_ID_OUT_RESPONSE_OFST;
469
470         if (response_len < RX_PREFIX_FIXED_RESPONSE_LENMIN) {
471                 rc = EMSGSIZE;
472                 goto fail4;
473         }
474
475         resp = MCDI_OUT2(req, efx_dword_t, QUERY_RX_PREFIX_ID_OUT_RESPONSE);
476
477         memset(erplp, 0, sizeof (*erplp));
478         erplp->erpl_id = prefix_id;
479         erplp->erpl_length =
480             EFX_DWORD_FIELD(*resp, RX_PREFIX_FIXED_RESPONSE_PREFIX_LENGTH_BYTES);
481         num_fields =
482             EFX_DWORD_FIELD(*resp, RX_PREFIX_FIXED_RESPONSE_FIELD_COUNT);
483
484         if (response_len < RX_PREFIX_FIXED_RESPONSE_LEN(num_fields)) {
485                 rc = EMSGSIZE;
486                 goto fail5;
487         }
488
489         finfo = (const efx_dword_t *)((const uint8_t *)resp +
490              RX_PREFIX_FIXED_RESPONSE_FIELDS_OFST);
491
492         for (i = 0; i < num_fields; ++i, ++finfo) {
493                 mcdi_field = EFX_DWORD_FIELD(*finfo, RX_PREFIX_FIELD_INFO_TYPE);
494
495                 field = efx_mcdi_rx_prefix_field_map(mcdi_field);
496                 if (field >= EFX_RX_PREFIX_NFIELDS)
497                         continue;
498
499                 erplp->erpl_fields[field].erpfi_offset_bits =
500                     EFX_DWORD_FIELD(*finfo, RX_PREFIX_FIELD_INFO_OFFSET_BITS);
501                 erplp->erpl_fields[field].erpfi_width_bits =
502                     EFX_DWORD_FIELD(*finfo, RX_PREFIX_FIELD_INFO_WIDTH_BITS);
503         }
504
505         return (0);
506
507 fail5:
508         EFSYS_PROBE(fail5);
509 fail4:
510         EFSYS_PROBE(fail4);
511 fail3:
512         EFSYS_PROBE(fail3);
513 fail2:
514         EFSYS_PROBE(fail2);
515 fail1:
516         EFSYS_PROBE1(fail1, efx_rc_t, rc);
517
518         return (rc);
519 }
520
521 static  __checkReturn   efx_rc_t
522 rhead_rx_choose_prefix_id(
523         __in            efx_nic_t *enp,
524         __in            uint32_t fields_mask,
525         __out           efx_rx_prefix_layout_t *erplp)
526 {
527         efx_rx_prefix_layout_t erpl;
528         uint32_t prefix_ids[RHEAD_RX_PREFIX_IDS_MAX];
529         uint32_t mcdi_fields_mask;
530         unsigned int num = 0;
531         unsigned int i;
532         efx_rc_t rc;
533
534         rc = efx_rx_prefix_fields_mask_to_mcdi(fields_mask, &mcdi_fields_mask);
535         if (rc != 0)
536                 goto fail1;
537
538         memset(erplp, 0, sizeof (*erplp));
539
540         rc = efx_mcdi_get_rx_prefix_ids(enp, mcdi_fields_mask,
541             EFX_ARRAY_SIZE(prefix_ids), &num, prefix_ids);
542         if (rc == ENOTSUP) {
543                 /* Not supported MCDI, use default prefix ID */
544                 *erplp = rhead_default_rx_prefix_layout;
545                 goto done;
546         }
547         if (rc != 0)
548                 goto fail2;
549
550         if (num == 0) {
551                 rc = ENOTSUP;
552                 goto fail3;
553         }
554
555         for (i = 0; i < num; ++i) {
556                 rc = efx_mcdi_query_rx_prefix_id(enp, prefix_ids[i], &erpl);
557                 if (rc != 0)
558                         goto fail4;
559
560                 /* Choose the smallest prefix which meets our requirements */
561                 if (i == 0 || erpl.erpl_length < erplp->erpl_length)
562                         *erplp = erpl;
563         }
564
565 done:
566         return (0);
567
568 fail4:
569         EFSYS_PROBE(fail4);
570 fail3:
571         EFSYS_PROBE(fail3);
572 fail2:
573         EFSYS_PROBE(fail2);
574 fail1:
575         EFSYS_PROBE1(fail1, efx_rc_t, rc);
576
577         return (rc);
578 }
579
580         __checkReturn   efx_rc_t
581 rhead_rx_qcreate(
582         __in            efx_nic_t *enp,
583         __in            unsigned int index,
584         __in            unsigned int label,
585         __in            efx_rxq_type_t type,
586         __in            const efx_rxq_type_data_t *type_data,
587         __in            efsys_mem_t *esmp,
588         __in            size_t ndescs,
589         __in            uint32_t id,
590         __in            unsigned int flags,
591         __in            efx_evq_t *eep,
592         __in            efx_rxq_t *erp)
593 {
594         const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
595         efx_mcdi_init_rxq_params_t params;
596         efx_rx_prefix_layout_t erpl;
597         efx_rc_t rc;
598
599         _NOTE(ARGUNUSED(id))
600
601         EFX_STATIC_ASSERT(EFX_EV_RX_NLABELS <=
602             (1 << ESF_GZ_EV_RXPKTS_Q_LABEL_WIDTH));
603         EFSYS_ASSERT3U(label, <, EFX_EV_RX_NLABELS);
604
605         memset(&params, 0, sizeof (params));
606
607         switch (type) {
608         case EFX_RXQ_TYPE_DEFAULT:
609                 if (type_data == NULL) {
610                         rc = EINVAL;
611                         goto fail1;
612                 }
613                 params.buf_size = type_data->ertd_default.ed_buf_size;
614                 break;
615         default:
616                 rc = ENOTSUP;
617                 goto fail2;
618         }
619
620         /* Scatter can only be disabled if the firmware supports doing so */
621         if (flags & EFX_RXQ_FLAG_SCATTER)
622                 params.disable_scatter = B_FALSE;
623         else
624                 params.disable_scatter = encp->enc_rx_disable_scatter_supported;
625
626         /*
627          * LENGTH is required in EF100 host interface, as receive events
628          * do not include the packet length.
629          * NOTE: Required fields are hard-wired now. Future designs will
630          * want to allow the client (driver) code to have control over
631          * which fields are required or may be allow to request so-called
632          * default Rx prefix (which ID is equal to 0).
633          */
634         if ((rc = rhead_rx_choose_prefix_id(enp,
635             (1U << EFX_RX_PREFIX_FIELD_LENGTH), &erpl)) != 0)
636                 goto fail3;
637
638         params.prefix_id = erpl.erpl_id;
639
640         /*
641          * Ignore EFX_RXQ_FLAG_INNER_CLASSES since in accordance with
642          * EF100 host interface both inner and outer classes are provided
643          * by HW if applicable.
644          */
645
646         if ((rc = efx_mcdi_init_rxq(enp, ndescs, eep, label, index,
647                     esmp, &params)) != 0)
648                 goto fail4;
649
650         erp->er_eep = eep;
651         erp->er_label = label;
652         erp->er_buf_size = params.buf_size;
653         erp->er_prefix_layout = erpl;
654
655         return (0);
656
657 fail4:
658         EFSYS_PROBE(fail4);
659 fail3:
660         EFSYS_PROBE(fail3);
661 fail2:
662         EFSYS_PROBE(fail2);
663 fail1:
664         EFSYS_PROBE1(fail1, efx_rc_t, rc);
665
666         return (rc);
667 }
668
669                 void
670 rhead_rx_qdestroy(
671         __in    efx_rxq_t *erp)
672 {
673         _NOTE(ARGUNUSED(erp))
674         /* Nothing to do here */
675 }
676
677 #endif /* EFSYS_OPT_RIVERHEAD */