common/sfc_efx/base: free Rx queue structure in generic code
[dpdk.git] / drivers / common / sfc_efx / base / ef10_rx.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Copyright(c) 2019-2020 Xilinx, Inc.
4  * Copyright(c) 2012-2019 Solarflare Communications Inc.
5  */
6
7 #include "efx.h"
8 #include "efx_impl.h"
9
10
11 #if EFX_OPTS_EF10()
12
13 #if EFSYS_OPT_RX_SCALE
14 static  __checkReturn   efx_rc_t
15 efx_mcdi_rss_context_alloc(
16         __in            efx_nic_t *enp,
17         __in            efx_rx_scale_context_type_t type,
18         __in            uint32_t num_queues,
19         __out           uint32_t *rss_contextp)
20 {
21         efx_mcdi_req_t req;
22         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_RSS_CONTEXT_ALLOC_IN_LEN,
23                 MC_CMD_RSS_CONTEXT_ALLOC_OUT_LEN);
24         uint32_t rss_context;
25         uint32_t context_type;
26         efx_rc_t rc;
27
28         if (num_queues > EFX_MAXRSS) {
29                 rc = EINVAL;
30                 goto fail1;
31         }
32
33         switch (type) {
34         case EFX_RX_SCALE_EXCLUSIVE:
35                 context_type = MC_CMD_RSS_CONTEXT_ALLOC_IN_TYPE_EXCLUSIVE;
36                 break;
37         case EFX_RX_SCALE_SHARED:
38                 context_type = MC_CMD_RSS_CONTEXT_ALLOC_IN_TYPE_SHARED;
39                 break;
40         default:
41                 rc = EINVAL;
42                 goto fail2;
43         }
44
45         req.emr_cmd = MC_CMD_RSS_CONTEXT_ALLOC;
46         req.emr_in_buf = payload;
47         req.emr_in_length = MC_CMD_RSS_CONTEXT_ALLOC_IN_LEN;
48         req.emr_out_buf = payload;
49         req.emr_out_length = MC_CMD_RSS_CONTEXT_ALLOC_OUT_LEN;
50
51         MCDI_IN_SET_DWORD(req, RSS_CONTEXT_ALLOC_IN_UPSTREAM_PORT_ID,
52                 enp->en_vport_id);
53         MCDI_IN_SET_DWORD(req, RSS_CONTEXT_ALLOC_IN_TYPE, context_type);
54
55         /*
56          * For exclusive contexts, NUM_QUEUES is only used to validate
57          * indirection table offsets.
58          * For shared contexts, the provided context will spread traffic over
59          * NUM_QUEUES many queues.
60          */
61         MCDI_IN_SET_DWORD(req, RSS_CONTEXT_ALLOC_IN_NUM_QUEUES, num_queues);
62
63         efx_mcdi_execute(enp, &req);
64
65         if (req.emr_rc != 0) {
66                 rc = req.emr_rc;
67                 goto fail3;
68         }
69
70         if (req.emr_out_length_used < MC_CMD_RSS_CONTEXT_ALLOC_OUT_LEN) {
71                 rc = EMSGSIZE;
72                 goto fail4;
73         }
74
75         rss_context = MCDI_OUT_DWORD(req, RSS_CONTEXT_ALLOC_OUT_RSS_CONTEXT_ID);
76         if (rss_context == EF10_RSS_CONTEXT_INVALID) {
77                 rc = ENOENT;
78                 goto fail5;
79         }
80
81         *rss_contextp = rss_context;
82
83         return (0);
84
85 fail5:
86         EFSYS_PROBE(fail5);
87 fail4:
88         EFSYS_PROBE(fail4);
89 fail3:
90         EFSYS_PROBE(fail3);
91 fail2:
92         EFSYS_PROBE(fail2);
93 fail1:
94         EFSYS_PROBE1(fail1, efx_rc_t, rc);
95
96         return (rc);
97 }
98 #endif /* EFSYS_OPT_RX_SCALE */
99
100 #if EFSYS_OPT_RX_SCALE
101 static                  efx_rc_t
102 efx_mcdi_rss_context_free(
103         __in            efx_nic_t *enp,
104         __in            uint32_t rss_context)
105 {
106         efx_mcdi_req_t req;
107         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_RSS_CONTEXT_FREE_IN_LEN,
108                 MC_CMD_RSS_CONTEXT_FREE_OUT_LEN);
109         efx_rc_t rc;
110
111         if (rss_context == EF10_RSS_CONTEXT_INVALID) {
112                 rc = EINVAL;
113                 goto fail1;
114         }
115
116         req.emr_cmd = MC_CMD_RSS_CONTEXT_FREE;
117         req.emr_in_buf = payload;
118         req.emr_in_length = MC_CMD_RSS_CONTEXT_FREE_IN_LEN;
119         req.emr_out_buf = payload;
120         req.emr_out_length = MC_CMD_RSS_CONTEXT_FREE_OUT_LEN;
121
122         MCDI_IN_SET_DWORD(req, RSS_CONTEXT_FREE_IN_RSS_CONTEXT_ID, rss_context);
123
124         efx_mcdi_execute_quiet(enp, &req);
125
126         if (req.emr_rc != 0) {
127                 rc = req.emr_rc;
128                 goto fail2;
129         }
130
131         return (0);
132
133 fail2:
134         EFSYS_PROBE(fail2);
135 fail1:
136         EFSYS_PROBE1(fail1, efx_rc_t, rc);
137
138         return (rc);
139 }
140 #endif /* EFSYS_OPT_RX_SCALE */
141
142 #if EFSYS_OPT_RX_SCALE
143 static                  efx_rc_t
144 efx_mcdi_rss_context_set_flags(
145         __in            efx_nic_t *enp,
146         __in            uint32_t rss_context,
147         __in            efx_rx_hash_type_t type)
148 {
149         efx_nic_cfg_t *encp = &enp->en_nic_cfg;
150         efx_mcdi_req_t req;
151         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_LEN,
152                 MC_CMD_RSS_CONTEXT_SET_FLAGS_OUT_LEN);
153         efx_rc_t rc;
154
155         EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV4_TCP_LBN ==
156                     MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV4_RSS_MODE_LBN);
157         EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV4_TCP_WIDTH ==
158                     MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV4_RSS_MODE_WIDTH);
159         EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV4_LBN ==
160                     MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV4_RSS_MODE_LBN);
161         EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV4_WIDTH ==
162                     MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV4_RSS_MODE_WIDTH);
163         EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV6_TCP_LBN ==
164                     MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV6_RSS_MODE_LBN);
165         EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV6_TCP_WIDTH ==
166                     MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV6_RSS_MODE_WIDTH);
167         EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV6_LBN ==
168                     MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV6_RSS_MODE_LBN);
169         EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV6_WIDTH ==
170                     MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV6_RSS_MODE_WIDTH);
171
172         if (rss_context == EF10_RSS_CONTEXT_INVALID) {
173                 rc = EINVAL;
174                 goto fail1;
175         }
176
177         req.emr_cmd = MC_CMD_RSS_CONTEXT_SET_FLAGS;
178         req.emr_in_buf = payload;
179         req.emr_in_length = MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_LEN;
180         req.emr_out_buf = payload;
181         req.emr_out_length = MC_CMD_RSS_CONTEXT_SET_FLAGS_OUT_LEN;
182
183         MCDI_IN_SET_DWORD(req, RSS_CONTEXT_SET_FLAGS_IN_RSS_CONTEXT_ID,
184             rss_context);
185
186         /*
187          * If the firmware lacks support for additional modes, RSS_MODE
188          * fields must contain zeros, otherwise the operation will fail.
189          */
190         if (encp->enc_rx_scale_additional_modes_supported == B_FALSE)
191                 type &= EFX_RX_HASH_LEGACY_MASK;
192
193         MCDI_IN_POPULATE_DWORD_10(req, RSS_CONTEXT_SET_FLAGS_IN_FLAGS,
194             RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_IPV4_EN,
195             (type & EFX_RX_HASH_IPV4) ? 1 : 0,
196             RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_TCPV4_EN,
197             (type & EFX_RX_HASH_TCPIPV4) ? 1 : 0,
198             RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_IPV6_EN,
199             (type & EFX_RX_HASH_IPV6) ? 1 : 0,
200             RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_TCPV6_EN,
201             (type & EFX_RX_HASH_TCPIPV6) ? 1 : 0,
202             RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV4_RSS_MODE,
203             (type >> EFX_RX_CLASS_IPV4_TCP_LBN) &
204             EFX_MASK32(EFX_RX_CLASS_IPV4_TCP),
205             RSS_CONTEXT_SET_FLAGS_IN_UDP_IPV4_RSS_MODE,
206             (type >> EFX_RX_CLASS_IPV4_UDP_LBN) &
207             EFX_MASK32(EFX_RX_CLASS_IPV4_UDP),
208             RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV4_RSS_MODE,
209             (type >> EFX_RX_CLASS_IPV4_LBN) & EFX_MASK32(EFX_RX_CLASS_IPV4),
210             RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV6_RSS_MODE,
211             (type >> EFX_RX_CLASS_IPV6_TCP_LBN) &
212             EFX_MASK32(EFX_RX_CLASS_IPV6_TCP),
213             RSS_CONTEXT_SET_FLAGS_IN_UDP_IPV6_RSS_MODE,
214             (type >> EFX_RX_CLASS_IPV6_UDP_LBN) &
215             EFX_MASK32(EFX_RX_CLASS_IPV6_UDP),
216             RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV6_RSS_MODE,
217             (type >> EFX_RX_CLASS_IPV6_LBN) & EFX_MASK32(EFX_RX_CLASS_IPV6));
218
219         efx_mcdi_execute(enp, &req);
220
221         if (req.emr_rc != 0) {
222                 rc = req.emr_rc;
223                 goto fail2;
224         }
225
226         return (0);
227
228 fail2:
229         EFSYS_PROBE(fail2);
230 fail1:
231         EFSYS_PROBE1(fail1, efx_rc_t, rc);
232
233         return (rc);
234 }
235 #endif /* EFSYS_OPT_RX_SCALE */
236
237 #if EFSYS_OPT_RX_SCALE
238 static                  efx_rc_t
239 efx_mcdi_rss_context_set_key(
240         __in            efx_nic_t *enp,
241         __in            uint32_t rss_context,
242         __in_ecount(n)  uint8_t *key,
243         __in            size_t n)
244 {
245         efx_mcdi_req_t req;
246         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_RSS_CONTEXT_SET_KEY_IN_LEN,
247                 MC_CMD_RSS_CONTEXT_SET_KEY_OUT_LEN);
248         efx_rc_t rc;
249
250         if (rss_context == EF10_RSS_CONTEXT_INVALID) {
251                 rc = EINVAL;
252                 goto fail1;
253         }
254
255         req.emr_cmd = MC_CMD_RSS_CONTEXT_SET_KEY;
256         req.emr_in_buf = payload;
257         req.emr_in_length = MC_CMD_RSS_CONTEXT_SET_KEY_IN_LEN;
258         req.emr_out_buf = payload;
259         req.emr_out_length = MC_CMD_RSS_CONTEXT_SET_KEY_OUT_LEN;
260
261         MCDI_IN_SET_DWORD(req, RSS_CONTEXT_SET_KEY_IN_RSS_CONTEXT_ID,
262             rss_context);
263
264         EFSYS_ASSERT3U(n, ==, MC_CMD_RSS_CONTEXT_SET_KEY_IN_TOEPLITZ_KEY_LEN);
265         if (n != MC_CMD_RSS_CONTEXT_SET_KEY_IN_TOEPLITZ_KEY_LEN) {
266                 rc = EINVAL;
267                 goto fail2;
268         }
269
270         memcpy(MCDI_IN2(req, uint8_t, RSS_CONTEXT_SET_KEY_IN_TOEPLITZ_KEY),
271             key, n);
272
273         efx_mcdi_execute(enp, &req);
274
275         if (req.emr_rc != 0) {
276                 rc = req.emr_rc;
277                 goto fail3;
278         }
279
280         return (0);
281
282 fail3:
283         EFSYS_PROBE(fail3);
284 fail2:
285         EFSYS_PROBE(fail2);
286 fail1:
287         EFSYS_PROBE1(fail1, efx_rc_t, rc);
288
289         return (rc);
290 }
291 #endif /* EFSYS_OPT_RX_SCALE */
292
293 #if EFSYS_OPT_RX_SCALE
294 static                  efx_rc_t
295 efx_mcdi_rss_context_set_table(
296         __in            efx_nic_t *enp,
297         __in            uint32_t rss_context,
298         __in_ecount(n)  unsigned int *table,
299         __in            size_t n)
300 {
301         efx_mcdi_req_t req;
302         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_RSS_CONTEXT_SET_TABLE_IN_LEN,
303                 MC_CMD_RSS_CONTEXT_SET_TABLE_OUT_LEN);
304         uint8_t *req_table;
305         int i, rc;
306
307         if (rss_context == EF10_RSS_CONTEXT_INVALID) {
308                 rc = EINVAL;
309                 goto fail1;
310         }
311
312         req.emr_cmd = MC_CMD_RSS_CONTEXT_SET_TABLE;
313         req.emr_in_buf = payload;
314         req.emr_in_length = MC_CMD_RSS_CONTEXT_SET_TABLE_IN_LEN;
315         req.emr_out_buf = payload;
316         req.emr_out_length = MC_CMD_RSS_CONTEXT_SET_TABLE_OUT_LEN;
317
318         MCDI_IN_SET_DWORD(req, RSS_CONTEXT_SET_TABLE_IN_RSS_CONTEXT_ID,
319             rss_context);
320
321         req_table =
322             MCDI_IN2(req, uint8_t, RSS_CONTEXT_SET_TABLE_IN_INDIRECTION_TABLE);
323
324         for (i = 0;
325             i < MC_CMD_RSS_CONTEXT_SET_TABLE_IN_INDIRECTION_TABLE_LEN;
326             i++) {
327                 req_table[i] = (n > 0) ? (uint8_t)table[i % n] : 0;
328         }
329
330         efx_mcdi_execute(enp, &req);
331
332         if (req.emr_rc != 0) {
333                 rc = req.emr_rc;
334                 goto fail2;
335         }
336
337         return (0);
338
339 fail2:
340         EFSYS_PROBE(fail2);
341 fail1:
342         EFSYS_PROBE1(fail1, efx_rc_t, rc);
343
344         return (rc);
345 }
346 #endif /* EFSYS_OPT_RX_SCALE */
347
348
349         __checkReturn   efx_rc_t
350 ef10_rx_init(
351         __in            efx_nic_t *enp)
352 {
353 #if EFSYS_OPT_RX_SCALE
354
355         if (efx_mcdi_rss_context_alloc(enp, EFX_RX_SCALE_EXCLUSIVE, EFX_MAXRSS,
356                 &enp->en_rss_context) == 0) {
357                 /*
358                  * Allocated an exclusive RSS context, which allows both the
359                  * indirection table and key to be modified.
360                  */
361                 enp->en_rss_context_type = EFX_RX_SCALE_EXCLUSIVE;
362                 enp->en_hash_support = EFX_RX_HASH_AVAILABLE;
363         } else {
364                 /*
365                  * Failed to allocate an exclusive RSS context. Continue
366                  * operation without support for RSS. The pseudo-header in
367                  * received packets will not contain a Toeplitz hash value.
368                  */
369                 enp->en_rss_context_type = EFX_RX_SCALE_UNAVAILABLE;
370                 enp->en_hash_support = EFX_RX_HASH_UNAVAILABLE;
371         }
372
373 #endif /* EFSYS_OPT_RX_SCALE */
374
375         return (0);
376 }
377
378 #if EFSYS_OPT_RX_SCATTER
379         __checkReturn   efx_rc_t
380 ef10_rx_scatter_enable(
381         __in            efx_nic_t *enp,
382         __in            unsigned int buf_size)
383 {
384         _NOTE(ARGUNUSED(enp, buf_size))
385         return (0);
386 }
387 #endif  /* EFSYS_OPT_RX_SCATTER */
388
389 #if EFSYS_OPT_RX_SCALE
390         __checkReturn   efx_rc_t
391 ef10_rx_scale_context_alloc(
392         __in            efx_nic_t *enp,
393         __in            efx_rx_scale_context_type_t type,
394         __in            uint32_t num_queues,
395         __out           uint32_t *rss_contextp)
396 {
397         efx_rc_t rc;
398
399         rc = efx_mcdi_rss_context_alloc(enp, type, num_queues, rss_contextp);
400         if (rc != 0)
401                 goto fail1;
402
403         return (0);
404
405 fail1:
406         EFSYS_PROBE1(fail1, efx_rc_t, rc);
407         return (rc);
408 }
409 #endif /* EFSYS_OPT_RX_SCALE */
410
411 #if EFSYS_OPT_RX_SCALE
412         __checkReturn   efx_rc_t
413 ef10_rx_scale_context_free(
414         __in            efx_nic_t *enp,
415         __in            uint32_t rss_context)
416 {
417         efx_rc_t rc;
418
419         rc = efx_mcdi_rss_context_free(enp, rss_context);
420         if (rc != 0)
421                 goto fail1;
422
423         return (0);
424
425 fail1:
426         EFSYS_PROBE1(fail1, efx_rc_t, rc);
427         return (rc);
428 }
429 #endif /* EFSYS_OPT_RX_SCALE */
430
431 #if EFSYS_OPT_RX_SCALE
432         __checkReturn   efx_rc_t
433 ef10_rx_scale_mode_set(
434         __in            efx_nic_t *enp,
435         __in            uint32_t rss_context,
436         __in            efx_rx_hash_alg_t alg,
437         __in            efx_rx_hash_type_t type,
438         __in            boolean_t insert)
439 {
440         efx_nic_cfg_t *encp = &enp->en_nic_cfg;
441         efx_rc_t rc;
442
443         EFSYS_ASSERT3U(insert, ==, B_TRUE);
444
445         if ((encp->enc_rx_scale_hash_alg_mask & (1U << alg)) == 0 ||
446             insert == B_FALSE) {
447                 rc = EINVAL;
448                 goto fail1;
449         }
450
451         if (rss_context == EFX_RSS_CONTEXT_DEFAULT) {
452                 if (enp->en_rss_context_type == EFX_RX_SCALE_UNAVAILABLE) {
453                         rc = ENOTSUP;
454                         goto fail2;
455                 }
456                 rss_context = enp->en_rss_context;
457         }
458
459         if ((rc = efx_mcdi_rss_context_set_flags(enp,
460                     rss_context, type)) != 0)
461                 goto fail3;
462
463         return (0);
464
465 fail3:
466         EFSYS_PROBE(fail3);
467 fail2:
468         EFSYS_PROBE(fail2);
469 fail1:
470         EFSYS_PROBE1(fail1, efx_rc_t, rc);
471
472         return (rc);
473 }
474 #endif /* EFSYS_OPT_RX_SCALE */
475
476 #if EFSYS_OPT_RX_SCALE
477         __checkReturn   efx_rc_t
478 ef10_rx_scale_key_set(
479         __in            efx_nic_t *enp,
480         __in            uint32_t rss_context,
481         __in_ecount(n)  uint8_t *key,
482         __in            size_t n)
483 {
484         efx_rc_t rc;
485
486         EFX_STATIC_ASSERT(EFX_RSS_KEY_SIZE ==
487             MC_CMD_RSS_CONTEXT_SET_KEY_IN_TOEPLITZ_KEY_LEN);
488
489         if (rss_context == EFX_RSS_CONTEXT_DEFAULT) {
490                 if (enp->en_rss_context_type == EFX_RX_SCALE_UNAVAILABLE) {
491                         rc = ENOTSUP;
492                         goto fail1;
493                 }
494                 rss_context = enp->en_rss_context;
495         }
496
497         if ((rc = efx_mcdi_rss_context_set_key(enp, rss_context, key, n)) != 0)
498                 goto fail2;
499
500         return (0);
501
502 fail2:
503         EFSYS_PROBE(fail2);
504 fail1:
505         EFSYS_PROBE1(fail1, efx_rc_t, rc);
506
507         return (rc);
508 }
509 #endif /* EFSYS_OPT_RX_SCALE */
510
511 #if EFSYS_OPT_RX_SCALE
512         __checkReturn   efx_rc_t
513 ef10_rx_scale_tbl_set(
514         __in            efx_nic_t *enp,
515         __in            uint32_t rss_context,
516         __in_ecount(n)  unsigned int *table,
517         __in            size_t n)
518 {
519         efx_rc_t rc;
520
521
522         if (rss_context == EFX_RSS_CONTEXT_DEFAULT) {
523                 if (enp->en_rss_context_type == EFX_RX_SCALE_UNAVAILABLE) {
524                         rc = ENOTSUP;
525                         goto fail1;
526                 }
527                 rss_context = enp->en_rss_context;
528         }
529
530         if ((rc = efx_mcdi_rss_context_set_table(enp,
531                     rss_context, table, n)) != 0)
532                 goto fail2;
533
534         return (0);
535
536 fail2:
537         EFSYS_PROBE(fail2);
538 fail1:
539         EFSYS_PROBE1(fail1, efx_rc_t, rc);
540
541         return (rc);
542 }
543 #endif /* EFSYS_OPT_RX_SCALE */
544
545
546 /*
547  * EF10 RX pseudo-header
548  * ---------------------
549  *
550  * Receive packets are prefixed by an (optional) 14 byte pseudo-header:
551  *
552  *  +00: Toeplitz hash value.
553  *       (32bit little-endian)
554  *  +04: Outer VLAN tag. Zero if the packet did not have an outer VLAN tag.
555  *       (16bit big-endian)
556  *  +06: Inner VLAN tag. Zero if the packet did not have an inner VLAN tag.
557  *       (16bit big-endian)
558  *  +08: Packet Length. Zero if the RX datapath was in cut-through mode.
559  *       (16bit little-endian)
560  *  +10: MAC timestamp. Zero if timestamping is not enabled.
561  *       (32bit little-endian)
562  *
563  * See "The RX Pseudo-header" in SF-109306-TC.
564  */
565
566         __checkReturn   efx_rc_t
567 ef10_rx_prefix_pktlen(
568         __in            efx_nic_t *enp,
569         __in            uint8_t *buffer,
570         __out           uint16_t *lengthp)
571 {
572         _NOTE(ARGUNUSED(enp))
573
574         /*
575          * The RX pseudo-header contains the packet length, excluding the
576          * pseudo-header. If the hardware receive datapath was operating in
577          * cut-through mode then the length in the RX pseudo-header will be
578          * zero, and the packet length must be obtained from the DMA length
579          * reported in the RX event.
580          */
581         *lengthp = buffer[8] | (buffer[9] << 8);
582         return (0);
583 }
584
585 #if EFSYS_OPT_RX_SCALE
586         __checkReturn   uint32_t
587 ef10_rx_prefix_hash(
588         __in            efx_nic_t *enp,
589         __in            efx_rx_hash_alg_t func,
590         __in            uint8_t *buffer)
591 {
592         _NOTE(ARGUNUSED(enp))
593
594         switch (func) {
595         case EFX_RX_HASHALG_PACKED_STREAM:
596         case EFX_RX_HASHALG_TOEPLITZ:
597                 return (buffer[0] |
598                     (buffer[1] << 8) |
599                     (buffer[2] << 16) |
600                     (buffer[3] << 24));
601
602         default:
603                 EFSYS_ASSERT(0);
604                 return (0);
605         }
606 }
607 #endif /* EFSYS_OPT_RX_SCALE */
608
609 #if EFSYS_OPT_RX_PACKED_STREAM
610 /*
611  * Fake length for RXQ descriptors in packed stream mode
612  * to make hardware happy
613  */
614 #define EFX_RXQ_PACKED_STREAM_FAKE_BUF_SIZE 32
615 #endif
616
617                                 void
618 ef10_rx_qpost(
619         __in                    efx_rxq_t *erp,
620         __in_ecount(ndescs)     efsys_dma_addr_t *addrp,
621         __in                    size_t size,
622         __in                    unsigned int ndescs,
623         __in                    unsigned int completed,
624         __in                    unsigned int added)
625 {
626         efx_qword_t qword;
627         unsigned int i;
628         unsigned int offset;
629         unsigned int id;
630
631         _NOTE(ARGUNUSED(completed))
632
633 #if EFSYS_OPT_RX_PACKED_STREAM
634         /*
635          * Real size of the buffer does not fit into ESF_DZ_RX_KER_BYTE_CNT
636          * and equal to 0 after applying mask. Hardware does not like it.
637          */
638         if (erp->er_ev_qstate->eers_rx_packed_stream)
639                 size = EFX_RXQ_PACKED_STREAM_FAKE_BUF_SIZE;
640 #endif
641
642         /* The client driver must not overfill the queue */
643         EFSYS_ASSERT3U(added - completed + ndescs, <=,
644             EFX_RXQ_LIMIT(erp->er_mask + 1));
645
646         id = added & (erp->er_mask);
647         for (i = 0; i < ndescs; i++) {
648                 EFSYS_PROBE4(rx_post, unsigned int, erp->er_index,
649                     unsigned int, id, efsys_dma_addr_t, addrp[i],
650                     size_t, size);
651
652                 EFX_POPULATE_QWORD_3(qword,
653                     ESF_DZ_RX_KER_BYTE_CNT, (uint32_t)(size),
654                     ESF_DZ_RX_KER_BUF_ADDR_DW0,
655                     (uint32_t)(addrp[i] & 0xffffffff),
656                     ESF_DZ_RX_KER_BUF_ADDR_DW1,
657                     (uint32_t)(addrp[i] >> 32));
658
659                 offset = id * sizeof (efx_qword_t);
660                 EFSYS_MEM_WRITEQ(erp->er_esmp, offset, &qword);
661
662                 id = (id + 1) & (erp->er_mask);
663         }
664 }
665
666                         void
667 ef10_rx_qpush(
668         __in    efx_rxq_t *erp,
669         __in    unsigned int added,
670         __inout unsigned int *pushedp)
671 {
672         efx_nic_t *enp = erp->er_enp;
673         unsigned int pushed = *pushedp;
674         uint32_t wptr;
675         efx_dword_t dword;
676
677         /* Hardware has alignment restriction for WPTR */
678         wptr = EFX_P2ALIGN(unsigned int, added, EF10_RX_WPTR_ALIGN);
679         if (pushed == wptr)
680                 return;
681
682         *pushedp = wptr;
683
684         /* Push the populated descriptors out */
685         wptr &= erp->er_mask;
686
687         EFX_POPULATE_DWORD_1(dword, ERF_DZ_RX_DESC_WPTR, wptr);
688
689         /* Guarantee ordering of memory (descriptors) and PIO (doorbell) */
690         EFX_DMA_SYNC_QUEUE_FOR_DEVICE(erp->er_esmp, erp->er_mask + 1,
691             wptr, pushed & erp->er_mask);
692         EFSYS_PIO_WRITE_BARRIER();
693         EFX_BAR_VI_WRITED(enp, ER_DZ_RX_DESC_UPD_REG,
694             erp->er_index, &dword, B_FALSE);
695 }
696
697 #if EFSYS_OPT_RX_PACKED_STREAM
698
699                         void
700 ef10_rx_qpush_ps_credits(
701         __in            efx_rxq_t *erp)
702 {
703         efx_nic_t *enp = erp->er_enp;
704         efx_dword_t dword;
705         efx_evq_rxq_state_t *rxq_state = erp->er_ev_qstate;
706         uint32_t credits;
707
708         EFSYS_ASSERT(rxq_state->eers_rx_packed_stream);
709
710         if (rxq_state->eers_rx_packed_stream_credits == 0)
711                 return;
712
713         /*
714          * It is a bug if we think that FW has utilized more
715          * credits than it is allowed to have (maximum). However,
716          * make sure that we do not credit more than maximum anyway.
717          */
718         credits = MIN(rxq_state->eers_rx_packed_stream_credits,
719             EFX_RX_PACKED_STREAM_MAX_CREDITS);
720         EFX_POPULATE_DWORD_3(dword,
721             ERF_DZ_RX_DESC_MAGIC_DOORBELL, 1,
722             ERF_DZ_RX_DESC_MAGIC_CMD,
723             ERE_DZ_RX_DESC_MAGIC_CMD_PS_CREDITS,
724             ERF_DZ_RX_DESC_MAGIC_DATA, credits);
725         EFX_BAR_VI_WRITED(enp, ER_DZ_RX_DESC_UPD_REG,
726             erp->er_index, &dword, B_FALSE);
727
728         rxq_state->eers_rx_packed_stream_credits = 0;
729 }
730
731 /*
732  * In accordance with SF-112241-TC the received data has the following layout:
733  *  - 8 byte pseudo-header which consist of:
734  *    - 4 byte little-endian timestamp
735  *    - 2 byte little-endian captured length in bytes
736  *    - 2 byte little-endian original packet length in bytes
737  *  - captured packet bytes
738  *  - optional padding to align to 64 bytes boundary
739  *  - 64 bytes scratch space for the host software
740  */
741         __checkReturn   uint8_t *
742 ef10_rx_qps_packet_info(
743         __in            efx_rxq_t *erp,
744         __in            uint8_t *buffer,
745         __in            uint32_t buffer_length,
746         __in            uint32_t current_offset,
747         __out           uint16_t *lengthp,
748         __out           uint32_t *next_offsetp,
749         __out           uint32_t *timestamp)
750 {
751         uint16_t buf_len;
752         uint8_t *pkt_start;
753         efx_qword_t *qwordp;
754         efx_evq_rxq_state_t *rxq_state = erp->er_ev_qstate;
755
756         EFSYS_ASSERT(rxq_state->eers_rx_packed_stream);
757
758         buffer += current_offset;
759         pkt_start = buffer + EFX_RX_PACKED_STREAM_RX_PREFIX_SIZE;
760
761         qwordp = (efx_qword_t *)buffer;
762         *timestamp = EFX_QWORD_FIELD(*qwordp, ES_DZ_PS_RX_PREFIX_TSTAMP);
763         *lengthp   = EFX_QWORD_FIELD(*qwordp, ES_DZ_PS_RX_PREFIX_ORIG_LEN);
764         buf_len    = EFX_QWORD_FIELD(*qwordp, ES_DZ_PS_RX_PREFIX_CAP_LEN);
765
766         buf_len = EFX_P2ROUNDUP(uint16_t,
767             buf_len + EFX_RX_PACKED_STREAM_RX_PREFIX_SIZE,
768             EFX_RX_PACKED_STREAM_ALIGNMENT);
769         *next_offsetp =
770             current_offset + buf_len + EFX_RX_PACKED_STREAM_ALIGNMENT;
771
772         EFSYS_ASSERT3U(*next_offsetp, <=, buffer_length);
773         EFSYS_ASSERT3U(current_offset + *lengthp, <, *next_offsetp);
774
775         if ((*next_offsetp ^ current_offset) &
776             EFX_RX_PACKED_STREAM_MEM_PER_CREDIT)
777                 rxq_state->eers_rx_packed_stream_credits++;
778
779         return (pkt_start);
780 }
781
782
783 #endif
784
785         __checkReturn   efx_rc_t
786 ef10_rx_qflush(
787         __in    efx_rxq_t *erp)
788 {
789         efx_nic_t *enp = erp->er_enp;
790         efx_rc_t rc;
791
792         if ((rc = efx_mcdi_fini_rxq(enp, erp->er_index)) != 0)
793                 goto fail1;
794
795         return (0);
796
797 fail1:
798         /*
799          * EALREADY is not an error, but indicates that the MC has rebooted and
800          * that the RXQ has already been destroyed. Callers need to know that
801          * the RXQ flush has completed to avoid waiting until timeout for a
802          * flush done event that will not be delivered.
803          */
804         if (rc != EALREADY)
805                 EFSYS_PROBE1(fail1, efx_rc_t, rc);
806
807         return (rc);
808 }
809
810                 void
811 ef10_rx_qenable(
812         __in    efx_rxq_t *erp)
813 {
814         /* FIXME */
815         _NOTE(ARGUNUSED(erp))
816         /* FIXME */
817 }
818
819         __checkReturn   efx_rc_t
820 ef10_rx_qcreate(
821         __in            efx_nic_t *enp,
822         __in            unsigned int index,
823         __in            unsigned int label,
824         __in            efx_rxq_type_t type,
825         __in_opt        const efx_rxq_type_data_t *type_data,
826         __in            efsys_mem_t *esmp,
827         __in            size_t ndescs,
828         __in            uint32_t id,
829         __in            unsigned int flags,
830         __in            efx_evq_t *eep,
831         __in            efx_rxq_t *erp)
832 {
833         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
834         efx_rc_t rc;
835         boolean_t disable_scatter;
836         boolean_t want_inner_classes;
837         unsigned int ps_buf_size;
838         uint32_t es_bufs_per_desc = 0;
839         uint32_t es_max_dma_len = 0;
840         uint32_t es_buf_stride = 0;
841         uint32_t hol_block_timeout = 0;
842
843         _NOTE(ARGUNUSED(id, erp))
844
845         EFX_STATIC_ASSERT(EFX_EV_RX_NLABELS == (1 << ESF_DZ_RX_QLABEL_WIDTH));
846         EFSYS_ASSERT3U(label, <, EFX_EV_RX_NLABELS);
847
848         if (index >= encp->enc_rxq_limit) {
849                 rc = EINVAL;
850                 goto fail1;
851         }
852
853         switch (type) {
854         case EFX_RXQ_TYPE_DEFAULT:
855                 if (type_data == NULL) {
856                         rc = EINVAL;
857                         goto fail2;
858                 }
859                 erp->er_buf_size = type_data->ertd_default.ed_buf_size;
860                 ps_buf_size = 0;
861                 break;
862 #if EFSYS_OPT_RX_PACKED_STREAM
863         case EFX_RXQ_TYPE_PACKED_STREAM:
864                 if (type_data == NULL) {
865                         rc = EINVAL;
866                         goto fail3;
867                 }
868                 switch (type_data->ertd_packed_stream.eps_buf_size) {
869                 case EFX_RXQ_PACKED_STREAM_BUF_SIZE_1M:
870                         ps_buf_size = MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_1M;
871                         break;
872                 case EFX_RXQ_PACKED_STREAM_BUF_SIZE_512K:
873                         ps_buf_size = MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_512K;
874                         break;
875                 case EFX_RXQ_PACKED_STREAM_BUF_SIZE_256K:
876                         ps_buf_size = MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_256K;
877                         break;
878                 case EFX_RXQ_PACKED_STREAM_BUF_SIZE_128K:
879                         ps_buf_size = MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_128K;
880                         break;
881                 case EFX_RXQ_PACKED_STREAM_BUF_SIZE_64K:
882                         ps_buf_size = MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_64K;
883                         break;
884                 default:
885                         rc = ENOTSUP;
886                         goto fail4;
887                 }
888                 erp->er_buf_size = type_data->ertd_packed_stream.eps_buf_size;
889                 break;
890 #endif /* EFSYS_OPT_RX_PACKED_STREAM */
891 #if EFSYS_OPT_RX_ES_SUPER_BUFFER
892         case EFX_RXQ_TYPE_ES_SUPER_BUFFER:
893                 if (type_data == NULL) {
894                         rc = EINVAL;
895                         goto fail5;
896                 }
897                 ps_buf_size = 0;
898                 es_bufs_per_desc =
899                     type_data->ertd_es_super_buffer.eessb_bufs_per_desc;
900                 es_max_dma_len =
901                     type_data->ertd_es_super_buffer.eessb_max_dma_len;
902                 es_buf_stride =
903                     type_data->ertd_es_super_buffer.eessb_buf_stride;
904                 hol_block_timeout =
905                     type_data->ertd_es_super_buffer.eessb_hol_block_timeout;
906                 break;
907 #endif /* EFSYS_OPT_RX_ES_SUPER_BUFFER */
908         default:
909                 rc = ENOTSUP;
910                 goto fail6;
911         }
912
913 #if EFSYS_OPT_RX_PACKED_STREAM
914         if (ps_buf_size != 0) {
915                 /* Check if datapath firmware supports packed stream mode */
916                 if (encp->enc_rx_packed_stream_supported == B_FALSE) {
917                         rc = ENOTSUP;
918                         goto fail7;
919                 }
920                 /* Check if packed stream allows configurable buffer sizes */
921                 if ((ps_buf_size != MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_1M) &&
922                     (encp->enc_rx_var_packed_stream_supported == B_FALSE)) {
923                         rc = ENOTSUP;
924                         goto fail8;
925                 }
926         }
927 #else /* EFSYS_OPT_RX_PACKED_STREAM */
928         EFSYS_ASSERT(ps_buf_size == 0);
929 #endif /* EFSYS_OPT_RX_PACKED_STREAM */
930
931 #if EFSYS_OPT_RX_ES_SUPER_BUFFER
932         if (es_bufs_per_desc > 0) {
933                 if (encp->enc_rx_es_super_buffer_supported == B_FALSE) {
934                         rc = ENOTSUP;
935                         goto fail9;
936                 }
937                 if (!EFX_IS_P2ALIGNED(uint32_t, es_max_dma_len,
938                             EFX_RX_ES_SUPER_BUFFER_BUF_ALIGNMENT)) {
939                         rc = EINVAL;
940                         goto fail10;
941                 }
942                 if (!EFX_IS_P2ALIGNED(uint32_t, es_buf_stride,
943                             EFX_RX_ES_SUPER_BUFFER_BUF_ALIGNMENT)) {
944                         rc = EINVAL;
945                         goto fail11;
946                 }
947         }
948 #else /* EFSYS_OPT_RX_ES_SUPER_BUFFER */
949         EFSYS_ASSERT(es_bufs_per_desc == 0);
950 #endif /* EFSYS_OPT_RX_ES_SUPER_BUFFER */
951
952         /* Scatter can only be disabled if the firmware supports doing so */
953         if (flags & EFX_RXQ_FLAG_SCATTER)
954                 disable_scatter = B_FALSE;
955         else
956                 disable_scatter = encp->enc_rx_disable_scatter_supported;
957
958         if (flags & EFX_RXQ_FLAG_INNER_CLASSES)
959                 want_inner_classes = B_TRUE;
960         else
961                 want_inner_classes = B_FALSE;
962
963         if ((rc = efx_mcdi_init_rxq(enp, ndescs, eep, label, index,
964                     esmp, disable_scatter, want_inner_classes, erp->er_buf_size,
965                     ps_buf_size, es_bufs_per_desc, es_max_dma_len,
966                     es_buf_stride, hol_block_timeout)) != 0)
967                 goto fail12;
968
969         erp->er_eep = eep;
970         erp->er_label = label;
971
972         ef10_ev_rxlabel_init(eep, erp, label, type);
973
974         erp->er_ev_qstate = &erp->er_eep->ee_rxq_state[label];
975
976         return (0);
977
978 fail12:
979         EFSYS_PROBE(fail12);
980 #if EFSYS_OPT_RX_ES_SUPER_BUFFER
981 fail11:
982         EFSYS_PROBE(fail11);
983 fail10:
984         EFSYS_PROBE(fail10);
985 fail9:
986         EFSYS_PROBE(fail9);
987 #endif /* EFSYS_OPT_RX_ES_SUPER_BUFFER */
988 #if EFSYS_OPT_RX_PACKED_STREAM
989 fail8:
990         EFSYS_PROBE(fail8);
991 fail7:
992         EFSYS_PROBE(fail7);
993 #endif /* EFSYS_OPT_RX_PACKED_STREAM */
994 fail6:
995         EFSYS_PROBE(fail6);
996 #if EFSYS_OPT_RX_ES_SUPER_BUFFER
997 fail5:
998         EFSYS_PROBE(fail5);
999 #endif /* EFSYS_OPT_RX_ES_SUPER_BUFFER */
1000 #if EFSYS_OPT_RX_PACKED_STREAM
1001 fail4:
1002         EFSYS_PROBE(fail4);
1003 fail3:
1004         EFSYS_PROBE(fail3);
1005 #endif /* EFSYS_OPT_RX_PACKED_STREAM */
1006 fail2:
1007         EFSYS_PROBE(fail2);
1008 fail1:
1009         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1010
1011         return (rc);
1012 }
1013
1014                 void
1015 ef10_rx_qdestroy(
1016         __in    efx_rxq_t *erp)
1017 {
1018         efx_evq_t *eep = erp->er_eep;
1019         unsigned int label = erp->er_label;
1020
1021         ef10_ev_rxlabel_fini(eep, label);
1022 }
1023
1024                 void
1025 ef10_rx_fini(
1026         __in    efx_nic_t *enp)
1027 {
1028 #if EFSYS_OPT_RX_SCALE
1029         if (enp->en_rss_context_type != EFX_RX_SCALE_UNAVAILABLE)
1030                 (void) efx_mcdi_rss_context_free(enp, enp->en_rss_context);
1031         enp->en_rss_context = 0;
1032         enp->en_rss_context_type = EFX_RX_SCALE_UNAVAILABLE;
1033 #else
1034         _NOTE(ARGUNUSED(enp))
1035 #endif /* EFSYS_OPT_RX_SCALE */
1036 }
1037
1038 #endif /* EFX_OPTS_EF10() */