xref: /dpdk/drivers/common/sfc_efx/base/rhead_rx.c (revision e5e5c12756d133e44456e64eafdc3a0e728b57d5)
1b6b29352SAndrew Rybchenko /* SPDX-License-Identifier: BSD-3-Clause
2b6b29352SAndrew Rybchenko  *
3672386c1SAndrew Rybchenko  * Copyright(c) 2019-2021 Xilinx, Inc.
4b6b29352SAndrew Rybchenko  * Copyright(c) 2018-2019 Solarflare Communications Inc.
5b6b29352SAndrew Rybchenko  */
6b6b29352SAndrew Rybchenko 
7b6b29352SAndrew Rybchenko #include "efx.h"
8b6b29352SAndrew Rybchenko #include "efx_impl.h"
9b6b29352SAndrew Rybchenko 
10b6b29352SAndrew Rybchenko 
11b6b29352SAndrew Rybchenko #if EFSYS_OPT_RIVERHEAD
12b6b29352SAndrew Rybchenko 
136bba823fSAndrew Rybchenko /*
14c1f02189SAndrew Rybchenko  * Maximum number of Rx prefixes supported by Rx prefix choice to be
15c1f02189SAndrew Rybchenko  * returned from firmware.
16c1f02189SAndrew Rybchenko  */
17c1f02189SAndrew Rybchenko #define	RHEAD_RX_PREFIX_IDS_MAX		16
18c1f02189SAndrew Rybchenko 
19c1f02189SAndrew Rybchenko /*
206bba823fSAndrew Rybchenko  * Default Rx prefix layout on Riverhead if FW does not support Rx
216bba823fSAndrew Rybchenko  * prefix choice using MC_CMD_GET_RX_PREFIX_ID and query its layout
226bba823fSAndrew Rybchenko  * using MC_CMD_QUERY_RX_PREFIX_ID.
236bba823fSAndrew Rybchenko  *
246bba823fSAndrew Rybchenko  * See SF-119689-TC Riverhead Host Interface section 6.4.
256bba823fSAndrew Rybchenko  */
266bba823fSAndrew Rybchenko static const efx_rx_prefix_layout_t rhead_default_rx_prefix_layout = {
276bba823fSAndrew Rybchenko 	.erpl_id	= 0,
286bba823fSAndrew Rybchenko 	.erpl_length	= ESE_GZ_RX_PKT_PREFIX_LEN,
296bba823fSAndrew Rybchenko 	.erpl_fields	= {
306bba823fSAndrew Rybchenko #define	RHEAD_RX_PREFIX_FIELD(_name, _big_endian) \
316bba823fSAndrew Rybchenko 	EFX_RX_PREFIX_FIELD(_name, ESF_GZ_RX_PREFIX_ ## _name, _big_endian)
326bba823fSAndrew Rybchenko 
336bba823fSAndrew Rybchenko 		RHEAD_RX_PREFIX_FIELD(LENGTH, B_FALSE),
346bba823fSAndrew Rybchenko 		RHEAD_RX_PREFIX_FIELD(RSS_HASH_VALID, B_FALSE),
356bba823fSAndrew Rybchenko 		RHEAD_RX_PREFIX_FIELD(USER_FLAG, B_FALSE),
366bba823fSAndrew Rybchenko 		RHEAD_RX_PREFIX_FIELD(CLASS, B_FALSE),
376bba823fSAndrew Rybchenko 		RHEAD_RX_PREFIX_FIELD(PARTIAL_TSTAMP, B_FALSE),
386bba823fSAndrew Rybchenko 		RHEAD_RX_PREFIX_FIELD(RSS_HASH, B_FALSE),
396bba823fSAndrew Rybchenko 		RHEAD_RX_PREFIX_FIELD(USER_MARK, B_FALSE),
40c4f4a0e6SAndrew Rybchenko 		RHEAD_RX_PREFIX_FIELD(INGRESS_MPORT, B_FALSE),
416bba823fSAndrew Rybchenko 		RHEAD_RX_PREFIX_FIELD(CSUM_FRAME, B_TRUE),
426bba823fSAndrew Rybchenko 		RHEAD_RX_PREFIX_FIELD(VLAN_STRIP_TCI, B_TRUE),
436bba823fSAndrew Rybchenko 
446bba823fSAndrew Rybchenko #undef	RHEAD_RX_PREFIX_FIELD
456bba823fSAndrew Rybchenko 	}
466bba823fSAndrew Rybchenko };
476bba823fSAndrew Rybchenko 
48b6b29352SAndrew Rybchenko 	__checkReturn	efx_rc_t
rhead_rx_init(__in efx_nic_t * enp)49b6b29352SAndrew Rybchenko rhead_rx_init(
50b6b29352SAndrew Rybchenko 	__in		efx_nic_t *enp)
51b6b29352SAndrew Rybchenko {
52b6b29352SAndrew Rybchenko 	efx_rc_t rc;
53b6b29352SAndrew Rybchenko 
54b6b29352SAndrew Rybchenko 	rc = ef10_rx_init(enp);
55b6b29352SAndrew Rybchenko 	if (rc != 0)
56b6b29352SAndrew Rybchenko 		goto fail1;
57b6b29352SAndrew Rybchenko 
58b6b29352SAndrew Rybchenko 	return (0);
59b6b29352SAndrew Rybchenko 
60b6b29352SAndrew Rybchenko fail1:
61b6b29352SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
62b6b29352SAndrew Rybchenko 	return (rc);
63b6b29352SAndrew Rybchenko }
64b6b29352SAndrew Rybchenko 
65b6b29352SAndrew Rybchenko 		void
rhead_rx_fini(__in efx_nic_t * enp)66b6b29352SAndrew Rybchenko rhead_rx_fini(
67b6b29352SAndrew Rybchenko 	__in	efx_nic_t *enp)
68b6b29352SAndrew Rybchenko {
69b6b29352SAndrew Rybchenko 	ef10_rx_fini(enp);
70b6b29352SAndrew Rybchenko }
71b6b29352SAndrew Rybchenko 
72b6b29352SAndrew Rybchenko #if EFSYS_OPT_RX_SCATTER
73b6b29352SAndrew Rybchenko 	__checkReturn	efx_rc_t
rhead_rx_scatter_enable(__in efx_nic_t * enp,__in unsigned int buf_size)74b6b29352SAndrew Rybchenko rhead_rx_scatter_enable(
75b6b29352SAndrew Rybchenko 	__in		efx_nic_t *enp,
76b6b29352SAndrew Rybchenko 	__in		unsigned int buf_size)
77b6b29352SAndrew Rybchenko {
78b6b29352SAndrew Rybchenko 	_NOTE(ARGUNUSED(enp, buf_size))
79b6b29352SAndrew Rybchenko 	/* Nothing to do here */
80b6b29352SAndrew Rybchenko 	return (0);
81b6b29352SAndrew Rybchenko }
82b6b29352SAndrew Rybchenko #endif	/* EFSYS_OPT_RX_SCATTER */
83b6b29352SAndrew Rybchenko 
84b6b29352SAndrew Rybchenko #if EFSYS_OPT_RX_SCALE
85b6b29352SAndrew Rybchenko 
86b6b29352SAndrew Rybchenko 	__checkReturn	efx_rc_t
rhead_rx_scale_context_alloc(__in efx_nic_t * enp,__in efx_rx_scale_context_type_t type,__in uint32_t num_queues,__in uint32_t table_nentries,__out uint32_t * rss_contextp)87b6b29352SAndrew Rybchenko rhead_rx_scale_context_alloc(
88b6b29352SAndrew Rybchenko 	__in		efx_nic_t *enp,
89b6b29352SAndrew Rybchenko 	__in		efx_rx_scale_context_type_t type,
90b6b29352SAndrew Rybchenko 	__in		uint32_t num_queues,
91e7ea5f30SIvan Malov 	__in		uint32_t table_nentries,
92b6b29352SAndrew Rybchenko 	__out		uint32_t *rss_contextp)
93b6b29352SAndrew Rybchenko {
94b6b29352SAndrew Rybchenko 	efx_rc_t rc;
95b6b29352SAndrew Rybchenko 
96e7ea5f30SIvan Malov 	rc = ef10_rx_scale_context_alloc(enp, type, num_queues, table_nentries,
97e7ea5f30SIvan Malov 		    rss_contextp);
98b6b29352SAndrew Rybchenko 	if (rc != 0)
99b6b29352SAndrew Rybchenko 		goto fail1;
100b6b29352SAndrew Rybchenko 
101b6b29352SAndrew Rybchenko 	return (0);
102b6b29352SAndrew Rybchenko 
103b6b29352SAndrew Rybchenko fail1:
104b6b29352SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
105b6b29352SAndrew Rybchenko 	return (rc);
106b6b29352SAndrew Rybchenko }
107b6b29352SAndrew Rybchenko 
108b6b29352SAndrew Rybchenko 	__checkReturn	efx_rc_t
rhead_rx_scale_context_free(__in efx_nic_t * enp,__in uint32_t rss_context)109b6b29352SAndrew Rybchenko rhead_rx_scale_context_free(
110b6b29352SAndrew Rybchenko 	__in		efx_nic_t *enp,
111b6b29352SAndrew Rybchenko 	__in		uint32_t rss_context)
112b6b29352SAndrew Rybchenko {
113b6b29352SAndrew Rybchenko 	efx_rc_t rc;
114b6b29352SAndrew Rybchenko 
115b6b29352SAndrew Rybchenko 	rc = ef10_rx_scale_context_free(enp, rss_context);
116b6b29352SAndrew Rybchenko 	if (rc != 0)
117b6b29352SAndrew Rybchenko 		goto fail1;
118b6b29352SAndrew Rybchenko 
119b6b29352SAndrew Rybchenko 	return (0);
120b6b29352SAndrew Rybchenko 
121b6b29352SAndrew Rybchenko fail1:
122b6b29352SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
123b6b29352SAndrew Rybchenko 	return (rc);
124b6b29352SAndrew Rybchenko }
125b6b29352SAndrew Rybchenko 
126b6b29352SAndrew Rybchenko 	__checkReturn	efx_rc_t
rhead_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)127b6b29352SAndrew Rybchenko rhead_rx_scale_mode_set(
128b6b29352SAndrew Rybchenko 	__in		efx_nic_t *enp,
129b6b29352SAndrew Rybchenko 	__in		uint32_t rss_context,
130b6b29352SAndrew Rybchenko 	__in		efx_rx_hash_alg_t alg,
131b6b29352SAndrew Rybchenko 	__in		efx_rx_hash_type_t type,
132b6b29352SAndrew Rybchenko 	__in		boolean_t insert)
133b6b29352SAndrew Rybchenko {
134b6b29352SAndrew Rybchenko 	efx_rc_t rc;
135b6b29352SAndrew Rybchenko 
136b6b29352SAndrew Rybchenko 	rc = ef10_rx_scale_mode_set(enp, rss_context, alg, type, insert);
137b6b29352SAndrew Rybchenko 	if (rc != 0)
138b6b29352SAndrew Rybchenko 		goto fail1;
139b6b29352SAndrew Rybchenko 
140b6b29352SAndrew Rybchenko 	return (0);
141b6b29352SAndrew Rybchenko 
142b6b29352SAndrew Rybchenko fail1:
143b6b29352SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
144b6b29352SAndrew Rybchenko 	return (rc);
145b6b29352SAndrew Rybchenko }
146b6b29352SAndrew Rybchenko 
147b6b29352SAndrew Rybchenko 	__checkReturn	efx_rc_t
rhead_rx_scale_key_set(__in efx_nic_t * enp,__in uint32_t rss_context,__in_ecount (n)uint8_t * key,__in size_t n)148b6b29352SAndrew Rybchenko rhead_rx_scale_key_set(
149b6b29352SAndrew Rybchenko 	__in		efx_nic_t *enp,
150b6b29352SAndrew Rybchenko 	__in		uint32_t rss_context,
151b6b29352SAndrew Rybchenko 	__in_ecount(n)	uint8_t *key,
152b6b29352SAndrew Rybchenko 	__in		size_t n)
153b6b29352SAndrew Rybchenko {
154b6b29352SAndrew Rybchenko 	efx_rc_t rc;
155b6b29352SAndrew Rybchenko 
156b6b29352SAndrew Rybchenko 	rc = ef10_rx_scale_key_set(enp, rss_context, key, n);
157b6b29352SAndrew Rybchenko 	if (rc != 0)
158b6b29352SAndrew Rybchenko 		goto fail1;
159b6b29352SAndrew Rybchenko 
160b6b29352SAndrew Rybchenko 	return (0);
161b6b29352SAndrew Rybchenko 
162b6b29352SAndrew Rybchenko fail1:
163b6b29352SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
164b6b29352SAndrew Rybchenko 	return (rc);
165b6b29352SAndrew Rybchenko }
166b6b29352SAndrew Rybchenko 
167b6b29352SAndrew Rybchenko 	__checkReturn		efx_rc_t
rhead_rx_scale_tbl_set(__in efx_nic_t * enp,__in uint32_t rss_context,__in_ecount (nentries)unsigned int * table,__in size_t nentries)168b6b29352SAndrew Rybchenko rhead_rx_scale_tbl_set(
169b6b29352SAndrew Rybchenko 	__in			efx_nic_t *enp,
170b6b29352SAndrew Rybchenko 	__in			uint32_t rss_context,
1717a71c15dSIvan Malov 	__in_ecount(nentries)	unsigned int *table,
1727a71c15dSIvan Malov 	__in			size_t nentries)
173b6b29352SAndrew Rybchenko {
174b6b29352SAndrew Rybchenko 	efx_rc_t rc;
175b6b29352SAndrew Rybchenko 
1767a71c15dSIvan Malov 	rc = ef10_rx_scale_tbl_set(enp, rss_context, table, nentries);
177b6b29352SAndrew Rybchenko 	if (rc != 0)
178b6b29352SAndrew Rybchenko 		goto fail1;
179b6b29352SAndrew Rybchenko 
180b6b29352SAndrew Rybchenko 	return (0);
181b6b29352SAndrew Rybchenko 
182b6b29352SAndrew Rybchenko fail1:
183b6b29352SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
184b6b29352SAndrew Rybchenko 	return (rc);
185b6b29352SAndrew Rybchenko }
186b6b29352SAndrew Rybchenko 
187b6b29352SAndrew Rybchenko 	__checkReturn	uint32_t
rhead_rx_prefix_hash(__in efx_nic_t * enp,__in efx_rx_hash_alg_t func,__in uint8_t * buffer)188b6b29352SAndrew Rybchenko rhead_rx_prefix_hash(
189b6b29352SAndrew Rybchenko 	__in		efx_nic_t *enp,
190b6b29352SAndrew Rybchenko 	__in		efx_rx_hash_alg_t func,
191b6b29352SAndrew Rybchenko 	__in		uint8_t *buffer)
192b6b29352SAndrew Rybchenko {
193b6b29352SAndrew Rybchenko 	_NOTE(ARGUNUSED(enp, func, buffer))
194b6b29352SAndrew Rybchenko 
195b6b29352SAndrew Rybchenko 	/* FIXME implement the method for Riverhead */
196b6b29352SAndrew Rybchenko 
197b6b29352SAndrew Rybchenko 	return (ENOTSUP);
198b6b29352SAndrew Rybchenko }
199b6b29352SAndrew Rybchenko 
200b6b29352SAndrew Rybchenko #endif /* EFSYS_OPT_RX_SCALE */
201b6b29352SAndrew Rybchenko 
202b6b29352SAndrew Rybchenko 	__checkReturn	efx_rc_t
rhead_rx_prefix_pktlen(__in efx_nic_t * enp,__in uint8_t * buffer,__out uint16_t * lengthp)203b6b29352SAndrew Rybchenko rhead_rx_prefix_pktlen(
204b6b29352SAndrew Rybchenko 	__in		efx_nic_t *enp,
205b6b29352SAndrew Rybchenko 	__in		uint8_t *buffer,
206b6b29352SAndrew Rybchenko 	__out		uint16_t *lengthp)
207b6b29352SAndrew Rybchenko {
208b6b29352SAndrew Rybchenko 	_NOTE(ARGUNUSED(enp, buffer, lengthp))
209b6b29352SAndrew Rybchenko 
210b6b29352SAndrew Rybchenko 	/* FIXME implement the method for Riverhead */
211b6b29352SAndrew Rybchenko 
212b6b29352SAndrew Rybchenko 	return (ENOTSUP);
213b6b29352SAndrew Rybchenko }
214b6b29352SAndrew Rybchenko 
215b6b29352SAndrew Rybchenko 				void
rhead_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)216b6b29352SAndrew Rybchenko rhead_rx_qpost(
217b6b29352SAndrew Rybchenko 	__in			efx_rxq_t *erp,
218b6b29352SAndrew Rybchenko 	__in_ecount(ndescs)	efsys_dma_addr_t *addrp,
219b6b29352SAndrew Rybchenko 	__in			size_t size,
220b6b29352SAndrew Rybchenko 	__in			unsigned int ndescs,
221b6b29352SAndrew Rybchenko 	__in			unsigned int completed,
222b6b29352SAndrew Rybchenko 	__in			unsigned int added)
223b6b29352SAndrew Rybchenko {
224b6b29352SAndrew Rybchenko 	_NOTE(ARGUNUSED(erp, addrp, size, ndescs, completed, added))
225b6b29352SAndrew Rybchenko 
226b6b29352SAndrew Rybchenko 	/* FIXME implement the method for Riverhead */
227b6b29352SAndrew Rybchenko 
228b6b29352SAndrew Rybchenko 	EFSYS_ASSERT(B_FALSE);
229b6b29352SAndrew Rybchenko }
230b6b29352SAndrew Rybchenko 
231b6b29352SAndrew Rybchenko 			void
rhead_rx_qpush(__in efx_rxq_t * erp,__in unsigned int added,__inout unsigned int * pushedp)232b6b29352SAndrew Rybchenko rhead_rx_qpush(
233b6b29352SAndrew Rybchenko 	__in	efx_rxq_t *erp,
234b6b29352SAndrew Rybchenko 	__in	unsigned int added,
235b6b29352SAndrew Rybchenko 	__inout	unsigned int *pushedp)
236b6b29352SAndrew Rybchenko {
237b6b29352SAndrew Rybchenko 	_NOTE(ARGUNUSED(erp, added, pushedp))
238b6b29352SAndrew Rybchenko 
239b6b29352SAndrew Rybchenko 	/* FIXME implement the method for Riverhead */
240b6b29352SAndrew Rybchenko 
241b6b29352SAndrew Rybchenko 	EFSYS_ASSERT(B_FALSE);
242b6b29352SAndrew Rybchenko }
243b6b29352SAndrew Rybchenko 
244b6b29352SAndrew Rybchenko 	__checkReturn	efx_rc_t
rhead_rx_qflush(__in efx_rxq_t * erp)245b6b29352SAndrew Rybchenko rhead_rx_qflush(
246b6b29352SAndrew Rybchenko 	__in	efx_rxq_t *erp)
247b6b29352SAndrew Rybchenko {
248b6b29352SAndrew Rybchenko 	efx_nic_t *enp = erp->er_enp;
249b6b29352SAndrew Rybchenko 	efx_rc_t rc;
250b6b29352SAndrew Rybchenko 
251b6b29352SAndrew Rybchenko 	if ((rc = efx_mcdi_fini_rxq(enp, erp->er_index)) != 0)
252b6b29352SAndrew Rybchenko 		goto fail1;
253b6b29352SAndrew Rybchenko 
254b6b29352SAndrew Rybchenko 	return (0);
255b6b29352SAndrew Rybchenko 
256b6b29352SAndrew Rybchenko fail1:
257b6b29352SAndrew Rybchenko 	/*
258b6b29352SAndrew Rybchenko 	 * EALREADY is not an error, but indicates that the MC has rebooted and
259b6b29352SAndrew Rybchenko 	 * that the RXQ has already been destroyed. Callers need to know that
260b6b29352SAndrew Rybchenko 	 * the RXQ flush has completed to avoid waiting until timeout for a
261b6b29352SAndrew Rybchenko 	 * flush done event that will not be delivered.
262b6b29352SAndrew Rybchenko 	 */
263b6b29352SAndrew Rybchenko 	if (rc != EALREADY)
264b6b29352SAndrew Rybchenko 		EFSYS_PROBE1(fail1, efx_rc_t, rc);
265b6b29352SAndrew Rybchenko 
266b6b29352SAndrew Rybchenko 	return (rc);
267b6b29352SAndrew Rybchenko }
268b6b29352SAndrew Rybchenko 
269b6b29352SAndrew Rybchenko 		void
rhead_rx_qenable(__in efx_rxq_t * erp)270b6b29352SAndrew Rybchenko rhead_rx_qenable(
271b6b29352SAndrew Rybchenko 	__in	efx_rxq_t *erp)
272b6b29352SAndrew Rybchenko {
273b6b29352SAndrew Rybchenko 	_NOTE(ARGUNUSED(erp))
274b6b29352SAndrew Rybchenko }
275b6b29352SAndrew Rybchenko 
276c1f02189SAndrew Rybchenko static	__checkReturn	efx_rc_t
efx_mcdi_get_rx_prefix_ids(__in efx_nic_t * enp,__in uint32_t mcdi_fields_mask,__in unsigned int max_ids,__out unsigned int * nids,__out_ecount_part (max_ids,* nids)uint32_t * idsp)277c1f02189SAndrew Rybchenko efx_mcdi_get_rx_prefix_ids(
278c1f02189SAndrew Rybchenko 	__in					efx_nic_t *enp,
279c1f02189SAndrew Rybchenko 	__in					uint32_t mcdi_fields_mask,
280c1f02189SAndrew Rybchenko 	__in					unsigned int max_ids,
281c1f02189SAndrew Rybchenko 	__out					unsigned int *nids,
282c1f02189SAndrew Rybchenko 	__out_ecount_part(max_ids, *nids)	uint32_t *idsp)
283c1f02189SAndrew Rybchenko {
284c1f02189SAndrew Rybchenko 	efx_mcdi_req_t req;
285c1f02189SAndrew Rybchenko 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_RX_PREFIX_ID_IN_LEN,
286c1f02189SAndrew Rybchenko 		MC_CMD_GET_RX_PREFIX_ID_OUT_LENMAX);
287c1f02189SAndrew Rybchenko 	efx_rc_t rc;
288c1f02189SAndrew Rybchenko 	uint32_t num;
289c1f02189SAndrew Rybchenko 
290c1f02189SAndrew Rybchenko 	req.emr_cmd = MC_CMD_GET_RX_PREFIX_ID;
291c1f02189SAndrew Rybchenko 	req.emr_in_buf = payload;
292c1f02189SAndrew Rybchenko 	req.emr_in_length = MC_CMD_GET_RX_PREFIX_ID_IN_LEN;
293c1f02189SAndrew Rybchenko 	req.emr_out_buf = payload;
294c1f02189SAndrew Rybchenko 	req.emr_out_length = MC_CMD_GET_RX_PREFIX_ID_OUT_LENMAX;
295c1f02189SAndrew Rybchenko 
296c1f02189SAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, GET_RX_PREFIX_ID_IN_FIELDS, mcdi_fields_mask);
297c1f02189SAndrew Rybchenko 
298c1f02189SAndrew Rybchenko 	efx_mcdi_execute(enp, &req);
299c1f02189SAndrew Rybchenko 
300c1f02189SAndrew Rybchenko 	if (req.emr_rc != 0) {
301c1f02189SAndrew Rybchenko 		rc = req.emr_rc;
302c1f02189SAndrew Rybchenko 		goto fail1;
303c1f02189SAndrew Rybchenko 	}
304c1f02189SAndrew Rybchenko 
305c1f02189SAndrew Rybchenko 	if (req.emr_out_length_used < MC_CMD_GET_RX_PREFIX_ID_OUT_LENMIN) {
306c1f02189SAndrew Rybchenko 		rc = EMSGSIZE;
307c1f02189SAndrew Rybchenko 		goto fail2;
308c1f02189SAndrew Rybchenko 	}
309c1f02189SAndrew Rybchenko 
310c1f02189SAndrew Rybchenko 	num = MCDI_OUT_DWORD(req, GET_RX_PREFIX_ID_OUT_NUM_RX_PREFIX_IDS);
311c1f02189SAndrew Rybchenko 
312c1f02189SAndrew Rybchenko 	if (req.emr_out_length_used != MC_CMD_GET_RX_PREFIX_ID_OUT_LEN(num)) {
313c1f02189SAndrew Rybchenko 		rc = EMSGSIZE;
314c1f02189SAndrew Rybchenko 		goto fail3;
315c1f02189SAndrew Rybchenko 	}
316c1f02189SAndrew Rybchenko 
317c1f02189SAndrew Rybchenko 	*nids = MIN(num, max_ids);
318c1f02189SAndrew Rybchenko 
319c1f02189SAndrew Rybchenko 	EFX_STATIC_ASSERT(sizeof (idsp[0]) ==
320c1f02189SAndrew Rybchenko 	    MC_CMD_GET_RX_PREFIX_ID_OUT_RX_PREFIX_ID_LEN);
321c1f02189SAndrew Rybchenko 	memcpy(idsp,
322c1f02189SAndrew Rybchenko 	    MCDI_OUT2(req, uint32_t, GET_RX_PREFIX_ID_OUT_RX_PREFIX_ID),
323c1f02189SAndrew Rybchenko 	    *nids * sizeof (idsp[0]));
324c1f02189SAndrew Rybchenko 
325c1f02189SAndrew Rybchenko 	return (0);
326c1f02189SAndrew Rybchenko 
327c1f02189SAndrew Rybchenko fail3:
328c1f02189SAndrew Rybchenko 	EFSYS_PROBE(fail3);
329c1f02189SAndrew Rybchenko fail2:
330c1f02189SAndrew Rybchenko 	EFSYS_PROBE(fail2);
331c1f02189SAndrew Rybchenko fail1:
332c1f02189SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
333c1f02189SAndrew Rybchenko 
334c1f02189SAndrew Rybchenko 	return (rc);
335c1f02189SAndrew Rybchenko }
336c1f02189SAndrew Rybchenko 
337c1f02189SAndrew Rybchenko static	__checkReturn	efx_rx_prefix_field_t
efx_mcdi_rx_prefix_field_map(unsigned int mcdi_idx)338c1f02189SAndrew Rybchenko efx_mcdi_rx_prefix_field_map(unsigned int mcdi_idx)
339c1f02189SAndrew Rybchenko {
340c1f02189SAndrew Rybchenko 	static const efx_rx_prefix_field_t efx_mcdi_to_rx_prefix_field[] = {
341c1f02189SAndrew Rybchenko #define	EFX_MCDI_TO_RX_PREFIX_FIELD(_field) \
342c1f02189SAndrew Rybchenko 	[RX_PREFIX_FIELD_INFO_ ## _field] = EFX_RX_PREFIX_FIELD_ ## _field
343c1f02189SAndrew Rybchenko 
344c1f02189SAndrew Rybchenko 		EFX_MCDI_TO_RX_PREFIX_FIELD(LENGTH),
345c1f02189SAndrew Rybchenko 		EFX_MCDI_TO_RX_PREFIX_FIELD(RSS_HASH_VALID),
346c1f02189SAndrew Rybchenko 		EFX_MCDI_TO_RX_PREFIX_FIELD(USER_FLAG),
347c1f02189SAndrew Rybchenko 		EFX_MCDI_TO_RX_PREFIX_FIELD(CLASS),
348c1f02189SAndrew Rybchenko 		EFX_MCDI_TO_RX_PREFIX_FIELD(PARTIAL_TSTAMP),
349c1f02189SAndrew Rybchenko 		EFX_MCDI_TO_RX_PREFIX_FIELD(RSS_HASH),
350c1f02189SAndrew Rybchenko 		EFX_MCDI_TO_RX_PREFIX_FIELD(USER_MARK),
351c1f02189SAndrew Rybchenko 		EFX_MCDI_TO_RX_PREFIX_FIELD(INGRESS_VPORT),
352c1f02189SAndrew Rybchenko 		EFX_MCDI_TO_RX_PREFIX_FIELD(CSUM_FRAME),
353c1f02189SAndrew Rybchenko 		EFX_MCDI_TO_RX_PREFIX_FIELD(VLAN_STRIP_TCI),
354c1f02189SAndrew Rybchenko 
355c1f02189SAndrew Rybchenko #undef	EFX_MCDI_TO_RX_PREFIX_FIELD
356c1f02189SAndrew Rybchenko 	};
357c1f02189SAndrew Rybchenko 
358c1f02189SAndrew Rybchenko 	if (mcdi_idx >= EFX_ARRAY_SIZE(efx_mcdi_to_rx_prefix_field))
359c1f02189SAndrew Rybchenko 		return (EFX_RX_PREFIX_NFIELDS);
360c1f02189SAndrew Rybchenko 
361c1f02189SAndrew Rybchenko 	return (efx_mcdi_to_rx_prefix_field[mcdi_idx]);
362c1f02189SAndrew Rybchenko }
363c1f02189SAndrew Rybchenko 
364c1f02189SAndrew Rybchenko static	__checkReturn	int
efx_rx_prefix_field_map_to_mcdi(__in efx_rx_prefix_field_t field)365c1f02189SAndrew Rybchenko efx_rx_prefix_field_map_to_mcdi(
366c1f02189SAndrew Rybchenko 	__in		efx_rx_prefix_field_t field)
367c1f02189SAndrew Rybchenko {
368c1f02189SAndrew Rybchenko 	static const int efx_rx_prefix_field_to_mcdi[] = {
369c1f02189SAndrew Rybchenko 		[EFX_RX_PREFIX_FIELD_LENGTH] =
370c1f02189SAndrew Rybchenko 			EFX_LOW_BIT(MC_CMD_GET_RX_PREFIX_ID_IN_LENGTH),
371c1f02189SAndrew Rybchenko 		[EFX_RX_PREFIX_FIELD_ORIG_LENGTH] = -1,
372c1f02189SAndrew Rybchenko 		[EFX_RX_PREFIX_FIELD_CLASS] =
373c1f02189SAndrew Rybchenko 			EFX_LOW_BIT(MC_CMD_GET_RX_PREFIX_ID_IN_CLASS),
374c1f02189SAndrew Rybchenko 		[EFX_RX_PREFIX_FIELD_RSS_HASH] =
375c1f02189SAndrew Rybchenko 			EFX_LOW_BIT(MC_CMD_GET_RX_PREFIX_ID_IN_RSS_HASH),
376c1f02189SAndrew Rybchenko 		[EFX_RX_PREFIX_FIELD_RSS_HASH_VALID] =
377c1f02189SAndrew Rybchenko 			EFX_LOW_BIT(MC_CMD_GET_RX_PREFIX_ID_IN_RSS_HASH_VALID),
378c1f02189SAndrew Rybchenko 		[EFX_RX_PREFIX_FIELD_PARTIAL_TSTAMP] =
379c1f02189SAndrew Rybchenko 			EFX_LOW_BIT(MC_CMD_GET_RX_PREFIX_ID_IN_PARTIAL_TSTAMP),
380c1f02189SAndrew Rybchenko 		[EFX_RX_PREFIX_FIELD_VLAN_STRIP_TCI] =
381c1f02189SAndrew Rybchenko 			EFX_LOW_BIT(MC_CMD_GET_RX_PREFIX_ID_IN_VLAN_STRIP_TCI),
382c1f02189SAndrew Rybchenko 		[EFX_RX_PREFIX_FIELD_INNER_VLAN_STRIP_TCI] = -1,
383c1f02189SAndrew Rybchenko 		[EFX_RX_PREFIX_FIELD_USER_FLAG] =
384c1f02189SAndrew Rybchenko 			EFX_LOW_BIT(MC_CMD_GET_RX_PREFIX_ID_IN_USER_FLAG),
385c1f02189SAndrew Rybchenko 		[EFX_RX_PREFIX_FIELD_USER_MARK] =
386c1f02189SAndrew Rybchenko 			EFX_LOW_BIT(MC_CMD_GET_RX_PREFIX_ID_IN_USER_MARK),
387c1f02189SAndrew Rybchenko 		[EFX_RX_PREFIX_FIELD_USER_MARK_VALID] = -1,
388c1f02189SAndrew Rybchenko 		[EFX_RX_PREFIX_FIELD_CSUM_FRAME] =
389c1f02189SAndrew Rybchenko 			EFX_LOW_BIT(MC_CMD_GET_RX_PREFIX_ID_IN_CSUM_FRAME),
390c1f02189SAndrew Rybchenko 		[EFX_RX_PREFIX_FIELD_INGRESS_VPORT] =
391c1f02189SAndrew Rybchenko 			EFX_LOW_BIT(MC_CMD_GET_RX_PREFIX_ID_IN_INGRESS_VPORT),
392c1f02189SAndrew Rybchenko 	};
393c1f02189SAndrew Rybchenko 
394c1f02189SAndrew Rybchenko 	if (field >= EFX_ARRAY_SIZE(efx_rx_prefix_field_to_mcdi))
395c1f02189SAndrew Rybchenko 		return (-1);
396c1f02189SAndrew Rybchenko 
397c1f02189SAndrew Rybchenko 	return (efx_rx_prefix_field_to_mcdi[field]);
398c1f02189SAndrew Rybchenko }
399c1f02189SAndrew Rybchenko 
400c1f02189SAndrew Rybchenko static	__checkReturn	efx_rc_t
efx_rx_prefix_fields_mask_to_mcdi(__in uint32_t fields_mask,__out uint32_t * mcdi_fields_maskp)401c1f02189SAndrew Rybchenko efx_rx_prefix_fields_mask_to_mcdi(
402c1f02189SAndrew Rybchenko 	__in		uint32_t fields_mask,
403c1f02189SAndrew Rybchenko 	__out		uint32_t *mcdi_fields_maskp)
404c1f02189SAndrew Rybchenko {
405c1f02189SAndrew Rybchenko 	uint32_t mcdi_fields_mask = 0;
406c1f02189SAndrew Rybchenko 	unsigned int i;
407c1f02189SAndrew Rybchenko 
408c1f02189SAndrew Rybchenko 	for (i = 0; i < EFX_RX_PREFIX_NFIELDS; ++i) {
409c1f02189SAndrew Rybchenko 		if (fields_mask & (1U << i)) {
410c1f02189SAndrew Rybchenko 			int mcdi_field = efx_rx_prefix_field_map_to_mcdi(i);
411c1f02189SAndrew Rybchenko 
412c1f02189SAndrew Rybchenko 			if (mcdi_field < 0)
413c1f02189SAndrew Rybchenko 				return (EINVAL);
414c1f02189SAndrew Rybchenko 
415c1f02189SAndrew Rybchenko 			mcdi_fields_mask |= (1U << mcdi_field);
416c1f02189SAndrew Rybchenko 		}
417c1f02189SAndrew Rybchenko 	}
418c1f02189SAndrew Rybchenko 
419c1f02189SAndrew Rybchenko 	*mcdi_fields_maskp = mcdi_fields_mask;
420c1f02189SAndrew Rybchenko 	return (0);
421c1f02189SAndrew Rybchenko }
422c1f02189SAndrew Rybchenko 
423c1f02189SAndrew Rybchenko static	__checkReturn	efx_rc_t
efx_mcdi_query_rx_prefix_id(__in efx_nic_t * enp,__in uint32_t prefix_id,__out efx_rx_prefix_layout_t * erplp)424c1f02189SAndrew Rybchenko efx_mcdi_query_rx_prefix_id(
425c1f02189SAndrew Rybchenko 	__in		efx_nic_t *enp,
426c1f02189SAndrew Rybchenko 	__in		uint32_t prefix_id,
427c1f02189SAndrew Rybchenko 	__out		efx_rx_prefix_layout_t *erplp)
428c1f02189SAndrew Rybchenko {
429c1f02189SAndrew Rybchenko 	efx_mcdi_req_t req;
430c1f02189SAndrew Rybchenko 	EFX_MCDI_DECLARE_BUF(payload, MC_CMD_QUERY_RX_PREFIX_ID_IN_LEN,
431c1f02189SAndrew Rybchenko 		MC_CMD_QUERY_RX_PREFIX_ID_OUT_LENMAX);
432c1f02189SAndrew Rybchenko 	efx_rc_t rc;
433c1f02189SAndrew Rybchenko 	size_t response_len;
434c1f02189SAndrew Rybchenko 	const efx_dword_t *resp;
435c1f02189SAndrew Rybchenko 	const efx_dword_t *finfo;
436c1f02189SAndrew Rybchenko 	unsigned int num_fields;
437c1f02189SAndrew Rybchenko 	unsigned int mcdi_field;
438c1f02189SAndrew Rybchenko 	efx_rx_prefix_field_t field;
439c1f02189SAndrew Rybchenko 	unsigned int i;
440c1f02189SAndrew Rybchenko 
441c1f02189SAndrew Rybchenko 	req.emr_cmd = MC_CMD_QUERY_RX_PREFIX_ID;
442c1f02189SAndrew Rybchenko 	req.emr_in_buf = payload;
443c1f02189SAndrew Rybchenko 	req.emr_in_length = MC_CMD_QUERY_RX_PREFIX_ID_IN_LEN;
444c1f02189SAndrew Rybchenko 	req.emr_out_buf = payload;
445c1f02189SAndrew Rybchenko 	req.emr_out_length = MC_CMD_QUERY_RX_PREFIX_ID_OUT_LENMAX;
446c1f02189SAndrew Rybchenko 
447c1f02189SAndrew Rybchenko 	MCDI_IN_SET_DWORD(req, QUERY_RX_PREFIX_ID_IN_RX_PREFIX_ID, prefix_id);
448c1f02189SAndrew Rybchenko 
449c1f02189SAndrew Rybchenko 	efx_mcdi_execute(enp, &req);
450c1f02189SAndrew Rybchenko 
451c1f02189SAndrew Rybchenko 	if (req.emr_rc != 0) {
452c1f02189SAndrew Rybchenko 		rc = req.emr_rc;
453c1f02189SAndrew Rybchenko 		goto fail1;
454c1f02189SAndrew Rybchenko 	}
455c1f02189SAndrew Rybchenko 
456c1f02189SAndrew Rybchenko 	if (req.emr_out_length_used < MC_CMD_QUERY_RX_PREFIX_ID_OUT_LENMIN) {
457c1f02189SAndrew Rybchenko 		rc = EMSGSIZE;
458c1f02189SAndrew Rybchenko 		goto fail2;
459c1f02189SAndrew Rybchenko 	}
460c1f02189SAndrew Rybchenko 
461c1f02189SAndrew Rybchenko 	if (MCDI_OUT_BYTE(req, QUERY_RX_PREFIX_ID_OUT_RESPONSE_TYPE) !=
462c1f02189SAndrew Rybchenko 	    MC_CMD_QUERY_RX_PREFIX_ID_OUT_RESPONSE_TYPE_FIXED) {
463c1f02189SAndrew Rybchenko 		rc = ENOTSUP;
464c1f02189SAndrew Rybchenko 		goto fail3;
465c1f02189SAndrew Rybchenko 	}
466c1f02189SAndrew Rybchenko 
467c1f02189SAndrew Rybchenko 	EFX_STATIC_ASSERT(MC_CMD_QUERY_RX_PREFIX_ID_OUT_LENMIN >=
468c1f02189SAndrew Rybchenko 	    MC_CMD_QUERY_RX_PREFIX_ID_OUT_RESPONSE_OFST);
469c1f02189SAndrew Rybchenko 	response_len = req.emr_out_length_used -
470c1f02189SAndrew Rybchenko 	    MC_CMD_QUERY_RX_PREFIX_ID_OUT_RESPONSE_OFST;
471c1f02189SAndrew Rybchenko 
472c1f02189SAndrew Rybchenko 	if (response_len < RX_PREFIX_FIXED_RESPONSE_LENMIN) {
473c1f02189SAndrew Rybchenko 		rc = EMSGSIZE;
474c1f02189SAndrew Rybchenko 		goto fail4;
475c1f02189SAndrew Rybchenko 	}
476c1f02189SAndrew Rybchenko 
477c1f02189SAndrew Rybchenko 	resp = MCDI_OUT2(req, efx_dword_t, QUERY_RX_PREFIX_ID_OUT_RESPONSE);
478c1f02189SAndrew Rybchenko 
479c1f02189SAndrew Rybchenko 	memset(erplp, 0, sizeof (*erplp));
480c1f02189SAndrew Rybchenko 	erplp->erpl_id = prefix_id;
481c1f02189SAndrew Rybchenko 	erplp->erpl_length =
482c1f02189SAndrew Rybchenko 	    EFX_DWORD_FIELD(*resp, RX_PREFIX_FIXED_RESPONSE_PREFIX_LENGTH_BYTES);
483c1f02189SAndrew Rybchenko 	num_fields =
484c1f02189SAndrew Rybchenko 	    EFX_DWORD_FIELD(*resp, RX_PREFIX_FIXED_RESPONSE_FIELD_COUNT);
485c1f02189SAndrew Rybchenko 
486c1f02189SAndrew Rybchenko 	if (response_len < RX_PREFIX_FIXED_RESPONSE_LEN(num_fields)) {
487c1f02189SAndrew Rybchenko 		rc = EMSGSIZE;
488c1f02189SAndrew Rybchenko 		goto fail5;
489c1f02189SAndrew Rybchenko 	}
490c1f02189SAndrew Rybchenko 
491c1f02189SAndrew Rybchenko 	finfo = (const efx_dword_t *)((const uint8_t *)resp +
492c1f02189SAndrew Rybchenko 	     RX_PREFIX_FIXED_RESPONSE_FIELDS_OFST);
493c1f02189SAndrew Rybchenko 
494c1f02189SAndrew Rybchenko 	for (i = 0; i < num_fields; ++i, ++finfo) {
495c1f02189SAndrew Rybchenko 		mcdi_field = EFX_DWORD_FIELD(*finfo, RX_PREFIX_FIELD_INFO_TYPE);
496c1f02189SAndrew Rybchenko 
497c1f02189SAndrew Rybchenko 		field = efx_mcdi_rx_prefix_field_map(mcdi_field);
498c1f02189SAndrew Rybchenko 		if (field >= EFX_RX_PREFIX_NFIELDS)
499c1f02189SAndrew Rybchenko 			continue;
500c1f02189SAndrew Rybchenko 
501c1f02189SAndrew Rybchenko 		erplp->erpl_fields[field].erpfi_offset_bits =
502c1f02189SAndrew Rybchenko 		    EFX_DWORD_FIELD(*finfo, RX_PREFIX_FIELD_INFO_OFFSET_BITS);
503c1f02189SAndrew Rybchenko 		erplp->erpl_fields[field].erpfi_width_bits =
504c1f02189SAndrew Rybchenko 		    EFX_DWORD_FIELD(*finfo, RX_PREFIX_FIELD_INFO_WIDTH_BITS);
505c1f02189SAndrew Rybchenko 	}
506c1f02189SAndrew Rybchenko 
507c1f02189SAndrew Rybchenko 	return (0);
508c1f02189SAndrew Rybchenko 
509c1f02189SAndrew Rybchenko fail5:
510c1f02189SAndrew Rybchenko 	EFSYS_PROBE(fail5);
511c1f02189SAndrew Rybchenko fail4:
512c1f02189SAndrew Rybchenko 	EFSYS_PROBE(fail4);
513c1f02189SAndrew Rybchenko fail3:
514c1f02189SAndrew Rybchenko 	EFSYS_PROBE(fail3);
515c1f02189SAndrew Rybchenko fail2:
516c1f02189SAndrew Rybchenko 	EFSYS_PROBE(fail2);
517c1f02189SAndrew Rybchenko fail1:
518c1f02189SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
519c1f02189SAndrew Rybchenko 
520c1f02189SAndrew Rybchenko 	return (rc);
521c1f02189SAndrew Rybchenko }
522c1f02189SAndrew Rybchenko 
523c1f02189SAndrew Rybchenko static	__checkReturn	efx_rc_t
rhead_rx_choose_prefix_id(__in efx_nic_t * enp,__in uint32_t fields_mask,__out efx_rx_prefix_layout_t * erplp)524c1f02189SAndrew Rybchenko rhead_rx_choose_prefix_id(
525c1f02189SAndrew Rybchenko 	__in		efx_nic_t *enp,
526c1f02189SAndrew Rybchenko 	__in		uint32_t fields_mask,
527c1f02189SAndrew Rybchenko 	__out		efx_rx_prefix_layout_t *erplp)
528c1f02189SAndrew Rybchenko {
529c1f02189SAndrew Rybchenko 	efx_rx_prefix_layout_t erpl;
530c1f02189SAndrew Rybchenko 	uint32_t prefix_ids[RHEAD_RX_PREFIX_IDS_MAX];
531c1f02189SAndrew Rybchenko 	uint32_t mcdi_fields_mask;
532c1f02189SAndrew Rybchenko 	unsigned int num = 0;
533c1f02189SAndrew Rybchenko 	unsigned int i;
534c1f02189SAndrew Rybchenko 	efx_rc_t rc;
535c1f02189SAndrew Rybchenko 
536c1f02189SAndrew Rybchenko 	rc = efx_rx_prefix_fields_mask_to_mcdi(fields_mask, &mcdi_fields_mask);
537c1f02189SAndrew Rybchenko 	if (rc != 0)
538c1f02189SAndrew Rybchenko 		goto fail1;
539c1f02189SAndrew Rybchenko 
540c1f02189SAndrew Rybchenko 	memset(erplp, 0, sizeof (*erplp));
541c1f02189SAndrew Rybchenko 
542c1f02189SAndrew Rybchenko 	rc = efx_mcdi_get_rx_prefix_ids(enp, mcdi_fields_mask,
543c1f02189SAndrew Rybchenko 	    EFX_ARRAY_SIZE(prefix_ids), &num, prefix_ids);
544c1f02189SAndrew Rybchenko 	if (rc == ENOTSUP) {
545c1f02189SAndrew Rybchenko 		/* Not supported MCDI, use default prefix ID */
546c1f02189SAndrew Rybchenko 		*erplp = rhead_default_rx_prefix_layout;
547c1f02189SAndrew Rybchenko 		goto done;
548c1f02189SAndrew Rybchenko 	}
549c1f02189SAndrew Rybchenko 	if (rc != 0)
550c1f02189SAndrew Rybchenko 		goto fail2;
551c1f02189SAndrew Rybchenko 
552c1f02189SAndrew Rybchenko 	if (num == 0) {
553c1f02189SAndrew Rybchenko 		rc = ENOTSUP;
554c1f02189SAndrew Rybchenko 		goto fail3;
555c1f02189SAndrew Rybchenko 	}
556c1f02189SAndrew Rybchenko 
557c1f02189SAndrew Rybchenko 	for (i = 0; i < num; ++i) {
558c1f02189SAndrew Rybchenko 		rc = efx_mcdi_query_rx_prefix_id(enp, prefix_ids[i], &erpl);
559c1f02189SAndrew Rybchenko 		if (rc != 0)
560c1f02189SAndrew Rybchenko 			goto fail4;
561c1f02189SAndrew Rybchenko 
562c1f02189SAndrew Rybchenko 		/* Choose the smallest prefix which meets our requirements */
563c1f02189SAndrew Rybchenko 		if (i == 0 || erpl.erpl_length < erplp->erpl_length)
564c1f02189SAndrew Rybchenko 			*erplp = erpl;
565c1f02189SAndrew Rybchenko 	}
566c1f02189SAndrew Rybchenko 
567c1f02189SAndrew Rybchenko done:
568c1f02189SAndrew Rybchenko 	return (0);
569c1f02189SAndrew Rybchenko 
570c1f02189SAndrew Rybchenko fail4:
571c1f02189SAndrew Rybchenko 	EFSYS_PROBE(fail4);
572c1f02189SAndrew Rybchenko fail3:
573c1f02189SAndrew Rybchenko 	EFSYS_PROBE(fail3);
574c1f02189SAndrew Rybchenko fail2:
575c1f02189SAndrew Rybchenko 	EFSYS_PROBE(fail2);
576c1f02189SAndrew Rybchenko fail1:
577c1f02189SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
578c1f02189SAndrew Rybchenko 
579c1f02189SAndrew Rybchenko 	return (rc);
580c1f02189SAndrew Rybchenko }
581c1f02189SAndrew Rybchenko 
582b6b29352SAndrew Rybchenko 	__checkReturn	efx_rc_t
rhead_rx_qcreate(__in efx_nic_t * enp,__in unsigned int index,__in unsigned int label,__in efx_rxq_type_t type,__in 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)583b6b29352SAndrew Rybchenko rhead_rx_qcreate(
584b6b29352SAndrew Rybchenko 	__in		efx_nic_t *enp,
585b6b29352SAndrew Rybchenko 	__in		unsigned int index,
586b6b29352SAndrew Rybchenko 	__in		unsigned int label,
587b6b29352SAndrew Rybchenko 	__in		efx_rxq_type_t type,
588b6b29352SAndrew Rybchenko 	__in		const efx_rxq_type_data_t *type_data,
589b6b29352SAndrew Rybchenko 	__in		efsys_mem_t *esmp,
590b6b29352SAndrew Rybchenko 	__in		size_t ndescs,
591b6b29352SAndrew Rybchenko 	__in		uint32_t id,
592b6b29352SAndrew Rybchenko 	__in		unsigned int flags,
593b6b29352SAndrew Rybchenko 	__in		efx_evq_t *eep,
594b6b29352SAndrew Rybchenko 	__in		efx_rxq_t *erp)
595b6b29352SAndrew Rybchenko {
596b6b29352SAndrew Rybchenko 	const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
5977640543fSAndrew Rybchenko 	efx_mcdi_init_rxq_params_t params;
598c1f02189SAndrew Rybchenko 	efx_rx_prefix_layout_t erpl;
599f21c6e7fSAndrew Rybchenko 	uint32_t fields_mask = 0;
600b6b29352SAndrew Rybchenko 	efx_rc_t rc;
601b6b29352SAndrew Rybchenko 
602b6b29352SAndrew Rybchenko 	_NOTE(ARGUNUSED(id))
603b6b29352SAndrew Rybchenko 
604b6b29352SAndrew Rybchenko 	EFX_STATIC_ASSERT(EFX_EV_RX_NLABELS <=
605b6b29352SAndrew Rybchenko 	    (1 << ESF_GZ_EV_RXPKTS_Q_LABEL_WIDTH));
606b6b29352SAndrew Rybchenko 	EFSYS_ASSERT3U(label, <, EFX_EV_RX_NLABELS);
607b6b29352SAndrew Rybchenko 
6087640543fSAndrew Rybchenko 	memset(&params, 0, sizeof (params));
6097640543fSAndrew Rybchenko 
610b6b29352SAndrew Rybchenko 	switch (type) {
611b6b29352SAndrew Rybchenko 	case EFX_RXQ_TYPE_DEFAULT:
612b6b29352SAndrew Rybchenko 		if (type_data == NULL) {
613b6b29352SAndrew Rybchenko 			rc = EINVAL;
614b6b29352SAndrew Rybchenko 			goto fail1;
615b6b29352SAndrew Rybchenko 		}
6167640543fSAndrew Rybchenko 		params.buf_size = type_data->ertd_default.ed_buf_size;
617b6b29352SAndrew Rybchenko 		break;
618b6b29352SAndrew Rybchenko 	default:
619b6b29352SAndrew Rybchenko 		rc = ENOTSUP;
620b6b29352SAndrew Rybchenko 		goto fail2;
621b6b29352SAndrew Rybchenko 	}
622b6b29352SAndrew Rybchenko 
623b6b29352SAndrew Rybchenko 	/* Scatter can only be disabled if the firmware supports doing so */
624b6b29352SAndrew Rybchenko 	if (flags & EFX_RXQ_FLAG_SCATTER)
6257640543fSAndrew Rybchenko 		params.disable_scatter = B_FALSE;
626b6b29352SAndrew Rybchenko 	else
6277640543fSAndrew Rybchenko 		params.disable_scatter = encp->enc_rx_disable_scatter_supported;
628b6b29352SAndrew Rybchenko 
629f784cdc5SAndrew Rybchenko 	if (flags & EFX_RXQ_FLAG_RSS_HASH) {
630f784cdc5SAndrew Rybchenko 		fields_mask |= 1U << EFX_RX_PREFIX_FIELD_RSS_HASH;
631f784cdc5SAndrew Rybchenko 		fields_mask |= 1U << EFX_RX_PREFIX_FIELD_RSS_HASH_VALID;
632f784cdc5SAndrew Rybchenko 	}
633f784cdc5SAndrew Rybchenko 
634aa3e21f0SIgor Romanov 	if (flags & EFX_RXQ_FLAG_INGRESS_MPORT)
635aa3e21f0SIgor Romanov 		fields_mask |= 1U << EFX_RX_PREFIX_FIELD_INGRESS_MPORT;
636aa3e21f0SIgor Romanov 
637c414c567SIgor Romanov 	if (flags & EFX_RXQ_FLAG_USER_MARK)
638c414c567SIgor Romanov 		fields_mask |= 1U << EFX_RX_PREFIX_FIELD_USER_MARK;
639c414c567SIgor Romanov 
640cdea571bSIvan Malov 	if (flags & EFX_RXQ_FLAG_USER_FLAG)
641cdea571bSIvan Malov 		fields_mask |= 1U << EFX_RX_PREFIX_FIELD_USER_FLAG;
642cdea571bSIvan Malov 
643*e5e5c127SArtemii Morozov 	if (flags & EFX_RXQ_FLAG_VLAN_STRIPPED_TCI)
644*e5e5c127SArtemii Morozov 		fields_mask |= 1U << EFX_RX_PREFIX_FIELD_VLAN_STRIP_TCI;
645*e5e5c127SArtemii Morozov 
646b6b29352SAndrew Rybchenko 	/*
647c1f02189SAndrew Rybchenko 	 * LENGTH is required in EF100 host interface, as receive events
648c1f02189SAndrew Rybchenko 	 * do not include the packet length.
649c1f02189SAndrew Rybchenko 	 */
650f21c6e7fSAndrew Rybchenko 	fields_mask |= 1U << EFX_RX_PREFIX_FIELD_LENGTH;
651f21c6e7fSAndrew Rybchenko 	if ((rc = rhead_rx_choose_prefix_id(enp, fields_mask, &erpl)) != 0)
652c1f02189SAndrew Rybchenko 		goto fail3;
653c1f02189SAndrew Rybchenko 
654c1f02189SAndrew Rybchenko 	params.prefix_id = erpl.erpl_id;
655c1f02189SAndrew Rybchenko 
656c1f02189SAndrew Rybchenko 	/*
657b6b29352SAndrew Rybchenko 	 * Ignore EFX_RXQ_FLAG_INNER_CLASSES since in accordance with
658b6b29352SAndrew Rybchenko 	 * EF100 host interface both inner and outer classes are provided
659b6b29352SAndrew Rybchenko 	 * by HW if applicable.
660b6b29352SAndrew Rybchenko 	 */
661b6b29352SAndrew Rybchenko 
662b6b29352SAndrew Rybchenko 	if ((rc = efx_mcdi_init_rxq(enp, ndescs, eep, label, index,
6637640543fSAndrew Rybchenko 		    esmp, &params)) != 0)
664c1f02189SAndrew Rybchenko 		goto fail4;
665b6b29352SAndrew Rybchenko 
666b6b29352SAndrew Rybchenko 	erp->er_eep = eep;
667b6b29352SAndrew Rybchenko 	erp->er_label = label;
6687640543fSAndrew Rybchenko 	erp->er_buf_size = params.buf_size;
669c1f02189SAndrew Rybchenko 	erp->er_prefix_layout = erpl;
670b6b29352SAndrew Rybchenko 
671b6b29352SAndrew Rybchenko 	return (0);
672b6b29352SAndrew Rybchenko 
673c1f02189SAndrew Rybchenko fail4:
674c1f02189SAndrew Rybchenko 	EFSYS_PROBE(fail4);
675b6b29352SAndrew Rybchenko fail3:
676b6b29352SAndrew Rybchenko 	EFSYS_PROBE(fail3);
677b6b29352SAndrew Rybchenko fail2:
678b6b29352SAndrew Rybchenko 	EFSYS_PROBE(fail2);
679b6b29352SAndrew Rybchenko fail1:
680b6b29352SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
681b6b29352SAndrew Rybchenko 
682b6b29352SAndrew Rybchenko 	return (rc);
683b6b29352SAndrew Rybchenko }
684b6b29352SAndrew Rybchenko 
685b6b29352SAndrew Rybchenko 		void
rhead_rx_qdestroy(__in efx_rxq_t * erp)686b6b29352SAndrew Rybchenko rhead_rx_qdestroy(
687b6b29352SAndrew Rybchenko 	__in	efx_rxq_t *erp)
688b6b29352SAndrew Rybchenko {
689b6b29352SAndrew Rybchenko 	_NOTE(ARGUNUSED(erp))
690b6b29352SAndrew Rybchenko 	/* Nothing to do here */
691b6b29352SAndrew Rybchenko }
692b6b29352SAndrew Rybchenko 
693b6b29352SAndrew Rybchenko #endif /* EFSYS_OPT_RIVERHEAD */
694