Branch data Line data Source code
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 : 0 : rhead_rx_init(
50 : : __in efx_nic_t *enp)
51 : : {
52 : : efx_rc_t rc;
53 : :
54 : 0 : rc = ef10_rx_init(enp);
55 [ # # ]: 0 : if (rc != 0)
56 : 0 : goto fail1;
57 : :
58 : : return (0);
59 : :
60 : : fail1:
61 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
62 : 0 : return (rc);
63 : : }
64 : :
65 : : void
66 : 0 : rhead_rx_fini(
67 : : __in efx_nic_t *enp)
68 : : {
69 : 0 : ef10_rx_fini(enp);
70 : 0 : }
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 : 0 : 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 : 0 : rc = ef10_rx_scale_context_alloc(enp, type, num_queues, table_nentries,
97 : : rss_contextp);
98 [ # # ]: 0 : if (rc != 0)
99 : 0 : goto fail1;
100 : :
101 : : return (0);
102 : :
103 : : fail1:
104 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
105 : 0 : return (rc);
106 : : }
107 : :
108 : : __checkReturn efx_rc_t
109 : 0 : 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 : 0 : rc = ef10_rx_scale_context_free(enp, rss_context);
116 [ # # ]: 0 : if (rc != 0)
117 : 0 : goto fail1;
118 : :
119 : : return (0);
120 : :
121 : : fail1:
122 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
123 : 0 : return (rc);
124 : : }
125 : :
126 : : __checkReturn efx_rc_t
127 : 0 : 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 : 0 : rc = ef10_rx_scale_mode_set(enp, rss_context, alg, type, insert);
137 [ # # ]: 0 : if (rc != 0)
138 : 0 : goto fail1;
139 : :
140 : : return (0);
141 : :
142 : : fail1:
143 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
144 : 0 : return (rc);
145 : : }
146 : :
147 : : __checkReturn efx_rc_t
148 : 0 : 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 : 0 : rc = ef10_rx_scale_key_set(enp, rss_context, key, n);
157 [ # # ]: 0 : if (rc != 0)
158 : 0 : goto fail1;
159 : :
160 : : return (0);
161 : :
162 : : fail1:
163 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
164 : 0 : return (rc);
165 : : }
166 : :
167 : : __checkReturn efx_rc_t
168 : 0 : 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 : 0 : rc = ef10_rx_scale_tbl_set(enp, rss_context, table, nentries);
177 [ # # ]: 0 : if (rc != 0)
178 : 0 : goto fail1;
179 : :
180 : : return (0);
181 : :
182 : : fail1:
183 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
184 : 0 : return (rc);
185 : : }
186 : :
187 : : __checkReturn uint32_t
188 : 0 : 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 : 0 : return (ENOTSUP);
198 : : }
199 : :
200 : : #endif /* EFSYS_OPT_RX_SCALE */
201 : :
202 : : __checkReturn efx_rc_t
203 : 0 : 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 : 0 : return (ENOTSUP);
213 : : }
214 : :
215 : : void
216 : 0 : 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 : 0 : EFSYS_ASSERT(B_FALSE);
229 : : }
230 : :
231 : : void
232 : 0 : 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 : 0 : EFSYS_ASSERT(B_FALSE);
242 : : }
243 : :
244 : : __checkReturn efx_rc_t
245 : 0 : rhead_rx_qflush(
246 : : __in efx_rxq_t *erp)
247 : : {
248 : 0 : efx_nic_t *enp = erp->er_enp;
249 : : efx_rc_t rc;
250 : :
251 [ # # ]: 0 : if ((rc = efx_mcdi_fini_rxq(enp, erp->er_index)) != 0)
252 : 0 : 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 : 0 : return (rc);
267 : : }
268 : :
269 : : void
270 : 0 : rhead_rx_qenable(
271 : : __in efx_rxq_t *erp)
272 : : {
273 : : _NOTE(ARGUNUSED(erp))
274 : 0 : }
275 : :
276 : : static __checkReturn efx_rc_t
277 : 0 : 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 : 0 : 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 : 0 : req.emr_cmd = MC_CMD_GET_RX_PREFIX_ID;
291 : 0 : req.emr_in_buf = payload;
292 : 0 : req.emr_in_length = MC_CMD_GET_RX_PREFIX_ID_IN_LEN;
293 : 0 : req.emr_out_buf = payload;
294 : 0 : req.emr_out_length = MC_CMD_GET_RX_PREFIX_ID_OUT_LENMAX;
295 : :
296 : 0 : MCDI_IN_SET_DWORD(req, GET_RX_PREFIX_ID_IN_FIELDS, mcdi_fields_mask);
297 : :
298 : 0 : efx_mcdi_execute(enp, &req);
299 : :
300 [ # # ]: 0 : if (req.emr_rc != 0) {
301 : : rc = req.emr_rc;
302 : 0 : goto fail1;
303 : : }
304 : :
305 [ # # ]: 0 : if (req.emr_out_length_used < MC_CMD_GET_RX_PREFIX_ID_OUT_LENMIN) {
306 : : rc = EMSGSIZE;
307 : 0 : goto fail2;
308 : : }
309 : :
310 : 0 : num = MCDI_OUT_DWORD(req, GET_RX_PREFIX_ID_OUT_NUM_RX_PREFIX_IDS);
311 : :
312 [ # # ]: 0 : if (req.emr_out_length_used != MC_CMD_GET_RX_PREFIX_ID_OUT_LEN(num)) {
313 : : rc = EMSGSIZE;
314 : 0 : goto fail3;
315 : : }
316 : :
317 : 0 : *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 : 0 : memcpy(idsp,
322 : 0 : MCDI_OUT2(req, uint32_t, GET_RX_PREFIX_ID_OUT_RX_PREFIX_ID),
323 : 0 : *nids * sizeof (idsp[0]));
324 : :
325 : 0 : 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
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 : 0 : if (mcdi_idx >= EFX_ARRAY_SIZE(efx_mcdi_to_rx_prefix_field))
359 : : return (EFX_RX_PREFIX_NFIELDS);
360 : :
361 : 0 : return (efx_mcdi_to_rx_prefix_field[mcdi_idx]);
362 : : }
363 : :
364 : : static __checkReturn int
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 : 0 : return (efx_rx_prefix_field_to_mcdi[field]);
398 : : }
399 : :
400 : : static __checkReturn efx_rc_t
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 [ # # ]: 0 : for (i = 0; i < EFX_RX_PREFIX_NFIELDS; ++i) {
409 [ # # ]: 0 : if (fields_mask & (1U << i)) {
410 : : int mcdi_field = efx_rx_prefix_field_map_to_mcdi(i);
411 : :
412 [ # # ]: 0 : if (mcdi_field < 0)
413 : : return (EINVAL);
414 : :
415 : 0 : 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
424 : 0 : 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 : 0 : 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 : 0 : req.emr_cmd = MC_CMD_QUERY_RX_PREFIX_ID;
442 : 0 : req.emr_in_buf = payload;
443 : 0 : req.emr_in_length = MC_CMD_QUERY_RX_PREFIX_ID_IN_LEN;
444 : 0 : req.emr_out_buf = payload;
445 : 0 : req.emr_out_length = MC_CMD_QUERY_RX_PREFIX_ID_OUT_LENMAX;
446 : :
447 : 0 : MCDI_IN_SET_DWORD(req, QUERY_RX_PREFIX_ID_IN_RX_PREFIX_ID, prefix_id);
448 : :
449 : 0 : efx_mcdi_execute(enp, &req);
450 : :
451 [ # # ]: 0 : if (req.emr_rc != 0) {
452 : : rc = req.emr_rc;
453 : 0 : goto fail1;
454 : : }
455 : :
456 [ # # ]: 0 : if (req.emr_out_length_used < MC_CMD_QUERY_RX_PREFIX_ID_OUT_LENMIN) {
457 : : rc = EMSGSIZE;
458 : 0 : goto fail2;
459 : : }
460 : :
461 [ # # ]: 0 : 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 : 0 : 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 : 0 : response_len = req.emr_out_length_used -
470 : : MC_CMD_QUERY_RX_PREFIX_ID_OUT_RESPONSE_OFST;
471 : :
472 [ # # ]: 0 : if (response_len < RX_PREFIX_FIXED_RESPONSE_LENMIN) {
473 : : rc = EMSGSIZE;
474 : 0 : 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 : 0 : erplp->erpl_id = prefix_id;
481 : 0 : erplp->erpl_length =
482 : 0 : EFX_DWORD_FIELD(*resp, RX_PREFIX_FIXED_RESPONSE_PREFIX_LENGTH_BYTES);
483 : 0 : num_fields =
484 : 0 : EFX_DWORD_FIELD(*resp, RX_PREFIX_FIXED_RESPONSE_FIELD_COUNT);
485 : :
486 [ # # ]: 0 : if (response_len < RX_PREFIX_FIXED_RESPONSE_LEN(num_fields)) {
487 : : rc = EMSGSIZE;
488 : 0 : goto fail5;
489 : : }
490 : :
491 : 0 : finfo = (const efx_dword_t *)((const uint8_t *)resp +
492 : : RX_PREFIX_FIXED_RESPONSE_FIELDS_OFST);
493 : :
494 [ # # ]: 0 : for (i = 0; i < num_fields; ++i, ++finfo) {
495 [ # # ]: 0 : mcdi_field = EFX_DWORD_FIELD(*finfo, RX_PREFIX_FIELD_INFO_TYPE);
496 : :
497 : : field = efx_mcdi_rx_prefix_field_map(mcdi_field);
498 [ # # ]: 0 : if (field >= EFX_RX_PREFIX_NFIELDS)
499 : 0 : continue;
500 : :
501 : 0 : erplp->erpl_fields[field].erpfi_offset_bits =
502 : : EFX_DWORD_FIELD(*finfo, RX_PREFIX_FIELD_INFO_OFFSET_BITS);
503 : 0 : erplp->erpl_fields[field].erpfi_width_bits =
504 : 0 : 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
524 : 0 : 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 : 0 : 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 [ # # ]: 0 : if (rc != 0)
538 : 0 : goto fail1;
539 : :
540 : : memset(erplp, 0, sizeof (*erplp));
541 : :
542 : 0 : rc = efx_mcdi_get_rx_prefix_ids(enp, mcdi_fields_mask,
543 : : EFX_ARRAY_SIZE(prefix_ids), &num, prefix_ids);
544 [ # # ]: 0 : if (rc == ENOTSUP) {
545 : : /* Not supported MCDI, use default prefix ID */
546 : 0 : *erplp = rhead_default_rx_prefix_layout;
547 : 0 : goto done;
548 : : }
549 [ # # ]: 0 : if (rc != 0)
550 : 0 : goto fail2;
551 : :
552 [ # # ]: 0 : if (num == 0) {
553 : : rc = ENOTSUP;
554 : 0 : goto fail3;
555 : : }
556 : :
557 [ # # ]: 0 : for (i = 0; i < num; ++i) {
558 : 0 : rc = efx_mcdi_query_rx_prefix_id(enp, prefix_ids[i], &erpl);
559 [ # # ]: 0 : if (rc != 0)
560 : 0 : goto fail4;
561 : :
562 : : /* Choose the smallest prefix which meets our requirements */
563 [ # # # # ]: 0 : if (i == 0 || erpl.erpl_length < erplp->erpl_length)
564 : 0 : *erplp = erpl;
565 : : }
566 : :
567 : 0 : 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
583 : 0 : 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 : 0 : 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 [ # # ]: 0 : EFSYS_ASSERT3U(label, <, EFX_EV_RX_NLABELS);
607 : :
608 : : memset(¶ms, 0, sizeof (params));
609 : :
610 [ # # ]: 0 : switch (type) {
611 : 0 : case EFX_RXQ_TYPE_DEFAULT:
612 [ # # ]: 0 : if (type_data == NULL) {
613 : : rc = EINVAL;
614 : 0 : goto fail1;
615 : : }
616 : 0 : params.buf_size = type_data->ertd_default.ed_buf_size;
617 : : break;
618 : 0 : default:
619 : : rc = ENOTSUP;
620 : 0 : goto fail2;
621 : : }
622 : :
623 : : /* Scatter can only be disabled if the firmware supports doing so */
624 [ # # ]: 0 : if (flags & EFX_RXQ_FLAG_SCATTER)
625 : : params.disable_scatter = B_FALSE;
626 : : else
627 : 0 : params.disable_scatter = encp->enc_rx_disable_scatter_supported;
628 : :
629 [ # # ]: 0 : 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 [ # # ]: 0 : if (flags & EFX_RXQ_FLAG_INGRESS_MPORT)
635 : 0 : fields_mask |= 1U << EFX_RX_PREFIX_FIELD_INGRESS_MPORT;
636 : :
637 [ # # ]: 0 : if (flags & EFX_RXQ_FLAG_USER_MARK)
638 : 0 : fields_mask |= 1U << EFX_RX_PREFIX_FIELD_USER_MARK;
639 : :
640 [ # # ]: 0 : if (flags & EFX_RXQ_FLAG_USER_FLAG)
641 : 0 : fields_mask |= 1U << EFX_RX_PREFIX_FIELD_USER_FLAG;
642 : :
643 [ # # ]: 0 : if (flags & EFX_RXQ_FLAG_VLAN_STRIPPED_TCI)
644 : 0 : 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 : 0 : fields_mask |= 1U << EFX_RX_PREFIX_FIELD_LENGTH;
651 [ # # ]: 0 : if ((rc = rhead_rx_choose_prefix_id(enp, fields_mask, &erpl)) != 0)
652 : 0 : goto fail3;
653 : :
654 : 0 : 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 [ # # ]: 0 : if ((rc = efx_mcdi_init_rxq(enp, ndescs, eep, label, index,
663 : : esmp, ¶ms)) != 0)
664 : 0 : goto fail4;
665 : :
666 : 0 : erp->er_eep = eep;
667 : 0 : erp->er_label = label;
668 : 0 : erp->er_buf_size = params.buf_size;
669 : 0 : erp->er_prefix_layout = erpl;
670 : :
671 : 0 : 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
686 : 0 : rhead_rx_qdestroy(
687 : : __in efx_rxq_t *erp)
688 : : {
689 : : _NOTE(ARGUNUSED(erp))
690 : : /* Nothing to do here */
691 : 0 : }
692 : :
693 : : #endif /* EFSYS_OPT_RIVERHEAD */
|