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