xref: /freebsd-src/sys/dev/sfxge/common/ef10_rx.c (revision 685dc743dc3b5645e34836464128e1c0558b404b)
1204d1d17SAndrew Rybchenko /*-
2929c7febSAndrew Rybchenko  * Copyright (c) 2012-2016 Solarflare Communications Inc.
3204d1d17SAndrew Rybchenko  * All rights reserved.
4204d1d17SAndrew Rybchenko  *
5204d1d17SAndrew Rybchenko  * Redistribution and use in source and binary forms, with or without
6204d1d17SAndrew Rybchenko  * modification, are permitted provided that the following conditions are met:
7204d1d17SAndrew Rybchenko  *
8204d1d17SAndrew Rybchenko  * 1. Redistributions of source code must retain the above copyright notice,
9204d1d17SAndrew Rybchenko  *    this list of conditions and the following disclaimer.
10204d1d17SAndrew Rybchenko  * 2. Redistributions in binary form must reproduce the above copyright notice,
11204d1d17SAndrew Rybchenko  *    this list of conditions and the following disclaimer in the documentation
12204d1d17SAndrew Rybchenko  *    and/or other materials provided with the distribution.
13204d1d17SAndrew Rybchenko  *
14204d1d17SAndrew Rybchenko  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15204d1d17SAndrew Rybchenko  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16204d1d17SAndrew Rybchenko  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17204d1d17SAndrew Rybchenko  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18204d1d17SAndrew Rybchenko  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19204d1d17SAndrew Rybchenko  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20204d1d17SAndrew Rybchenko  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21204d1d17SAndrew Rybchenko  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22204d1d17SAndrew Rybchenko  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23204d1d17SAndrew Rybchenko  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24204d1d17SAndrew Rybchenko  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25204d1d17SAndrew Rybchenko  *
26204d1d17SAndrew Rybchenko  * The views and conclusions contained in the software and documentation are
27204d1d17SAndrew Rybchenko  * those of the authors and should not be interpreted as representing official
28204d1d17SAndrew Rybchenko  * policies, either expressed or implied, of the FreeBSD Project.
29204d1d17SAndrew Rybchenko  */
30204d1d17SAndrew Rybchenko 
31204d1d17SAndrew Rybchenko #include <sys/cdefs.h>
32204d1d17SAndrew Rybchenko #include "efx.h"
33204d1d17SAndrew Rybchenko #include "efx_impl.h"
34204d1d17SAndrew Rybchenko 
3534352ef8SAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
36204d1d17SAndrew Rybchenko 
37204d1d17SAndrew Rybchenko static	__checkReturn	efx_rc_t
efx_mcdi_init_rxq(__in efx_nic_t * enp,__in uint32_t ndescs,__in uint32_t target_evq,__in uint32_t label,__in uint32_t instance,__in efsys_mem_t * esmp,__in boolean_t disable_scatter,__in boolean_t want_inner_classes,__in uint32_t ps_bufsize,__in uint32_t es_bufs_per_desc,__in uint32_t es_max_dma_len,__in uint32_t es_buf_stride,__in uint32_t hol_block_timeout)38204d1d17SAndrew Rybchenko efx_mcdi_init_rxq(
39204d1d17SAndrew Rybchenko 	__in		efx_nic_t *enp,
4059ee8172SAndrew Rybchenko 	__in		uint32_t ndescs,
41204d1d17SAndrew Rybchenko 	__in		uint32_t target_evq,
42204d1d17SAndrew Rybchenko 	__in		uint32_t label,
43204d1d17SAndrew Rybchenko 	__in		uint32_t instance,
44204d1d17SAndrew Rybchenko 	__in		efsys_mem_t *esmp,
458e0c4827SAndrew Rybchenko 	__in		boolean_t disable_scatter,
464ed151b8SAndrew Rybchenko 	__in		boolean_t want_inner_classes,
4704381b5eSAndrew Rybchenko 	__in		uint32_t ps_bufsize,
4804381b5eSAndrew Rybchenko 	__in		uint32_t es_bufs_per_desc,
4904381b5eSAndrew Rybchenko 	__in		uint32_t es_max_dma_len,
5004381b5eSAndrew Rybchenko 	__in		uint32_t es_buf_stride,
5104381b5eSAndrew Rybchenko 	__in		uint32_t hol_block_timeout)
52204d1d17SAndrew Rybchenko {
53fbca55a5SAndrew Rybchenko 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
54204d1d17SAndrew Rybchenko 	efx_mcdi_req_t req;
55315bbbaaSAndrew Rybchenko 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_INIT_RXQ_V3_IN_LEN,
56315bbbaaSAndrew Rybchenko 		MC_CMD_INIT_RXQ_V3_OUT_LEN);
5759ee8172SAndrew Rybchenko 	int npages = EFX_RXQ_NBUFS(ndescs);
58204d1d17SAndrew Rybchenko 	int i;
59204d1d17SAndrew Rybchenko 	efx_qword_t *dma_addr;
60204d1d17SAndrew Rybchenko 	uint64_t addr;
61204d1d17SAndrew Rybchenko 	efx_rc_t rc;
628e0c4827SAndrew Rybchenko 	uint32_t dma_mode;
63fbca55a5SAndrew Rybchenko 	boolean_t want_outer_classes;
64204d1d17SAndrew Rybchenko 
6559ee8172SAndrew Rybchenko 	EFSYS_ASSERT3U(ndescs, <=, EFX_RXQ_MAXNDESCS);
66204d1d17SAndrew Rybchenko 
674aaefb95SAndrew Rybchenko 	if ((esmp == NULL) || (EFSYS_MEM_SIZE(esmp) < EFX_RXQ_SIZE(ndescs))) {
684aaefb95SAndrew Rybchenko 		rc = EINVAL;
694aaefb95SAndrew Rybchenko 		goto fail1;
704aaefb95SAndrew Rybchenko 	}
714aaefb95SAndrew Rybchenko 
728e0c4827SAndrew Rybchenko 	if (ps_bufsize > 0)
738e0c4827SAndrew Rybchenko 		dma_mode = MC_CMD_INIT_RXQ_EXT_IN_PACKED_STREAM;
7404381b5eSAndrew Rybchenko 	else if (es_bufs_per_desc > 0)
7504381b5eSAndrew Rybchenko 		dma_mode = MC_CMD_INIT_RXQ_V3_IN_EQUAL_STRIDE_SUPER_BUFFER;
768e0c4827SAndrew Rybchenko 	else
778e0c4827SAndrew Rybchenko 		dma_mode = MC_CMD_INIT_RXQ_EXT_IN_SINGLE_PACKET;
788e0c4827SAndrew Rybchenko 
794ed151b8SAndrew Rybchenko 	if (encp->enc_tunnel_encapsulations_supported != 0 &&
804ed151b8SAndrew Rybchenko 	    !want_inner_classes) {
81fbca55a5SAndrew Rybchenko 		/*
82fbca55a5SAndrew Rybchenko 		 * WANT_OUTER_CLASSES can only be specified on hardware which
83fbca55a5SAndrew Rybchenko 		 * supports tunnel encapsulation offloads, even though it is
84fbca55a5SAndrew Rybchenko 		 * effectively the behaviour the hardware gives.
85fbca55a5SAndrew Rybchenko 		 *
86fbca55a5SAndrew Rybchenko 		 * Also, on hardware which does support such offloads, older
87fbca55a5SAndrew Rybchenko 		 * firmware rejects the flag if the offloads are not supported
88fbca55a5SAndrew Rybchenko 		 * by the current firmware variant, which means this may fail if
89fbca55a5SAndrew Rybchenko 		 * the capabilities are not updated when the firmware variant
90fbca55a5SAndrew Rybchenko 		 * changes. This is not an issue on newer firmware, as it was
91fbca55a5SAndrew Rybchenko 		 * changed in bug 69842 (v6.4.2.1007) to permit this flag to be
92fbca55a5SAndrew Rybchenko 		 * specified on all firmware variants.
93fbca55a5SAndrew Rybchenko 		 */
94fbca55a5SAndrew Rybchenko 		want_outer_classes = B_TRUE;
95fbca55a5SAndrew Rybchenko 	} else {
96fbca55a5SAndrew Rybchenko 		want_outer_classes = B_FALSE;
97fbca55a5SAndrew Rybchenko 	}
98fbca55a5SAndrew Rybchenko 
99204d1d17SAndrew Rybchenko 	req.emr_cmd = MC_CMD_INIT_RXQ;
100204d1d17SAndrew Rybchenko 	req.emr_in_buf = payload;
10104381b5eSAndrew Rybchenko 	req.emr_in_length = MC_CMD_INIT_RXQ_V3_IN_LEN;
102204d1d17SAndrew Rybchenko 	req.emr_out_buf = payload;
10304381b5eSAndrew Rybchenko 	req.emr_out_length = MC_CMD_INIT_RXQ_V3_OUT_LEN;
104204d1d17SAndrew Rybchenko 
10559ee8172SAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, INIT_RXQ_EXT_IN_SIZE, ndescs);
1068e0c4827SAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, INIT_RXQ_EXT_IN_TARGET_EVQ, target_evq);
1078e0c4827SAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, INIT_RXQ_EXT_IN_LABEL, label);
1088e0c4827SAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, INIT_RXQ_EXT_IN_INSTANCE, instance);
109fbca55a5SAndrew Rybchenko 	MCDI_IN_POPULATE_DWORD_9(req, INIT_RXQ_EXT_IN_FLAGS,
1108e0c4827SAndrew Rybchenko 	    INIT_RXQ_EXT_IN_FLAG_BUFF_MODE, 0,
1118e0c4827SAndrew Rybchenko 	    INIT_RXQ_EXT_IN_FLAG_HDR_SPLIT, 0,
1128e0c4827SAndrew Rybchenko 	    INIT_RXQ_EXT_IN_FLAG_TIMESTAMP, 0,
1138e0c4827SAndrew Rybchenko 	    INIT_RXQ_EXT_IN_CRC_MODE, 0,
1148e0c4827SAndrew Rybchenko 	    INIT_RXQ_EXT_IN_FLAG_PREFIX, 1,
1158e0c4827SAndrew Rybchenko 	    INIT_RXQ_EXT_IN_FLAG_DISABLE_SCATTER, disable_scatter,
1168e0c4827SAndrew Rybchenko 	    INIT_RXQ_EXT_IN_DMA_MODE,
1178e0c4827SAndrew Rybchenko 	    dma_mode,
118fbca55a5SAndrew Rybchenko 	    INIT_RXQ_EXT_IN_PACKED_STREAM_BUFF_SIZE, ps_bufsize,
119fbca55a5SAndrew Rybchenko 	    INIT_RXQ_EXT_IN_FLAG_WANT_OUTER_CLASSES, want_outer_classes);
1208e0c4827SAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, INIT_RXQ_EXT_IN_OWNER_ID, 0);
1218e0c4827SAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, INIT_RXQ_EXT_IN_PORT_ID, EVB_PORT_ID_ASSIGNED);
122204d1d17SAndrew Rybchenko 
12304381b5eSAndrew Rybchenko 	if (es_bufs_per_desc > 0) {
12404381b5eSAndrew Rybchenko 		MCDI_IN_SET_DWORD(req,
12504381b5eSAndrew Rybchenko 		    INIT_RXQ_V3_IN_ES_PACKET_BUFFERS_PER_BUCKET,
12604381b5eSAndrew Rybchenko 		    es_bufs_per_desc);
12704381b5eSAndrew Rybchenko 		MCDI_IN_SET_DWORD(req,
12804381b5eSAndrew Rybchenko 		    INIT_RXQ_V3_IN_ES_MAX_DMA_LEN, es_max_dma_len);
12904381b5eSAndrew Rybchenko 		MCDI_IN_SET_DWORD(req,
13004381b5eSAndrew Rybchenko 		    INIT_RXQ_V3_IN_ES_PACKET_STRIDE, es_buf_stride);
13104381b5eSAndrew Rybchenko 		MCDI_IN_SET_DWORD(req,
13204381b5eSAndrew Rybchenko 		    INIT_RXQ_V3_IN_ES_HEAD_OF_LINE_BLOCK_TIMEOUT,
13304381b5eSAndrew Rybchenko 		    hol_block_timeout);
13404381b5eSAndrew Rybchenko 	}
13504381b5eSAndrew Rybchenko 
136204d1d17SAndrew Rybchenko 	dma_addr = MCDI_IN2(req, efx_qword_t, INIT_RXQ_IN_DMA_ADDR);
137204d1d17SAndrew Rybchenko 	addr = EFSYS_MEM_ADDR(esmp);
138204d1d17SAndrew Rybchenko 
139204d1d17SAndrew Rybchenko 	for (i = 0; i < npages; i++) {
140204d1d17SAndrew Rybchenko 		EFX_POPULATE_QWORD_2(*dma_addr,
141204d1d17SAndrew Rybchenko 		    EFX_DWORD_1, (uint32_t)(addr >> 32),
142204d1d17SAndrew Rybchenko 		    EFX_DWORD_0, (uint32_t)(addr & 0xffffffff));
143204d1d17SAndrew Rybchenko 
144204d1d17SAndrew Rybchenko 		dma_addr++;
145204d1d17SAndrew Rybchenko 		addr += EFX_BUF_SIZE;
146204d1d17SAndrew Rybchenko 	}
147204d1d17SAndrew Rybchenko 
148204d1d17SAndrew Rybchenko 	efx_mcdi_execute(enp, &req);
149204d1d17SAndrew Rybchenko 
150204d1d17SAndrew Rybchenko 	if (req.emr_rc != 0) {
151204d1d17SAndrew Rybchenko 		rc = req.emr_rc;
1524aaefb95SAndrew Rybchenko 		goto fail2;
153204d1d17SAndrew Rybchenko 	}
154204d1d17SAndrew Rybchenko 
155204d1d17SAndrew Rybchenko 	return (0);
156204d1d17SAndrew Rybchenko 
1574aaefb95SAndrew Rybchenko fail2:
1584aaefb95SAndrew Rybchenko 	EFSYS_PROBE(fail2);
159204d1d17SAndrew Rybchenko fail1:
160204d1d17SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
161204d1d17SAndrew Rybchenko 
162204d1d17SAndrew Rybchenko 	return (rc);
163204d1d17SAndrew Rybchenko }
164204d1d17SAndrew Rybchenko 
165204d1d17SAndrew Rybchenko static	__checkReturn	efx_rc_t
efx_mcdi_fini_rxq(__in efx_nic_t * enp,__in uint32_t instance)166204d1d17SAndrew Rybchenko efx_mcdi_fini_rxq(
167204d1d17SAndrew Rybchenko 	__in		efx_nic_t *enp,
168204d1d17SAndrew Rybchenko 	__in		uint32_t instance)
169204d1d17SAndrew Rybchenko {
170204d1d17SAndrew Rybchenko 	efx_mcdi_req_t req;
171315bbbaaSAndrew Rybchenko 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FINI_RXQ_IN_LEN,
172315bbbaaSAndrew Rybchenko 		MC_CMD_FINI_RXQ_OUT_LEN);
173204d1d17SAndrew Rybchenko 	efx_rc_t rc;
174204d1d17SAndrew Rybchenko 
175204d1d17SAndrew Rybchenko 	req.emr_cmd = MC_CMD_FINI_RXQ;
176204d1d17SAndrew Rybchenko 	req.emr_in_buf = payload;
177204d1d17SAndrew Rybchenko 	req.emr_in_length = MC_CMD_FINI_RXQ_IN_LEN;
178204d1d17SAndrew Rybchenko 	req.emr_out_buf = payload;
179204d1d17SAndrew Rybchenko 	req.emr_out_length = MC_CMD_FINI_RXQ_OUT_LEN;
180204d1d17SAndrew Rybchenko 
181204d1d17SAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, FINI_RXQ_IN_INSTANCE, instance);
182204d1d17SAndrew Rybchenko 
183bba8dcbcSAndrew Rybchenko 	efx_mcdi_execute_quiet(enp, &req);
184204d1d17SAndrew Rybchenko 
1857e1059e8SAndrew Rybchenko 	if (req.emr_rc != 0) {
186204d1d17SAndrew Rybchenko 		rc = req.emr_rc;
187204d1d17SAndrew Rybchenko 		goto fail1;
188204d1d17SAndrew Rybchenko 	}
189204d1d17SAndrew Rybchenko 
190204d1d17SAndrew Rybchenko 	return (0);
191204d1d17SAndrew Rybchenko 
192204d1d17SAndrew Rybchenko fail1:
1937e1059e8SAndrew Rybchenko 	/*
1947e1059e8SAndrew Rybchenko 	 * EALREADY is not an error, but indicates that the MC has rebooted and
1957e1059e8SAndrew Rybchenko 	 * that the RXQ has already been destroyed.
1967e1059e8SAndrew Rybchenko 	 */
1977e1059e8SAndrew Rybchenko 	if (rc != EALREADY)
198204d1d17SAndrew Rybchenko 		EFSYS_PROBE1(fail1, efx_rc_t, rc);
199204d1d17SAndrew Rybchenko 
200204d1d17SAndrew Rybchenko 	return (rc);
201204d1d17SAndrew Rybchenko }
202204d1d17SAndrew Rybchenko 
203204d1d17SAndrew Rybchenko #if EFSYS_OPT_RX_SCALE
204204d1d17SAndrew Rybchenko static	__checkReturn	efx_rc_t
efx_mcdi_rss_context_alloc(__in efx_nic_t * enp,__in efx_rx_scale_context_type_t type,__in uint32_t num_queues,__out uint32_t * rss_contextp)205204d1d17SAndrew Rybchenko efx_mcdi_rss_context_alloc(
206204d1d17SAndrew Rybchenko 	__in		efx_nic_t *enp,
20739023729SAndrew Rybchenko 	__in		efx_rx_scale_context_type_t type,
208204d1d17SAndrew Rybchenko 	__in		uint32_t num_queues,
209204d1d17SAndrew Rybchenko 	__out		uint32_t *rss_contextp)
210204d1d17SAndrew Rybchenko {
211204d1d17SAndrew Rybchenko 	efx_mcdi_req_t req;
212315bbbaaSAndrew Rybchenko 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_RSS_CONTEXT_ALLOC_IN_LEN,
213315bbbaaSAndrew Rybchenko 		MC_CMD_RSS_CONTEXT_ALLOC_OUT_LEN);
214204d1d17SAndrew Rybchenko 	uint32_t rss_context;
215204d1d17SAndrew Rybchenko 	uint32_t context_type;
216204d1d17SAndrew Rybchenko 	efx_rc_t rc;
217204d1d17SAndrew Rybchenko 
218204d1d17SAndrew Rybchenko 	if (num_queues > EFX_MAXRSS) {
219204d1d17SAndrew Rybchenko 		rc = EINVAL;
220204d1d17SAndrew Rybchenko 		goto fail1;
221204d1d17SAndrew Rybchenko 	}
222204d1d17SAndrew Rybchenko 
22339023729SAndrew Rybchenko 	switch (type) {
224204d1d17SAndrew Rybchenko 	case EFX_RX_SCALE_EXCLUSIVE:
225204d1d17SAndrew Rybchenko 		context_type = MC_CMD_RSS_CONTEXT_ALLOC_IN_TYPE_EXCLUSIVE;
226204d1d17SAndrew Rybchenko 		break;
227204d1d17SAndrew Rybchenko 	case EFX_RX_SCALE_SHARED:
228204d1d17SAndrew Rybchenko 		context_type = MC_CMD_RSS_CONTEXT_ALLOC_IN_TYPE_SHARED;
229204d1d17SAndrew Rybchenko 		break;
230204d1d17SAndrew Rybchenko 	default:
231204d1d17SAndrew Rybchenko 		rc = EINVAL;
232204d1d17SAndrew Rybchenko 		goto fail2;
233204d1d17SAndrew Rybchenko 	}
234204d1d17SAndrew Rybchenko 
235204d1d17SAndrew Rybchenko 	req.emr_cmd = MC_CMD_RSS_CONTEXT_ALLOC;
236204d1d17SAndrew Rybchenko 	req.emr_in_buf = payload;
237204d1d17SAndrew Rybchenko 	req.emr_in_length = MC_CMD_RSS_CONTEXT_ALLOC_IN_LEN;
238204d1d17SAndrew Rybchenko 	req.emr_out_buf = payload;
239204d1d17SAndrew Rybchenko 	req.emr_out_length = MC_CMD_RSS_CONTEXT_ALLOC_OUT_LEN;
240204d1d17SAndrew Rybchenko 
241204d1d17SAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, RSS_CONTEXT_ALLOC_IN_UPSTREAM_PORT_ID,
242204d1d17SAndrew Rybchenko 	    EVB_PORT_ID_ASSIGNED);
243204d1d17SAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, RSS_CONTEXT_ALLOC_IN_TYPE, context_type);
244ee1d6deeSAndrew Rybchenko 
245ee1d6deeSAndrew Rybchenko 	/*
246ee1d6deeSAndrew Rybchenko 	 * For exclusive contexts, NUM_QUEUES is only used to validate
247ee1d6deeSAndrew Rybchenko 	 * indirection table offsets.
248ee1d6deeSAndrew Rybchenko 	 * For shared contexts, the provided context will spread traffic over
249ee1d6deeSAndrew Rybchenko 	 * NUM_QUEUES many queues.
250ee1d6deeSAndrew Rybchenko 	 */
251204d1d17SAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, RSS_CONTEXT_ALLOC_IN_NUM_QUEUES, num_queues);
252204d1d17SAndrew Rybchenko 
253204d1d17SAndrew Rybchenko 	efx_mcdi_execute(enp, &req);
254204d1d17SAndrew Rybchenko 
255204d1d17SAndrew Rybchenko 	if (req.emr_rc != 0) {
256204d1d17SAndrew Rybchenko 		rc = req.emr_rc;
257204d1d17SAndrew Rybchenko 		goto fail3;
258204d1d17SAndrew Rybchenko 	}
259204d1d17SAndrew Rybchenko 
260204d1d17SAndrew Rybchenko 	if (req.emr_out_length_used < MC_CMD_RSS_CONTEXT_ALLOC_OUT_LEN) {
261204d1d17SAndrew Rybchenko 		rc = EMSGSIZE;
262204d1d17SAndrew Rybchenko 		goto fail4;
263204d1d17SAndrew Rybchenko 	}
264204d1d17SAndrew Rybchenko 
265204d1d17SAndrew Rybchenko 	rss_context = MCDI_OUT_DWORD(req, RSS_CONTEXT_ALLOC_OUT_RSS_CONTEXT_ID);
266204d1d17SAndrew Rybchenko 	if (rss_context == EF10_RSS_CONTEXT_INVALID) {
267204d1d17SAndrew Rybchenko 		rc = ENOENT;
268204d1d17SAndrew Rybchenko 		goto fail5;
269204d1d17SAndrew Rybchenko 	}
270204d1d17SAndrew Rybchenko 
271204d1d17SAndrew Rybchenko 	*rss_contextp = rss_context;
272204d1d17SAndrew Rybchenko 
273204d1d17SAndrew Rybchenko 	return (0);
274204d1d17SAndrew Rybchenko 
275204d1d17SAndrew Rybchenko fail5:
276204d1d17SAndrew Rybchenko 	EFSYS_PROBE(fail5);
277204d1d17SAndrew Rybchenko fail4:
278204d1d17SAndrew Rybchenko 	EFSYS_PROBE(fail4);
279204d1d17SAndrew Rybchenko fail3:
280204d1d17SAndrew Rybchenko 	EFSYS_PROBE(fail3);
281204d1d17SAndrew Rybchenko fail2:
282204d1d17SAndrew Rybchenko 	EFSYS_PROBE(fail2);
283204d1d17SAndrew Rybchenko fail1:
284204d1d17SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
285204d1d17SAndrew Rybchenko 
286204d1d17SAndrew Rybchenko 	return (rc);
287204d1d17SAndrew Rybchenko }
288204d1d17SAndrew Rybchenko #endif /* EFSYS_OPT_RX_SCALE */
289204d1d17SAndrew Rybchenko 
290204d1d17SAndrew Rybchenko #if EFSYS_OPT_RX_SCALE
291204d1d17SAndrew Rybchenko static			efx_rc_t
efx_mcdi_rss_context_free(__in efx_nic_t * enp,__in uint32_t rss_context)292204d1d17SAndrew Rybchenko efx_mcdi_rss_context_free(
293204d1d17SAndrew Rybchenko 	__in		efx_nic_t *enp,
294204d1d17SAndrew Rybchenko 	__in		uint32_t rss_context)
295204d1d17SAndrew Rybchenko {
296204d1d17SAndrew Rybchenko 	efx_mcdi_req_t req;
297315bbbaaSAndrew Rybchenko 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_RSS_CONTEXT_FREE_IN_LEN,
298315bbbaaSAndrew Rybchenko 		MC_CMD_RSS_CONTEXT_FREE_OUT_LEN);
299204d1d17SAndrew Rybchenko 	efx_rc_t rc;
300204d1d17SAndrew Rybchenko 
301204d1d17SAndrew Rybchenko 	if (rss_context == EF10_RSS_CONTEXT_INVALID) {
302204d1d17SAndrew Rybchenko 		rc = EINVAL;
303204d1d17SAndrew Rybchenko 		goto fail1;
304204d1d17SAndrew Rybchenko 	}
305204d1d17SAndrew Rybchenko 
306204d1d17SAndrew Rybchenko 	req.emr_cmd = MC_CMD_RSS_CONTEXT_FREE;
307204d1d17SAndrew Rybchenko 	req.emr_in_buf = payload;
308204d1d17SAndrew Rybchenko 	req.emr_in_length = MC_CMD_RSS_CONTEXT_FREE_IN_LEN;
309204d1d17SAndrew Rybchenko 	req.emr_out_buf = payload;
310204d1d17SAndrew Rybchenko 	req.emr_out_length = MC_CMD_RSS_CONTEXT_FREE_OUT_LEN;
311204d1d17SAndrew Rybchenko 
312204d1d17SAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, RSS_CONTEXT_FREE_IN_RSS_CONTEXT_ID, rss_context);
313204d1d17SAndrew Rybchenko 
314bba8dcbcSAndrew Rybchenko 	efx_mcdi_execute_quiet(enp, &req);
315204d1d17SAndrew Rybchenko 
316204d1d17SAndrew Rybchenko 	if (req.emr_rc != 0) {
317204d1d17SAndrew Rybchenko 		rc = req.emr_rc;
318204d1d17SAndrew Rybchenko 		goto fail2;
319204d1d17SAndrew Rybchenko 	}
320204d1d17SAndrew Rybchenko 
321204d1d17SAndrew Rybchenko 	return (0);
322204d1d17SAndrew Rybchenko 
323204d1d17SAndrew Rybchenko fail2:
324204d1d17SAndrew Rybchenko 	EFSYS_PROBE(fail2);
325204d1d17SAndrew Rybchenko fail1:
326204d1d17SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
327204d1d17SAndrew Rybchenko 
328204d1d17SAndrew Rybchenko 	return (rc);
329204d1d17SAndrew Rybchenko }
330204d1d17SAndrew Rybchenko #endif /* EFSYS_OPT_RX_SCALE */
331204d1d17SAndrew Rybchenko 
332204d1d17SAndrew Rybchenko #if EFSYS_OPT_RX_SCALE
333204d1d17SAndrew Rybchenko static			efx_rc_t
efx_mcdi_rss_context_set_flags(__in efx_nic_t * enp,__in uint32_t rss_context,__in efx_rx_hash_type_t type)334204d1d17SAndrew Rybchenko efx_mcdi_rss_context_set_flags(
335204d1d17SAndrew Rybchenko 	__in		efx_nic_t *enp,
336204d1d17SAndrew Rybchenko 	__in		uint32_t rss_context,
337204d1d17SAndrew Rybchenko 	__in		efx_rx_hash_type_t type)
338204d1d17SAndrew Rybchenko {
339fd962dffSAndrew Rybchenko 	efx_nic_cfg_t *encp = &enp->en_nic_cfg;
340204d1d17SAndrew Rybchenko 	efx_mcdi_req_t req;
341315bbbaaSAndrew Rybchenko 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_LEN,
342315bbbaaSAndrew Rybchenko 		MC_CMD_RSS_CONTEXT_SET_FLAGS_OUT_LEN);
343204d1d17SAndrew Rybchenko 	efx_rc_t rc;
344204d1d17SAndrew Rybchenko 
34535ebf2a9SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV4_TCP_LBN ==
34635ebf2a9SAndrew Rybchenko 		    MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV4_RSS_MODE_LBN);
34735ebf2a9SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV4_TCP_WIDTH ==
34835ebf2a9SAndrew Rybchenko 		    MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV4_RSS_MODE_WIDTH);
34935ebf2a9SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV4_LBN ==
35035ebf2a9SAndrew Rybchenko 		    MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV4_RSS_MODE_LBN);
35135ebf2a9SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV4_WIDTH ==
35235ebf2a9SAndrew Rybchenko 		    MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV4_RSS_MODE_WIDTH);
35335ebf2a9SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV6_TCP_LBN ==
35435ebf2a9SAndrew Rybchenko 		    MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV6_RSS_MODE_LBN);
35535ebf2a9SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV6_TCP_WIDTH ==
35635ebf2a9SAndrew Rybchenko 		    MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV6_RSS_MODE_WIDTH);
35735ebf2a9SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV6_LBN ==
35835ebf2a9SAndrew Rybchenko 		    MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV6_RSS_MODE_LBN);
35935ebf2a9SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV6_WIDTH ==
36035ebf2a9SAndrew Rybchenko 		    MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV6_RSS_MODE_WIDTH);
36135ebf2a9SAndrew Rybchenko 
362204d1d17SAndrew Rybchenko 	if (rss_context == EF10_RSS_CONTEXT_INVALID) {
363204d1d17SAndrew Rybchenko 		rc = EINVAL;
364204d1d17SAndrew Rybchenko 		goto fail1;
365204d1d17SAndrew Rybchenko 	}
366204d1d17SAndrew Rybchenko 
367204d1d17SAndrew Rybchenko 	req.emr_cmd = MC_CMD_RSS_CONTEXT_SET_FLAGS;
368204d1d17SAndrew Rybchenko 	req.emr_in_buf = payload;
369204d1d17SAndrew Rybchenko 	req.emr_in_length = MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_LEN;
370204d1d17SAndrew Rybchenko 	req.emr_out_buf = payload;
371204d1d17SAndrew Rybchenko 	req.emr_out_length = MC_CMD_RSS_CONTEXT_SET_FLAGS_OUT_LEN;
372204d1d17SAndrew Rybchenko 
373204d1d17SAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, RSS_CONTEXT_SET_FLAGS_IN_RSS_CONTEXT_ID,
374204d1d17SAndrew Rybchenko 	    rss_context);
375204d1d17SAndrew Rybchenko 
376fd962dffSAndrew Rybchenko 	/*
377fd962dffSAndrew Rybchenko 	 * If the firmware lacks support for additional modes, RSS_MODE
378fd962dffSAndrew Rybchenko 	 * fields must contain zeros, otherwise the operation will fail.
379fd962dffSAndrew Rybchenko 	 */
380fd962dffSAndrew Rybchenko 	if (encp->enc_rx_scale_additional_modes_supported == B_FALSE)
3816ddb48deSAndrew Rybchenko 		type &= EFX_RX_HASH_LEGACY_MASK;
382fd962dffSAndrew Rybchenko 
383fd962dffSAndrew Rybchenko 	MCDI_IN_POPULATE_DWORD_10(req, RSS_CONTEXT_SET_FLAGS_IN_FLAGS,
384204d1d17SAndrew Rybchenko 	    RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_IPV4_EN,
3856ddb48deSAndrew Rybchenko 	    (type & EFX_RX_HASH_IPV4) ? 1 : 0,
386204d1d17SAndrew Rybchenko 	    RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_TCPV4_EN,
3876ddb48deSAndrew Rybchenko 	    (type & EFX_RX_HASH_TCPIPV4) ? 1 : 0,
388204d1d17SAndrew Rybchenko 	    RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_IPV6_EN,
3896ddb48deSAndrew Rybchenko 	    (type & EFX_RX_HASH_IPV6) ? 1 : 0,
390204d1d17SAndrew Rybchenko 	    RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_TCPV6_EN,
3916ddb48deSAndrew Rybchenko 	    (type & EFX_RX_HASH_TCPIPV6) ? 1 : 0,
392fd962dffSAndrew Rybchenko 	    RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV4_RSS_MODE,
3936ddb48deSAndrew Rybchenko 	    (type >> EFX_RX_CLASS_IPV4_TCP_LBN) &
394d085cfffSAndrew Rybchenko 	    EFX_MASK32(EFX_RX_CLASS_IPV4_TCP),
395fd962dffSAndrew Rybchenko 	    RSS_CONTEXT_SET_FLAGS_IN_UDP_IPV4_RSS_MODE,
3966ddb48deSAndrew Rybchenko 	    (type >> EFX_RX_CLASS_IPV4_UDP_LBN) &
397d085cfffSAndrew Rybchenko 	    EFX_MASK32(EFX_RX_CLASS_IPV4_UDP),
398fd962dffSAndrew Rybchenko 	    RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV4_RSS_MODE,
3996ddb48deSAndrew Rybchenko 	    (type >> EFX_RX_CLASS_IPV4_LBN) & EFX_MASK32(EFX_RX_CLASS_IPV4),
400fd962dffSAndrew Rybchenko 	    RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV6_RSS_MODE,
4016ddb48deSAndrew Rybchenko 	    (type >> EFX_RX_CLASS_IPV6_TCP_LBN) &
402d085cfffSAndrew Rybchenko 	    EFX_MASK32(EFX_RX_CLASS_IPV6_TCP),
403fd962dffSAndrew Rybchenko 	    RSS_CONTEXT_SET_FLAGS_IN_UDP_IPV6_RSS_MODE,
4046ddb48deSAndrew Rybchenko 	    (type >> EFX_RX_CLASS_IPV6_UDP_LBN) &
405d085cfffSAndrew Rybchenko 	    EFX_MASK32(EFX_RX_CLASS_IPV6_UDP),
406fd962dffSAndrew Rybchenko 	    RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV6_RSS_MODE,
4076ddb48deSAndrew Rybchenko 	    (type >> EFX_RX_CLASS_IPV6_LBN) & EFX_MASK32(EFX_RX_CLASS_IPV6));
408204d1d17SAndrew Rybchenko 
409204d1d17SAndrew Rybchenko 	efx_mcdi_execute(enp, &req);
410204d1d17SAndrew Rybchenko 
411204d1d17SAndrew Rybchenko 	if (req.emr_rc != 0) {
412204d1d17SAndrew Rybchenko 		rc = req.emr_rc;
413204d1d17SAndrew Rybchenko 		goto fail2;
414204d1d17SAndrew Rybchenko 	}
415204d1d17SAndrew Rybchenko 
416204d1d17SAndrew Rybchenko 	return (0);
417204d1d17SAndrew Rybchenko 
418204d1d17SAndrew Rybchenko fail2:
419204d1d17SAndrew Rybchenko 	EFSYS_PROBE(fail2);
420204d1d17SAndrew Rybchenko fail1:
421204d1d17SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
422204d1d17SAndrew Rybchenko 
423204d1d17SAndrew Rybchenko 	return (rc);
424204d1d17SAndrew Rybchenko }
425204d1d17SAndrew Rybchenko #endif /* EFSYS_OPT_RX_SCALE */
426204d1d17SAndrew Rybchenko 
427204d1d17SAndrew Rybchenko #if EFSYS_OPT_RX_SCALE
428204d1d17SAndrew Rybchenko static			efx_rc_t
efx_mcdi_rss_context_set_key(__in efx_nic_t * enp,__in uint32_t rss_context,__in_ecount (n)uint8_t * key,__in size_t n)429204d1d17SAndrew Rybchenko efx_mcdi_rss_context_set_key(
430204d1d17SAndrew Rybchenko 	__in		efx_nic_t *enp,
431204d1d17SAndrew Rybchenko 	__in		uint32_t rss_context,
432204d1d17SAndrew Rybchenko 	__in_ecount(n)	uint8_t *key,
433204d1d17SAndrew Rybchenko 	__in		size_t n)
434204d1d17SAndrew Rybchenko {
435204d1d17SAndrew Rybchenko 	efx_mcdi_req_t req;
436315bbbaaSAndrew Rybchenko 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_RSS_CONTEXT_SET_KEY_IN_LEN,
437315bbbaaSAndrew Rybchenko 		MC_CMD_RSS_CONTEXT_SET_KEY_OUT_LEN);
438204d1d17SAndrew Rybchenko 	efx_rc_t rc;
439204d1d17SAndrew Rybchenko 
440204d1d17SAndrew Rybchenko 	if (rss_context == EF10_RSS_CONTEXT_INVALID) {
441204d1d17SAndrew Rybchenko 		rc = EINVAL;
442204d1d17SAndrew Rybchenko 		goto fail1;
443204d1d17SAndrew Rybchenko 	}
444204d1d17SAndrew Rybchenko 
445204d1d17SAndrew Rybchenko 	req.emr_cmd = MC_CMD_RSS_CONTEXT_SET_KEY;
446204d1d17SAndrew Rybchenko 	req.emr_in_buf = payload;
447204d1d17SAndrew Rybchenko 	req.emr_in_length = MC_CMD_RSS_CONTEXT_SET_KEY_IN_LEN;
448204d1d17SAndrew Rybchenko 	req.emr_out_buf = payload;
449204d1d17SAndrew Rybchenko 	req.emr_out_length = MC_CMD_RSS_CONTEXT_SET_KEY_OUT_LEN;
450204d1d17SAndrew Rybchenko 
451204d1d17SAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, RSS_CONTEXT_SET_KEY_IN_RSS_CONTEXT_ID,
452204d1d17SAndrew Rybchenko 	    rss_context);
453204d1d17SAndrew Rybchenko 
454204d1d17SAndrew Rybchenko 	EFSYS_ASSERT3U(n, ==, MC_CMD_RSS_CONTEXT_SET_KEY_IN_TOEPLITZ_KEY_LEN);
455204d1d17SAndrew Rybchenko 	if (n != MC_CMD_RSS_CONTEXT_SET_KEY_IN_TOEPLITZ_KEY_LEN) {
456204d1d17SAndrew Rybchenko 		rc = EINVAL;
457204d1d17SAndrew Rybchenko 		goto fail2;
458204d1d17SAndrew Rybchenko 	}
459204d1d17SAndrew Rybchenko 
460204d1d17SAndrew Rybchenko 	memcpy(MCDI_IN2(req, uint8_t, RSS_CONTEXT_SET_KEY_IN_TOEPLITZ_KEY),
461204d1d17SAndrew Rybchenko 	    key, n);
462204d1d17SAndrew Rybchenko 
463204d1d17SAndrew Rybchenko 	efx_mcdi_execute(enp, &req);
464204d1d17SAndrew Rybchenko 
465204d1d17SAndrew Rybchenko 	if (req.emr_rc != 0) {
466204d1d17SAndrew Rybchenko 		rc = req.emr_rc;
467204d1d17SAndrew Rybchenko 		goto fail3;
468204d1d17SAndrew Rybchenko 	}
469204d1d17SAndrew Rybchenko 
470204d1d17SAndrew Rybchenko 	return (0);
471204d1d17SAndrew Rybchenko 
472204d1d17SAndrew Rybchenko fail3:
473204d1d17SAndrew Rybchenko 	EFSYS_PROBE(fail3);
474204d1d17SAndrew Rybchenko fail2:
475204d1d17SAndrew Rybchenko 	EFSYS_PROBE(fail2);
476204d1d17SAndrew Rybchenko fail1:
477204d1d17SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
478204d1d17SAndrew Rybchenko 
479204d1d17SAndrew Rybchenko 	return (rc);
480204d1d17SAndrew Rybchenko }
481204d1d17SAndrew Rybchenko #endif /* EFSYS_OPT_RX_SCALE */
482204d1d17SAndrew Rybchenko 
483204d1d17SAndrew Rybchenko #if EFSYS_OPT_RX_SCALE
484204d1d17SAndrew Rybchenko static			efx_rc_t
efx_mcdi_rss_context_set_table(__in efx_nic_t * enp,__in uint32_t rss_context,__in_ecount (n)unsigned int * table,__in size_t n)485204d1d17SAndrew Rybchenko efx_mcdi_rss_context_set_table(
486204d1d17SAndrew Rybchenko 	__in		efx_nic_t *enp,
487204d1d17SAndrew Rybchenko 	__in		uint32_t rss_context,
488204d1d17SAndrew Rybchenko 	__in_ecount(n)	unsigned int *table,
489204d1d17SAndrew Rybchenko 	__in		size_t n)
490204d1d17SAndrew Rybchenko {
491204d1d17SAndrew Rybchenko 	efx_mcdi_req_t req;
492315bbbaaSAndrew Rybchenko 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_RSS_CONTEXT_SET_TABLE_IN_LEN,
493315bbbaaSAndrew Rybchenko 		MC_CMD_RSS_CONTEXT_SET_TABLE_OUT_LEN);
494204d1d17SAndrew Rybchenko 	uint8_t *req_table;
495204d1d17SAndrew Rybchenko 	int i, rc;
496204d1d17SAndrew Rybchenko 
497204d1d17SAndrew Rybchenko 	if (rss_context == EF10_RSS_CONTEXT_INVALID) {
498204d1d17SAndrew Rybchenko 		rc = EINVAL;
499204d1d17SAndrew Rybchenko 		goto fail1;
500204d1d17SAndrew Rybchenko 	}
501204d1d17SAndrew Rybchenko 
502204d1d17SAndrew Rybchenko 	req.emr_cmd = MC_CMD_RSS_CONTEXT_SET_TABLE;
503204d1d17SAndrew Rybchenko 	req.emr_in_buf = payload;
504204d1d17SAndrew Rybchenko 	req.emr_in_length = MC_CMD_RSS_CONTEXT_SET_TABLE_IN_LEN;
505204d1d17SAndrew Rybchenko 	req.emr_out_buf = payload;
506204d1d17SAndrew Rybchenko 	req.emr_out_length = MC_CMD_RSS_CONTEXT_SET_TABLE_OUT_LEN;
507204d1d17SAndrew Rybchenko 
508204d1d17SAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, RSS_CONTEXT_SET_TABLE_IN_RSS_CONTEXT_ID,
509204d1d17SAndrew Rybchenko 	    rss_context);
510204d1d17SAndrew Rybchenko 
511204d1d17SAndrew Rybchenko 	req_table =
512204d1d17SAndrew Rybchenko 	    MCDI_IN2(req, uint8_t, RSS_CONTEXT_SET_TABLE_IN_INDIRECTION_TABLE);
513204d1d17SAndrew Rybchenko 
514204d1d17SAndrew Rybchenko 	for (i = 0;
515204d1d17SAndrew Rybchenko 	    i < MC_CMD_RSS_CONTEXT_SET_TABLE_IN_INDIRECTION_TABLE_LEN;
516204d1d17SAndrew Rybchenko 	    i++) {
517204d1d17SAndrew Rybchenko 		req_table[i] = (n > 0) ? (uint8_t)table[i % n] : 0;
518204d1d17SAndrew Rybchenko 	}
519204d1d17SAndrew Rybchenko 
520204d1d17SAndrew Rybchenko 	efx_mcdi_execute(enp, &req);
521204d1d17SAndrew Rybchenko 
522204d1d17SAndrew Rybchenko 	if (req.emr_rc != 0) {
523204d1d17SAndrew Rybchenko 		rc = req.emr_rc;
524204d1d17SAndrew Rybchenko 		goto fail2;
525204d1d17SAndrew Rybchenko 	}
526204d1d17SAndrew Rybchenko 
527204d1d17SAndrew Rybchenko 	return (0);
528204d1d17SAndrew Rybchenko 
529204d1d17SAndrew Rybchenko fail2:
530204d1d17SAndrew Rybchenko 	EFSYS_PROBE(fail2);
531204d1d17SAndrew Rybchenko fail1:
532204d1d17SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
533204d1d17SAndrew Rybchenko 
534204d1d17SAndrew Rybchenko 	return (rc);
535204d1d17SAndrew Rybchenko }
536204d1d17SAndrew Rybchenko #endif /* EFSYS_OPT_RX_SCALE */
537204d1d17SAndrew Rybchenko 
538204d1d17SAndrew Rybchenko 	__checkReturn	efx_rc_t
ef10_rx_init(__in efx_nic_t * enp)539204d1d17SAndrew Rybchenko ef10_rx_init(
540204d1d17SAndrew Rybchenko 	__in		efx_nic_t *enp)
541204d1d17SAndrew Rybchenko {
542204d1d17SAndrew Rybchenko #if EFSYS_OPT_RX_SCALE
543204d1d17SAndrew Rybchenko 
544204d1d17SAndrew Rybchenko 	if (efx_mcdi_rss_context_alloc(enp, EFX_RX_SCALE_EXCLUSIVE, EFX_MAXRSS,
545204d1d17SAndrew Rybchenko 		&enp->en_rss_context) == 0) {
546204d1d17SAndrew Rybchenko 		/*
547204d1d17SAndrew Rybchenko 		 * Allocated an exclusive RSS context, which allows both the
548204d1d17SAndrew Rybchenko 		 * indirection table and key to be modified.
549204d1d17SAndrew Rybchenko 		 */
55039023729SAndrew Rybchenko 		enp->en_rss_context_type = EFX_RX_SCALE_EXCLUSIVE;
551204d1d17SAndrew Rybchenko 		enp->en_hash_support = EFX_RX_HASH_AVAILABLE;
552204d1d17SAndrew Rybchenko 	} else {
553204d1d17SAndrew Rybchenko 		/*
554204d1d17SAndrew Rybchenko 		 * Failed to allocate an exclusive RSS context. Continue
555204d1d17SAndrew Rybchenko 		 * operation without support for RSS. The pseudo-header in
556204d1d17SAndrew Rybchenko 		 * received packets will not contain a Toeplitz hash value.
557204d1d17SAndrew Rybchenko 		 */
55839023729SAndrew Rybchenko 		enp->en_rss_context_type = EFX_RX_SCALE_UNAVAILABLE;
559204d1d17SAndrew Rybchenko 		enp->en_hash_support = EFX_RX_HASH_UNAVAILABLE;
560204d1d17SAndrew Rybchenko 	}
561204d1d17SAndrew Rybchenko 
562204d1d17SAndrew Rybchenko #endif /* EFSYS_OPT_RX_SCALE */
563204d1d17SAndrew Rybchenko 
564204d1d17SAndrew Rybchenko 	return (0);
565204d1d17SAndrew Rybchenko }
566204d1d17SAndrew Rybchenko 
567204d1d17SAndrew Rybchenko #if EFSYS_OPT_RX_SCATTER
568204d1d17SAndrew Rybchenko 	__checkReturn	efx_rc_t
ef10_rx_scatter_enable(__in efx_nic_t * enp,__in unsigned int buf_size)569204d1d17SAndrew Rybchenko ef10_rx_scatter_enable(
570204d1d17SAndrew Rybchenko 	__in		efx_nic_t *enp,
571204d1d17SAndrew Rybchenko 	__in		unsigned int buf_size)
572204d1d17SAndrew Rybchenko {
573204d1d17SAndrew Rybchenko 	_NOTE(ARGUNUSED(enp, buf_size))
574204d1d17SAndrew Rybchenko 	return (0);
575204d1d17SAndrew Rybchenko }
576204d1d17SAndrew Rybchenko #endif	/* EFSYS_OPT_RX_SCATTER */
577204d1d17SAndrew Rybchenko 
578204d1d17SAndrew Rybchenko #if EFSYS_OPT_RX_SCALE
579204d1d17SAndrew Rybchenko 	__checkReturn	efx_rc_t
ef10_rx_scale_context_alloc(__in efx_nic_t * enp,__in efx_rx_scale_context_type_t type,__in uint32_t num_queues,__out uint32_t * rss_contextp)580e6d55a0bSAndrew Rybchenko ef10_rx_scale_context_alloc(
581e6d55a0bSAndrew Rybchenko 	__in		efx_nic_t *enp,
582e6d55a0bSAndrew Rybchenko 	__in		efx_rx_scale_context_type_t type,
583e6d55a0bSAndrew Rybchenko 	__in		uint32_t num_queues,
584e6d55a0bSAndrew Rybchenko 	__out		uint32_t *rss_contextp)
585e6d55a0bSAndrew Rybchenko {
586e6d55a0bSAndrew Rybchenko 	efx_rc_t rc;
587e6d55a0bSAndrew Rybchenko 
588e6d55a0bSAndrew Rybchenko 	rc = efx_mcdi_rss_context_alloc(enp, type, num_queues, rss_contextp);
589e6d55a0bSAndrew Rybchenko 	if (rc != 0)
590e6d55a0bSAndrew Rybchenko 		goto fail1;
591e6d55a0bSAndrew Rybchenko 
592e6d55a0bSAndrew Rybchenko 	return (0);
593e6d55a0bSAndrew Rybchenko 
594e6d55a0bSAndrew Rybchenko fail1:
595e6d55a0bSAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
596e6d55a0bSAndrew Rybchenko 	return (rc);
597e6d55a0bSAndrew Rybchenko }
598e6d55a0bSAndrew Rybchenko #endif /* EFSYS_OPT_RX_SCALE */
599e6d55a0bSAndrew Rybchenko 
600e6d55a0bSAndrew Rybchenko #if EFSYS_OPT_RX_SCALE
601e6d55a0bSAndrew Rybchenko 	__checkReturn	efx_rc_t
ef10_rx_scale_context_free(__in efx_nic_t * enp,__in uint32_t rss_context)602e6d55a0bSAndrew Rybchenko ef10_rx_scale_context_free(
603e6d55a0bSAndrew Rybchenko 	__in		efx_nic_t *enp,
604e6d55a0bSAndrew Rybchenko 	__in		uint32_t rss_context)
605e6d55a0bSAndrew Rybchenko {
606e6d55a0bSAndrew Rybchenko 	efx_rc_t rc;
607e6d55a0bSAndrew Rybchenko 
608e6d55a0bSAndrew Rybchenko 	rc = efx_mcdi_rss_context_free(enp, rss_context);
609e6d55a0bSAndrew Rybchenko 	if (rc != 0)
610e6d55a0bSAndrew Rybchenko 		goto fail1;
611e6d55a0bSAndrew Rybchenko 
612e6d55a0bSAndrew Rybchenko 	return (0);
613e6d55a0bSAndrew Rybchenko 
614e6d55a0bSAndrew Rybchenko fail1:
615e6d55a0bSAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
616e6d55a0bSAndrew Rybchenko 	return (rc);
617e6d55a0bSAndrew Rybchenko }
618e6d55a0bSAndrew Rybchenko #endif /* EFSYS_OPT_RX_SCALE */
619e6d55a0bSAndrew Rybchenko 
620e6d55a0bSAndrew Rybchenko #if EFSYS_OPT_RX_SCALE
621e6d55a0bSAndrew Rybchenko 	__checkReturn	efx_rc_t
ef10_rx_scale_mode_set(__in efx_nic_t * enp,__in uint32_t rss_context,__in efx_rx_hash_alg_t alg,__in efx_rx_hash_type_t type,__in boolean_t insert)622204d1d17SAndrew Rybchenko ef10_rx_scale_mode_set(
623204d1d17SAndrew Rybchenko 	__in		efx_nic_t *enp,
62482af879cSAndrew Rybchenko 	__in		uint32_t rss_context,
625204d1d17SAndrew Rybchenko 	__in		efx_rx_hash_alg_t alg,
626204d1d17SAndrew Rybchenko 	__in		efx_rx_hash_type_t type,
627204d1d17SAndrew Rybchenko 	__in		boolean_t insert)
628204d1d17SAndrew Rybchenko {
629fcfb73b8SAndrew Rybchenko 	efx_nic_cfg_t *encp = &enp->en_nic_cfg;
630204d1d17SAndrew Rybchenko 	efx_rc_t rc;
631204d1d17SAndrew Rybchenko 
632204d1d17SAndrew Rybchenko 	EFSYS_ASSERT3U(insert, ==, B_TRUE);
633204d1d17SAndrew Rybchenko 
634fcfb73b8SAndrew Rybchenko 	if ((encp->enc_rx_scale_hash_alg_mask & (1U << alg)) == 0 ||
635fcfb73b8SAndrew Rybchenko 	    insert == B_FALSE) {
636204d1d17SAndrew Rybchenko 		rc = EINVAL;
637204d1d17SAndrew Rybchenko 		goto fail1;
638204d1d17SAndrew Rybchenko 	}
639204d1d17SAndrew Rybchenko 
64082af879cSAndrew Rybchenko 	if (rss_context == EFX_RSS_CONTEXT_DEFAULT) {
64139023729SAndrew Rybchenko 		if (enp->en_rss_context_type == EFX_RX_SCALE_UNAVAILABLE) {
642204d1d17SAndrew Rybchenko 			rc = ENOTSUP;
643204d1d17SAndrew Rybchenko 			goto fail2;
644204d1d17SAndrew Rybchenko 		}
64582af879cSAndrew Rybchenko 		rss_context = enp->en_rss_context;
64682af879cSAndrew Rybchenko 	}
647204d1d17SAndrew Rybchenko 
648204d1d17SAndrew Rybchenko 	if ((rc = efx_mcdi_rss_context_set_flags(enp,
64982af879cSAndrew Rybchenko 		    rss_context, type)) != 0)
650204d1d17SAndrew Rybchenko 		goto fail3;
651204d1d17SAndrew Rybchenko 
652204d1d17SAndrew Rybchenko 	return (0);
653204d1d17SAndrew Rybchenko 
654204d1d17SAndrew Rybchenko fail3:
655204d1d17SAndrew Rybchenko 	EFSYS_PROBE(fail3);
656204d1d17SAndrew Rybchenko fail2:
657204d1d17SAndrew Rybchenko 	EFSYS_PROBE(fail2);
658204d1d17SAndrew Rybchenko fail1:
659204d1d17SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
660204d1d17SAndrew Rybchenko 
661204d1d17SAndrew Rybchenko 	return (rc);
662204d1d17SAndrew Rybchenko }
663204d1d17SAndrew Rybchenko #endif /* EFSYS_OPT_RX_SCALE */
664204d1d17SAndrew Rybchenko 
665204d1d17SAndrew Rybchenko #if EFSYS_OPT_RX_SCALE
666204d1d17SAndrew Rybchenko 	__checkReturn	efx_rc_t
ef10_rx_scale_key_set(__in efx_nic_t * enp,__in uint32_t rss_context,__in_ecount (n)uint8_t * key,__in size_t n)667204d1d17SAndrew Rybchenko ef10_rx_scale_key_set(
668204d1d17SAndrew Rybchenko 	__in		efx_nic_t *enp,
66982af879cSAndrew Rybchenko 	__in		uint32_t rss_context,
670204d1d17SAndrew Rybchenko 	__in_ecount(n)	uint8_t *key,
671204d1d17SAndrew Rybchenko 	__in		size_t n)
672204d1d17SAndrew Rybchenko {
673204d1d17SAndrew Rybchenko 	efx_rc_t rc;
674204d1d17SAndrew Rybchenko 
67544d836f8SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_RSS_KEY_SIZE ==
67644d836f8SAndrew Rybchenko 	    MC_CMD_RSS_CONTEXT_SET_KEY_IN_TOEPLITZ_KEY_LEN);
67744d836f8SAndrew Rybchenko 
67882af879cSAndrew Rybchenko 	if (rss_context == EFX_RSS_CONTEXT_DEFAULT) {
67939023729SAndrew Rybchenko 		if (enp->en_rss_context_type == EFX_RX_SCALE_UNAVAILABLE) {
680204d1d17SAndrew Rybchenko 			rc = ENOTSUP;
681204d1d17SAndrew Rybchenko 			goto fail1;
682204d1d17SAndrew Rybchenko 		}
68382af879cSAndrew Rybchenko 		rss_context = enp->en_rss_context;
68482af879cSAndrew Rybchenko 	}
685204d1d17SAndrew Rybchenko 
68682af879cSAndrew Rybchenko 	if ((rc = efx_mcdi_rss_context_set_key(enp, rss_context, key, n)) != 0)
687204d1d17SAndrew Rybchenko 		goto fail2;
688204d1d17SAndrew Rybchenko 
689204d1d17SAndrew Rybchenko 	return (0);
690204d1d17SAndrew Rybchenko 
691204d1d17SAndrew Rybchenko fail2:
692204d1d17SAndrew Rybchenko 	EFSYS_PROBE(fail2);
693204d1d17SAndrew Rybchenko fail1:
694204d1d17SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
695204d1d17SAndrew Rybchenko 
696204d1d17SAndrew Rybchenko 	return (rc);
697204d1d17SAndrew Rybchenko }
698204d1d17SAndrew Rybchenko #endif /* EFSYS_OPT_RX_SCALE */
699204d1d17SAndrew Rybchenko 
700204d1d17SAndrew Rybchenko #if EFSYS_OPT_RX_SCALE
701204d1d17SAndrew Rybchenko 	__checkReturn	efx_rc_t
ef10_rx_scale_tbl_set(__in efx_nic_t * enp,__in uint32_t rss_context,__in_ecount (n)unsigned int * table,__in size_t n)702204d1d17SAndrew Rybchenko ef10_rx_scale_tbl_set(
703204d1d17SAndrew Rybchenko 	__in		efx_nic_t *enp,
70482af879cSAndrew Rybchenko 	__in		uint32_t rss_context,
705204d1d17SAndrew Rybchenko 	__in_ecount(n)	unsigned int *table,
706204d1d17SAndrew Rybchenko 	__in		size_t n)
707204d1d17SAndrew Rybchenko {
708204d1d17SAndrew Rybchenko 	efx_rc_t rc;
709204d1d17SAndrew Rybchenko 
71082af879cSAndrew Rybchenko 	if (rss_context == EFX_RSS_CONTEXT_DEFAULT) {
71139023729SAndrew Rybchenko 		if (enp->en_rss_context_type == EFX_RX_SCALE_UNAVAILABLE) {
712204d1d17SAndrew Rybchenko 			rc = ENOTSUP;
713204d1d17SAndrew Rybchenko 			goto fail1;
714204d1d17SAndrew Rybchenko 		}
71582af879cSAndrew Rybchenko 		rss_context = enp->en_rss_context;
71682af879cSAndrew Rybchenko 	}
717204d1d17SAndrew Rybchenko 
718204d1d17SAndrew Rybchenko 	if ((rc = efx_mcdi_rss_context_set_table(enp,
71982af879cSAndrew Rybchenko 		    rss_context, table, n)) != 0)
720204d1d17SAndrew Rybchenko 		goto fail2;
721204d1d17SAndrew Rybchenko 
722204d1d17SAndrew Rybchenko 	return (0);
723204d1d17SAndrew Rybchenko 
724204d1d17SAndrew Rybchenko fail2:
725204d1d17SAndrew Rybchenko 	EFSYS_PROBE(fail2);
726204d1d17SAndrew Rybchenko fail1:
727204d1d17SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
728204d1d17SAndrew Rybchenko 
729204d1d17SAndrew Rybchenko 	return (rc);
730204d1d17SAndrew Rybchenko }
731204d1d17SAndrew Rybchenko #endif /* EFSYS_OPT_RX_SCALE */
732204d1d17SAndrew Rybchenko 
733204d1d17SAndrew Rybchenko /*
734204d1d17SAndrew Rybchenko  * EF10 RX pseudo-header
735204d1d17SAndrew Rybchenko  * ---------------------
736204d1d17SAndrew Rybchenko  *
737204d1d17SAndrew Rybchenko  * Receive packets are prefixed by an (optional) 14 byte pseudo-header:
738204d1d17SAndrew Rybchenko  *
739204d1d17SAndrew Rybchenko  *  +00: Toeplitz hash value.
740204d1d17SAndrew Rybchenko  *       (32bit little-endian)
741204d1d17SAndrew Rybchenko  *  +04: Outer VLAN tag. Zero if the packet did not have an outer VLAN tag.
742204d1d17SAndrew Rybchenko  *       (16bit big-endian)
743204d1d17SAndrew Rybchenko  *  +06: Inner VLAN tag. Zero if the packet did not have an inner VLAN tag.
744204d1d17SAndrew Rybchenko  *       (16bit big-endian)
745204d1d17SAndrew Rybchenko  *  +08: Packet Length. Zero if the RX datapath was in cut-through mode.
746204d1d17SAndrew Rybchenko  *       (16bit little-endian)
747204d1d17SAndrew Rybchenko  *  +10: MAC timestamp. Zero if timestamping is not enabled.
748204d1d17SAndrew Rybchenko  *       (32bit little-endian)
749204d1d17SAndrew Rybchenko  *
750204d1d17SAndrew Rybchenko  * See "The RX Pseudo-header" in SF-109306-TC.
751204d1d17SAndrew Rybchenko  */
752204d1d17SAndrew Rybchenko 
753204d1d17SAndrew Rybchenko 	__checkReturn	efx_rc_t
ef10_rx_prefix_pktlen(__in efx_nic_t * enp,__in uint8_t * buffer,__out uint16_t * lengthp)754204d1d17SAndrew Rybchenko ef10_rx_prefix_pktlen(
755204d1d17SAndrew Rybchenko 	__in		efx_nic_t *enp,
756204d1d17SAndrew Rybchenko 	__in		uint8_t *buffer,
757204d1d17SAndrew Rybchenko 	__out		uint16_t *lengthp)
758204d1d17SAndrew Rybchenko {
759a92a2133SAndrew Rybchenko 	_NOTE(ARGUNUSED(enp))
760a92a2133SAndrew Rybchenko 
761204d1d17SAndrew Rybchenko 	/*
762204d1d17SAndrew Rybchenko 	 * The RX pseudo-header contains the packet length, excluding the
763204d1d17SAndrew Rybchenko 	 * pseudo-header. If the hardware receive datapath was operating in
764204d1d17SAndrew Rybchenko 	 * cut-through mode then the length in the RX pseudo-header will be
765204d1d17SAndrew Rybchenko 	 * zero, and the packet length must be obtained from the DMA length
766204d1d17SAndrew Rybchenko 	 * reported in the RX event.
767204d1d17SAndrew Rybchenko 	 */
768204d1d17SAndrew Rybchenko 	*lengthp = buffer[8] | (buffer[9] << 8);
769204d1d17SAndrew Rybchenko 	return (0);
770204d1d17SAndrew Rybchenko }
771204d1d17SAndrew Rybchenko 
772204d1d17SAndrew Rybchenko #if EFSYS_OPT_RX_SCALE
773204d1d17SAndrew Rybchenko 	__checkReturn	uint32_t
ef10_rx_prefix_hash(__in efx_nic_t * enp,__in efx_rx_hash_alg_t func,__in uint8_t * buffer)774204d1d17SAndrew Rybchenko ef10_rx_prefix_hash(
775204d1d17SAndrew Rybchenko 	__in		efx_nic_t *enp,
776204d1d17SAndrew Rybchenko 	__in		efx_rx_hash_alg_t func,
777204d1d17SAndrew Rybchenko 	__in		uint8_t *buffer)
778204d1d17SAndrew Rybchenko {
779a92a2133SAndrew Rybchenko 	_NOTE(ARGUNUSED(enp))
780a92a2133SAndrew Rybchenko 
781204d1d17SAndrew Rybchenko 	switch (func) {
782fcfb73b8SAndrew Rybchenko 	case EFX_RX_HASHALG_PACKED_STREAM:
783204d1d17SAndrew Rybchenko 	case EFX_RX_HASHALG_TOEPLITZ:
784204d1d17SAndrew Rybchenko 		return (buffer[0] |
785204d1d17SAndrew Rybchenko 		    (buffer[1] << 8) |
786204d1d17SAndrew Rybchenko 		    (buffer[2] << 16) |
787204d1d17SAndrew Rybchenko 		    (buffer[3] << 24));
788204d1d17SAndrew Rybchenko 
789204d1d17SAndrew Rybchenko 	default:
790204d1d17SAndrew Rybchenko 		EFSYS_ASSERT(0);
791204d1d17SAndrew Rybchenko 		return (0);
792204d1d17SAndrew Rybchenko 	}
793204d1d17SAndrew Rybchenko }
794204d1d17SAndrew Rybchenko #endif /* EFSYS_OPT_RX_SCALE */
795204d1d17SAndrew Rybchenko 
7963caf31e9SAndrew Rybchenko #if EFSYS_OPT_RX_PACKED_STREAM
7973caf31e9SAndrew Rybchenko /*
7983caf31e9SAndrew Rybchenko  * Fake length for RXQ descriptors in packed stream mode
7993caf31e9SAndrew Rybchenko  * to make hardware happy
8003caf31e9SAndrew Rybchenko  */
8013caf31e9SAndrew Rybchenko #define	EFX_RXQ_PACKED_STREAM_FAKE_BUF_SIZE 32
8023caf31e9SAndrew Rybchenko #endif
8033caf31e9SAndrew Rybchenko 
804204d1d17SAndrew Rybchenko 				void
ef10_rx_qpost(__in efx_rxq_t * erp,__in_ecount (ndescs)efsys_dma_addr_t * addrp,__in size_t size,__in unsigned int ndescs,__in unsigned int completed,__in unsigned int added)805204d1d17SAndrew Rybchenko ef10_rx_qpost(
806204d1d17SAndrew Rybchenko 	__in			efx_rxq_t *erp,
80759ee8172SAndrew Rybchenko 	__in_ecount(ndescs)	efsys_dma_addr_t *addrp,
808204d1d17SAndrew Rybchenko 	__in			size_t size,
80959ee8172SAndrew Rybchenko 	__in			unsigned int ndescs,
810204d1d17SAndrew Rybchenko 	__in			unsigned int completed,
811204d1d17SAndrew Rybchenko 	__in			unsigned int added)
812204d1d17SAndrew Rybchenko {
813204d1d17SAndrew Rybchenko 	efx_qword_t qword;
814204d1d17SAndrew Rybchenko 	unsigned int i;
815204d1d17SAndrew Rybchenko 	unsigned int offset;
816204d1d17SAndrew Rybchenko 	unsigned int id;
817204d1d17SAndrew Rybchenko 
818bbea9604SAndrew Rybchenko 	_NOTE(ARGUNUSED(completed))
819bbea9604SAndrew Rybchenko 
8203caf31e9SAndrew Rybchenko #if EFSYS_OPT_RX_PACKED_STREAM
8213caf31e9SAndrew Rybchenko 	/*
8223caf31e9SAndrew Rybchenko 	 * Real size of the buffer does not fit into ESF_DZ_RX_KER_BYTE_CNT
8233caf31e9SAndrew Rybchenko 	 * and equal to 0 after applying mask. Hardware does not like it.
8243caf31e9SAndrew Rybchenko 	 */
8253caf31e9SAndrew Rybchenko 	if (erp->er_ev_qstate->eers_rx_packed_stream)
8263caf31e9SAndrew Rybchenko 		size = EFX_RXQ_PACKED_STREAM_FAKE_BUF_SIZE;
8273caf31e9SAndrew Rybchenko #endif
8283caf31e9SAndrew Rybchenko 
829204d1d17SAndrew Rybchenko 	/* The client driver must not overfill the queue */
83059ee8172SAndrew Rybchenko 	EFSYS_ASSERT3U(added - completed + ndescs, <=,
831204d1d17SAndrew Rybchenko 	    EFX_RXQ_LIMIT(erp->er_mask + 1));
832204d1d17SAndrew Rybchenko 
833204d1d17SAndrew Rybchenko 	id = added & (erp->er_mask);
83459ee8172SAndrew Rybchenko 	for (i = 0; i < ndescs; i++) {
835204d1d17SAndrew Rybchenko 		EFSYS_PROBE4(rx_post, unsigned int, erp->er_index,
836204d1d17SAndrew Rybchenko 		    unsigned int, id, efsys_dma_addr_t, addrp[i],
837204d1d17SAndrew Rybchenko 		    size_t, size);
838204d1d17SAndrew Rybchenko 
839204d1d17SAndrew Rybchenko 		EFX_POPULATE_QWORD_3(qword,
840204d1d17SAndrew Rybchenko 		    ESF_DZ_RX_KER_BYTE_CNT, (uint32_t)(size),
841204d1d17SAndrew Rybchenko 		    ESF_DZ_RX_KER_BUF_ADDR_DW0,
842204d1d17SAndrew Rybchenko 		    (uint32_t)(addrp[i] & 0xffffffff),
843204d1d17SAndrew Rybchenko 		    ESF_DZ_RX_KER_BUF_ADDR_DW1,
844204d1d17SAndrew Rybchenko 		    (uint32_t)(addrp[i] >> 32));
845204d1d17SAndrew Rybchenko 
846204d1d17SAndrew Rybchenko 		offset = id * sizeof (efx_qword_t);
847204d1d17SAndrew Rybchenko 		EFSYS_MEM_WRITEQ(erp->er_esmp, offset, &qword);
848204d1d17SAndrew Rybchenko 
849204d1d17SAndrew Rybchenko 		id = (id + 1) & (erp->er_mask);
850204d1d17SAndrew Rybchenko 	}
851204d1d17SAndrew Rybchenko }
852204d1d17SAndrew Rybchenko 
853204d1d17SAndrew Rybchenko 			void
ef10_rx_qpush(__in efx_rxq_t * erp,__in unsigned int added,__inout unsigned int * pushedp)854204d1d17SAndrew Rybchenko ef10_rx_qpush(
855204d1d17SAndrew Rybchenko 	__in	efx_rxq_t *erp,
856204d1d17SAndrew Rybchenko 	__in	unsigned int added,
857204d1d17SAndrew Rybchenko 	__inout	unsigned int *pushedp)
858204d1d17SAndrew Rybchenko {
859204d1d17SAndrew Rybchenko 	efx_nic_t *enp = erp->er_enp;
860204d1d17SAndrew Rybchenko 	unsigned int pushed = *pushedp;
861204d1d17SAndrew Rybchenko 	uint32_t wptr;
862204d1d17SAndrew Rybchenko 	efx_dword_t dword;
863204d1d17SAndrew Rybchenko 
864204d1d17SAndrew Rybchenko 	/* Hardware has alignment restriction for WPTR */
865e561c5feSAndrew Rybchenko 	wptr = EFX_P2ALIGN(unsigned int, added, EF10_RX_WPTR_ALIGN);
866204d1d17SAndrew Rybchenko 	if (pushed == wptr)
867204d1d17SAndrew Rybchenko 		return;
868204d1d17SAndrew Rybchenko 
869204d1d17SAndrew Rybchenko 	*pushedp = wptr;
870204d1d17SAndrew Rybchenko 
871204d1d17SAndrew Rybchenko 	/* Push the populated descriptors out */
872204d1d17SAndrew Rybchenko 	wptr &= erp->er_mask;
873204d1d17SAndrew Rybchenko 
874204d1d17SAndrew Rybchenko 	EFX_POPULATE_DWORD_1(dword, ERF_DZ_RX_DESC_WPTR, wptr);
875204d1d17SAndrew Rybchenko 
876204d1d17SAndrew Rybchenko 	/* Guarantee ordering of memory (descriptors) and PIO (doorbell) */
877204d1d17SAndrew Rybchenko 	EFX_DMA_SYNC_QUEUE_FOR_DEVICE(erp->er_esmp, erp->er_mask + 1,
878204d1d17SAndrew Rybchenko 	    wptr, pushed & erp->er_mask);
879204d1d17SAndrew Rybchenko 	EFSYS_PIO_WRITE_BARRIER();
880c63c8369SAndrew Rybchenko 	EFX_BAR_VI_WRITED(enp, ER_DZ_RX_DESC_UPD_REG,
881204d1d17SAndrew Rybchenko 	    erp->er_index, &dword, B_FALSE);
882204d1d17SAndrew Rybchenko }
883204d1d17SAndrew Rybchenko 
8848e0c4827SAndrew Rybchenko #if EFSYS_OPT_RX_PACKED_STREAM
8858e0c4827SAndrew Rybchenko 
8868e0c4827SAndrew Rybchenko 			void
ef10_rx_qpush_ps_credits(__in efx_rxq_t * erp)8878e0c4827SAndrew Rybchenko ef10_rx_qpush_ps_credits(
8888e0c4827SAndrew Rybchenko 	__in		efx_rxq_t *erp)
8898e0c4827SAndrew Rybchenko {
8908e0c4827SAndrew Rybchenko 	efx_nic_t *enp = erp->er_enp;
8918e0c4827SAndrew Rybchenko 	efx_dword_t dword;
8925fb80fd4SAndrew Rybchenko 	efx_evq_rxq_state_t *rxq_state = erp->er_ev_qstate;
8938e0c4827SAndrew Rybchenko 	uint32_t credits;
8948e0c4827SAndrew Rybchenko 
8958e0c4827SAndrew Rybchenko 	EFSYS_ASSERT(rxq_state->eers_rx_packed_stream);
8968e0c4827SAndrew Rybchenko 
8978e0c4827SAndrew Rybchenko 	if (rxq_state->eers_rx_packed_stream_credits == 0)
8988e0c4827SAndrew Rybchenko 		return;
8998e0c4827SAndrew Rybchenko 
9008e0c4827SAndrew Rybchenko 	/*
9018e0c4827SAndrew Rybchenko 	 * It is a bug if we think that FW has utilized more
9028e0c4827SAndrew Rybchenko 	 * credits than it is allowed to have (maximum). However,
9038e0c4827SAndrew Rybchenko 	 * make sure that we do not credit more than maximum anyway.
9048e0c4827SAndrew Rybchenko 	 */
9058e0c4827SAndrew Rybchenko 	credits = MIN(rxq_state->eers_rx_packed_stream_credits,
9068e0c4827SAndrew Rybchenko 	    EFX_RX_PACKED_STREAM_MAX_CREDITS);
9078e0c4827SAndrew Rybchenko 	EFX_POPULATE_DWORD_3(dword,
9088e0c4827SAndrew Rybchenko 	    ERF_DZ_RX_DESC_MAGIC_DOORBELL, 1,
9098e0c4827SAndrew Rybchenko 	    ERF_DZ_RX_DESC_MAGIC_CMD,
9108e0c4827SAndrew Rybchenko 	    ERE_DZ_RX_DESC_MAGIC_CMD_PS_CREDITS,
9118e0c4827SAndrew Rybchenko 	    ERF_DZ_RX_DESC_MAGIC_DATA, credits);
912c63c8369SAndrew Rybchenko 	EFX_BAR_VI_WRITED(enp, ER_DZ_RX_DESC_UPD_REG,
9138e0c4827SAndrew Rybchenko 	    erp->er_index, &dword, B_FALSE);
9148e0c4827SAndrew Rybchenko 
9158e0c4827SAndrew Rybchenko 	rxq_state->eers_rx_packed_stream_credits = 0;
9168e0c4827SAndrew Rybchenko }
9178e0c4827SAndrew Rybchenko 
9188e0c4827SAndrew Rybchenko /*
9198e0c4827SAndrew Rybchenko  * In accordance with SF-112241-TC the received data has the following layout:
9208e0c4827SAndrew Rybchenko  *  - 8 byte pseudo-header which consist of:
9218e0c4827SAndrew Rybchenko  *    - 4 byte little-endian timestamp
9228e0c4827SAndrew Rybchenko  *    - 2 byte little-endian captured length in bytes
9238e0c4827SAndrew Rybchenko  *    - 2 byte little-endian original packet length in bytes
9248e0c4827SAndrew Rybchenko  *  - captured packet bytes
9258e0c4827SAndrew Rybchenko  *  - optional padding to align to 64 bytes boundary
9268e0c4827SAndrew Rybchenko  *  - 64 bytes scratch space for the host software
9278e0c4827SAndrew Rybchenko  */
9288e0c4827SAndrew Rybchenko 	__checkReturn	uint8_t *
ef10_rx_qps_packet_info(__in efx_rxq_t * erp,__in uint8_t * buffer,__in uint32_t buffer_length,__in uint32_t current_offset,__out uint16_t * lengthp,__out uint32_t * next_offsetp,__out uint32_t * timestamp)9298e0c4827SAndrew Rybchenko ef10_rx_qps_packet_info(
9308e0c4827SAndrew Rybchenko 	__in		efx_rxq_t *erp,
9318e0c4827SAndrew Rybchenko 	__in		uint8_t *buffer,
9328e0c4827SAndrew Rybchenko 	__in		uint32_t buffer_length,
9338e0c4827SAndrew Rybchenko 	__in		uint32_t current_offset,
9348e0c4827SAndrew Rybchenko 	__out		uint16_t *lengthp,
9358e0c4827SAndrew Rybchenko 	__out		uint32_t *next_offsetp,
9368e0c4827SAndrew Rybchenko 	__out		uint32_t *timestamp)
9378e0c4827SAndrew Rybchenko {
9388e0c4827SAndrew Rybchenko 	uint16_t buf_len;
9398e0c4827SAndrew Rybchenko 	uint8_t *pkt_start;
9408e0c4827SAndrew Rybchenko 	efx_qword_t *qwordp;
9415fb80fd4SAndrew Rybchenko 	efx_evq_rxq_state_t *rxq_state = erp->er_ev_qstate;
9428e0c4827SAndrew Rybchenko 
9438e0c4827SAndrew Rybchenko 	EFSYS_ASSERT(rxq_state->eers_rx_packed_stream);
9448e0c4827SAndrew Rybchenko 
9458e0c4827SAndrew Rybchenko 	buffer += current_offset;
9468e0c4827SAndrew Rybchenko 	pkt_start = buffer + EFX_RX_PACKED_STREAM_RX_PREFIX_SIZE;
9478e0c4827SAndrew Rybchenko 
9488e0c4827SAndrew Rybchenko 	qwordp = (efx_qword_t *)buffer;
9498e0c4827SAndrew Rybchenko 	*timestamp = EFX_QWORD_FIELD(*qwordp, ES_DZ_PS_RX_PREFIX_TSTAMP);
9508e0c4827SAndrew Rybchenko 	*lengthp   = EFX_QWORD_FIELD(*qwordp, ES_DZ_PS_RX_PREFIX_ORIG_LEN);
9518e0c4827SAndrew Rybchenko 	buf_len    = EFX_QWORD_FIELD(*qwordp, ES_DZ_PS_RX_PREFIX_CAP_LEN);
9528e0c4827SAndrew Rybchenko 
953ec30f0beSAndrew Rybchenko 	buf_len = EFX_P2ROUNDUP(uint16_t,
954ec30f0beSAndrew Rybchenko 	    buf_len + EFX_RX_PACKED_STREAM_RX_PREFIX_SIZE,
9558e0c4827SAndrew Rybchenko 	    EFX_RX_PACKED_STREAM_ALIGNMENT);
9568e0c4827SAndrew Rybchenko 	*next_offsetp =
9578e0c4827SAndrew Rybchenko 	    current_offset + buf_len + EFX_RX_PACKED_STREAM_ALIGNMENT;
9588e0c4827SAndrew Rybchenko 
9598e0c4827SAndrew Rybchenko 	EFSYS_ASSERT3U(*next_offsetp, <=, buffer_length);
9608e0c4827SAndrew Rybchenko 	EFSYS_ASSERT3U(current_offset + *lengthp, <, *next_offsetp);
9618e0c4827SAndrew Rybchenko 
9628e0c4827SAndrew Rybchenko 	if ((*next_offsetp ^ current_offset) &
9638e0c4827SAndrew Rybchenko 	    EFX_RX_PACKED_STREAM_MEM_PER_CREDIT)
9648e0c4827SAndrew Rybchenko 		rxq_state->eers_rx_packed_stream_credits++;
9658e0c4827SAndrew Rybchenko 
9668e0c4827SAndrew Rybchenko 	return (pkt_start);
9678e0c4827SAndrew Rybchenko }
9688e0c4827SAndrew Rybchenko 
9698e0c4827SAndrew Rybchenko #endif
9708e0c4827SAndrew Rybchenko 
971204d1d17SAndrew Rybchenko 	__checkReturn	efx_rc_t
ef10_rx_qflush(__in efx_rxq_t * erp)972204d1d17SAndrew Rybchenko ef10_rx_qflush(
973204d1d17SAndrew Rybchenko 	__in	efx_rxq_t *erp)
974204d1d17SAndrew Rybchenko {
975204d1d17SAndrew Rybchenko 	efx_nic_t *enp = erp->er_enp;
976204d1d17SAndrew Rybchenko 	efx_rc_t rc;
977204d1d17SAndrew Rybchenko 
978204d1d17SAndrew Rybchenko 	if ((rc = efx_mcdi_fini_rxq(enp, erp->er_index)) != 0)
979204d1d17SAndrew Rybchenko 		goto fail1;
980204d1d17SAndrew Rybchenko 
981204d1d17SAndrew Rybchenko 	return (0);
982204d1d17SAndrew Rybchenko 
983204d1d17SAndrew Rybchenko fail1:
9847e1059e8SAndrew Rybchenko 	/*
9857e1059e8SAndrew Rybchenko 	 * EALREADY is not an error, but indicates that the MC has rebooted and
9867e1059e8SAndrew Rybchenko 	 * that the RXQ has already been destroyed. Callers need to know that
9877e1059e8SAndrew Rybchenko 	 * the RXQ flush has completed to avoid waiting until timeout for a
9887e1059e8SAndrew Rybchenko 	 * flush done event that will not be delivered.
9897e1059e8SAndrew Rybchenko 	 */
9907e1059e8SAndrew Rybchenko 	if (rc != EALREADY)
991204d1d17SAndrew Rybchenko 		EFSYS_PROBE1(fail1, efx_rc_t, rc);
992204d1d17SAndrew Rybchenko 
993204d1d17SAndrew Rybchenko 	return (rc);
994204d1d17SAndrew Rybchenko }
995204d1d17SAndrew Rybchenko 
996204d1d17SAndrew Rybchenko 		void
ef10_rx_qenable(__in efx_rxq_t * erp)997204d1d17SAndrew Rybchenko ef10_rx_qenable(
998204d1d17SAndrew Rybchenko 	__in	efx_rxq_t *erp)
999204d1d17SAndrew Rybchenko {
1000204d1d17SAndrew Rybchenko 	/* FIXME */
1001204d1d17SAndrew Rybchenko 	_NOTE(ARGUNUSED(erp))
1002204d1d17SAndrew Rybchenko 	/* FIXME */
1003204d1d17SAndrew Rybchenko }
1004204d1d17SAndrew Rybchenko 
1005204d1d17SAndrew Rybchenko 	__checkReturn	efx_rc_t
ef10_rx_qcreate(__in efx_nic_t * enp,__in unsigned int index,__in unsigned int label,__in efx_rxq_type_t type,__in_opt const efx_rxq_type_data_t * type_data,__in efsys_mem_t * esmp,__in size_t ndescs,__in uint32_t id,__in unsigned int flags,__in efx_evq_t * eep,__in efx_rxq_t * erp)1006204d1d17SAndrew Rybchenko ef10_rx_qcreate(
1007204d1d17SAndrew Rybchenko 	__in		efx_nic_t *enp,
1008204d1d17SAndrew Rybchenko 	__in		unsigned int index,
1009204d1d17SAndrew Rybchenko 	__in		unsigned int label,
1010204d1d17SAndrew Rybchenko 	__in		efx_rxq_type_t type,
1011d707fb20SAndrew Rybchenko 	__in_opt	const efx_rxq_type_data_t *type_data,
1012204d1d17SAndrew Rybchenko 	__in		efsys_mem_t *esmp,
101359ee8172SAndrew Rybchenko 	__in		size_t ndescs,
1014204d1d17SAndrew Rybchenko 	__in		uint32_t id,
10159445d1c5SAndrew Rybchenko 	__in		unsigned int flags,
1016204d1d17SAndrew Rybchenko 	__in		efx_evq_t *eep,
1017204d1d17SAndrew Rybchenko 	__in		efx_rxq_t *erp)
1018204d1d17SAndrew Rybchenko {
1019204d1d17SAndrew Rybchenko 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1020204d1d17SAndrew Rybchenko 	efx_rc_t rc;
1021204d1d17SAndrew Rybchenko 	boolean_t disable_scatter;
10224ed151b8SAndrew Rybchenko 	boolean_t want_inner_classes;
10238e0c4827SAndrew Rybchenko 	unsigned int ps_buf_size;
102404381b5eSAndrew Rybchenko 	uint32_t es_bufs_per_desc = 0;
102504381b5eSAndrew Rybchenko 	uint32_t es_max_dma_len = 0;
102604381b5eSAndrew Rybchenko 	uint32_t es_buf_stride = 0;
102704381b5eSAndrew Rybchenko 	uint32_t hol_block_timeout = 0;
1028204d1d17SAndrew Rybchenko 
1029074cfb5cSAndrew Rybchenko 	_NOTE(ARGUNUSED(id, erp, type_data))
1030204d1d17SAndrew Rybchenko 
1031204d1d17SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_EV_RX_NLABELS == (1 << ESF_DZ_RX_QLABEL_WIDTH));
1032204d1d17SAndrew Rybchenko 	EFSYS_ASSERT3U(label, <, EFX_EV_RX_NLABELS);
1033204d1d17SAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_rx_qcount + 1, <, encp->enc_rxq_limit);
1034204d1d17SAndrew Rybchenko 
1035204d1d17SAndrew Rybchenko 	EFX_STATIC_ASSERT(ISP2(EFX_RXQ_MAXNDESCS));
1036204d1d17SAndrew Rybchenko 	EFX_STATIC_ASSERT(ISP2(EFX_RXQ_MINNDESCS));
1037204d1d17SAndrew Rybchenko 
103859ee8172SAndrew Rybchenko 	if (!ISP2(ndescs) ||
103959ee8172SAndrew Rybchenko 	    (ndescs < EFX_RXQ_MINNDESCS) || (ndescs > EFX_RXQ_MAXNDESCS)) {
1040204d1d17SAndrew Rybchenko 		rc = EINVAL;
1041204d1d17SAndrew Rybchenko 		goto fail1;
1042204d1d17SAndrew Rybchenko 	}
1043204d1d17SAndrew Rybchenko 	if (index >= encp->enc_rxq_limit) {
1044204d1d17SAndrew Rybchenko 		rc = EINVAL;
1045204d1d17SAndrew Rybchenko 		goto fail2;
1046204d1d17SAndrew Rybchenko 	}
1047204d1d17SAndrew Rybchenko 
10488e0c4827SAndrew Rybchenko 	switch (type) {
10498e0c4827SAndrew Rybchenko 	case EFX_RXQ_TYPE_DEFAULT:
10508e0c4827SAndrew Rybchenko 		ps_buf_size = 0;
10518e0c4827SAndrew Rybchenko 		break;
10528e0c4827SAndrew Rybchenko #if EFSYS_OPT_RX_PACKED_STREAM
1053074cfb5cSAndrew Rybchenko 	case EFX_RXQ_TYPE_PACKED_STREAM:
1054d707fb20SAndrew Rybchenko 		if (type_data == NULL) {
1055d707fb20SAndrew Rybchenko 			rc = EINVAL;
1056d707fb20SAndrew Rybchenko 			goto fail3;
1057d707fb20SAndrew Rybchenko 		}
10582a726a7fSAndrew Rybchenko 		switch (type_data->ertd_packed_stream.eps_buf_size) {
1059074cfb5cSAndrew Rybchenko 		case EFX_RXQ_PACKED_STREAM_BUF_SIZE_1M:
10608e0c4827SAndrew Rybchenko 			ps_buf_size = MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_1M;
10618e0c4827SAndrew Rybchenko 			break;
1062074cfb5cSAndrew Rybchenko 		case EFX_RXQ_PACKED_STREAM_BUF_SIZE_512K:
10638e0c4827SAndrew Rybchenko 			ps_buf_size = MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_512K;
10648e0c4827SAndrew Rybchenko 			break;
1065074cfb5cSAndrew Rybchenko 		case EFX_RXQ_PACKED_STREAM_BUF_SIZE_256K:
10668e0c4827SAndrew Rybchenko 			ps_buf_size = MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_256K;
10678e0c4827SAndrew Rybchenko 			break;
1068074cfb5cSAndrew Rybchenko 		case EFX_RXQ_PACKED_STREAM_BUF_SIZE_128K:
10698e0c4827SAndrew Rybchenko 			ps_buf_size = MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_128K;
10708e0c4827SAndrew Rybchenko 			break;
1071074cfb5cSAndrew Rybchenko 		case EFX_RXQ_PACKED_STREAM_BUF_SIZE_64K:
10728e0c4827SAndrew Rybchenko 			ps_buf_size = MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_64K;
10738e0c4827SAndrew Rybchenko 			break;
1074074cfb5cSAndrew Rybchenko 		default:
1075074cfb5cSAndrew Rybchenko 			rc = ENOTSUP;
1076d707fb20SAndrew Rybchenko 			goto fail4;
1077074cfb5cSAndrew Rybchenko 		}
1078074cfb5cSAndrew Rybchenko 		break;
10798e0c4827SAndrew Rybchenko #endif /* EFSYS_OPT_RX_PACKED_STREAM */
108004381b5eSAndrew Rybchenko #if EFSYS_OPT_RX_ES_SUPER_BUFFER
108104381b5eSAndrew Rybchenko 	case EFX_RXQ_TYPE_ES_SUPER_BUFFER:
1082d707fb20SAndrew Rybchenko 		if (type_data == NULL) {
1083d707fb20SAndrew Rybchenko 			rc = EINVAL;
1084d707fb20SAndrew Rybchenko 			goto fail5;
1085d707fb20SAndrew Rybchenko 		}
108604381b5eSAndrew Rybchenko 		ps_buf_size = 0;
108704381b5eSAndrew Rybchenko 		es_bufs_per_desc =
108804381b5eSAndrew Rybchenko 		    type_data->ertd_es_super_buffer.eessb_bufs_per_desc;
108904381b5eSAndrew Rybchenko 		es_max_dma_len =
109004381b5eSAndrew Rybchenko 		    type_data->ertd_es_super_buffer.eessb_max_dma_len;
109104381b5eSAndrew Rybchenko 		es_buf_stride =
109204381b5eSAndrew Rybchenko 		    type_data->ertd_es_super_buffer.eessb_buf_stride;
109304381b5eSAndrew Rybchenko 		hol_block_timeout =
109404381b5eSAndrew Rybchenko 		    type_data->ertd_es_super_buffer.eessb_hol_block_timeout;
109504381b5eSAndrew Rybchenko 		break;
109604381b5eSAndrew Rybchenko #endif /* EFSYS_OPT_RX_ES_SUPER_BUFFER */
10978e0c4827SAndrew Rybchenko 	default:
10988e0c4827SAndrew Rybchenko 		rc = ENOTSUP;
1099d707fb20SAndrew Rybchenko 		goto fail6;
11008e0c4827SAndrew Rybchenko 	}
11018e0c4827SAndrew Rybchenko 
11028e0c4827SAndrew Rybchenko #if EFSYS_OPT_RX_PACKED_STREAM
11038e0c4827SAndrew Rybchenko 	if (ps_buf_size != 0) {
11048e0c4827SAndrew Rybchenko 		/* Check if datapath firmware supports packed stream mode */
11058e0c4827SAndrew Rybchenko 		if (encp->enc_rx_packed_stream_supported == B_FALSE) {
11068e0c4827SAndrew Rybchenko 			rc = ENOTSUP;
1107d707fb20SAndrew Rybchenko 			goto fail7;
11088e0c4827SAndrew Rybchenko 		}
11098e0c4827SAndrew Rybchenko 		/* Check if packed stream allows configurable buffer sizes */
1110074cfb5cSAndrew Rybchenko 		if ((ps_buf_size != MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_1M) &&
11118e0c4827SAndrew Rybchenko 		    (encp->enc_rx_var_packed_stream_supported == B_FALSE)) {
11128e0c4827SAndrew Rybchenko 			rc = ENOTSUP;
1113d707fb20SAndrew Rybchenko 			goto fail8;
11148e0c4827SAndrew Rybchenko 		}
11158e0c4827SAndrew Rybchenko 	}
11168e0c4827SAndrew Rybchenko #else /* EFSYS_OPT_RX_PACKED_STREAM */
11178e0c4827SAndrew Rybchenko 	EFSYS_ASSERT(ps_buf_size == 0);
11188e0c4827SAndrew Rybchenko #endif /* EFSYS_OPT_RX_PACKED_STREAM */
11198e0c4827SAndrew Rybchenko 
112004381b5eSAndrew Rybchenko #if EFSYS_OPT_RX_ES_SUPER_BUFFER
112104381b5eSAndrew Rybchenko 	if (es_bufs_per_desc > 0) {
112204381b5eSAndrew Rybchenko 		if (encp->enc_rx_es_super_buffer_supported == B_FALSE) {
112304381b5eSAndrew Rybchenko 			rc = ENOTSUP;
1124d707fb20SAndrew Rybchenko 			goto fail9;
112504381b5eSAndrew Rybchenko 		}
1126*7daf1fedSAndrew Rybchenko 		if (!EFX_IS_P2ALIGNED(uint32_t, es_max_dma_len,
112704381b5eSAndrew Rybchenko 			    EFX_RX_ES_SUPER_BUFFER_BUF_ALIGNMENT)) {
112804381b5eSAndrew Rybchenko 			rc = EINVAL;
1129d707fb20SAndrew Rybchenko 			goto fail10;
113004381b5eSAndrew Rybchenko 		}
1131*7daf1fedSAndrew Rybchenko 		if (!EFX_IS_P2ALIGNED(uint32_t, es_buf_stride,
113204381b5eSAndrew Rybchenko 			    EFX_RX_ES_SUPER_BUFFER_BUF_ALIGNMENT)) {
113304381b5eSAndrew Rybchenko 			rc = EINVAL;
1134d707fb20SAndrew Rybchenko 			goto fail11;
113504381b5eSAndrew Rybchenko 		}
113604381b5eSAndrew Rybchenko 	}
113704381b5eSAndrew Rybchenko #else /* EFSYS_OPT_RX_ES_SUPER_BUFFER */
113804381b5eSAndrew Rybchenko 	EFSYS_ASSERT(es_bufs_per_desc == 0);
113904381b5eSAndrew Rybchenko #endif /* EFSYS_OPT_RX_ES_SUPER_BUFFER */
114004381b5eSAndrew Rybchenko 
1141204d1d17SAndrew Rybchenko 	/* Scatter can only be disabled if the firmware supports doing so */
11429445d1c5SAndrew Rybchenko 	if (flags & EFX_RXQ_FLAG_SCATTER)
1143204d1d17SAndrew Rybchenko 		disable_scatter = B_FALSE;
1144f3cacdebSAndrew Rybchenko 	else
1145f3cacdebSAndrew Rybchenko 		disable_scatter = encp->enc_rx_disable_scatter_supported;
1146204d1d17SAndrew Rybchenko 
11474ed151b8SAndrew Rybchenko 	if (flags & EFX_RXQ_FLAG_INNER_CLASSES)
11484ed151b8SAndrew Rybchenko 		want_inner_classes = B_TRUE;
11494ed151b8SAndrew Rybchenko 	else
11504ed151b8SAndrew Rybchenko 		want_inner_classes = B_FALSE;
11514ed151b8SAndrew Rybchenko 
115259ee8172SAndrew Rybchenko 	if ((rc = efx_mcdi_init_rxq(enp, ndescs, eep->ee_index, label, index,
11534ed151b8SAndrew Rybchenko 		    esmp, disable_scatter, want_inner_classes,
115404381b5eSAndrew Rybchenko 		    ps_buf_size, es_bufs_per_desc, es_max_dma_len,
115504381b5eSAndrew Rybchenko 		    es_buf_stride, hol_block_timeout)) != 0)
1156d707fb20SAndrew Rybchenko 		goto fail12;
1157204d1d17SAndrew Rybchenko 
1158204d1d17SAndrew Rybchenko 	erp->er_eep = eep;
1159204d1d17SAndrew Rybchenko 	erp->er_label = label;
1160204d1d17SAndrew Rybchenko 
11611aa1b495SAndrew Rybchenko 	ef10_ev_rxlabel_init(eep, erp, label, type);
1162204d1d17SAndrew Rybchenko 
11635fb80fd4SAndrew Rybchenko 	erp->er_ev_qstate = &erp->er_eep->ee_rxq_state[label];
11645fb80fd4SAndrew Rybchenko 
1165204d1d17SAndrew Rybchenko 	return (0);
1166204d1d17SAndrew Rybchenko 
1167d707fb20SAndrew Rybchenko fail12:
1168d707fb20SAndrew Rybchenko 	EFSYS_PROBE(fail12);
1169d707fb20SAndrew Rybchenko #if EFSYS_OPT_RX_ES_SUPER_BUFFER
1170d707fb20SAndrew Rybchenko fail11:
1171d707fb20SAndrew Rybchenko 	EFSYS_PROBE(fail11);
117204381b5eSAndrew Rybchenko fail10:
117304381b5eSAndrew Rybchenko 	EFSYS_PROBE(fail10);
117404381b5eSAndrew Rybchenko fail9:
117504381b5eSAndrew Rybchenko 	EFSYS_PROBE(fail9);
1176d707fb20SAndrew Rybchenko #endif /* EFSYS_OPT_RX_ES_SUPER_BUFFER */
1177d707fb20SAndrew Rybchenko #if EFSYS_OPT_RX_PACKED_STREAM
117804381b5eSAndrew Rybchenko fail8:
117904381b5eSAndrew Rybchenko 	EFSYS_PROBE(fail8);
1180074cfb5cSAndrew Rybchenko fail7:
1181074cfb5cSAndrew Rybchenko 	EFSYS_PROBE(fail7);
1182d707fb20SAndrew Rybchenko #endif /* EFSYS_OPT_RX_PACKED_STREAM */
11838e0c4827SAndrew Rybchenko fail6:
11848e0c4827SAndrew Rybchenko 	EFSYS_PROBE(fail6);
1185d707fb20SAndrew Rybchenko #if EFSYS_OPT_RX_ES_SUPER_BUFFER
11868e0c4827SAndrew Rybchenko fail5:
11878e0c4827SAndrew Rybchenko 	EFSYS_PROBE(fail5);
1188d707fb20SAndrew Rybchenko #endif /* EFSYS_OPT_RX_ES_SUPER_BUFFER */
1189d707fb20SAndrew Rybchenko #if EFSYS_OPT_RX_PACKED_STREAM
11908e0c4827SAndrew Rybchenko fail4:
11918e0c4827SAndrew Rybchenko 	EFSYS_PROBE(fail4);
1192204d1d17SAndrew Rybchenko fail3:
1193204d1d17SAndrew Rybchenko 	EFSYS_PROBE(fail3);
1194074cfb5cSAndrew Rybchenko #endif /* EFSYS_OPT_RX_PACKED_STREAM */
1195204d1d17SAndrew Rybchenko fail2:
1196204d1d17SAndrew Rybchenko 	EFSYS_PROBE(fail2);
1197204d1d17SAndrew Rybchenko fail1:
1198204d1d17SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1199204d1d17SAndrew Rybchenko 
1200204d1d17SAndrew Rybchenko 	return (rc);
1201204d1d17SAndrew Rybchenko }
1202204d1d17SAndrew Rybchenko 
1203204d1d17SAndrew Rybchenko 		void
ef10_rx_qdestroy(__in efx_rxq_t * erp)1204204d1d17SAndrew Rybchenko ef10_rx_qdestroy(
1205204d1d17SAndrew Rybchenko 	__in	efx_rxq_t *erp)
1206204d1d17SAndrew Rybchenko {
1207204d1d17SAndrew Rybchenko 	efx_nic_t *enp = erp->er_enp;
1208204d1d17SAndrew Rybchenko 	efx_evq_t *eep = erp->er_eep;
1209204d1d17SAndrew Rybchenko 	unsigned int label = erp->er_label;
1210204d1d17SAndrew Rybchenko 
1211204d1d17SAndrew Rybchenko 	ef10_ev_rxlabel_fini(eep, label);
1212204d1d17SAndrew Rybchenko 
1213204d1d17SAndrew Rybchenko 	EFSYS_ASSERT(enp->en_rx_qcount != 0);
1214204d1d17SAndrew Rybchenko 	--enp->en_rx_qcount;
1215204d1d17SAndrew Rybchenko 
1216204d1d17SAndrew Rybchenko 	EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_rxq_t), erp);
1217204d1d17SAndrew Rybchenko }
1218204d1d17SAndrew Rybchenko 
1219204d1d17SAndrew Rybchenko 		void
ef10_rx_fini(__in efx_nic_t * enp)1220204d1d17SAndrew Rybchenko ef10_rx_fini(
1221204d1d17SAndrew Rybchenko 	__in	efx_nic_t *enp)
1222204d1d17SAndrew Rybchenko {
1223204d1d17SAndrew Rybchenko #if EFSYS_OPT_RX_SCALE
122439023729SAndrew Rybchenko 	if (enp->en_rss_context_type != EFX_RX_SCALE_UNAVAILABLE)
1225204d1d17SAndrew Rybchenko 		(void) efx_mcdi_rss_context_free(enp, enp->en_rss_context);
1226204d1d17SAndrew Rybchenko 	enp->en_rss_context = 0;
122739023729SAndrew Rybchenko 	enp->en_rss_context_type = EFX_RX_SCALE_UNAVAILABLE;
1228204d1d17SAndrew Rybchenko #else
1229204d1d17SAndrew Rybchenko 	_NOTE(ARGUNUSED(enp))
1230204d1d17SAndrew Rybchenko #endif /* EFSYS_OPT_RX_SCALE */
1231204d1d17SAndrew Rybchenko }
1232204d1d17SAndrew Rybchenko 
123334352ef8SAndrew Rybchenko #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
1234