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