1227569Sphilip/*- 2284555Sarybchik * Copyright (c) 2007-2015 Solarflare Communications Inc. 3284555Sarybchik * All rights reserved. 4227569Sphilip * 5227569Sphilip * Redistribution and use in source and binary forms, with or without 6284555Sarybchik * modification, are permitted provided that the following conditions are met: 7227569Sphilip * 8284555Sarybchik * 1. Redistributions of source code must retain the above copyright notice, 9284555Sarybchik * this list of conditions and the following disclaimer. 10284555Sarybchik * 2. Redistributions in binary form must reproduce the above copyright notice, 11284555Sarybchik * this list of conditions and the following disclaimer in the documentation 12284555Sarybchik * and/or other materials provided with the distribution. 13284555Sarybchik * 14284555Sarybchik * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15284555Sarybchik * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16284555Sarybchik * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17284555Sarybchik * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 18284555Sarybchik * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19284555Sarybchik * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20284555Sarybchik * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21284555Sarybchik * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22284555Sarybchik * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23284555Sarybchik * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 24284555Sarybchik * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25284555Sarybchik * 26284555Sarybchik * The views and conclusions contained in the software and documentation are 27284555Sarybchik * those of the authors and should not be interpreted as representing official 28284555Sarybchik * policies, either expressed or implied, of the FreeBSD Project. 29227569Sphilip */ 30227569Sphilip 31228078Sphilip#include <sys/cdefs.h> 32228078Sphilip__FBSDID("$FreeBSD: releng/10.3/sys/dev/sfxge/common/efx_mac.c 294397 2016-01-20 08:17:28Z arybchik $"); 33228078Sphilip 34227569Sphilip#include "efx.h" 35227569Sphilip#include "efx_impl.h" 36227569Sphilip 37227569Sphilip#if EFSYS_OPT_MAC_FALCON_GMAC 38227569Sphilip#include "falcon_gmac.h" 39227569Sphilip#endif 40227569Sphilip 41227569Sphilip#if EFSYS_OPT_MAC_FALCON_XMAC 42227569Sphilip#include "falcon_xmac.h" 43227569Sphilip#endif 44227569Sphilip 45284555Sarybchik#if EFSYS_OPT_FALCON || EFSYS_OPT_SIENA 46284555Sarybchik 47293927Sarybchikstatic __checkReturn efx_rc_t 48284555Sarybchikfalconsiena_mac_multicast_list_set( 49293927Sarybchik __in efx_nic_t *enp); 50284555Sarybchik 51284555Sarybchik#endif /* EFSYS_OPT_FALCON || EFSYS_OPT_SIENA */ 52284555Sarybchik 53227569Sphilip#if EFSYS_OPT_MAC_FALCON_GMAC 54284555Sarybchikstatic efx_mac_ops_t __efx_falcon_gmac_ops = { 55284555Sarybchik falcon_gmac_reset, /* emo_reset */ 56284555Sarybchik falcon_mac_poll, /* emo_poll */ 57284555Sarybchik falcon_mac_up, /* emo_up */ 58284555Sarybchik falcon_gmac_reconfigure, /* emo_addr_set */ 59294397Sarybchik falcon_gmac_reconfigure, /* emo_pdu_set */ 60284555Sarybchik falcon_gmac_reconfigure, /* emo_reconfigure */ 61284555Sarybchik falconsiena_mac_multicast_list_set, /* emo_multicast_list_set */ 62284555Sarybchik NULL, /* emo_filter_set_default_rxq */ 63284555Sarybchik NULL, /* emo_filter_default_rxq_clear */ 64227569Sphilip#if EFSYS_OPT_LOOPBACK 65284555Sarybchik falcon_mac_loopback_set, /* emo_loopback_set */ 66227569Sphilip#endif /* EFSYS_OPT_LOOPBACK */ 67227569Sphilip#if EFSYS_OPT_MAC_STATS 68284555Sarybchik falcon_mac_stats_upload, /* emo_stats_upload */ 69284555Sarybchik NULL, /* emo_stats_periodic */ 70284555Sarybchik falcon_gmac_stats_update /* emo_stats_update */ 71227569Sphilip#endif /* EFSYS_OPT_MAC_STATS */ 72227569Sphilip}; 73227569Sphilip#endif /* EFSYS_OPT_MAC_FALCON_GMAC */ 74227569Sphilip 75227569Sphilip#if EFSYS_OPT_MAC_FALCON_XMAC 76284555Sarybchikstatic efx_mac_ops_t __efx_falcon_xmac_ops = { 77284555Sarybchik falcon_xmac_reset, /* emo_reset */ 78284555Sarybchik falcon_mac_poll, /* emo_poll */ 79284555Sarybchik falcon_mac_up, /* emo_up */ 80284555Sarybchik falcon_xmac_reconfigure, /* emo_addr_set */ 81294397Sarybchik falcon_xmac_reconfigure, /* emo_pdu_set */ 82284555Sarybchik falcon_xmac_reconfigure, /* emo_reconfigure */ 83284555Sarybchik falconsiena_mac_multicast_list_set, /* emo_multicast_list_set */ 84284555Sarybchik NULL, /* emo_filter_set_default_rxq */ 85284555Sarybchik NULL, /* emo_filter_default_rxq_clear */ 86227569Sphilip#if EFSYS_OPT_LOOPBACK 87284555Sarybchik falcon_mac_loopback_set, /* emo_loopback_set */ 88227569Sphilip#endif /* EFSYS_OPT_LOOPBACK */ 89227569Sphilip#if EFSYS_OPT_MAC_STATS 90284555Sarybchik falcon_mac_stats_upload, /* emo_stats_upload */ 91284555Sarybchik NULL, /* emo_stats_periodic */ 92284555Sarybchik falcon_xmac_stats_update /* emo_stats_update */ 93227569Sphilip#endif /* EFSYS_OPT_MAC_STATS */ 94227569Sphilip}; 95227569Sphilip#endif /* EFSYS_OPT_MAC_FALCON_XMAC */ 96227569Sphilip 97227569Sphilip#if EFSYS_OPT_SIENA 98284555Sarybchikstatic efx_mac_ops_t __efx_siena_mac_ops = { 99284555Sarybchik NULL, /* emo_reset */ 100284555Sarybchik siena_mac_poll, /* emo_poll */ 101284555Sarybchik siena_mac_up, /* emo_up */ 102284555Sarybchik siena_mac_reconfigure, /* emo_addr_set */ 103294397Sarybchik siena_mac_reconfigure, /* emo_pdu_set */ 104284555Sarybchik siena_mac_reconfigure, /* emo_reconfigure */ 105284555Sarybchik falconsiena_mac_multicast_list_set, /* emo_multicast_list_set */ 106284555Sarybchik NULL, /* emo_filter_set_default_rxq */ 107284555Sarybchik NULL, /* emo_filter_default_rxq_clear */ 108227569Sphilip#if EFSYS_OPT_LOOPBACK 109284555Sarybchik siena_mac_loopback_set, /* emo_loopback_set */ 110227569Sphilip#endif /* EFSYS_OPT_LOOPBACK */ 111227569Sphilip#if EFSYS_OPT_MAC_STATS 112284555Sarybchik efx_mcdi_mac_stats_upload, /* emo_stats_upload */ 113284555Sarybchik efx_mcdi_mac_stats_periodic, /* emo_stats_periodic */ 114284555Sarybchik siena_mac_stats_update /* emo_stats_update */ 115227569Sphilip#endif /* EFSYS_OPT_MAC_STATS */ 116227569Sphilip}; 117227569Sphilip#endif /* EFSYS_OPT_SIENA */ 118227569Sphilip 119294395Sarybchik#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD 120294395Sarybchikstatic efx_mac_ops_t __efx_ef10_mac_ops = { 121284555Sarybchik NULL, /* emo_reset */ 122294395Sarybchik ef10_mac_poll, /* emo_poll */ 123294395Sarybchik ef10_mac_up, /* emo_up */ 124294395Sarybchik ef10_mac_addr_set, /* emo_addr_set */ 125294397Sarybchik ef10_mac_pdu_set, /* emo_pdu_set */ 126294395Sarybchik ef10_mac_reconfigure, /* emo_reconfigure */ 127294395Sarybchik ef10_mac_multicast_list_set, /* emo_multicast_list_set */ 128294395Sarybchik ef10_mac_filter_default_rxq_set, /* emo_filter_default_rxq_set */ 129294395Sarybchik ef10_mac_filter_default_rxq_clear, 130284555Sarybchik /* emo_filter_default_rxq_clear */ 131284555Sarybchik#if EFSYS_OPT_LOOPBACK 132294395Sarybchik ef10_mac_loopback_set, /* emo_loopback_set */ 133284555Sarybchik#endif /* EFSYS_OPT_LOOPBACK */ 134284555Sarybchik#if EFSYS_OPT_MAC_STATS 135284555Sarybchik efx_mcdi_mac_stats_upload, /* emo_stats_upload */ 136284555Sarybchik efx_mcdi_mac_stats_periodic, /* emo_stats_periodic */ 137294395Sarybchik ef10_mac_stats_update /* emo_stats_update */ 138284555Sarybchik#endif /* EFSYS_OPT_MAC_STATS */ 139284555Sarybchik}; 140294395Sarybchik#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */ 141284555Sarybchik 142284555Sarybchikstatic efx_mac_ops_t *__efx_mac_ops[] = { 143284555Sarybchik /* [EFX_MAC_INVALID] */ 144227569Sphilip NULL, 145284555Sarybchik /* [EFX_MAC_FALCON_GMAC] */ 146227569Sphilip#if EFSYS_OPT_MAC_FALCON_GMAC 147227569Sphilip &__efx_falcon_gmac_ops, 148227569Sphilip#else 149227569Sphilip NULL, 150284555Sarybchik#endif 151284555Sarybchik /* [EFX_MAC_FALCON_XMAC] */ 152227569Sphilip#if EFSYS_OPT_MAC_FALCON_XMAC 153227569Sphilip &__efx_falcon_xmac_ops, 154227569Sphilip#else 155227569Sphilip NULL, 156284555Sarybchik#endif 157284555Sarybchik /* [EFX_MAC_SIENA] */ 158227569Sphilip#if EFSYS_OPT_SIENA 159227569Sphilip &__efx_siena_mac_ops, 160227569Sphilip#else 161227569Sphilip NULL, 162284555Sarybchik#endif 163284555Sarybchik /* [EFX_MAC_HUNTINGTON] */ 164284555Sarybchik#if EFSYS_OPT_HUNTINGTON 165294395Sarybchik &__efx_ef10_mac_ops, 166284555Sarybchik#else 167284555Sarybchik NULL, 168284555Sarybchik#endif 169294395Sarybchik /* [EFX_MAC_MEDFORD] */ 170294395Sarybchik#if EFSYS_OPT_MEDFORD 171294395Sarybchik &__efx_ef10_mac_ops, 172294395Sarybchik#else 173294395Sarybchik NULL, 174294395Sarybchik#endif 175227569Sphilip}; 176227569Sphilip 177293927Sarybchik __checkReturn efx_rc_t 178227569Sphilipefx_mac_pdu_set( 179227569Sphilip __in efx_nic_t *enp, 180227569Sphilip __in size_t pdu) 181227569Sphilip{ 182227569Sphilip efx_port_t *epp = &(enp->en_port); 183227569Sphilip efx_mac_ops_t *emop = epp->ep_emop; 184227569Sphilip uint32_t old_pdu; 185293927Sarybchik efx_rc_t rc; 186227569Sphilip 187227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 188227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 189227569Sphilip EFSYS_ASSERT(emop != NULL); 190227569Sphilip 191227569Sphilip if (pdu < EFX_MAC_PDU_MIN) { 192227569Sphilip rc = EINVAL; 193227569Sphilip goto fail1; 194227569Sphilip } 195227569Sphilip 196227569Sphilip if (pdu > EFX_MAC_PDU_MAX) { 197227569Sphilip rc = EINVAL; 198227569Sphilip goto fail2; 199227569Sphilip } 200227569Sphilip 201227569Sphilip old_pdu = epp->ep_mac_pdu; 202227569Sphilip epp->ep_mac_pdu = (uint32_t)pdu; 203294397Sarybchik if ((rc = emop->emo_pdu_set(enp)) != 0) 204227569Sphilip goto fail3; 205227569Sphilip 206227569Sphilip return (0); 207227569Sphilip 208227569Sphilipfail3: 209227569Sphilip EFSYS_PROBE(fail3); 210227569Sphilip 211227569Sphilip epp->ep_mac_pdu = old_pdu; 212227569Sphilip 213227569Sphilipfail2: 214227569Sphilip EFSYS_PROBE(fail2); 215227569Sphilipfail1: 216293927Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 217227569Sphilip 218227569Sphilip return (rc); 219227569Sphilip} 220227569Sphilip 221293927Sarybchik __checkReturn efx_rc_t 222227569Sphilipefx_mac_addr_set( 223227569Sphilip __in efx_nic_t *enp, 224227569Sphilip __in uint8_t *addr) 225227569Sphilip{ 226227569Sphilip efx_port_t *epp = &(enp->en_port); 227227569Sphilip efx_mac_ops_t *emop = epp->ep_emop; 228227569Sphilip uint8_t old_addr[6]; 229227569Sphilip uint32_t oui; 230293927Sarybchik efx_rc_t rc; 231227569Sphilip 232227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 233227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 234227569Sphilip 235284555Sarybchik if (EFX_MAC_ADDR_IS_MULTICAST(addr)) { 236227569Sphilip rc = EINVAL; 237227569Sphilip goto fail1; 238227569Sphilip } 239227569Sphilip 240227569Sphilip oui = addr[0] << 16 | addr[1] << 8 | addr[2]; 241227569Sphilip if (oui == 0x000000) { 242227569Sphilip rc = EINVAL; 243227569Sphilip goto fail2; 244227569Sphilip } 245227569Sphilip 246227569Sphilip EFX_MAC_ADDR_COPY(old_addr, epp->ep_mac_addr); 247227569Sphilip EFX_MAC_ADDR_COPY(epp->ep_mac_addr, addr); 248284555Sarybchik if ((rc = emop->emo_addr_set(enp)) != 0) 249227569Sphilip goto fail3; 250227569Sphilip 251227569Sphilip return (0); 252227569Sphilip 253227569Sphilipfail3: 254227569Sphilip EFSYS_PROBE(fail3); 255227569Sphilip 256227569Sphilip EFX_MAC_ADDR_COPY(epp->ep_mac_addr, old_addr); 257227569Sphilip 258227569Sphilipfail2: 259227569Sphilip EFSYS_PROBE(fail2); 260227569Sphilipfail1: 261293927Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 262227569Sphilip 263227569Sphilip return (rc); 264227569Sphilip} 265227569Sphilip 266293927Sarybchik __checkReturn efx_rc_t 267227569Sphilipefx_mac_filter_set( 268227569Sphilip __in efx_nic_t *enp, 269284555Sarybchik __in boolean_t all_unicst, 270284555Sarybchik __in boolean_t mulcst, 271284555Sarybchik __in boolean_t all_mulcst, 272227569Sphilip __in boolean_t brdcst) 273227569Sphilip{ 274227569Sphilip efx_port_t *epp = &(enp->en_port); 275227569Sphilip efx_mac_ops_t *emop = epp->ep_emop; 276284555Sarybchik boolean_t old_all_unicst; 277284555Sarybchik boolean_t old_mulcst; 278284555Sarybchik boolean_t old_all_mulcst; 279227569Sphilip boolean_t old_brdcst; 280293927Sarybchik efx_rc_t rc; 281227569Sphilip 282227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 283227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 284227569Sphilip 285284555Sarybchik old_all_unicst = epp->ep_all_unicst; 286284555Sarybchik old_mulcst = epp->ep_mulcst; 287284555Sarybchik old_all_mulcst = epp->ep_all_mulcst; 288284555Sarybchik old_brdcst = epp->ep_brdcst; 289227569Sphilip 290284555Sarybchik epp->ep_all_unicst = all_unicst; 291284555Sarybchik epp->ep_mulcst = mulcst; 292284555Sarybchik epp->ep_all_mulcst = all_mulcst; 293227569Sphilip epp->ep_brdcst = brdcst; 294227569Sphilip 295227569Sphilip if ((rc = emop->emo_reconfigure(enp)) != 0) 296227569Sphilip goto fail1; 297227569Sphilip 298227569Sphilip return (0); 299227569Sphilip 300227569Sphilipfail1: 301293927Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 302227569Sphilip 303284555Sarybchik epp->ep_all_unicst = old_all_unicst; 304284555Sarybchik epp->ep_mulcst = old_mulcst; 305284555Sarybchik epp->ep_all_mulcst = old_all_mulcst; 306227569Sphilip epp->ep_brdcst = old_brdcst; 307227569Sphilip 308227569Sphilip return (rc); 309227569Sphilip} 310227569Sphilip 311293927Sarybchik __checkReturn efx_rc_t 312227569Sphilipefx_mac_drain( 313227569Sphilip __in efx_nic_t *enp, 314227569Sphilip __in boolean_t enabled) 315227569Sphilip{ 316227569Sphilip efx_port_t *epp = &(enp->en_port); 317227569Sphilip efx_mac_ops_t *emop = epp->ep_emop; 318293927Sarybchik efx_rc_t rc; 319227569Sphilip 320227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 321227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 322227569Sphilip EFSYS_ASSERT(emop != NULL); 323227569Sphilip 324227569Sphilip if (epp->ep_mac_drain == enabled) 325227569Sphilip return (0); 326227569Sphilip 327227569Sphilip epp->ep_mac_drain = enabled; 328227569Sphilip 329227569Sphilip if (enabled && emop->emo_reset != NULL) { 330227569Sphilip if ((rc = emop->emo_reset(enp)) != 0) 331227569Sphilip goto fail1; 332227569Sphilip 333227569Sphilip EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_MAC); 334227569Sphilip enp->en_reset_flags &= ~EFX_RESET_PHY; 335227569Sphilip } 336227569Sphilip 337227569Sphilip if ((rc = emop->emo_reconfigure(enp)) != 0) 338227569Sphilip goto fail2; 339227569Sphilip 340227569Sphilip return (0); 341227569Sphilip 342227569Sphilipfail2: 343227569Sphilip EFSYS_PROBE(fail2); 344227569Sphilipfail1: 345293927Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 346227569Sphilip 347227569Sphilip return (rc); 348227569Sphilip} 349227569Sphilip 350293927Sarybchik __checkReturn efx_rc_t 351227569Sphilipefx_mac_up( 352227569Sphilip __in efx_nic_t *enp, 353227569Sphilip __out boolean_t *mac_upp) 354227569Sphilip{ 355227569Sphilip efx_port_t *epp = &(enp->en_port); 356227569Sphilip efx_mac_ops_t *emop = epp->ep_emop; 357293927Sarybchik efx_rc_t rc; 358227569Sphilip 359227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 360227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 361227569Sphilip 362227569Sphilip if ((rc = emop->emo_up(enp, mac_upp)) != 0) 363227569Sphilip goto fail1; 364227569Sphilip 365227569Sphilip return (0); 366227569Sphilip 367227569Sphilipfail1: 368293927Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 369227569Sphilip 370227569Sphilip return (rc); 371227569Sphilip} 372227569Sphilip 373293927Sarybchik __checkReturn efx_rc_t 374227569Sphilipefx_mac_fcntl_set( 375227569Sphilip __in efx_nic_t *enp, 376227569Sphilip __in unsigned int fcntl, 377227569Sphilip __in boolean_t autoneg) 378227569Sphilip{ 379227569Sphilip efx_port_t *epp = &(enp->en_port); 380227569Sphilip efx_mac_ops_t *emop = epp->ep_emop; 381227569Sphilip efx_phy_ops_t *epop = epp->ep_epop; 382227569Sphilip unsigned int old_fcntl; 383227569Sphilip boolean_t old_autoneg; 384227569Sphilip unsigned int old_adv_cap; 385293927Sarybchik efx_rc_t rc; 386227569Sphilip 387227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 388227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 389227569Sphilip 390227569Sphilip if ((fcntl & ~(EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE)) != 0) { 391227569Sphilip rc = EINVAL; 392227569Sphilip goto fail1; 393227569Sphilip } 394227569Sphilip 395227569Sphilip /* 396284555Sarybchik * Ignore a request to set flow control auto-negotiation 397227569Sphilip * if the PHY doesn't support it. 398227569Sphilip */ 399227569Sphilip if (~epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN)) 400227569Sphilip autoneg = B_FALSE; 401227569Sphilip 402227569Sphilip old_fcntl = epp->ep_fcntl; 403284555Sarybchik old_autoneg = epp->ep_fcntl_autoneg; 404227569Sphilip old_adv_cap = epp->ep_adv_cap_mask; 405227569Sphilip 406227569Sphilip epp->ep_fcntl = fcntl; 407227569Sphilip epp->ep_fcntl_autoneg = autoneg; 408227569Sphilip 409227569Sphilip /* 410284555Sarybchik * Always encode the flow control settings in the advertised 411284555Sarybchik * capabilities even if we are not trying to auto-negotiate 412284555Sarybchik * them and reconfigure both the PHY and the MAC. 413227569Sphilip */ 414284555Sarybchik if (fcntl & EFX_FCNTL_RESPOND) 415284555Sarybchik epp->ep_adv_cap_mask |= (1 << EFX_PHY_CAP_PAUSE | 416284555Sarybchik 1 << EFX_PHY_CAP_ASYM); 417284555Sarybchik else 418284555Sarybchik epp->ep_adv_cap_mask &= ~(1 << EFX_PHY_CAP_PAUSE | 419284555Sarybchik 1 << EFX_PHY_CAP_ASYM); 420227569Sphilip 421284555Sarybchik if (fcntl & EFX_FCNTL_GENERATE) 422284555Sarybchik epp->ep_adv_cap_mask ^= (1 << EFX_PHY_CAP_ASYM); 423227569Sphilip 424284555Sarybchik if ((rc = epop->epo_reconfigure(enp)) != 0) 425284555Sarybchik goto fail2; 426227569Sphilip 427284555Sarybchik if ((rc = emop->emo_reconfigure(enp)) != 0) 428284555Sarybchik goto fail3; 429227569Sphilip 430227569Sphilip return (0); 431227569Sphilip 432284555Sarybchikfail3: 433284555Sarybchik EFSYS_PROBE(fail3); 434284555Sarybchik 435227569Sphilipfail2: 436227569Sphilip EFSYS_PROBE(fail2); 437227569Sphilip 438227569Sphilip epp->ep_fcntl = old_fcntl; 439227569Sphilip epp->ep_fcntl_autoneg = old_autoneg; 440227569Sphilip epp->ep_adv_cap_mask = old_adv_cap; 441227569Sphilip 442227569Sphilipfail1: 443293927Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 444227569Sphilip 445227569Sphilip return (rc); 446227569Sphilip} 447227569Sphilip 448227569Sphilip void 449227569Sphilipefx_mac_fcntl_get( 450227569Sphilip __in efx_nic_t *enp, 451227569Sphilip __out unsigned int *fcntl_wantedp, 452227569Sphilip __out unsigned int *fcntl_linkp) 453227569Sphilip{ 454227569Sphilip efx_port_t *epp = &(enp->en_port); 455284555Sarybchik unsigned int wanted = 0; 456227569Sphilip 457227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 458227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 459227569Sphilip 460227569Sphilip /* 461284555Sarybchik * Decode the requested flow control settings from the PHY 462284555Sarybchik * advertised capabilities. 463227569Sphilip */ 464284555Sarybchik if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_PAUSE)) 465284555Sarybchik wanted = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE; 466284555Sarybchik if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_ASYM)) 467284555Sarybchik wanted ^= EFX_FCNTL_GENERATE; 468227569Sphilip 469227569Sphilip *fcntl_linkp = epp->ep_fcntl; 470227569Sphilip *fcntl_wantedp = wanted; 471227569Sphilip} 472227569Sphilip 473293927Sarybchik __checkReturn efx_rc_t 474284555Sarybchikefx_mac_multicast_list_set( 475284555Sarybchik __in efx_nic_t *enp, 476284555Sarybchik __in_ecount(6*count) uint8_t const *addrs, 477284555Sarybchik __in int count) 478284555Sarybchik{ 479284555Sarybchik efx_port_t *epp = &(enp->en_port); 480284555Sarybchik efx_mac_ops_t *emop = epp->ep_emop; 481284555Sarybchik uint8_t *old_mulcst_addr_list = NULL; 482284555Sarybchik uint32_t old_mulcst_addr_count; 483293927Sarybchik efx_rc_t rc; 484284555Sarybchik 485284555Sarybchik EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 486284555Sarybchik EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 487284555Sarybchik 488284555Sarybchik if (count > EFX_MAC_MULTICAST_LIST_MAX) { 489284555Sarybchik rc = EINVAL; 490284555Sarybchik goto fail1; 491284555Sarybchik } 492284555Sarybchik 493284555Sarybchik old_mulcst_addr_count = epp->ep_mulcst_addr_count; 494284555Sarybchik if (old_mulcst_addr_count > 0) { 495284555Sarybchik /* Allocate memory to store old list (instead of using stack) */ 496284555Sarybchik EFSYS_KMEM_ALLOC(enp->en_esip, 497284555Sarybchik old_mulcst_addr_count * EFX_MAC_ADDR_LEN, 498284555Sarybchik old_mulcst_addr_list); 499284555Sarybchik if (old_mulcst_addr_list == NULL) { 500284555Sarybchik rc = ENOMEM; 501284555Sarybchik goto fail2; 502284555Sarybchik } 503284555Sarybchik 504284555Sarybchik /* Save the old list in case we need to rollback */ 505284555Sarybchik memcpy(old_mulcst_addr_list, epp->ep_mulcst_addr_list, 506284555Sarybchik old_mulcst_addr_count * EFX_MAC_ADDR_LEN); 507284555Sarybchik } 508284555Sarybchik 509284555Sarybchik /* Store the new list */ 510284555Sarybchik memcpy(epp->ep_mulcst_addr_list, addrs, 511284555Sarybchik count * EFX_MAC_ADDR_LEN); 512284555Sarybchik epp->ep_mulcst_addr_count = count; 513284555Sarybchik 514284555Sarybchik if ((rc = emop->emo_multicast_list_set(enp)) != 0) 515284555Sarybchik goto fail3; 516284555Sarybchik 517284555Sarybchik if (old_mulcst_addr_count > 0) { 518284555Sarybchik EFSYS_KMEM_FREE(enp->en_esip, 519284555Sarybchik old_mulcst_addr_count * EFX_MAC_ADDR_LEN, 520284555Sarybchik old_mulcst_addr_list); 521284555Sarybchik } 522284555Sarybchik 523284555Sarybchik return (0); 524284555Sarybchik 525284555Sarybchikfail3: 526284555Sarybchik EFSYS_PROBE(fail3); 527284555Sarybchik 528284555Sarybchik /* Restore original list on failure */ 529284555Sarybchik epp->ep_mulcst_addr_count = old_mulcst_addr_count; 530284555Sarybchik if (old_mulcst_addr_count > 0) { 531284555Sarybchik memcpy(epp->ep_mulcst_addr_list, old_mulcst_addr_list, 532284555Sarybchik old_mulcst_addr_count * EFX_MAC_ADDR_LEN); 533284555Sarybchik 534284555Sarybchik EFSYS_KMEM_FREE(enp->en_esip, 535284555Sarybchik old_mulcst_addr_count * EFX_MAC_ADDR_LEN, 536284555Sarybchik old_mulcst_addr_list); 537284555Sarybchik } 538284555Sarybchik 539284555Sarybchikfail2: 540284555Sarybchik EFSYS_PROBE(fail2); 541284555Sarybchik 542284555Sarybchikfail1: 543293927Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 544284555Sarybchik 545284555Sarybchik return (rc); 546284555Sarybchik 547284555Sarybchik} 548284555Sarybchik 549293927Sarybchik __checkReturn efx_rc_t 550284555Sarybchikefx_mac_filter_default_rxq_set( 551284555Sarybchik __in efx_nic_t *enp, 552284555Sarybchik __in efx_rxq_t *erp, 553284555Sarybchik __in boolean_t using_rss) 554284555Sarybchik{ 555284555Sarybchik efx_port_t *epp = &(enp->en_port); 556284555Sarybchik efx_mac_ops_t *emop = epp->ep_emop; 557293927Sarybchik efx_rc_t rc; 558284555Sarybchik 559284555Sarybchik EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 560284555Sarybchik EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 561284555Sarybchik 562284555Sarybchik if (emop->emo_filter_default_rxq_set != NULL) { 563284555Sarybchik rc = emop->emo_filter_default_rxq_set(enp, erp, using_rss); 564284555Sarybchik if (rc != 0) 565284555Sarybchik goto fail1; 566284555Sarybchik } 567284555Sarybchik 568284555Sarybchik return (0); 569284555Sarybchik 570284555Sarybchikfail1: 571293927Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 572284555Sarybchik 573284555Sarybchik return (rc); 574284555Sarybchik} 575284555Sarybchik 576284555Sarybchik void 577284555Sarybchikefx_mac_filter_default_rxq_clear( 578284555Sarybchik __in efx_nic_t *enp) 579284555Sarybchik{ 580284555Sarybchik efx_port_t *epp = &(enp->en_port); 581284555Sarybchik efx_mac_ops_t *emop = epp->ep_emop; 582284555Sarybchik 583284555Sarybchik EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 584284555Sarybchik EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 585284555Sarybchik 586284555Sarybchik if (emop->emo_filter_default_rxq_clear != NULL) 587284555Sarybchik emop->emo_filter_default_rxq_clear(enp); 588284555Sarybchik} 589284555Sarybchik 590284555Sarybchik 591227569Sphilip#if EFSYS_OPT_MAC_STATS 592227569Sphilip 593227569Sphilip#if EFSYS_OPT_NAMES 594227569Sphilip 595284555Sarybchik/* START MKCONFIG GENERATED EfxMacStatNamesBlock 054d43a31d2d7a45 */ 596284555Sarybchikstatic const char *__efx_mac_stat_name[] = { 597227569Sphilip "rx_octets", 598227569Sphilip "rx_pkts", 599227569Sphilip "rx_unicst_pkts", 600227569Sphilip "rx_multicst_pkts", 601227569Sphilip "rx_brdcst_pkts", 602227569Sphilip "rx_pause_pkts", 603227569Sphilip "rx_le_64_pkts", 604227569Sphilip "rx_65_to_127_pkts", 605227569Sphilip "rx_128_to_255_pkts", 606227569Sphilip "rx_256_to_511_pkts", 607227569Sphilip "rx_512_to_1023_pkts", 608227569Sphilip "rx_1024_to_15xx_pkts", 609227569Sphilip "rx_ge_15xx_pkts", 610227569Sphilip "rx_errors", 611227569Sphilip "rx_fcs_errors", 612227569Sphilip "rx_drop_events", 613227569Sphilip "rx_false_carrier_errors", 614227569Sphilip "rx_symbol_errors", 615227569Sphilip "rx_align_errors", 616227569Sphilip "rx_internal_errors", 617227569Sphilip "rx_jabber_pkts", 618227569Sphilip "rx_lane0_char_err", 619227569Sphilip "rx_lane1_char_err", 620227569Sphilip "rx_lane2_char_err", 621227569Sphilip "rx_lane3_char_err", 622227569Sphilip "rx_lane0_disp_err", 623227569Sphilip "rx_lane1_disp_err", 624227569Sphilip "rx_lane2_disp_err", 625227569Sphilip "rx_lane3_disp_err", 626227569Sphilip "rx_match_fault", 627227569Sphilip "rx_nodesc_drop_cnt", 628227569Sphilip "tx_octets", 629227569Sphilip "tx_pkts", 630227569Sphilip "tx_unicst_pkts", 631227569Sphilip "tx_multicst_pkts", 632227569Sphilip "tx_brdcst_pkts", 633227569Sphilip "tx_pause_pkts", 634227569Sphilip "tx_le_64_pkts", 635227569Sphilip "tx_65_to_127_pkts", 636227569Sphilip "tx_128_to_255_pkts", 637227569Sphilip "tx_256_to_511_pkts", 638227569Sphilip "tx_512_to_1023_pkts", 639227569Sphilip "tx_1024_to_15xx_pkts", 640227569Sphilip "tx_ge_15xx_pkts", 641227569Sphilip "tx_errors", 642227569Sphilip "tx_sgl_col_pkts", 643227569Sphilip "tx_mult_col_pkts", 644227569Sphilip "tx_ex_col_pkts", 645227569Sphilip "tx_late_col_pkts", 646227569Sphilip "tx_def_pkts", 647227569Sphilip "tx_ex_def_pkts", 648284555Sarybchik "pm_trunc_bb_overflow", 649284555Sarybchik "pm_discard_bb_overflow", 650284555Sarybchik "pm_trunc_vfifo_full", 651284555Sarybchik "pm_discard_vfifo_full", 652284555Sarybchik "pm_trunc_qbb", 653284555Sarybchik "pm_discard_qbb", 654284555Sarybchik "pm_discard_mapping", 655284555Sarybchik "rxdp_q_disabled_pkts", 656284555Sarybchik "rxdp_di_dropped_pkts", 657284555Sarybchik "rxdp_streaming_pkts", 658284555Sarybchik "rxdp_hlb_fetch", 659284555Sarybchik "rxdp_hlb_wait", 660284555Sarybchik "vadapter_rx_unicast_packets", 661284555Sarybchik "vadapter_rx_unicast_bytes", 662284555Sarybchik "vadapter_rx_multicast_packets", 663284555Sarybchik "vadapter_rx_multicast_bytes", 664284555Sarybchik "vadapter_rx_broadcast_packets", 665284555Sarybchik "vadapter_rx_broadcast_bytes", 666284555Sarybchik "vadapter_rx_bad_packets", 667284555Sarybchik "vadapter_rx_bad_bytes", 668284555Sarybchik "vadapter_rx_overflow", 669284555Sarybchik "vadapter_tx_unicast_packets", 670284555Sarybchik "vadapter_tx_unicast_bytes", 671284555Sarybchik "vadapter_tx_multicast_packets", 672284555Sarybchik "vadapter_tx_multicast_bytes", 673284555Sarybchik "vadapter_tx_broadcast_packets", 674284555Sarybchik "vadapter_tx_broadcast_bytes", 675284555Sarybchik "vadapter_tx_bad_packets", 676284555Sarybchik "vadapter_tx_bad_bytes", 677284555Sarybchik "vadapter_tx_overflow", 678227569Sphilip}; 679227569Sphilip/* END MKCONFIG GENERATED EfxMacStatNamesBlock */ 680227569Sphilip 681284555Sarybchik __checkReturn const char * 682227569Sphilipefx_mac_stat_name( 683227569Sphilip __in efx_nic_t *enp, 684227569Sphilip __in unsigned int id) 685227569Sphilip{ 686227569Sphilip _NOTE(ARGUNUSED(enp)) 687227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 688227569Sphilip 689227569Sphilip EFSYS_ASSERT3U(id, <, EFX_MAC_NSTATS); 690227569Sphilip return (__efx_mac_stat_name[id]); 691227569Sphilip} 692227569Sphilip 693284555Sarybchik#endif /* EFSYS_OPT_NAMES */ 694227569Sphilip 695293927Sarybchik __checkReturn efx_rc_t 696227569Sphilipefx_mac_stats_upload( 697227569Sphilip __in efx_nic_t *enp, 698227569Sphilip __in efsys_mem_t *esmp) 699227569Sphilip{ 700227569Sphilip efx_port_t *epp = &(enp->en_port); 701227569Sphilip efx_mac_ops_t *emop = epp->ep_emop; 702293927Sarybchik efx_rc_t rc; 703227569Sphilip 704227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 705227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 706227569Sphilip EFSYS_ASSERT(emop != NULL); 707227569Sphilip 708227569Sphilip /* 709227569Sphilip * Don't assert !ep_mac_stats_pending, because the client might 710227569Sphilip * have failed to finalise statistics when previously stopping 711227569Sphilip * the port. 712227569Sphilip */ 713227569Sphilip if ((rc = emop->emo_stats_upload(enp, esmp)) != 0) 714227569Sphilip goto fail1; 715227569Sphilip 716227569Sphilip epp->ep_mac_stats_pending = B_TRUE; 717227569Sphilip 718227569Sphilip return (0); 719227569Sphilip 720227569Sphilipfail1: 721293927Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 722227569Sphilip 723227569Sphilip return (rc); 724227569Sphilip} 725227569Sphilip 726293927Sarybchik __checkReturn efx_rc_t 727227569Sphilipefx_mac_stats_periodic( 728227569Sphilip __in efx_nic_t *enp, 729227569Sphilip __in efsys_mem_t *esmp, 730227569Sphilip __in uint16_t period_ms, 731227569Sphilip __in boolean_t events) 732227569Sphilip{ 733227569Sphilip efx_port_t *epp = &(enp->en_port); 734227569Sphilip efx_mac_ops_t *emop = epp->ep_emop; 735293927Sarybchik efx_rc_t rc; 736227569Sphilip 737227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 738227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 739227569Sphilip 740227569Sphilip EFSYS_ASSERT(emop != NULL); 741227569Sphilip 742227569Sphilip if (emop->emo_stats_periodic == NULL) { 743227569Sphilip rc = EINVAL; 744227569Sphilip goto fail1; 745227569Sphilip } 746227569Sphilip 747227569Sphilip if ((rc = emop->emo_stats_periodic(enp, esmp, period_ms, events)) != 0) 748227569Sphilip goto fail2; 749227569Sphilip 750227569Sphilip return (0); 751227569Sphilip 752227569Sphilipfail2: 753227569Sphilip EFSYS_PROBE(fail2); 754227569Sphilipfail1: 755293927Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 756227569Sphilip 757227569Sphilip return (rc); 758227569Sphilip} 759227569Sphilip 760227569Sphilip 761293927Sarybchik __checkReturn efx_rc_t 762227569Sphilipefx_mac_stats_update( 763227569Sphilip __in efx_nic_t *enp, 764227569Sphilip __in efsys_mem_t *esmp, 765227569Sphilip __inout_ecount(EFX_MAC_NSTATS) efsys_stat_t *essp, 766293923Sarybchik __inout_opt uint32_t *generationp) 767227569Sphilip{ 768227569Sphilip efx_port_t *epp = &(enp->en_port); 769227569Sphilip efx_mac_ops_t *emop = epp->ep_emop; 770293927Sarybchik efx_rc_t rc; 771227569Sphilip 772227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 773227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 774227569Sphilip EFSYS_ASSERT(emop != NULL); 775227569Sphilip 776227569Sphilip rc = emop->emo_stats_update(enp, esmp, essp, generationp); 777227569Sphilip if (rc == 0) 778227569Sphilip epp->ep_mac_stats_pending = B_FALSE; 779227569Sphilip 780227569Sphilip return (rc); 781227569Sphilip} 782227569Sphilip 783227569Sphilip#endif /* EFSYS_OPT_MAC_STATS */ 784227569Sphilip 785293927Sarybchik __checkReturn efx_rc_t 786227569Sphilipefx_mac_select( 787227569Sphilip __in efx_nic_t *enp) 788227569Sphilip{ 789227569Sphilip efx_port_t *epp = &(enp->en_port); 790227569Sphilip efx_mac_type_t type = EFX_MAC_INVALID; 791227569Sphilip efx_mac_ops_t *emop; 792227569Sphilip int rc = EINVAL; 793227569Sphilip 794294395Sarybchik#if EFSYS_OPT_SIENA 795294395Sarybchik if (enp->en_family == EFX_FAMILY_SIENA) { 796294395Sarybchik type = EFX_MAC_SIENA; 797294395Sarybchik goto chosen; 798294395Sarybchik } 799294395Sarybchik#endif 800294395Sarybchik 801284555Sarybchik#if EFSYS_OPT_HUNTINGTON 802284555Sarybchik if (enp->en_family == EFX_FAMILY_HUNTINGTON) { 803284555Sarybchik type = EFX_MAC_HUNTINGTON; 804284555Sarybchik goto chosen; 805284555Sarybchik } 806284555Sarybchik#endif 807284555Sarybchik 808294395Sarybchik#if EFSYS_OPT_MEDFORD 809294395Sarybchik if (enp->en_family == EFX_FAMILY_MEDFORD) { 810294395Sarybchik type = EFX_MAC_MEDFORD; 811227569Sphilip goto chosen; 812227569Sphilip } 813227569Sphilip#endif 814227569Sphilip 815227569Sphilip#if EFSYS_OPT_FALCON 816227569Sphilip switch (epp->ep_link_mode) { 817227569Sphilip#if EFSYS_OPT_MAC_FALCON_GMAC 818227569Sphilip case EFX_LINK_100HDX: 819227569Sphilip case EFX_LINK_100FDX: 820227569Sphilip case EFX_LINK_1000HDX: 821227569Sphilip case EFX_LINK_1000FDX: 822227569Sphilip type = EFX_MAC_FALCON_GMAC; 823227569Sphilip goto chosen; 824227569Sphilip#endif /* EFSYS_OPT_FALCON_GMAC */ 825227569Sphilip 826227569Sphilip#if EFSYS_OPT_MAC_FALCON_XMAC 827227569Sphilip case EFX_LINK_10000FDX: 828227569Sphilip type = EFX_MAC_FALCON_XMAC; 829227569Sphilip goto chosen; 830227569Sphilip#endif /* EFSYS_OPT_FALCON_XMAC */ 831227569Sphilip 832227569Sphilip default: 833227569Sphilip#if EFSYS_OPT_MAC_FALCON_GMAC && EFSYS_OPT_MAC_FALCON_XMAC 834227569Sphilip /* Only initialise a MAC supported by the PHY */ 835227569Sphilip if (epp->ep_phy_cap_mask & 836227569Sphilip ((1 << EFX_PHY_CAP_1000FDX) | 837227569Sphilip (1 << EFX_PHY_CAP_1000HDX) | 838227569Sphilip (1 << EFX_PHY_CAP_100FDX) | 839227569Sphilip (1 << EFX_PHY_CAP_100HDX) | 840227569Sphilip (1 << EFX_PHY_CAP_10FDX) | 841227569Sphilip (1 << EFX_PHY_CAP_10FDX))) 842227569Sphilip type = EFX_MAC_FALCON_GMAC; 843227569Sphilip else 844227569Sphilip type = EFX_MAC_FALCON_XMAC; 845227569Sphilip#elif EFSYS_OPT_MAC_FALCON_GMAC 846227569Sphilip type = EFX_MAC_FALCON_GMAC; 847227569Sphilip#else 848227569Sphilip type = EFX_MAC_FALCON_XMAC; 849227569Sphilip#endif 850227569Sphilip goto chosen; 851227569Sphilip } 852227569Sphilip#endif /* EFSYS_OPT_FALCON */ 853227569Sphilip 854227569Sphilipchosen: 855227569Sphilip EFSYS_ASSERT(type != EFX_MAC_INVALID); 856227569Sphilip EFSYS_ASSERT3U(type, <, EFX_MAC_NTYPES); 857227569Sphilip emop = epp->ep_emop = (efx_mac_ops_t *)__efx_mac_ops[type]; 858227569Sphilip EFSYS_ASSERT(emop != NULL); 859227569Sphilip 860227569Sphilip epp->ep_mac_type = type; 861280535Sarybchik 862227569Sphilip if (emop->emo_reset != NULL) { 863227569Sphilip if ((rc = emop->emo_reset(enp)) != 0) 864227569Sphilip goto fail1; 865280535Sarybchik 866227569Sphilip EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_MAC); 867227569Sphilip enp->en_reset_flags &= ~EFX_RESET_MAC; 868227569Sphilip } 869227569Sphilip 870227569Sphilip return (0); 871227569Sphilip 872227569Sphilipfail1: 873293927Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 874227569Sphilip 875227569Sphilip return (rc); 876227569Sphilip} 877284555Sarybchik 878284555Sarybchik 879284555Sarybchik#if EFSYS_OPT_FALCON || EFSYS_OPT_SIENA 880284555Sarybchik 881293998Sarybchik#define EFX_MAC_HASH_BITS (1 << 8) 882293998Sarybchik 883284555Sarybchik/* Compute the multicast hash as used on Falcon and Siena. */ 884284555Sarybchikstatic void 885284555Sarybchikfalconsiena_mac_multicast_hash_compute( 886284555Sarybchik __in_ecount(6*count) uint8_t const *addrs, 887284555Sarybchik __in int count, 888284555Sarybchik __out efx_oword_t *hash_low, 889284555Sarybchik __out efx_oword_t *hash_high) 890284555Sarybchik{ 891284555Sarybchik uint32_t crc, index; 892284555Sarybchik int i; 893284555Sarybchik 894284555Sarybchik EFSYS_ASSERT(hash_low != NULL); 895284555Sarybchik EFSYS_ASSERT(hash_high != NULL); 896284555Sarybchik 897284555Sarybchik EFX_ZERO_OWORD(*hash_low); 898284555Sarybchik EFX_ZERO_OWORD(*hash_high); 899284555Sarybchik 900284555Sarybchik for (i = 0; i < count; i++) { 901284555Sarybchik /* Calculate hash bucket (IEEE 802.3 CRC32 of the MAC addr) */ 902284555Sarybchik crc = efx_crc32_calculate(0xffffffff, addrs, EFX_MAC_ADDR_LEN); 903284555Sarybchik index = crc % EFX_MAC_HASH_BITS; 904284555Sarybchik if (index < 128) { 905284555Sarybchik EFX_SET_OWORD_BIT(*hash_low, index); 906284555Sarybchik } else { 907284555Sarybchik EFX_SET_OWORD_BIT(*hash_high, index - 128); 908284555Sarybchik } 909284555Sarybchik 910284555Sarybchik addrs += EFX_MAC_ADDR_LEN; 911284555Sarybchik } 912284555Sarybchik} 913284555Sarybchik 914293927Sarybchikstatic __checkReturn efx_rc_t 915284555Sarybchikfalconsiena_mac_multicast_list_set( 916293927Sarybchik __in efx_nic_t *enp) 917284555Sarybchik{ 918284555Sarybchik efx_port_t *epp = &(enp->en_port); 919284555Sarybchik efx_mac_ops_t *emop = epp->ep_emop; 920284555Sarybchik efx_oword_t old_hash[2]; 921293927Sarybchik efx_rc_t rc; 922284555Sarybchik 923284555Sarybchik EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 924284555Sarybchik EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 925284555Sarybchik 926284555Sarybchik memcpy(old_hash, epp->ep_multicst_hash, sizeof (old_hash)); 927284555Sarybchik 928284555Sarybchik falconsiena_mac_multicast_hash_compute(epp->ep_mulcst_addr_list, 929284555Sarybchik epp->ep_mulcst_addr_count, 930284555Sarybchik &epp->ep_multicst_hash[0], 931284555Sarybchik &epp->ep_multicst_hash[1]); 932284555Sarybchik 933284555Sarybchik if ((rc = emop->emo_reconfigure(enp)) != 0) 934284555Sarybchik goto fail1; 935284555Sarybchik 936284555Sarybchik return (0); 937284555Sarybchik 938284555Sarybchikfail1: 939293927Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 940284555Sarybchik 941284555Sarybchik memcpy(epp->ep_multicst_hash, old_hash, sizeof (old_hash)); 942284555Sarybchik 943284555Sarybchik return (rc); 944284555Sarybchik} 945284555Sarybchik 946284555Sarybchik#endif /* EFSYS_OPT_FALCON || EFSYS_OPT_SIENA */ 947