1e948693eSPhilip Paeps /*- 2929c7febSAndrew Rybchenko * Copyright (c) 2007-2016 Solarflare Communications Inc. 33c838a9fSAndrew Rybchenko * All rights reserved. 4e948693eSPhilip Paeps * 5e948693eSPhilip Paeps * Redistribution and use in source and binary forms, with or without 63c838a9fSAndrew Rybchenko * modification, are permitted provided that the following conditions are met: 7e948693eSPhilip Paeps * 83c838a9fSAndrew Rybchenko * 1. Redistributions of source code must retain the above copyright notice, 93c838a9fSAndrew Rybchenko * this list of conditions and the following disclaimer. 103c838a9fSAndrew Rybchenko * 2. Redistributions in binary form must reproduce the above copyright notice, 113c838a9fSAndrew Rybchenko * this list of conditions and the following disclaimer in the documentation 123c838a9fSAndrew Rybchenko * and/or other materials provided with the distribution. 133c838a9fSAndrew Rybchenko * 143c838a9fSAndrew Rybchenko * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 153c838a9fSAndrew Rybchenko * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 163c838a9fSAndrew Rybchenko * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 173c838a9fSAndrew Rybchenko * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 183c838a9fSAndrew Rybchenko * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 193c838a9fSAndrew Rybchenko * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 203c838a9fSAndrew Rybchenko * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 213c838a9fSAndrew Rybchenko * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 223c838a9fSAndrew Rybchenko * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 233c838a9fSAndrew Rybchenko * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 243c838a9fSAndrew Rybchenko * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 253c838a9fSAndrew Rybchenko * 263c838a9fSAndrew Rybchenko * The views and conclusions contained in the software and documentation are 273c838a9fSAndrew Rybchenko * those of the authors and should not be interpreted as representing official 283c838a9fSAndrew Rybchenko * policies, either expressed or implied, of the FreeBSD Project. 29e948693eSPhilip Paeps */ 30e948693eSPhilip Paeps 315dee87d7SPhilip Paeps #include <sys/cdefs.h> 325dee87d7SPhilip Paeps __FBSDID("$FreeBSD$"); 335dee87d7SPhilip Paeps 34e948693eSPhilip Paeps #include "efx.h" 35e948693eSPhilip Paeps #include "efx_impl.h" 36e948693eSPhilip Paeps 37e75412c9SAndrew Rybchenko #if EFSYS_OPT_SIENA 383c838a9fSAndrew Rybchenko 39460cb568SAndrew Rybchenko static __checkReturn efx_rc_t 405cab4fc7SAndrew Rybchenko siena_mac_multicast_list_set( 413c838a9fSAndrew Rybchenko __in efx_nic_t *enp); 423c838a9fSAndrew Rybchenko 43e75412c9SAndrew Rybchenko #endif /* EFSYS_OPT_SIENA */ 443c838a9fSAndrew Rybchenko 45e948693eSPhilip Paeps #if EFSYS_OPT_SIENA 46ec831f7fSAndrew Rybchenko static const efx_mac_ops_t __efx_siena_mac_ops = { 47e948693eSPhilip Paeps siena_mac_poll, /* emo_poll */ 48e948693eSPhilip Paeps siena_mac_up, /* emo_up */ 493c838a9fSAndrew Rybchenko siena_mac_reconfigure, /* emo_addr_set */ 5008c5af79SAndrew Rybchenko siena_mac_reconfigure, /* emo_pdu_set */ 51d8484af2SAndrew Rybchenko siena_mac_pdu_get, /* emo_pdu_get */ 52e948693eSPhilip Paeps siena_mac_reconfigure, /* emo_reconfigure */ 535cab4fc7SAndrew Rybchenko siena_mac_multicast_list_set, /* emo_multicast_list_set */ 543c838a9fSAndrew Rybchenko NULL, /* emo_filter_set_default_rxq */ 553c838a9fSAndrew Rybchenko NULL, /* emo_filter_default_rxq_clear */ 56e948693eSPhilip Paeps #if EFSYS_OPT_LOOPBACK 57e948693eSPhilip Paeps siena_mac_loopback_set, /* emo_loopback_set */ 58e948693eSPhilip Paeps #endif /* EFSYS_OPT_LOOPBACK */ 59e948693eSPhilip Paeps #if EFSYS_OPT_MAC_STATS 603c838a9fSAndrew Rybchenko efx_mcdi_mac_stats_upload, /* emo_stats_upload */ 613c838a9fSAndrew Rybchenko efx_mcdi_mac_stats_periodic, /* emo_stats_periodic */ 62e948693eSPhilip Paeps siena_mac_stats_update /* emo_stats_update */ 63e948693eSPhilip Paeps #endif /* EFSYS_OPT_MAC_STATS */ 64e948693eSPhilip Paeps }; 65e948693eSPhilip Paeps #endif /* EFSYS_OPT_SIENA */ 66e948693eSPhilip Paeps 67c15d6d21SAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD 68ec831f7fSAndrew Rybchenko static const efx_mac_ops_t __efx_ef10_mac_ops = { 69c15d6d21SAndrew Rybchenko ef10_mac_poll, /* emo_poll */ 70c15d6d21SAndrew Rybchenko ef10_mac_up, /* emo_up */ 71c15d6d21SAndrew Rybchenko ef10_mac_addr_set, /* emo_addr_set */ 7208c5af79SAndrew Rybchenko ef10_mac_pdu_set, /* emo_pdu_set */ 73d8484af2SAndrew Rybchenko ef10_mac_pdu_get, /* emo_pdu_get */ 74c15d6d21SAndrew Rybchenko ef10_mac_reconfigure, /* emo_reconfigure */ 75c15d6d21SAndrew Rybchenko ef10_mac_multicast_list_set, /* emo_multicast_list_set */ 76c15d6d21SAndrew Rybchenko ef10_mac_filter_default_rxq_set, /* emo_filter_default_rxq_set */ 77c15d6d21SAndrew Rybchenko ef10_mac_filter_default_rxq_clear, 783c838a9fSAndrew Rybchenko /* emo_filter_default_rxq_clear */ 793c838a9fSAndrew Rybchenko #if EFSYS_OPT_LOOPBACK 80c15d6d21SAndrew Rybchenko ef10_mac_loopback_set, /* emo_loopback_set */ 813c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_LOOPBACK */ 823c838a9fSAndrew Rybchenko #if EFSYS_OPT_MAC_STATS 833c838a9fSAndrew Rybchenko efx_mcdi_mac_stats_upload, /* emo_stats_upload */ 843c838a9fSAndrew Rybchenko efx_mcdi_mac_stats_periodic, /* emo_stats_periodic */ 85c15d6d21SAndrew Rybchenko ef10_mac_stats_update /* emo_stats_update */ 863c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_MAC_STATS */ 873c838a9fSAndrew Rybchenko }; 88c15d6d21SAndrew Rybchenko #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */ 893c838a9fSAndrew Rybchenko 90460cb568SAndrew Rybchenko __checkReturn efx_rc_t 91e948693eSPhilip Paeps efx_mac_pdu_set( 92e948693eSPhilip Paeps __in efx_nic_t *enp, 93e948693eSPhilip Paeps __in size_t pdu) 94e948693eSPhilip Paeps { 95e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port); 96ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop; 97e948693eSPhilip Paeps uint32_t old_pdu; 98460cb568SAndrew Rybchenko efx_rc_t rc; 99e948693eSPhilip Paeps 100e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 101e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 102e948693eSPhilip Paeps EFSYS_ASSERT(emop != NULL); 103e948693eSPhilip Paeps 104e948693eSPhilip Paeps if (pdu < EFX_MAC_PDU_MIN) { 105e948693eSPhilip Paeps rc = EINVAL; 106e948693eSPhilip Paeps goto fail1; 107e948693eSPhilip Paeps } 108e948693eSPhilip Paeps 109e948693eSPhilip Paeps if (pdu > EFX_MAC_PDU_MAX) { 110e948693eSPhilip Paeps rc = EINVAL; 111e948693eSPhilip Paeps goto fail2; 112e948693eSPhilip Paeps } 113e948693eSPhilip Paeps 114e948693eSPhilip Paeps old_pdu = epp->ep_mac_pdu; 115e948693eSPhilip Paeps epp->ep_mac_pdu = (uint32_t)pdu; 11608c5af79SAndrew Rybchenko if ((rc = emop->emo_pdu_set(enp)) != 0) 117e948693eSPhilip Paeps goto fail3; 118e948693eSPhilip Paeps 119e948693eSPhilip Paeps return (0); 120e948693eSPhilip Paeps 121e948693eSPhilip Paeps fail3: 122e948693eSPhilip Paeps EFSYS_PROBE(fail3); 123e948693eSPhilip Paeps 124e948693eSPhilip Paeps epp->ep_mac_pdu = old_pdu; 125e948693eSPhilip Paeps 126e948693eSPhilip Paeps fail2: 127e948693eSPhilip Paeps EFSYS_PROBE(fail2); 128e948693eSPhilip Paeps fail1: 129460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 130e948693eSPhilip Paeps 131e948693eSPhilip Paeps return (rc); 132e948693eSPhilip Paeps } 133e948693eSPhilip Paeps 134460cb568SAndrew Rybchenko __checkReturn efx_rc_t 135d8484af2SAndrew Rybchenko efx_mac_pdu_get( 136d8484af2SAndrew Rybchenko __in efx_nic_t *enp, 137d8484af2SAndrew Rybchenko __out size_t *pdu) 138d8484af2SAndrew Rybchenko { 139d8484af2SAndrew Rybchenko efx_port_t *epp = &(enp->en_port); 140d8484af2SAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop; 141d8484af2SAndrew Rybchenko efx_rc_t rc; 142d8484af2SAndrew Rybchenko 143d8484af2SAndrew Rybchenko if ((rc = emop->emo_pdu_get(enp, pdu)) != 0) 144d8484af2SAndrew Rybchenko goto fail1; 145d8484af2SAndrew Rybchenko 146d8484af2SAndrew Rybchenko return (0); 147d8484af2SAndrew Rybchenko 148d8484af2SAndrew Rybchenko fail1: 149d8484af2SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 150d8484af2SAndrew Rybchenko 151d8484af2SAndrew Rybchenko return (rc); 152d8484af2SAndrew Rybchenko } 153d8484af2SAndrew Rybchenko 154d8484af2SAndrew Rybchenko __checkReturn efx_rc_t 155e948693eSPhilip Paeps efx_mac_addr_set( 156e948693eSPhilip Paeps __in efx_nic_t *enp, 157e948693eSPhilip Paeps __in uint8_t *addr) 158e948693eSPhilip Paeps { 159e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port); 160ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop; 161e948693eSPhilip Paeps uint8_t old_addr[6]; 162e948693eSPhilip Paeps uint32_t oui; 163460cb568SAndrew Rybchenko efx_rc_t rc; 164e948693eSPhilip Paeps 165e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 166e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 167e948693eSPhilip Paeps 1683c838a9fSAndrew Rybchenko if (EFX_MAC_ADDR_IS_MULTICAST(addr)) { 169e948693eSPhilip Paeps rc = EINVAL; 170e948693eSPhilip Paeps goto fail1; 171e948693eSPhilip Paeps } 172e948693eSPhilip Paeps 173e948693eSPhilip Paeps oui = addr[0] << 16 | addr[1] << 8 | addr[2]; 174e948693eSPhilip Paeps if (oui == 0x000000) { 175e948693eSPhilip Paeps rc = EINVAL; 176e948693eSPhilip Paeps goto fail2; 177e948693eSPhilip Paeps } 178e948693eSPhilip Paeps 179e948693eSPhilip Paeps EFX_MAC_ADDR_COPY(old_addr, epp->ep_mac_addr); 180e948693eSPhilip Paeps EFX_MAC_ADDR_COPY(epp->ep_mac_addr, addr); 1813c838a9fSAndrew Rybchenko if ((rc = emop->emo_addr_set(enp)) != 0) 182e948693eSPhilip Paeps goto fail3; 183e948693eSPhilip Paeps 184e948693eSPhilip Paeps return (0); 185e948693eSPhilip Paeps 186e948693eSPhilip Paeps fail3: 187e948693eSPhilip Paeps EFSYS_PROBE(fail3); 188e948693eSPhilip Paeps 189e948693eSPhilip Paeps EFX_MAC_ADDR_COPY(epp->ep_mac_addr, old_addr); 190e948693eSPhilip Paeps 191e948693eSPhilip Paeps fail2: 192e948693eSPhilip Paeps EFSYS_PROBE(fail2); 193e948693eSPhilip Paeps fail1: 194460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 195e948693eSPhilip Paeps 196e948693eSPhilip Paeps return (rc); 197e948693eSPhilip Paeps } 198e948693eSPhilip Paeps 199460cb568SAndrew Rybchenko __checkReturn efx_rc_t 200e948693eSPhilip Paeps efx_mac_filter_set( 201e948693eSPhilip Paeps __in efx_nic_t *enp, 2023c838a9fSAndrew Rybchenko __in boolean_t all_unicst, 2033c838a9fSAndrew Rybchenko __in boolean_t mulcst, 2043c838a9fSAndrew Rybchenko __in boolean_t all_mulcst, 205e948693eSPhilip Paeps __in boolean_t brdcst) 206e948693eSPhilip Paeps { 207e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port); 208ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop; 2093c838a9fSAndrew Rybchenko boolean_t old_all_unicst; 2103c838a9fSAndrew Rybchenko boolean_t old_mulcst; 2113c838a9fSAndrew Rybchenko boolean_t old_all_mulcst; 212e948693eSPhilip Paeps boolean_t old_brdcst; 213460cb568SAndrew Rybchenko efx_rc_t rc; 214e948693eSPhilip Paeps 215e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 216e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 217e948693eSPhilip Paeps 2183c838a9fSAndrew Rybchenko old_all_unicst = epp->ep_all_unicst; 2193c838a9fSAndrew Rybchenko old_mulcst = epp->ep_mulcst; 2203c838a9fSAndrew Rybchenko old_all_mulcst = epp->ep_all_mulcst; 2213c838a9fSAndrew Rybchenko old_brdcst = epp->ep_brdcst; 222e948693eSPhilip Paeps 2233c838a9fSAndrew Rybchenko epp->ep_all_unicst = all_unicst; 2243c838a9fSAndrew Rybchenko epp->ep_mulcst = mulcst; 2253c838a9fSAndrew Rybchenko epp->ep_all_mulcst = all_mulcst; 226e948693eSPhilip Paeps epp->ep_brdcst = brdcst; 227e948693eSPhilip Paeps 228e948693eSPhilip Paeps if ((rc = emop->emo_reconfigure(enp)) != 0) 229e948693eSPhilip Paeps goto fail1; 230e948693eSPhilip Paeps 231e948693eSPhilip Paeps return (0); 232e948693eSPhilip Paeps 233e948693eSPhilip Paeps fail1: 234460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 235e948693eSPhilip Paeps 2363c838a9fSAndrew Rybchenko epp->ep_all_unicst = old_all_unicst; 2373c838a9fSAndrew Rybchenko epp->ep_mulcst = old_mulcst; 2383c838a9fSAndrew Rybchenko epp->ep_all_mulcst = old_all_mulcst; 239e948693eSPhilip Paeps epp->ep_brdcst = old_brdcst; 240e948693eSPhilip Paeps 241e948693eSPhilip Paeps return (rc); 242e948693eSPhilip Paeps } 243e948693eSPhilip Paeps 244460cb568SAndrew Rybchenko __checkReturn efx_rc_t 245e948693eSPhilip Paeps efx_mac_drain( 246e948693eSPhilip Paeps __in efx_nic_t *enp, 247e948693eSPhilip Paeps __in boolean_t enabled) 248e948693eSPhilip Paeps { 249e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port); 250ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop; 251460cb568SAndrew Rybchenko efx_rc_t rc; 252e948693eSPhilip Paeps 253e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 254e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 255e948693eSPhilip Paeps EFSYS_ASSERT(emop != NULL); 256e948693eSPhilip Paeps 257e948693eSPhilip Paeps if (epp->ep_mac_drain == enabled) 258e948693eSPhilip Paeps return (0); 259e948693eSPhilip Paeps 260e948693eSPhilip Paeps epp->ep_mac_drain = enabled; 261e948693eSPhilip Paeps 262e948693eSPhilip Paeps if ((rc = emop->emo_reconfigure(enp)) != 0) 2630c909247SAndrew Rybchenko goto fail1; 264e948693eSPhilip Paeps 265e948693eSPhilip Paeps return (0); 266e948693eSPhilip Paeps 267e948693eSPhilip Paeps fail1: 268460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 269e948693eSPhilip Paeps 270e948693eSPhilip Paeps return (rc); 271e948693eSPhilip Paeps } 272e948693eSPhilip Paeps 273460cb568SAndrew Rybchenko __checkReturn efx_rc_t 274e948693eSPhilip Paeps efx_mac_up( 275e948693eSPhilip Paeps __in efx_nic_t *enp, 276e948693eSPhilip Paeps __out boolean_t *mac_upp) 277e948693eSPhilip Paeps { 278e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port); 279ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop; 280460cb568SAndrew Rybchenko efx_rc_t rc; 281e948693eSPhilip Paeps 282e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 283e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 284e948693eSPhilip Paeps 285e948693eSPhilip Paeps if ((rc = emop->emo_up(enp, mac_upp)) != 0) 286e948693eSPhilip Paeps goto fail1; 287e948693eSPhilip Paeps 288e948693eSPhilip Paeps return (0); 289e948693eSPhilip Paeps 290e948693eSPhilip Paeps fail1: 291460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 292e948693eSPhilip Paeps 293e948693eSPhilip Paeps return (rc); 294e948693eSPhilip Paeps } 295e948693eSPhilip Paeps 296460cb568SAndrew Rybchenko __checkReturn efx_rc_t 297e948693eSPhilip Paeps efx_mac_fcntl_set( 298e948693eSPhilip Paeps __in efx_nic_t *enp, 299e948693eSPhilip Paeps __in unsigned int fcntl, 300e948693eSPhilip Paeps __in boolean_t autoneg) 301e948693eSPhilip Paeps { 302e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port); 303ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop; 304ec831f7fSAndrew Rybchenko const efx_phy_ops_t *epop = epp->ep_epop; 305e948693eSPhilip Paeps unsigned int old_fcntl; 306e948693eSPhilip Paeps boolean_t old_autoneg; 307e948693eSPhilip Paeps unsigned int old_adv_cap; 308460cb568SAndrew Rybchenko efx_rc_t rc; 309e948693eSPhilip Paeps 310e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 311e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 312e948693eSPhilip Paeps 313e948693eSPhilip Paeps if ((fcntl & ~(EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE)) != 0) { 314e948693eSPhilip Paeps rc = EINVAL; 315e948693eSPhilip Paeps goto fail1; 316e948693eSPhilip Paeps } 317e948693eSPhilip Paeps 318e948693eSPhilip Paeps /* 3193c838a9fSAndrew Rybchenko * Ignore a request to set flow control auto-negotiation 320e948693eSPhilip Paeps * if the PHY doesn't support it. 321e948693eSPhilip Paeps */ 322e948693eSPhilip Paeps if (~epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN)) 323e948693eSPhilip Paeps autoneg = B_FALSE; 324e948693eSPhilip Paeps 325e948693eSPhilip Paeps old_fcntl = epp->ep_fcntl; 3263c838a9fSAndrew Rybchenko old_autoneg = epp->ep_fcntl_autoneg; 327e948693eSPhilip Paeps old_adv_cap = epp->ep_adv_cap_mask; 328e948693eSPhilip Paeps 329e948693eSPhilip Paeps epp->ep_fcntl = fcntl; 330e948693eSPhilip Paeps epp->ep_fcntl_autoneg = autoneg; 331e948693eSPhilip Paeps 332e948693eSPhilip Paeps /* 3333c838a9fSAndrew Rybchenko * Always encode the flow control settings in the advertised 3343c838a9fSAndrew Rybchenko * capabilities even if we are not trying to auto-negotiate 3353c838a9fSAndrew Rybchenko * them and reconfigure both the PHY and the MAC. 336e948693eSPhilip Paeps */ 337e948693eSPhilip Paeps if (fcntl & EFX_FCNTL_RESPOND) 338e948693eSPhilip Paeps epp->ep_adv_cap_mask |= (1 << EFX_PHY_CAP_PAUSE | 339e948693eSPhilip Paeps 1 << EFX_PHY_CAP_ASYM); 340e948693eSPhilip Paeps else 341e948693eSPhilip Paeps epp->ep_adv_cap_mask &= ~(1 << EFX_PHY_CAP_PAUSE | 342e948693eSPhilip Paeps 1 << EFX_PHY_CAP_ASYM); 343e948693eSPhilip Paeps 344e948693eSPhilip Paeps if (fcntl & EFX_FCNTL_GENERATE) 345e948693eSPhilip Paeps epp->ep_adv_cap_mask ^= (1 << EFX_PHY_CAP_ASYM); 346e948693eSPhilip Paeps 347e948693eSPhilip Paeps if ((rc = epop->epo_reconfigure(enp)) != 0) 348e948693eSPhilip Paeps goto fail2; 349e948693eSPhilip Paeps 350e948693eSPhilip Paeps if ((rc = emop->emo_reconfigure(enp)) != 0) 3513c838a9fSAndrew Rybchenko goto fail3; 352e948693eSPhilip Paeps 353e948693eSPhilip Paeps return (0); 354e948693eSPhilip Paeps 3553c838a9fSAndrew Rybchenko fail3: 3563c838a9fSAndrew Rybchenko EFSYS_PROBE(fail3); 3573c838a9fSAndrew Rybchenko 358e948693eSPhilip Paeps fail2: 359e948693eSPhilip Paeps EFSYS_PROBE(fail2); 360e948693eSPhilip Paeps 361e948693eSPhilip Paeps epp->ep_fcntl = old_fcntl; 362e948693eSPhilip Paeps epp->ep_fcntl_autoneg = old_autoneg; 363e948693eSPhilip Paeps epp->ep_adv_cap_mask = old_adv_cap; 364e948693eSPhilip Paeps 365e948693eSPhilip Paeps fail1: 366460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 367e948693eSPhilip Paeps 368e948693eSPhilip Paeps return (rc); 369e948693eSPhilip Paeps } 370e948693eSPhilip Paeps 371e948693eSPhilip Paeps void 372e948693eSPhilip Paeps efx_mac_fcntl_get( 373e948693eSPhilip Paeps __in efx_nic_t *enp, 374e948693eSPhilip Paeps __out unsigned int *fcntl_wantedp, 375e948693eSPhilip Paeps __out unsigned int *fcntl_linkp) 376e948693eSPhilip Paeps { 377e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port); 3783c838a9fSAndrew Rybchenko unsigned int wanted = 0; 379e948693eSPhilip Paeps 380e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 381e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 382e948693eSPhilip Paeps 383e948693eSPhilip Paeps /* 3843c838a9fSAndrew Rybchenko * Decode the requested flow control settings from the PHY 3853c838a9fSAndrew Rybchenko * advertised capabilities. 386e948693eSPhilip Paeps */ 387e948693eSPhilip Paeps if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_PAUSE)) 388e948693eSPhilip Paeps wanted = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE; 389e948693eSPhilip Paeps if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_ASYM)) 390e948693eSPhilip Paeps wanted ^= EFX_FCNTL_GENERATE; 391e948693eSPhilip Paeps 392e948693eSPhilip Paeps *fcntl_linkp = epp->ep_fcntl; 393e948693eSPhilip Paeps *fcntl_wantedp = wanted; 394e948693eSPhilip Paeps } 395e948693eSPhilip Paeps 396460cb568SAndrew Rybchenko __checkReturn efx_rc_t 3973c838a9fSAndrew Rybchenko efx_mac_multicast_list_set( 3983c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 3993c838a9fSAndrew Rybchenko __in_ecount(6*count) uint8_t const *addrs, 4003c838a9fSAndrew Rybchenko __in int count) 4013c838a9fSAndrew Rybchenko { 4023c838a9fSAndrew Rybchenko efx_port_t *epp = &(enp->en_port); 403ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop; 4043c838a9fSAndrew Rybchenko uint8_t *old_mulcst_addr_list = NULL; 4053c838a9fSAndrew Rybchenko uint32_t old_mulcst_addr_count; 406460cb568SAndrew Rybchenko efx_rc_t rc; 4073c838a9fSAndrew Rybchenko 4083c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 4093c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 4103c838a9fSAndrew Rybchenko 4113c838a9fSAndrew Rybchenko if (count > EFX_MAC_MULTICAST_LIST_MAX) { 4123c838a9fSAndrew Rybchenko rc = EINVAL; 4133c838a9fSAndrew Rybchenko goto fail1; 4143c838a9fSAndrew Rybchenko } 4153c838a9fSAndrew Rybchenko 4163c838a9fSAndrew Rybchenko old_mulcst_addr_count = epp->ep_mulcst_addr_count; 4173c838a9fSAndrew Rybchenko if (old_mulcst_addr_count > 0) { 4183c838a9fSAndrew Rybchenko /* Allocate memory to store old list (instead of using stack) */ 4193c838a9fSAndrew Rybchenko EFSYS_KMEM_ALLOC(enp->en_esip, 4203c838a9fSAndrew Rybchenko old_mulcst_addr_count * EFX_MAC_ADDR_LEN, 4213c838a9fSAndrew Rybchenko old_mulcst_addr_list); 4223c838a9fSAndrew Rybchenko if (old_mulcst_addr_list == NULL) { 4233c838a9fSAndrew Rybchenko rc = ENOMEM; 4243c838a9fSAndrew Rybchenko goto fail2; 4253c838a9fSAndrew Rybchenko } 4263c838a9fSAndrew Rybchenko 4273c838a9fSAndrew Rybchenko /* Save the old list in case we need to rollback */ 4283c838a9fSAndrew Rybchenko memcpy(old_mulcst_addr_list, epp->ep_mulcst_addr_list, 4293c838a9fSAndrew Rybchenko old_mulcst_addr_count * EFX_MAC_ADDR_LEN); 4303c838a9fSAndrew Rybchenko } 4313c838a9fSAndrew Rybchenko 4323c838a9fSAndrew Rybchenko /* Store the new list */ 4333c838a9fSAndrew Rybchenko memcpy(epp->ep_mulcst_addr_list, addrs, 4343c838a9fSAndrew Rybchenko count * EFX_MAC_ADDR_LEN); 4353c838a9fSAndrew Rybchenko epp->ep_mulcst_addr_count = count; 4363c838a9fSAndrew Rybchenko 4373c838a9fSAndrew Rybchenko if ((rc = emop->emo_multicast_list_set(enp)) != 0) 4383c838a9fSAndrew Rybchenko goto fail3; 4393c838a9fSAndrew Rybchenko 4403c838a9fSAndrew Rybchenko if (old_mulcst_addr_count > 0) { 4413c838a9fSAndrew Rybchenko EFSYS_KMEM_FREE(enp->en_esip, 4423c838a9fSAndrew Rybchenko old_mulcst_addr_count * EFX_MAC_ADDR_LEN, 4433c838a9fSAndrew Rybchenko old_mulcst_addr_list); 4443c838a9fSAndrew Rybchenko } 4453c838a9fSAndrew Rybchenko 4463c838a9fSAndrew Rybchenko return (0); 4473c838a9fSAndrew Rybchenko 4483c838a9fSAndrew Rybchenko fail3: 4493c838a9fSAndrew Rybchenko EFSYS_PROBE(fail3); 4503c838a9fSAndrew Rybchenko 4513c838a9fSAndrew Rybchenko /* Restore original list on failure */ 4523c838a9fSAndrew Rybchenko epp->ep_mulcst_addr_count = old_mulcst_addr_count; 4533c838a9fSAndrew Rybchenko if (old_mulcst_addr_count > 0) { 4543c838a9fSAndrew Rybchenko memcpy(epp->ep_mulcst_addr_list, old_mulcst_addr_list, 4553c838a9fSAndrew Rybchenko old_mulcst_addr_count * EFX_MAC_ADDR_LEN); 4563c838a9fSAndrew Rybchenko 4573c838a9fSAndrew Rybchenko EFSYS_KMEM_FREE(enp->en_esip, 4583c838a9fSAndrew Rybchenko old_mulcst_addr_count * EFX_MAC_ADDR_LEN, 4593c838a9fSAndrew Rybchenko old_mulcst_addr_list); 4603c838a9fSAndrew Rybchenko } 4613c838a9fSAndrew Rybchenko 4623c838a9fSAndrew Rybchenko fail2: 4633c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2); 4643c838a9fSAndrew Rybchenko 4653c838a9fSAndrew Rybchenko fail1: 466460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 4673c838a9fSAndrew Rybchenko 4683c838a9fSAndrew Rybchenko return (rc); 4693c838a9fSAndrew Rybchenko 4703c838a9fSAndrew Rybchenko } 4713c838a9fSAndrew Rybchenko 472460cb568SAndrew Rybchenko __checkReturn efx_rc_t 4733c838a9fSAndrew Rybchenko efx_mac_filter_default_rxq_set( 4743c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 4753c838a9fSAndrew Rybchenko __in efx_rxq_t *erp, 4763c838a9fSAndrew Rybchenko __in boolean_t using_rss) 4773c838a9fSAndrew Rybchenko { 4783c838a9fSAndrew Rybchenko efx_port_t *epp = &(enp->en_port); 479ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop; 480460cb568SAndrew Rybchenko efx_rc_t rc; 4813c838a9fSAndrew Rybchenko 4823c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 4833c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 4843c838a9fSAndrew Rybchenko 4853c838a9fSAndrew Rybchenko if (emop->emo_filter_default_rxq_set != NULL) { 4863c838a9fSAndrew Rybchenko rc = emop->emo_filter_default_rxq_set(enp, erp, using_rss); 4873c838a9fSAndrew Rybchenko if (rc != 0) 4883c838a9fSAndrew Rybchenko goto fail1; 4893c838a9fSAndrew Rybchenko } 4903c838a9fSAndrew Rybchenko 4913c838a9fSAndrew Rybchenko return (0); 4923c838a9fSAndrew Rybchenko 4933c838a9fSAndrew Rybchenko fail1: 494460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 4953c838a9fSAndrew Rybchenko 4963c838a9fSAndrew Rybchenko return (rc); 4973c838a9fSAndrew Rybchenko } 4983c838a9fSAndrew Rybchenko 4993c838a9fSAndrew Rybchenko void 5003c838a9fSAndrew Rybchenko efx_mac_filter_default_rxq_clear( 5013c838a9fSAndrew Rybchenko __in efx_nic_t *enp) 5023c838a9fSAndrew Rybchenko { 5033c838a9fSAndrew Rybchenko efx_port_t *epp = &(enp->en_port); 504ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop; 5053c838a9fSAndrew Rybchenko 5063c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 5073c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 5083c838a9fSAndrew Rybchenko 5093c838a9fSAndrew Rybchenko if (emop->emo_filter_default_rxq_clear != NULL) 5103c838a9fSAndrew Rybchenko emop->emo_filter_default_rxq_clear(enp); 5113c838a9fSAndrew Rybchenko } 5123c838a9fSAndrew Rybchenko 5133c838a9fSAndrew Rybchenko 514e948693eSPhilip Paeps #if EFSYS_OPT_MAC_STATS 515e948693eSPhilip Paeps 516e948693eSPhilip Paeps #if EFSYS_OPT_NAMES 517e948693eSPhilip Paeps 5183c838a9fSAndrew Rybchenko /* START MKCONFIG GENERATED EfxMacStatNamesBlock 054d43a31d2d7a45 */ 5193c838a9fSAndrew Rybchenko static const char *__efx_mac_stat_name[] = { 520e948693eSPhilip Paeps "rx_octets", 521e948693eSPhilip Paeps "rx_pkts", 522e948693eSPhilip Paeps "rx_unicst_pkts", 523e948693eSPhilip Paeps "rx_multicst_pkts", 524e948693eSPhilip Paeps "rx_brdcst_pkts", 525e948693eSPhilip Paeps "rx_pause_pkts", 526e948693eSPhilip Paeps "rx_le_64_pkts", 527e948693eSPhilip Paeps "rx_65_to_127_pkts", 528e948693eSPhilip Paeps "rx_128_to_255_pkts", 529e948693eSPhilip Paeps "rx_256_to_511_pkts", 530e948693eSPhilip Paeps "rx_512_to_1023_pkts", 531e948693eSPhilip Paeps "rx_1024_to_15xx_pkts", 532e948693eSPhilip Paeps "rx_ge_15xx_pkts", 533e948693eSPhilip Paeps "rx_errors", 534e948693eSPhilip Paeps "rx_fcs_errors", 535e948693eSPhilip Paeps "rx_drop_events", 536e948693eSPhilip Paeps "rx_false_carrier_errors", 537e948693eSPhilip Paeps "rx_symbol_errors", 538e948693eSPhilip Paeps "rx_align_errors", 539e948693eSPhilip Paeps "rx_internal_errors", 540e948693eSPhilip Paeps "rx_jabber_pkts", 541e948693eSPhilip Paeps "rx_lane0_char_err", 542e948693eSPhilip Paeps "rx_lane1_char_err", 543e948693eSPhilip Paeps "rx_lane2_char_err", 544e948693eSPhilip Paeps "rx_lane3_char_err", 545e948693eSPhilip Paeps "rx_lane0_disp_err", 546e948693eSPhilip Paeps "rx_lane1_disp_err", 547e948693eSPhilip Paeps "rx_lane2_disp_err", 548e948693eSPhilip Paeps "rx_lane3_disp_err", 549e948693eSPhilip Paeps "rx_match_fault", 550e948693eSPhilip Paeps "rx_nodesc_drop_cnt", 551e948693eSPhilip Paeps "tx_octets", 552e948693eSPhilip Paeps "tx_pkts", 553e948693eSPhilip Paeps "tx_unicst_pkts", 554e948693eSPhilip Paeps "tx_multicst_pkts", 555e948693eSPhilip Paeps "tx_brdcst_pkts", 556e948693eSPhilip Paeps "tx_pause_pkts", 557e948693eSPhilip Paeps "tx_le_64_pkts", 558e948693eSPhilip Paeps "tx_65_to_127_pkts", 559e948693eSPhilip Paeps "tx_128_to_255_pkts", 560e948693eSPhilip Paeps "tx_256_to_511_pkts", 561e948693eSPhilip Paeps "tx_512_to_1023_pkts", 562e948693eSPhilip Paeps "tx_1024_to_15xx_pkts", 563e948693eSPhilip Paeps "tx_ge_15xx_pkts", 564e948693eSPhilip Paeps "tx_errors", 565e948693eSPhilip Paeps "tx_sgl_col_pkts", 566e948693eSPhilip Paeps "tx_mult_col_pkts", 567e948693eSPhilip Paeps "tx_ex_col_pkts", 568e948693eSPhilip Paeps "tx_late_col_pkts", 569e948693eSPhilip Paeps "tx_def_pkts", 570e948693eSPhilip Paeps "tx_ex_def_pkts", 5713c838a9fSAndrew Rybchenko "pm_trunc_bb_overflow", 5723c838a9fSAndrew Rybchenko "pm_discard_bb_overflow", 5733c838a9fSAndrew Rybchenko "pm_trunc_vfifo_full", 5743c838a9fSAndrew Rybchenko "pm_discard_vfifo_full", 5753c838a9fSAndrew Rybchenko "pm_trunc_qbb", 5763c838a9fSAndrew Rybchenko "pm_discard_qbb", 5773c838a9fSAndrew Rybchenko "pm_discard_mapping", 5783c838a9fSAndrew Rybchenko "rxdp_q_disabled_pkts", 5793c838a9fSAndrew Rybchenko "rxdp_di_dropped_pkts", 5803c838a9fSAndrew Rybchenko "rxdp_streaming_pkts", 5813c838a9fSAndrew Rybchenko "rxdp_hlb_fetch", 5823c838a9fSAndrew Rybchenko "rxdp_hlb_wait", 5833c838a9fSAndrew Rybchenko "vadapter_rx_unicast_packets", 5843c838a9fSAndrew Rybchenko "vadapter_rx_unicast_bytes", 5853c838a9fSAndrew Rybchenko "vadapter_rx_multicast_packets", 5863c838a9fSAndrew Rybchenko "vadapter_rx_multicast_bytes", 5873c838a9fSAndrew Rybchenko "vadapter_rx_broadcast_packets", 5883c838a9fSAndrew Rybchenko "vadapter_rx_broadcast_bytes", 5893c838a9fSAndrew Rybchenko "vadapter_rx_bad_packets", 5903c838a9fSAndrew Rybchenko "vadapter_rx_bad_bytes", 5913c838a9fSAndrew Rybchenko "vadapter_rx_overflow", 5923c838a9fSAndrew Rybchenko "vadapter_tx_unicast_packets", 5933c838a9fSAndrew Rybchenko "vadapter_tx_unicast_bytes", 5943c838a9fSAndrew Rybchenko "vadapter_tx_multicast_packets", 5953c838a9fSAndrew Rybchenko "vadapter_tx_multicast_bytes", 5963c838a9fSAndrew Rybchenko "vadapter_tx_broadcast_packets", 5973c838a9fSAndrew Rybchenko "vadapter_tx_broadcast_bytes", 5983c838a9fSAndrew Rybchenko "vadapter_tx_bad_packets", 5993c838a9fSAndrew Rybchenko "vadapter_tx_bad_bytes", 6003c838a9fSAndrew Rybchenko "vadapter_tx_overflow", 601e948693eSPhilip Paeps }; 602e948693eSPhilip Paeps /* END MKCONFIG GENERATED EfxMacStatNamesBlock */ 603e948693eSPhilip Paeps 6043c838a9fSAndrew Rybchenko __checkReturn const char * 605e948693eSPhilip Paeps efx_mac_stat_name( 606e948693eSPhilip Paeps __in efx_nic_t *enp, 607e948693eSPhilip Paeps __in unsigned int id) 608e948693eSPhilip Paeps { 609e948693eSPhilip Paeps _NOTE(ARGUNUSED(enp)) 610e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 611e948693eSPhilip Paeps 612e948693eSPhilip Paeps EFSYS_ASSERT3U(id, <, EFX_MAC_NSTATS); 613e948693eSPhilip Paeps return (__efx_mac_stat_name[id]); 614e948693eSPhilip Paeps } 615e948693eSPhilip Paeps 6163c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_NAMES */ 617e948693eSPhilip Paeps 618460cb568SAndrew Rybchenko __checkReturn efx_rc_t 619e948693eSPhilip Paeps efx_mac_stats_upload( 620e948693eSPhilip Paeps __in efx_nic_t *enp, 621e948693eSPhilip Paeps __in efsys_mem_t *esmp) 622e948693eSPhilip Paeps { 623e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port); 624ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop; 625460cb568SAndrew Rybchenko efx_rc_t rc; 626e948693eSPhilip Paeps 627e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 628e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 629e948693eSPhilip Paeps EFSYS_ASSERT(emop != NULL); 630e948693eSPhilip Paeps 631e948693eSPhilip Paeps /* 632e948693eSPhilip Paeps * Don't assert !ep_mac_stats_pending, because the client might 633e948693eSPhilip Paeps * have failed to finalise statistics when previously stopping 634e948693eSPhilip Paeps * the port. 635e948693eSPhilip Paeps */ 636e948693eSPhilip Paeps if ((rc = emop->emo_stats_upload(enp, esmp)) != 0) 637e948693eSPhilip Paeps goto fail1; 638e948693eSPhilip Paeps 639e948693eSPhilip Paeps epp->ep_mac_stats_pending = B_TRUE; 640e948693eSPhilip Paeps 641e948693eSPhilip Paeps return (0); 642e948693eSPhilip Paeps 643e948693eSPhilip Paeps fail1: 644460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 645e948693eSPhilip Paeps 646e948693eSPhilip Paeps return (rc); 647e948693eSPhilip Paeps } 648e948693eSPhilip Paeps 649460cb568SAndrew Rybchenko __checkReturn efx_rc_t 650e948693eSPhilip Paeps efx_mac_stats_periodic( 651e948693eSPhilip Paeps __in efx_nic_t *enp, 652e948693eSPhilip Paeps __in efsys_mem_t *esmp, 653e948693eSPhilip Paeps __in uint16_t period_ms, 654e948693eSPhilip Paeps __in boolean_t events) 655e948693eSPhilip Paeps { 656e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port); 657ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop; 658460cb568SAndrew Rybchenko efx_rc_t rc; 659e948693eSPhilip Paeps 660e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 661e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 662e948693eSPhilip Paeps 663e948693eSPhilip Paeps EFSYS_ASSERT(emop != NULL); 664e948693eSPhilip Paeps 665e948693eSPhilip Paeps if (emop->emo_stats_periodic == NULL) { 666e948693eSPhilip Paeps rc = EINVAL; 667e948693eSPhilip Paeps goto fail1; 668e948693eSPhilip Paeps } 669e948693eSPhilip Paeps 670e948693eSPhilip Paeps if ((rc = emop->emo_stats_periodic(enp, esmp, period_ms, events)) != 0) 671e948693eSPhilip Paeps goto fail2; 672e948693eSPhilip Paeps 673e948693eSPhilip Paeps return (0); 674e948693eSPhilip Paeps 675e948693eSPhilip Paeps fail2: 676e948693eSPhilip Paeps EFSYS_PROBE(fail2); 677e948693eSPhilip Paeps fail1: 678460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 679e948693eSPhilip Paeps 680e948693eSPhilip Paeps return (rc); 681e948693eSPhilip Paeps } 682e948693eSPhilip Paeps 683e948693eSPhilip Paeps 684460cb568SAndrew Rybchenko __checkReturn efx_rc_t 685e948693eSPhilip Paeps efx_mac_stats_update( 686e948693eSPhilip Paeps __in efx_nic_t *enp, 687e948693eSPhilip Paeps __in efsys_mem_t *esmp, 688e948693eSPhilip Paeps __inout_ecount(EFX_MAC_NSTATS) efsys_stat_t *essp, 68914c3e490SAndrew Rybchenko __inout_opt uint32_t *generationp) 690e948693eSPhilip Paeps { 691e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port); 692ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop; 693460cb568SAndrew Rybchenko efx_rc_t rc; 694e948693eSPhilip Paeps 695e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 696e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 697e948693eSPhilip Paeps EFSYS_ASSERT(emop != NULL); 698e948693eSPhilip Paeps 699e948693eSPhilip Paeps rc = emop->emo_stats_update(enp, esmp, essp, generationp); 700e948693eSPhilip Paeps if (rc == 0) 701e948693eSPhilip Paeps epp->ep_mac_stats_pending = B_FALSE; 702e948693eSPhilip Paeps 703e948693eSPhilip Paeps return (rc); 704e948693eSPhilip Paeps } 705e948693eSPhilip Paeps 706e948693eSPhilip Paeps #endif /* EFSYS_OPT_MAC_STATS */ 707e948693eSPhilip Paeps 708460cb568SAndrew Rybchenko __checkReturn efx_rc_t 709e948693eSPhilip Paeps efx_mac_select( 710e948693eSPhilip Paeps __in efx_nic_t *enp) 711e948693eSPhilip Paeps { 712e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port); 713e948693eSPhilip Paeps efx_mac_type_t type = EFX_MAC_INVALID; 714ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop; 715e948693eSPhilip Paeps int rc = EINVAL; 716e948693eSPhilip Paeps 71795812f27SAndrew Rybchenko switch (enp->en_family) { 718c15d6d21SAndrew Rybchenko #if EFSYS_OPT_SIENA 71995812f27SAndrew Rybchenko case EFX_FAMILY_SIENA: 72095812f27SAndrew Rybchenko emop = &__efx_siena_mac_ops; 721c15d6d21SAndrew Rybchenko type = EFX_MAC_SIENA; 72295812f27SAndrew Rybchenko break; 72395812f27SAndrew Rybchenko #endif /* EFSYS_OPT_SIENA */ 724c15d6d21SAndrew Rybchenko 7253c838a9fSAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON 72695812f27SAndrew Rybchenko case EFX_FAMILY_HUNTINGTON: 72795812f27SAndrew Rybchenko emop = &__efx_ef10_mac_ops; 7283c838a9fSAndrew Rybchenko type = EFX_MAC_HUNTINGTON; 72995812f27SAndrew Rybchenko break; 73095812f27SAndrew Rybchenko #endif /* EFSYS_OPT_HUNTINGTON */ 7313c838a9fSAndrew Rybchenko 732c15d6d21SAndrew Rybchenko #if EFSYS_OPT_MEDFORD 73395812f27SAndrew Rybchenko case EFX_FAMILY_MEDFORD: 73495812f27SAndrew Rybchenko emop = &__efx_ef10_mac_ops; 735c15d6d21SAndrew Rybchenko type = EFX_MAC_MEDFORD; 73695812f27SAndrew Rybchenko break; 73795812f27SAndrew Rybchenko #endif /* EFSYS_OPT_MEDFORD */ 738e948693eSPhilip Paeps 73995812f27SAndrew Rybchenko default: 74095812f27SAndrew Rybchenko rc = EINVAL; 74195812f27SAndrew Rybchenko goto fail1; 74295812f27SAndrew Rybchenko } 74395812f27SAndrew Rybchenko 744e948693eSPhilip Paeps EFSYS_ASSERT(type != EFX_MAC_INVALID); 745e948693eSPhilip Paeps EFSYS_ASSERT3U(type, <, EFX_MAC_NTYPES); 746e948693eSPhilip Paeps EFSYS_ASSERT(emop != NULL); 747e948693eSPhilip Paeps 74895812f27SAndrew Rybchenko epp->ep_emop = emop; 749e948693eSPhilip Paeps epp->ep_mac_type = type; 750e948693eSPhilip Paeps 751e948693eSPhilip Paeps return (0); 752e948693eSPhilip Paeps 753e948693eSPhilip Paeps fail1: 754460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 755e948693eSPhilip Paeps 756e948693eSPhilip Paeps return (rc); 757e948693eSPhilip Paeps } 7583c838a9fSAndrew Rybchenko 7593c838a9fSAndrew Rybchenko 760e75412c9SAndrew Rybchenko #if EFSYS_OPT_SIENA 7613c838a9fSAndrew Rybchenko 76274bb0ed8SAndrew Rybchenko #define EFX_MAC_HASH_BITS (1 << 8) 76374bb0ed8SAndrew Rybchenko 7643c838a9fSAndrew Rybchenko /* Compute the multicast hash as used on Falcon and Siena. */ 7653c838a9fSAndrew Rybchenko static void 7665cab4fc7SAndrew Rybchenko siena_mac_multicast_hash_compute( 7673c838a9fSAndrew Rybchenko __in_ecount(6*count) uint8_t const *addrs, 7683c838a9fSAndrew Rybchenko __in int count, 7693c838a9fSAndrew Rybchenko __out efx_oword_t *hash_low, 7703c838a9fSAndrew Rybchenko __out efx_oword_t *hash_high) 7713c838a9fSAndrew Rybchenko { 7723c838a9fSAndrew Rybchenko uint32_t crc, index; 7733c838a9fSAndrew Rybchenko int i; 7743c838a9fSAndrew Rybchenko 7753c838a9fSAndrew Rybchenko EFSYS_ASSERT(hash_low != NULL); 7763c838a9fSAndrew Rybchenko EFSYS_ASSERT(hash_high != NULL); 7773c838a9fSAndrew Rybchenko 7783c838a9fSAndrew Rybchenko EFX_ZERO_OWORD(*hash_low); 7793c838a9fSAndrew Rybchenko EFX_ZERO_OWORD(*hash_high); 7803c838a9fSAndrew Rybchenko 7813c838a9fSAndrew Rybchenko for (i = 0; i < count; i++) { 7823c838a9fSAndrew Rybchenko /* Calculate hash bucket (IEEE 802.3 CRC32 of the MAC addr) */ 7833c838a9fSAndrew Rybchenko crc = efx_crc32_calculate(0xffffffff, addrs, EFX_MAC_ADDR_LEN); 7843c838a9fSAndrew Rybchenko index = crc % EFX_MAC_HASH_BITS; 7853c838a9fSAndrew Rybchenko if (index < 128) { 7863c838a9fSAndrew Rybchenko EFX_SET_OWORD_BIT(*hash_low, index); 7873c838a9fSAndrew Rybchenko } else { 7883c838a9fSAndrew Rybchenko EFX_SET_OWORD_BIT(*hash_high, index - 128); 7893c838a9fSAndrew Rybchenko } 7903c838a9fSAndrew Rybchenko 7913c838a9fSAndrew Rybchenko addrs += EFX_MAC_ADDR_LEN; 7923c838a9fSAndrew Rybchenko } 7933c838a9fSAndrew Rybchenko } 7943c838a9fSAndrew Rybchenko 795460cb568SAndrew Rybchenko static __checkReturn efx_rc_t 7965cab4fc7SAndrew Rybchenko siena_mac_multicast_list_set( 7973c838a9fSAndrew Rybchenko __in efx_nic_t *enp) 7983c838a9fSAndrew Rybchenko { 7993c838a9fSAndrew Rybchenko efx_port_t *epp = &(enp->en_port); 800ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop; 8013c838a9fSAndrew Rybchenko efx_oword_t old_hash[2]; 802460cb568SAndrew Rybchenko efx_rc_t rc; 8033c838a9fSAndrew Rybchenko 8043c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 8053c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 8063c838a9fSAndrew Rybchenko 8073c838a9fSAndrew Rybchenko memcpy(old_hash, epp->ep_multicst_hash, sizeof (old_hash)); 8083c838a9fSAndrew Rybchenko 8095cab4fc7SAndrew Rybchenko siena_mac_multicast_hash_compute( 8105cab4fc7SAndrew Rybchenko epp->ep_mulcst_addr_list, 8113c838a9fSAndrew Rybchenko epp->ep_mulcst_addr_count, 8123c838a9fSAndrew Rybchenko &epp->ep_multicst_hash[0], 8133c838a9fSAndrew Rybchenko &epp->ep_multicst_hash[1]); 8143c838a9fSAndrew Rybchenko 8153c838a9fSAndrew Rybchenko if ((rc = emop->emo_reconfigure(enp)) != 0) 8163c838a9fSAndrew Rybchenko goto fail1; 8173c838a9fSAndrew Rybchenko 8183c838a9fSAndrew Rybchenko return (0); 8193c838a9fSAndrew Rybchenko 8203c838a9fSAndrew Rybchenko fail1: 821460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 8223c838a9fSAndrew Rybchenko 8233c838a9fSAndrew Rybchenko memcpy(epp->ep_multicst_hash, old_hash, sizeof (old_hash)); 8243c838a9fSAndrew Rybchenko 8253c838a9fSAndrew Rybchenko return (rc); 8263c838a9fSAndrew Rybchenko } 8273c838a9fSAndrew Rybchenko 828e75412c9SAndrew Rybchenko #endif /* EFSYS_OPT_SIENA */ 829