2 * Copyright (c) 2007-2016 Solarflare Communications Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
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.
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.
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.
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
39 static __checkReturn efx_rc_t
40 siena_mac_multicast_list_set(
43 #endif /* EFSYS_OPT_SIENA */
46 static const efx_mac_ops_t __efx_siena_mac_ops = {
47 siena_mac_poll, /* emo_poll */
48 siena_mac_up, /* emo_up */
49 siena_mac_reconfigure, /* emo_addr_set */
50 siena_mac_reconfigure, /* emo_pdu_set */
51 siena_mac_pdu_get, /* emo_pdu_get */
52 siena_mac_reconfigure, /* emo_reconfigure */
53 siena_mac_multicast_list_set, /* emo_multicast_list_set */
54 NULL, /* emo_filter_set_default_rxq */
55 NULL, /* emo_filter_default_rxq_clear */
56 #if EFSYS_OPT_LOOPBACK
57 siena_mac_loopback_set, /* emo_loopback_set */
58 #endif /* EFSYS_OPT_LOOPBACK */
59 #if EFSYS_OPT_MAC_STATS
60 efx_mcdi_mac_stats_upload, /* emo_stats_upload */
61 efx_mcdi_mac_stats_periodic, /* emo_stats_periodic */
62 siena_mac_stats_update /* emo_stats_update */
63 #endif /* EFSYS_OPT_MAC_STATS */
65 #endif /* EFSYS_OPT_SIENA */
67 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
68 static const efx_mac_ops_t __efx_ef10_mac_ops = {
69 ef10_mac_poll, /* emo_poll */
70 ef10_mac_up, /* emo_up */
71 ef10_mac_addr_set, /* emo_addr_set */
72 ef10_mac_pdu_set, /* emo_pdu_set */
73 ef10_mac_pdu_get, /* emo_pdu_get */
74 ef10_mac_reconfigure, /* emo_reconfigure */
75 ef10_mac_multicast_list_set, /* emo_multicast_list_set */
76 ef10_mac_filter_default_rxq_set, /* emo_filter_default_rxq_set */
77 ef10_mac_filter_default_rxq_clear,
78 /* emo_filter_default_rxq_clear */
79 #if EFSYS_OPT_LOOPBACK
80 ef10_mac_loopback_set, /* emo_loopback_set */
81 #endif /* EFSYS_OPT_LOOPBACK */
82 #if EFSYS_OPT_MAC_STATS
83 efx_mcdi_mac_stats_upload, /* emo_stats_upload */
84 efx_mcdi_mac_stats_periodic, /* emo_stats_periodic */
85 ef10_mac_stats_update /* emo_stats_update */
86 #endif /* EFSYS_OPT_MAC_STATS */
88 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
90 __checkReturn efx_rc_t
95 efx_port_t *epp = &(enp->en_port);
96 const efx_mac_ops_t *emop = epp->ep_emop;
100 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
101 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
102 EFSYS_ASSERT(emop != NULL);
104 if (pdu < EFX_MAC_PDU_MIN) {
109 if (pdu > EFX_MAC_PDU_MAX) {
114 old_pdu = epp->ep_mac_pdu;
115 epp->ep_mac_pdu = (uint32_t)pdu;
116 if ((rc = emop->emo_pdu_set(enp)) != 0)
124 epp->ep_mac_pdu = old_pdu;
129 EFSYS_PROBE1(fail1, efx_rc_t, rc);
134 __checkReturn efx_rc_t
139 efx_port_t *epp = &(enp->en_port);
140 const efx_mac_ops_t *emop = epp->ep_emop;
143 if ((rc = emop->emo_pdu_get(enp, pdu)) != 0)
149 EFSYS_PROBE1(fail1, efx_rc_t, rc);
154 __checkReturn efx_rc_t
159 efx_port_t *epp = &(enp->en_port);
160 const efx_mac_ops_t *emop = epp->ep_emop;
165 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
166 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
168 if (EFX_MAC_ADDR_IS_MULTICAST(addr)) {
173 oui = addr[0] << 16 | addr[1] << 8 | addr[2];
174 if (oui == 0x000000) {
179 EFX_MAC_ADDR_COPY(old_addr, epp->ep_mac_addr);
180 EFX_MAC_ADDR_COPY(epp->ep_mac_addr, addr);
181 if ((rc = emop->emo_addr_set(enp)) != 0)
189 EFX_MAC_ADDR_COPY(epp->ep_mac_addr, old_addr);
194 EFSYS_PROBE1(fail1, efx_rc_t, rc);
199 __checkReturn efx_rc_t
202 __in boolean_t all_unicst,
203 __in boolean_t mulcst,
204 __in boolean_t all_mulcst,
205 __in boolean_t brdcst)
207 efx_port_t *epp = &(enp->en_port);
208 const efx_mac_ops_t *emop = epp->ep_emop;
209 boolean_t old_all_unicst;
210 boolean_t old_mulcst;
211 boolean_t old_all_mulcst;
212 boolean_t old_brdcst;
215 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
216 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
218 old_all_unicst = epp->ep_all_unicst;
219 old_mulcst = epp->ep_mulcst;
220 old_all_mulcst = epp->ep_all_mulcst;
221 old_brdcst = epp->ep_brdcst;
223 epp->ep_all_unicst = all_unicst;
224 epp->ep_mulcst = mulcst;
225 epp->ep_all_mulcst = all_mulcst;
226 epp->ep_brdcst = brdcst;
228 if ((rc = emop->emo_reconfigure(enp)) != 0)
234 EFSYS_PROBE1(fail1, efx_rc_t, rc);
236 epp->ep_all_unicst = old_all_unicst;
237 epp->ep_mulcst = old_mulcst;
238 epp->ep_all_mulcst = old_all_mulcst;
239 epp->ep_brdcst = old_brdcst;
244 __checkReturn efx_rc_t
247 __in boolean_t enabled)
249 efx_port_t *epp = &(enp->en_port);
250 const efx_mac_ops_t *emop = epp->ep_emop;
253 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
254 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
255 EFSYS_ASSERT(emop != NULL);
257 if (epp->ep_mac_drain == enabled)
260 epp->ep_mac_drain = enabled;
262 if ((rc = emop->emo_reconfigure(enp)) != 0)
268 EFSYS_PROBE1(fail1, efx_rc_t, rc);
273 __checkReturn efx_rc_t
276 __out boolean_t *mac_upp)
278 efx_port_t *epp = &(enp->en_port);
279 const efx_mac_ops_t *emop = epp->ep_emop;
282 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
283 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
285 if ((rc = emop->emo_up(enp, mac_upp)) != 0)
291 EFSYS_PROBE1(fail1, efx_rc_t, rc);
296 __checkReturn efx_rc_t
299 __in unsigned int fcntl,
300 __in boolean_t autoneg)
302 efx_port_t *epp = &(enp->en_port);
303 const efx_mac_ops_t *emop = epp->ep_emop;
304 const efx_phy_ops_t *epop = epp->ep_epop;
305 unsigned int old_fcntl;
306 boolean_t old_autoneg;
307 unsigned int old_adv_cap;
310 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
311 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
313 if ((fcntl & ~(EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE)) != 0) {
319 * Ignore a request to set flow control auto-negotiation
320 * if the PHY doesn't support it.
322 if (~epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN))
325 old_fcntl = epp->ep_fcntl;
326 old_autoneg = epp->ep_fcntl_autoneg;
327 old_adv_cap = epp->ep_adv_cap_mask;
329 epp->ep_fcntl = fcntl;
330 epp->ep_fcntl_autoneg = autoneg;
333 * Always encode the flow control settings in the advertised
334 * capabilities even if we are not trying to auto-negotiate
335 * them and reconfigure both the PHY and the MAC.
337 if (fcntl & EFX_FCNTL_RESPOND)
338 epp->ep_adv_cap_mask |= (1 << EFX_PHY_CAP_PAUSE |
339 1 << EFX_PHY_CAP_ASYM);
341 epp->ep_adv_cap_mask &= ~(1 << EFX_PHY_CAP_PAUSE |
342 1 << EFX_PHY_CAP_ASYM);
344 if (fcntl & EFX_FCNTL_GENERATE)
345 epp->ep_adv_cap_mask ^= (1 << EFX_PHY_CAP_ASYM);
347 if ((rc = epop->epo_reconfigure(enp)) != 0)
350 if ((rc = emop->emo_reconfigure(enp)) != 0)
361 epp->ep_fcntl = old_fcntl;
362 epp->ep_fcntl_autoneg = old_autoneg;
363 epp->ep_adv_cap_mask = old_adv_cap;
366 EFSYS_PROBE1(fail1, efx_rc_t, rc);
374 __out unsigned int *fcntl_wantedp,
375 __out unsigned int *fcntl_linkp)
377 efx_port_t *epp = &(enp->en_port);
378 unsigned int wanted = 0;
380 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
381 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
384 * Decode the requested flow control settings from the PHY
385 * advertised capabilities.
387 if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_PAUSE))
388 wanted = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE;
389 if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_ASYM))
390 wanted ^= EFX_FCNTL_GENERATE;
392 *fcntl_linkp = epp->ep_fcntl;
393 *fcntl_wantedp = wanted;
396 __checkReturn efx_rc_t
397 efx_mac_multicast_list_set(
399 __in_ecount(6*count) uint8_t const *addrs,
402 efx_port_t *epp = &(enp->en_port);
403 const efx_mac_ops_t *emop = epp->ep_emop;
404 uint8_t *old_mulcst_addr_list = NULL;
405 uint32_t old_mulcst_addr_count;
408 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
409 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
411 if (count > EFX_MAC_MULTICAST_LIST_MAX) {
416 old_mulcst_addr_count = epp->ep_mulcst_addr_count;
417 if (old_mulcst_addr_count > 0) {
418 /* Allocate memory to store old list (instead of using stack) */
419 EFSYS_KMEM_ALLOC(enp->en_esip,
420 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
421 old_mulcst_addr_list);
422 if (old_mulcst_addr_list == NULL) {
427 /* Save the old list in case we need to rollback */
428 memcpy(old_mulcst_addr_list, epp->ep_mulcst_addr_list,
429 old_mulcst_addr_count * EFX_MAC_ADDR_LEN);
432 /* Store the new list */
433 memcpy(epp->ep_mulcst_addr_list, addrs,
434 count * EFX_MAC_ADDR_LEN);
435 epp->ep_mulcst_addr_count = count;
437 if ((rc = emop->emo_multicast_list_set(enp)) != 0)
440 if (old_mulcst_addr_count > 0) {
441 EFSYS_KMEM_FREE(enp->en_esip,
442 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
443 old_mulcst_addr_list);
451 /* Restore original list on failure */
452 epp->ep_mulcst_addr_count = old_mulcst_addr_count;
453 if (old_mulcst_addr_count > 0) {
454 memcpy(epp->ep_mulcst_addr_list, old_mulcst_addr_list,
455 old_mulcst_addr_count * EFX_MAC_ADDR_LEN);
457 EFSYS_KMEM_FREE(enp->en_esip,
458 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
459 old_mulcst_addr_list);
466 EFSYS_PROBE1(fail1, efx_rc_t, rc);
472 __checkReturn efx_rc_t
473 efx_mac_filter_default_rxq_set(
476 __in boolean_t using_rss)
478 efx_port_t *epp = &(enp->en_port);
479 const efx_mac_ops_t *emop = epp->ep_emop;
482 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
483 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
485 if (emop->emo_filter_default_rxq_set != NULL) {
486 rc = emop->emo_filter_default_rxq_set(enp, erp, using_rss);
494 EFSYS_PROBE1(fail1, efx_rc_t, rc);
500 efx_mac_filter_default_rxq_clear(
503 efx_port_t *epp = &(enp->en_port);
504 const efx_mac_ops_t *emop = epp->ep_emop;
506 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
507 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
509 if (emop->emo_filter_default_rxq_clear != NULL)
510 emop->emo_filter_default_rxq_clear(enp);
514 #if EFSYS_OPT_MAC_STATS
518 /* START MKCONFIG GENERATED EfxMacStatNamesBlock 054d43a31d2d7a45 */
519 static const char *__efx_mac_stat_name[] = {
528 "rx_128_to_255_pkts",
529 "rx_256_to_511_pkts",
530 "rx_512_to_1023_pkts",
531 "rx_1024_to_15xx_pkts",
536 "rx_false_carrier_errors",
539 "rx_internal_errors",
550 "rx_nodesc_drop_cnt",
559 "tx_128_to_255_pkts",
560 "tx_256_to_511_pkts",
561 "tx_512_to_1023_pkts",
562 "tx_1024_to_15xx_pkts",
571 "pm_trunc_bb_overflow",
572 "pm_discard_bb_overflow",
573 "pm_trunc_vfifo_full",
574 "pm_discard_vfifo_full",
577 "pm_discard_mapping",
578 "rxdp_q_disabled_pkts",
579 "rxdp_di_dropped_pkts",
580 "rxdp_streaming_pkts",
583 "vadapter_rx_unicast_packets",
584 "vadapter_rx_unicast_bytes",
585 "vadapter_rx_multicast_packets",
586 "vadapter_rx_multicast_bytes",
587 "vadapter_rx_broadcast_packets",
588 "vadapter_rx_broadcast_bytes",
589 "vadapter_rx_bad_packets",
590 "vadapter_rx_bad_bytes",
591 "vadapter_rx_overflow",
592 "vadapter_tx_unicast_packets",
593 "vadapter_tx_unicast_bytes",
594 "vadapter_tx_multicast_packets",
595 "vadapter_tx_multicast_bytes",
596 "vadapter_tx_broadcast_packets",
597 "vadapter_tx_broadcast_bytes",
598 "vadapter_tx_bad_packets",
599 "vadapter_tx_bad_bytes",
600 "vadapter_tx_overflow",
602 /* END MKCONFIG GENERATED EfxMacStatNamesBlock */
604 __checkReturn const char *
607 __in unsigned int id)
609 _NOTE(ARGUNUSED(enp))
610 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
612 EFSYS_ASSERT3U(id, <, EFX_MAC_NSTATS);
613 return (__efx_mac_stat_name[id]);
616 #endif /* EFSYS_OPT_NAMES */
618 __checkReturn efx_rc_t
619 efx_mac_stats_upload(
621 __in efsys_mem_t *esmp)
623 efx_port_t *epp = &(enp->en_port);
624 const efx_mac_ops_t *emop = epp->ep_emop;
627 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
628 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
629 EFSYS_ASSERT(emop != NULL);
632 * Don't assert !ep_mac_stats_pending, because the client might
633 * have failed to finalise statistics when previously stopping
636 if ((rc = emop->emo_stats_upload(enp, esmp)) != 0)
639 epp->ep_mac_stats_pending = B_TRUE;
644 EFSYS_PROBE1(fail1, efx_rc_t, rc);
649 __checkReturn efx_rc_t
650 efx_mac_stats_periodic(
652 __in efsys_mem_t *esmp,
653 __in uint16_t period_ms,
654 __in boolean_t events)
656 efx_port_t *epp = &(enp->en_port);
657 const efx_mac_ops_t *emop = epp->ep_emop;
660 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
661 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
663 EFSYS_ASSERT(emop != NULL);
665 if (emop->emo_stats_periodic == NULL) {
670 if ((rc = emop->emo_stats_periodic(enp, esmp, period_ms, events)) != 0)
678 EFSYS_PROBE1(fail1, efx_rc_t, rc);
684 __checkReturn efx_rc_t
685 efx_mac_stats_update(
687 __in efsys_mem_t *esmp,
688 __inout_ecount(EFX_MAC_NSTATS) efsys_stat_t *essp,
689 __inout_opt uint32_t *generationp)
691 efx_port_t *epp = &(enp->en_port);
692 const efx_mac_ops_t *emop = epp->ep_emop;
695 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
696 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
697 EFSYS_ASSERT(emop != NULL);
699 rc = emop->emo_stats_update(enp, esmp, essp, generationp);
701 epp->ep_mac_stats_pending = B_FALSE;
706 #endif /* EFSYS_OPT_MAC_STATS */
708 __checkReturn efx_rc_t
712 efx_port_t *epp = &(enp->en_port);
713 efx_mac_type_t type = EFX_MAC_INVALID;
714 const efx_mac_ops_t *emop;
717 switch (enp->en_family) {
719 case EFX_FAMILY_SIENA:
720 emop = &__efx_siena_mac_ops;
721 type = EFX_MAC_SIENA;
723 #endif /* EFSYS_OPT_SIENA */
725 #if EFSYS_OPT_HUNTINGTON
726 case EFX_FAMILY_HUNTINGTON:
727 emop = &__efx_ef10_mac_ops;
728 type = EFX_MAC_HUNTINGTON;
730 #endif /* EFSYS_OPT_HUNTINGTON */
732 #if EFSYS_OPT_MEDFORD
733 case EFX_FAMILY_MEDFORD:
734 emop = &__efx_ef10_mac_ops;
735 type = EFX_MAC_MEDFORD;
737 #endif /* EFSYS_OPT_MEDFORD */
744 EFSYS_ASSERT(type != EFX_MAC_INVALID);
745 EFSYS_ASSERT3U(type, <, EFX_MAC_NTYPES);
746 EFSYS_ASSERT(emop != NULL);
749 epp->ep_mac_type = type;
754 EFSYS_PROBE1(fail1, efx_rc_t, rc);
762 #define EFX_MAC_HASH_BITS (1 << 8)
764 /* Compute the multicast hash as used on Falcon and Siena. */
766 siena_mac_multicast_hash_compute(
767 __in_ecount(6*count) uint8_t const *addrs,
769 __out efx_oword_t *hash_low,
770 __out efx_oword_t *hash_high)
775 EFSYS_ASSERT(hash_low != NULL);
776 EFSYS_ASSERT(hash_high != NULL);
778 EFX_ZERO_OWORD(*hash_low);
779 EFX_ZERO_OWORD(*hash_high);
781 for (i = 0; i < count; i++) {
782 /* Calculate hash bucket (IEEE 802.3 CRC32 of the MAC addr) */
783 crc = efx_crc32_calculate(0xffffffff, addrs, EFX_MAC_ADDR_LEN);
784 index = crc % EFX_MAC_HASH_BITS;
786 EFX_SET_OWORD_BIT(*hash_low, index);
788 EFX_SET_OWORD_BIT(*hash_high, index - 128);
791 addrs += EFX_MAC_ADDR_LEN;
795 static __checkReturn efx_rc_t
796 siena_mac_multicast_list_set(
799 efx_port_t *epp = &(enp->en_port);
800 const efx_mac_ops_t *emop = epp->ep_emop;
801 efx_oword_t old_hash[2];
804 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
805 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
807 memcpy(old_hash, epp->ep_multicst_hash, sizeof (old_hash));
809 siena_mac_multicast_hash_compute(
810 epp->ep_mulcst_addr_list,
811 epp->ep_mulcst_addr_count,
812 &epp->ep_multicst_hash[0],
813 &epp->ep_multicst_hash[1]);
815 if ((rc = emop->emo_reconfigure(enp)) != 0)
821 EFSYS_PROBE1(fail1, efx_rc_t, rc);
823 memcpy(epp->ep_multicst_hash, old_hash, sizeof (old_hash));
828 #endif /* EFSYS_OPT_SIENA */