2899a0f296179b03609d4816fe9597335089b980
[dpdk.git] / drivers / net / sfc / base / efx_rx.c
1 /*
2  * Copyright (c) 2007-2016 Solarflare Communications Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  *    this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright notice,
11  *    this list of conditions and the following disclaimer in the documentation
12  *    and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  * The views and conclusions contained in the software and documentation are
27  * those of the authors and should not be interpreted as representing official
28  * policies, either expressed or implied, of the FreeBSD Project.
29  */
30
31 #include "efx.h"
32 #include "efx_impl.h"
33
34
35 #if EFSYS_OPT_SIENA
36
37 static  __checkReturn   efx_rc_t
38 siena_rx_init(
39         __in            efx_nic_t *enp);
40
41 static                  void
42 siena_rx_fini(
43         __in            efx_nic_t *enp);
44
45 static  __checkReturn   efx_rc_t
46 siena_rx_prefix_pktlen(
47         __in            efx_nic_t *enp,
48         __in            uint8_t *buffer,
49         __out           uint16_t *lengthp);
50
51 static                  void
52 siena_rx_qpost(
53         __in            efx_rxq_t *erp,
54         __in_ecount(n)  efsys_dma_addr_t *addrp,
55         __in            size_t size,
56         __in            unsigned int n,
57         __in            unsigned int completed,
58         __in            unsigned int added);
59
60 static                  void
61 siena_rx_qpush(
62         __in            efx_rxq_t *erp,
63         __in            unsigned int added,
64         __inout         unsigned int *pushedp);
65
66 static  __checkReturn   efx_rc_t
67 siena_rx_qflush(
68         __in            efx_rxq_t *erp);
69
70 static                  void
71 siena_rx_qenable(
72         __in            efx_rxq_t *erp);
73
74 static  __checkReturn   efx_rc_t
75 siena_rx_qcreate(
76         __in            efx_nic_t *enp,
77         __in            unsigned int index,
78         __in            unsigned int label,
79         __in            efx_rxq_type_t type,
80         __in            efsys_mem_t *esmp,
81         __in            size_t n,
82         __in            uint32_t id,
83         __in            efx_evq_t *eep,
84         __in            efx_rxq_t *erp);
85
86 static                  void
87 siena_rx_qdestroy(
88         __in            efx_rxq_t *erp);
89
90 #endif /* EFSYS_OPT_SIENA */
91
92
93 #if EFSYS_OPT_SIENA
94 static const efx_rx_ops_t __efx_rx_siena_ops = {
95         siena_rx_init,                          /* erxo_init */
96         siena_rx_fini,                          /* erxo_fini */
97         siena_rx_prefix_pktlen,                 /* erxo_prefix_pktlen */
98         siena_rx_qpost,                         /* erxo_qpost */
99         siena_rx_qpush,                         /* erxo_qpush */
100         siena_rx_qflush,                        /* erxo_qflush */
101         siena_rx_qenable,                       /* erxo_qenable */
102         siena_rx_qcreate,                       /* erxo_qcreate */
103         siena_rx_qdestroy,                      /* erxo_qdestroy */
104 };
105 #endif  /* EFSYS_OPT_SIENA */
106
107 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
108 static const efx_rx_ops_t __efx_rx_ef10_ops = {
109         ef10_rx_init,                           /* erxo_init */
110         ef10_rx_fini,                           /* erxo_fini */
111         ef10_rx_prefix_pktlen,                  /* erxo_prefix_pktlen */
112         ef10_rx_qpost,                          /* erxo_qpost */
113         ef10_rx_qpush,                          /* erxo_qpush */
114         ef10_rx_qflush,                         /* erxo_qflush */
115         ef10_rx_qenable,                        /* erxo_qenable */
116         ef10_rx_qcreate,                        /* erxo_qcreate */
117         ef10_rx_qdestroy,                       /* erxo_qdestroy */
118 };
119 #endif  /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
120
121
122         __checkReturn   efx_rc_t
123 efx_rx_init(
124         __inout         efx_nic_t *enp)
125 {
126         const efx_rx_ops_t *erxop;
127         efx_rc_t rc;
128
129         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
130         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
131
132         if (!(enp->en_mod_flags & EFX_MOD_EV)) {
133                 rc = EINVAL;
134                 goto fail1;
135         }
136
137         if (enp->en_mod_flags & EFX_MOD_RX) {
138                 rc = EINVAL;
139                 goto fail2;
140         }
141
142         switch (enp->en_family) {
143 #if EFSYS_OPT_SIENA
144         case EFX_FAMILY_SIENA:
145                 erxop = &__efx_rx_siena_ops;
146                 break;
147 #endif /* EFSYS_OPT_SIENA */
148
149 #if EFSYS_OPT_HUNTINGTON
150         case EFX_FAMILY_HUNTINGTON:
151                 erxop = &__efx_rx_ef10_ops;
152                 break;
153 #endif /* EFSYS_OPT_HUNTINGTON */
154
155 #if EFSYS_OPT_MEDFORD
156         case EFX_FAMILY_MEDFORD:
157                 erxop = &__efx_rx_ef10_ops;
158                 break;
159 #endif /* EFSYS_OPT_MEDFORD */
160
161         default:
162                 EFSYS_ASSERT(0);
163                 rc = ENOTSUP;
164                 goto fail3;
165         }
166
167         if ((rc = erxop->erxo_init(enp)) != 0)
168                 goto fail4;
169
170         enp->en_erxop = erxop;
171         enp->en_mod_flags |= EFX_MOD_RX;
172         return (0);
173
174 fail4:
175         EFSYS_PROBE(fail4);
176 fail3:
177         EFSYS_PROBE(fail3);
178 fail2:
179         EFSYS_PROBE(fail2);
180 fail1:
181         EFSYS_PROBE1(fail1, efx_rc_t, rc);
182
183         enp->en_erxop = NULL;
184         enp->en_mod_flags &= ~EFX_MOD_RX;
185         return (rc);
186 }
187
188                         void
189 efx_rx_fini(
190         __in            efx_nic_t *enp)
191 {
192         const efx_rx_ops_t *erxop = enp->en_erxop;
193
194         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
195         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
196         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX);
197         EFSYS_ASSERT3U(enp->en_rx_qcount, ==, 0);
198
199         erxop->erxo_fini(enp);
200
201         enp->en_erxop = NULL;
202         enp->en_mod_flags &= ~EFX_MOD_RX;
203 }
204
205                         void
206 efx_rx_qpost(
207         __in            efx_rxq_t *erp,
208         __in_ecount(n)  efsys_dma_addr_t *addrp,
209         __in            size_t size,
210         __in            unsigned int n,
211         __in            unsigned int completed,
212         __in            unsigned int added)
213 {
214         efx_nic_t *enp = erp->er_enp;
215         const efx_rx_ops_t *erxop = enp->en_erxop;
216
217         EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
218
219         erxop->erxo_qpost(erp, addrp, size, n, completed, added);
220 }
221
222                         void
223 efx_rx_qpush(
224         __in            efx_rxq_t *erp,
225         __in            unsigned int added,
226         __inout         unsigned int *pushedp)
227 {
228         efx_nic_t *enp = erp->er_enp;
229         const efx_rx_ops_t *erxop = enp->en_erxop;
230
231         EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
232
233         erxop->erxo_qpush(erp, added, pushedp);
234 }
235
236         __checkReturn   efx_rc_t
237 efx_rx_qflush(
238         __in            efx_rxq_t *erp)
239 {
240         efx_nic_t *enp = erp->er_enp;
241         const efx_rx_ops_t *erxop = enp->en_erxop;
242         efx_rc_t rc;
243
244         EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
245
246         if ((rc = erxop->erxo_qflush(erp)) != 0)
247                 goto fail1;
248
249         return (0);
250
251 fail1:
252         EFSYS_PROBE1(fail1, efx_rc_t, rc);
253
254         return (rc);
255 }
256
257                         void
258 efx_rx_qenable(
259         __in            efx_rxq_t *erp)
260 {
261         efx_nic_t *enp = erp->er_enp;
262         const efx_rx_ops_t *erxop = enp->en_erxop;
263
264         EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
265
266         erxop->erxo_qenable(erp);
267 }
268
269         __checkReturn   efx_rc_t
270 efx_rx_qcreate(
271         __in            efx_nic_t *enp,
272         __in            unsigned int index,
273         __in            unsigned int label,
274         __in            efx_rxq_type_t type,
275         __in            efsys_mem_t *esmp,
276         __in            size_t n,
277         __in            uint32_t id,
278         __in            efx_evq_t *eep,
279         __deref_out     efx_rxq_t **erpp)
280 {
281         const efx_rx_ops_t *erxop = enp->en_erxop;
282         efx_rxq_t *erp;
283         efx_rc_t rc;
284
285         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
286         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX);
287
288         /* Allocate an RXQ object */
289         EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (efx_rxq_t), erp);
290
291         if (erp == NULL) {
292                 rc = ENOMEM;
293                 goto fail1;
294         }
295
296         erp->er_magic = EFX_RXQ_MAGIC;
297         erp->er_enp = enp;
298         erp->er_index = index;
299         erp->er_mask = n - 1;
300         erp->er_esmp = esmp;
301
302         if ((rc = erxop->erxo_qcreate(enp, index, label, type, esmp, n, id,
303             eep, erp)) != 0)
304                 goto fail2;
305
306         enp->en_rx_qcount++;
307         *erpp = erp;
308
309         return (0);
310
311 fail2:
312         EFSYS_PROBE(fail2);
313
314         EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_rxq_t), erp);
315 fail1:
316         EFSYS_PROBE1(fail1, efx_rc_t, rc);
317
318         return (rc);
319 }
320
321                         void
322 efx_rx_qdestroy(
323         __in            efx_rxq_t *erp)
324 {
325         efx_nic_t *enp = erp->er_enp;
326         const efx_rx_ops_t *erxop = enp->en_erxop;
327
328         EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
329
330         erxop->erxo_qdestroy(erp);
331 }
332
333         __checkReturn   efx_rc_t
334 efx_pseudo_hdr_pkt_length_get(
335         __in            efx_rxq_t *erp,
336         __in            uint8_t *buffer,
337         __out           uint16_t *lengthp)
338 {
339         efx_nic_t *enp = erp->er_enp;
340         const efx_rx_ops_t *erxop = enp->en_erxop;
341
342         EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
343
344         return (erxop->erxo_prefix_pktlen(enp, buffer, lengthp));
345 }
346
347 #if EFSYS_OPT_SIENA
348
349 static  __checkReturn   efx_rc_t
350 siena_rx_init(
351         __in            efx_nic_t *enp)
352 {
353         efx_oword_t oword;
354         unsigned int index;
355
356         EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword);
357
358         EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_DESC_PUSH_EN, 0);
359         EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_HASH_ALG, 0);
360         EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_IP_HASH, 0);
361         EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_TCP_SUP, 0);
362         EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_HASH_INSRT_HDR, 0);
363         EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_USR_BUF_SIZE, 0x3000 / 32);
364         EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword);
365
366         /* Zero the RSS table */
367         for (index = 0; index < FR_BZ_RX_INDIRECTION_TBL_ROWS;
368             index++) {
369                 EFX_ZERO_OWORD(oword);
370                 EFX_BAR_TBL_WRITEO(enp, FR_BZ_RX_INDIRECTION_TBL,
371                                     index, &oword, B_TRUE);
372         }
373
374         return (0);
375 }
376
377
378 #define EFX_RX_LFSR_HASH(_enp, _insert)                                 \
379         do {                                                            \
380                 efx_oword_t oword;                                      \
381                                                                         \
382                 EFX_BAR_READO((_enp), FR_AZ_RX_CFG_REG, &oword);        \
383                 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_HASH_ALG, 0);      \
384                 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_IP_HASH, 0);       \
385                 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_TCP_SUP, 0);       \
386                 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_HASH_INSRT_HDR,    \
387                     (_insert) ? 1 : 0);                                 \
388                 EFX_BAR_WRITEO((_enp), FR_AZ_RX_CFG_REG, &oword);       \
389                                                                         \
390                 if ((_enp)->en_family == EFX_FAMILY_SIENA) {            \
391                         EFX_BAR_READO((_enp), FR_CZ_RX_RSS_IPV6_REG3,   \
392                             &oword);                                    \
393                         EFX_SET_OWORD_FIELD(oword,                      \
394                             FRF_CZ_RX_RSS_IPV6_THASH_ENABLE, 0);        \
395                         EFX_BAR_WRITEO((_enp), FR_CZ_RX_RSS_IPV6_REG3,  \
396                             &oword);                                    \
397                 }                                                       \
398                                                                         \
399                 _NOTE(CONSTANTCONDITION)                                \
400         } while (B_FALSE)
401
402 #define EFX_RX_TOEPLITZ_IPV4_HASH(_enp, _insert, _ip, _tcp)             \
403         do {                                                            \
404                 efx_oword_t oword;                                      \
405                                                                         \
406                 EFX_BAR_READO((_enp), FR_AZ_RX_CFG_REG, &oword);        \
407                 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_HASH_ALG, 1);      \
408                 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_IP_HASH,           \
409                     (_ip) ? 1 : 0);                                     \
410                 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_TCP_SUP,           \
411                     (_tcp) ? 0 : 1);                                    \
412                 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_HASH_INSRT_HDR,    \
413                     (_insert) ? 1 : 0);                                 \
414                 EFX_BAR_WRITEO((_enp), FR_AZ_RX_CFG_REG, &oword);       \
415                                                                         \
416                 _NOTE(CONSTANTCONDITION)                                \
417         } while (B_FALSE)
418
419 #define EFX_RX_TOEPLITZ_IPV6_HASH(_enp, _ip, _tcp, _rc)                 \
420         do {                                                            \
421                 efx_oword_t oword;                                      \
422                                                                         \
423                 EFX_BAR_READO((_enp), FR_CZ_RX_RSS_IPV6_REG3, &oword);  \
424                 EFX_SET_OWORD_FIELD(oword,                              \
425                     FRF_CZ_RX_RSS_IPV6_THASH_ENABLE, 1);                \
426                 EFX_SET_OWORD_FIELD(oword,                              \
427                     FRF_CZ_RX_RSS_IPV6_IP_THASH_ENABLE, (_ip) ? 1 : 0); \
428                 EFX_SET_OWORD_FIELD(oword,                              \
429                     FRF_CZ_RX_RSS_IPV6_TCP_SUPPRESS, (_tcp) ? 0 : 1);   \
430                 EFX_BAR_WRITEO((_enp), FR_CZ_RX_RSS_IPV6_REG3, &oword); \
431                                                                         \
432                 (_rc) = 0;                                              \
433                                                                         \
434                 _NOTE(CONSTANTCONDITION)                                \
435         } while (B_FALSE)
436
437
438 /*
439  * Falcon/Siena pseudo-header
440  * --------------------------
441  *
442  * Receive packets are prefixed by an optional 16 byte pseudo-header.
443  * The pseudo-header is a byte array of one of the forms:
444  *
445  *  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
446  * xx.xx.xx.xx.xx.xx.xx.xx.xx.xx.xx.xx.TT.TT.TT.TT
447  * xx.xx.xx.xx.xx.xx.xx.xx.xx.xx.xx.xx.xx.xx.LL.LL
448  *
449  * where:
450  *   TT.TT.TT.TT   Toeplitz hash (32-bit big-endian)
451  *   LL.LL         LFSR hash     (16-bit big-endian)
452  */
453
454 static  __checkReturn   efx_rc_t
455 siena_rx_prefix_pktlen(
456         __in            efx_nic_t *enp,
457         __in            uint8_t *buffer,
458         __out           uint16_t *lengthp)
459 {
460         _NOTE(ARGUNUSED(enp, buffer, lengthp))
461
462         /* Not supported by Falcon/Siena hardware */
463         EFSYS_ASSERT(0);
464         return (ENOTSUP);
465 }
466
467
468 static                  void
469 siena_rx_qpost(
470         __in            efx_rxq_t *erp,
471         __in_ecount(n)  efsys_dma_addr_t *addrp,
472         __in            size_t size,
473         __in            unsigned int n,
474         __in            unsigned int completed,
475         __in            unsigned int added)
476 {
477         efx_qword_t qword;
478         unsigned int i;
479         unsigned int offset;
480         unsigned int id;
481
482         /* The client driver must not overfill the queue */
483         EFSYS_ASSERT3U(added - completed + n, <=,
484             EFX_RXQ_LIMIT(erp->er_mask + 1));
485
486         id = added & (erp->er_mask);
487         for (i = 0; i < n; i++) {
488                 EFSYS_PROBE4(rx_post, unsigned int, erp->er_index,
489                     unsigned int, id, efsys_dma_addr_t, addrp[i],
490                     size_t, size);
491
492                 EFX_POPULATE_QWORD_3(qword,
493                     FSF_AZ_RX_KER_BUF_SIZE, (uint32_t)(size),
494                     FSF_AZ_RX_KER_BUF_ADDR_DW0,
495                     (uint32_t)(addrp[i] & 0xffffffff),
496                     FSF_AZ_RX_KER_BUF_ADDR_DW1,
497                     (uint32_t)(addrp[i] >> 32));
498
499                 offset = id * sizeof (efx_qword_t);
500                 EFSYS_MEM_WRITEQ(erp->er_esmp, offset, &qword);
501
502                 id = (id + 1) & (erp->er_mask);
503         }
504 }
505
506 static                  void
507 siena_rx_qpush(
508         __in    efx_rxq_t *erp,
509         __in    unsigned int added,
510         __inout unsigned int *pushedp)
511 {
512         efx_nic_t *enp = erp->er_enp;
513         unsigned int pushed = *pushedp;
514         uint32_t wptr;
515         efx_oword_t oword;
516         efx_dword_t dword;
517
518         /* All descriptors are pushed */
519         *pushedp = added;
520
521         /* Push the populated descriptors out */
522         wptr = added & erp->er_mask;
523
524         EFX_POPULATE_OWORD_1(oword, FRF_AZ_RX_DESC_WPTR, wptr);
525
526         /* Only write the third DWORD */
527         EFX_POPULATE_DWORD_1(dword,
528             EFX_DWORD_0, EFX_OWORD_FIELD(oword, EFX_DWORD_3));
529
530         /* Guarantee ordering of memory (descriptors) and PIO (doorbell) */
531         EFX_DMA_SYNC_QUEUE_FOR_DEVICE(erp->er_esmp, erp->er_mask + 1,
532             wptr, pushed & erp->er_mask);
533         EFSYS_PIO_WRITE_BARRIER();
534         EFX_BAR_TBL_WRITED3(enp, FR_BZ_RX_DESC_UPD_REGP0,
535                             erp->er_index, &dword, B_FALSE);
536 }
537
538 static  __checkReturn   efx_rc_t
539 siena_rx_qflush(
540         __in    efx_rxq_t *erp)
541 {
542         efx_nic_t *enp = erp->er_enp;
543         efx_oword_t oword;
544         uint32_t label;
545
546         label = erp->er_index;
547
548         /* Flush the queue */
549         EFX_POPULATE_OWORD_2(oword, FRF_AZ_RX_FLUSH_DESCQ_CMD, 1,
550             FRF_AZ_RX_FLUSH_DESCQ, label);
551         EFX_BAR_WRITEO(enp, FR_AZ_RX_FLUSH_DESCQ_REG, &oword);
552
553         return (0);
554 }
555
556 static          void
557 siena_rx_qenable(
558         __in    efx_rxq_t *erp)
559 {
560         efx_nic_t *enp = erp->er_enp;
561         efx_oword_t oword;
562
563         EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
564
565         EFX_BAR_TBL_READO(enp, FR_AZ_RX_DESC_PTR_TBL,
566                             erp->er_index, &oword, B_TRUE);
567
568         EFX_SET_OWORD_FIELD(oword, FRF_AZ_RX_DC_HW_RPTR, 0);
569         EFX_SET_OWORD_FIELD(oword, FRF_AZ_RX_DESCQ_HW_RPTR, 0);
570         EFX_SET_OWORD_FIELD(oword, FRF_AZ_RX_DESCQ_EN, 1);
571
572         EFX_BAR_TBL_WRITEO(enp, FR_AZ_RX_DESC_PTR_TBL,
573                             erp->er_index, &oword, B_TRUE);
574 }
575
576 static  __checkReturn   efx_rc_t
577 siena_rx_qcreate(
578         __in            efx_nic_t *enp,
579         __in            unsigned int index,
580         __in            unsigned int label,
581         __in            efx_rxq_type_t type,
582         __in            efsys_mem_t *esmp,
583         __in            size_t n,
584         __in            uint32_t id,
585         __in            efx_evq_t *eep,
586         __in            efx_rxq_t *erp)
587 {
588         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
589         efx_oword_t oword;
590         uint32_t size;
591         boolean_t jumbo;
592         efx_rc_t rc;
593
594         _NOTE(ARGUNUSED(esmp))
595
596         EFX_STATIC_ASSERT(EFX_EV_RX_NLABELS ==
597             (1 << FRF_AZ_RX_DESCQ_LABEL_WIDTH));
598         EFSYS_ASSERT3U(label, <, EFX_EV_RX_NLABELS);
599         EFSYS_ASSERT3U(enp->en_rx_qcount + 1, <, encp->enc_rxq_limit);
600
601         EFX_STATIC_ASSERT(ISP2(EFX_RXQ_MAXNDESCS));
602         EFX_STATIC_ASSERT(ISP2(EFX_RXQ_MINNDESCS));
603
604         if (!ISP2(n) || (n < EFX_RXQ_MINNDESCS) || (n > EFX_RXQ_MAXNDESCS)) {
605                 rc = EINVAL;
606                 goto fail1;
607         }
608         if (index >= encp->enc_rxq_limit) {
609                 rc = EINVAL;
610                 goto fail2;
611         }
612         for (size = 0; (1 << size) <= (EFX_RXQ_MAXNDESCS / EFX_RXQ_MINNDESCS);
613             size++)
614                 if ((1 << size) == (int)(n / EFX_RXQ_MINNDESCS))
615                         break;
616         if (id + (1 << size) >= encp->enc_buftbl_limit) {
617                 rc = EINVAL;
618                 goto fail3;
619         }
620
621         switch (type) {
622         case EFX_RXQ_TYPE_DEFAULT:
623                 jumbo = B_FALSE;
624                 break;
625
626         default:
627                 rc = EINVAL;
628                 goto fail4;
629         }
630
631         /* Set up the new descriptor queue */
632         EFX_POPULATE_OWORD_7(oword,
633             FRF_AZ_RX_DESCQ_BUF_BASE_ID, id,
634             FRF_AZ_RX_DESCQ_EVQ_ID, eep->ee_index,
635             FRF_AZ_RX_DESCQ_OWNER_ID, 0,
636             FRF_AZ_RX_DESCQ_LABEL, label,
637             FRF_AZ_RX_DESCQ_SIZE, size,
638             FRF_AZ_RX_DESCQ_TYPE, 0,
639             FRF_AZ_RX_DESCQ_JUMBO, jumbo);
640
641         EFX_BAR_TBL_WRITEO(enp, FR_AZ_RX_DESC_PTR_TBL,
642                             erp->er_index, &oword, B_TRUE);
643
644         return (0);
645
646 fail4:
647         EFSYS_PROBE(fail4);
648 fail3:
649         EFSYS_PROBE(fail3);
650 fail2:
651         EFSYS_PROBE(fail2);
652 fail1:
653         EFSYS_PROBE1(fail1, efx_rc_t, rc);
654
655         return (rc);
656 }
657
658 static          void
659 siena_rx_qdestroy(
660         __in    efx_rxq_t *erp)
661 {
662         efx_nic_t *enp = erp->er_enp;
663         efx_oword_t oword;
664
665         EFSYS_ASSERT(enp->en_rx_qcount != 0);
666         --enp->en_rx_qcount;
667
668         /* Purge descriptor queue */
669         EFX_ZERO_OWORD(oword);
670
671         EFX_BAR_TBL_WRITEO(enp, FR_AZ_RX_DESC_PTR_TBL,
672                             erp->er_index, &oword, B_TRUE);
673
674         /* Free the RXQ object */
675         EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_rxq_t), erp);
676 }
677
678 static          void
679 siena_rx_fini(
680         __in    efx_nic_t *enp)
681 {
682         _NOTE(ARGUNUSED(enp))
683 }
684
685 #endif /* EFSYS_OPT_SIENA */