2 * Copyright (c) 2007-2015 Solarflare Communications Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
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.
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.
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.
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
36 #include "efx_types.h"
41 #if EFSYS_OPT_FALCON || EFSYS_OPT_SIENA
43 static __checkReturn int
51 #if EFSYS_OPT_RX_HDR_SPLIT
52 static __checkReturn int
53 falconsiena_rx_hdr_split_enable(
55 __in unsigned int hdr_buf_size,
56 __in unsigned int pld_buf_size);
57 #endif /* EFSYS_OPT_RX_HDR_SPLIT */
59 #if EFSYS_OPT_RX_SCATTER
60 static __checkReturn int
61 falconsiena_rx_scatter_enable(
63 __in unsigned int buf_size);
64 #endif /* EFSYS_OPT_RX_SCATTER */
66 #if EFSYS_OPT_RX_SCALE
67 static __checkReturn int
68 falconsiena_rx_scale_mode_set(
70 __in efx_rx_hash_alg_t alg,
71 __in efx_rx_hash_type_t type,
72 __in boolean_t insert);
74 static __checkReturn int
75 falconsiena_rx_scale_key_set(
77 __in_ecount(n) uint8_t *key,
80 static __checkReturn int
81 falconsiena_rx_scale_tbl_set(
83 __in_ecount(n) unsigned int *table,
86 #endif /* EFSYS_OPT_RX_SCALE */
91 __in_ecount(n) efsys_dma_addr_t *addrp,
94 __in unsigned int completed,
95 __in unsigned int added);
100 __in unsigned int added,
101 __inout unsigned int *pushedp);
103 static __checkReturn int
104 falconsiena_rx_qflush(
105 __in efx_rxq_t *erp);
108 falconsiena_rx_qenable(
109 __in efx_rxq_t *erp);
111 static __checkReturn int
112 falconsiena_rx_qcreate(
114 __in unsigned int index,
115 __in unsigned int label,
116 __in efx_rxq_type_t type,
117 __in efsys_mem_t *esmp,
121 __in efx_rxq_t *erp);
124 falconsiena_rx_qdestroy(
125 __in efx_rxq_t *erp);
127 #endif /* EFSYS_OPT_FALCON || EFSYS_OPT_SIENA */
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 */
137 #if EFSYS_OPT_RX_SCATTER
138 falconsiena_rx_scatter_enable, /* erxo_scatter_enable */
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 */
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 */
152 #endif /* EFSYS_OPT_FALCON */
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 */
161 #if EFSYS_OPT_RX_SCATTER
162 falconsiena_rx_scatter_enable, /* erxo_scatter_enable */
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 */
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 */
176 #endif /* EFSYS_OPT_SIENA */
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 */
185 #if EFSYS_OPT_RX_SCATTER
186 hunt_rx_scatter_enable, /* erxo_scatter_enable */
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 */
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 */
200 #endif /* EFSYS_OPT_HUNTINGTON */
205 __inout efx_nic_t *enp)
210 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
211 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
213 if (!(enp->en_mod_flags & EFX_MOD_EV)) {
218 if (enp->en_mod_flags & EFX_MOD_RX) {
223 switch (enp->en_family) {
225 case EFX_FAMILY_FALCON:
226 erxop = (efx_rx_ops_t *)&__efx_rx_falcon_ops;
228 #endif /* EFSYS_OPT_FALCON */
231 case EFX_FAMILY_SIENA:
232 erxop = (efx_rx_ops_t *)&__efx_rx_siena_ops;
234 #endif /* EFSYS_OPT_SIENA */
236 #if EFSYS_OPT_HUNTINGTON
237 case EFX_FAMILY_HUNTINGTON:
238 erxop = (efx_rx_ops_t *)&__efx_rx_hunt_ops;
240 #endif /* EFSYS_OPT_HUNTINGTON */
248 if ((rc = erxop->erxo_init(enp)) != 0)
251 enp->en_erxop = erxop;
252 enp->en_mod_flags |= EFX_MOD_RX;
262 EFSYS_PROBE1(fail1, int, rc);
264 enp->en_erxop = NULL;
265 enp->en_mod_flags &= ~EFX_MOD_RX;
273 efx_rx_ops_t *erxop = enp->en_erxop;
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);
280 erxop->erxo_fini(enp);
282 enp->en_erxop = NULL;
283 enp->en_mod_flags &= ~EFX_MOD_RX;
286 #if EFSYS_OPT_RX_HDR_SPLIT
288 efx_rx_hdr_split_enable(
290 __in unsigned int hdr_buf_size,
291 __in unsigned int pld_buf_size)
293 efx_rx_ops_t *erxop = enp->en_erxop;
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);
300 if ((rc = erxop->erxo_hdr_split_enable(enp, hdr_buf_size,
307 EFSYS_PROBE1(fail1, int, rc);
310 #endif /* EFSYS_OPT_RX_HDR_SPLIT */
312 #if EFSYS_OPT_RX_SCATTER
314 efx_rx_scatter_enable(
316 __in unsigned int buf_size)
318 efx_rx_ops_t *erxop = enp->en_erxop;
321 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
322 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX);
324 if ((rc = erxop->erxo_scatter_enable(enp, buf_size)) != 0)
330 EFSYS_PROBE1(fail1, int, rc);
333 #endif /* EFSYS_OPT_RX_SCATTER */
335 #if EFSYS_OPT_RX_SCALE
337 efx_rx_hash_support_get(
339 __out efx_rx_hash_support_t *supportp)
343 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
344 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX);
346 if (supportp == NULL) {
351 /* Report if resources are available to insert RX hash value */
352 *supportp = enp->en_hash_support;
357 EFSYS_PROBE1(fail1, int, rc);
363 efx_rx_scale_support_get(
365 __out efx_rx_scale_support_t *supportp)
369 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
370 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX);
372 if (supportp == NULL) {
377 /* Report if resources are available to support RSS */
378 *supportp = enp->en_rss_support;
383 EFSYS_PROBE1(fail1, int, rc);
389 efx_rx_scale_mode_set(
391 __in efx_rx_hash_alg_t alg,
392 __in efx_rx_hash_type_t type,
393 __in boolean_t insert)
395 efx_rx_ops_t *erxop = enp->en_erxop;
398 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
399 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX);
401 if (erxop->erxo_scale_mode_set != NULL) {
402 if ((rc = erxop->erxo_scale_mode_set(enp, alg,
410 EFSYS_PROBE1(fail1, int, rc);
413 #endif /* EFSYS_OPT_RX_SCALE */
415 #if EFSYS_OPT_RX_SCALE
417 efx_rx_scale_key_set(
419 __in_ecount(n) uint8_t *key,
422 efx_rx_ops_t *erxop = enp->en_erxop;
425 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
426 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX);
428 if ((rc = erxop->erxo_scale_key_set(enp, key, n)) != 0)
434 EFSYS_PROBE1(fail1, int, rc);
438 #endif /* EFSYS_OPT_RX_SCALE */
440 #if EFSYS_OPT_RX_SCALE
442 efx_rx_scale_tbl_set(
444 __in_ecount(n) unsigned int *table,
447 efx_rx_ops_t *erxop = enp->en_erxop;
450 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
451 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX);
453 if ((rc = erxop->erxo_scale_tbl_set(enp, table, n)) != 0)
459 EFSYS_PROBE1(fail1, int, rc);
463 #endif /* EFSYS_OPT_RX_SCALE */
468 __in_ecount(n) efsys_dma_addr_t *addrp,
471 __in unsigned int completed,
472 __in unsigned int added)
474 efx_nic_t *enp = erp->er_enp;
475 efx_rx_ops_t *erxop = enp->en_erxop;
477 EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
479 erxop->erxo_qpost(erp, addrp, size, n, completed, added);
485 __in unsigned int added,
486 __inout unsigned int *pushedp)
488 efx_nic_t *enp = erp->er_enp;
489 efx_rx_ops_t *erxop = enp->en_erxop;
491 EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
493 erxop->erxo_qpush(erp, added, pushedp);
500 efx_nic_t *enp = erp->er_enp;
501 efx_rx_ops_t *erxop = enp->en_erxop;
504 EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
506 if ((rc = erxop->erxo_qflush(erp)) != 0)
512 EFSYS_PROBE1(fail1, int, rc);
521 efx_nic_t *enp = erp->er_enp;
522 efx_rx_ops_t *erxop = enp->en_erxop;
524 EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
526 erxop->erxo_qenable(erp);
532 __in unsigned int index,
533 __in unsigned int label,
534 __in efx_rxq_type_t type,
535 __in efsys_mem_t *esmp,
539 __deref_out efx_rxq_t **erpp)
541 efx_rx_ops_t *erxop = enp->en_erxop;
545 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
546 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX);
548 /* Allocate an RXQ object */
549 EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (efx_rxq_t), erp);
556 erp->er_magic = EFX_RXQ_MAGIC;
558 erp->er_index = index;
559 erp->er_mask = n - 1;
562 if ((rc = erxop->erxo_qcreate(enp, index, label, type, esmp, n, id,
574 EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_rxq_t), erp);
576 EFSYS_PROBE1(fail1, int, rc);
585 efx_nic_t *enp = erp->er_enp;
586 efx_rx_ops_t *erxop = enp->en_erxop;
588 EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
590 erxop->erxo_qdestroy(erp);
594 * Psuedo-header info for Siena/Falcon.
596 * The psuedo-header is a byte array of one of the forms:
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
604 * TT.TT.TT.TT is a 32-bit Toeplitz hash
605 * LL.LL is a 16-bit LFSR hash
607 * Hash values are in network (big-endian) byte order.
610 * On Huntington the pseudo-header is laid out as:
611 * (See also SF-109306-TC section 9)
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)
621 * (16 bits, big-endian, 0 if the packet did not have an outer VLAN tag)
623 * (16 bits, big-endian, 0 if the packet did not have an inner VLAN tag)
627 efx_psuedo_hdr_pkt_length_get(
629 __in uint8_t *buffer,
630 __out uint16_t *pkt_lengthp)
632 if (enp->en_family != EFX_FAMILY_HUNTINGTON) {
637 *pkt_lengthp = buffer[8] | (buffer[9] << 8);
642 #if EFSYS_OPT_RX_SCALE
645 efx_psuedo_hdr_hash_get(
647 __in efx_rx_hash_alg_t func,
648 __in uint8_t *buffer)
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) |
658 case EFX_FAMILY_HUNTINGTON:
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]);
677 #endif /* EFSYS_OPT_RX_SCALE */
679 #if EFSYS_OPT_FALCON || EFSYS_OPT_SIENA
681 static __checkReturn int
688 EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword);
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);
698 /* Zero the RSS table */
699 for (index = 0; index < FR_BZ_RX_INDIRECTION_TBL_ROWS;
701 EFX_ZERO_OWORD(oword);
702 EFX_BAR_TBL_WRITEO(enp, FR_BZ_RX_INDIRECTION_TBL,
703 index, &oword, B_TRUE);
706 #if EFSYS_OPT_RX_SCALE
707 /* The RSS key and indirection table are writable. */
708 enp->en_rss_support = EFX_RX_SCALE_EXCLUSIVE;
710 /* Hardware can insert RX hash with/without RSS */
711 enp->en_hash_support = EFX_RX_HASH_AVAILABLE;
712 #endif /* EFSYS_OPT_RX_SCALE */
717 #if EFSYS_OPT_RX_HDR_SPLIT
718 static __checkReturn int
719 falconsiena_rx_hdr_split_enable(
721 __in unsigned int hdr_buf_size,
722 __in unsigned int pld_buf_size)
729 nhdr32 = hdr_buf_size / 32;
731 (nhdr32 >= (1 << FRF_CZ_RX_HDR_SPLIT_HDR_BUF_SIZE_WIDTH)) ||
732 ((hdr_buf_size % 32) != 0)) {
737 npld32 = pld_buf_size / 32;
739 (npld32 >= (1 << FRF_CZ_RX_HDR_SPLIT_PLD_BUF_SIZE_WIDTH)) ||
740 ((pld_buf_size % 32) != 0)) {
745 if (enp->en_rx_qcount > 0) {
750 EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword);
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);
756 EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword);
765 EFSYS_PROBE1(fail1, int, rc);
769 #endif /* EFSYS_OPT_RX_HDR_SPLIT */
771 #if EFSYS_OPT_RX_SCATTER
772 static __checkReturn int
773 falconsiena_rx_scatter_enable(
775 __in unsigned int buf_size)
781 nbuf32 = buf_size / 32;
783 (nbuf32 >= (1 << FRF_BZ_RX_USR_BUF_SIZE_WIDTH)) ||
784 ((buf_size % 32) != 0)) {
789 if (enp->en_rx_qcount > 0) {
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);
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);
809 EFSYS_PROBE1(fail1, int, rc);
813 #endif /* EFSYS_OPT_RX_SCATTER */
816 #define EFX_RX_LFSR_HASH(_enp, _insert) \
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); \
828 if ((_enp)->en_family == EFX_FAMILY_SIENA) { \
829 EFX_BAR_READO((_enp), FR_CZ_RX_RSS_IPV6_REG3, \
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, \
837 _NOTE(CONSTANTCONDITION) \
840 #define EFX_RX_TOEPLITZ_IPV4_HASH(_enp, _insert, _ip, _tcp) \
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, \
848 EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_TCP_SUP, \
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); \
854 _NOTE(CONSTANTCONDITION) \
857 #define EFX_RX_TOEPLITZ_IPV6_HASH(_enp, _ip, _tcp, _rc) \
861 if ((_enp)->en_family == EFX_FAMILY_FALCON) { \
862 (_rc) = ((_ip) || (_tcp)) ? ENOTSUP : 0; \
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); \
877 _NOTE(CONSTANTCONDITION) \
881 #if EFSYS_OPT_RX_SCALE
883 static __checkReturn int
884 falconsiena_rx_scale_mode_set(
886 __in efx_rx_hash_alg_t alg,
887 __in efx_rx_hash_type_t type,
888 __in boolean_t insert)
893 case EFX_RX_HASHALG_LFSR:
894 EFX_RX_LFSR_HASH(enp, insert);
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));
902 EFX_RX_TOEPLITZ_IPV6_HASH(enp,
903 type & (1 << EFX_RX_HASH_IPV6),
904 type & (1 << EFX_RX_HASH_TCPIPV6),
921 EFSYS_PROBE1(fail1, int, rc);
923 EFX_RX_LFSR_HASH(enp, B_FALSE);
929 #if EFSYS_OPT_RX_SCALE
930 static __checkReturn int
931 falconsiena_rx_scale_key_set(
933 __in_ecount(n) uint8_t *key,
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;
948 oword.eo_u8[offset - 1] = key[byte++];
950 EFX_BAR_WRITEO(enp, FR_BZ_RX_RSS_TKEY_REG, &oword);
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;
959 if (oword.eo_u8[offset - 1] != key[byte++]) {
965 if ((enp->en_features & EFX_FEATURE_IPV6) == 0)
968 EFSYS_ASSERT3U(enp->en_family, !=, EFX_FAMILY_FALCON);
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;
978 oword.eo_u8[offset - 1] = key[byte++];
980 EFX_BAR_WRITEO(enp, FR_CZ_RX_RSS_IPV6_REG3, &oword);
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;
988 oword.eo_u8[offset - 1] = key[byte++];
990 EFX_BAR_WRITEO(enp, FR_CZ_RX_RSS_IPV6_REG2, &oword);
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;
998 oword.eo_u8[offset - 1] = key[byte++];
1000 EFX_BAR_WRITEO(enp, FR_CZ_RX_RSS_IPV6_REG1, &oword);
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;
1010 if (oword.eo_u8[offset - 1] != key[byte++]) {
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;
1022 if (oword.eo_u8[offset - 1] != key[byte++]) {
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;
1034 if (oword.eo_u8[offset - 1] != key[byte++]) {
1050 EFSYS_PROBE1(fail1, int, rc);
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,
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));
1070 if (n > FR_BZ_RX_INDIRECTION_TBL_ROWS) {
1075 for (index = 0; index < FR_BZ_RX_INDIRECTION_TBL_ROWS; index++) {
1078 /* Calculate the entry to place in the table */
1079 byte = (n > 0) ? (uint32_t)table[index % n] : 0;
1081 EFSYS_PROBE2(table, int, index, uint32_t, byte);
1083 EFX_POPULATE_OWORD_1(oword, FRF_BZ_IT_QUEUE, byte);
1085 /* Write the table */
1086 EFX_BAR_TBL_WRITEO(enp, FR_BZ_RX_INDIRECTION_TBL,
1087 index, &oword, B_TRUE);
1090 for (index = FR_BZ_RX_INDIRECTION_TBL_ROWS - 1; index >= 0; --index) {
1093 /* Determine if we're starting a new batch */
1094 byte = (n > 0) ? (uint32_t)table[index % n] : 0;
1096 /* Read the table */
1097 EFX_BAR_TBL_READO(enp, FR_BZ_RX_INDIRECTION_TBL,
1098 index, &oword, B_TRUE);
1100 /* Verify the entry */
1101 if (EFX_OWORD_FIELD(oword, FRF_BZ_IT_QUEUE) != byte) {
1112 EFSYS_PROBE1(fail1, int, rc);
1119 falconsiena_rx_qpost(
1120 __in efx_rxq_t *erp,
1121 __in_ecount(n) efsys_dma_addr_t *addrp,
1123 __in unsigned int n,
1124 __in unsigned int completed,
1125 __in unsigned int added)
1129 unsigned int offset;
1132 /* The client driver must not overfill the queue */
1133 EFSYS_ASSERT3U(added - completed + n, <=,
1134 EFX_RXQ_LIMIT(erp->er_mask + 1));
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],
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));
1149 offset = id * sizeof (efx_qword_t);
1150 EFSYS_MEM_WRITEQ(erp->er_esmp, offset, &qword);
1152 id = (id + 1) & (erp->er_mask);
1157 falconsiena_rx_qpush(
1158 __in efx_rxq_t *erp,
1159 __in unsigned int added,
1160 __inout unsigned int *pushedp)
1162 efx_nic_t *enp = erp->er_enp;
1163 unsigned int pushed = *pushedp;
1168 /* All descriptors are pushed */
1171 /* Push the populated descriptors out */
1172 wptr = added & erp->er_mask;
1174 EFX_POPULATE_OWORD_1(oword, FRF_AZ_RX_DESC_WPTR, wptr);
1176 /* Only write the third DWORD */
1177 EFX_POPULATE_DWORD_1(dword,
1178 EFX_DWORD_0, EFX_OWORD_FIELD(oword, EFX_DWORD_3));
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);
1188 static __checkReturn int
1189 falconsiena_rx_qflush(
1190 __in efx_rxq_t *erp)
1192 efx_nic_t *enp = erp->er_enp;
1196 label = erp->er_index;
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);
1207 falconsiena_rx_qenable(
1208 __in efx_rxq_t *erp)
1210 efx_nic_t *enp = erp->er_enp;
1213 EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
1215 EFX_BAR_TBL_READO(enp, FR_AZ_RX_DESC_PTR_TBL,
1216 erp->er_index, &oword, B_TRUE);
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);
1222 EFX_BAR_TBL_WRITEO(enp, FR_AZ_RX_DESC_PTR_TBL,
1223 erp->er_index, &oword, B_TRUE);
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,
1235 __in efx_evq_t *eep,
1236 __in efx_rxq_t *erp)
1238 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
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);
1250 EFX_STATIC_ASSERT(ISP2(EFX_RXQ_MAXNDESCS));
1251 EFX_STATIC_ASSERT(ISP2(EFX_RXQ_MINNDESCS));
1253 if (!ISP2(n) || (n < EFX_RXQ_MINNDESCS) || (n > EFX_RXQ_MAXNDESCS)) {
1257 if (index >= encp->enc_rxq_limit) {
1261 for (size = 0; (1 << size) <= (EFX_RXQ_MAXNDESCS / EFX_RXQ_MINNDESCS);
1263 if ((1 << size) == (int)(n / EFX_RXQ_MINNDESCS))
1265 if (id + (1 << size) >= encp->enc_buftbl_limit) {
1271 case EFX_RXQ_TYPE_DEFAULT:
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)) {
1286 case EFX_RXQ_TYPE_SPLIT_PAYLOAD:
1287 if ((enp->en_family < EFX_FAMILY_SIENA) || ((index & 1) == 0)) {
1294 #endif /* EFSYS_OPT_RX_HDR_SPLIT */
1296 #if EFSYS_OPT_RX_SCATTER
1297 case EFX_RXQ_TYPE_SCATTER:
1298 if (enp->en_family < EFX_FAMILY_SIENA) {
1305 #endif /* EFSYS_OPT_RX_SCATTER */
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);
1325 EFX_BAR_TBL_WRITEO(enp, FR_AZ_RX_DESC_PTR_TBL,
1326 erp->er_index, &oword, B_TRUE);
1337 EFSYS_PROBE1(fail1, int, rc);
1343 falconsiena_rx_qdestroy(
1344 __in efx_rxq_t *erp)
1346 efx_nic_t *enp = erp->er_enp;
1349 EFSYS_ASSERT(enp->en_rx_qcount != 0);
1350 --enp->en_rx_qcount;
1352 /* Purge descriptor queue */
1353 EFX_ZERO_OWORD(oword);
1355 EFX_BAR_TBL_WRITEO(enp, FR_AZ_RX_DESC_PTR_TBL,
1356 erp->er_index, &oword, B_TRUE);
1358 /* Free the RXQ object */
1359 EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_rxq_t), erp);
1363 falconsiena_rx_fini(
1364 __in efx_nic_t *enp)
1366 _NOTE(ARGUNUSED(enp))
1369 #endif /* EFSYS_OPT_FALCON || EFSYS_OPT_SIENA */