xref: /freebsd/sys/dev/sfxge/common/efx_rx.c (revision 0ff2378988f66a607248711faec21b2190247ed7)
1e948693eSPhilip Paeps /*-
2e948693eSPhilip Paeps  * Copyright 2007-2009 Solarflare Communications Inc.  All rights reserved.
3e948693eSPhilip Paeps  *
4e948693eSPhilip Paeps  * Redistribution and use in source and binary forms, with or without
5e948693eSPhilip Paeps  * modification, are permitted provided that the following conditions
6e948693eSPhilip Paeps  * are met:
7e948693eSPhilip Paeps  * 1. Redistributions of source code must retain the above copyright
8e948693eSPhilip Paeps  *    notice, this list of conditions and the following disclaimer.
9e948693eSPhilip Paeps  * 2. Redistributions in binary form must reproduce the above copyright
10e948693eSPhilip Paeps  *    notice, this list of conditions and the following disclaimer in the
11e948693eSPhilip Paeps  *    documentation and/or other materials provided with the distribution.
12e948693eSPhilip Paeps  *
13e948693eSPhilip Paeps  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
14e948693eSPhilip Paeps  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15e948693eSPhilip Paeps  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16e948693eSPhilip Paeps  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17e948693eSPhilip Paeps  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18e948693eSPhilip Paeps  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19e948693eSPhilip Paeps  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20e948693eSPhilip Paeps  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21e948693eSPhilip Paeps  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22e948693eSPhilip Paeps  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23e948693eSPhilip Paeps  * SUCH DAMAGE.
24e948693eSPhilip Paeps  */
25e948693eSPhilip Paeps 
265dee87d7SPhilip Paeps #include <sys/cdefs.h>
275dee87d7SPhilip Paeps __FBSDID("$FreeBSD$");
285dee87d7SPhilip Paeps 
29e948693eSPhilip Paeps #include "efsys.h"
30e948693eSPhilip Paeps #include "efx.h"
31e948693eSPhilip Paeps #include "efx_types.h"
32e948693eSPhilip Paeps #include "efx_regs.h"
33e948693eSPhilip Paeps #include "efx_impl.h"
34e948693eSPhilip Paeps 
35e948693eSPhilip Paeps 	__checkReturn	int
36e948693eSPhilip Paeps efx_rx_init(
37e948693eSPhilip Paeps 	__in		efx_nic_t *enp)
38e948693eSPhilip Paeps {
39e948693eSPhilip Paeps 	efx_oword_t oword;
40e948693eSPhilip Paeps 	unsigned int index;
41e948693eSPhilip Paeps 	int rc;
42e948693eSPhilip Paeps 
43e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
44e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
45e948693eSPhilip Paeps 
46e948693eSPhilip Paeps 	if (!(enp->en_mod_flags & EFX_MOD_EV)) {
47e948693eSPhilip Paeps 		rc = EINVAL;
48e948693eSPhilip Paeps 		goto fail1;
49e948693eSPhilip Paeps 	}
50e948693eSPhilip Paeps 
51e948693eSPhilip Paeps 	if (enp->en_mod_flags & EFX_MOD_RX) {
52e948693eSPhilip Paeps 		rc = EINVAL;
53e948693eSPhilip Paeps 		goto fail2;
54e948693eSPhilip Paeps 	}
55e948693eSPhilip Paeps 
56e948693eSPhilip Paeps 	EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword);
57e948693eSPhilip Paeps 
58e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_DESC_PUSH_EN, 0);
59e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_HASH_ALG, 0);
60e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_IP_HASH, 0);
61e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_TCP_SUP, 0);
62e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_HASH_INSRT_HDR, 0);
63e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_USR_BUF_SIZE, 0x3000 / 32);
64e948693eSPhilip Paeps 	EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword);
65e948693eSPhilip Paeps 
66e948693eSPhilip Paeps 	/* Zero the RSS table */
67e948693eSPhilip Paeps 	for (index = 0; index < FR_BZ_RX_INDIRECTION_TBL_ROWS;
68e948693eSPhilip Paeps 	    index++) {
69e948693eSPhilip Paeps 		EFX_ZERO_OWORD(oword);
70e948693eSPhilip Paeps 		EFX_BAR_TBL_WRITEO(enp, FR_BZ_RX_INDIRECTION_TBL,
71e948693eSPhilip Paeps 				    index, &oword);
72e948693eSPhilip Paeps 	}
73e948693eSPhilip Paeps 
74e948693eSPhilip Paeps 	enp->en_mod_flags |= EFX_MOD_RX;
75e948693eSPhilip Paeps 	return (0);
76e948693eSPhilip Paeps 
77e948693eSPhilip Paeps fail2:
78e948693eSPhilip Paeps 	EFSYS_PROBE(fail2);
79e948693eSPhilip Paeps fail1:
80e948693eSPhilip Paeps 	EFSYS_PROBE1(fail1, int, rc);
81e948693eSPhilip Paeps 
82e948693eSPhilip Paeps 	return (rc);
83e948693eSPhilip Paeps }
84e948693eSPhilip Paeps 
85e948693eSPhilip Paeps #if EFSYS_OPT_RX_HDR_SPLIT
86e948693eSPhilip Paeps 	__checkReturn	int
87e948693eSPhilip Paeps efx_rx_hdr_split_enable(
88e948693eSPhilip Paeps 	__in		efx_nic_t *enp,
89e948693eSPhilip Paeps 	__in		unsigned int hdr_buf_size,
90e948693eSPhilip Paeps 	__in		unsigned int pld_buf_size)
91e948693eSPhilip Paeps {
92e948693eSPhilip Paeps 	unsigned int nhdr32;
93e948693eSPhilip Paeps 	unsigned int npld32;
94e948693eSPhilip Paeps 	efx_oword_t oword;
95e948693eSPhilip Paeps 	int rc;
96e948693eSPhilip Paeps 
97e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
98e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX);
99e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_family, >=, EFX_FAMILY_SIENA);
100e948693eSPhilip Paeps 
101e948693eSPhilip Paeps 	nhdr32 = hdr_buf_size / 32;
102e948693eSPhilip Paeps 	if ((nhdr32 == 0) ||
103e948693eSPhilip Paeps 	    (nhdr32 >= (1 << FRF_CZ_RX_HDR_SPLIT_HDR_BUF_SIZE_WIDTH)) ||
104e948693eSPhilip Paeps 	    ((hdr_buf_size % 32) != 0)) {
105e948693eSPhilip Paeps 		rc = EINVAL;
106e948693eSPhilip Paeps 		goto fail1;
107e948693eSPhilip Paeps 	}
108e948693eSPhilip Paeps 
109e948693eSPhilip Paeps 	npld32 = pld_buf_size / 32;
110e948693eSPhilip Paeps 	if ((npld32 == 0) ||
111e948693eSPhilip Paeps 	    (npld32 >= (1 << FRF_CZ_RX_HDR_SPLIT_PLD_BUF_SIZE_WIDTH)) ||
112e948693eSPhilip Paeps 	    ((pld_buf_size % 32) != 0)) {
113e948693eSPhilip Paeps 		rc = EINVAL;
114e948693eSPhilip Paeps 		goto fail2;
115e948693eSPhilip Paeps 	}
116e948693eSPhilip Paeps 
117e948693eSPhilip Paeps 	if (enp->en_rx_qcount > 0) {
118e948693eSPhilip Paeps 		rc = EBUSY;
119e948693eSPhilip Paeps 		goto fail3;
120e948693eSPhilip Paeps 	}
121e948693eSPhilip Paeps 
122e948693eSPhilip Paeps 	EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword);
123e948693eSPhilip Paeps 
124e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_HDR_SPLIT_EN, 1);
125e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_HDR_SPLIT_HDR_BUF_SIZE, nhdr32);
126e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_HDR_SPLIT_PLD_BUF_SIZE, npld32);
127e948693eSPhilip Paeps 
128e948693eSPhilip Paeps 	EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword);
129e948693eSPhilip Paeps 
130e948693eSPhilip Paeps 	return (0);
131e948693eSPhilip Paeps 
132e948693eSPhilip Paeps fail3:
133e948693eSPhilip Paeps 	EFSYS_PROBE(fail3);
134e948693eSPhilip Paeps fail2:
135e948693eSPhilip Paeps 	EFSYS_PROBE(fail2);
136e948693eSPhilip Paeps fail1:
137e948693eSPhilip Paeps 	EFSYS_PROBE1(fail1, int, rc);
138e948693eSPhilip Paeps 
139e948693eSPhilip Paeps 	return (rc);
140e948693eSPhilip Paeps }
141e948693eSPhilip Paeps #endif	/* EFSYS_OPT_RX_HDR_SPLIT */
142e948693eSPhilip Paeps 
143e948693eSPhilip Paeps 
144e948693eSPhilip Paeps #if EFSYS_OPT_RX_SCATTER
145e948693eSPhilip Paeps 	__checkReturn	int
146e948693eSPhilip Paeps efx_rx_scatter_enable(
147e948693eSPhilip Paeps 	__in		efx_nic_t *enp,
148e948693eSPhilip Paeps 	__in		unsigned int buf_size)
149e948693eSPhilip Paeps {
150e948693eSPhilip Paeps 	unsigned int nbuf32;
151e948693eSPhilip Paeps 	efx_oword_t oword;
152e948693eSPhilip Paeps 	int rc;
153e948693eSPhilip Paeps 
154e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
155e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX);
156e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_family, >=, EFX_FAMILY_FALCON);
157e948693eSPhilip Paeps 
158e948693eSPhilip Paeps 	nbuf32 = buf_size / 32;
159e948693eSPhilip Paeps 	if ((nbuf32 == 0) ||
160e948693eSPhilip Paeps 	    (nbuf32 >= (1 << FRF_BZ_RX_USR_BUF_SIZE_WIDTH)) ||
161e948693eSPhilip Paeps 	    ((buf_size % 32) != 0)) {
162e948693eSPhilip Paeps 		rc = EINVAL;
163e948693eSPhilip Paeps 		goto fail1;
164e948693eSPhilip Paeps 	}
165e948693eSPhilip Paeps 
166e948693eSPhilip Paeps 	if (enp->en_rx_qcount > 0) {
167e948693eSPhilip Paeps 		rc = EBUSY;
168e948693eSPhilip Paeps 		goto fail2;
169e948693eSPhilip Paeps 	}
170e948693eSPhilip Paeps 
171e948693eSPhilip Paeps 	/* Set scatter buffer size */
172e948693eSPhilip Paeps 	EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword);
173e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_USR_BUF_SIZE, nbuf32);
174e948693eSPhilip Paeps 	EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword);
175e948693eSPhilip Paeps 
176e948693eSPhilip Paeps 	/* Enable scatter for packets not matching a filter */
177e948693eSPhilip Paeps 	EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
178e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_BZ_SCATTER_ENBL_NO_MATCH_Q, 1);
179e948693eSPhilip Paeps 	EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
180e948693eSPhilip Paeps 
181e948693eSPhilip Paeps 	return (0);
182e948693eSPhilip Paeps 
183e948693eSPhilip Paeps fail2:
184e948693eSPhilip Paeps 	EFSYS_PROBE(fail2);
185e948693eSPhilip Paeps fail1:
186e948693eSPhilip Paeps 	EFSYS_PROBE1(fail1, int, rc);
187e948693eSPhilip Paeps 
188e948693eSPhilip Paeps 	return (rc);
189e948693eSPhilip Paeps }
190e948693eSPhilip Paeps #endif	/* EFSYS_OPT_RX_SCATTER */
191e948693eSPhilip Paeps 
192e948693eSPhilip Paeps 
193e948693eSPhilip Paeps #define	EFX_RX_LFSR_HASH(_enp, _insert)					\
194e948693eSPhilip Paeps 	do {                                    			\
195e948693eSPhilip Paeps 		efx_oword_t oword;					\
196e948693eSPhilip Paeps 									\
197e948693eSPhilip Paeps 		EFX_BAR_READO((_enp), FR_AZ_RX_CFG_REG, &oword);	\
198e948693eSPhilip Paeps 		EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_HASH_ALG, 0);	\
199e948693eSPhilip Paeps 		EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_IP_HASH, 0);	\
200e948693eSPhilip Paeps 		EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_TCP_SUP, 0);	\
201e948693eSPhilip Paeps 		EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_HASH_INSRT_HDR,	\
202e948693eSPhilip Paeps 		    (_insert) ? 1 : 0);					\
203e948693eSPhilip Paeps 		EFX_BAR_WRITEO((_enp), FR_AZ_RX_CFG_REG, &oword);	\
204e948693eSPhilip Paeps 									\
205e948693eSPhilip Paeps 		if ((_enp)->en_family == EFX_FAMILY_SIENA) {		\
206e948693eSPhilip Paeps 			EFX_BAR_READO((_enp), FR_CZ_RX_RSS_IPV6_REG3,	\
207e948693eSPhilip Paeps 			    &oword);					\
208e948693eSPhilip Paeps 			EFX_SET_OWORD_FIELD(oword,			\
209e948693eSPhilip Paeps 			    FRF_CZ_RX_RSS_IPV6_THASH_ENABLE, 0);	\
210e948693eSPhilip Paeps 			EFX_BAR_WRITEO((_enp), FR_CZ_RX_RSS_IPV6_REG3,	\
211e948693eSPhilip Paeps 			    &oword);					\
212e948693eSPhilip Paeps 		}							\
213e948693eSPhilip Paeps 									\
214e948693eSPhilip Paeps 		_NOTE(CONSTANTCONDITION)				\
215e948693eSPhilip Paeps 	} while (B_FALSE)
216e948693eSPhilip Paeps 
217e948693eSPhilip Paeps #define	EFX_RX_TOEPLITZ_IPV4_HASH(_enp, _insert, _ip, _tcp)		\
218e948693eSPhilip Paeps 	do {                                    			\
219e948693eSPhilip Paeps 		efx_oword_t oword;					\
220e948693eSPhilip Paeps 									\
221e948693eSPhilip Paeps 		EFX_BAR_READO((_enp), FR_AZ_RX_CFG_REG,	&oword);	\
222e948693eSPhilip Paeps 		EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_HASH_ALG, 1);	\
223e948693eSPhilip Paeps 		EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_IP_HASH,		\
224e948693eSPhilip Paeps 		    (_ip) ? 1 : 0);					\
225e948693eSPhilip Paeps 		EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_TCP_SUP,		\
226e948693eSPhilip Paeps 		    (_tcp) ? 0 : 1);					\
227e948693eSPhilip Paeps 		EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_HASH_INSRT_HDR,	\
228e948693eSPhilip Paeps 		    (_insert) ? 1 : 0);					\
229e948693eSPhilip Paeps 		EFX_BAR_WRITEO((_enp), FR_AZ_RX_CFG_REG, &oword);	\
230e948693eSPhilip Paeps 									\
231e948693eSPhilip Paeps 		_NOTE(CONSTANTCONDITION)				\
232e948693eSPhilip Paeps 	} while (B_FALSE)
233e948693eSPhilip Paeps 
234e948693eSPhilip Paeps #define	EFX_RX_TOEPLITZ_IPV6_HASH(_enp, _ip, _tcp, _rc)			\
235e948693eSPhilip Paeps 	do {                                    			\
236e948693eSPhilip Paeps 		efx_oword_t oword;					\
237e948693eSPhilip Paeps 									\
238e948693eSPhilip Paeps 		if ((_enp)->en_family == EFX_FAMILY_FALCON) {		\
239e948693eSPhilip Paeps 			(_rc) = ((_ip) || (_tcp)) ? ENOTSUP : 0;	\
240e948693eSPhilip Paeps 			break;						\
241e948693eSPhilip Paeps 		}							\
242e948693eSPhilip Paeps 									\
243e948693eSPhilip Paeps 		EFX_BAR_READO((_enp), FR_CZ_RX_RSS_IPV6_REG3, &oword);	\
244e948693eSPhilip Paeps 		EFX_SET_OWORD_FIELD(oword,				\
245e948693eSPhilip Paeps 		    FRF_CZ_RX_RSS_IPV6_THASH_ENABLE, 1);		\
246e948693eSPhilip Paeps 		EFX_SET_OWORD_FIELD(oword,				\
247e948693eSPhilip Paeps 		    FRF_CZ_RX_RSS_IPV6_IP_THASH_ENABLE, (_ip) ? 1 : 0);	\
248e948693eSPhilip Paeps 		EFX_SET_OWORD_FIELD(oword,				\
249e948693eSPhilip Paeps 		    FRF_CZ_RX_RSS_IPV6_TCP_SUPPRESS, (_tcp) ? 0 : 1);	\
250e948693eSPhilip Paeps 		EFX_BAR_WRITEO((_enp), FR_CZ_RX_RSS_IPV6_REG3, &oword);	\
251e948693eSPhilip Paeps 									\
252e948693eSPhilip Paeps 		(_rc) = 0;						\
253e948693eSPhilip Paeps 									\
254e948693eSPhilip Paeps 		_NOTE(CONSTANTCONDITION)				\
255e948693eSPhilip Paeps 	} while (B_FALSE)
256e948693eSPhilip Paeps 
257e948693eSPhilip Paeps 
258e948693eSPhilip Paeps #if EFSYS_OPT_RX_SCALE
259e948693eSPhilip Paeps 	__checkReturn	int
260e948693eSPhilip Paeps efx_rx_scale_mode_set(
261e948693eSPhilip Paeps 	__in		efx_nic_t *enp,
262e948693eSPhilip Paeps 	__in		efx_rx_hash_alg_t alg,
263e948693eSPhilip Paeps 	__in		efx_rx_hash_type_t type,
264e948693eSPhilip Paeps 	__in		boolean_t insert)
265e948693eSPhilip Paeps {
266e948693eSPhilip Paeps 	int rc;
267e948693eSPhilip Paeps 
268e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
269e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX);
270e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_family, >=, EFX_FAMILY_FALCON);
271e948693eSPhilip Paeps 
272e948693eSPhilip Paeps 	switch (alg) {
273e948693eSPhilip Paeps 	case EFX_RX_HASHALG_LFSR:
274e948693eSPhilip Paeps 		EFX_RX_LFSR_HASH(enp, insert);
275e948693eSPhilip Paeps 		break;
276e948693eSPhilip Paeps 
277e948693eSPhilip Paeps 	case EFX_RX_HASHALG_TOEPLITZ:
278e948693eSPhilip Paeps 		EFX_RX_TOEPLITZ_IPV4_HASH(enp, insert,
279e948693eSPhilip Paeps 		    type & (1 << EFX_RX_HASH_IPV4),
280e948693eSPhilip Paeps 		    type & (1 << EFX_RX_HASH_TCPIPV4));
281e948693eSPhilip Paeps 
282e948693eSPhilip Paeps 		EFX_RX_TOEPLITZ_IPV6_HASH(enp,
283e948693eSPhilip Paeps 		    type & (1 << EFX_RX_HASH_IPV6),
284e948693eSPhilip Paeps 		    type & (1 << EFX_RX_HASH_TCPIPV6),
285e948693eSPhilip Paeps 		    rc);
286e948693eSPhilip Paeps 		if (rc != 0)
287e948693eSPhilip Paeps 			goto fail1;
288e948693eSPhilip Paeps 
289e948693eSPhilip Paeps 		break;
290e948693eSPhilip Paeps 
291e948693eSPhilip Paeps 	default:
292e948693eSPhilip Paeps 		rc = EINVAL;
293e948693eSPhilip Paeps 		goto fail2;
294e948693eSPhilip Paeps 	}
295e948693eSPhilip Paeps 
296e948693eSPhilip Paeps 	return (0);
297e948693eSPhilip Paeps 
298e948693eSPhilip Paeps fail2:
299e948693eSPhilip Paeps 	EFSYS_PROBE(fail2);
300e948693eSPhilip Paeps fail1:
301e948693eSPhilip Paeps 	EFSYS_PROBE1(fail1, int, rc);
302e948693eSPhilip Paeps 
303e948693eSPhilip Paeps 	EFX_RX_LFSR_HASH(enp, B_FALSE);
304e948693eSPhilip Paeps 
305e948693eSPhilip Paeps 	return (rc);
306e948693eSPhilip Paeps }
307e948693eSPhilip Paeps #endif
308e948693eSPhilip Paeps 
309e948693eSPhilip Paeps #if EFSYS_OPT_RX_SCALE
310e948693eSPhilip Paeps 	__checkReturn	int
311e948693eSPhilip Paeps efx_rx_scale_toeplitz_ipv4_key_set(
312e948693eSPhilip Paeps 	__in		efx_nic_t *enp,
313e948693eSPhilip Paeps 	__in_ecount(n)	uint8_t *key,
314e948693eSPhilip Paeps 	__in		size_t n)
315e948693eSPhilip Paeps {
316e948693eSPhilip Paeps 	efx_oword_t oword;
317e948693eSPhilip Paeps 	unsigned int byte;
318e948693eSPhilip Paeps 	unsigned int offset;
319e948693eSPhilip Paeps 	int rc;
320e948693eSPhilip Paeps 
321e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
322e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX);
323e948693eSPhilip Paeps 
324e948693eSPhilip Paeps 	byte = 0;
325e948693eSPhilip Paeps 
326e948693eSPhilip Paeps 	/* Write toeplitz hash key */
327e948693eSPhilip Paeps 	EFX_ZERO_OWORD(oword);
328e948693eSPhilip Paeps 	for (offset = (FRF_BZ_RX_RSS_TKEY_LBN + FRF_BZ_RX_RSS_TKEY_WIDTH) / 8;
329e948693eSPhilip Paeps 	    offset > 0 && byte < n;
330e948693eSPhilip Paeps 	    --offset)
331e948693eSPhilip Paeps 		oword.eo_u8[offset - 1] = key[byte++];
332e948693eSPhilip Paeps 
333e948693eSPhilip Paeps 	EFX_BAR_WRITEO(enp, FR_BZ_RX_RSS_TKEY_REG, &oword);
334e948693eSPhilip Paeps 
335e948693eSPhilip Paeps 	byte = 0;
336e948693eSPhilip Paeps 
337e948693eSPhilip Paeps 	/* Verify toeplitz hash key */
338e948693eSPhilip Paeps 	EFX_BAR_READO(enp, FR_BZ_RX_RSS_TKEY_REG, &oword);
339e948693eSPhilip Paeps 	for (offset = (FRF_BZ_RX_RSS_TKEY_LBN + FRF_BZ_RX_RSS_TKEY_WIDTH) / 8;
340e948693eSPhilip Paeps 	    offset > 0 && byte < n;
341e948693eSPhilip Paeps 	    --offset) {
342e948693eSPhilip Paeps 		if (oword.eo_u8[offset - 1] != key[byte++]) {
343e948693eSPhilip Paeps 			rc = EFAULT;
344e948693eSPhilip Paeps 			goto fail1;
345e948693eSPhilip Paeps 		}
346e948693eSPhilip Paeps 	}
347e948693eSPhilip Paeps 
348e948693eSPhilip Paeps 	return (0);
349e948693eSPhilip Paeps 
350e948693eSPhilip Paeps fail1:
351e948693eSPhilip Paeps 	EFSYS_PROBE1(fail1, int, rc);
352e948693eSPhilip Paeps 
353e948693eSPhilip Paeps 	return (rc);
354e948693eSPhilip Paeps }
355e948693eSPhilip Paeps #endif
356e948693eSPhilip Paeps 
357e948693eSPhilip Paeps #if EFSYS_OPT_RX_SCALE
358e948693eSPhilip Paeps 	__checkReturn	int
359e948693eSPhilip Paeps efx_rx_scale_toeplitz_ipv6_key_set(
360e948693eSPhilip Paeps 	__in		efx_nic_t *enp,
361e948693eSPhilip Paeps 	__in_ecount(n)	uint8_t *key,
362e948693eSPhilip Paeps 	__in		size_t n)
363e948693eSPhilip Paeps {
364e948693eSPhilip Paeps 	efx_oword_t oword;
365e948693eSPhilip Paeps 	unsigned int byte;
366e948693eSPhilip Paeps 	int offset;
367e948693eSPhilip Paeps 	int rc;
368e948693eSPhilip Paeps 
369e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
370e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX);
371e948693eSPhilip Paeps 
372e948693eSPhilip Paeps 	byte = 0;
373e948693eSPhilip Paeps 
374e948693eSPhilip Paeps 	/* Write toeplitz hash key 3 */
375e948693eSPhilip Paeps 	EFX_BAR_READO(enp, FR_CZ_RX_RSS_IPV6_REG3, &oword);
376e948693eSPhilip Paeps 	for (offset = (FRF_CZ_RX_RSS_IPV6_TKEY_HI_LBN +
377e948693eSPhilip Paeps 	    FRF_CZ_RX_RSS_IPV6_TKEY_HI_WIDTH) / 8;
378e948693eSPhilip Paeps 	    offset > 0 && byte < n;
379e948693eSPhilip Paeps 	    --offset)
380e948693eSPhilip Paeps 		oword.eo_u8[offset - 1] = key[byte++];
381e948693eSPhilip Paeps 
382e948693eSPhilip Paeps 	EFX_BAR_WRITEO(enp, FR_CZ_RX_RSS_IPV6_REG3, &oword);
383e948693eSPhilip Paeps 
384e948693eSPhilip Paeps 	/* Write toeplitz hash key 2 */
385e948693eSPhilip Paeps 	EFX_ZERO_OWORD(oword);
386e948693eSPhilip Paeps 	for (offset = (FRF_CZ_RX_RSS_IPV6_TKEY_MID_LBN +
387e948693eSPhilip Paeps 	    FRF_CZ_RX_RSS_IPV6_TKEY_MID_WIDTH) / 8;
388e948693eSPhilip Paeps 	    offset > 0 && byte < n;
389e948693eSPhilip Paeps 	    --offset)
390e948693eSPhilip Paeps 		oword.eo_u8[offset - 1] = key[byte++];
391e948693eSPhilip Paeps 
392e948693eSPhilip Paeps 	EFX_BAR_WRITEO(enp, FR_CZ_RX_RSS_IPV6_REG2, &oword);
393e948693eSPhilip Paeps 
394e948693eSPhilip Paeps 	/* Write toeplitz hash key 1 */
395e948693eSPhilip Paeps 	EFX_ZERO_OWORD(oword);
396e948693eSPhilip Paeps 	for (offset = (FRF_CZ_RX_RSS_IPV6_TKEY_LO_LBN +
397e948693eSPhilip Paeps 	    FRF_CZ_RX_RSS_IPV6_TKEY_LO_WIDTH) / 8;
398e948693eSPhilip Paeps 	    offset > 0 && byte < n;
399e948693eSPhilip Paeps 	    --offset)
400e948693eSPhilip Paeps 		oword.eo_u8[offset - 1] = key[byte++];
401e948693eSPhilip Paeps 
402e948693eSPhilip Paeps 	EFX_BAR_WRITEO(enp, FR_CZ_RX_RSS_IPV6_REG1, &oword);
403e948693eSPhilip Paeps 
404e948693eSPhilip Paeps 	byte = 0;
405e948693eSPhilip Paeps 
406e948693eSPhilip Paeps 	/* Verify toeplitz hash key 3 */
407e948693eSPhilip Paeps 	EFX_BAR_READO(enp, FR_CZ_RX_RSS_IPV6_REG3, &oword);
408e948693eSPhilip Paeps 	for (offset = (FRF_CZ_RX_RSS_IPV6_TKEY_HI_LBN +
409e948693eSPhilip Paeps 	    FRF_CZ_RX_RSS_IPV6_TKEY_HI_WIDTH) / 8;
410e948693eSPhilip Paeps 	    offset > 0 && byte < n;
411e948693eSPhilip Paeps 	    --offset) {
412e948693eSPhilip Paeps 		if (oword.eo_u8[offset - 1] != key[byte++]) {
413e948693eSPhilip Paeps 			rc = EFAULT;
414e948693eSPhilip Paeps 			goto fail1;
415e948693eSPhilip Paeps 		}
416e948693eSPhilip Paeps 	}
417e948693eSPhilip Paeps 
418e948693eSPhilip Paeps 	/* Verify toeplitz hash key 2 */
419e948693eSPhilip Paeps 	EFX_BAR_READO(enp, FR_CZ_RX_RSS_IPV6_REG2, &oword);
420e948693eSPhilip Paeps 	for (offset = (FRF_CZ_RX_RSS_IPV6_TKEY_MID_LBN +
421e948693eSPhilip Paeps 	    FRF_CZ_RX_RSS_IPV6_TKEY_MID_WIDTH) / 8;
422e948693eSPhilip Paeps 	    offset > 0 && byte < n;
423e948693eSPhilip Paeps 	    --offset) {
424e948693eSPhilip Paeps 		if (oword.eo_u8[offset - 1] != key[byte++]) {
425e948693eSPhilip Paeps 			rc = EFAULT;
426e948693eSPhilip Paeps 			goto fail2;
427e948693eSPhilip Paeps 		}
428e948693eSPhilip Paeps 	}
429e948693eSPhilip Paeps 
430e948693eSPhilip Paeps 	/* Verify toeplitz hash key 1 */
431e948693eSPhilip Paeps 	EFX_BAR_READO(enp, FR_CZ_RX_RSS_IPV6_REG1, &oword);
432e948693eSPhilip Paeps 	for (offset = (FRF_CZ_RX_RSS_IPV6_TKEY_LO_LBN +
433e948693eSPhilip Paeps 	    FRF_CZ_RX_RSS_IPV6_TKEY_LO_WIDTH) / 8;
434e948693eSPhilip Paeps 	    offset > 0 && byte < n;
435e948693eSPhilip Paeps 	    --offset) {
436e948693eSPhilip Paeps 		if (oword.eo_u8[offset - 1] != key[byte++]) {
437e948693eSPhilip Paeps 			rc = EFAULT;
438e948693eSPhilip Paeps 			goto fail3;
439e948693eSPhilip Paeps 		}
440e948693eSPhilip Paeps 	}
441e948693eSPhilip Paeps 
442e948693eSPhilip Paeps 	return (0);
443e948693eSPhilip Paeps 
444e948693eSPhilip Paeps fail3:
445e948693eSPhilip Paeps 	EFSYS_PROBE(fail3);
446e948693eSPhilip Paeps fail2:
447e948693eSPhilip Paeps 	EFSYS_PROBE(fail2);
448e948693eSPhilip Paeps fail1:
449e948693eSPhilip Paeps 	EFSYS_PROBE1(fail1, int, rc);
450e948693eSPhilip Paeps 
451e948693eSPhilip Paeps 	return (rc);
452e948693eSPhilip Paeps }
453e948693eSPhilip Paeps #endif
454e948693eSPhilip Paeps 
455e948693eSPhilip Paeps #if EFSYS_OPT_RX_SCALE
456e948693eSPhilip Paeps 	__checkReturn	int
457e948693eSPhilip Paeps efx_rx_scale_tbl_set(
458e948693eSPhilip Paeps 	__in		efx_nic_t *enp,
459e948693eSPhilip Paeps 	__in_ecount(n)	unsigned int *table,
460e948693eSPhilip Paeps 	__in		size_t n)
461e948693eSPhilip Paeps {
462e948693eSPhilip Paeps 	efx_oword_t oword;
463e948693eSPhilip Paeps 	int index;
464e948693eSPhilip Paeps 	int rc;
465e948693eSPhilip Paeps 
466e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
467e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX);
468e948693eSPhilip Paeps 
469e948693eSPhilip Paeps 	EFX_STATIC_ASSERT(EFX_RSS_TBL_SIZE == FR_BZ_RX_INDIRECTION_TBL_ROWS);
470e948693eSPhilip Paeps 	EFX_STATIC_ASSERT(EFX_MAXRSS == (1 << FRF_BZ_IT_QUEUE_WIDTH));
471e948693eSPhilip Paeps 
472e948693eSPhilip Paeps 	if (n > FR_BZ_RX_INDIRECTION_TBL_ROWS) {
473e948693eSPhilip Paeps 		rc = EINVAL;
474e948693eSPhilip Paeps 		goto fail1;
475e948693eSPhilip Paeps 	}
476e948693eSPhilip Paeps 
477e948693eSPhilip Paeps 	for (index = 0; index < FR_BZ_RX_INDIRECTION_TBL_ROWS; index++) {
478e948693eSPhilip Paeps 		uint32_t byte;
479e948693eSPhilip Paeps 
480e948693eSPhilip Paeps 		/* Calculate the entry to place in the table */
481e948693eSPhilip Paeps 		byte = (uint32_t)table[index % n];
482e948693eSPhilip Paeps 
483e948693eSPhilip Paeps 		EFSYS_PROBE2(table, int, index, uint32_t, byte);
484e948693eSPhilip Paeps 
485e948693eSPhilip Paeps 		EFX_POPULATE_OWORD_1(oword, FRF_BZ_IT_QUEUE, byte);
486e948693eSPhilip Paeps 
487e948693eSPhilip Paeps 		/* Write the table */
488e948693eSPhilip Paeps 		EFX_BAR_TBL_WRITEO(enp, FR_BZ_RX_INDIRECTION_TBL,
489e948693eSPhilip Paeps 				    index, &oword);
490e948693eSPhilip Paeps 	}
491e948693eSPhilip Paeps 
492e948693eSPhilip Paeps 	for (index = FR_BZ_RX_INDIRECTION_TBL_ROWS - 1; index >= 0; --index) {
493e948693eSPhilip Paeps 		uint32_t byte;
494e948693eSPhilip Paeps 
495e948693eSPhilip Paeps 		/* Determine if we're starting a new batch */
496e948693eSPhilip Paeps 		byte = (uint32_t)table[index % n];
497e948693eSPhilip Paeps 
498e948693eSPhilip Paeps 		/* Read the table */
499e948693eSPhilip Paeps 		EFX_BAR_TBL_READO(enp, FR_BZ_RX_INDIRECTION_TBL,
500e948693eSPhilip Paeps 				    index, &oword);
501e948693eSPhilip Paeps 
502e948693eSPhilip Paeps 		/* Verify the entry */
503e948693eSPhilip Paeps 		if (EFX_OWORD_FIELD(oword, FRF_BZ_IT_QUEUE) != byte) {
504e948693eSPhilip Paeps 			rc = EFAULT;
505e948693eSPhilip Paeps 			goto fail2;
506e948693eSPhilip Paeps 		}
507e948693eSPhilip Paeps 	}
508e948693eSPhilip Paeps 
509e948693eSPhilip Paeps 	return (0);
510e948693eSPhilip Paeps 
511e948693eSPhilip Paeps fail2:
512e948693eSPhilip Paeps 	EFSYS_PROBE(fail2);
513e948693eSPhilip Paeps fail1:
514e948693eSPhilip Paeps 	EFSYS_PROBE1(fail1, int, rc);
515e948693eSPhilip Paeps 
516e948693eSPhilip Paeps 	return (rc);
517e948693eSPhilip Paeps }
518e948693eSPhilip Paeps #endif
519e948693eSPhilip Paeps 
520e948693eSPhilip Paeps #if EFSYS_OPT_FILTER
521e948693eSPhilip Paeps extern	__checkReturn	int
522e948693eSPhilip Paeps efx_rx_filter_insert(
523e948693eSPhilip Paeps 	__in		efx_rxq_t *erp,
524e948693eSPhilip Paeps 	__inout		efx_filter_spec_t *spec)
525e948693eSPhilip Paeps {
526e948693eSPhilip Paeps 	EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
527e948693eSPhilip Paeps 	EFSYS_ASSERT3P(spec, !=, NULL);
528e948693eSPhilip Paeps 
529e948693eSPhilip Paeps 	spec->efs_dmaq_id = (uint16_t)erp->er_index;
530*0ff23789SAndrew Rybchenko 	return (efx_filter_insert_filter(erp->er_enp, spec, B_FALSE));
531e948693eSPhilip Paeps }
532e948693eSPhilip Paeps #endif
533e948693eSPhilip Paeps 
534e948693eSPhilip Paeps #if EFSYS_OPT_FILTER
535e948693eSPhilip Paeps extern	__checkReturn	int
536e948693eSPhilip Paeps efx_rx_filter_remove(
537e948693eSPhilip Paeps 	__in		efx_rxq_t *erp,
538e948693eSPhilip Paeps 	__inout		efx_filter_spec_t *spec)
539e948693eSPhilip Paeps {
540e948693eSPhilip Paeps 	EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
541e948693eSPhilip Paeps 	EFSYS_ASSERT3P(spec, !=, NULL);
542e948693eSPhilip Paeps 
543e948693eSPhilip Paeps 	spec->efs_dmaq_id = (uint16_t)erp->er_index;
544*0ff23789SAndrew Rybchenko 	return (efx_filter_remove_filter(erp->er_enp, spec));
545e948693eSPhilip Paeps }
546e948693eSPhilip Paeps #endif
547e948693eSPhilip Paeps 
548e948693eSPhilip Paeps extern			void
549e948693eSPhilip Paeps efx_rx_qpost(
550e948693eSPhilip Paeps 	__in		efx_rxq_t *erp,
551e948693eSPhilip Paeps 	__in_ecount(n)	efsys_dma_addr_t *addrp,
552e948693eSPhilip Paeps 	__in		size_t size,
553e948693eSPhilip Paeps 	__in		unsigned int n,
554e948693eSPhilip Paeps 	__in		unsigned int completed,
555e948693eSPhilip Paeps 	__in		unsigned int added)
556e948693eSPhilip Paeps {
557e948693eSPhilip Paeps 	efx_qword_t qword;
558e948693eSPhilip Paeps 	unsigned int i;
559e948693eSPhilip Paeps 	unsigned int offset;
560e948693eSPhilip Paeps 	unsigned int id;
561e948693eSPhilip Paeps 
562e948693eSPhilip Paeps 	EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
563e948693eSPhilip Paeps 
564e948693eSPhilip Paeps 	/* The client driver must not overfill the queue */
565e948693eSPhilip Paeps 	EFSYS_ASSERT3U(added - completed + n, <=,
566e948693eSPhilip Paeps 	    EFX_RXQ_LIMIT(erp->er_mask + 1));
567e948693eSPhilip Paeps 
568e948693eSPhilip Paeps 	id = added & (erp->er_mask);
569e948693eSPhilip Paeps 	for (i = 0; i < n; i++) {
570e948693eSPhilip Paeps 		EFSYS_PROBE4(rx_post, unsigned int, erp->er_index,
571e948693eSPhilip Paeps 		    unsigned int, id, efsys_dma_addr_t, addrp[i],
572e948693eSPhilip Paeps 		    size_t, size);
573e948693eSPhilip Paeps 
574e948693eSPhilip Paeps 		EFX_POPULATE_QWORD_3(qword,
575e948693eSPhilip Paeps 		    FSF_AZ_RX_KER_BUF_SIZE, (uint32_t)(size),
576e948693eSPhilip Paeps 		    FSF_AZ_RX_KER_BUF_ADDR_DW0,
577e948693eSPhilip Paeps 		    (uint32_t)(addrp[i] & 0xffffffff),
578e948693eSPhilip Paeps 		    FSF_AZ_RX_KER_BUF_ADDR_DW1,
579e948693eSPhilip Paeps 		    (uint32_t)(addrp[i] >> 32));
580e948693eSPhilip Paeps 
581e948693eSPhilip Paeps 		offset = id * sizeof (efx_qword_t);
582e948693eSPhilip Paeps 		EFSYS_MEM_WRITEQ(erp->er_esmp, offset, &qword);
583e948693eSPhilip Paeps 
584e948693eSPhilip Paeps 		id = (id + 1) & (erp->er_mask);
585e948693eSPhilip Paeps 	}
586e948693eSPhilip Paeps }
587e948693eSPhilip Paeps 
588e948693eSPhilip Paeps 		void
589e948693eSPhilip Paeps efx_rx_qpush(
590e948693eSPhilip Paeps 	__in	efx_rxq_t *erp,
591e948693eSPhilip Paeps 	__in	unsigned int added)
592e948693eSPhilip Paeps {
593e948693eSPhilip Paeps 	efx_nic_t *enp = erp->er_enp;
594e948693eSPhilip Paeps 	uint32_t wptr;
595e948693eSPhilip Paeps 	efx_oword_t oword;
596e948693eSPhilip Paeps 	efx_dword_t dword;
597e948693eSPhilip Paeps 
598e948693eSPhilip Paeps 	EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
599e948693eSPhilip Paeps 
600e948693eSPhilip Paeps 	/* Guarantee ordering of memory (descriptors) and PIO (doorbell) */
601e948693eSPhilip Paeps 	EFSYS_PIO_WRITE_BARRIER();
602e948693eSPhilip Paeps 
603e948693eSPhilip Paeps 	/* Push the populated descriptors out */
604e948693eSPhilip Paeps 	wptr = added & erp->er_mask;
605e948693eSPhilip Paeps 
606e948693eSPhilip Paeps 	EFX_POPULATE_OWORD_1(oword, FRF_AZ_RX_DESC_WPTR, wptr);
607e948693eSPhilip Paeps 
608e948693eSPhilip Paeps 	/* Only write the third DWORD */
609e948693eSPhilip Paeps 	EFX_POPULATE_DWORD_1(dword,
610e948693eSPhilip Paeps 	    EFX_DWORD_0, EFX_OWORD_FIELD(oword, EFX_DWORD_3));
611e948693eSPhilip Paeps 	EFX_BAR_TBL_WRITED3(enp, FR_BZ_RX_DESC_UPD_REGP0,
612e948693eSPhilip Paeps 			    erp->er_index, &dword, B_FALSE);
613e948693eSPhilip Paeps }
614e948693eSPhilip Paeps 
615e948693eSPhilip Paeps 		void
616e948693eSPhilip Paeps efx_rx_qflush(
617e948693eSPhilip Paeps 	__in	efx_rxq_t *erp)
618e948693eSPhilip Paeps {
619e948693eSPhilip Paeps 	efx_nic_t *enp = erp->er_enp;
620e948693eSPhilip Paeps 	efx_oword_t oword;
621e948693eSPhilip Paeps 	uint32_t label;
622e948693eSPhilip Paeps 
623e948693eSPhilip Paeps 	EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
624e948693eSPhilip Paeps 
625e948693eSPhilip Paeps 	label = erp->er_index;
626e948693eSPhilip Paeps 
627e948693eSPhilip Paeps 	/* Flush the queue */
628e948693eSPhilip Paeps 	EFX_POPULATE_OWORD_2(oword, FRF_AZ_RX_FLUSH_DESCQ_CMD, 1,
629e948693eSPhilip Paeps 	    FRF_AZ_RX_FLUSH_DESCQ, label);
630e948693eSPhilip Paeps 	EFX_BAR_WRITEO(enp, FR_AZ_RX_FLUSH_DESCQ_REG, &oword);
631e948693eSPhilip Paeps }
632e948693eSPhilip Paeps 
633e948693eSPhilip Paeps 		void
634e948693eSPhilip Paeps efx_rx_qenable(
635e948693eSPhilip Paeps 	__in	efx_rxq_t *erp)
636e948693eSPhilip Paeps {
637e948693eSPhilip Paeps 	efx_nic_t *enp = erp->er_enp;
638e948693eSPhilip Paeps 	efx_oword_t oword;
639e948693eSPhilip Paeps 
640e948693eSPhilip Paeps 	EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
641e948693eSPhilip Paeps 
642e948693eSPhilip Paeps 	EFX_BAR_TBL_READO(enp, FR_AZ_RX_DESC_PTR_TBL,
643e948693eSPhilip Paeps 			    erp->er_index, &oword);
644e948693eSPhilip Paeps 
645e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_AZ_RX_DC_HW_RPTR, 0);
646e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_AZ_RX_DESCQ_HW_RPTR, 0);
647e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_AZ_RX_DESCQ_EN, 1);
648e948693eSPhilip Paeps 
649e948693eSPhilip Paeps 	EFX_BAR_TBL_WRITEO(enp, FR_AZ_RX_DESC_PTR_TBL,
650e948693eSPhilip Paeps 			    erp->er_index, &oword);
651e948693eSPhilip Paeps }
652e948693eSPhilip Paeps 
653e948693eSPhilip Paeps 	__checkReturn	int
654e948693eSPhilip Paeps efx_rx_qcreate(
655e948693eSPhilip Paeps 	__in		efx_nic_t *enp,
656e948693eSPhilip Paeps 	__in		unsigned int index,
657e948693eSPhilip Paeps 	__in		unsigned int label,
658e948693eSPhilip Paeps 	__in		efx_rxq_type_t type,
659e948693eSPhilip Paeps 	__in		efsys_mem_t *esmp,
660e948693eSPhilip Paeps 	__in		size_t n,
661e948693eSPhilip Paeps 	__in		uint32_t id,
662e948693eSPhilip Paeps 	__in		efx_evq_t *eep,
663e948693eSPhilip Paeps 	__deref_out	efx_rxq_t **erpp)
664e948693eSPhilip Paeps {
665e948693eSPhilip Paeps 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
666e948693eSPhilip Paeps 	efx_rxq_t *erp;
667e948693eSPhilip Paeps 	efx_oword_t oword;
668e948693eSPhilip Paeps 	uint32_t size;
669e948693eSPhilip Paeps 	boolean_t split;
670e948693eSPhilip Paeps 	boolean_t jumbo;
671e948693eSPhilip Paeps 	int rc;
672e948693eSPhilip Paeps 
673e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
674e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX);
675e948693eSPhilip Paeps 
676*0ff23789SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_EV_RX_NLABELS ==
677*0ff23789SAndrew Rybchenko 	    (1 << FRF_AZ_RX_DESCQ_LABEL_WIDTH));
678e948693eSPhilip Paeps 	EFSYS_ASSERT3U(label, <, EFX_EV_RX_NLABELS);
679e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_rx_qcount + 1, <, encp->enc_rxq_limit);
680e948693eSPhilip Paeps 
681e948693eSPhilip Paeps 	if (!ISP2(n) || !(n & EFX_RXQ_NDESCS_MASK)) {
682e948693eSPhilip Paeps 		rc = EINVAL;
683e948693eSPhilip Paeps 		goto fail1;
684e948693eSPhilip Paeps 	}
685e948693eSPhilip Paeps 	if (index >= encp->enc_rxq_limit) {
686e948693eSPhilip Paeps 		rc = EINVAL;
687e948693eSPhilip Paeps 		goto fail2;
688e948693eSPhilip Paeps 	}
689e948693eSPhilip Paeps 	for (size = 0; (1 << size) <= (EFX_RXQ_MAXNDESCS / EFX_RXQ_MINNDESCS);
690e948693eSPhilip Paeps 	    size++)
691e948693eSPhilip Paeps 		if ((1 << size) == (int)(n / EFX_RXQ_MINNDESCS))
692e948693eSPhilip Paeps 			break;
693e948693eSPhilip Paeps 	if (id + (1 << size) >= encp->enc_buftbl_limit) {
694e948693eSPhilip Paeps 		rc = EINVAL;
695e948693eSPhilip Paeps 		goto fail3;
696e948693eSPhilip Paeps 	}
697e948693eSPhilip Paeps 
698e948693eSPhilip Paeps 	switch (type) {
699e948693eSPhilip Paeps 	case EFX_RXQ_TYPE_DEFAULT:
700e948693eSPhilip Paeps 		split = B_FALSE;
701e948693eSPhilip Paeps 		jumbo = B_FALSE;
702e948693eSPhilip Paeps 		break;
703e948693eSPhilip Paeps 
704e948693eSPhilip Paeps #if EFSYS_OPT_RX_HDR_SPLIT
705e948693eSPhilip Paeps 	case EFX_RXQ_TYPE_SPLIT_HEADER:
706e948693eSPhilip Paeps 		if ((enp->en_family < EFX_FAMILY_SIENA) || ((index & 1) != 0)) {
707e948693eSPhilip Paeps 			rc = EINVAL;
708e948693eSPhilip Paeps 			goto fail4;
709e948693eSPhilip Paeps 		}
710e948693eSPhilip Paeps 		split = B_TRUE;
711e948693eSPhilip Paeps 		jumbo = B_TRUE;
712e948693eSPhilip Paeps 		break;
713e948693eSPhilip Paeps 
714e948693eSPhilip Paeps 	case EFX_RXQ_TYPE_SPLIT_PAYLOAD:
715e948693eSPhilip Paeps 		if ((enp->en_family < EFX_FAMILY_SIENA) || ((index & 1) == 0)) {
716e948693eSPhilip Paeps 			rc = EINVAL;
717e948693eSPhilip Paeps 			goto fail4;
718e948693eSPhilip Paeps 		}
719e948693eSPhilip Paeps 		split = B_FALSE;
720e948693eSPhilip Paeps 		jumbo = B_TRUE;
721e948693eSPhilip Paeps 		break;
722e948693eSPhilip Paeps #endif	/* EFSYS_OPT_RX_HDR_SPLIT */
723e948693eSPhilip Paeps 
724e948693eSPhilip Paeps #if EFSYS_OPT_RX_SCATTER
725e948693eSPhilip Paeps 	case EFX_RXQ_TYPE_SCATTER:
726e948693eSPhilip Paeps 		if (enp->en_family < EFX_FAMILY_SIENA) {
727e948693eSPhilip Paeps 			rc = EINVAL;
728e948693eSPhilip Paeps 			goto fail4;
729e948693eSPhilip Paeps 		}
730e948693eSPhilip Paeps 		split = B_FALSE;
731e948693eSPhilip Paeps 		jumbo = B_TRUE;
732e948693eSPhilip Paeps 		break;
733e948693eSPhilip Paeps #endif	/* EFSYS_OPT_RX_SCATTER */
734e948693eSPhilip Paeps 
735e948693eSPhilip Paeps 	default:
736e948693eSPhilip Paeps 		rc = EINVAL;
737e948693eSPhilip Paeps 		goto fail4;
738e948693eSPhilip Paeps 	}
739e948693eSPhilip Paeps 
740e948693eSPhilip Paeps 	/* Allocate an RXQ object */
741e948693eSPhilip Paeps 	EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (efx_rxq_t), erp);
742e948693eSPhilip Paeps 
743e948693eSPhilip Paeps 	if (erp == NULL) {
744e948693eSPhilip Paeps 		rc = ENOMEM;
745e948693eSPhilip Paeps 		goto fail5;
746e948693eSPhilip Paeps 	}
747e948693eSPhilip Paeps 
748e948693eSPhilip Paeps 	erp->er_magic = EFX_RXQ_MAGIC;
749e948693eSPhilip Paeps 	erp->er_enp = enp;
750e948693eSPhilip Paeps 	erp->er_index = index;
751e948693eSPhilip Paeps 	erp->er_mask = n - 1;
752e948693eSPhilip Paeps 	erp->er_esmp = esmp;
753e948693eSPhilip Paeps 
754e948693eSPhilip Paeps 	/* Set up the new descriptor queue */
755e948693eSPhilip Paeps 	EFX_POPULATE_OWORD_10(oword,
756e948693eSPhilip Paeps 	    FRF_CZ_RX_HDR_SPLIT, split,
757e948693eSPhilip Paeps 	    FRF_AZ_RX_ISCSI_DDIG_EN, 0,
758e948693eSPhilip Paeps 	    FRF_AZ_RX_ISCSI_HDIG_EN, 0,
759e948693eSPhilip Paeps 	    FRF_AZ_RX_DESCQ_BUF_BASE_ID, id,
760e948693eSPhilip Paeps 	    FRF_AZ_RX_DESCQ_EVQ_ID, eep->ee_index,
761e948693eSPhilip Paeps 	    FRF_AZ_RX_DESCQ_OWNER_ID, 0,
762e948693eSPhilip Paeps 	    FRF_AZ_RX_DESCQ_LABEL, label,
763e948693eSPhilip Paeps 	    FRF_AZ_RX_DESCQ_SIZE, size,
764e948693eSPhilip Paeps 	    FRF_AZ_RX_DESCQ_TYPE, 0,
765e948693eSPhilip Paeps 	    FRF_AZ_RX_DESCQ_JUMBO, jumbo);
766e948693eSPhilip Paeps 
767e948693eSPhilip Paeps 	EFX_BAR_TBL_WRITEO(enp, FR_AZ_RX_DESC_PTR_TBL,
768e948693eSPhilip Paeps 			    erp->er_index, &oword);
769e948693eSPhilip Paeps 
770e948693eSPhilip Paeps 	enp->en_rx_qcount++;
771e948693eSPhilip Paeps 	*erpp = erp;
772e948693eSPhilip Paeps 	return (0);
773e948693eSPhilip Paeps 
774e948693eSPhilip Paeps fail5:
775e948693eSPhilip Paeps 	EFSYS_PROBE(fail5);
776e948693eSPhilip Paeps fail4:
777e948693eSPhilip Paeps 	EFSYS_PROBE(fail4);
778e948693eSPhilip Paeps fail3:
779e948693eSPhilip Paeps 	EFSYS_PROBE(fail3);
780e948693eSPhilip Paeps fail2:
781e948693eSPhilip Paeps 	EFSYS_PROBE(fail2);
782e948693eSPhilip Paeps fail1:
783e948693eSPhilip Paeps 	EFSYS_PROBE1(fail1, int, rc);
784e948693eSPhilip Paeps 
785e948693eSPhilip Paeps 	return (rc);
786e948693eSPhilip Paeps }
787e948693eSPhilip Paeps 
788e948693eSPhilip Paeps 		void
789e948693eSPhilip Paeps efx_rx_qdestroy(
790e948693eSPhilip Paeps 	__in	efx_rxq_t *erp)
791e948693eSPhilip Paeps {
792e948693eSPhilip Paeps 	efx_nic_t *enp = erp->er_enp;
793e948693eSPhilip Paeps 	efx_oword_t oword;
794e948693eSPhilip Paeps 
795e948693eSPhilip Paeps 	EFSYS_ASSERT3U(erp->er_magic, ==, EFX_RXQ_MAGIC);
796e948693eSPhilip Paeps 
797e948693eSPhilip Paeps 	EFSYS_ASSERT(enp->en_rx_qcount != 0);
798e948693eSPhilip Paeps 	--enp->en_rx_qcount;
799e948693eSPhilip Paeps 
800e948693eSPhilip Paeps 	/* Purge descriptor queue */
801e948693eSPhilip Paeps 	EFX_ZERO_OWORD(oword);
802e948693eSPhilip Paeps 
803e948693eSPhilip Paeps 	EFX_BAR_TBL_WRITEO(enp, FR_AZ_RX_DESC_PTR_TBL,
804e948693eSPhilip Paeps 			    erp->er_index, &oword);
805e948693eSPhilip Paeps 
806e948693eSPhilip Paeps 	/* Free the RXQ object */
807e948693eSPhilip Paeps 	EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_rxq_t), erp);
808e948693eSPhilip Paeps }
809e948693eSPhilip Paeps 
810e948693eSPhilip Paeps 		void
811e948693eSPhilip Paeps efx_rx_fini(
812e948693eSPhilip Paeps 	__in	efx_nic_t *enp)
813e948693eSPhilip Paeps {
814e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
815e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
816e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_RX);
817e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_rx_qcount, ==, 0);
818e948693eSPhilip Paeps 
819e948693eSPhilip Paeps 	enp->en_mod_flags &= ~EFX_MOD_RX;
820e948693eSPhilip Paeps }
821