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