1 /* SPDX-License-Identifier: BSD-3-Clause
2 *
3 * Copyright(c) 2019-2020 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_VPORT, 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,__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 __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
rhead_rx_scale_context_free(__in efx_nic_t * enp,__in uint32_t rss_context)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
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)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
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)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
rhead_rx_scale_tbl_set(__in efx_nic_t * enp,__in uint32_t rss_context,__in_ecount (n)unsigned int * table,__in size_t n)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
rhead_rx_prefix_hash(__in efx_nic_t * enp,__in efx_rx_hash_alg_t func,__in uint8_t * buffer)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
rhead_rx_prefix_pktlen(__in efx_nic_t * enp,__in uint8_t * buffer,__out uint16_t * lengthp)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
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)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
rhead_rx_qpush(__in efx_rxq_t * erp,__in unsigned int added,__inout unsigned int * pushedp)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
rhead_rx_qflush(__in efx_rxq_t * erp)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
rhead_rx_qenable(__in efx_rxq_t * erp)268 rhead_rx_qenable(
269 __in efx_rxq_t *erp)
270 {
271 _NOTE(ARGUNUSED(erp))
272 }
273
274 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)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
efx_mcdi_rx_prefix_field_map(unsigned int mcdi_idx)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
efx_rx_prefix_field_map_to_mcdi(__in efx_rx_prefix_field_t field)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
efx_rx_prefix_fields_mask_to_mcdi(__in uint32_t fields_mask,__out uint32_t * mcdi_fields_maskp)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
efx_mcdi_query_rx_prefix_id(__in efx_nic_t * enp,__in uint32_t prefix_id,__out efx_rx_prefix_layout_t * erplp)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
rhead_rx_choose_prefix_id(__in efx_nic_t * enp,__in uint32_t fields_mask,__out efx_rx_prefix_layout_t * erplp)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
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)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(¶ms, 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 /*
633 * LENGTH is required in EF100 host interface, as receive events
634 * do not include the packet length.
635 */
636 fields_mask |= 1U << EFX_RX_PREFIX_FIELD_LENGTH;
637 if ((rc = rhead_rx_choose_prefix_id(enp, fields_mask, &erpl)) != 0)
638 goto fail3;
639
640 params.prefix_id = erpl.erpl_id;
641
642 /*
643 * Ignore EFX_RXQ_FLAG_INNER_CLASSES since in accordance with
644 * EF100 host interface both inner and outer classes are provided
645 * by HW if applicable.
646 */
647
648 if ((rc = efx_mcdi_init_rxq(enp, ndescs, eep, label, index,
649 esmp, ¶ms)) != 0)
650 goto fail4;
651
652 erp->er_eep = eep;
653 erp->er_label = label;
654 erp->er_buf_size = params.buf_size;
655 erp->er_prefix_layout = erpl;
656
657 return (0);
658
659 fail4:
660 EFSYS_PROBE(fail4);
661 fail3:
662 EFSYS_PROBE(fail3);
663 fail2:
664 EFSYS_PROBE(fail2);
665 fail1:
666 EFSYS_PROBE1(fail1, efx_rc_t, rc);
667
668 return (rc);
669 }
670
671 void
rhead_rx_qdestroy(__in efx_rxq_t * erp)672 rhead_rx_qdestroy(
673 __in efx_rxq_t *erp)
674 {
675 _NOTE(ARGUNUSED(erp))
676 /* Nothing to do here */
677 }
678
679 #endif /* EFSYS_OPT_RIVERHEAD */
680