net/sfc/base: make RxQ type data an union
[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_nic_cfg_t *encp = &enp->en_nic_cfg;
302         efx_rx_hash_type_t type_ipv4;
303         efx_rx_hash_type_t type_ipv4_tcp;
304         efx_rx_hash_type_t type_ipv6;
305         efx_rx_hash_type_t type_ipv6_tcp;
306         efx_rx_hash_type_t modes;
307         efx_mcdi_req_t req;
308         uint8_t payload[MAX(MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_LEN,
309                             MC_CMD_RSS_CONTEXT_SET_FLAGS_OUT_LEN)];
310         efx_rc_t rc;
311
312         EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV4_TCP_LBN ==
313                     MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV4_RSS_MODE_LBN);
314         EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV4_TCP_WIDTH ==
315                     MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV4_RSS_MODE_WIDTH);
316         EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV4_LBN ==
317                     MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV4_RSS_MODE_LBN);
318         EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV4_WIDTH ==
319                     MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV4_RSS_MODE_WIDTH);
320         EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV6_TCP_LBN ==
321                     MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV6_RSS_MODE_LBN);
322         EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV6_TCP_WIDTH ==
323                     MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV6_RSS_MODE_WIDTH);
324         EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV6_LBN ==
325                     MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV6_RSS_MODE_LBN);
326         EFX_STATIC_ASSERT(EFX_RX_CLASS_IPV6_WIDTH ==
327                     MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV6_RSS_MODE_WIDTH);
328
329         if (rss_context == EF10_RSS_CONTEXT_INVALID) {
330                 rc = EINVAL;
331                 goto fail1;
332         }
333
334         (void) memset(payload, 0, sizeof (payload));
335         req.emr_cmd = MC_CMD_RSS_CONTEXT_SET_FLAGS;
336         req.emr_in_buf = payload;
337         req.emr_in_length = MC_CMD_RSS_CONTEXT_SET_FLAGS_IN_LEN;
338         req.emr_out_buf = payload;
339         req.emr_out_length = MC_CMD_RSS_CONTEXT_SET_FLAGS_OUT_LEN;
340
341         MCDI_IN_SET_DWORD(req, RSS_CONTEXT_SET_FLAGS_IN_RSS_CONTEXT_ID,
342             rss_context);
343
344         type_ipv4 = EFX_RX_HASH(IPV4, 2TUPLE) | EFX_RX_HASH(IPV4_TCP, 2TUPLE) |
345                     EFX_RX_HASH(IPV4_UDP, 2TUPLE);
346         type_ipv4_tcp = EFX_RX_HASH(IPV4_TCP, 4TUPLE);
347         type_ipv6 = EFX_RX_HASH(IPV6, 2TUPLE) | EFX_RX_HASH(IPV6_TCP, 2TUPLE) |
348                     EFX_RX_HASH(IPV6_UDP, 2TUPLE);
349         type_ipv6_tcp = EFX_RX_HASH(IPV6_TCP, 4TUPLE);
350
351         /*
352          * Create a copy of the original hash type.
353          * The copy will be used to fill in RSS_MODE bits and
354          * may be cleared beforehand. The original variable
355          * and, thus, EN bits will remain unaffected.
356          */
357         modes = type;
358
359         /*
360          * If the firmware lacks support for additional modes, RSS_MODE
361          * fields must contain zeros, otherwise the operation will fail.
362          */
363         if (encp->enc_rx_scale_additional_modes_supported == B_FALSE)
364                 modes = 0;
365
366 #define EXTRACT_RSS_MODE(_type, _class)         \
367         (EFX_EXTRACT_NATIVE(_type, 0, 31,       \
368         EFX_LOW_BIT(EFX_RX_CLASS_##_class),     \
369         EFX_HIGH_BIT(EFX_RX_CLASS_##_class)) &  \
370         EFX_MASK32(EFX_RX_CLASS_##_class))
371
372         MCDI_IN_POPULATE_DWORD_10(req, RSS_CONTEXT_SET_FLAGS_IN_FLAGS,
373             RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_IPV4_EN,
374             ((type & type_ipv4) == type_ipv4) ? 1 : 0,
375             RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_TCPV4_EN,
376             ((type & type_ipv4_tcp) == type_ipv4_tcp) ? 1 : 0,
377             RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_IPV6_EN,
378             ((type & type_ipv6) == type_ipv6) ? 1 : 0,
379             RSS_CONTEXT_SET_FLAGS_IN_TOEPLITZ_TCPV6_EN,
380             ((type & type_ipv6_tcp) == type_ipv6_tcp) ? 1 : 0,
381             RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV4_RSS_MODE,
382             EXTRACT_RSS_MODE(modes, IPV4_TCP),
383             RSS_CONTEXT_SET_FLAGS_IN_UDP_IPV4_RSS_MODE,
384             EXTRACT_RSS_MODE(modes, IPV4_UDP),
385             RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV4_RSS_MODE,
386             EXTRACT_RSS_MODE(modes, IPV4),
387             RSS_CONTEXT_SET_FLAGS_IN_TCP_IPV6_RSS_MODE,
388             EXTRACT_RSS_MODE(modes, IPV6_TCP),
389             RSS_CONTEXT_SET_FLAGS_IN_UDP_IPV6_RSS_MODE,
390             EXTRACT_RSS_MODE(modes, IPV6_UDP),
391             RSS_CONTEXT_SET_FLAGS_IN_OTHER_IPV6_RSS_MODE,
392             EXTRACT_RSS_MODE(modes, IPV6));
393
394 #undef EXTRACT_RSS_MODE
395
396         efx_mcdi_execute(enp, &req);
397
398         if (req.emr_rc != 0) {
399                 rc = req.emr_rc;
400                 goto fail2;
401         }
402
403         return (0);
404
405 fail2:
406         EFSYS_PROBE(fail2);
407 fail1:
408         EFSYS_PROBE1(fail1, efx_rc_t, rc);
409
410         return (rc);
411 }
412 #endif /* EFSYS_OPT_RX_SCALE */
413
414 #if EFSYS_OPT_RX_SCALE
415 static                  efx_rc_t
416 efx_mcdi_rss_context_set_key(
417         __in            efx_nic_t *enp,
418         __in            uint32_t rss_context,
419         __in_ecount(n)  uint8_t *key,
420         __in            size_t n)
421 {
422         efx_mcdi_req_t req;
423         uint8_t payload[MAX(MC_CMD_RSS_CONTEXT_SET_KEY_IN_LEN,
424                             MC_CMD_RSS_CONTEXT_SET_KEY_OUT_LEN)];
425         efx_rc_t rc;
426
427         if (rss_context == EF10_RSS_CONTEXT_INVALID) {
428                 rc = EINVAL;
429                 goto fail1;
430         }
431
432         (void) memset(payload, 0, sizeof (payload));
433         req.emr_cmd = MC_CMD_RSS_CONTEXT_SET_KEY;
434         req.emr_in_buf = payload;
435         req.emr_in_length = MC_CMD_RSS_CONTEXT_SET_KEY_IN_LEN;
436         req.emr_out_buf = payload;
437         req.emr_out_length = MC_CMD_RSS_CONTEXT_SET_KEY_OUT_LEN;
438
439         MCDI_IN_SET_DWORD(req, RSS_CONTEXT_SET_KEY_IN_RSS_CONTEXT_ID,
440             rss_context);
441
442         EFSYS_ASSERT3U(n, ==, MC_CMD_RSS_CONTEXT_SET_KEY_IN_TOEPLITZ_KEY_LEN);
443         if (n != MC_CMD_RSS_CONTEXT_SET_KEY_IN_TOEPLITZ_KEY_LEN) {
444                 rc = EINVAL;
445                 goto fail2;
446         }
447
448         memcpy(MCDI_IN2(req, uint8_t, RSS_CONTEXT_SET_KEY_IN_TOEPLITZ_KEY),
449             key, n);
450
451         efx_mcdi_execute(enp, &req);
452
453         if (req.emr_rc != 0) {
454                 rc = req.emr_rc;
455                 goto fail3;
456         }
457
458         return (0);
459
460 fail3:
461         EFSYS_PROBE(fail3);
462 fail2:
463         EFSYS_PROBE(fail2);
464 fail1:
465         EFSYS_PROBE1(fail1, efx_rc_t, rc);
466
467         return (rc);
468 }
469 #endif /* EFSYS_OPT_RX_SCALE */
470
471 #if EFSYS_OPT_RX_SCALE
472 static                  efx_rc_t
473 efx_mcdi_rss_context_set_table(
474         __in            efx_nic_t *enp,
475         __in            uint32_t rss_context,
476         __in_ecount(n)  unsigned int *table,
477         __in            size_t n)
478 {
479         efx_mcdi_req_t req;
480         uint8_t payload[MAX(MC_CMD_RSS_CONTEXT_SET_TABLE_IN_LEN,
481                             MC_CMD_RSS_CONTEXT_SET_TABLE_OUT_LEN)];
482         uint8_t *req_table;
483         int i, rc;
484
485         if (rss_context == EF10_RSS_CONTEXT_INVALID) {
486                 rc = EINVAL;
487                 goto fail1;
488         }
489
490         (void) memset(payload, 0, sizeof (payload));
491         req.emr_cmd = MC_CMD_RSS_CONTEXT_SET_TABLE;
492         req.emr_in_buf = payload;
493         req.emr_in_length = MC_CMD_RSS_CONTEXT_SET_TABLE_IN_LEN;
494         req.emr_out_buf = payload;
495         req.emr_out_length = MC_CMD_RSS_CONTEXT_SET_TABLE_OUT_LEN;
496
497         MCDI_IN_SET_DWORD(req, RSS_CONTEXT_SET_TABLE_IN_RSS_CONTEXT_ID,
498             rss_context);
499
500         req_table =
501             MCDI_IN2(req, uint8_t, RSS_CONTEXT_SET_TABLE_IN_INDIRECTION_TABLE);
502
503         for (i = 0;
504             i < MC_CMD_RSS_CONTEXT_SET_TABLE_IN_INDIRECTION_TABLE_LEN;
505             i++) {
506                 req_table[i] = (n > 0) ? (uint8_t)table[i % n] : 0;
507         }
508
509         efx_mcdi_execute(enp, &req);
510
511         if (req.emr_rc != 0) {
512                 rc = req.emr_rc;
513                 goto fail2;
514         }
515
516         return (0);
517
518 fail2:
519         EFSYS_PROBE(fail2);
520 fail1:
521         EFSYS_PROBE1(fail1, efx_rc_t, rc);
522
523         return (rc);
524 }
525 #endif /* EFSYS_OPT_RX_SCALE */
526
527
528         __checkReturn   efx_rc_t
529 ef10_rx_init(
530         __in            efx_nic_t *enp)
531 {
532 #if EFSYS_OPT_RX_SCALE
533
534         if (efx_mcdi_rss_context_alloc(enp, EFX_RX_SCALE_EXCLUSIVE, EFX_MAXRSS,
535                 &enp->en_rss_context) == 0) {
536                 /*
537                  * Allocated an exclusive RSS context, which allows both the
538                  * indirection table and key to be modified.
539                  */
540                 enp->en_rss_context_type = EFX_RX_SCALE_EXCLUSIVE;
541                 enp->en_hash_support = EFX_RX_HASH_AVAILABLE;
542         } else {
543                 /*
544                  * Failed to allocate an exclusive RSS context. Continue
545                  * operation without support for RSS. The pseudo-header in
546                  * received packets will not contain a Toeplitz hash value.
547                  */
548                 enp->en_rss_context_type = EFX_RX_SCALE_UNAVAILABLE;
549                 enp->en_hash_support = EFX_RX_HASH_UNAVAILABLE;
550         }
551
552 #endif /* EFSYS_OPT_RX_SCALE */
553
554         return (0);
555 }
556
557 #if EFSYS_OPT_RX_SCATTER
558         __checkReturn   efx_rc_t
559 ef10_rx_scatter_enable(
560         __in            efx_nic_t *enp,
561         __in            unsigned int buf_size)
562 {
563         _NOTE(ARGUNUSED(enp, buf_size))
564         return (0);
565 }
566 #endif  /* EFSYS_OPT_RX_SCATTER */
567
568 #if EFSYS_OPT_RX_SCALE
569         __checkReturn   efx_rc_t
570 ef10_rx_scale_context_alloc(
571         __in            efx_nic_t *enp,
572         __in            efx_rx_scale_context_type_t type,
573         __in            uint32_t num_queues,
574         __out           uint32_t *rss_contextp)
575 {
576         efx_rc_t rc;
577
578         rc = efx_mcdi_rss_context_alloc(enp, type, num_queues, rss_contextp);
579         if (rc != 0)
580                 goto fail1;
581
582         return (0);
583
584 fail1:
585         EFSYS_PROBE1(fail1, efx_rc_t, rc);
586         return (rc);
587 }
588 #endif /* EFSYS_OPT_RX_SCALE */
589
590 #if EFSYS_OPT_RX_SCALE
591         __checkReturn   efx_rc_t
592 ef10_rx_scale_context_free(
593         __in            efx_nic_t *enp,
594         __in            uint32_t rss_context)
595 {
596         efx_rc_t rc;
597
598         rc = efx_mcdi_rss_context_free(enp, rss_context);
599         if (rc != 0)
600                 goto fail1;
601
602         return (0);
603
604 fail1:
605         EFSYS_PROBE1(fail1, efx_rc_t, rc);
606         return (rc);
607 }
608 #endif /* EFSYS_OPT_RX_SCALE */
609
610 #if EFSYS_OPT_RX_SCALE
611         __checkReturn   efx_rc_t
612 ef10_rx_scale_mode_set(
613         __in            efx_nic_t *enp,
614         __in            uint32_t rss_context,
615         __in            efx_rx_hash_alg_t alg,
616         __in            efx_rx_hash_type_t type,
617         __in            boolean_t insert)
618 {
619         efx_nic_cfg_t *encp = &enp->en_nic_cfg;
620         efx_rc_t rc;
621
622         EFSYS_ASSERT3U(insert, ==, B_TRUE);
623
624         if ((encp->enc_rx_scale_hash_alg_mask & (1U << alg)) == 0 ||
625             insert == B_FALSE) {
626                 rc = EINVAL;
627                 goto fail1;
628         }
629
630         if (rss_context == EFX_RSS_CONTEXT_DEFAULT) {
631                 if (enp->en_rss_context_type == EFX_RX_SCALE_UNAVAILABLE) {
632                         rc = ENOTSUP;
633                         goto fail2;
634                 }
635                 rss_context = enp->en_rss_context;
636         }
637
638         if ((rc = efx_mcdi_rss_context_set_flags(enp,
639                     rss_context, type)) != 0)
640                 goto fail3;
641
642         return (0);
643
644 fail3:
645         EFSYS_PROBE(fail3);
646 fail2:
647         EFSYS_PROBE(fail2);
648 fail1:
649         EFSYS_PROBE1(fail1, efx_rc_t, rc);
650
651         return (rc);
652 }
653 #endif /* EFSYS_OPT_RX_SCALE */
654
655 #if EFSYS_OPT_RX_SCALE
656         __checkReturn   efx_rc_t
657 ef10_rx_scale_key_set(
658         __in            efx_nic_t *enp,
659         __in            uint32_t rss_context,
660         __in_ecount(n)  uint8_t *key,
661         __in            size_t n)
662 {
663         efx_rc_t rc;
664
665         EFX_STATIC_ASSERT(EFX_RSS_KEY_SIZE ==
666             MC_CMD_RSS_CONTEXT_SET_KEY_IN_TOEPLITZ_KEY_LEN);
667
668         if (rss_context == EFX_RSS_CONTEXT_DEFAULT) {
669                 if (enp->en_rss_context_type == EFX_RX_SCALE_UNAVAILABLE) {
670                         rc = ENOTSUP;
671                         goto fail1;
672                 }
673                 rss_context = enp->en_rss_context;
674         }
675
676         if ((rc = efx_mcdi_rss_context_set_key(enp, rss_context, key, n)) != 0)
677                 goto fail2;
678
679         return (0);
680
681 fail2:
682         EFSYS_PROBE(fail2);
683 fail1:
684         EFSYS_PROBE1(fail1, efx_rc_t, rc);
685
686         return (rc);
687 }
688 #endif /* EFSYS_OPT_RX_SCALE */
689
690 #if EFSYS_OPT_RX_SCALE
691         __checkReturn   efx_rc_t
692 ef10_rx_scale_tbl_set(
693         __in            efx_nic_t *enp,
694         __in            uint32_t rss_context,
695         __in_ecount(n)  unsigned int *table,
696         __in            size_t n)
697 {
698         efx_rc_t rc;
699
700
701         if (rss_context == EFX_RSS_CONTEXT_DEFAULT) {
702                 if (enp->en_rss_context_type == EFX_RX_SCALE_UNAVAILABLE) {
703                         rc = ENOTSUP;
704                         goto fail1;
705                 }
706                 rss_context = enp->en_rss_context;
707         }
708
709         if ((rc = efx_mcdi_rss_context_set_table(enp,
710                     rss_context, table, n)) != 0)
711                 goto fail2;
712
713         return (0);
714
715 fail2:
716         EFSYS_PROBE(fail2);
717 fail1:
718         EFSYS_PROBE1(fail1, efx_rc_t, rc);
719
720         return (rc);
721 }
722 #endif /* EFSYS_OPT_RX_SCALE */
723
724
725 /*
726  * EF10 RX pseudo-header
727  * ---------------------
728  *
729  * Receive packets are prefixed by an (optional) 14 byte pseudo-header:
730  *
731  *  +00: Toeplitz hash value.
732  *       (32bit little-endian)
733  *  +04: Outer VLAN tag. Zero if the packet did not have an outer VLAN tag.
734  *       (16bit big-endian)
735  *  +06: Inner VLAN tag. Zero if the packet did not have an inner VLAN tag.
736  *       (16bit big-endian)
737  *  +08: Packet Length. Zero if the RX datapath was in cut-through mode.
738  *       (16bit little-endian)
739  *  +10: MAC timestamp. Zero if timestamping is not enabled.
740  *       (32bit little-endian)
741  *
742  * See "The RX Pseudo-header" in SF-109306-TC.
743  */
744
745         __checkReturn   efx_rc_t
746 ef10_rx_prefix_pktlen(
747         __in            efx_nic_t *enp,
748         __in            uint8_t *buffer,
749         __out           uint16_t *lengthp)
750 {
751         _NOTE(ARGUNUSED(enp))
752
753         /*
754          * The RX pseudo-header contains the packet length, excluding the
755          * pseudo-header. If the hardware receive datapath was operating in
756          * cut-through mode then the length in the RX pseudo-header will be
757          * zero, and the packet length must be obtained from the DMA length
758          * reported in the RX event.
759          */
760         *lengthp = buffer[8] | (buffer[9] << 8);
761         return (0);
762 }
763
764 #if EFSYS_OPT_RX_SCALE
765         __checkReturn   uint32_t
766 ef10_rx_prefix_hash(
767         __in            efx_nic_t *enp,
768         __in            efx_rx_hash_alg_t func,
769         __in            uint8_t *buffer)
770 {
771         _NOTE(ARGUNUSED(enp))
772
773         switch (func) {
774         case EFX_RX_HASHALG_PACKED_STREAM:
775         case EFX_RX_HASHALG_TOEPLITZ:
776                 return (buffer[0] |
777                     (buffer[1] << 8) |
778                     (buffer[2] << 16) |
779                     (buffer[3] << 24));
780
781         default:
782                 EFSYS_ASSERT(0);
783                 return (0);
784         }
785 }
786 #endif /* EFSYS_OPT_RX_SCALE */
787
788 #if EFSYS_OPT_RX_PACKED_STREAM
789 /*
790  * Fake length for RXQ descriptors in packed stream mode
791  * to make hardware happy
792  */
793 #define EFX_RXQ_PACKED_STREAM_FAKE_BUF_SIZE 32
794 #endif
795
796                                 void
797 ef10_rx_qpost(
798         __in                    efx_rxq_t *erp,
799         __in_ecount(ndescs)     efsys_dma_addr_t *addrp,
800         __in                    size_t size,
801         __in                    unsigned int ndescs,
802         __in                    unsigned int completed,
803         __in                    unsigned int added)
804 {
805         efx_qword_t qword;
806         unsigned int i;
807         unsigned int offset;
808         unsigned int id;
809
810         _NOTE(ARGUNUSED(completed))
811
812 #if EFSYS_OPT_RX_PACKED_STREAM
813         /*
814          * Real size of the buffer does not fit into ESF_DZ_RX_KER_BYTE_CNT
815          * and equal to 0 after applying mask. Hardware does not like it.
816          */
817         if (erp->er_ev_qstate->eers_rx_packed_stream)
818                 size = EFX_RXQ_PACKED_STREAM_FAKE_BUF_SIZE;
819 #endif
820
821         /* The client driver must not overfill the queue */
822         EFSYS_ASSERT3U(added - completed + ndescs, <=,
823             EFX_RXQ_LIMIT(erp->er_mask + 1));
824
825         id = added & (erp->er_mask);
826         for (i = 0; i < ndescs; i++) {
827                 EFSYS_PROBE4(rx_post, unsigned int, erp->er_index,
828                     unsigned int, id, efsys_dma_addr_t, addrp[i],
829                     size_t, size);
830
831                 EFX_POPULATE_QWORD_3(qword,
832                     ESF_DZ_RX_KER_BYTE_CNT, (uint32_t)(size),
833                     ESF_DZ_RX_KER_BUF_ADDR_DW0,
834                     (uint32_t)(addrp[i] & 0xffffffff),
835                     ESF_DZ_RX_KER_BUF_ADDR_DW1,
836                     (uint32_t)(addrp[i] >> 32));
837
838                 offset = id * sizeof (efx_qword_t);
839                 EFSYS_MEM_WRITEQ(erp->er_esmp, offset, &qword);
840
841                 id = (id + 1) & (erp->er_mask);
842         }
843 }
844
845                         void
846 ef10_rx_qpush(
847         __in    efx_rxq_t *erp,
848         __in    unsigned int added,
849         __inout unsigned int *pushedp)
850 {
851         efx_nic_t *enp = erp->er_enp;
852         unsigned int pushed = *pushedp;
853         uint32_t wptr;
854         efx_dword_t dword;
855
856         /* Hardware has alignment restriction for WPTR */
857         wptr = P2ALIGN(added, EF10_RX_WPTR_ALIGN);
858         if (pushed == wptr)
859                 return;
860
861         *pushedp = wptr;
862
863         /* Push the populated descriptors out */
864         wptr &= erp->er_mask;
865
866         EFX_POPULATE_DWORD_1(dword, ERF_DZ_RX_DESC_WPTR, wptr);
867
868         /* Guarantee ordering of memory (descriptors) and PIO (doorbell) */
869         EFX_DMA_SYNC_QUEUE_FOR_DEVICE(erp->er_esmp, erp->er_mask + 1,
870             wptr, pushed & erp->er_mask);
871         EFSYS_PIO_WRITE_BARRIER();
872         EFX_BAR_VI_WRITED(enp, ER_DZ_RX_DESC_UPD_REG,
873             erp->er_index, &dword, B_FALSE);
874 }
875
876 #if EFSYS_OPT_RX_PACKED_STREAM
877
878                         void
879 ef10_rx_qpush_ps_credits(
880         __in            efx_rxq_t *erp)
881 {
882         efx_nic_t *enp = erp->er_enp;
883         efx_dword_t dword;
884         efx_evq_rxq_state_t *rxq_state = erp->er_ev_qstate;
885         uint32_t credits;
886
887         EFSYS_ASSERT(rxq_state->eers_rx_packed_stream);
888
889         if (rxq_state->eers_rx_packed_stream_credits == 0)
890                 return;
891
892         /*
893          * It is a bug if we think that FW has utilized more
894          * credits than it is allowed to have (maximum). However,
895          * make sure that we do not credit more than maximum anyway.
896          */
897         credits = MIN(rxq_state->eers_rx_packed_stream_credits,
898             EFX_RX_PACKED_STREAM_MAX_CREDITS);
899         EFX_POPULATE_DWORD_3(dword,
900             ERF_DZ_RX_DESC_MAGIC_DOORBELL, 1,
901             ERF_DZ_RX_DESC_MAGIC_CMD,
902             ERE_DZ_RX_DESC_MAGIC_CMD_PS_CREDITS,
903             ERF_DZ_RX_DESC_MAGIC_DATA, credits);
904         EFX_BAR_VI_WRITED(enp, ER_DZ_RX_DESC_UPD_REG,
905             erp->er_index, &dword, B_FALSE);
906
907         rxq_state->eers_rx_packed_stream_credits = 0;
908 }
909
910 /*
911  * In accordance with SF-112241-TC the received data has the following layout:
912  *  - 8 byte pseudo-header which consist of:
913  *    - 4 byte little-endian timestamp
914  *    - 2 byte little-endian captured length in bytes
915  *    - 2 byte little-endian original packet length in bytes
916  *  - captured packet bytes
917  *  - optional padding to align to 64 bytes boundary
918  *  - 64 bytes scratch space for the host software
919  */
920         __checkReturn   uint8_t *
921 ef10_rx_qps_packet_info(
922         __in            efx_rxq_t *erp,
923         __in            uint8_t *buffer,
924         __in            uint32_t buffer_length,
925         __in            uint32_t current_offset,
926         __out           uint16_t *lengthp,
927         __out           uint32_t *next_offsetp,
928         __out           uint32_t *timestamp)
929 {
930         uint16_t buf_len;
931         uint8_t *pkt_start;
932         efx_qword_t *qwordp;
933         efx_evq_rxq_state_t *rxq_state = erp->er_ev_qstate;
934
935         EFSYS_ASSERT(rxq_state->eers_rx_packed_stream);
936
937         buffer += current_offset;
938         pkt_start = buffer + EFX_RX_PACKED_STREAM_RX_PREFIX_SIZE;
939
940         qwordp = (efx_qword_t *)buffer;
941         *timestamp = EFX_QWORD_FIELD(*qwordp, ES_DZ_PS_RX_PREFIX_TSTAMP);
942         *lengthp   = EFX_QWORD_FIELD(*qwordp, ES_DZ_PS_RX_PREFIX_ORIG_LEN);
943         buf_len    = EFX_QWORD_FIELD(*qwordp, ES_DZ_PS_RX_PREFIX_CAP_LEN);
944
945         buf_len = P2ROUNDUP(buf_len + EFX_RX_PACKED_STREAM_RX_PREFIX_SIZE,
946                             EFX_RX_PACKED_STREAM_ALIGNMENT);
947         *next_offsetp =
948             current_offset + buf_len + EFX_RX_PACKED_STREAM_ALIGNMENT;
949
950         EFSYS_ASSERT3U(*next_offsetp, <=, buffer_length);
951         EFSYS_ASSERT3U(current_offset + *lengthp, <, *next_offsetp);
952
953         if ((*next_offsetp ^ current_offset) &
954             EFX_RX_PACKED_STREAM_MEM_PER_CREDIT)
955                 rxq_state->eers_rx_packed_stream_credits++;
956
957         return (pkt_start);
958 }
959
960
961 #endif
962
963         __checkReturn   efx_rc_t
964 ef10_rx_qflush(
965         __in    efx_rxq_t *erp)
966 {
967         efx_nic_t *enp = erp->er_enp;
968         efx_rc_t rc;
969
970         if ((rc = efx_mcdi_fini_rxq(enp, erp->er_index)) != 0)
971                 goto fail1;
972
973         return (0);
974
975 fail1:
976         /*
977          * EALREADY is not an error, but indicates that the MC has rebooted and
978          * that the RXQ has already been destroyed. Callers need to know that
979          * the RXQ flush has completed to avoid waiting until timeout for a
980          * flush done event that will not be delivered.
981          */
982         if (rc != EALREADY)
983                 EFSYS_PROBE1(fail1, efx_rc_t, rc);
984
985         return (rc);
986 }
987
988                 void
989 ef10_rx_qenable(
990         __in    efx_rxq_t *erp)
991 {
992         /* FIXME */
993         _NOTE(ARGUNUSED(erp))
994         /* FIXME */
995 }
996
997         __checkReturn   efx_rc_t
998 ef10_rx_qcreate(
999         __in            efx_nic_t *enp,
1000         __in            unsigned int index,
1001         __in            unsigned int label,
1002         __in            efx_rxq_type_t type,
1003         __in            const efx_rxq_type_data_t *type_data,
1004         __in            efsys_mem_t *esmp,
1005         __in            size_t ndescs,
1006         __in            uint32_t id,
1007         __in            unsigned int flags,
1008         __in            efx_evq_t *eep,
1009         __in            efx_rxq_t *erp)
1010 {
1011         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1012         efx_rc_t rc;
1013         boolean_t disable_scatter;
1014         boolean_t want_inner_classes;
1015         unsigned int ps_buf_size;
1016
1017         _NOTE(ARGUNUSED(id, erp, type_data))
1018
1019         EFX_STATIC_ASSERT(EFX_EV_RX_NLABELS == (1 << ESF_DZ_RX_QLABEL_WIDTH));
1020         EFSYS_ASSERT3U(label, <, EFX_EV_RX_NLABELS);
1021         EFSYS_ASSERT3U(enp->en_rx_qcount + 1, <, encp->enc_rxq_limit);
1022
1023         EFX_STATIC_ASSERT(ISP2(EFX_RXQ_MAXNDESCS));
1024         EFX_STATIC_ASSERT(ISP2(EFX_RXQ_MINNDESCS));
1025
1026         if (!ISP2(ndescs) ||
1027             (ndescs < EFX_RXQ_MINNDESCS) || (ndescs > EFX_RXQ_MAXNDESCS)) {
1028                 rc = EINVAL;
1029                 goto fail1;
1030         }
1031         if (index >= encp->enc_rxq_limit) {
1032                 rc = EINVAL;
1033                 goto fail2;
1034         }
1035
1036         switch (type) {
1037         case EFX_RXQ_TYPE_DEFAULT:
1038                 ps_buf_size = 0;
1039                 break;
1040 #if EFSYS_OPT_RX_PACKED_STREAM
1041         case EFX_RXQ_TYPE_PACKED_STREAM:
1042                 switch (type_data->ertd_packed_stream.eps_buf_size) {
1043                 case EFX_RXQ_PACKED_STREAM_BUF_SIZE_1M:
1044                         ps_buf_size = MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_1M;
1045                         break;
1046                 case EFX_RXQ_PACKED_STREAM_BUF_SIZE_512K:
1047                         ps_buf_size = MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_512K;
1048                         break;
1049                 case EFX_RXQ_PACKED_STREAM_BUF_SIZE_256K:
1050                         ps_buf_size = MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_256K;
1051                         break;
1052                 case EFX_RXQ_PACKED_STREAM_BUF_SIZE_128K:
1053                         ps_buf_size = MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_128K;
1054                         break;
1055                 case EFX_RXQ_PACKED_STREAM_BUF_SIZE_64K:
1056                         ps_buf_size = MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_64K;
1057                         break;
1058                 default:
1059                         rc = ENOTSUP;
1060                         goto fail3;
1061                 }
1062                 break;
1063 #endif /* EFSYS_OPT_RX_PACKED_STREAM */
1064         default:
1065                 rc = ENOTSUP;
1066                 goto fail4;
1067         }
1068
1069 #if EFSYS_OPT_RX_PACKED_STREAM
1070         if (ps_buf_size != 0) {
1071                 /* Check if datapath firmware supports packed stream mode */
1072                 if (encp->enc_rx_packed_stream_supported == B_FALSE) {
1073                         rc = ENOTSUP;
1074                         goto fail5;
1075                 }
1076                 /* Check if packed stream allows configurable buffer sizes */
1077                 if ((ps_buf_size != MC_CMD_INIT_RXQ_EXT_IN_PS_BUFF_1M) &&
1078                     (encp->enc_rx_var_packed_stream_supported == B_FALSE)) {
1079                         rc = ENOTSUP;
1080                         goto fail6;
1081                 }
1082         }
1083 #else /* EFSYS_OPT_RX_PACKED_STREAM */
1084         EFSYS_ASSERT(ps_buf_size == 0);
1085 #endif /* EFSYS_OPT_RX_PACKED_STREAM */
1086
1087         /* Scatter can only be disabled if the firmware supports doing so */
1088         if (flags & EFX_RXQ_FLAG_SCATTER)
1089                 disable_scatter = B_FALSE;
1090         else
1091                 disable_scatter = encp->enc_rx_disable_scatter_supported;
1092
1093         if (flags & EFX_RXQ_FLAG_INNER_CLASSES)
1094                 want_inner_classes = B_TRUE;
1095         else
1096                 want_inner_classes = B_FALSE;
1097
1098         if ((rc = efx_mcdi_init_rxq(enp, ndescs, eep->ee_index, label, index,
1099                     esmp, disable_scatter, want_inner_classes,
1100                     ps_buf_size)) != 0)
1101                 goto fail7;
1102
1103         erp->er_eep = eep;
1104         erp->er_label = label;
1105
1106         ef10_ev_rxlabel_init(eep, erp, label, type);
1107
1108         erp->er_ev_qstate = &erp->er_eep->ee_rxq_state[label];
1109
1110         return (0);
1111
1112 fail7:
1113         EFSYS_PROBE(fail7);
1114 #if EFSYS_OPT_RX_PACKED_STREAM
1115 fail6:
1116         EFSYS_PROBE(fail6);
1117 fail5:
1118         EFSYS_PROBE(fail5);
1119 #endif /* EFSYS_OPT_RX_PACKED_STREAM */
1120 fail4:
1121         EFSYS_PROBE(fail4);
1122 #if EFSYS_OPT_RX_PACKED_STREAM
1123 fail3:
1124         EFSYS_PROBE(fail3);
1125 #endif /* EFSYS_OPT_RX_PACKED_STREAM */
1126 fail2:
1127         EFSYS_PROBE(fail2);
1128 fail1:
1129         EFSYS_PROBE1(fail1, efx_rc_t, rc);
1130
1131         return (rc);
1132 }
1133
1134                 void
1135 ef10_rx_qdestroy(
1136         __in    efx_rxq_t *erp)
1137 {
1138         efx_nic_t *enp = erp->er_enp;
1139         efx_evq_t *eep = erp->er_eep;
1140         unsigned int label = erp->er_label;
1141
1142         ef10_ev_rxlabel_fini(eep, label);
1143
1144         EFSYS_ASSERT(enp->en_rx_qcount != 0);
1145         --enp->en_rx_qcount;
1146
1147         EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_rxq_t), erp);
1148 }
1149
1150                 void
1151 ef10_rx_fini(
1152         __in    efx_nic_t *enp)
1153 {
1154 #if EFSYS_OPT_RX_SCALE
1155         if (enp->en_rss_context_type != EFX_RX_SCALE_UNAVAILABLE)
1156                 (void) efx_mcdi_rss_context_free(enp, enp->en_rss_context);
1157         enp->en_rss_context = 0;
1158         enp->en_rss_context_type = EFX_RX_SCALE_UNAVAILABLE;
1159 #else
1160         _NOTE(ARGUNUSED(enp))
1161 #endif /* EFSYS_OPT_RX_SCALE */
1162 }
1163
1164 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */