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