1227569Sphilip/*- 2227569Sphilip * Copyright 2007-2009 Solarflare Communications Inc. All rights reserved. 3227569Sphilip * 4227569Sphilip * Redistribution and use in source and binary forms, with or without 5227569Sphilip * modification, are permitted provided that the following conditions 6227569Sphilip * are met: 7227569Sphilip * 1. Redistributions of source code must retain the above copyright 8227569Sphilip * notice, this list of conditions and the following disclaimer. 9227569Sphilip * 2. Redistributions in binary form must reproduce the above copyright 10227569Sphilip * notice, this list of conditions and the following disclaimer in the 11227569Sphilip * documentation and/or other materials provided with the distribution. 12227569Sphilip * 13227569Sphilip * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND 14227569Sphilip * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15227569Sphilip * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16227569Sphilip * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17227569Sphilip * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18227569Sphilip * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19227569Sphilip * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20227569Sphilip * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21227569Sphilip * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22227569Sphilip * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23227569Sphilip * SUCH DAMAGE. 24227569Sphilip */ 25227569Sphilip 26228100Sphilip#include <sys/cdefs.h> 27228100Sphilip__FBSDID("$FreeBSD$"); 28228100Sphilip 29227569Sphilip#include "efsys.h" 30227569Sphilip#include "efx.h" 31227569Sphilip#include "efx_types.h" 32227569Sphilip#include "efx_impl.h" 33227569Sphilip 34227569Sphilip#if EFSYS_OPT_MAC_FALCON_GMAC 35227569Sphilip#include "falcon_gmac.h" 36227569Sphilip#endif 37227569Sphilip 38227569Sphilip#if EFSYS_OPT_MAC_FALCON_XMAC 39227569Sphilip#include "falcon_xmac.h" 40227569Sphilip#endif 41227569Sphilip 42227569Sphilip#if EFSYS_OPT_MAC_FALCON_GMAC 43227569Sphilipstatic efx_mac_ops_t __cs __efx_falcon_gmac_ops = { 44227569Sphilip falcon_gmac_reset, /* emo_reset */ 45227569Sphilip falcon_mac_poll, /* emo_poll */ 46227569Sphilip falcon_mac_up, /* emo_up */ 47227569Sphilip falcon_gmac_reconfigure, /* emo_reconfigure */ 48227569Sphilip#if EFSYS_OPT_LOOPBACK 49227569Sphilip falcon_mac_loopback_set, /* emo_loopback_set */ 50227569Sphilip#endif /* EFSYS_OPT_LOOPBACK */ 51227569Sphilip#if EFSYS_OPT_MAC_STATS 52227569Sphilip falcon_mac_stats_upload, /* emo_stats_upload */ 53227569Sphilip NULL, /* emo_stats_periodic */ 54227569Sphilip falcon_gmac_stats_update /* emo_stats_update */ 55227569Sphilip#endif /* EFSYS_OPT_MAC_STATS */ 56227569Sphilip}; 57227569Sphilip#endif /* EFSYS_OPT_MAC_FALCON_GMAC */ 58227569Sphilip 59227569Sphilip#if EFSYS_OPT_MAC_FALCON_XMAC 60227569Sphilipstatic efx_mac_ops_t __cs __efx_falcon_xmac_ops = { 61227569Sphilip falcon_xmac_reset, /* emo_reset */ 62227569Sphilip falcon_mac_poll, /* emo_poll */ 63227569Sphilip falcon_mac_up, /* emo_up */ 64227569Sphilip falcon_xmac_reconfigure, /* emo_reconfigure */ 65227569Sphilip#if EFSYS_OPT_LOOPBACK 66227569Sphilip falcon_mac_loopback_set, /* emo_loopback_set */ 67227569Sphilip#endif /* EFSYS_OPT_LOOPBACK */ 68227569Sphilip#if EFSYS_OPT_MAC_STATS 69227569Sphilip falcon_mac_stats_upload, /* emo_stats_upload */ 70227569Sphilip NULL, /* emo_stats_periodic */ 71227569Sphilip falcon_xmac_stats_update /* emo_stats_update */ 72227569Sphilip#endif /* EFSYS_OPT_MAC_STATS */ 73227569Sphilip}; 74227569Sphilip#endif /* EFSYS_OPT_MAC_FALCON_XMAC */ 75227569Sphilip 76227569Sphilip#if EFSYS_OPT_SIENA 77227569Sphilipstatic efx_mac_ops_t __cs __efx_siena_mac_ops = { 78227569Sphilip NULL, /* emo_reset */ 79227569Sphilip siena_mac_poll, /* emo_poll */ 80227569Sphilip siena_mac_up, /* emo_up */ 81227569Sphilip siena_mac_reconfigure, /* emo_reconfigure */ 82227569Sphilip#if EFSYS_OPT_LOOPBACK 83227569Sphilip siena_mac_loopback_set, /* emo_loopback_set */ 84227569Sphilip#endif /* EFSYS_OPT_LOOPBACK */ 85227569Sphilip#if EFSYS_OPT_MAC_STATS 86227569Sphilip siena_mac_stats_upload, /* emo_stats_upload */ 87227569Sphilip siena_mac_stats_periodic, /* emo_stats_periodic */ 88227569Sphilip siena_mac_stats_update /* emo_stats_update */ 89227569Sphilip#endif /* EFSYS_OPT_MAC_STATS */ 90227569Sphilip}; 91227569Sphilip#endif /* EFSYS_OPT_SIENA */ 92227569Sphilip 93227569Sphilipstatic efx_mac_ops_t __cs * __cs __efx_mac_ops[] = { 94227569Sphilip NULL, 95227569Sphilip#if EFSYS_OPT_MAC_FALCON_GMAC 96227569Sphilip &__efx_falcon_gmac_ops, 97227569Sphilip#else 98227569Sphilip NULL, 99227569Sphilip#endif /* EFSYS_OPT_MAC_FALCON_GMAC */ 100227569Sphilip#if EFSYS_OPT_MAC_FALCON_XMAC 101227569Sphilip &__efx_falcon_xmac_ops, 102227569Sphilip#else 103227569Sphilip NULL, 104227569Sphilip#endif /* EFSYS_OPT_MAC_FALCON_XMAC */ 105227569Sphilip#if EFSYS_OPT_SIENA 106227569Sphilip &__efx_siena_mac_ops, 107227569Sphilip#else 108227569Sphilip NULL, 109227569Sphilip#endif /* EFSYS_OPT_SIENA */ 110227569Sphilip}; 111227569Sphilip 112227569Sphilip __checkReturn int 113227569Sphilipefx_mac_pdu_set( 114227569Sphilip __in efx_nic_t *enp, 115227569Sphilip __in size_t pdu) 116227569Sphilip{ 117227569Sphilip efx_port_t *epp = &(enp->en_port); 118227569Sphilip efx_mac_ops_t *emop = epp->ep_emop; 119227569Sphilip uint32_t old_pdu; 120227569Sphilip int rc; 121227569Sphilip 122227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 123227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 124227569Sphilip EFSYS_ASSERT(emop != NULL); 125227569Sphilip 126227569Sphilip if (pdu < EFX_MAC_PDU_MIN) { 127227569Sphilip rc = EINVAL; 128227569Sphilip goto fail1; 129227569Sphilip } 130227569Sphilip 131227569Sphilip if (pdu > EFX_MAC_PDU_MAX) { 132227569Sphilip rc = EINVAL; 133227569Sphilip goto fail2; 134227569Sphilip } 135227569Sphilip 136227569Sphilip old_pdu = epp->ep_mac_pdu; 137227569Sphilip epp->ep_mac_pdu = (uint32_t)pdu; 138227569Sphilip if ((rc = emop->emo_reconfigure(enp)) != 0) 139227569Sphilip goto fail3; 140227569Sphilip 141227569Sphilip return (0); 142227569Sphilip 143227569Sphilipfail3: 144227569Sphilip EFSYS_PROBE(fail3); 145227569Sphilip 146227569Sphilip epp->ep_mac_pdu = old_pdu; 147227569Sphilip 148227569Sphilipfail2: 149227569Sphilip EFSYS_PROBE(fail2); 150227569Sphilipfail1: 151227569Sphilip EFSYS_PROBE1(fail1, int, rc); 152227569Sphilip 153227569Sphilip return (rc); 154227569Sphilip} 155227569Sphilip 156227569Sphilip __checkReturn int 157227569Sphilipefx_mac_addr_set( 158227569Sphilip __in efx_nic_t *enp, 159227569Sphilip __in uint8_t *addr) 160227569Sphilip{ 161227569Sphilip efx_port_t *epp = &(enp->en_port); 162227569Sphilip efx_mac_ops_t *emop = epp->ep_emop; 163227569Sphilip uint8_t old_addr[6]; 164227569Sphilip uint32_t oui; 165227569Sphilip int rc; 166227569Sphilip 167227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 168227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 169227569Sphilip 170227569Sphilip if (addr[0] & 0x01) { 171227569Sphilip rc = EINVAL; 172227569Sphilip goto fail1; 173227569Sphilip } 174227569Sphilip 175227569Sphilip oui = addr[0] << 16 | addr[1] << 8 | addr[2]; 176227569Sphilip if (oui == 0x000000) { 177227569Sphilip rc = EINVAL; 178227569Sphilip goto fail2; 179227569Sphilip } 180227569Sphilip 181227569Sphilip EFX_MAC_ADDR_COPY(old_addr, epp->ep_mac_addr); 182227569Sphilip EFX_MAC_ADDR_COPY(epp->ep_mac_addr, addr); 183227569Sphilip if ((rc = emop->emo_reconfigure(enp)) != 0) 184227569Sphilip goto fail3; 185227569Sphilip 186227569Sphilip return (0); 187227569Sphilip 188227569Sphilipfail3: 189227569Sphilip EFSYS_PROBE(fail3); 190227569Sphilip 191227569Sphilip EFX_MAC_ADDR_COPY(epp->ep_mac_addr, old_addr); 192227569Sphilip 193227569Sphilipfail2: 194227569Sphilip EFSYS_PROBE(fail2); 195227569Sphilipfail1: 196227569Sphilip EFSYS_PROBE1(fail1, int, rc); 197227569Sphilip 198227569Sphilip return (rc); 199227569Sphilip} 200227569Sphilip 201227569Sphilip __checkReturn int 202227569Sphilipefx_mac_filter_set( 203227569Sphilip __in efx_nic_t *enp, 204227569Sphilip __in boolean_t unicst, 205227569Sphilip __in boolean_t brdcst) 206227569Sphilip{ 207227569Sphilip efx_port_t *epp = &(enp->en_port); 208227569Sphilip efx_mac_ops_t *emop = epp->ep_emop; 209227569Sphilip boolean_t old_unicst; 210227569Sphilip boolean_t old_brdcst; 211227569Sphilip int rc; 212227569Sphilip 213227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 214227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 215227569Sphilip 216227569Sphilip old_unicst = unicst; 217227569Sphilip old_brdcst = brdcst; 218227569Sphilip 219227569Sphilip epp->ep_unicst = unicst; 220227569Sphilip epp->ep_brdcst = brdcst; 221227569Sphilip 222227569Sphilip if ((rc = emop->emo_reconfigure(enp)) != 0) 223227569Sphilip goto fail1; 224227569Sphilip 225227569Sphilip return (0); 226227569Sphilip 227227569Sphilipfail1: 228227569Sphilip EFSYS_PROBE1(fail1, int, rc); 229227569Sphilip 230227569Sphilip epp->ep_unicst = old_unicst; 231227569Sphilip epp->ep_brdcst = old_brdcst; 232227569Sphilip 233227569Sphilip return (rc); 234227569Sphilip} 235227569Sphilip 236227569Sphilip __checkReturn int 237227569Sphilipefx_mac_drain( 238227569Sphilip __in efx_nic_t *enp, 239227569Sphilip __in boolean_t enabled) 240227569Sphilip{ 241227569Sphilip efx_port_t *epp = &(enp->en_port); 242227569Sphilip efx_mac_ops_t *emop = epp->ep_emop; 243227569Sphilip int rc; 244227569Sphilip 245227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 246227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 247227569Sphilip EFSYS_ASSERT(emop != NULL); 248227569Sphilip 249227569Sphilip if (epp->ep_mac_drain == enabled) 250227569Sphilip return (0); 251227569Sphilip 252227569Sphilip epp->ep_mac_drain = enabled; 253227569Sphilip 254227569Sphilip if (enabled && emop->emo_reset != NULL) { 255227569Sphilip if ((rc = emop->emo_reset(enp)) != 0) 256227569Sphilip goto fail1; 257227569Sphilip 258227569Sphilip EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_MAC); 259227569Sphilip enp->en_reset_flags &= ~EFX_RESET_PHY; 260227569Sphilip } 261227569Sphilip 262227569Sphilip if ((rc = emop->emo_reconfigure(enp)) != 0) 263227569Sphilip goto fail2; 264227569Sphilip 265227569Sphilip return (0); 266227569Sphilip 267227569Sphilipfail2: 268227569Sphilip EFSYS_PROBE(fail2); 269227569Sphilipfail1: 270227569Sphilip EFSYS_PROBE1(fail1, int, rc); 271227569Sphilip 272227569Sphilip return (rc); 273227569Sphilip} 274227569Sphilip 275227569Sphilip __checkReturn int 276227569Sphilipefx_mac_up( 277227569Sphilip __in efx_nic_t *enp, 278227569Sphilip __out boolean_t *mac_upp) 279227569Sphilip{ 280227569Sphilip efx_port_t *epp = &(enp->en_port); 281227569Sphilip efx_mac_ops_t *emop = epp->ep_emop; 282227569Sphilip int rc; 283227569Sphilip 284227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 285227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 286227569Sphilip 287227569Sphilip if ((rc = emop->emo_up(enp, mac_upp)) != 0) 288227569Sphilip goto fail1; 289227569Sphilip 290227569Sphilip return (0); 291227569Sphilip 292227569Sphilipfail1: 293227569Sphilip EFSYS_PROBE1(fail1, int, rc); 294227569Sphilip 295227569Sphilip return (rc); 296227569Sphilip} 297227569Sphilip 298227569Sphilip __checkReturn int 299227569Sphilipefx_mac_fcntl_set( 300227569Sphilip __in efx_nic_t *enp, 301227569Sphilip __in unsigned int fcntl, 302227569Sphilip __in boolean_t autoneg) 303227569Sphilip{ 304227569Sphilip efx_port_t *epp = &(enp->en_port); 305227569Sphilip efx_mac_ops_t *emop = epp->ep_emop; 306227569Sphilip efx_phy_ops_t *epop = epp->ep_epop; 307227569Sphilip unsigned int old_fcntl; 308227569Sphilip boolean_t old_autoneg; 309227569Sphilip unsigned int old_adv_cap; 310227569Sphilip int rc; 311227569Sphilip 312227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 313227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 314227569Sphilip 315227569Sphilip if ((fcntl & ~(EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE)) != 0) { 316227569Sphilip rc = EINVAL; 317227569Sphilip goto fail1; 318227569Sphilip } 319227569Sphilip 320227569Sphilip /* 321227569Sphilip * Ignore a request to set flow control autonegotiation 322227569Sphilip * if the PHY doesn't support it. 323227569Sphilip */ 324227569Sphilip if (~epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN)) 325227569Sphilip autoneg = B_FALSE; 326227569Sphilip 327227569Sphilip old_fcntl = epp->ep_fcntl; 328227569Sphilip old_autoneg = autoneg; 329227569Sphilip old_adv_cap = epp->ep_adv_cap_mask; 330227569Sphilip 331227569Sphilip epp->ep_fcntl = fcntl; 332227569Sphilip epp->ep_fcntl_autoneg = autoneg; 333227569Sphilip 334227569Sphilip /* 335227569Sphilip * If the PHY supports autonegotiation, then encode the flow control 336227569Sphilip * settings in the advertised capabilities, and restart AN. Otherwise, 337227569Sphilip * just push the new settings directly to the MAC. 338227569Sphilip */ 339227569Sphilip if (epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN)) { 340227569Sphilip if (fcntl & EFX_FCNTL_RESPOND) 341227569Sphilip epp->ep_adv_cap_mask |= (1 << EFX_PHY_CAP_PAUSE | 342227569Sphilip 1 << EFX_PHY_CAP_ASYM); 343227569Sphilip else 344227569Sphilip epp->ep_adv_cap_mask &= ~(1 << EFX_PHY_CAP_PAUSE | 345227569Sphilip 1 << EFX_PHY_CAP_ASYM); 346227569Sphilip 347227569Sphilip if (fcntl & EFX_FCNTL_GENERATE) 348227569Sphilip epp->ep_adv_cap_mask ^= (1 << EFX_PHY_CAP_ASYM); 349227569Sphilip 350227569Sphilip if ((rc = epop->epo_reconfigure(enp)) != 0) 351227569Sphilip goto fail2; 352227569Sphilip 353227569Sphilip } else { 354227569Sphilip if ((rc = emop->emo_reconfigure(enp)) != 0) 355227569Sphilip goto fail2; 356227569Sphilip } 357227569Sphilip 358227569Sphilip return (0); 359227569Sphilip 360227569Sphilipfail2: 361227569Sphilip EFSYS_PROBE(fail2); 362227569Sphilip 363227569Sphilip epp->ep_fcntl = old_fcntl; 364227569Sphilip epp->ep_fcntl_autoneg = old_autoneg; 365227569Sphilip epp->ep_adv_cap_mask = old_adv_cap; 366227569Sphilip 367227569Sphilipfail1: 368227569Sphilip EFSYS_PROBE1(fail1, int, rc); 369227569Sphilip 370227569Sphilip return (rc); 371227569Sphilip} 372227569Sphilip 373227569Sphilip void 374227569Sphilipefx_mac_fcntl_get( 375227569Sphilip __in efx_nic_t *enp, 376227569Sphilip __out unsigned int *fcntl_wantedp, 377227569Sphilip __out unsigned int *fcntl_linkp) 378227569Sphilip{ 379227569Sphilip efx_port_t *epp = &(enp->en_port); 380227569Sphilip unsigned int wanted; 381227569Sphilip 382227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 383227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 384227569Sphilip 385227569Sphilip /* 386227569Sphilip * If the PHY supports auto negotiation, then the requested flow 387227569Sphilip * control settings are encoded in the advertised capabilities. 388227569Sphilip */ 389227569Sphilip if (epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN)) { 390227569Sphilip wanted = 0; 391227569Sphilip 392227569Sphilip if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_PAUSE)) 393227569Sphilip wanted = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE; 394227569Sphilip if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_ASYM)) 395227569Sphilip wanted ^= EFX_FCNTL_GENERATE; 396227569Sphilip } else 397227569Sphilip wanted = epp->ep_fcntl; 398227569Sphilip 399227569Sphilip *fcntl_linkp = epp->ep_fcntl; 400227569Sphilip *fcntl_wantedp = wanted; 401227569Sphilip} 402227569Sphilip 403227569Sphilip __checkReturn int 404227569Sphilipefx_mac_hash_set( 405227569Sphilip __in efx_nic_t *enp, 406227569Sphilip __in_ecount(EFX_MAC_HASH_BITS) unsigned int const *bucket) 407227569Sphilip{ 408227569Sphilip efx_port_t *epp = &(enp->en_port); 409227569Sphilip efx_mac_ops_t *emop = epp->ep_emop; 410227569Sphilip efx_oword_t old_hash[2]; 411227569Sphilip unsigned int index; 412227569Sphilip int rc; 413227569Sphilip 414227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 415227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 416227569Sphilip 417227569Sphilip memcpy(old_hash, epp->ep_multicst_hash, sizeof (old_hash)); 418227569Sphilip 419227569Sphilip /* Set the lower 128 bits of the hash */ 420227569Sphilip EFX_ZERO_OWORD(epp->ep_multicst_hash[0]); 421227569Sphilip for (index = 0; index < 128; index++) { 422227569Sphilip if (bucket[index] != 0) 423227569Sphilip EFX_SET_OWORD_BIT(epp->ep_multicst_hash[0], index); 424227569Sphilip } 425227569Sphilip 426227569Sphilip /* Set the upper 128 bits of the hash */ 427227569Sphilip EFX_ZERO_OWORD(epp->ep_multicst_hash[1]); 428227569Sphilip for (index = 0; index < 128; index++) { 429227569Sphilip if (bucket[index + 128] != 0) 430227569Sphilip EFX_SET_OWORD_BIT(epp->ep_multicst_hash[1], index); 431227569Sphilip } 432227569Sphilip 433227569Sphilip if ((rc = emop->emo_reconfigure(enp)) != 0) 434227569Sphilip goto fail1; 435227569Sphilip 436227569Sphilip return (0); 437227569Sphilip 438227569Sphilipfail1: 439227569Sphilip EFSYS_PROBE1(fail1, int, rc); 440227569Sphilip 441227569Sphilip memcpy(epp->ep_multicst_hash, old_hash, sizeof (old_hash)); 442227569Sphilip 443227569Sphilip return (rc); 444227569Sphilip} 445227569Sphilip 446227569Sphilip#if EFSYS_OPT_MAC_STATS 447227569Sphilip 448227569Sphilip#if EFSYS_OPT_NAMES 449227569Sphilip 450227569Sphilip/* START MKCONFIG GENERATED EfxMacStatNamesBlock adf707adba80813e */ 451227569Sphilipstatic const char __cs * __cs __efx_mac_stat_name[] = { 452227569Sphilip "rx_octets", 453227569Sphilip "rx_pkts", 454227569Sphilip "rx_unicst_pkts", 455227569Sphilip "rx_multicst_pkts", 456227569Sphilip "rx_brdcst_pkts", 457227569Sphilip "rx_pause_pkts", 458227569Sphilip "rx_le_64_pkts", 459227569Sphilip "rx_65_to_127_pkts", 460227569Sphilip "rx_128_to_255_pkts", 461227569Sphilip "rx_256_to_511_pkts", 462227569Sphilip "rx_512_to_1023_pkts", 463227569Sphilip "rx_1024_to_15xx_pkts", 464227569Sphilip "rx_ge_15xx_pkts", 465227569Sphilip "rx_errors", 466227569Sphilip "rx_fcs_errors", 467227569Sphilip "rx_drop_events", 468227569Sphilip "rx_false_carrier_errors", 469227569Sphilip "rx_symbol_errors", 470227569Sphilip "rx_align_errors", 471227569Sphilip "rx_internal_errors", 472227569Sphilip "rx_jabber_pkts", 473227569Sphilip "rx_lane0_char_err", 474227569Sphilip "rx_lane1_char_err", 475227569Sphilip "rx_lane2_char_err", 476227569Sphilip "rx_lane3_char_err", 477227569Sphilip "rx_lane0_disp_err", 478227569Sphilip "rx_lane1_disp_err", 479227569Sphilip "rx_lane2_disp_err", 480227569Sphilip "rx_lane3_disp_err", 481227569Sphilip "rx_match_fault", 482227569Sphilip "rx_nodesc_drop_cnt", 483227569Sphilip "tx_octets", 484227569Sphilip "tx_pkts", 485227569Sphilip "tx_unicst_pkts", 486227569Sphilip "tx_multicst_pkts", 487227569Sphilip "tx_brdcst_pkts", 488227569Sphilip "tx_pause_pkts", 489227569Sphilip "tx_le_64_pkts", 490227569Sphilip "tx_65_to_127_pkts", 491227569Sphilip "tx_128_to_255_pkts", 492227569Sphilip "tx_256_to_511_pkts", 493227569Sphilip "tx_512_to_1023_pkts", 494227569Sphilip "tx_1024_to_15xx_pkts", 495227569Sphilip "tx_ge_15xx_pkts", 496227569Sphilip "tx_errors", 497227569Sphilip "tx_sgl_col_pkts", 498227569Sphilip "tx_mult_col_pkts", 499227569Sphilip "tx_ex_col_pkts", 500227569Sphilip "tx_late_col_pkts", 501227569Sphilip "tx_def_pkts", 502227569Sphilip "tx_ex_def_pkts", 503227569Sphilip}; 504227569Sphilip/* END MKCONFIG GENERATED EfxMacStatNamesBlock */ 505227569Sphilip 506227569Sphilip __checkReturn const char __cs * 507227569Sphilipefx_mac_stat_name( 508227569Sphilip __in efx_nic_t *enp, 509227569Sphilip __in unsigned int id) 510227569Sphilip{ 511227569Sphilip _NOTE(ARGUNUSED(enp)) 512227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 513227569Sphilip 514227569Sphilip EFSYS_ASSERT3U(id, <, EFX_MAC_NSTATS); 515227569Sphilip return (__efx_mac_stat_name[id]); 516227569Sphilip} 517227569Sphilip 518227569Sphilip#endif /* EFSYS_OPT_STAT_NAME */ 519227569Sphilip 520227569Sphilip __checkReturn int 521227569Sphilipefx_mac_stats_upload( 522227569Sphilip __in efx_nic_t *enp, 523227569Sphilip __in efsys_mem_t *esmp) 524227569Sphilip{ 525227569Sphilip efx_port_t *epp = &(enp->en_port); 526227569Sphilip efx_mac_ops_t *emop = epp->ep_emop; 527227569Sphilip int rc; 528227569Sphilip 529227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 530227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 531227569Sphilip EFSYS_ASSERT(emop != NULL); 532227569Sphilip 533227569Sphilip /* 534227569Sphilip * Don't assert !ep_mac_stats_pending, because the client might 535227569Sphilip * have failed to finalise statistics when previously stopping 536227569Sphilip * the port. 537227569Sphilip */ 538227569Sphilip if ((rc = emop->emo_stats_upload(enp, esmp)) != 0) 539227569Sphilip goto fail1; 540227569Sphilip 541227569Sphilip epp->ep_mac_stats_pending = B_TRUE; 542227569Sphilip 543227569Sphilip return (0); 544227569Sphilip 545227569Sphilipfail1: 546227569Sphilip EFSYS_PROBE1(fail1, int, rc); 547227569Sphilip 548227569Sphilip return (rc); 549227569Sphilip} 550227569Sphilip 551227569Sphilip __checkReturn int 552227569Sphilipefx_mac_stats_periodic( 553227569Sphilip __in efx_nic_t *enp, 554227569Sphilip __in efsys_mem_t *esmp, 555227569Sphilip __in uint16_t period_ms, 556227569Sphilip __in boolean_t events) 557227569Sphilip{ 558227569Sphilip efx_port_t *epp = &(enp->en_port); 559227569Sphilip efx_mac_ops_t *emop = epp->ep_emop; 560227569Sphilip int rc; 561227569Sphilip 562227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 563227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 564227569Sphilip 565227569Sphilip EFSYS_ASSERT(emop != NULL); 566227569Sphilip 567227569Sphilip if (emop->emo_stats_periodic == NULL) { 568227569Sphilip rc = EINVAL; 569227569Sphilip goto fail1; 570227569Sphilip } 571227569Sphilip 572227569Sphilip if ((rc = emop->emo_stats_periodic(enp, esmp, period_ms, events)) != 0) 573227569Sphilip goto fail2; 574227569Sphilip 575227569Sphilip return (0); 576227569Sphilip 577227569Sphilipfail2: 578227569Sphilip EFSYS_PROBE(fail2); 579227569Sphilipfail1: 580227569Sphilip EFSYS_PROBE1(fail1, int, rc); 581227569Sphilip 582227569Sphilip return (rc); 583227569Sphilip} 584227569Sphilip 585227569Sphilip 586227569Sphilip __checkReturn int 587227569Sphilipefx_mac_stats_update( 588227569Sphilip __in efx_nic_t *enp, 589227569Sphilip __in efsys_mem_t *esmp, 590227569Sphilip __inout_ecount(EFX_MAC_NSTATS) efsys_stat_t *essp, 591227569Sphilip __in uint32_t *generationp) 592227569Sphilip{ 593227569Sphilip efx_port_t *epp = &(enp->en_port); 594227569Sphilip efx_mac_ops_t *emop = epp->ep_emop; 595227569Sphilip int rc; 596227569Sphilip 597227569Sphilip EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 598227569Sphilip EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 599227569Sphilip EFSYS_ASSERT(emop != NULL); 600227569Sphilip 601227569Sphilip rc = emop->emo_stats_update(enp, esmp, essp, generationp); 602227569Sphilip if (rc == 0) 603227569Sphilip epp->ep_mac_stats_pending = B_FALSE; 604227569Sphilip 605227569Sphilip return (rc); 606227569Sphilip} 607227569Sphilip 608227569Sphilip#endif /* EFSYS_OPT_MAC_STATS */ 609227569Sphilip 610227569Sphilip __checkReturn int 611227569Sphilipefx_mac_select( 612227569Sphilip __in efx_nic_t *enp) 613227569Sphilip{ 614227569Sphilip efx_port_t *epp = &(enp->en_port); 615227569Sphilip efx_mac_type_t type = EFX_MAC_INVALID; 616227569Sphilip efx_mac_ops_t *emop; 617227569Sphilip int rc = EINVAL; 618227569Sphilip 619227569Sphilip#if EFSYS_OPT_SIENA 620227569Sphilip if (enp->en_family == EFX_FAMILY_SIENA) { 621227569Sphilip type = EFX_MAC_SIENA; 622227569Sphilip goto chosen; 623227569Sphilip } 624227569Sphilip#endif 625227569Sphilip 626227569Sphilip#if EFSYS_OPT_FALCON 627227569Sphilip switch (epp->ep_link_mode) { 628227569Sphilip#if EFSYS_OPT_MAC_FALCON_GMAC 629227569Sphilip case EFX_LINK_100HDX: 630227569Sphilip case EFX_LINK_100FDX: 631227569Sphilip case EFX_LINK_1000HDX: 632227569Sphilip case EFX_LINK_1000FDX: 633227569Sphilip type = EFX_MAC_FALCON_GMAC; 634227569Sphilip goto chosen; 635227569Sphilip#endif /* EFSYS_OPT_FALCON_GMAC */ 636227569Sphilip 637227569Sphilip#if EFSYS_OPT_MAC_FALCON_XMAC 638227569Sphilip case EFX_LINK_10000FDX: 639227569Sphilip type = EFX_MAC_FALCON_XMAC; 640227569Sphilip goto chosen; 641227569Sphilip#endif /* EFSYS_OPT_FALCON_XMAC */ 642227569Sphilip 643227569Sphilip default: 644227569Sphilip#if EFSYS_OPT_MAC_FALCON_GMAC && EFSYS_OPT_MAC_FALCON_XMAC 645227569Sphilip /* Only initialise a MAC supported by the PHY */ 646227569Sphilip if (epp->ep_phy_cap_mask & 647227569Sphilip ((1 << EFX_PHY_CAP_1000FDX) | 648227569Sphilip (1 << EFX_PHY_CAP_1000HDX) | 649227569Sphilip (1 << EFX_PHY_CAP_100FDX) | 650227569Sphilip (1 << EFX_PHY_CAP_100HDX) | 651227569Sphilip (1 << EFX_PHY_CAP_10FDX) | 652227569Sphilip (1 << EFX_PHY_CAP_10FDX))) 653227569Sphilip type = EFX_MAC_FALCON_GMAC; 654227569Sphilip else 655227569Sphilip type = EFX_MAC_FALCON_XMAC; 656227569Sphilip#elif EFSYS_OPT_MAC_FALCON_GMAC 657227569Sphilip type = EFX_MAC_FALCON_GMAC; 658227569Sphilip#else 659227569Sphilip type = EFX_MAC_FALCON_XMAC; 660227569Sphilip#endif 661227569Sphilip goto chosen; 662227569Sphilip } 663227569Sphilip#endif /* EFSYS_OPT_FALCON */ 664227569Sphilip 665227569Sphilipchosen: 666227569Sphilip EFSYS_ASSERT(type != EFX_MAC_INVALID); 667227569Sphilip EFSYS_ASSERT3U(type, <, EFX_MAC_NTYPES); 668227569Sphilip emop = epp->ep_emop = (efx_mac_ops_t *)__efx_mac_ops[type]; 669227569Sphilip EFSYS_ASSERT(emop != NULL); 670227569Sphilip 671227569Sphilip epp->ep_mac_type = type; 672227569Sphilip 673227569Sphilip if (emop->emo_reset != NULL) { 674227569Sphilip if ((rc = emop->emo_reset(enp)) != 0) 675227569Sphilip goto fail1; 676227569Sphilip 677227569Sphilip EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_MAC); 678227569Sphilip enp->en_reset_flags &= ~EFX_RESET_MAC; 679227569Sphilip } 680227569Sphilip 681227569Sphilip return (0); 682227569Sphilip 683227569Sphilipfail1: 684227569Sphilip EFSYS_PROBE1(fail1, int, rc); 685227569Sphilip 686227569Sphilip return (rc); 687227569Sphilip} 688