1/*-
2 * Copyright (c) 2007-2015 Solarflare Communications Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * The views and conclusions contained in the software and documentation are
27 * those of the authors and should not be interpreted as representing official
28 * policies, either expressed or implied, of the FreeBSD Project.
29 */
30
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD: head/sys/dev/sfxge/common/efx_mac.c 294253 2016-01-18 06:19:28Z arybchik $");
33
34#include "efx.h"
35#include "efx_impl.h"
36
37#if EFSYS_OPT_MAC_FALCON_GMAC
38#include "falcon_gmac.h"
39#endif
40
41#if EFSYS_OPT_MAC_FALCON_XMAC
42#include "falcon_xmac.h"
43#endif
44
45#if EFSYS_OPT_FALCON || EFSYS_OPT_SIENA
46
47static __checkReturn efx_rc_t
48falconsiena_mac_multicast_list_set(
49 __in efx_nic_t *enp);
50
51#endif /* EFSYS_OPT_FALCON || EFSYS_OPT_SIENA */
52
53#if EFSYS_OPT_MAC_FALCON_GMAC
54static efx_mac_ops_t __efx_falcon_gmac_ops = {
55 falcon_gmac_reset, /* emo_reset */
56 falcon_mac_poll, /* emo_poll */
57 falcon_mac_up, /* emo_up */
58 falcon_gmac_reconfigure, /* emo_addr_set */
59 falcon_gmac_reconfigure, /* emo_pdu_set */
60 falcon_gmac_reconfigure, /* emo_reconfigure */
61 falconsiena_mac_multicast_list_set, /* emo_multicast_list_set */
62 NULL, /* emo_filter_set_default_rxq */
63 NULL, /* emo_filter_default_rxq_clear */
64#if EFSYS_OPT_LOOPBACK
65 falcon_mac_loopback_set, /* emo_loopback_set */
66#endif /* EFSYS_OPT_LOOPBACK */
67#if EFSYS_OPT_MAC_STATS
68 falcon_mac_stats_upload, /* emo_stats_upload */
69 NULL, /* emo_stats_periodic */
70 falcon_gmac_stats_update /* emo_stats_update */
71#endif /* EFSYS_OPT_MAC_STATS */
72};
73#endif /* EFSYS_OPT_MAC_FALCON_GMAC */
74
75#if EFSYS_OPT_MAC_FALCON_XMAC
76static efx_mac_ops_t __efx_falcon_xmac_ops = {
77 falcon_xmac_reset, /* emo_reset */
78 falcon_mac_poll, /* emo_poll */
79 falcon_mac_up, /* emo_up */
80 falcon_xmac_reconfigure, /* emo_addr_set */
81 falcon_xmac_reconfigure, /* emo_pdu_set */
82 falcon_xmac_reconfigure, /* emo_reconfigure */
83 falconsiena_mac_multicast_list_set, /* emo_multicast_list_set */
84 NULL, /* emo_filter_set_default_rxq */
85 NULL, /* emo_filter_default_rxq_clear */
86#if EFSYS_OPT_LOOPBACK
87 falcon_mac_loopback_set, /* emo_loopback_set */
88#endif /* EFSYS_OPT_LOOPBACK */
89#if EFSYS_OPT_MAC_STATS
90 falcon_mac_stats_upload, /* emo_stats_upload */
91 NULL, /* emo_stats_periodic */
92 falcon_xmac_stats_update /* emo_stats_update */
93#endif /* EFSYS_OPT_MAC_STATS */
94};
95#endif /* EFSYS_OPT_MAC_FALCON_XMAC */
96
97#if EFSYS_OPT_SIENA
98static efx_mac_ops_t __efx_siena_mac_ops = {
99 NULL, /* emo_reset */
100 siena_mac_poll, /* emo_poll */
101 siena_mac_up, /* emo_up */
102 siena_mac_reconfigure, /* emo_addr_set */
103 siena_mac_reconfigure, /* emo_pdu_set */
104 siena_mac_reconfigure, /* emo_reconfigure */
105 falconsiena_mac_multicast_list_set, /* emo_multicast_list_set */
106 NULL, /* emo_filter_set_default_rxq */
107 NULL, /* emo_filter_default_rxq_clear */
108#if EFSYS_OPT_LOOPBACK
109 siena_mac_loopback_set, /* emo_loopback_set */
110#endif /* EFSYS_OPT_LOOPBACK */
111#if EFSYS_OPT_MAC_STATS
112 efx_mcdi_mac_stats_upload, /* emo_stats_upload */
113 efx_mcdi_mac_stats_periodic, /* emo_stats_periodic */
114 siena_mac_stats_update /* emo_stats_update */
115#endif /* EFSYS_OPT_MAC_STATS */
116};
117#endif /* EFSYS_OPT_SIENA */
118
119#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
120static efx_mac_ops_t __efx_ef10_mac_ops = {
121 NULL, /* emo_reset */
122 ef10_mac_poll, /* emo_poll */
123 ef10_mac_up, /* emo_up */
124 ef10_mac_addr_set, /* emo_addr_set */
125 ef10_mac_pdu_set, /* emo_pdu_set */
126 ef10_mac_reconfigure, /* emo_reconfigure */
127 ef10_mac_multicast_list_set, /* emo_multicast_list_set */
128 ef10_mac_filter_default_rxq_set, /* emo_filter_default_rxq_set */
129 ef10_mac_filter_default_rxq_clear,
130 /* emo_filter_default_rxq_clear */
131#if EFSYS_OPT_LOOPBACK
132 ef10_mac_loopback_set, /* emo_loopback_set */
133#endif /* EFSYS_OPT_LOOPBACK */
134#if EFSYS_OPT_MAC_STATS
135 efx_mcdi_mac_stats_upload, /* emo_stats_upload */
136 efx_mcdi_mac_stats_periodic, /* emo_stats_periodic */
137 ef10_mac_stats_update /* emo_stats_update */
138#endif /* EFSYS_OPT_MAC_STATS */
139};
140#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
141
142static efx_mac_ops_t *__efx_mac_ops[] = {
143 /* [EFX_MAC_INVALID] */
144 NULL,
145 /* [EFX_MAC_FALCON_GMAC] */
146#if EFSYS_OPT_MAC_FALCON_GMAC
147 &__efx_falcon_gmac_ops,
148#else
149 NULL,
150#endif
151 /* [EFX_MAC_FALCON_XMAC] */
152#if EFSYS_OPT_MAC_FALCON_XMAC
153 &__efx_falcon_xmac_ops,
154#else
155 NULL,
156#endif
157 /* [EFX_MAC_SIENA] */
158#if EFSYS_OPT_SIENA
159 &__efx_siena_mac_ops,
160#else
161 NULL,
162#endif
163 /* [EFX_MAC_HUNTINGTON] */
164#if EFSYS_OPT_HUNTINGTON
165 &__efx_ef10_mac_ops,
166#else
167 NULL,
168#endif
169 /* [EFX_MAC_MEDFORD] */
170#if EFSYS_OPT_MEDFORD
171 &__efx_ef10_mac_ops,
172#else
173 NULL,
174#endif
175};
176
177 __checkReturn efx_rc_t
178efx_mac_pdu_set(
179 __in efx_nic_t *enp,
180 __in size_t pdu)
181{
182 efx_port_t *epp = &(enp->en_port);
183 efx_mac_ops_t *emop = epp->ep_emop;
184 uint32_t old_pdu;
185 efx_rc_t rc;
186
187 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
188 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
189 EFSYS_ASSERT(emop != NULL);
190
191 if (pdu < EFX_MAC_PDU_MIN) {
192 rc = EINVAL;
193 goto fail1;
194 }
195
196 if (pdu > EFX_MAC_PDU_MAX) {
197 rc = EINVAL;
198 goto fail2;
199 }
200
201 old_pdu = epp->ep_mac_pdu;
202 epp->ep_mac_pdu = (uint32_t)pdu;
203 if ((rc = emop->emo_pdu_set(enp)) != 0)
204 goto fail3;
205
206 return (0);
207
208fail3:
209 EFSYS_PROBE(fail3);
210
211 epp->ep_mac_pdu = old_pdu;
212
213fail2:
214 EFSYS_PROBE(fail2);
215fail1:
216 EFSYS_PROBE1(fail1, efx_rc_t, rc);
217
218 return (rc);
219}
220
221 __checkReturn efx_rc_t
222efx_mac_addr_set(
223 __in efx_nic_t *enp,
224 __in uint8_t *addr)
225{
226 efx_port_t *epp = &(enp->en_port);
227 efx_mac_ops_t *emop = epp->ep_emop;
228 uint8_t old_addr[6];
229 uint32_t oui;
230 efx_rc_t rc;
231
232 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
233 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
234
235 if (EFX_MAC_ADDR_IS_MULTICAST(addr)) {
236 rc = EINVAL;
237 goto fail1;
238 }
239
240 oui = addr[0] << 16 | addr[1] << 8 | addr[2];
241 if (oui == 0x000000) {
242 rc = EINVAL;
243 goto fail2;
244 }
245
246 EFX_MAC_ADDR_COPY(old_addr, epp->ep_mac_addr);
247 EFX_MAC_ADDR_COPY(epp->ep_mac_addr, addr);
248 if ((rc = emop->emo_addr_set(enp)) != 0)
249 goto fail3;
250
251 return (0);
252
253fail3:
254 EFSYS_PROBE(fail3);
255
256 EFX_MAC_ADDR_COPY(epp->ep_mac_addr, old_addr);
257
258fail2:
259 EFSYS_PROBE(fail2);
260fail1:
261 EFSYS_PROBE1(fail1, efx_rc_t, rc);
262
263 return (rc);
264}
265
266 __checkReturn efx_rc_t
267efx_mac_filter_set(
268 __in efx_nic_t *enp,
269 __in boolean_t all_unicst,
270 __in boolean_t mulcst,
271 __in boolean_t all_mulcst,
272 __in boolean_t brdcst)
273{
274 efx_port_t *epp = &(enp->en_port);
275 efx_mac_ops_t *emop = epp->ep_emop;
276 boolean_t old_all_unicst;
277 boolean_t old_mulcst;
278 boolean_t old_all_mulcst;
279 boolean_t old_brdcst;
280 efx_rc_t rc;
281
282 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
283 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
284
285 old_all_unicst = epp->ep_all_unicst;
286 old_mulcst = epp->ep_mulcst;
287 old_all_mulcst = epp->ep_all_mulcst;
288 old_brdcst = epp->ep_brdcst;
289
290 epp->ep_all_unicst = all_unicst;
291 epp->ep_mulcst = mulcst;
292 epp->ep_all_mulcst = all_mulcst;
293 epp->ep_brdcst = brdcst;
294
295 if ((rc = emop->emo_reconfigure(enp)) != 0)
296 goto fail1;
297
298 return (0);
299
300fail1:
301 EFSYS_PROBE1(fail1, efx_rc_t, rc);
302
303 epp->ep_all_unicst = old_all_unicst;
304 epp->ep_mulcst = old_mulcst;
305 epp->ep_all_mulcst = old_all_mulcst;
306 epp->ep_brdcst = old_brdcst;
307
308 return (rc);
309}
310
311 __checkReturn efx_rc_t
312efx_mac_drain(
313 __in efx_nic_t *enp,
314 __in boolean_t enabled)
315{
316 efx_port_t *epp = &(enp->en_port);
317 efx_mac_ops_t *emop = epp->ep_emop;
318 efx_rc_t rc;
319
320 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
321 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
322 EFSYS_ASSERT(emop != NULL);
323
324 if (epp->ep_mac_drain == enabled)
325 return (0);
326
327 epp->ep_mac_drain = enabled;
328
329 if (enabled && emop->emo_reset != NULL) {
330 if ((rc = emop->emo_reset(enp)) != 0)
331 goto fail1;
332
333 EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_MAC);
334 enp->en_reset_flags &= ~EFX_RESET_PHY;
335 }
336
337 if ((rc = emop->emo_reconfigure(enp)) != 0)
338 goto fail2;
339
340 return (0);
341
342fail2:
343 EFSYS_PROBE(fail2);
344fail1:
345 EFSYS_PROBE1(fail1, efx_rc_t, rc);
346
347 return (rc);
348}
349
350 __checkReturn efx_rc_t
351efx_mac_up(
352 __in efx_nic_t *enp,
353 __out boolean_t *mac_upp)
354{
355 efx_port_t *epp = &(enp->en_port);
356 efx_mac_ops_t *emop = epp->ep_emop;
357 efx_rc_t rc;
358
359 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
360 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
361
362 if ((rc = emop->emo_up(enp, mac_upp)) != 0)
363 goto fail1;
364
365 return (0);
366
367fail1:
368 EFSYS_PROBE1(fail1, efx_rc_t, rc);
369
370 return (rc);
371}
372
373 __checkReturn efx_rc_t
374efx_mac_fcntl_set(
375 __in efx_nic_t *enp,
376 __in unsigned int fcntl,
377 __in boolean_t autoneg)
378{
379 efx_port_t *epp = &(enp->en_port);
380 efx_mac_ops_t *emop = epp->ep_emop;
381 efx_phy_ops_t *epop = epp->ep_epop;
382 unsigned int old_fcntl;
383 boolean_t old_autoneg;
384 unsigned int old_adv_cap;
385 efx_rc_t rc;
386
387 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
388 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
389
390 if ((fcntl & ~(EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE)) != 0) {
391 rc = EINVAL;
392 goto fail1;
393 }
394
395 /*
396 * Ignore a request to set flow control auto-negotiation
397 * if the PHY doesn't support it.
398 */
399 if (~epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN))
400 autoneg = B_FALSE;
401
402 old_fcntl = epp->ep_fcntl;
403 old_autoneg = epp->ep_fcntl_autoneg;
404 old_adv_cap = epp->ep_adv_cap_mask;
405
406 epp->ep_fcntl = fcntl;
407 epp->ep_fcntl_autoneg = autoneg;
408
409 /*
410 * Always encode the flow control settings in the advertised
411 * capabilities even if we are not trying to auto-negotiate
412 * them and reconfigure both the PHY and the MAC.
413 */
414 if (fcntl & EFX_FCNTL_RESPOND)
415 epp->ep_adv_cap_mask |= (1 << EFX_PHY_CAP_PAUSE |
416 1 << EFX_PHY_CAP_ASYM);
417 else
418 epp->ep_adv_cap_mask &= ~(1 << EFX_PHY_CAP_PAUSE |
419 1 << EFX_PHY_CAP_ASYM);
420
421 if (fcntl & EFX_FCNTL_GENERATE)
422 epp->ep_adv_cap_mask ^= (1 << EFX_PHY_CAP_ASYM);
423
424 if ((rc = epop->epo_reconfigure(enp)) != 0)
425 goto fail2;
426
427 if ((rc = emop->emo_reconfigure(enp)) != 0)
428 goto fail3;
429
430 return (0);
431
432fail3:
433 EFSYS_PROBE(fail3);
434
435fail2:
436 EFSYS_PROBE(fail2);
437
438 epp->ep_fcntl = old_fcntl;
439 epp->ep_fcntl_autoneg = old_autoneg;
440 epp->ep_adv_cap_mask = old_adv_cap;
441
442fail1:
443 EFSYS_PROBE1(fail1, efx_rc_t, rc);
444
445 return (rc);
446}
447
448 void
449efx_mac_fcntl_get(
450 __in efx_nic_t *enp,
451 __out unsigned int *fcntl_wantedp,
452 __out unsigned int *fcntl_linkp)
453{
454 efx_port_t *epp = &(enp->en_port);
455 unsigned int wanted = 0;
456
457 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
458 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
459
460 /*
461 * Decode the requested flow control settings from the PHY
462 * advertised capabilities.
463 */
464 if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_PAUSE))
465 wanted = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE;
466 if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_ASYM))
467 wanted ^= EFX_FCNTL_GENERATE;
468
469 *fcntl_linkp = epp->ep_fcntl;
470 *fcntl_wantedp = wanted;
471}
472
473 __checkReturn efx_rc_t
474efx_mac_multicast_list_set(
475 __in efx_nic_t *enp,
476 __in_ecount(6*count) uint8_t const *addrs,
477 __in int count)
478{
479 efx_port_t *epp = &(enp->en_port);
480 efx_mac_ops_t *emop = epp->ep_emop;
481 uint8_t *old_mulcst_addr_list = NULL;
482 uint32_t old_mulcst_addr_count;
483 efx_rc_t rc;
484
485 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
486 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
487
488 if (count > EFX_MAC_MULTICAST_LIST_MAX) {
489 rc = EINVAL;
490 goto fail1;
491 }
492
493 old_mulcst_addr_count = epp->ep_mulcst_addr_count;
494 if (old_mulcst_addr_count > 0) {
495 /* Allocate memory to store old list (instead of using stack) */
496 EFSYS_KMEM_ALLOC(enp->en_esip,
497 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
498 old_mulcst_addr_list);
499 if (old_mulcst_addr_list == NULL) {
500 rc = ENOMEM;
501 goto fail2;
502 }
503
504 /* Save the old list in case we need to rollback */
505 memcpy(old_mulcst_addr_list, epp->ep_mulcst_addr_list,
506 old_mulcst_addr_count * EFX_MAC_ADDR_LEN);
507 }
508
509 /* Store the new list */
510 memcpy(epp->ep_mulcst_addr_list, addrs,
511 count * EFX_MAC_ADDR_LEN);
512 epp->ep_mulcst_addr_count = count;
513
514 if ((rc = emop->emo_multicast_list_set(enp)) != 0)
515 goto fail3;
516
517 if (old_mulcst_addr_count > 0) {
518 EFSYS_KMEM_FREE(enp->en_esip,
519 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
520 old_mulcst_addr_list);
521 }
522
523 return (0);
524
525fail3:
526 EFSYS_PROBE(fail3);
527
528 /* Restore original list on failure */
529 epp->ep_mulcst_addr_count = old_mulcst_addr_count;
530 if (old_mulcst_addr_count > 0) {
531 memcpy(epp->ep_mulcst_addr_list, old_mulcst_addr_list,
532 old_mulcst_addr_count * EFX_MAC_ADDR_LEN);
533
534 EFSYS_KMEM_FREE(enp->en_esip,
535 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
536 old_mulcst_addr_list);
537 }
538
539fail2:
540 EFSYS_PROBE(fail2);
541
542fail1:
543 EFSYS_PROBE1(fail1, efx_rc_t, rc);
544
545 return (rc);
546
547}
548
549 __checkReturn efx_rc_t
550efx_mac_filter_default_rxq_set(
551 __in efx_nic_t *enp,
552 __in efx_rxq_t *erp,
553 __in boolean_t using_rss)
554{
555 efx_port_t *epp = &(enp->en_port);
556 efx_mac_ops_t *emop = epp->ep_emop;
557 efx_rc_t rc;
558
559 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
560 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
561
562 if (emop->emo_filter_default_rxq_set != NULL) {
563 rc = emop->emo_filter_default_rxq_set(enp, erp, using_rss);
564 if (rc != 0)
565 goto fail1;
566 }
567
568 return (0);
569
570fail1:
571 EFSYS_PROBE1(fail1, efx_rc_t, rc);
572
573 return (rc);
574}
575
576 void
577efx_mac_filter_default_rxq_clear(
578 __in efx_nic_t *enp)
579{
580 efx_port_t *epp = &(enp->en_port);
581 efx_mac_ops_t *emop = epp->ep_emop;
582
583 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
584 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
585
586 if (emop->emo_filter_default_rxq_clear != NULL)
587 emop->emo_filter_default_rxq_clear(enp);
588}
589
590
591#if EFSYS_OPT_MAC_STATS
592
593#if EFSYS_OPT_NAMES
594
595/* START MKCONFIG GENERATED EfxMacStatNamesBlock 054d43a31d2d7a45 */
596static const char *__efx_mac_stat_name[] = {
597 "rx_octets",
598 "rx_pkts",
599 "rx_unicst_pkts",
600 "rx_multicst_pkts",
601 "rx_brdcst_pkts",
602 "rx_pause_pkts",
603 "rx_le_64_pkts",
604 "rx_65_to_127_pkts",
605 "rx_128_to_255_pkts",
606 "rx_256_to_511_pkts",
607 "rx_512_to_1023_pkts",
608 "rx_1024_to_15xx_pkts",
609 "rx_ge_15xx_pkts",
610 "rx_errors",
611 "rx_fcs_errors",
612 "rx_drop_events",
613 "rx_false_carrier_errors",
614 "rx_symbol_errors",
615 "rx_align_errors",
616 "rx_internal_errors",
617 "rx_jabber_pkts",
618 "rx_lane0_char_err",
619 "rx_lane1_char_err",
620 "rx_lane2_char_err",
621 "rx_lane3_char_err",
622 "rx_lane0_disp_err",
623 "rx_lane1_disp_err",
624 "rx_lane2_disp_err",
625 "rx_lane3_disp_err",
626 "rx_match_fault",
627 "rx_nodesc_drop_cnt",
628 "tx_octets",
629 "tx_pkts",
630 "tx_unicst_pkts",
631 "tx_multicst_pkts",
632 "tx_brdcst_pkts",
633 "tx_pause_pkts",
634 "tx_le_64_pkts",
635 "tx_65_to_127_pkts",
636 "tx_128_to_255_pkts",
637 "tx_256_to_511_pkts",
638 "tx_512_to_1023_pkts",
639 "tx_1024_to_15xx_pkts",
640 "tx_ge_15xx_pkts",
641 "tx_errors",
642 "tx_sgl_col_pkts",
643 "tx_mult_col_pkts",
644 "tx_ex_col_pkts",
645 "tx_late_col_pkts",
646 "tx_def_pkts",
647 "tx_ex_def_pkts",
648 "pm_trunc_bb_overflow",
649 "pm_discard_bb_overflow",
650 "pm_trunc_vfifo_full",
651 "pm_discard_vfifo_full",
652 "pm_trunc_qbb",
653 "pm_discard_qbb",
654 "pm_discard_mapping",
655 "rxdp_q_disabled_pkts",
656 "rxdp_di_dropped_pkts",
657 "rxdp_streaming_pkts",
658 "rxdp_hlb_fetch",
659 "rxdp_hlb_wait",
660 "vadapter_rx_unicast_packets",
661 "vadapter_rx_unicast_bytes",
662 "vadapter_rx_multicast_packets",
663 "vadapter_rx_multicast_bytes",
664 "vadapter_rx_broadcast_packets",
665 "vadapter_rx_broadcast_bytes",
666 "vadapter_rx_bad_packets",
667 "vadapter_rx_bad_bytes",
668 "vadapter_rx_overflow",
669 "vadapter_tx_unicast_packets",
670 "vadapter_tx_unicast_bytes",
671 "vadapter_tx_multicast_packets",
672 "vadapter_tx_multicast_bytes",
673 "vadapter_tx_broadcast_packets",
674 "vadapter_tx_broadcast_bytes",
675 "vadapter_tx_bad_packets",
676 "vadapter_tx_bad_bytes",
677 "vadapter_tx_overflow",
678};
679/* END MKCONFIG GENERATED EfxMacStatNamesBlock */
680
681 __checkReturn const char *
682efx_mac_stat_name(
683 __in efx_nic_t *enp,
684 __in unsigned int id)
685{
686 _NOTE(ARGUNUSED(enp))
687 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
688
689 EFSYS_ASSERT3U(id, <, EFX_MAC_NSTATS);
690 return (__efx_mac_stat_name[id]);
691}
692
693#endif /* EFSYS_OPT_NAMES */
694
695 __checkReturn efx_rc_t
696efx_mac_stats_upload(
697 __in efx_nic_t *enp,
698 __in efsys_mem_t *esmp)
699{
700 efx_port_t *epp = &(enp->en_port);
701 efx_mac_ops_t *emop = epp->ep_emop;
702 efx_rc_t rc;
703
704 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
705 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
706 EFSYS_ASSERT(emop != NULL);
707
708 /*
709 * Don't assert !ep_mac_stats_pending, because the client might
710 * have failed to finalise statistics when previously stopping
711 * the port.
712 */
713 if ((rc = emop->emo_stats_upload(enp, esmp)) != 0)
714 goto fail1;
715
716 epp->ep_mac_stats_pending = B_TRUE;
717
718 return (0);
719
720fail1:
721 EFSYS_PROBE1(fail1, efx_rc_t, rc);
722
723 return (rc);
724}
725
726 __checkReturn efx_rc_t
727efx_mac_stats_periodic(
728 __in efx_nic_t *enp,
729 __in efsys_mem_t *esmp,
730 __in uint16_t period_ms,
731 __in boolean_t events)
732{
733 efx_port_t *epp = &(enp->en_port);
734 efx_mac_ops_t *emop = epp->ep_emop;
735 efx_rc_t rc;
736
737 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
738 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
739
740 EFSYS_ASSERT(emop != NULL);
741
742 if (emop->emo_stats_periodic == NULL) {
743 rc = EINVAL;
744 goto fail1;
745 }
746
747 if ((rc = emop->emo_stats_periodic(enp, esmp, period_ms, events)) != 0)
748 goto fail2;
749
750 return (0);
751
752fail2:
753 EFSYS_PROBE(fail2);
754fail1:
755 EFSYS_PROBE1(fail1, efx_rc_t, rc);
756
757 return (rc);
758}
759
760
761 __checkReturn efx_rc_t
762efx_mac_stats_update(
763 __in efx_nic_t *enp,
764 __in efsys_mem_t *esmp,
765 __inout_ecount(EFX_MAC_NSTATS) efsys_stat_t *essp,
766 __inout_opt uint32_t *generationp)
767{
768 efx_port_t *epp = &(enp->en_port);
769 efx_mac_ops_t *emop = epp->ep_emop;
770 efx_rc_t rc;
771
772 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
773 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
774 EFSYS_ASSERT(emop != NULL);
775
776 rc = emop->emo_stats_update(enp, esmp, essp, generationp);
777 if (rc == 0)
778 epp->ep_mac_stats_pending = B_FALSE;
779
780 return (rc);
781}
782
783#endif /* EFSYS_OPT_MAC_STATS */
784
785 __checkReturn efx_rc_t
786efx_mac_select(
787 __in efx_nic_t *enp)
788{
789 efx_port_t *epp = &(enp->en_port);
790 efx_mac_type_t type = EFX_MAC_INVALID;
791 efx_mac_ops_t *emop;
792 int rc = EINVAL;
793
794#if EFSYS_OPT_SIENA
795 if (enp->en_family == EFX_FAMILY_SIENA) {
796 type = EFX_MAC_SIENA;
797 goto chosen;
798 }
799#endif
800
801#if EFSYS_OPT_HUNTINGTON
802 if (enp->en_family == EFX_FAMILY_HUNTINGTON) {
803 type = EFX_MAC_HUNTINGTON;
804 goto chosen;
805 }
806#endif
807
808#if EFSYS_OPT_MEDFORD
809 if (enp->en_family == EFX_FAMILY_MEDFORD) {
810 type = EFX_MAC_MEDFORD;
811 goto chosen;
812 }
813#endif
814
815#if EFSYS_OPT_FALCON
816 switch (epp->ep_link_mode) {
817#if EFSYS_OPT_MAC_FALCON_GMAC
818 case EFX_LINK_100HDX:
819 case EFX_LINK_100FDX:
820 case EFX_LINK_1000HDX:
821 case EFX_LINK_1000FDX:
822 type = EFX_MAC_FALCON_GMAC;
823 goto chosen;
824#endif /* EFSYS_OPT_FALCON_GMAC */
825
826#if EFSYS_OPT_MAC_FALCON_XMAC
827 case EFX_LINK_10000FDX:
828 type = EFX_MAC_FALCON_XMAC;
829 goto chosen;
830#endif /* EFSYS_OPT_FALCON_XMAC */
831
832 default:
833#if EFSYS_OPT_MAC_FALCON_GMAC && EFSYS_OPT_MAC_FALCON_XMAC
834 /* Only initialise a MAC supported by the PHY */
835 if (epp->ep_phy_cap_mask &
836 ((1 << EFX_PHY_CAP_1000FDX) |
837 (1 << EFX_PHY_CAP_1000HDX) |
838 (1 << EFX_PHY_CAP_100FDX) |
839 (1 << EFX_PHY_CAP_100HDX) |
840 (1 << EFX_PHY_CAP_10FDX) |
841 (1 << EFX_PHY_CAP_10FDX)))
842 type = EFX_MAC_FALCON_GMAC;
843 else
844 type = EFX_MAC_FALCON_XMAC;
845#elif EFSYS_OPT_MAC_FALCON_GMAC
846 type = EFX_MAC_FALCON_GMAC;
847#else
848 type = EFX_MAC_FALCON_XMAC;
849#endif
850 goto chosen;
851 }
852#endif /* EFSYS_OPT_FALCON */
853
854chosen:
855 EFSYS_ASSERT(type != EFX_MAC_INVALID);
856 EFSYS_ASSERT3U(type, <, EFX_MAC_NTYPES);
857 emop = epp->ep_emop = (efx_mac_ops_t *)__efx_mac_ops[type];
858 EFSYS_ASSERT(emop != NULL);
859
860 epp->ep_mac_type = type;
861
862 if (emop->emo_reset != NULL) {
863 if ((rc = emop->emo_reset(enp)) != 0)
864 goto fail1;
865
866 EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_MAC);
867 enp->en_reset_flags &= ~EFX_RESET_MAC;
868 }
869
870 return (0);
871
872fail1:
873 EFSYS_PROBE1(fail1, efx_rc_t, rc);
874
875 return (rc);
876}
877
878
879#if EFSYS_OPT_FALCON || EFSYS_OPT_SIENA
880
881#define EFX_MAC_HASH_BITS (1 << 8)
882
883/* Compute the multicast hash as used on Falcon and Siena. */
884static void
885falconsiena_mac_multicast_hash_compute(
886 __in_ecount(6*count) uint8_t const *addrs,
887 __in int count,
888 __out efx_oword_t *hash_low,
889 __out efx_oword_t *hash_high)
890{
891 uint32_t crc, index;
892 int i;
893
894 EFSYS_ASSERT(hash_low != NULL);
895 EFSYS_ASSERT(hash_high != NULL);
896
897 EFX_ZERO_OWORD(*hash_low);
898 EFX_ZERO_OWORD(*hash_high);
899
900 for (i = 0; i < count; i++) {
901 /* Calculate hash bucket (IEEE 802.3 CRC32 of the MAC addr) */
902 crc = efx_crc32_calculate(0xffffffff, addrs, EFX_MAC_ADDR_LEN);
903 index = crc % EFX_MAC_HASH_BITS;
904 if (index < 128) {
905 EFX_SET_OWORD_BIT(*hash_low, index);
906 } else {
907 EFX_SET_OWORD_BIT(*hash_high, index - 128);
908 }
909
910 addrs += EFX_MAC_ADDR_LEN;
911 }
912}
913
914static __checkReturn efx_rc_t
915falconsiena_mac_multicast_list_set(
916 __in efx_nic_t *enp)
917{
918 efx_port_t *epp = &(enp->en_port);
919 efx_mac_ops_t *emop = epp->ep_emop;
920 efx_oword_t old_hash[2];
921 efx_rc_t rc;
922
923 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
924 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
925
926 memcpy(old_hash, epp->ep_multicst_hash, sizeof (old_hash));
927
928 falconsiena_mac_multicast_hash_compute(epp->ep_mulcst_addr_list,
929 epp->ep_mulcst_addr_count,
930 &epp->ep_multicst_hash[0],
931 &epp->ep_multicst_hash[1]);
932
933 if ((rc = emop->emo_reconfigure(enp)) != 0)
934 goto fail1;
935
936 return (0);
937
938fail1:
939 EFSYS_PROBE1(fail1, efx_rc_t, rc);
940
941 memcpy(epp->ep_multicst_hash, old_hash, sizeof (old_hash));
942
943 return (rc);
944}
945
946#endif /* EFSYS_OPT_FALCON || EFSYS_OPT_SIENA */
2 * Copyright (c) 2007-2015 Solarflare Communications Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * The views and conclusions contained in the software and documentation are
27 * those of the authors and should not be interpreted as representing official
28 * policies, either expressed or implied, of the FreeBSD Project.
29 */
30
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD: head/sys/dev/sfxge/common/efx_mac.c 294253 2016-01-18 06:19:28Z arybchik $");
33
34#include "efx.h"
35#include "efx_impl.h"
36
37#if EFSYS_OPT_MAC_FALCON_GMAC
38#include "falcon_gmac.h"
39#endif
40
41#if EFSYS_OPT_MAC_FALCON_XMAC
42#include "falcon_xmac.h"
43#endif
44
45#if EFSYS_OPT_FALCON || EFSYS_OPT_SIENA
46
47static __checkReturn efx_rc_t
48falconsiena_mac_multicast_list_set(
49 __in efx_nic_t *enp);
50
51#endif /* EFSYS_OPT_FALCON || EFSYS_OPT_SIENA */
52
53#if EFSYS_OPT_MAC_FALCON_GMAC
54static efx_mac_ops_t __efx_falcon_gmac_ops = {
55 falcon_gmac_reset, /* emo_reset */
56 falcon_mac_poll, /* emo_poll */
57 falcon_mac_up, /* emo_up */
58 falcon_gmac_reconfigure, /* emo_addr_set */
59 falcon_gmac_reconfigure, /* emo_pdu_set */
60 falcon_gmac_reconfigure, /* emo_reconfigure */
61 falconsiena_mac_multicast_list_set, /* emo_multicast_list_set */
62 NULL, /* emo_filter_set_default_rxq */
63 NULL, /* emo_filter_default_rxq_clear */
64#if EFSYS_OPT_LOOPBACK
65 falcon_mac_loopback_set, /* emo_loopback_set */
66#endif /* EFSYS_OPT_LOOPBACK */
67#if EFSYS_OPT_MAC_STATS
68 falcon_mac_stats_upload, /* emo_stats_upload */
69 NULL, /* emo_stats_periodic */
70 falcon_gmac_stats_update /* emo_stats_update */
71#endif /* EFSYS_OPT_MAC_STATS */
72};
73#endif /* EFSYS_OPT_MAC_FALCON_GMAC */
74
75#if EFSYS_OPT_MAC_FALCON_XMAC
76static efx_mac_ops_t __efx_falcon_xmac_ops = {
77 falcon_xmac_reset, /* emo_reset */
78 falcon_mac_poll, /* emo_poll */
79 falcon_mac_up, /* emo_up */
80 falcon_xmac_reconfigure, /* emo_addr_set */
81 falcon_xmac_reconfigure, /* emo_pdu_set */
82 falcon_xmac_reconfigure, /* emo_reconfigure */
83 falconsiena_mac_multicast_list_set, /* emo_multicast_list_set */
84 NULL, /* emo_filter_set_default_rxq */
85 NULL, /* emo_filter_default_rxq_clear */
86#if EFSYS_OPT_LOOPBACK
87 falcon_mac_loopback_set, /* emo_loopback_set */
88#endif /* EFSYS_OPT_LOOPBACK */
89#if EFSYS_OPT_MAC_STATS
90 falcon_mac_stats_upload, /* emo_stats_upload */
91 NULL, /* emo_stats_periodic */
92 falcon_xmac_stats_update /* emo_stats_update */
93#endif /* EFSYS_OPT_MAC_STATS */
94};
95#endif /* EFSYS_OPT_MAC_FALCON_XMAC */
96
97#if EFSYS_OPT_SIENA
98static efx_mac_ops_t __efx_siena_mac_ops = {
99 NULL, /* emo_reset */
100 siena_mac_poll, /* emo_poll */
101 siena_mac_up, /* emo_up */
102 siena_mac_reconfigure, /* emo_addr_set */
103 siena_mac_reconfigure, /* emo_pdu_set */
104 siena_mac_reconfigure, /* emo_reconfigure */
105 falconsiena_mac_multicast_list_set, /* emo_multicast_list_set */
106 NULL, /* emo_filter_set_default_rxq */
107 NULL, /* emo_filter_default_rxq_clear */
108#if EFSYS_OPT_LOOPBACK
109 siena_mac_loopback_set, /* emo_loopback_set */
110#endif /* EFSYS_OPT_LOOPBACK */
111#if EFSYS_OPT_MAC_STATS
112 efx_mcdi_mac_stats_upload, /* emo_stats_upload */
113 efx_mcdi_mac_stats_periodic, /* emo_stats_periodic */
114 siena_mac_stats_update /* emo_stats_update */
115#endif /* EFSYS_OPT_MAC_STATS */
116};
117#endif /* EFSYS_OPT_SIENA */
118
119#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
120static efx_mac_ops_t __efx_ef10_mac_ops = {
121 NULL, /* emo_reset */
122 ef10_mac_poll, /* emo_poll */
123 ef10_mac_up, /* emo_up */
124 ef10_mac_addr_set, /* emo_addr_set */
125 ef10_mac_pdu_set, /* emo_pdu_set */
126 ef10_mac_reconfigure, /* emo_reconfigure */
127 ef10_mac_multicast_list_set, /* emo_multicast_list_set */
128 ef10_mac_filter_default_rxq_set, /* emo_filter_default_rxq_set */
129 ef10_mac_filter_default_rxq_clear,
130 /* emo_filter_default_rxq_clear */
131#if EFSYS_OPT_LOOPBACK
132 ef10_mac_loopback_set, /* emo_loopback_set */
133#endif /* EFSYS_OPT_LOOPBACK */
134#if EFSYS_OPT_MAC_STATS
135 efx_mcdi_mac_stats_upload, /* emo_stats_upload */
136 efx_mcdi_mac_stats_periodic, /* emo_stats_periodic */
137 ef10_mac_stats_update /* emo_stats_update */
138#endif /* EFSYS_OPT_MAC_STATS */
139};
140#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
141
142static efx_mac_ops_t *__efx_mac_ops[] = {
143 /* [EFX_MAC_INVALID] */
144 NULL,
145 /* [EFX_MAC_FALCON_GMAC] */
146#if EFSYS_OPT_MAC_FALCON_GMAC
147 &__efx_falcon_gmac_ops,
148#else
149 NULL,
150#endif
151 /* [EFX_MAC_FALCON_XMAC] */
152#if EFSYS_OPT_MAC_FALCON_XMAC
153 &__efx_falcon_xmac_ops,
154#else
155 NULL,
156#endif
157 /* [EFX_MAC_SIENA] */
158#if EFSYS_OPT_SIENA
159 &__efx_siena_mac_ops,
160#else
161 NULL,
162#endif
163 /* [EFX_MAC_HUNTINGTON] */
164#if EFSYS_OPT_HUNTINGTON
165 &__efx_ef10_mac_ops,
166#else
167 NULL,
168#endif
169 /* [EFX_MAC_MEDFORD] */
170#if EFSYS_OPT_MEDFORD
171 &__efx_ef10_mac_ops,
172#else
173 NULL,
174#endif
175};
176
177 __checkReturn efx_rc_t
178efx_mac_pdu_set(
179 __in efx_nic_t *enp,
180 __in size_t pdu)
181{
182 efx_port_t *epp = &(enp->en_port);
183 efx_mac_ops_t *emop = epp->ep_emop;
184 uint32_t old_pdu;
185 efx_rc_t rc;
186
187 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
188 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
189 EFSYS_ASSERT(emop != NULL);
190
191 if (pdu < EFX_MAC_PDU_MIN) {
192 rc = EINVAL;
193 goto fail1;
194 }
195
196 if (pdu > EFX_MAC_PDU_MAX) {
197 rc = EINVAL;
198 goto fail2;
199 }
200
201 old_pdu = epp->ep_mac_pdu;
202 epp->ep_mac_pdu = (uint32_t)pdu;
203 if ((rc = emop->emo_pdu_set(enp)) != 0)
204 goto fail3;
205
206 return (0);
207
208fail3:
209 EFSYS_PROBE(fail3);
210
211 epp->ep_mac_pdu = old_pdu;
212
213fail2:
214 EFSYS_PROBE(fail2);
215fail1:
216 EFSYS_PROBE1(fail1, efx_rc_t, rc);
217
218 return (rc);
219}
220
221 __checkReturn efx_rc_t
222efx_mac_addr_set(
223 __in efx_nic_t *enp,
224 __in uint8_t *addr)
225{
226 efx_port_t *epp = &(enp->en_port);
227 efx_mac_ops_t *emop = epp->ep_emop;
228 uint8_t old_addr[6];
229 uint32_t oui;
230 efx_rc_t rc;
231
232 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
233 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
234
235 if (EFX_MAC_ADDR_IS_MULTICAST(addr)) {
236 rc = EINVAL;
237 goto fail1;
238 }
239
240 oui = addr[0] << 16 | addr[1] << 8 | addr[2];
241 if (oui == 0x000000) {
242 rc = EINVAL;
243 goto fail2;
244 }
245
246 EFX_MAC_ADDR_COPY(old_addr, epp->ep_mac_addr);
247 EFX_MAC_ADDR_COPY(epp->ep_mac_addr, addr);
248 if ((rc = emop->emo_addr_set(enp)) != 0)
249 goto fail3;
250
251 return (0);
252
253fail3:
254 EFSYS_PROBE(fail3);
255
256 EFX_MAC_ADDR_COPY(epp->ep_mac_addr, old_addr);
257
258fail2:
259 EFSYS_PROBE(fail2);
260fail1:
261 EFSYS_PROBE1(fail1, efx_rc_t, rc);
262
263 return (rc);
264}
265
266 __checkReturn efx_rc_t
267efx_mac_filter_set(
268 __in efx_nic_t *enp,
269 __in boolean_t all_unicst,
270 __in boolean_t mulcst,
271 __in boolean_t all_mulcst,
272 __in boolean_t brdcst)
273{
274 efx_port_t *epp = &(enp->en_port);
275 efx_mac_ops_t *emop = epp->ep_emop;
276 boolean_t old_all_unicst;
277 boolean_t old_mulcst;
278 boolean_t old_all_mulcst;
279 boolean_t old_brdcst;
280 efx_rc_t rc;
281
282 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
283 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
284
285 old_all_unicst = epp->ep_all_unicst;
286 old_mulcst = epp->ep_mulcst;
287 old_all_mulcst = epp->ep_all_mulcst;
288 old_brdcst = epp->ep_brdcst;
289
290 epp->ep_all_unicst = all_unicst;
291 epp->ep_mulcst = mulcst;
292 epp->ep_all_mulcst = all_mulcst;
293 epp->ep_brdcst = brdcst;
294
295 if ((rc = emop->emo_reconfigure(enp)) != 0)
296 goto fail1;
297
298 return (0);
299
300fail1:
301 EFSYS_PROBE1(fail1, efx_rc_t, rc);
302
303 epp->ep_all_unicst = old_all_unicst;
304 epp->ep_mulcst = old_mulcst;
305 epp->ep_all_mulcst = old_all_mulcst;
306 epp->ep_brdcst = old_brdcst;
307
308 return (rc);
309}
310
311 __checkReturn efx_rc_t
312efx_mac_drain(
313 __in efx_nic_t *enp,
314 __in boolean_t enabled)
315{
316 efx_port_t *epp = &(enp->en_port);
317 efx_mac_ops_t *emop = epp->ep_emop;
318 efx_rc_t rc;
319
320 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
321 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
322 EFSYS_ASSERT(emop != NULL);
323
324 if (epp->ep_mac_drain == enabled)
325 return (0);
326
327 epp->ep_mac_drain = enabled;
328
329 if (enabled && emop->emo_reset != NULL) {
330 if ((rc = emop->emo_reset(enp)) != 0)
331 goto fail1;
332
333 EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_MAC);
334 enp->en_reset_flags &= ~EFX_RESET_PHY;
335 }
336
337 if ((rc = emop->emo_reconfigure(enp)) != 0)
338 goto fail2;
339
340 return (0);
341
342fail2:
343 EFSYS_PROBE(fail2);
344fail1:
345 EFSYS_PROBE1(fail1, efx_rc_t, rc);
346
347 return (rc);
348}
349
350 __checkReturn efx_rc_t
351efx_mac_up(
352 __in efx_nic_t *enp,
353 __out boolean_t *mac_upp)
354{
355 efx_port_t *epp = &(enp->en_port);
356 efx_mac_ops_t *emop = epp->ep_emop;
357 efx_rc_t rc;
358
359 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
360 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
361
362 if ((rc = emop->emo_up(enp, mac_upp)) != 0)
363 goto fail1;
364
365 return (0);
366
367fail1:
368 EFSYS_PROBE1(fail1, efx_rc_t, rc);
369
370 return (rc);
371}
372
373 __checkReturn efx_rc_t
374efx_mac_fcntl_set(
375 __in efx_nic_t *enp,
376 __in unsigned int fcntl,
377 __in boolean_t autoneg)
378{
379 efx_port_t *epp = &(enp->en_port);
380 efx_mac_ops_t *emop = epp->ep_emop;
381 efx_phy_ops_t *epop = epp->ep_epop;
382 unsigned int old_fcntl;
383 boolean_t old_autoneg;
384 unsigned int old_adv_cap;
385 efx_rc_t rc;
386
387 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
388 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
389
390 if ((fcntl & ~(EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE)) != 0) {
391 rc = EINVAL;
392 goto fail1;
393 }
394
395 /*
396 * Ignore a request to set flow control auto-negotiation
397 * if the PHY doesn't support it.
398 */
399 if (~epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN))
400 autoneg = B_FALSE;
401
402 old_fcntl = epp->ep_fcntl;
403 old_autoneg = epp->ep_fcntl_autoneg;
404 old_adv_cap = epp->ep_adv_cap_mask;
405
406 epp->ep_fcntl = fcntl;
407 epp->ep_fcntl_autoneg = autoneg;
408
409 /*
410 * Always encode the flow control settings in the advertised
411 * capabilities even if we are not trying to auto-negotiate
412 * them and reconfigure both the PHY and the MAC.
413 */
414 if (fcntl & EFX_FCNTL_RESPOND)
415 epp->ep_adv_cap_mask |= (1 << EFX_PHY_CAP_PAUSE |
416 1 << EFX_PHY_CAP_ASYM);
417 else
418 epp->ep_adv_cap_mask &= ~(1 << EFX_PHY_CAP_PAUSE |
419 1 << EFX_PHY_CAP_ASYM);
420
421 if (fcntl & EFX_FCNTL_GENERATE)
422 epp->ep_adv_cap_mask ^= (1 << EFX_PHY_CAP_ASYM);
423
424 if ((rc = epop->epo_reconfigure(enp)) != 0)
425 goto fail2;
426
427 if ((rc = emop->emo_reconfigure(enp)) != 0)
428 goto fail3;
429
430 return (0);
431
432fail3:
433 EFSYS_PROBE(fail3);
434
435fail2:
436 EFSYS_PROBE(fail2);
437
438 epp->ep_fcntl = old_fcntl;
439 epp->ep_fcntl_autoneg = old_autoneg;
440 epp->ep_adv_cap_mask = old_adv_cap;
441
442fail1:
443 EFSYS_PROBE1(fail1, efx_rc_t, rc);
444
445 return (rc);
446}
447
448 void
449efx_mac_fcntl_get(
450 __in efx_nic_t *enp,
451 __out unsigned int *fcntl_wantedp,
452 __out unsigned int *fcntl_linkp)
453{
454 efx_port_t *epp = &(enp->en_port);
455 unsigned int wanted = 0;
456
457 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
458 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
459
460 /*
461 * Decode the requested flow control settings from the PHY
462 * advertised capabilities.
463 */
464 if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_PAUSE))
465 wanted = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE;
466 if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_ASYM))
467 wanted ^= EFX_FCNTL_GENERATE;
468
469 *fcntl_linkp = epp->ep_fcntl;
470 *fcntl_wantedp = wanted;
471}
472
473 __checkReturn efx_rc_t
474efx_mac_multicast_list_set(
475 __in efx_nic_t *enp,
476 __in_ecount(6*count) uint8_t const *addrs,
477 __in int count)
478{
479 efx_port_t *epp = &(enp->en_port);
480 efx_mac_ops_t *emop = epp->ep_emop;
481 uint8_t *old_mulcst_addr_list = NULL;
482 uint32_t old_mulcst_addr_count;
483 efx_rc_t rc;
484
485 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
486 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
487
488 if (count > EFX_MAC_MULTICAST_LIST_MAX) {
489 rc = EINVAL;
490 goto fail1;
491 }
492
493 old_mulcst_addr_count = epp->ep_mulcst_addr_count;
494 if (old_mulcst_addr_count > 0) {
495 /* Allocate memory to store old list (instead of using stack) */
496 EFSYS_KMEM_ALLOC(enp->en_esip,
497 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
498 old_mulcst_addr_list);
499 if (old_mulcst_addr_list == NULL) {
500 rc = ENOMEM;
501 goto fail2;
502 }
503
504 /* Save the old list in case we need to rollback */
505 memcpy(old_mulcst_addr_list, epp->ep_mulcst_addr_list,
506 old_mulcst_addr_count * EFX_MAC_ADDR_LEN);
507 }
508
509 /* Store the new list */
510 memcpy(epp->ep_mulcst_addr_list, addrs,
511 count * EFX_MAC_ADDR_LEN);
512 epp->ep_mulcst_addr_count = count;
513
514 if ((rc = emop->emo_multicast_list_set(enp)) != 0)
515 goto fail3;
516
517 if (old_mulcst_addr_count > 0) {
518 EFSYS_KMEM_FREE(enp->en_esip,
519 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
520 old_mulcst_addr_list);
521 }
522
523 return (0);
524
525fail3:
526 EFSYS_PROBE(fail3);
527
528 /* Restore original list on failure */
529 epp->ep_mulcst_addr_count = old_mulcst_addr_count;
530 if (old_mulcst_addr_count > 0) {
531 memcpy(epp->ep_mulcst_addr_list, old_mulcst_addr_list,
532 old_mulcst_addr_count * EFX_MAC_ADDR_LEN);
533
534 EFSYS_KMEM_FREE(enp->en_esip,
535 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
536 old_mulcst_addr_list);
537 }
538
539fail2:
540 EFSYS_PROBE(fail2);
541
542fail1:
543 EFSYS_PROBE1(fail1, efx_rc_t, rc);
544
545 return (rc);
546
547}
548
549 __checkReturn efx_rc_t
550efx_mac_filter_default_rxq_set(
551 __in efx_nic_t *enp,
552 __in efx_rxq_t *erp,
553 __in boolean_t using_rss)
554{
555 efx_port_t *epp = &(enp->en_port);
556 efx_mac_ops_t *emop = epp->ep_emop;
557 efx_rc_t rc;
558
559 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
560 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
561
562 if (emop->emo_filter_default_rxq_set != NULL) {
563 rc = emop->emo_filter_default_rxq_set(enp, erp, using_rss);
564 if (rc != 0)
565 goto fail1;
566 }
567
568 return (0);
569
570fail1:
571 EFSYS_PROBE1(fail1, efx_rc_t, rc);
572
573 return (rc);
574}
575
576 void
577efx_mac_filter_default_rxq_clear(
578 __in efx_nic_t *enp)
579{
580 efx_port_t *epp = &(enp->en_port);
581 efx_mac_ops_t *emop = epp->ep_emop;
582
583 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
584 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
585
586 if (emop->emo_filter_default_rxq_clear != NULL)
587 emop->emo_filter_default_rxq_clear(enp);
588}
589
590
591#if EFSYS_OPT_MAC_STATS
592
593#if EFSYS_OPT_NAMES
594
595/* START MKCONFIG GENERATED EfxMacStatNamesBlock 054d43a31d2d7a45 */
596static const char *__efx_mac_stat_name[] = {
597 "rx_octets",
598 "rx_pkts",
599 "rx_unicst_pkts",
600 "rx_multicst_pkts",
601 "rx_brdcst_pkts",
602 "rx_pause_pkts",
603 "rx_le_64_pkts",
604 "rx_65_to_127_pkts",
605 "rx_128_to_255_pkts",
606 "rx_256_to_511_pkts",
607 "rx_512_to_1023_pkts",
608 "rx_1024_to_15xx_pkts",
609 "rx_ge_15xx_pkts",
610 "rx_errors",
611 "rx_fcs_errors",
612 "rx_drop_events",
613 "rx_false_carrier_errors",
614 "rx_symbol_errors",
615 "rx_align_errors",
616 "rx_internal_errors",
617 "rx_jabber_pkts",
618 "rx_lane0_char_err",
619 "rx_lane1_char_err",
620 "rx_lane2_char_err",
621 "rx_lane3_char_err",
622 "rx_lane0_disp_err",
623 "rx_lane1_disp_err",
624 "rx_lane2_disp_err",
625 "rx_lane3_disp_err",
626 "rx_match_fault",
627 "rx_nodesc_drop_cnt",
628 "tx_octets",
629 "tx_pkts",
630 "tx_unicst_pkts",
631 "tx_multicst_pkts",
632 "tx_brdcst_pkts",
633 "tx_pause_pkts",
634 "tx_le_64_pkts",
635 "tx_65_to_127_pkts",
636 "tx_128_to_255_pkts",
637 "tx_256_to_511_pkts",
638 "tx_512_to_1023_pkts",
639 "tx_1024_to_15xx_pkts",
640 "tx_ge_15xx_pkts",
641 "tx_errors",
642 "tx_sgl_col_pkts",
643 "tx_mult_col_pkts",
644 "tx_ex_col_pkts",
645 "tx_late_col_pkts",
646 "tx_def_pkts",
647 "tx_ex_def_pkts",
648 "pm_trunc_bb_overflow",
649 "pm_discard_bb_overflow",
650 "pm_trunc_vfifo_full",
651 "pm_discard_vfifo_full",
652 "pm_trunc_qbb",
653 "pm_discard_qbb",
654 "pm_discard_mapping",
655 "rxdp_q_disabled_pkts",
656 "rxdp_di_dropped_pkts",
657 "rxdp_streaming_pkts",
658 "rxdp_hlb_fetch",
659 "rxdp_hlb_wait",
660 "vadapter_rx_unicast_packets",
661 "vadapter_rx_unicast_bytes",
662 "vadapter_rx_multicast_packets",
663 "vadapter_rx_multicast_bytes",
664 "vadapter_rx_broadcast_packets",
665 "vadapter_rx_broadcast_bytes",
666 "vadapter_rx_bad_packets",
667 "vadapter_rx_bad_bytes",
668 "vadapter_rx_overflow",
669 "vadapter_tx_unicast_packets",
670 "vadapter_tx_unicast_bytes",
671 "vadapter_tx_multicast_packets",
672 "vadapter_tx_multicast_bytes",
673 "vadapter_tx_broadcast_packets",
674 "vadapter_tx_broadcast_bytes",
675 "vadapter_tx_bad_packets",
676 "vadapter_tx_bad_bytes",
677 "vadapter_tx_overflow",
678};
679/* END MKCONFIG GENERATED EfxMacStatNamesBlock */
680
681 __checkReturn const char *
682efx_mac_stat_name(
683 __in efx_nic_t *enp,
684 __in unsigned int id)
685{
686 _NOTE(ARGUNUSED(enp))
687 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
688
689 EFSYS_ASSERT3U(id, <, EFX_MAC_NSTATS);
690 return (__efx_mac_stat_name[id]);
691}
692
693#endif /* EFSYS_OPT_NAMES */
694
695 __checkReturn efx_rc_t
696efx_mac_stats_upload(
697 __in efx_nic_t *enp,
698 __in efsys_mem_t *esmp)
699{
700 efx_port_t *epp = &(enp->en_port);
701 efx_mac_ops_t *emop = epp->ep_emop;
702 efx_rc_t rc;
703
704 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
705 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
706 EFSYS_ASSERT(emop != NULL);
707
708 /*
709 * Don't assert !ep_mac_stats_pending, because the client might
710 * have failed to finalise statistics when previously stopping
711 * the port.
712 */
713 if ((rc = emop->emo_stats_upload(enp, esmp)) != 0)
714 goto fail1;
715
716 epp->ep_mac_stats_pending = B_TRUE;
717
718 return (0);
719
720fail1:
721 EFSYS_PROBE1(fail1, efx_rc_t, rc);
722
723 return (rc);
724}
725
726 __checkReturn efx_rc_t
727efx_mac_stats_periodic(
728 __in efx_nic_t *enp,
729 __in efsys_mem_t *esmp,
730 __in uint16_t period_ms,
731 __in boolean_t events)
732{
733 efx_port_t *epp = &(enp->en_port);
734 efx_mac_ops_t *emop = epp->ep_emop;
735 efx_rc_t rc;
736
737 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
738 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
739
740 EFSYS_ASSERT(emop != NULL);
741
742 if (emop->emo_stats_periodic == NULL) {
743 rc = EINVAL;
744 goto fail1;
745 }
746
747 if ((rc = emop->emo_stats_periodic(enp, esmp, period_ms, events)) != 0)
748 goto fail2;
749
750 return (0);
751
752fail2:
753 EFSYS_PROBE(fail2);
754fail1:
755 EFSYS_PROBE1(fail1, efx_rc_t, rc);
756
757 return (rc);
758}
759
760
761 __checkReturn efx_rc_t
762efx_mac_stats_update(
763 __in efx_nic_t *enp,
764 __in efsys_mem_t *esmp,
765 __inout_ecount(EFX_MAC_NSTATS) efsys_stat_t *essp,
766 __inout_opt uint32_t *generationp)
767{
768 efx_port_t *epp = &(enp->en_port);
769 efx_mac_ops_t *emop = epp->ep_emop;
770 efx_rc_t rc;
771
772 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
773 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
774 EFSYS_ASSERT(emop != NULL);
775
776 rc = emop->emo_stats_update(enp, esmp, essp, generationp);
777 if (rc == 0)
778 epp->ep_mac_stats_pending = B_FALSE;
779
780 return (rc);
781}
782
783#endif /* EFSYS_OPT_MAC_STATS */
784
785 __checkReturn efx_rc_t
786efx_mac_select(
787 __in efx_nic_t *enp)
788{
789 efx_port_t *epp = &(enp->en_port);
790 efx_mac_type_t type = EFX_MAC_INVALID;
791 efx_mac_ops_t *emop;
792 int rc = EINVAL;
793
794#if EFSYS_OPT_SIENA
795 if (enp->en_family == EFX_FAMILY_SIENA) {
796 type = EFX_MAC_SIENA;
797 goto chosen;
798 }
799#endif
800
801#if EFSYS_OPT_HUNTINGTON
802 if (enp->en_family == EFX_FAMILY_HUNTINGTON) {
803 type = EFX_MAC_HUNTINGTON;
804 goto chosen;
805 }
806#endif
807
808#if EFSYS_OPT_MEDFORD
809 if (enp->en_family == EFX_FAMILY_MEDFORD) {
810 type = EFX_MAC_MEDFORD;
811 goto chosen;
812 }
813#endif
814
815#if EFSYS_OPT_FALCON
816 switch (epp->ep_link_mode) {
817#if EFSYS_OPT_MAC_FALCON_GMAC
818 case EFX_LINK_100HDX:
819 case EFX_LINK_100FDX:
820 case EFX_LINK_1000HDX:
821 case EFX_LINK_1000FDX:
822 type = EFX_MAC_FALCON_GMAC;
823 goto chosen;
824#endif /* EFSYS_OPT_FALCON_GMAC */
825
826#if EFSYS_OPT_MAC_FALCON_XMAC
827 case EFX_LINK_10000FDX:
828 type = EFX_MAC_FALCON_XMAC;
829 goto chosen;
830#endif /* EFSYS_OPT_FALCON_XMAC */
831
832 default:
833#if EFSYS_OPT_MAC_FALCON_GMAC && EFSYS_OPT_MAC_FALCON_XMAC
834 /* Only initialise a MAC supported by the PHY */
835 if (epp->ep_phy_cap_mask &
836 ((1 << EFX_PHY_CAP_1000FDX) |
837 (1 << EFX_PHY_CAP_1000HDX) |
838 (1 << EFX_PHY_CAP_100FDX) |
839 (1 << EFX_PHY_CAP_100HDX) |
840 (1 << EFX_PHY_CAP_10FDX) |
841 (1 << EFX_PHY_CAP_10FDX)))
842 type = EFX_MAC_FALCON_GMAC;
843 else
844 type = EFX_MAC_FALCON_XMAC;
845#elif EFSYS_OPT_MAC_FALCON_GMAC
846 type = EFX_MAC_FALCON_GMAC;
847#else
848 type = EFX_MAC_FALCON_XMAC;
849#endif
850 goto chosen;
851 }
852#endif /* EFSYS_OPT_FALCON */
853
854chosen:
855 EFSYS_ASSERT(type != EFX_MAC_INVALID);
856 EFSYS_ASSERT3U(type, <, EFX_MAC_NTYPES);
857 emop = epp->ep_emop = (efx_mac_ops_t *)__efx_mac_ops[type];
858 EFSYS_ASSERT(emop != NULL);
859
860 epp->ep_mac_type = type;
861
862 if (emop->emo_reset != NULL) {
863 if ((rc = emop->emo_reset(enp)) != 0)
864 goto fail1;
865
866 EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_MAC);
867 enp->en_reset_flags &= ~EFX_RESET_MAC;
868 }
869
870 return (0);
871
872fail1:
873 EFSYS_PROBE1(fail1, efx_rc_t, rc);
874
875 return (rc);
876}
877
878
879#if EFSYS_OPT_FALCON || EFSYS_OPT_SIENA
880
881#define EFX_MAC_HASH_BITS (1 << 8)
882
883/* Compute the multicast hash as used on Falcon and Siena. */
884static void
885falconsiena_mac_multicast_hash_compute(
886 __in_ecount(6*count) uint8_t const *addrs,
887 __in int count,
888 __out efx_oword_t *hash_low,
889 __out efx_oword_t *hash_high)
890{
891 uint32_t crc, index;
892 int i;
893
894 EFSYS_ASSERT(hash_low != NULL);
895 EFSYS_ASSERT(hash_high != NULL);
896
897 EFX_ZERO_OWORD(*hash_low);
898 EFX_ZERO_OWORD(*hash_high);
899
900 for (i = 0; i < count; i++) {
901 /* Calculate hash bucket (IEEE 802.3 CRC32 of the MAC addr) */
902 crc = efx_crc32_calculate(0xffffffff, addrs, EFX_MAC_ADDR_LEN);
903 index = crc % EFX_MAC_HASH_BITS;
904 if (index < 128) {
905 EFX_SET_OWORD_BIT(*hash_low, index);
906 } else {
907 EFX_SET_OWORD_BIT(*hash_high, index - 128);
908 }
909
910 addrs += EFX_MAC_ADDR_LEN;
911 }
912}
913
914static __checkReturn efx_rc_t
915falconsiena_mac_multicast_list_set(
916 __in efx_nic_t *enp)
917{
918 efx_port_t *epp = &(enp->en_port);
919 efx_mac_ops_t *emop = epp->ep_emop;
920 efx_oword_t old_hash[2];
921 efx_rc_t rc;
922
923 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
924 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
925
926 memcpy(old_hash, epp->ep_multicst_hash, sizeof (old_hash));
927
928 falconsiena_mac_multicast_hash_compute(epp->ep_mulcst_addr_list,
929 epp->ep_mulcst_addr_count,
930 &epp->ep_multicst_hash[0],
931 &epp->ep_multicst_hash[1]);
932
933 if ((rc = emop->emo_reconfigure(enp)) != 0)
934 goto fail1;
935
936 return (0);
937
938fail1:
939 EFSYS_PROBE1(fail1, efx_rc_t, rc);
940
941 memcpy(epp->ep_multicst_hash, old_hash, sizeof (old_hash));
942
943 return (rc);
944}
945
946#endif /* EFSYS_OPT_FALCON || EFSYS_OPT_SIENA */