]> CyberLeo.Net >> Repos - FreeBSD/releng/10.3.git/blob - sys/dev/sfxge/common/efx_rx.c
- Copy stable/10@296371 to releng/10.3 in preparation for 10.3-RC1
[FreeBSD/releng/10.3.git] / sys / dev / sfxge / common / efx_rx.c
1 /*-
2  * Copyright (c) 2007-2015 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 <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
34 #include "efx.h"
35 #include "efx_impl.h"
36
37
38 #if EFSYS_OPT_FALCON || EFSYS_OPT_SIENA
39
40 static  __checkReturn   efx_rc_t
41 falconsiena_rx_init(
42         __in            efx_nic_t *enp);
43
44 static                  void
45 falconsiena_rx_fini(
46         __in            efx_nic_t *enp);
47
48 #if EFSYS_OPT_RX_SCATTER
49 static  __checkReturn   efx_rc_t
50 falconsiena_rx_scatter_enable(
51         __in            efx_nic_t *enp,
52         __in            unsigned int buf_size);
53 #endif /* EFSYS_OPT_RX_SCATTER */
54
55 #if EFSYS_OPT_RX_SCALE
56 static  __checkReturn   efx_rc_t
57 falconsiena_rx_scale_mode_set(
58         __in            efx_nic_t *enp,
59         __in            efx_rx_hash_alg_t alg,
60         __in            efx_rx_hash_type_t type,
61         __in            boolean_t insert);
62
63 static  __checkReturn   efx_rc_t
64 falconsiena_rx_scale_key_set(
65         __in            efx_nic_t *enp,
66         __in_ecount(n)  uint8_t *key,
67         __in            size_t n);
68
69 static  __checkReturn   efx_rc_t
70 falconsiena_rx_scale_tbl_set(
71         __in            efx_nic_t *enp,
72         __in_ecount(n)  unsigned int *table,
73         __in            size_t n);
74
75 static  __checkReturn   uint32_t
76 falconsiena_rx_prefix_hash(
77         __in            efx_nic_t *enp,
78         __in            efx_rx_hash_alg_t func,
79         __in            uint8_t *buffer);
80
81 #endif /* EFSYS_OPT_RX_SCALE */
82
83 static  __checkReturn   efx_rc_t
84 falconsiena_rx_prefix_pktlen(
85         __in            efx_nic_t *enp,
86         __in            uint8_t *buffer,
87         __out           uint16_t *lengthp);
88
89 static                  void
90 falconsiena_rx_qpost(
91         __in            efx_rxq_t *erp,
92         __in_ecount(n)  efsys_dma_addr_t *addrp,
93         __in            size_t size,
94         __in            unsigned int n,
95         __in            unsigned int completed,
96         __in            unsigned int added);
97
98 static                  void
99 falconsiena_rx_qpush(
100         __in            efx_rxq_t *erp,
101         __in            unsigned int added,
102         __inout         unsigned int *pushedp);
103
104 static  __checkReturn   efx_rc_t
105 falconsiena_rx_qflush(
106         __in            efx_rxq_t *erp);
107
108 static                  void
109 falconsiena_rx_qenable(
110         __in            efx_rxq_t *erp);
111
112 static  __checkReturn   efx_rc_t
113 falconsiena_rx_qcreate(
114         __in            efx_nic_t *enp,
115         __in            unsigned int index,
116         __in            unsigned int label,
117         __in            efx_rxq_type_t type,
118         __in            efsys_mem_t *esmp,
119         __in            size_t n,
120         __in            uint32_t id,
121         __in            efx_evq_t *eep,
122         __in            efx_rxq_t *erp);
123
124 static                  void
125 falconsiena_rx_qdestroy(
126         __in            efx_rxq_t *erp);
127
128 #endif /* EFSYS_OPT_FALCON || EFSYS_OPT_SIENA */
129
130
131 #if EFSYS_OPT_FALCON
132 static efx_rx_ops_t __efx_rx_falcon_ops = {
133         falconsiena_rx_init,                    /* erxo_init */
134         falconsiena_rx_fini,                    /* erxo_fini */
135 #if EFSYS_OPT_RX_SCATTER
136         falconsiena_rx_scatter_enable,          /* erxo_scatter_enable */
137 #endif
138 #if EFSYS_OPT_RX_SCALE
139         falconsiena_rx_scale_mode_set,          /* erxo_scale_mode_set */
140         falconsiena_rx_scale_key_set,           /* erxo_scale_key_set */
141         falconsiena_rx_scale_tbl_set,           /* erxo_scale_tbl_set */
142         falconsiena_rx_prefix_hash,             /* erxo_prefix_hash */
143 #endif
144         falconsiena_rx_prefix_pktlen,           /* erxo_prefix_pktlen */
145         falconsiena_rx_qpost,                   /* erxo_qpost */
146         falconsiena_rx_qpush,                   /* erxo_qpush */
147         falconsiena_rx_qflush,                  /* erxo_qflush */
148         falconsiena_rx_qenable,                 /* erxo_qenable */
149         falconsiena_rx_qcreate,                 /* erxo_qcreate */
150         falconsiena_rx_qdestroy,                /* erxo_qdestroy */
151 };
152 #endif  /* EFSYS_OPT_FALCON */
153
154 #if EFSYS_OPT_SIENA
155 static efx_rx_ops_t __efx_rx_siena_ops = {
156         falconsiena_rx_init,                    /* erxo_init */
157         falconsiena_rx_fini,                    /* erxo_fini */
158 #if EFSYS_OPT_RX_SCATTER
159         falconsiena_rx_scatter_enable,          /* erxo_scatter_enable */
160 #endif
161 #if EFSYS_OPT_RX_SCALE
162         falconsiena_rx_scale_mode_set,          /* erxo_scale_mode_set */
163         falconsiena_rx_scale_key_set,           /* erxo_scale_key_set */
164         falconsiena_rx_scale_tbl_set,           /* erxo_scale_tbl_set */
165         falconsiena_rx_prefix_hash,             /* erxo_prefix_hash */
166 #endif
167         falconsiena_rx_prefix_pktlen,           /* erxo_prefix_pktlen */
168         falconsiena_rx_qpost,                   /* erxo_qpost */
169         falconsiena_rx_qpush,                   /* erxo_qpush */
170         falconsiena_rx_qflush,                  /* erxo_qflush */
171         falconsiena_rx_qenable,                 /* erxo_qenable */
172         falconsiena_rx_qcreate,                 /* erxo_qcreate */
173         falconsiena_rx_qdestroy,                /* erxo_qdestroy */
174 };
175 #endif  /* EFSYS_OPT_SIENA */
176
177 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
178 static efx_rx_ops_t __efx_rx_ef10_ops = {
179         ef10_rx_init,                           /* erxo_init */
180         ef10_rx_fini,                           /* erxo_fini */
181 #if EFSYS_OPT_RX_SCATTER
182         ef10_rx_scatter_enable,                 /* erxo_scatter_enable */
183 #endif
184 #if EFSYS_OPT_RX_SCALE
185         ef10_rx_scale_mode_set,                 /* erxo_scale_mode_set */
186         ef10_rx_scale_key_set,                  /* erxo_scale_key_set */
187         ef10_rx_scale_tbl_set,                  /* erxo_scale_tbl_set */
188         ef10_rx_prefix_hash,                    /* erxo_prefix_hash */
189 #endif
190         ef10_rx_prefix_pktlen,                  /* erxo_prefix_pktlen */
191         ef10_rx_qpost,                          /* erxo_qpost */
192         ef10_rx_qpush,                          /* erxo_qpush */
193         ef10_rx_qflush,                         /* erxo_qflush */
194         ef10_rx_qenable,                        /* erxo_qenable */
195         ef10_rx_qcreate,                        /* erxo_qcreate */
196         ef10_rx_qdestroy,                       /* erxo_qdestroy */
197 };
198 #endif  /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
199
200
201         __checkReturn   efx_rc_t
202 efx_rx_init(
203         __inout         efx_nic_t *enp)
204 {
205         efx_rx_ops_t *erxop;
206         efx_rc_t rc;
207
208         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
209         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
210
211         if (!(enp->en_mod_flags & EFX_MOD_EV)) {
212                 rc = EINVAL;
213                 goto fail1;
214         }
215
216         if (enp->en_mod_flags & EFX_MOD_RX) {
217                 rc = EINVAL;
218                 goto fail2;
219         }
220
221         switch (enp->en_family) {
222 #if EFSYS_OPT_FALCON
223         case EFX_FAMILY_FALCON:
224                 erxop = (efx_rx_ops_t *)&__efx_rx_falcon_ops;
225                 break;
226 #endif /* EFSYS_OPT_FALCON */
227
228 #if EFSYS_OPT_SIENA
229         case EFX_FAMILY_SIENA:
230                 erxop = (efx_rx_ops_t *)&__efx_rx_siena_ops;
231                 break;
232 #endif /* EFSYS_OPT_SIENA */
233
234 #if EFSYS_OPT_HUNTINGTON
235         case EFX_FAMILY_HUNTINGTON:
236                 erxop = (efx_rx_ops_t *)&__efx_rx_ef10_ops;
237                 break;
238 #endif /* EFSYS_OPT_HUNTINGTON */
239
240 #if EFSYS_OPT_MEDFORD
241         case EFX_FAMILY_MEDFORD:
242                 erxop = (efx_rx_ops_t *)&__efx_rx_ef10_ops;
243                 break;
244 #endif /* EFSYS_OPT_MEDFORD */
245
246         default:
247                 EFSYS_ASSERT(0);
248                 rc = ENOTSUP;
249                 goto fail3;
250         }
251
252         if ((rc = erxop->erxo_init(enp)) != 0)
253                 goto fail4;
254
255         enp->en_erxop = erxop;
256         enp->en_mod_flags |= EFX_MOD_RX;
257         return (0);
258
259 fail4:
260         EFSYS_PROBE(fail4);
261 fail3:
262         EFSYS_PROBE(fail3);
263 fail2:
264         EFSYS_PROBE(fail2);
265 fail1:
266         EFSYS_PROBE1(fail1, efx_rc_t, rc);
267
268         enp->en_erxop = NULL;
269         enp->en_mod_flags &= ~EFX_MOD_RX;
270         return (rc);
271 }
272
273                         void
274 efx_rx_fini(
275         __in            efx_nic_t *enp)
276 {
277         efx_rx_ops_t *erxop = enp->en_erxop;
278
279         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
280         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
281         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX);
282         EFSYS_ASSERT3U(enp->en_rx_qcount, ==, 0);
283
284         erxop->erxo_fini(enp);
285
286         enp->en_erxop = NULL;
287         enp->en_mod_flags &= ~EFX_MOD_RX;
288 }
289
290 #if EFSYS_OPT_RX_SCATTER
291         __checkReturn   efx_rc_t
292 efx_rx_scatter_enable(
293         __in            efx_nic_t *enp,
294         __in            unsigned int buf_size)
295 {
296         efx_rx_ops_t *erxop = enp->en_erxop;
297         efx_rc_t rc;
298
299         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
300         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX);
301
302         if ((rc = erxop->erxo_scatter_enable(enp, buf_size)) != 0)
303                 goto fail1;
304
305         return (0);
306
307 fail1:
308         EFSYS_PROBE1(fail1, efx_rc_t, rc);
309         return (rc);
310 }
311 #endif  /* EFSYS_OPT_RX_SCATTER */
312
313 #if EFSYS_OPT_RX_SCALE
314         __checkReturn   efx_rc_t
315 efx_rx_hash_support_get(
316         __in            efx_nic_t *enp,
317         __out           efx_rx_hash_support_t *supportp)
318 {
319         efx_rc_t rc;
320
321         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
322         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX);
323
324         if (supportp == NULL) {
325                 rc = EINVAL;
326                 goto fail1;
327         }
328
329         /* Report if resources are available to insert RX hash value */
330         *supportp = enp->en_hash_support;
331
332         return (0);
333
334 fail1:
335         EFSYS_PROBE1(fail1, efx_rc_t, rc);
336
337         return (rc);
338 }
339
340         __checkReturn   efx_rc_t
341 efx_rx_scale_support_get(
342         __in            efx_nic_t *enp,
343         __out           efx_rx_scale_support_t *supportp)
344 {
345         efx_rc_t rc;
346
347         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
348         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX);
349
350         if (supportp == NULL) {
351                 rc = EINVAL;
352                 goto fail1;
353         }
354
355         /* Report if resources are available to support RSS */
356         *supportp = enp->en_rss_support;
357
358         return (0);
359
360 fail1:
361         EFSYS_PROBE1(fail1, efx_rc_t, rc);
362
363         return (rc);
364 }
365
366         __checkReturn   efx_rc_t
367 efx_rx_scale_mode_set(
368         __in            efx_nic_t *enp,
369         __in            efx_rx_hash_alg_t alg,
370         __in            efx_rx_hash_type_t type,
371         __in            boolean_t insert)
372 {
373         efx_rx_ops_t *erxop = enp->en_erxop;
374         efx_rc_t rc;
375
376         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
377         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX);
378
379         if (erxop->erxo_scale_mode_set != NULL) {
380                 if ((rc = erxop->erxo_scale_mode_set(enp, alg,
381                             type, insert)) != 0)
382                         goto fail1;
383         }
384
385         return (0);
386
387 fail1:
388         EFSYS_PROBE1(fail1, efx_rc_t, rc);
389         return (rc);
390 }
391 #endif  /* EFSYS_OPT_RX_SCALE */
392
393 #if EFSYS_OPT_RX_SCALE
394         __checkReturn   efx_rc_t
395 efx_rx_scale_key_set(
396         __in            efx_nic_t *enp,
397         __in_ecount(n)  uint8_t *key,
398         __in            size_t n)
399 {
400         efx_rx_ops_t *erxop = enp->en_erxop;
401         efx_rc_t rc;
402
403         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
404         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX);
405
406         if ((rc = erxop->erxo_scale_key_set(enp, key, n)) != 0)
407                 goto fail1;
408
409         return (0);
410
411 fail1:
412         EFSYS_PROBE1(fail1, efx_rc_t, rc);
413
414         return (rc);
415 }
416 #endif  /* EFSYS_OPT_RX_SCALE */
417
418 #if EFSYS_OPT_RX_SCALE
419         __checkReturn   efx_rc_t
420 efx_rx_scale_tbl_set(
421         __in            efx_nic_t *enp,
422         __in_ecount(n)  unsigned int *table,
423         __in            size_t n)
424 {
425         efx_rx_ops_t *erxop = enp->en_erxop;
426         efx_rc_t rc;
427
428         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
429         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX);
430
431         if ((rc = erxop->erxo_scale_tbl_set(enp, table, n)) != 0)
432                 goto fail1;
433
434         return (0);
435
436 fail1:
437         EFSYS_PROBE1(fail1, efx_rc_t, rc);
438
439         return (rc);
440 }
441 #endif  /* EFSYS_OPT_RX_SCALE */
442
443                         void
444 efx_rx_qpost(
445         __in            efx_rxq_t *erp,
446         __in_ecount(n)  efsys_dma_addr_t *addrp,
447         __in            size_t size,
448         __in            unsigned int n,
449         __in            unsigned int completed,
450         __in            unsigned int added)
451 {
452         efx_nic_t *enp = erp->er_enp;
453         efx_rx_ops_t *erxop = enp->en_erxop;
454
455         EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
456
457         erxop->erxo_qpost(erp, addrp, size, n, completed, added);
458 }
459
460                         void
461 efx_rx_qpush(
462         __in            efx_rxq_t *erp,
463         __in            unsigned int added,
464         __inout         unsigned int *pushedp)
465 {
466         efx_nic_t *enp = erp->er_enp;
467         efx_rx_ops_t *erxop = enp->en_erxop;
468
469         EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
470
471         erxop->erxo_qpush(erp, added, pushedp);
472 }
473
474         __checkReturn   efx_rc_t
475 efx_rx_qflush(
476         __in            efx_rxq_t *erp)
477 {
478         efx_nic_t *enp = erp->er_enp;
479         efx_rx_ops_t *erxop = enp->en_erxop;
480         efx_rc_t rc;
481
482         EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
483
484         if ((rc = erxop->erxo_qflush(erp)) != 0)
485                 goto fail1;
486
487         return (0);
488
489 fail1:
490         EFSYS_PROBE1(fail1, efx_rc_t, rc);
491
492         return (rc);
493 }
494
495                         void
496 efx_rx_qenable(
497         __in            efx_rxq_t *erp)
498 {
499         efx_nic_t *enp = erp->er_enp;
500         efx_rx_ops_t *erxop = enp->en_erxop;
501
502         EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
503
504         erxop->erxo_qenable(erp);
505 }
506
507         __checkReturn   efx_rc_t
508 efx_rx_qcreate(
509         __in            efx_nic_t *enp,
510         __in            unsigned int index,
511         __in            unsigned int label,
512         __in            efx_rxq_type_t type,
513         __in            efsys_mem_t *esmp,
514         __in            size_t n,
515         __in            uint32_t id,
516         __in            efx_evq_t *eep,
517         __deref_out     efx_rxq_t **erpp)
518 {
519         efx_rx_ops_t *erxop = enp->en_erxop;
520         efx_rxq_t *erp;
521         efx_rc_t rc;
522
523         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
524         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX);
525
526         /* Allocate an RXQ object */
527         EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (efx_rxq_t), erp);
528
529         if (erp == NULL) {
530                 rc = ENOMEM;
531                 goto fail1;
532         }
533
534         erp->er_magic = EFX_RXQ_MAGIC;
535         erp->er_enp = enp;
536         erp->er_index = index;
537         erp->er_mask = n - 1;
538         erp->er_esmp = esmp;
539
540         if ((rc = erxop->erxo_qcreate(enp, index, label, type, esmp, n, id,
541             eep, erp)) != 0)
542                 goto fail2;
543
544         enp->en_rx_qcount++;
545         *erpp = erp;
546
547         return (0);
548
549 fail2:
550         EFSYS_PROBE(fail2);
551
552         EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_rxq_t), erp);
553 fail1:
554         EFSYS_PROBE1(fail1, efx_rc_t, rc);
555
556         return (rc);
557 }
558
559                         void
560 efx_rx_qdestroy(
561         __in            efx_rxq_t *erp)
562 {
563         efx_nic_t *enp = erp->er_enp;
564         efx_rx_ops_t *erxop = enp->en_erxop;
565
566         EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
567
568         erxop->erxo_qdestroy(erp);
569 }
570
571         __checkReturn   efx_rc_t
572 efx_psuedo_hdr_pkt_length_get(
573         __in            efx_nic_t *enp,
574         __in            uint8_t *buffer,
575         __out           uint16_t *lengthp)
576 {
577         efx_rx_ops_t *erxop = enp->en_erxop;
578
579         return (erxop->erxo_prefix_pktlen(enp, buffer, lengthp));
580 }
581
582 #if EFSYS_OPT_RX_SCALE
583         __checkReturn   uint32_t
584 efx_psuedo_hdr_hash_get(
585         __in            efx_nic_t *enp,
586         __in            efx_rx_hash_alg_t func,
587         __in            uint8_t *buffer)
588 {
589         efx_rx_ops_t *erxop = enp->en_erxop;
590
591         EFSYS_ASSERT3U(enp->en_hash_support, ==, EFX_RX_HASH_AVAILABLE);
592         return (erxop->erxo_prefix_hash(enp, func, buffer));
593 }
594 #endif  /* EFSYS_OPT_RX_SCALE */
595
596 #if EFSYS_OPT_FALCON || EFSYS_OPT_SIENA
597
598 static  __checkReturn   efx_rc_t
599 falconsiena_rx_init(
600         __in            efx_nic_t *enp)
601 {
602         efx_oword_t oword;
603         unsigned int index;
604
605         EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword);
606
607         EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_DESC_PUSH_EN, 0);
608         EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_HASH_ALG, 0);
609         EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_IP_HASH, 0);
610         EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_TCP_SUP, 0);
611         EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_HASH_INSRT_HDR, 0);
612         EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_USR_BUF_SIZE, 0x3000 / 32);
613         EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword);
614
615         /* Zero the RSS table */
616         for (index = 0; index < FR_BZ_RX_INDIRECTION_TBL_ROWS;
617             index++) {
618                 EFX_ZERO_OWORD(oword);
619                 EFX_BAR_TBL_WRITEO(enp, FR_BZ_RX_INDIRECTION_TBL,
620                                     index, &oword, B_TRUE);
621         }
622
623 #if EFSYS_OPT_RX_SCALE
624         /* The RSS key and indirection table are writable. */
625         enp->en_rss_support = EFX_RX_SCALE_EXCLUSIVE;
626
627         /* Hardware can insert RX hash with/without RSS */
628         enp->en_hash_support = EFX_RX_HASH_AVAILABLE;
629 #endif  /* EFSYS_OPT_RX_SCALE */
630
631         return (0);
632 }
633
634 #if EFSYS_OPT_RX_SCATTER
635 static  __checkReturn   efx_rc_t
636 falconsiena_rx_scatter_enable(
637         __in            efx_nic_t *enp,
638         __in            unsigned int buf_size)
639 {
640         unsigned int nbuf32;
641         efx_oword_t oword;
642         efx_rc_t rc;
643
644         nbuf32 = buf_size / 32;
645         if ((nbuf32 == 0) ||
646             (nbuf32 >= (1 << FRF_BZ_RX_USR_BUF_SIZE_WIDTH)) ||
647             ((buf_size % 32) != 0)) {
648                 rc = EINVAL;
649                 goto fail1;
650         }
651
652         if (enp->en_rx_qcount > 0) {
653                 rc = EBUSY;
654                 goto fail2;
655         }
656
657         /* Set scatter buffer size */
658         EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword);
659         EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_USR_BUF_SIZE, nbuf32);
660         EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword);
661
662         /* Enable scatter for packets not matching a filter */
663         EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
664         EFX_SET_OWORD_FIELD(oword, FRF_BZ_SCATTER_ENBL_NO_MATCH_Q, 1);
665         EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
666
667         return (0);
668
669 fail2:
670         EFSYS_PROBE(fail2);
671 fail1:
672         EFSYS_PROBE1(fail1, efx_rc_t, rc);
673
674         return (rc);
675 }
676 #endif  /* EFSYS_OPT_RX_SCATTER */
677
678
679 #define EFX_RX_LFSR_HASH(_enp, _insert)                                 \
680         do {                                                            \
681                 efx_oword_t oword;                                      \
682                                                                         \
683                 EFX_BAR_READO((_enp), FR_AZ_RX_CFG_REG, &oword);        \
684                 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_HASH_ALG, 0);      \
685                 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_IP_HASH, 0);       \
686                 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_TCP_SUP, 0);       \
687                 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_HASH_INSRT_HDR,    \
688                     (_insert) ? 1 : 0);                                 \
689                 EFX_BAR_WRITEO((_enp), FR_AZ_RX_CFG_REG, &oword);       \
690                                                                         \
691                 if ((_enp)->en_family == EFX_FAMILY_SIENA) {            \
692                         EFX_BAR_READO((_enp), FR_CZ_RX_RSS_IPV6_REG3,   \
693                             &oword);                                    \
694                         EFX_SET_OWORD_FIELD(oword,                      \
695                             FRF_CZ_RX_RSS_IPV6_THASH_ENABLE, 0);        \
696                         EFX_BAR_WRITEO((_enp), FR_CZ_RX_RSS_IPV6_REG3,  \
697                             &oword);                                    \
698                 }                                                       \
699                                                                         \
700                 _NOTE(CONSTANTCONDITION)                                \
701         } while (B_FALSE)
702
703 #define EFX_RX_TOEPLITZ_IPV4_HASH(_enp, _insert, _ip, _tcp)             \
704         do {                                                            \
705                 efx_oword_t oword;                                      \
706                                                                         \
707                 EFX_BAR_READO((_enp), FR_AZ_RX_CFG_REG, &oword);        \
708                 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_HASH_ALG, 1);      \
709                 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_IP_HASH,           \
710                     (_ip) ? 1 : 0);                                     \
711                 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_TCP_SUP,           \
712                     (_tcp) ? 0 : 1);                                    \
713                 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_HASH_INSRT_HDR,    \
714                     (_insert) ? 1 : 0);                                 \
715                 EFX_BAR_WRITEO((_enp), FR_AZ_RX_CFG_REG, &oword);       \
716                                                                         \
717                 _NOTE(CONSTANTCONDITION)                                \
718         } while (B_FALSE)
719
720 #define EFX_RX_TOEPLITZ_IPV6_HASH(_enp, _ip, _tcp, _rc)                 \
721         do {                                                            \
722                 efx_oword_t oword;                                      \
723                                                                         \
724                 if ((_enp)->en_family == EFX_FAMILY_FALCON) {           \
725                         (_rc) = ((_ip) || (_tcp)) ? ENOTSUP : 0;        \
726                         break;                                          \
727                 }                                                       \
728                                                                         \
729                 EFX_BAR_READO((_enp), FR_CZ_RX_RSS_IPV6_REG3, &oword);  \
730                 EFX_SET_OWORD_FIELD(oword,                              \
731                     FRF_CZ_RX_RSS_IPV6_THASH_ENABLE, 1);                \
732                 EFX_SET_OWORD_FIELD(oword,                              \
733                     FRF_CZ_RX_RSS_IPV6_IP_THASH_ENABLE, (_ip) ? 1 : 0); \
734                 EFX_SET_OWORD_FIELD(oword,                              \
735                     FRF_CZ_RX_RSS_IPV6_TCP_SUPPRESS, (_tcp) ? 0 : 1);   \
736                 EFX_BAR_WRITEO((_enp), FR_CZ_RX_RSS_IPV6_REG3, &oword); \
737                                                                         \
738                 (_rc) = 0;                                              \
739                                                                         \
740                 _NOTE(CONSTANTCONDITION)                                \
741         } while (B_FALSE)
742
743
744 #if EFSYS_OPT_RX_SCALE
745
746 static  __checkReturn   efx_rc_t
747 falconsiena_rx_scale_mode_set(
748         __in            efx_nic_t *enp,
749         __in            efx_rx_hash_alg_t alg,
750         __in            efx_rx_hash_type_t type,
751         __in            boolean_t insert)
752 {
753         efx_rc_t rc;
754
755         switch (alg) {
756         case EFX_RX_HASHALG_LFSR:
757                 EFX_RX_LFSR_HASH(enp, insert);
758                 break;
759
760         case EFX_RX_HASHALG_TOEPLITZ:
761                 EFX_RX_TOEPLITZ_IPV4_HASH(enp, insert,
762                     type & (1 << EFX_RX_HASH_IPV4),
763                     type & (1 << EFX_RX_HASH_TCPIPV4));
764
765                 EFX_RX_TOEPLITZ_IPV6_HASH(enp,
766                     type & (1 << EFX_RX_HASH_IPV6),
767                     type & (1 << EFX_RX_HASH_TCPIPV6),
768                     rc);
769                 if (rc != 0)
770                         goto fail1;
771
772                 break;
773
774         default:
775                 rc = EINVAL;
776                 goto fail2;
777         }
778
779         return (0);
780
781 fail2:
782         EFSYS_PROBE(fail2);
783 fail1:
784         EFSYS_PROBE1(fail1, efx_rc_t, rc);
785
786         EFX_RX_LFSR_HASH(enp, B_FALSE);
787
788         return (rc);
789 }
790 #endif
791
792 #if EFSYS_OPT_RX_SCALE
793 static  __checkReturn   efx_rc_t
794 falconsiena_rx_scale_key_set(
795         __in            efx_nic_t *enp,
796         __in_ecount(n)  uint8_t *key,
797         __in            size_t n)
798 {
799         efx_oword_t oword;
800         unsigned int byte;
801         unsigned int offset;
802         efx_rc_t rc;
803
804         byte = 0;
805
806         /* Write Toeplitz IPv4 hash key */
807         EFX_ZERO_OWORD(oword);
808         for (offset = (FRF_BZ_RX_RSS_TKEY_LBN + FRF_BZ_RX_RSS_TKEY_WIDTH) / 8;
809             offset > 0 && byte < n;
810             --offset)
811                 oword.eo_u8[offset - 1] = key[byte++];
812
813         EFX_BAR_WRITEO(enp, FR_BZ_RX_RSS_TKEY_REG, &oword);
814
815         byte = 0;
816
817         /* Verify Toeplitz IPv4 hash key */
818         EFX_BAR_READO(enp, FR_BZ_RX_RSS_TKEY_REG, &oword);
819         for (offset = (FRF_BZ_RX_RSS_TKEY_LBN + FRF_BZ_RX_RSS_TKEY_WIDTH) / 8;
820             offset > 0 && byte < n;
821             --offset) {
822                 if (oword.eo_u8[offset - 1] != key[byte++]) {
823                         rc = EFAULT;
824                         goto fail1;
825                 }
826         }
827
828         if ((enp->en_features & EFX_FEATURE_IPV6) == 0)
829                 goto done;
830
831         EFSYS_ASSERT3U(enp->en_family, !=, EFX_FAMILY_FALCON);
832
833         byte = 0;
834
835         /* Write Toeplitz IPv6 hash key 3 */
836         EFX_BAR_READO(enp, FR_CZ_RX_RSS_IPV6_REG3, &oword);
837         for (offset = (FRF_CZ_RX_RSS_IPV6_TKEY_HI_LBN +
838             FRF_CZ_RX_RSS_IPV6_TKEY_HI_WIDTH) / 8;
839             offset > 0 && byte < n;
840             --offset)
841                 oword.eo_u8[offset - 1] = key[byte++];
842
843         EFX_BAR_WRITEO(enp, FR_CZ_RX_RSS_IPV6_REG3, &oword);
844
845         /* Write Toeplitz IPv6 hash key 2 */
846         EFX_ZERO_OWORD(oword);
847         for (offset = (FRF_CZ_RX_RSS_IPV6_TKEY_MID_LBN +
848             FRF_CZ_RX_RSS_IPV6_TKEY_MID_WIDTH) / 8;
849             offset > 0 && byte < n;
850             --offset)
851                 oword.eo_u8[offset - 1] = key[byte++];
852
853         EFX_BAR_WRITEO(enp, FR_CZ_RX_RSS_IPV6_REG2, &oword);
854
855         /* Write Toeplitz IPv6 hash key 1 */
856         EFX_ZERO_OWORD(oword);
857         for (offset = (FRF_CZ_RX_RSS_IPV6_TKEY_LO_LBN +
858             FRF_CZ_RX_RSS_IPV6_TKEY_LO_WIDTH) / 8;
859             offset > 0 && byte < n;
860             --offset)
861                 oword.eo_u8[offset - 1] = key[byte++];
862
863         EFX_BAR_WRITEO(enp, FR_CZ_RX_RSS_IPV6_REG1, &oword);
864
865         byte = 0;
866
867         /* Verify Toeplitz IPv6 hash key 3 */
868         EFX_BAR_READO(enp, FR_CZ_RX_RSS_IPV6_REG3, &oword);
869         for (offset = (FRF_CZ_RX_RSS_IPV6_TKEY_HI_LBN +
870             FRF_CZ_RX_RSS_IPV6_TKEY_HI_WIDTH) / 8;
871             offset > 0 && byte < n;
872             --offset) {
873                 if (oword.eo_u8[offset - 1] != key[byte++]) {
874                         rc = EFAULT;
875                         goto fail2;
876                 }
877         }
878
879         /* Verify Toeplitz IPv6 hash key 2 */
880         EFX_BAR_READO(enp, FR_CZ_RX_RSS_IPV6_REG2, &oword);
881         for (offset = (FRF_CZ_RX_RSS_IPV6_TKEY_MID_LBN +
882             FRF_CZ_RX_RSS_IPV6_TKEY_MID_WIDTH) / 8;
883             offset > 0 && byte < n;
884             --offset) {
885                 if (oword.eo_u8[offset - 1] != key[byte++]) {
886                         rc = EFAULT;
887                         goto fail3;
888                 }
889         }
890
891         /* Verify Toeplitz IPv6 hash key 1 */
892         EFX_BAR_READO(enp, FR_CZ_RX_RSS_IPV6_REG1, &oword);
893         for (offset = (FRF_CZ_RX_RSS_IPV6_TKEY_LO_LBN +
894             FRF_CZ_RX_RSS_IPV6_TKEY_LO_WIDTH) / 8;
895             offset > 0 && byte < n;
896             --offset) {
897                 if (oword.eo_u8[offset - 1] != key[byte++]) {
898                         rc = EFAULT;
899                         goto fail4;
900                 }
901         }
902
903 done:
904         return (0);
905
906 fail4:
907         EFSYS_PROBE(fail4);
908 fail3:
909         EFSYS_PROBE(fail3);
910 fail2:
911         EFSYS_PROBE(fail2);
912 fail1:
913         EFSYS_PROBE1(fail1, efx_rc_t, rc);
914
915         return (rc);
916 }
917 #endif
918
919 #if EFSYS_OPT_RX_SCALE
920 static  __checkReturn   efx_rc_t
921 falconsiena_rx_scale_tbl_set(
922         __in            efx_nic_t *enp,
923         __in_ecount(n)  unsigned int *table,
924         __in            size_t n)
925 {
926         efx_oword_t oword;
927         int index;
928         efx_rc_t rc;
929
930         EFX_STATIC_ASSERT(EFX_RSS_TBL_SIZE == FR_BZ_RX_INDIRECTION_TBL_ROWS);
931         EFX_STATIC_ASSERT(EFX_MAXRSS == (1 << FRF_BZ_IT_QUEUE_WIDTH));
932
933         if (n > FR_BZ_RX_INDIRECTION_TBL_ROWS) {
934                 rc = EINVAL;
935                 goto fail1;
936         }
937
938         for (index = 0; index < FR_BZ_RX_INDIRECTION_TBL_ROWS; index++) {
939                 uint32_t byte;
940
941                 /* Calculate the entry to place in the table */
942                 byte = (n > 0) ? (uint32_t)table[index % n] : 0;
943
944                 EFSYS_PROBE2(table, int, index, uint32_t, byte);
945
946                 EFX_POPULATE_OWORD_1(oword, FRF_BZ_IT_QUEUE, byte);
947
948                 /* Write the table */
949                 EFX_BAR_TBL_WRITEO(enp, FR_BZ_RX_INDIRECTION_TBL,
950                                     index, &oword, B_TRUE);
951         }
952
953         for (index = FR_BZ_RX_INDIRECTION_TBL_ROWS - 1; index >= 0; --index) {
954                 uint32_t byte;
955
956                 /* Determine if we're starting a new batch */
957                 byte = (n > 0) ? (uint32_t)table[index % n] : 0;
958
959                 /* Read the table */
960                 EFX_BAR_TBL_READO(enp, FR_BZ_RX_INDIRECTION_TBL,
961                                     index, &oword, B_TRUE);
962
963                 /* Verify the entry */
964                 if (EFX_OWORD_FIELD(oword, FRF_BZ_IT_QUEUE) != byte) {
965                         rc = EFAULT;
966                         goto fail2;
967                 }
968         }
969
970         return (0);
971
972 fail2:
973         EFSYS_PROBE(fail2);
974 fail1:
975         EFSYS_PROBE1(fail1, efx_rc_t, rc);
976
977         return (rc);
978 }
979 #endif
980
981 /*
982  * Falcon/Siena psuedo-header
983  * --------------------------
984  *
985  * Receive packets are prefixed by an optional 16 byte pseudo-header.
986  * The psuedo-header is a byte array of one of the forms:
987  *
988  *  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
989  * xx.xx.xx.xx.xx.xx.xx.xx.xx.xx.xx.xx.TT.TT.TT.TT
990  * xx.xx.xx.xx.xx.xx.xx.xx.xx.xx.xx.xx.xx.xx.LL.LL
991  *
992  * where:
993  *   TT.TT.TT.TT   Toeplitz hash (32-bit big-endian)
994  *   LL.LL         LFSR hash     (16-bit big-endian)
995  */
996
997 #if EFSYS_OPT_RX_SCALE
998 static  __checkReturn   uint32_t
999 falconsiena_rx_prefix_hash(
1000         __in            efx_nic_t *enp,
1001         __in            efx_rx_hash_alg_t func,
1002         __in            uint8_t *buffer)
1003 {
1004         switch (func) {
1005         case EFX_RX_HASHALG_TOEPLITZ:
1006                 return ((buffer[12] << 24) |
1007                     (buffer[13] << 16) |
1008                     (buffer[14] <<  8) |
1009                     buffer[15]);
1010
1011         case EFX_RX_HASHALG_LFSR:
1012                 return ((buffer[14] << 8) | buffer[15]);
1013
1014         default:
1015                 EFSYS_ASSERT(0);
1016                 return (0);
1017         }
1018 }
1019 #endif /* EFSYS_OPT_RX_SCALE */
1020
1021 static  __checkReturn   efx_rc_t
1022 falconsiena_rx_prefix_pktlen(
1023         __in            efx_nic_t *enp,
1024         __in            uint8_t *buffer,
1025         __out           uint16_t *lengthp)
1026 {
1027         /* Not supported by Falcon/Siena hardware */
1028         EFSYS_ASSERT(0);
1029         return (ENOTSUP);
1030 }
1031
1032
1033 static                  void
1034 falconsiena_rx_qpost(
1035         __in            efx_rxq_t *erp,
1036         __in_ecount(n)  efsys_dma_addr_t *addrp,
1037         __in            size_t size,
1038         __in            unsigned int n,
1039         __in            unsigned int completed,
1040         __in            unsigned int added)
1041 {
1042         efx_qword_t qword;
1043         unsigned int i;
1044         unsigned int offset;
1045         unsigned int id;
1046
1047         /* The client driver must not overfill the queue */
1048         EFSYS_ASSERT3U(added - completed + n, <=,
1049             EFX_RXQ_LIMIT(erp->er_mask + 1));
1050
1051         id = added & (erp->er_mask);
1052         for (i = 0; i < n; i++) {
1053                 EFSYS_PROBE4(rx_post, unsigned int, erp->er_index,
1054                     unsigned int, id, efsys_dma_addr_t, addrp[i],
1055                     size_t, size);
1056
1057                 EFX_POPULATE_QWORD_3(qword,
1058                     FSF_AZ_RX_KER_BUF_SIZE, (uint32_t)(size),
1059                     FSF_AZ_RX_KER_BUF_ADDR_DW0,
1060                     (uint32_t)(addrp[i] & 0xffffffff),
1061                     FSF_AZ_RX_KER_BUF_ADDR_DW1,
1062                     (uint32_t)(addrp[i] >> 32));
1063
1064                 offset = id * sizeof (efx_qword_t);
1065                 EFSYS_MEM_WRITEQ(erp->er_esmp, offset, &qword);
1066
1067                 id = (id + 1) & (erp->er_mask);
1068         }
1069 }
1070
1071 static                  void
1072 falconsiena_rx_qpush(
1073         __in    efx_rxq_t *erp,
1074         __in    unsigned int added,
1075         __inout unsigned int *pushedp)
1076 {
1077         efx_nic_t *enp = erp->er_enp;
1078         unsigned int pushed = *pushedp;
1079         uint32_t wptr;
1080         efx_oword_t oword;
1081         efx_dword_t dword;
1082
1083         /* All descriptors are pushed */
1084         *pushedp = added;
1085
1086         /* Push the populated descriptors out */
1087         wptr = added & erp->er_mask;
1088
1089         EFX_POPULATE_OWORD_1(oword, FRF_AZ_RX_DESC_WPTR, wptr);
1090
1091         /* Only write the third DWORD */
1092         EFX_POPULATE_DWORD_1(dword,
1093             EFX_DWORD_0, EFX_OWORD_FIELD(oword, EFX_DWORD_3));
1094
1095         /* Guarantee ordering of memory (descriptors) and PIO (doorbell) */
1096         EFX_DMA_SYNC_QUEUE_FOR_DEVICE(erp->er_esmp, erp->er_mask + 1,
1097             wptr, pushed & erp->er_mask);
1098         EFSYS_PIO_WRITE_BARRIER();
1099         EFX_BAR_TBL_WRITED3(enp, FR_BZ_RX_DESC_UPD_REGP0,
1100                             erp->er_index, &dword, B_FALSE);
1101 }
1102
1103 static  __checkReturn   efx_rc_t
1104 falconsiena_rx_qflush(
1105         __in    efx_rxq_t *erp)
1106 {
1107         efx_nic_t *enp = erp->er_enp;
1108         efx_oword_t oword;
1109         uint32_t label;
1110
1111         label = erp->er_index;
1112
1113         /* Flush the queue */
1114         EFX_POPULATE_OWORD_2(oword, FRF_AZ_RX_FLUSH_DESCQ_CMD, 1,
1115             FRF_AZ_RX_FLUSH_DESCQ, label);
1116         EFX_BAR_WRITEO(enp, FR_AZ_RX_FLUSH_DESCQ_REG, &oword);
1117
1118         return (0);
1119 }
1120
1121 static          void
1122 falconsiena_rx_qenable(
1123         __in    efx_rxq_t *erp)
1124 {
1125         efx_nic_t *enp = erp->er_enp;
1126         efx_oword_t oword;
1127
1128         EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
1129
1130         EFX_BAR_TBL_READO(enp, FR_AZ_RX_DESC_PTR_TBL,
1131                             erp->er_index, &oword, B_TRUE);
1132
1133         EFX_SET_OWORD_FIELD(oword, FRF_AZ_RX_DC_HW_RPTR, 0);
1134         EFX_SET_OWORD_FIELD(oword, FRF_AZ_RX_DESCQ_HW_RPTR, 0);
1135         EFX_SET_OWORD_FIELD(oword, FRF_AZ_RX_DESCQ_EN, 1);
1136
1137         EFX_BAR_TBL_WRITEO(enp, FR_AZ_RX_DESC_PTR_TBL,
1138                             erp->er_index, &oword, B_TRUE);
1139 }
1140
1141 static  __checkReturn   efx_rc_t
1142 falconsiena_rx_qcreate(
1143         __in            efx_nic_t *enp,
1144         __in            unsigned int index,
1145         __in            unsigned int label,
1146         __in            efx_rxq_type_t type,
1147         __in            efsys_mem_t *esmp,
1148         __in            size_t n,
1149         __in            uint32_t id,
1150         __in            efx_evq_t *eep,
1151         __in            efx_rxq_t *erp)
1152 {
1153         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1154         efx_oword_t oword;
1155         uint32_t size;
1156         boolean_t jumbo;
1157         efx_rc_t rc;
1158
1159         EFX_STATIC_ASSERT(EFX_EV_RX_NLABELS ==
1160             (1 << FRF_AZ_RX_DESCQ_LABEL_WIDTH));
1161         EFSYS_ASSERT3U(label, <, EFX_EV_RX_NLABELS);
1162         EFSYS_ASSERT3U(enp->en_rx_qcount + 1, <, encp->enc_rxq_limit);
1163
1164         EFX_STATIC_ASSERT(ISP2(EFX_RXQ_MAXNDESCS));
1165         EFX_STATIC_ASSERT(ISP2(EFX_RXQ_MINNDESCS));
1166
1167         if (!ISP2(n) || (n < EFX_RXQ_MINNDESCS) || (n > EFX_RXQ_MAXNDESCS)) {
1168                 rc = EINVAL;
1169                 goto fail1;
1170         }
1171         if (index >= encp->enc_rxq_limit) {
1172                 rc = EINVAL;
1173                 goto fail2;
1174         }
1175         for (size = 0; (1 << size) <= (EFX_RXQ_MAXNDESCS / EFX_RXQ_MINNDESCS);
1176             size++)
1177                 if ((1 << size) == (int)(n / EFX_RXQ_MINNDESCS))
1178                         break;
1179         if (id + (1 << size) >= encp->enc_buftbl_limit) {
1180                 rc = EINVAL;
1181                 goto fail3;
1182         }
1183
1184         switch (type) {
1185         case EFX_RXQ_TYPE_DEFAULT:
1186                 jumbo = B_FALSE;
1187                 break;
1188
1189 #if EFSYS_OPT_RX_SCATTER
1190         case EFX_RXQ_TYPE_SCATTER:
1191                 if (enp->en_family < EFX_FAMILY_SIENA) {
1192                         rc = EINVAL;
1193                         goto fail4;
1194                 }
1195                 jumbo = B_TRUE;
1196                 break;
1197 #endif  /* EFSYS_OPT_RX_SCATTER */
1198
1199         default:
1200                 rc = EINVAL;
1201                 goto fail4;
1202         }
1203
1204         /* Set up the new descriptor queue */
1205         EFX_POPULATE_OWORD_7(oword,
1206             FRF_AZ_RX_DESCQ_BUF_BASE_ID, id,
1207             FRF_AZ_RX_DESCQ_EVQ_ID, eep->ee_index,
1208             FRF_AZ_RX_DESCQ_OWNER_ID, 0,
1209             FRF_AZ_RX_DESCQ_LABEL, label,
1210             FRF_AZ_RX_DESCQ_SIZE, size,
1211             FRF_AZ_RX_DESCQ_TYPE, 0,
1212             FRF_AZ_RX_DESCQ_JUMBO, jumbo);
1213
1214         EFX_BAR_TBL_WRITEO(enp, FR_AZ_RX_DESC_PTR_TBL,
1215                             erp->er_index, &oword, B_TRUE);
1216
1217         return (0);
1218
1219 fail4:
1220         EFSYS_PROBE(fail4);
1221 fail3:
1222         EFSYS_PROBE(fail3);
1223 fail2:
1224         EFSYS_PROBE(fail2);
1225 fail1:
1226         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1227
1228         return (rc);
1229 }
1230
1231 static          void
1232 falconsiena_rx_qdestroy(
1233         __in    efx_rxq_t *erp)
1234 {
1235         efx_nic_t *enp = erp->er_enp;
1236         efx_oword_t oword;
1237
1238         EFSYS_ASSERT(enp->en_rx_qcount != 0);
1239         --enp->en_rx_qcount;
1240
1241         /* Purge descriptor queue */
1242         EFX_ZERO_OWORD(oword);
1243
1244         EFX_BAR_TBL_WRITEO(enp, FR_AZ_RX_DESC_PTR_TBL,
1245                             erp->er_index, &oword, B_TRUE);
1246
1247         /* Free the RXQ object */
1248         EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_rxq_t), erp);
1249 }
1250
1251 static          void
1252 falconsiena_rx_fini(
1253         __in    efx_nic_t *enp)
1254 {
1255         _NOTE(ARGUNUSED(enp))
1256 }
1257
1258 #endif /* EFSYS_OPT_FALCON || EFSYS_OPT_SIENA */