net/sfc/base: import SFN7xxx family support
[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         default:
156                 EFSYS_ASSERT(0);
157                 rc = ENOTSUP;
158                 goto fail3;
159         }
160
161         if ((rc = erxop->erxo_init(enp)) != 0)
162                 goto fail4;
163
164         enp->en_erxop = erxop;
165         enp->en_mod_flags |= EFX_MOD_RX;
166         return (0);
167
168 fail4:
169         EFSYS_PROBE(fail4);
170 fail3:
171         EFSYS_PROBE(fail3);
172 fail2:
173         EFSYS_PROBE(fail2);
174 fail1:
175         EFSYS_PROBE1(fail1, efx_rc_t, rc);
176
177         enp->en_erxop = NULL;
178         enp->en_mod_flags &= ~EFX_MOD_RX;
179         return (rc);
180 }
181
182                         void
183 efx_rx_fini(
184         __in            efx_nic_t *enp)
185 {
186         const efx_rx_ops_t *erxop = enp->en_erxop;
187
188         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
189         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
190         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX);
191         EFSYS_ASSERT3U(enp->en_rx_qcount, ==, 0);
192
193         erxop->erxo_fini(enp);
194
195         enp->en_erxop = NULL;
196         enp->en_mod_flags &= ~EFX_MOD_RX;
197 }
198
199                         void
200 efx_rx_qpost(
201         __in            efx_rxq_t *erp,
202         __in_ecount(n)  efsys_dma_addr_t *addrp,
203         __in            size_t size,
204         __in            unsigned int n,
205         __in            unsigned int completed,
206         __in            unsigned int added)
207 {
208         efx_nic_t *enp = erp->er_enp;
209         const efx_rx_ops_t *erxop = enp->en_erxop;
210
211         EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
212
213         erxop->erxo_qpost(erp, addrp, size, n, completed, added);
214 }
215
216                         void
217 efx_rx_qpush(
218         __in            efx_rxq_t *erp,
219         __in            unsigned int added,
220         __inout         unsigned int *pushedp)
221 {
222         efx_nic_t *enp = erp->er_enp;
223         const efx_rx_ops_t *erxop = enp->en_erxop;
224
225         EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
226
227         erxop->erxo_qpush(erp, added, pushedp);
228 }
229
230         __checkReturn   efx_rc_t
231 efx_rx_qflush(
232         __in            efx_rxq_t *erp)
233 {
234         efx_nic_t *enp = erp->er_enp;
235         const efx_rx_ops_t *erxop = enp->en_erxop;
236         efx_rc_t rc;
237
238         EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
239
240         if ((rc = erxop->erxo_qflush(erp)) != 0)
241                 goto fail1;
242
243         return (0);
244
245 fail1:
246         EFSYS_PROBE1(fail1, efx_rc_t, rc);
247
248         return (rc);
249 }
250
251                         void
252 efx_rx_qenable(
253         __in            efx_rxq_t *erp)
254 {
255         efx_nic_t *enp = erp->er_enp;
256         const efx_rx_ops_t *erxop = enp->en_erxop;
257
258         EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
259
260         erxop->erxo_qenable(erp);
261 }
262
263         __checkReturn   efx_rc_t
264 efx_rx_qcreate(
265         __in            efx_nic_t *enp,
266         __in            unsigned int index,
267         __in            unsigned int label,
268         __in            efx_rxq_type_t type,
269         __in            efsys_mem_t *esmp,
270         __in            size_t n,
271         __in            uint32_t id,
272         __in            efx_evq_t *eep,
273         __deref_out     efx_rxq_t **erpp)
274 {
275         const efx_rx_ops_t *erxop = enp->en_erxop;
276         efx_rxq_t *erp;
277         efx_rc_t rc;
278
279         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
280         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX);
281
282         /* Allocate an RXQ object */
283         EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (efx_rxq_t), erp);
284
285         if (erp == NULL) {
286                 rc = ENOMEM;
287                 goto fail1;
288         }
289
290         erp->er_magic = EFX_RXQ_MAGIC;
291         erp->er_enp = enp;
292         erp->er_index = index;
293         erp->er_mask = n - 1;
294         erp->er_esmp = esmp;
295
296         if ((rc = erxop->erxo_qcreate(enp, index, label, type, esmp, n, id,
297             eep, erp)) != 0)
298                 goto fail2;
299
300         enp->en_rx_qcount++;
301         *erpp = erp;
302
303         return (0);
304
305 fail2:
306         EFSYS_PROBE(fail2);
307
308         EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_rxq_t), erp);
309 fail1:
310         EFSYS_PROBE1(fail1, efx_rc_t, rc);
311
312         return (rc);
313 }
314
315                         void
316 efx_rx_qdestroy(
317         __in            efx_rxq_t *erp)
318 {
319         efx_nic_t *enp = erp->er_enp;
320         const efx_rx_ops_t *erxop = enp->en_erxop;
321
322         EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
323
324         erxop->erxo_qdestroy(erp);
325 }
326
327         __checkReturn   efx_rc_t
328 efx_pseudo_hdr_pkt_length_get(
329         __in            efx_rxq_t *erp,
330         __in            uint8_t *buffer,
331         __out           uint16_t *lengthp)
332 {
333         efx_nic_t *enp = erp->er_enp;
334         const efx_rx_ops_t *erxop = enp->en_erxop;
335
336         EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
337
338         return (erxop->erxo_prefix_pktlen(enp, buffer, lengthp));
339 }
340
341 #if EFSYS_OPT_SIENA
342
343 static  __checkReturn   efx_rc_t
344 siena_rx_init(
345         __in            efx_nic_t *enp)
346 {
347         efx_oword_t oword;
348         unsigned int index;
349
350         EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword);
351
352         EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_DESC_PUSH_EN, 0);
353         EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_HASH_ALG, 0);
354         EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_IP_HASH, 0);
355         EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_TCP_SUP, 0);
356         EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_HASH_INSRT_HDR, 0);
357         EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_USR_BUF_SIZE, 0x3000 / 32);
358         EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword);
359
360         /* Zero the RSS table */
361         for (index = 0; index < FR_BZ_RX_INDIRECTION_TBL_ROWS;
362             index++) {
363                 EFX_ZERO_OWORD(oword);
364                 EFX_BAR_TBL_WRITEO(enp, FR_BZ_RX_INDIRECTION_TBL,
365                                     index, &oword, B_TRUE);
366         }
367
368         return (0);
369 }
370
371
372 #define EFX_RX_LFSR_HASH(_enp, _insert)                                 \
373         do {                                                            \
374                 efx_oword_t oword;                                      \
375                                                                         \
376                 EFX_BAR_READO((_enp), FR_AZ_RX_CFG_REG, &oword);        \
377                 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_HASH_ALG, 0);      \
378                 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_IP_HASH, 0);       \
379                 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_TCP_SUP, 0);       \
380                 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_HASH_INSRT_HDR,    \
381                     (_insert) ? 1 : 0);                                 \
382                 EFX_BAR_WRITEO((_enp), FR_AZ_RX_CFG_REG, &oword);       \
383                                                                         \
384                 if ((_enp)->en_family == EFX_FAMILY_SIENA) {            \
385                         EFX_BAR_READO((_enp), FR_CZ_RX_RSS_IPV6_REG3,   \
386                             &oword);                                    \
387                         EFX_SET_OWORD_FIELD(oword,                      \
388                             FRF_CZ_RX_RSS_IPV6_THASH_ENABLE, 0);        \
389                         EFX_BAR_WRITEO((_enp), FR_CZ_RX_RSS_IPV6_REG3,  \
390                             &oword);                                    \
391                 }                                                       \
392                                                                         \
393                 _NOTE(CONSTANTCONDITION)                                \
394         } while (B_FALSE)
395
396 #define EFX_RX_TOEPLITZ_IPV4_HASH(_enp, _insert, _ip, _tcp)             \
397         do {                                                            \
398                 efx_oword_t oword;                                      \
399                                                                         \
400                 EFX_BAR_READO((_enp), FR_AZ_RX_CFG_REG, &oword);        \
401                 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_HASH_ALG, 1);      \
402                 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_IP_HASH,           \
403                     (_ip) ? 1 : 0);                                     \
404                 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_TCP_SUP,           \
405                     (_tcp) ? 0 : 1);                                    \
406                 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_HASH_INSRT_HDR,    \
407                     (_insert) ? 1 : 0);                                 \
408                 EFX_BAR_WRITEO((_enp), FR_AZ_RX_CFG_REG, &oword);       \
409                                                                         \
410                 _NOTE(CONSTANTCONDITION)                                \
411         } while (B_FALSE)
412
413 #define EFX_RX_TOEPLITZ_IPV6_HASH(_enp, _ip, _tcp, _rc)                 \
414         do {                                                            \
415                 efx_oword_t oword;                                      \
416                                                                         \
417                 EFX_BAR_READO((_enp), FR_CZ_RX_RSS_IPV6_REG3, &oword);  \
418                 EFX_SET_OWORD_FIELD(oword,                              \
419                     FRF_CZ_RX_RSS_IPV6_THASH_ENABLE, 1);                \
420                 EFX_SET_OWORD_FIELD(oword,                              \
421                     FRF_CZ_RX_RSS_IPV6_IP_THASH_ENABLE, (_ip) ? 1 : 0); \
422                 EFX_SET_OWORD_FIELD(oword,                              \
423                     FRF_CZ_RX_RSS_IPV6_TCP_SUPPRESS, (_tcp) ? 0 : 1);   \
424                 EFX_BAR_WRITEO((_enp), FR_CZ_RX_RSS_IPV6_REG3, &oword); \
425                                                                         \
426                 (_rc) = 0;                                              \
427                                                                         \
428                 _NOTE(CONSTANTCONDITION)                                \
429         } while (B_FALSE)
430
431
432 /*
433  * Falcon/Siena pseudo-header
434  * --------------------------
435  *
436  * Receive packets are prefixed by an optional 16 byte pseudo-header.
437  * The pseudo-header is a byte array of one of the forms:
438  *
439  *  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
440  * xx.xx.xx.xx.xx.xx.xx.xx.xx.xx.xx.xx.TT.TT.TT.TT
441  * xx.xx.xx.xx.xx.xx.xx.xx.xx.xx.xx.xx.xx.xx.LL.LL
442  *
443  * where:
444  *   TT.TT.TT.TT   Toeplitz hash (32-bit big-endian)
445  *   LL.LL         LFSR hash     (16-bit big-endian)
446  */
447
448 static  __checkReturn   efx_rc_t
449 siena_rx_prefix_pktlen(
450         __in            efx_nic_t *enp,
451         __in            uint8_t *buffer,
452         __out           uint16_t *lengthp)
453 {
454         _NOTE(ARGUNUSED(enp, buffer, lengthp))
455
456         /* Not supported by Falcon/Siena hardware */
457         EFSYS_ASSERT(0);
458         return (ENOTSUP);
459 }
460
461
462 static                  void
463 siena_rx_qpost(
464         __in            efx_rxq_t *erp,
465         __in_ecount(n)  efsys_dma_addr_t *addrp,
466         __in            size_t size,
467         __in            unsigned int n,
468         __in            unsigned int completed,
469         __in            unsigned int added)
470 {
471         efx_qword_t qword;
472         unsigned int i;
473         unsigned int offset;
474         unsigned int id;
475
476         /* The client driver must not overfill the queue */
477         EFSYS_ASSERT3U(added - completed + n, <=,
478             EFX_RXQ_LIMIT(erp->er_mask + 1));
479
480         id = added & (erp->er_mask);
481         for (i = 0; i < n; i++) {
482                 EFSYS_PROBE4(rx_post, unsigned int, erp->er_index,
483                     unsigned int, id, efsys_dma_addr_t, addrp[i],
484                     size_t, size);
485
486                 EFX_POPULATE_QWORD_3(qword,
487                     FSF_AZ_RX_KER_BUF_SIZE, (uint32_t)(size),
488                     FSF_AZ_RX_KER_BUF_ADDR_DW0,
489                     (uint32_t)(addrp[i] & 0xffffffff),
490                     FSF_AZ_RX_KER_BUF_ADDR_DW1,
491                     (uint32_t)(addrp[i] >> 32));
492
493                 offset = id * sizeof (efx_qword_t);
494                 EFSYS_MEM_WRITEQ(erp->er_esmp, offset, &qword);
495
496                 id = (id + 1) & (erp->er_mask);
497         }
498 }
499
500 static                  void
501 siena_rx_qpush(
502         __in    efx_rxq_t *erp,
503         __in    unsigned int added,
504         __inout unsigned int *pushedp)
505 {
506         efx_nic_t *enp = erp->er_enp;
507         unsigned int pushed = *pushedp;
508         uint32_t wptr;
509         efx_oword_t oword;
510         efx_dword_t dword;
511
512         /* All descriptors are pushed */
513         *pushedp = added;
514
515         /* Push the populated descriptors out */
516         wptr = added & erp->er_mask;
517
518         EFX_POPULATE_OWORD_1(oword, FRF_AZ_RX_DESC_WPTR, wptr);
519
520         /* Only write the third DWORD */
521         EFX_POPULATE_DWORD_1(dword,
522             EFX_DWORD_0, EFX_OWORD_FIELD(oword, EFX_DWORD_3));
523
524         /* Guarantee ordering of memory (descriptors) and PIO (doorbell) */
525         EFX_DMA_SYNC_QUEUE_FOR_DEVICE(erp->er_esmp, erp->er_mask + 1,
526             wptr, pushed & erp->er_mask);
527         EFSYS_PIO_WRITE_BARRIER();
528         EFX_BAR_TBL_WRITED3(enp, FR_BZ_RX_DESC_UPD_REGP0,
529                             erp->er_index, &dword, B_FALSE);
530 }
531
532 static  __checkReturn   efx_rc_t
533 siena_rx_qflush(
534         __in    efx_rxq_t *erp)
535 {
536         efx_nic_t *enp = erp->er_enp;
537         efx_oword_t oword;
538         uint32_t label;
539
540         label = erp->er_index;
541
542         /* Flush the queue */
543         EFX_POPULATE_OWORD_2(oword, FRF_AZ_RX_FLUSH_DESCQ_CMD, 1,
544             FRF_AZ_RX_FLUSH_DESCQ, label);
545         EFX_BAR_WRITEO(enp, FR_AZ_RX_FLUSH_DESCQ_REG, &oword);
546
547         return (0);
548 }
549
550 static          void
551 siena_rx_qenable(
552         __in    efx_rxq_t *erp)
553 {
554         efx_nic_t *enp = erp->er_enp;
555         efx_oword_t oword;
556
557         EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
558
559         EFX_BAR_TBL_READO(enp, FR_AZ_RX_DESC_PTR_TBL,
560                             erp->er_index, &oword, B_TRUE);
561
562         EFX_SET_OWORD_FIELD(oword, FRF_AZ_RX_DC_HW_RPTR, 0);
563         EFX_SET_OWORD_FIELD(oword, FRF_AZ_RX_DESCQ_HW_RPTR, 0);
564         EFX_SET_OWORD_FIELD(oword, FRF_AZ_RX_DESCQ_EN, 1);
565
566         EFX_BAR_TBL_WRITEO(enp, FR_AZ_RX_DESC_PTR_TBL,
567                             erp->er_index, &oword, B_TRUE);
568 }
569
570 static  __checkReturn   efx_rc_t
571 siena_rx_qcreate(
572         __in            efx_nic_t *enp,
573         __in            unsigned int index,
574         __in            unsigned int label,
575         __in            efx_rxq_type_t type,
576         __in            efsys_mem_t *esmp,
577         __in            size_t n,
578         __in            uint32_t id,
579         __in            efx_evq_t *eep,
580         __in            efx_rxq_t *erp)
581 {
582         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
583         efx_oword_t oword;
584         uint32_t size;
585         boolean_t jumbo;
586         efx_rc_t rc;
587
588         _NOTE(ARGUNUSED(esmp))
589
590         EFX_STATIC_ASSERT(EFX_EV_RX_NLABELS ==
591             (1 << FRF_AZ_RX_DESCQ_LABEL_WIDTH));
592         EFSYS_ASSERT3U(label, <, EFX_EV_RX_NLABELS);
593         EFSYS_ASSERT3U(enp->en_rx_qcount + 1, <, encp->enc_rxq_limit);
594
595         EFX_STATIC_ASSERT(ISP2(EFX_RXQ_MAXNDESCS));
596         EFX_STATIC_ASSERT(ISP2(EFX_RXQ_MINNDESCS));
597
598         if (!ISP2(n) || (n < EFX_RXQ_MINNDESCS) || (n > EFX_RXQ_MAXNDESCS)) {
599                 rc = EINVAL;
600                 goto fail1;
601         }
602         if (index >= encp->enc_rxq_limit) {
603                 rc = EINVAL;
604                 goto fail2;
605         }
606         for (size = 0; (1 << size) <= (EFX_RXQ_MAXNDESCS / EFX_RXQ_MINNDESCS);
607             size++)
608                 if ((1 << size) == (int)(n / EFX_RXQ_MINNDESCS))
609                         break;
610         if (id + (1 << size) >= encp->enc_buftbl_limit) {
611                 rc = EINVAL;
612                 goto fail3;
613         }
614
615         switch (type) {
616         case EFX_RXQ_TYPE_DEFAULT:
617                 jumbo = B_FALSE;
618                 break;
619
620         default:
621                 rc = EINVAL;
622                 goto fail4;
623         }
624
625         /* Set up the new descriptor queue */
626         EFX_POPULATE_OWORD_7(oword,
627             FRF_AZ_RX_DESCQ_BUF_BASE_ID, id,
628             FRF_AZ_RX_DESCQ_EVQ_ID, eep->ee_index,
629             FRF_AZ_RX_DESCQ_OWNER_ID, 0,
630             FRF_AZ_RX_DESCQ_LABEL, label,
631             FRF_AZ_RX_DESCQ_SIZE, size,
632             FRF_AZ_RX_DESCQ_TYPE, 0,
633             FRF_AZ_RX_DESCQ_JUMBO, jumbo);
634
635         EFX_BAR_TBL_WRITEO(enp, FR_AZ_RX_DESC_PTR_TBL,
636                             erp->er_index, &oword, B_TRUE);
637
638         return (0);
639
640 fail4:
641         EFSYS_PROBE(fail4);
642 fail3:
643         EFSYS_PROBE(fail3);
644 fail2:
645         EFSYS_PROBE(fail2);
646 fail1:
647         EFSYS_PROBE1(fail1, efx_rc_t, rc);
648
649         return (rc);
650 }
651
652 static          void
653 siena_rx_qdestroy(
654         __in    efx_rxq_t *erp)
655 {
656         efx_nic_t *enp = erp->er_enp;
657         efx_oword_t oword;
658
659         EFSYS_ASSERT(enp->en_rx_qcount != 0);
660         --enp->en_rx_qcount;
661
662         /* Purge descriptor queue */
663         EFX_ZERO_OWORD(oword);
664
665         EFX_BAR_TBL_WRITEO(enp, FR_AZ_RX_DESC_PTR_TBL,
666                             erp->er_index, &oword, B_TRUE);
667
668         /* Free the RXQ object */
669         EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_rxq_t), erp);
670 }
671
672 static          void
673 siena_rx_fini(
674         __in    efx_nic_t *enp)
675 {
676         _NOTE(ARGUNUSED(enp))
677 }
678
679 #endif /* EFSYS_OPT_SIENA */