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_mac_siena_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 siena_mac_stats_get_mask, /* emo_stats_get_mask */
61 efx_mcdi_mac_stats_upload, /* emo_stats_upload */
62 efx_mcdi_mac_stats_periodic, /* emo_stats_periodic */
63 siena_mac_stats_update /* emo_stats_update */
64 #endif /* EFSYS_OPT_MAC_STATS */
66 #endif /* EFSYS_OPT_SIENA */
68 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
69 static const efx_mac_ops_t __efx_mac_ef10_ops = {
70 ef10_mac_poll, /* emo_poll */
71 ef10_mac_up, /* emo_up */
72 ef10_mac_addr_set, /* emo_addr_set */
73 ef10_mac_pdu_set, /* emo_pdu_set */
74 ef10_mac_pdu_get, /* emo_pdu_get */
75 ef10_mac_reconfigure, /* emo_reconfigure */
76 ef10_mac_multicast_list_set, /* emo_multicast_list_set */
77 ef10_mac_filter_default_rxq_set, /* emo_filter_default_rxq_set */
78 ef10_mac_filter_default_rxq_clear,
79 /* emo_filter_default_rxq_clear */
80 #if EFSYS_OPT_LOOPBACK
81 ef10_mac_loopback_set, /* emo_loopback_set */
82 #endif /* EFSYS_OPT_LOOPBACK */
83 #if EFSYS_OPT_MAC_STATS
84 ef10_mac_stats_get_mask, /* emo_stats_get_mask */
85 efx_mcdi_mac_stats_upload, /* emo_stats_upload */
86 efx_mcdi_mac_stats_periodic, /* emo_stats_periodic */
87 ef10_mac_stats_update /* emo_stats_update */
88 #endif /* EFSYS_OPT_MAC_STATS */
90 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
92 __checkReturn efx_rc_t
97 efx_port_t *epp = &(enp->en_port);
98 const efx_mac_ops_t *emop = epp->ep_emop;
102 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
103 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
104 EFSYS_ASSERT(emop != NULL);
106 if (pdu < EFX_MAC_PDU_MIN) {
111 if (pdu > EFX_MAC_PDU_MAX) {
116 old_pdu = epp->ep_mac_pdu;
117 epp->ep_mac_pdu = (uint32_t)pdu;
118 if ((rc = emop->emo_pdu_set(enp)) != 0)
126 epp->ep_mac_pdu = old_pdu;
131 EFSYS_PROBE1(fail1, efx_rc_t, rc);
136 __checkReturn efx_rc_t
141 efx_port_t *epp = &(enp->en_port);
142 const efx_mac_ops_t *emop = epp->ep_emop;
145 if ((rc = emop->emo_pdu_get(enp, pdu)) != 0)
151 EFSYS_PROBE1(fail1, efx_rc_t, rc);
156 __checkReturn efx_rc_t
161 efx_port_t *epp = &(enp->en_port);
162 const efx_mac_ops_t *emop = epp->ep_emop;
167 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
168 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
170 if (EFX_MAC_ADDR_IS_MULTICAST(addr)) {
175 oui = addr[0] << 16 | addr[1] << 8 | addr[2];
176 if (oui == 0x000000) {
181 EFX_MAC_ADDR_COPY(old_addr, epp->ep_mac_addr);
182 EFX_MAC_ADDR_COPY(epp->ep_mac_addr, addr);
183 if ((rc = emop->emo_addr_set(enp)) != 0)
191 EFX_MAC_ADDR_COPY(epp->ep_mac_addr, old_addr);
196 EFSYS_PROBE1(fail1, efx_rc_t, rc);
201 __checkReturn efx_rc_t
204 __in boolean_t all_unicst,
205 __in boolean_t mulcst,
206 __in boolean_t all_mulcst,
207 __in boolean_t brdcst)
209 efx_port_t *epp = &(enp->en_port);
210 const efx_mac_ops_t *emop = epp->ep_emop;
211 boolean_t old_all_unicst;
212 boolean_t old_mulcst;
213 boolean_t old_all_mulcst;
214 boolean_t old_brdcst;
217 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
218 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
220 old_all_unicst = epp->ep_all_unicst;
221 old_mulcst = epp->ep_mulcst;
222 old_all_mulcst = epp->ep_all_mulcst;
223 old_brdcst = epp->ep_brdcst;
225 epp->ep_all_unicst = all_unicst;
226 epp->ep_mulcst = mulcst;
227 epp->ep_all_mulcst = all_mulcst;
228 epp->ep_brdcst = brdcst;
230 if ((rc = emop->emo_reconfigure(enp)) != 0)
236 EFSYS_PROBE1(fail1, efx_rc_t, rc);
238 epp->ep_all_unicst = old_all_unicst;
239 epp->ep_mulcst = old_mulcst;
240 epp->ep_all_mulcst = old_all_mulcst;
241 epp->ep_brdcst = old_brdcst;
246 __checkReturn efx_rc_t
249 __in boolean_t enabled)
251 efx_port_t *epp = &(enp->en_port);
252 const efx_mac_ops_t *emop = epp->ep_emop;
255 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
256 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
257 EFSYS_ASSERT(emop != NULL);
259 if (epp->ep_mac_drain == enabled)
262 epp->ep_mac_drain = enabled;
264 if ((rc = emop->emo_reconfigure(enp)) != 0)
270 EFSYS_PROBE1(fail1, efx_rc_t, rc);
275 __checkReturn efx_rc_t
278 __out boolean_t *mac_upp)
280 efx_port_t *epp = &(enp->en_port);
281 const efx_mac_ops_t *emop = epp->ep_emop;
284 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
285 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
287 if ((rc = emop->emo_up(enp, mac_upp)) != 0)
293 EFSYS_PROBE1(fail1, efx_rc_t, rc);
298 __checkReturn efx_rc_t
301 __in unsigned int fcntl,
302 __in boolean_t autoneg)
304 efx_port_t *epp = &(enp->en_port);
305 const efx_mac_ops_t *emop = epp->ep_emop;
306 const efx_phy_ops_t *epop = epp->ep_epop;
307 unsigned int old_fcntl;
308 boolean_t old_autoneg;
309 unsigned int old_adv_cap;
312 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
313 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
315 if ((fcntl & ~(EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE)) != 0) {
321 * Ignore a request to set flow control auto-negotiation
322 * if the PHY doesn't support it.
324 if (~epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN))
327 old_fcntl = epp->ep_fcntl;
328 old_autoneg = epp->ep_fcntl_autoneg;
329 old_adv_cap = epp->ep_adv_cap_mask;
331 epp->ep_fcntl = fcntl;
332 epp->ep_fcntl_autoneg = autoneg;
335 * Always encode the flow control settings in the advertised
336 * capabilities even if we are not trying to auto-negotiate
337 * them and reconfigure both the PHY and the MAC.
339 if (fcntl & EFX_FCNTL_RESPOND)
340 epp->ep_adv_cap_mask |= (1 << EFX_PHY_CAP_PAUSE |
341 1 << EFX_PHY_CAP_ASYM);
343 epp->ep_adv_cap_mask &= ~(1 << EFX_PHY_CAP_PAUSE |
344 1 << EFX_PHY_CAP_ASYM);
346 if (fcntl & EFX_FCNTL_GENERATE)
347 epp->ep_adv_cap_mask ^= (1 << EFX_PHY_CAP_ASYM);
349 if ((rc = epop->epo_reconfigure(enp)) != 0)
352 if ((rc = emop->emo_reconfigure(enp)) != 0)
363 epp->ep_fcntl = old_fcntl;
364 epp->ep_fcntl_autoneg = old_autoneg;
365 epp->ep_adv_cap_mask = old_adv_cap;
368 EFSYS_PROBE1(fail1, efx_rc_t, rc);
376 __out unsigned int *fcntl_wantedp,
377 __out unsigned int *fcntl_linkp)
379 efx_port_t *epp = &(enp->en_port);
380 unsigned int wanted = 0;
382 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
383 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
386 * Decode the requested flow control settings from the PHY
387 * advertised capabilities.
389 if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_PAUSE))
390 wanted = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE;
391 if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_ASYM))
392 wanted ^= EFX_FCNTL_GENERATE;
394 *fcntl_linkp = epp->ep_fcntl;
395 *fcntl_wantedp = wanted;
398 __checkReturn efx_rc_t
399 efx_mac_multicast_list_set(
401 __in_ecount(6*count) uint8_t const *addrs,
404 efx_port_t *epp = &(enp->en_port);
405 const efx_mac_ops_t *emop = epp->ep_emop;
406 uint8_t *old_mulcst_addr_list = NULL;
407 uint32_t old_mulcst_addr_count;
410 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
411 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
413 if (count > EFX_MAC_MULTICAST_LIST_MAX) {
418 old_mulcst_addr_count = epp->ep_mulcst_addr_count;
419 if (old_mulcst_addr_count > 0) {
420 /* Allocate memory to store old list (instead of using stack) */
421 EFSYS_KMEM_ALLOC(enp->en_esip,
422 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
423 old_mulcst_addr_list);
424 if (old_mulcst_addr_list == NULL) {
429 /* Save the old list in case we need to rollback */
430 memcpy(old_mulcst_addr_list, epp->ep_mulcst_addr_list,
431 old_mulcst_addr_count * EFX_MAC_ADDR_LEN);
434 /* Store the new list */
435 memcpy(epp->ep_mulcst_addr_list, addrs,
436 count * EFX_MAC_ADDR_LEN);
437 epp->ep_mulcst_addr_count = count;
439 if ((rc = emop->emo_multicast_list_set(enp)) != 0)
442 if (old_mulcst_addr_count > 0) {
443 EFSYS_KMEM_FREE(enp->en_esip,
444 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
445 old_mulcst_addr_list);
453 /* Restore original list on failure */
454 epp->ep_mulcst_addr_count = old_mulcst_addr_count;
455 if (old_mulcst_addr_count > 0) {
456 memcpy(epp->ep_mulcst_addr_list, old_mulcst_addr_list,
457 old_mulcst_addr_count * EFX_MAC_ADDR_LEN);
459 EFSYS_KMEM_FREE(enp->en_esip,
460 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
461 old_mulcst_addr_list);
468 EFSYS_PROBE1(fail1, efx_rc_t, rc);
474 __checkReturn efx_rc_t
475 efx_mac_filter_default_rxq_set(
478 __in boolean_t using_rss)
480 efx_port_t *epp = &(enp->en_port);
481 const efx_mac_ops_t *emop = epp->ep_emop;
484 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
485 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
487 if (emop->emo_filter_default_rxq_set != NULL) {
488 rc = emop->emo_filter_default_rxq_set(enp, erp, using_rss);
496 EFSYS_PROBE1(fail1, efx_rc_t, rc);
502 efx_mac_filter_default_rxq_clear(
505 efx_port_t *epp = &(enp->en_port);
506 const efx_mac_ops_t *emop = epp->ep_emop;
508 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
509 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
511 if (emop->emo_filter_default_rxq_clear != NULL)
512 emop->emo_filter_default_rxq_clear(enp);
516 #if EFSYS_OPT_MAC_STATS
520 /* START MKCONFIG GENERATED EfxMacStatNamesBlock c11b91b42f922516 */
521 static const char * const __efx_mac_stat_name[] = {
530 "rx_128_to_255_pkts",
531 "rx_256_to_511_pkts",
532 "rx_512_to_1023_pkts",
533 "rx_1024_to_15xx_pkts",
538 "rx_false_carrier_errors",
541 "rx_internal_errors",
552 "rx_nodesc_drop_cnt",
561 "tx_128_to_255_pkts",
562 "tx_256_to_511_pkts",
563 "tx_512_to_1023_pkts",
564 "tx_1024_to_15xx_pkts",
573 "pm_trunc_bb_overflow",
574 "pm_discard_bb_overflow",
575 "pm_trunc_vfifo_full",
576 "pm_discard_vfifo_full",
579 "pm_discard_mapping",
580 "rxdp_q_disabled_pkts",
581 "rxdp_di_dropped_pkts",
582 "rxdp_streaming_pkts",
585 "vadapter_rx_unicast_packets",
586 "vadapter_rx_unicast_bytes",
587 "vadapter_rx_multicast_packets",
588 "vadapter_rx_multicast_bytes",
589 "vadapter_rx_broadcast_packets",
590 "vadapter_rx_broadcast_bytes",
591 "vadapter_rx_bad_packets",
592 "vadapter_rx_bad_bytes",
593 "vadapter_rx_overflow",
594 "vadapter_tx_unicast_packets",
595 "vadapter_tx_unicast_bytes",
596 "vadapter_tx_multicast_packets",
597 "vadapter_tx_multicast_bytes",
598 "vadapter_tx_broadcast_packets",
599 "vadapter_tx_broadcast_bytes",
600 "vadapter_tx_bad_packets",
601 "vadapter_tx_bad_bytes",
602 "vadapter_tx_overflow",
604 /* END MKCONFIG GENERATED EfxMacStatNamesBlock */
606 __checkReturn const char *
609 __in unsigned int id)
611 _NOTE(ARGUNUSED(enp))
612 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
614 EFSYS_ASSERT3U(id, <, EFX_MAC_NSTATS);
615 return (__efx_mac_stat_name[id]);
618 #endif /* EFSYS_OPT_NAMES */
621 efx_mac_stats_mask_add_range(
622 __inout_bcount(mask_size) uint32_t *maskp,
623 __in size_t mask_size,
624 __in const struct efx_mac_stats_range *rngp)
626 unsigned int mask_npages = mask_size / sizeof (*maskp);
635 if ((mask_npages * EFX_MAC_STATS_MASK_BITS_PER_PAGE) <=
636 (unsigned int)rngp->last) {
641 EFSYS_ASSERT3U(rngp->first, <=, rngp->last);
642 EFSYS_ASSERT3U(rngp->last, <, EFX_MAC_NSTATS);
644 for (el = 0; el < mask_npages; ++el) {
645 el_min = el * EFX_MAC_STATS_MASK_BITS_PER_PAGE;
647 el_min + (EFX_MAC_STATS_MASK_BITS_PER_PAGE - 1);
648 if ((unsigned int)rngp->first > el_max ||
649 (unsigned int)rngp->last < el_min)
651 low = MAX((unsigned int)rngp->first, el_min);
652 high = MIN((unsigned int)rngp->last, el_max);
653 width = high - low + 1;
655 (width == EFX_MAC_STATS_MASK_BITS_PER_PAGE) ?
656 (~0ULL) : (((1ULL << width) - 1) << (low - el_min));
662 EFSYS_PROBE1(fail1, efx_rc_t, rc);
668 efx_mac_stats_mask_add_ranges(
669 __inout_bcount(mask_size) uint32_t *maskp,
670 __in size_t mask_size,
671 __in_ecount(rng_count) const struct efx_mac_stats_range *rngp,
672 __in unsigned int rng_count)
677 for (i = 0; i < rng_count; ++i) {
678 if ((rc = efx_mac_stats_mask_add_range(maskp, mask_size,
686 EFSYS_PROBE1(fail1, efx_rc_t, rc);
691 __checkReturn efx_rc_t
692 efx_mac_stats_get_mask(
694 __out_bcount(mask_size) uint32_t *maskp,
695 __in size_t mask_size)
697 efx_port_t *epp = &(enp->en_port);
698 const efx_mac_ops_t *emop = epp->ep_emop;
701 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
702 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
703 EFSYS_ASSERT(maskp != NULL);
704 EFSYS_ASSERT(mask_size % sizeof (maskp[0]) == 0);
706 (void) memset(maskp, 0, mask_size);
708 if ((rc = emop->emo_stats_get_mask(enp, maskp, mask_size)) != 0)
714 EFSYS_PROBE1(fail1, efx_rc_t, rc);
719 __checkReturn efx_rc_t
720 efx_mac_stats_upload(
722 __in efsys_mem_t *esmp)
724 efx_port_t *epp = &(enp->en_port);
725 const efx_mac_ops_t *emop = epp->ep_emop;
728 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
729 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
730 EFSYS_ASSERT(emop != NULL);
732 if ((rc = emop->emo_stats_upload(enp, esmp)) != 0)
738 EFSYS_PROBE1(fail1, efx_rc_t, rc);
743 __checkReturn efx_rc_t
744 efx_mac_stats_periodic(
746 __in efsys_mem_t *esmp,
747 __in uint16_t period_ms,
748 __in boolean_t events)
750 efx_port_t *epp = &(enp->en_port);
751 const efx_mac_ops_t *emop = epp->ep_emop;
754 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
755 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
757 EFSYS_ASSERT(emop != NULL);
759 if (emop->emo_stats_periodic == NULL) {
764 if ((rc = emop->emo_stats_periodic(enp, esmp, period_ms, events)) != 0)
772 EFSYS_PROBE1(fail1, efx_rc_t, rc);
778 __checkReturn efx_rc_t
779 efx_mac_stats_update(
781 __in efsys_mem_t *esmp,
782 __inout_ecount(EFX_MAC_NSTATS) efsys_stat_t *essp,
783 __inout_opt uint32_t *generationp)
785 efx_port_t *epp = &(enp->en_port);
786 const efx_mac_ops_t *emop = epp->ep_emop;
789 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
790 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
791 EFSYS_ASSERT(emop != NULL);
793 rc = emop->emo_stats_update(enp, esmp, essp, generationp);
798 #endif /* EFSYS_OPT_MAC_STATS */
800 __checkReturn efx_rc_t
804 efx_port_t *epp = &(enp->en_port);
805 efx_mac_type_t type = EFX_MAC_INVALID;
806 const efx_mac_ops_t *emop;
809 switch (enp->en_family) {
811 case EFX_FAMILY_SIENA:
812 emop = &__efx_mac_siena_ops;
813 type = EFX_MAC_SIENA;
815 #endif /* EFSYS_OPT_SIENA */
817 #if EFSYS_OPT_HUNTINGTON
818 case EFX_FAMILY_HUNTINGTON:
819 emop = &__efx_mac_ef10_ops;
820 type = EFX_MAC_HUNTINGTON;
822 #endif /* EFSYS_OPT_HUNTINGTON */
824 #if EFSYS_OPT_MEDFORD
825 case EFX_FAMILY_MEDFORD:
826 emop = &__efx_mac_ef10_ops;
827 type = EFX_MAC_MEDFORD;
829 #endif /* EFSYS_OPT_MEDFORD */
836 EFSYS_ASSERT(type != EFX_MAC_INVALID);
837 EFSYS_ASSERT3U(type, <, EFX_MAC_NTYPES);
838 EFSYS_ASSERT(emop != NULL);
841 epp->ep_mac_type = type;
846 EFSYS_PROBE1(fail1, efx_rc_t, rc);
854 #define EFX_MAC_HASH_BITS (1 << 8)
856 /* Compute the multicast hash as used on Falcon and Siena. */
858 siena_mac_multicast_hash_compute(
859 __in_ecount(6*count) uint8_t const *addrs,
861 __out efx_oword_t *hash_low,
862 __out efx_oword_t *hash_high)
867 EFSYS_ASSERT(hash_low != NULL);
868 EFSYS_ASSERT(hash_high != NULL);
870 EFX_ZERO_OWORD(*hash_low);
871 EFX_ZERO_OWORD(*hash_high);
873 for (i = 0; i < count; i++) {
874 /* Calculate hash bucket (IEEE 802.3 CRC32 of the MAC addr) */
875 crc = efx_crc32_calculate(0xffffffff, addrs, EFX_MAC_ADDR_LEN);
876 index = crc % EFX_MAC_HASH_BITS;
878 EFX_SET_OWORD_BIT(*hash_low, index);
880 EFX_SET_OWORD_BIT(*hash_high, index - 128);
883 addrs += EFX_MAC_ADDR_LEN;
887 static __checkReturn efx_rc_t
888 siena_mac_multicast_list_set(
891 efx_port_t *epp = &(enp->en_port);
892 const efx_mac_ops_t *emop = epp->ep_emop;
893 efx_oword_t old_hash[2];
896 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
897 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
899 memcpy(old_hash, epp->ep_multicst_hash, sizeof (old_hash));
901 siena_mac_multicast_hash_compute(
902 epp->ep_mulcst_addr_list,
903 epp->ep_mulcst_addr_count,
904 &epp->ep_multicst_hash[0],
905 &epp->ep_multicst_hash[1]);
907 if ((rc = emop->emo_reconfigure(enp)) != 0)
913 EFSYS_PROBE1(fail1, efx_rc_t, rc);
915 memcpy(epp->ep_multicst_hash, old_hash, sizeof (old_hash));
920 #endif /* EFSYS_OPT_SIENA */