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(¶ms, 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, ¶ms)) != 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