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 6058a72cb2SAndrew Rybchenko siena_mac_stats_get_mask, /* emo_stats_get_mask */ 613c838a9fSAndrew Rybchenko efx_mcdi_mac_stats_upload, /* emo_stats_upload */ 623c838a9fSAndrew Rybchenko efx_mcdi_mac_stats_periodic, /* emo_stats_periodic */ 63e948693eSPhilip Paeps siena_mac_stats_update /* emo_stats_update */ 64e948693eSPhilip Paeps #endif /* EFSYS_OPT_MAC_STATS */ 65e948693eSPhilip Paeps }; 66e948693eSPhilip Paeps #endif /* EFSYS_OPT_SIENA */ 67e948693eSPhilip Paeps 68c15d6d21SAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD 69ec831f7fSAndrew Rybchenko static const efx_mac_ops_t __efx_ef10_mac_ops = { 70c15d6d21SAndrew Rybchenko ef10_mac_poll, /* emo_poll */ 71c15d6d21SAndrew Rybchenko ef10_mac_up, /* emo_up */ 72c15d6d21SAndrew Rybchenko ef10_mac_addr_set, /* emo_addr_set */ 7308c5af79SAndrew Rybchenko ef10_mac_pdu_set, /* emo_pdu_set */ 74d8484af2SAndrew Rybchenko ef10_mac_pdu_get, /* emo_pdu_get */ 75c15d6d21SAndrew Rybchenko ef10_mac_reconfigure, /* emo_reconfigure */ 76c15d6d21SAndrew Rybchenko ef10_mac_multicast_list_set, /* emo_multicast_list_set */ 77c15d6d21SAndrew Rybchenko ef10_mac_filter_default_rxq_set, /* emo_filter_default_rxq_set */ 78c15d6d21SAndrew Rybchenko ef10_mac_filter_default_rxq_clear, 793c838a9fSAndrew Rybchenko /* emo_filter_default_rxq_clear */ 803c838a9fSAndrew Rybchenko #if EFSYS_OPT_LOOPBACK 81c15d6d21SAndrew Rybchenko ef10_mac_loopback_set, /* emo_loopback_set */ 823c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_LOOPBACK */ 833c838a9fSAndrew Rybchenko #if EFSYS_OPT_MAC_STATS 8458a72cb2SAndrew Rybchenko ef10_mac_stats_get_mask, /* emo_stats_get_mask */ 853c838a9fSAndrew Rybchenko efx_mcdi_mac_stats_upload, /* emo_stats_upload */ 863c838a9fSAndrew Rybchenko efx_mcdi_mac_stats_periodic, /* emo_stats_periodic */ 87c15d6d21SAndrew Rybchenko ef10_mac_stats_update /* emo_stats_update */ 883c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_MAC_STATS */ 893c838a9fSAndrew Rybchenko }; 90c15d6d21SAndrew Rybchenko #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */ 913c838a9fSAndrew Rybchenko 92460cb568SAndrew Rybchenko __checkReturn efx_rc_t 93e948693eSPhilip Paeps efx_mac_pdu_set( 94e948693eSPhilip Paeps __in efx_nic_t *enp, 95e948693eSPhilip Paeps __in size_t pdu) 96e948693eSPhilip Paeps { 97e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port); 98ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop; 99e948693eSPhilip Paeps uint32_t old_pdu; 100460cb568SAndrew Rybchenko efx_rc_t rc; 101e948693eSPhilip Paeps 102e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 103e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 104e948693eSPhilip Paeps EFSYS_ASSERT(emop != NULL); 105e948693eSPhilip Paeps 106e948693eSPhilip Paeps if (pdu < EFX_MAC_PDU_MIN) { 107e948693eSPhilip Paeps rc = EINVAL; 108e948693eSPhilip Paeps goto fail1; 109e948693eSPhilip Paeps } 110e948693eSPhilip Paeps 111e948693eSPhilip Paeps if (pdu > EFX_MAC_PDU_MAX) { 112e948693eSPhilip Paeps rc = EINVAL; 113e948693eSPhilip Paeps goto fail2; 114e948693eSPhilip Paeps } 115e948693eSPhilip Paeps 116e948693eSPhilip Paeps old_pdu = epp->ep_mac_pdu; 117e948693eSPhilip Paeps epp->ep_mac_pdu = (uint32_t)pdu; 11808c5af79SAndrew Rybchenko if ((rc = emop->emo_pdu_set(enp)) != 0) 119e948693eSPhilip Paeps goto fail3; 120e948693eSPhilip Paeps 121e948693eSPhilip Paeps return (0); 122e948693eSPhilip Paeps 123e948693eSPhilip Paeps fail3: 124e948693eSPhilip Paeps EFSYS_PROBE(fail3); 125e948693eSPhilip Paeps 126e948693eSPhilip Paeps epp->ep_mac_pdu = old_pdu; 127e948693eSPhilip Paeps 128e948693eSPhilip Paeps fail2: 129e948693eSPhilip Paeps EFSYS_PROBE(fail2); 130e948693eSPhilip Paeps fail1: 131460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 132e948693eSPhilip Paeps 133e948693eSPhilip Paeps return (rc); 134e948693eSPhilip Paeps } 135e948693eSPhilip Paeps 136460cb568SAndrew Rybchenko __checkReturn efx_rc_t 137d8484af2SAndrew Rybchenko efx_mac_pdu_get( 138d8484af2SAndrew Rybchenko __in efx_nic_t *enp, 139d8484af2SAndrew Rybchenko __out size_t *pdu) 140d8484af2SAndrew Rybchenko { 141d8484af2SAndrew Rybchenko efx_port_t *epp = &(enp->en_port); 142d8484af2SAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop; 143d8484af2SAndrew Rybchenko efx_rc_t rc; 144d8484af2SAndrew Rybchenko 145d8484af2SAndrew Rybchenko if ((rc = emop->emo_pdu_get(enp, pdu)) != 0) 146d8484af2SAndrew Rybchenko goto fail1; 147d8484af2SAndrew Rybchenko 148d8484af2SAndrew Rybchenko return (0); 149d8484af2SAndrew Rybchenko 150d8484af2SAndrew Rybchenko fail1: 151d8484af2SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 152d8484af2SAndrew Rybchenko 153d8484af2SAndrew Rybchenko return (rc); 154d8484af2SAndrew Rybchenko } 155d8484af2SAndrew Rybchenko 156d8484af2SAndrew Rybchenko __checkReturn efx_rc_t 157e948693eSPhilip Paeps efx_mac_addr_set( 158e948693eSPhilip Paeps __in efx_nic_t *enp, 159e948693eSPhilip Paeps __in uint8_t *addr) 160e948693eSPhilip Paeps { 161e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port); 162ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop; 163e948693eSPhilip Paeps uint8_t old_addr[6]; 164e948693eSPhilip Paeps uint32_t oui; 165460cb568SAndrew Rybchenko efx_rc_t rc; 166e948693eSPhilip Paeps 167e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 168e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 169e948693eSPhilip Paeps 1703c838a9fSAndrew Rybchenko if (EFX_MAC_ADDR_IS_MULTICAST(addr)) { 171e948693eSPhilip Paeps rc = EINVAL; 172e948693eSPhilip Paeps goto fail1; 173e948693eSPhilip Paeps } 174e948693eSPhilip Paeps 175e948693eSPhilip Paeps oui = addr[0] << 16 | addr[1] << 8 | addr[2]; 176e948693eSPhilip Paeps if (oui == 0x000000) { 177e948693eSPhilip Paeps rc = EINVAL; 178e948693eSPhilip Paeps goto fail2; 179e948693eSPhilip Paeps } 180e948693eSPhilip Paeps 181e948693eSPhilip Paeps EFX_MAC_ADDR_COPY(old_addr, epp->ep_mac_addr); 182e948693eSPhilip Paeps EFX_MAC_ADDR_COPY(epp->ep_mac_addr, addr); 1833c838a9fSAndrew Rybchenko if ((rc = emop->emo_addr_set(enp)) != 0) 184e948693eSPhilip Paeps goto fail3; 185e948693eSPhilip Paeps 186e948693eSPhilip Paeps return (0); 187e948693eSPhilip Paeps 188e948693eSPhilip Paeps fail3: 189e948693eSPhilip Paeps EFSYS_PROBE(fail3); 190e948693eSPhilip Paeps 191e948693eSPhilip Paeps EFX_MAC_ADDR_COPY(epp->ep_mac_addr, old_addr); 192e948693eSPhilip Paeps 193e948693eSPhilip Paeps fail2: 194e948693eSPhilip Paeps EFSYS_PROBE(fail2); 195e948693eSPhilip Paeps fail1: 196460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 197e948693eSPhilip Paeps 198e948693eSPhilip Paeps return (rc); 199e948693eSPhilip Paeps } 200e948693eSPhilip Paeps 201460cb568SAndrew Rybchenko __checkReturn efx_rc_t 202e948693eSPhilip Paeps efx_mac_filter_set( 203e948693eSPhilip Paeps __in efx_nic_t *enp, 2043c838a9fSAndrew Rybchenko __in boolean_t all_unicst, 2053c838a9fSAndrew Rybchenko __in boolean_t mulcst, 2063c838a9fSAndrew Rybchenko __in boolean_t all_mulcst, 207e948693eSPhilip Paeps __in boolean_t brdcst) 208e948693eSPhilip Paeps { 209e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port); 210ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop; 2113c838a9fSAndrew Rybchenko boolean_t old_all_unicst; 2123c838a9fSAndrew Rybchenko boolean_t old_mulcst; 2133c838a9fSAndrew Rybchenko boolean_t old_all_mulcst; 214e948693eSPhilip Paeps boolean_t old_brdcst; 215460cb568SAndrew Rybchenko efx_rc_t rc; 216e948693eSPhilip Paeps 217e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 218e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 219e948693eSPhilip Paeps 2203c838a9fSAndrew Rybchenko old_all_unicst = epp->ep_all_unicst; 2213c838a9fSAndrew Rybchenko old_mulcst = epp->ep_mulcst; 2223c838a9fSAndrew Rybchenko old_all_mulcst = epp->ep_all_mulcst; 2233c838a9fSAndrew Rybchenko old_brdcst = epp->ep_brdcst; 224e948693eSPhilip Paeps 2253c838a9fSAndrew Rybchenko epp->ep_all_unicst = all_unicst; 2263c838a9fSAndrew Rybchenko epp->ep_mulcst = mulcst; 2273c838a9fSAndrew Rybchenko epp->ep_all_mulcst = all_mulcst; 228e948693eSPhilip Paeps epp->ep_brdcst = brdcst; 229e948693eSPhilip Paeps 230e948693eSPhilip Paeps if ((rc = emop->emo_reconfigure(enp)) != 0) 231e948693eSPhilip Paeps goto fail1; 232e948693eSPhilip Paeps 233e948693eSPhilip Paeps return (0); 234e948693eSPhilip Paeps 235e948693eSPhilip Paeps fail1: 236460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 237e948693eSPhilip Paeps 2383c838a9fSAndrew Rybchenko epp->ep_all_unicst = old_all_unicst; 2393c838a9fSAndrew Rybchenko epp->ep_mulcst = old_mulcst; 2403c838a9fSAndrew Rybchenko epp->ep_all_mulcst = old_all_mulcst; 241e948693eSPhilip Paeps epp->ep_brdcst = old_brdcst; 242e948693eSPhilip Paeps 243e948693eSPhilip Paeps return (rc); 244e948693eSPhilip Paeps } 245e948693eSPhilip Paeps 246460cb568SAndrew Rybchenko __checkReturn efx_rc_t 247e948693eSPhilip Paeps efx_mac_drain( 248e948693eSPhilip Paeps __in efx_nic_t *enp, 249e948693eSPhilip Paeps __in boolean_t enabled) 250e948693eSPhilip Paeps { 251e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port); 252ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop; 253460cb568SAndrew Rybchenko efx_rc_t rc; 254e948693eSPhilip Paeps 255e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 256e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 257e948693eSPhilip Paeps EFSYS_ASSERT(emop != NULL); 258e948693eSPhilip Paeps 259e948693eSPhilip Paeps if (epp->ep_mac_drain == enabled) 260e948693eSPhilip Paeps return (0); 261e948693eSPhilip Paeps 262e948693eSPhilip Paeps epp->ep_mac_drain = enabled; 263e948693eSPhilip Paeps 264e948693eSPhilip Paeps if ((rc = emop->emo_reconfigure(enp)) != 0) 2650c909247SAndrew Rybchenko goto fail1; 266e948693eSPhilip Paeps 267e948693eSPhilip Paeps return (0); 268e948693eSPhilip Paeps 269e948693eSPhilip Paeps fail1: 270460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 271e948693eSPhilip Paeps 272e948693eSPhilip Paeps return (rc); 273e948693eSPhilip Paeps } 274e948693eSPhilip Paeps 275460cb568SAndrew Rybchenko __checkReturn efx_rc_t 276e948693eSPhilip Paeps efx_mac_up( 277e948693eSPhilip Paeps __in efx_nic_t *enp, 278e948693eSPhilip Paeps __out boolean_t *mac_upp) 279e948693eSPhilip Paeps { 280e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port); 281ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop; 282460cb568SAndrew Rybchenko efx_rc_t rc; 283e948693eSPhilip Paeps 284e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 285e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 286e948693eSPhilip Paeps 287e948693eSPhilip Paeps if ((rc = emop->emo_up(enp, mac_upp)) != 0) 288e948693eSPhilip Paeps goto fail1; 289e948693eSPhilip Paeps 290e948693eSPhilip Paeps return (0); 291e948693eSPhilip Paeps 292e948693eSPhilip Paeps fail1: 293460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 294e948693eSPhilip Paeps 295e948693eSPhilip Paeps return (rc); 296e948693eSPhilip Paeps } 297e948693eSPhilip Paeps 298460cb568SAndrew Rybchenko __checkReturn efx_rc_t 299e948693eSPhilip Paeps efx_mac_fcntl_set( 300e948693eSPhilip Paeps __in efx_nic_t *enp, 301e948693eSPhilip Paeps __in unsigned int fcntl, 302e948693eSPhilip Paeps __in boolean_t autoneg) 303e948693eSPhilip Paeps { 304e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port); 305ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop; 306ec831f7fSAndrew Rybchenko const efx_phy_ops_t *epop = epp->ep_epop; 307e948693eSPhilip Paeps unsigned int old_fcntl; 308e948693eSPhilip Paeps boolean_t old_autoneg; 309e948693eSPhilip Paeps unsigned int old_adv_cap; 310460cb568SAndrew Rybchenko efx_rc_t rc; 311e948693eSPhilip Paeps 312e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 313e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 314e948693eSPhilip Paeps 315e948693eSPhilip Paeps if ((fcntl & ~(EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE)) != 0) { 316e948693eSPhilip Paeps rc = EINVAL; 317e948693eSPhilip Paeps goto fail1; 318e948693eSPhilip Paeps } 319e948693eSPhilip Paeps 320e948693eSPhilip Paeps /* 3213c838a9fSAndrew Rybchenko * Ignore a request to set flow control auto-negotiation 322e948693eSPhilip Paeps * if the PHY doesn't support it. 323e948693eSPhilip Paeps */ 324e948693eSPhilip Paeps if (~epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN)) 325e948693eSPhilip Paeps autoneg = B_FALSE; 326e948693eSPhilip Paeps 327e948693eSPhilip Paeps old_fcntl = epp->ep_fcntl; 3283c838a9fSAndrew Rybchenko old_autoneg = epp->ep_fcntl_autoneg; 329e948693eSPhilip Paeps old_adv_cap = epp->ep_adv_cap_mask; 330e948693eSPhilip Paeps 331e948693eSPhilip Paeps epp->ep_fcntl = fcntl; 332e948693eSPhilip Paeps epp->ep_fcntl_autoneg = autoneg; 333e948693eSPhilip Paeps 334e948693eSPhilip Paeps /* 3353c838a9fSAndrew Rybchenko * Always encode the flow control settings in the advertised 3363c838a9fSAndrew Rybchenko * capabilities even if we are not trying to auto-negotiate 3373c838a9fSAndrew Rybchenko * them and reconfigure both the PHY and the MAC. 338e948693eSPhilip Paeps */ 339e948693eSPhilip Paeps if (fcntl & EFX_FCNTL_RESPOND) 340e948693eSPhilip Paeps epp->ep_adv_cap_mask |= (1 << EFX_PHY_CAP_PAUSE | 341e948693eSPhilip Paeps 1 << EFX_PHY_CAP_ASYM); 342e948693eSPhilip Paeps else 343e948693eSPhilip Paeps epp->ep_adv_cap_mask &= ~(1 << EFX_PHY_CAP_PAUSE | 344e948693eSPhilip Paeps 1 << EFX_PHY_CAP_ASYM); 345e948693eSPhilip Paeps 346e948693eSPhilip Paeps if (fcntl & EFX_FCNTL_GENERATE) 347e948693eSPhilip Paeps epp->ep_adv_cap_mask ^= (1 << EFX_PHY_CAP_ASYM); 348e948693eSPhilip Paeps 349e948693eSPhilip Paeps if ((rc = epop->epo_reconfigure(enp)) != 0) 350e948693eSPhilip Paeps goto fail2; 351e948693eSPhilip Paeps 352e948693eSPhilip Paeps if ((rc = emop->emo_reconfigure(enp)) != 0) 3533c838a9fSAndrew Rybchenko goto fail3; 354e948693eSPhilip Paeps 355e948693eSPhilip Paeps return (0); 356e948693eSPhilip Paeps 3573c838a9fSAndrew Rybchenko fail3: 3583c838a9fSAndrew Rybchenko EFSYS_PROBE(fail3); 3593c838a9fSAndrew Rybchenko 360e948693eSPhilip Paeps fail2: 361e948693eSPhilip Paeps EFSYS_PROBE(fail2); 362e948693eSPhilip Paeps 363e948693eSPhilip Paeps epp->ep_fcntl = old_fcntl; 364e948693eSPhilip Paeps epp->ep_fcntl_autoneg = old_autoneg; 365e948693eSPhilip Paeps epp->ep_adv_cap_mask = old_adv_cap; 366e948693eSPhilip Paeps 367e948693eSPhilip Paeps fail1: 368460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 369e948693eSPhilip Paeps 370e948693eSPhilip Paeps return (rc); 371e948693eSPhilip Paeps } 372e948693eSPhilip Paeps 373e948693eSPhilip Paeps void 374e948693eSPhilip Paeps efx_mac_fcntl_get( 375e948693eSPhilip Paeps __in efx_nic_t *enp, 376e948693eSPhilip Paeps __out unsigned int *fcntl_wantedp, 377e948693eSPhilip Paeps __out unsigned int *fcntl_linkp) 378e948693eSPhilip Paeps { 379e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port); 3803c838a9fSAndrew Rybchenko unsigned int wanted = 0; 381e948693eSPhilip Paeps 382e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 383e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 384e948693eSPhilip Paeps 385e948693eSPhilip Paeps /* 3863c838a9fSAndrew Rybchenko * Decode the requested flow control settings from the PHY 3873c838a9fSAndrew Rybchenko * advertised capabilities. 388e948693eSPhilip Paeps */ 389e948693eSPhilip Paeps if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_PAUSE)) 390e948693eSPhilip Paeps wanted = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE; 391e948693eSPhilip Paeps if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_ASYM)) 392e948693eSPhilip Paeps wanted ^= EFX_FCNTL_GENERATE; 393e948693eSPhilip Paeps 394e948693eSPhilip Paeps *fcntl_linkp = epp->ep_fcntl; 395e948693eSPhilip Paeps *fcntl_wantedp = wanted; 396e948693eSPhilip Paeps } 397e948693eSPhilip Paeps 398460cb568SAndrew Rybchenko __checkReturn efx_rc_t 3993c838a9fSAndrew Rybchenko efx_mac_multicast_list_set( 4003c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 4013c838a9fSAndrew Rybchenko __in_ecount(6*count) uint8_t const *addrs, 4023c838a9fSAndrew Rybchenko __in int count) 4033c838a9fSAndrew Rybchenko { 4043c838a9fSAndrew Rybchenko efx_port_t *epp = &(enp->en_port); 405ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop; 4063c838a9fSAndrew Rybchenko uint8_t *old_mulcst_addr_list = NULL; 4073c838a9fSAndrew Rybchenko uint32_t old_mulcst_addr_count; 408460cb568SAndrew Rybchenko efx_rc_t rc; 4093c838a9fSAndrew Rybchenko 4103c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 4113c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 4123c838a9fSAndrew Rybchenko 4133c838a9fSAndrew Rybchenko if (count > EFX_MAC_MULTICAST_LIST_MAX) { 4143c838a9fSAndrew Rybchenko rc = EINVAL; 4153c838a9fSAndrew Rybchenko goto fail1; 4163c838a9fSAndrew Rybchenko } 4173c838a9fSAndrew Rybchenko 4183c838a9fSAndrew Rybchenko old_mulcst_addr_count = epp->ep_mulcst_addr_count; 4193c838a9fSAndrew Rybchenko if (old_mulcst_addr_count > 0) { 4203c838a9fSAndrew Rybchenko /* Allocate memory to store old list (instead of using stack) */ 4213c838a9fSAndrew Rybchenko EFSYS_KMEM_ALLOC(enp->en_esip, 4223c838a9fSAndrew Rybchenko old_mulcst_addr_count * EFX_MAC_ADDR_LEN, 4233c838a9fSAndrew Rybchenko old_mulcst_addr_list); 4243c838a9fSAndrew Rybchenko if (old_mulcst_addr_list == NULL) { 4253c838a9fSAndrew Rybchenko rc = ENOMEM; 4263c838a9fSAndrew Rybchenko goto fail2; 4273c838a9fSAndrew Rybchenko } 4283c838a9fSAndrew Rybchenko 4293c838a9fSAndrew Rybchenko /* Save the old list in case we need to rollback */ 4303c838a9fSAndrew Rybchenko memcpy(old_mulcst_addr_list, epp->ep_mulcst_addr_list, 4313c838a9fSAndrew Rybchenko old_mulcst_addr_count * EFX_MAC_ADDR_LEN); 4323c838a9fSAndrew Rybchenko } 4333c838a9fSAndrew Rybchenko 4343c838a9fSAndrew Rybchenko /* Store the new list */ 4353c838a9fSAndrew Rybchenko memcpy(epp->ep_mulcst_addr_list, addrs, 4363c838a9fSAndrew Rybchenko count * EFX_MAC_ADDR_LEN); 4373c838a9fSAndrew Rybchenko epp->ep_mulcst_addr_count = count; 4383c838a9fSAndrew Rybchenko 4393c838a9fSAndrew Rybchenko if ((rc = emop->emo_multicast_list_set(enp)) != 0) 4403c838a9fSAndrew Rybchenko goto fail3; 4413c838a9fSAndrew Rybchenko 4423c838a9fSAndrew Rybchenko if (old_mulcst_addr_count > 0) { 4433c838a9fSAndrew Rybchenko EFSYS_KMEM_FREE(enp->en_esip, 4443c838a9fSAndrew Rybchenko old_mulcst_addr_count * EFX_MAC_ADDR_LEN, 4453c838a9fSAndrew Rybchenko old_mulcst_addr_list); 4463c838a9fSAndrew Rybchenko } 4473c838a9fSAndrew Rybchenko 4483c838a9fSAndrew Rybchenko return (0); 4493c838a9fSAndrew Rybchenko 4503c838a9fSAndrew Rybchenko fail3: 4513c838a9fSAndrew Rybchenko EFSYS_PROBE(fail3); 4523c838a9fSAndrew Rybchenko 4533c838a9fSAndrew Rybchenko /* Restore original list on failure */ 4543c838a9fSAndrew Rybchenko epp->ep_mulcst_addr_count = old_mulcst_addr_count; 4553c838a9fSAndrew Rybchenko if (old_mulcst_addr_count > 0) { 4563c838a9fSAndrew Rybchenko memcpy(epp->ep_mulcst_addr_list, old_mulcst_addr_list, 4573c838a9fSAndrew Rybchenko old_mulcst_addr_count * EFX_MAC_ADDR_LEN); 4583c838a9fSAndrew Rybchenko 4593c838a9fSAndrew Rybchenko EFSYS_KMEM_FREE(enp->en_esip, 4603c838a9fSAndrew Rybchenko old_mulcst_addr_count * EFX_MAC_ADDR_LEN, 4613c838a9fSAndrew Rybchenko old_mulcst_addr_list); 4623c838a9fSAndrew Rybchenko } 4633c838a9fSAndrew Rybchenko 4643c838a9fSAndrew Rybchenko fail2: 4653c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2); 4663c838a9fSAndrew Rybchenko 4673c838a9fSAndrew Rybchenko fail1: 468460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 4693c838a9fSAndrew Rybchenko 4703c838a9fSAndrew Rybchenko return (rc); 4713c838a9fSAndrew Rybchenko 4723c838a9fSAndrew Rybchenko } 4733c838a9fSAndrew Rybchenko 474460cb568SAndrew Rybchenko __checkReturn efx_rc_t 4753c838a9fSAndrew Rybchenko efx_mac_filter_default_rxq_set( 4763c838a9fSAndrew Rybchenko __in efx_nic_t *enp, 4773c838a9fSAndrew Rybchenko __in efx_rxq_t *erp, 4783c838a9fSAndrew Rybchenko __in boolean_t using_rss) 4793c838a9fSAndrew Rybchenko { 4803c838a9fSAndrew Rybchenko efx_port_t *epp = &(enp->en_port); 481ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop; 482460cb568SAndrew Rybchenko efx_rc_t rc; 4833c838a9fSAndrew Rybchenko 4843c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 4853c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 4863c838a9fSAndrew Rybchenko 4873c838a9fSAndrew Rybchenko if (emop->emo_filter_default_rxq_set != NULL) { 4883c838a9fSAndrew Rybchenko rc = emop->emo_filter_default_rxq_set(enp, erp, using_rss); 4893c838a9fSAndrew Rybchenko if (rc != 0) 4903c838a9fSAndrew Rybchenko goto fail1; 4913c838a9fSAndrew Rybchenko } 4923c838a9fSAndrew Rybchenko 4933c838a9fSAndrew Rybchenko return (0); 4943c838a9fSAndrew Rybchenko 4953c838a9fSAndrew Rybchenko fail1: 496460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 4973c838a9fSAndrew Rybchenko 4983c838a9fSAndrew Rybchenko return (rc); 4993c838a9fSAndrew Rybchenko } 5003c838a9fSAndrew Rybchenko 5013c838a9fSAndrew Rybchenko void 5023c838a9fSAndrew Rybchenko efx_mac_filter_default_rxq_clear( 5033c838a9fSAndrew Rybchenko __in efx_nic_t *enp) 5043c838a9fSAndrew Rybchenko { 5053c838a9fSAndrew Rybchenko efx_port_t *epp = &(enp->en_port); 506ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop; 5073c838a9fSAndrew Rybchenko 5083c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 5093c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 5103c838a9fSAndrew Rybchenko 5113c838a9fSAndrew Rybchenko if (emop->emo_filter_default_rxq_clear != NULL) 5123c838a9fSAndrew Rybchenko emop->emo_filter_default_rxq_clear(enp); 5133c838a9fSAndrew Rybchenko } 5143c838a9fSAndrew Rybchenko 5153c838a9fSAndrew Rybchenko 516e948693eSPhilip Paeps #if EFSYS_OPT_MAC_STATS 517e948693eSPhilip Paeps 518e948693eSPhilip Paeps #if EFSYS_OPT_NAMES 519e948693eSPhilip Paeps 520a260bd77SAndrew Rybchenko /* START MKCONFIG GENERATED EfxMacStatNamesBlock c11b91b42f922516 */ 521a260bd77SAndrew Rybchenko static const char * const __efx_mac_stat_name[] = { 522e948693eSPhilip Paeps "rx_octets", 523e948693eSPhilip Paeps "rx_pkts", 524e948693eSPhilip Paeps "rx_unicst_pkts", 525e948693eSPhilip Paeps "rx_multicst_pkts", 526e948693eSPhilip Paeps "rx_brdcst_pkts", 527e948693eSPhilip Paeps "rx_pause_pkts", 528e948693eSPhilip Paeps "rx_le_64_pkts", 529e948693eSPhilip Paeps "rx_65_to_127_pkts", 530e948693eSPhilip Paeps "rx_128_to_255_pkts", 531e948693eSPhilip Paeps "rx_256_to_511_pkts", 532e948693eSPhilip Paeps "rx_512_to_1023_pkts", 533e948693eSPhilip Paeps "rx_1024_to_15xx_pkts", 534e948693eSPhilip Paeps "rx_ge_15xx_pkts", 535e948693eSPhilip Paeps "rx_errors", 536e948693eSPhilip Paeps "rx_fcs_errors", 537e948693eSPhilip Paeps "rx_drop_events", 538e948693eSPhilip Paeps "rx_false_carrier_errors", 539e948693eSPhilip Paeps "rx_symbol_errors", 540e948693eSPhilip Paeps "rx_align_errors", 541e948693eSPhilip Paeps "rx_internal_errors", 542e948693eSPhilip Paeps "rx_jabber_pkts", 543e948693eSPhilip Paeps "rx_lane0_char_err", 544e948693eSPhilip Paeps "rx_lane1_char_err", 545e948693eSPhilip Paeps "rx_lane2_char_err", 546e948693eSPhilip Paeps "rx_lane3_char_err", 547e948693eSPhilip Paeps "rx_lane0_disp_err", 548e948693eSPhilip Paeps "rx_lane1_disp_err", 549e948693eSPhilip Paeps "rx_lane2_disp_err", 550e948693eSPhilip Paeps "rx_lane3_disp_err", 551e948693eSPhilip Paeps "rx_match_fault", 552e948693eSPhilip Paeps "rx_nodesc_drop_cnt", 553e948693eSPhilip Paeps "tx_octets", 554e948693eSPhilip Paeps "tx_pkts", 555e948693eSPhilip Paeps "tx_unicst_pkts", 556e948693eSPhilip Paeps "tx_multicst_pkts", 557e948693eSPhilip Paeps "tx_brdcst_pkts", 558e948693eSPhilip Paeps "tx_pause_pkts", 559e948693eSPhilip Paeps "tx_le_64_pkts", 560e948693eSPhilip Paeps "tx_65_to_127_pkts", 561e948693eSPhilip Paeps "tx_128_to_255_pkts", 562e948693eSPhilip Paeps "tx_256_to_511_pkts", 563e948693eSPhilip Paeps "tx_512_to_1023_pkts", 564e948693eSPhilip Paeps "tx_1024_to_15xx_pkts", 565e948693eSPhilip Paeps "tx_ge_15xx_pkts", 566e948693eSPhilip Paeps "tx_errors", 567e948693eSPhilip Paeps "tx_sgl_col_pkts", 568e948693eSPhilip Paeps "tx_mult_col_pkts", 569e948693eSPhilip Paeps "tx_ex_col_pkts", 570e948693eSPhilip Paeps "tx_late_col_pkts", 571e948693eSPhilip Paeps "tx_def_pkts", 572e948693eSPhilip Paeps "tx_ex_def_pkts", 5733c838a9fSAndrew Rybchenko "pm_trunc_bb_overflow", 5743c838a9fSAndrew Rybchenko "pm_discard_bb_overflow", 5753c838a9fSAndrew Rybchenko "pm_trunc_vfifo_full", 5763c838a9fSAndrew Rybchenko "pm_discard_vfifo_full", 5773c838a9fSAndrew Rybchenko "pm_trunc_qbb", 5783c838a9fSAndrew Rybchenko "pm_discard_qbb", 5793c838a9fSAndrew Rybchenko "pm_discard_mapping", 5803c838a9fSAndrew Rybchenko "rxdp_q_disabled_pkts", 5813c838a9fSAndrew Rybchenko "rxdp_di_dropped_pkts", 5823c838a9fSAndrew Rybchenko "rxdp_streaming_pkts", 5833c838a9fSAndrew Rybchenko "rxdp_hlb_fetch", 5843c838a9fSAndrew Rybchenko "rxdp_hlb_wait", 5853c838a9fSAndrew Rybchenko "vadapter_rx_unicast_packets", 5863c838a9fSAndrew Rybchenko "vadapter_rx_unicast_bytes", 5873c838a9fSAndrew Rybchenko "vadapter_rx_multicast_packets", 5883c838a9fSAndrew Rybchenko "vadapter_rx_multicast_bytes", 5893c838a9fSAndrew Rybchenko "vadapter_rx_broadcast_packets", 5903c838a9fSAndrew Rybchenko "vadapter_rx_broadcast_bytes", 5913c838a9fSAndrew Rybchenko "vadapter_rx_bad_packets", 5923c838a9fSAndrew Rybchenko "vadapter_rx_bad_bytes", 5933c838a9fSAndrew Rybchenko "vadapter_rx_overflow", 5943c838a9fSAndrew Rybchenko "vadapter_tx_unicast_packets", 5953c838a9fSAndrew Rybchenko "vadapter_tx_unicast_bytes", 5963c838a9fSAndrew Rybchenko "vadapter_tx_multicast_packets", 5973c838a9fSAndrew Rybchenko "vadapter_tx_multicast_bytes", 5983c838a9fSAndrew Rybchenko "vadapter_tx_broadcast_packets", 5993c838a9fSAndrew Rybchenko "vadapter_tx_broadcast_bytes", 6003c838a9fSAndrew Rybchenko "vadapter_tx_bad_packets", 6013c838a9fSAndrew Rybchenko "vadapter_tx_bad_bytes", 6023c838a9fSAndrew Rybchenko "vadapter_tx_overflow", 603e948693eSPhilip Paeps }; 604e948693eSPhilip Paeps /* END MKCONFIG GENERATED EfxMacStatNamesBlock */ 605e948693eSPhilip Paeps 6063c838a9fSAndrew Rybchenko __checkReturn const char * 607e948693eSPhilip Paeps efx_mac_stat_name( 608e948693eSPhilip Paeps __in efx_nic_t *enp, 609e948693eSPhilip Paeps __in unsigned int id) 610e948693eSPhilip Paeps { 611e948693eSPhilip Paeps _NOTE(ARGUNUSED(enp)) 612e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 613e948693eSPhilip Paeps 614e948693eSPhilip Paeps EFSYS_ASSERT3U(id, <, EFX_MAC_NSTATS); 615e948693eSPhilip Paeps return (__efx_mac_stat_name[id]); 616e948693eSPhilip Paeps } 617e948693eSPhilip Paeps 6183c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_NAMES */ 619e948693eSPhilip Paeps 62058a72cb2SAndrew Rybchenko static efx_rc_t 62158a72cb2SAndrew Rybchenko efx_mac_stats_mask_add_range( 62258a72cb2SAndrew Rybchenko __inout_bcount(mask_size) uint32_t *maskp, 62358a72cb2SAndrew Rybchenko __in size_t mask_size, 62458a72cb2SAndrew Rybchenko __in const struct efx_mac_stats_range *rngp) 62558a72cb2SAndrew Rybchenko { 62658a72cb2SAndrew Rybchenko unsigned int mask_npages = mask_size / sizeof (*maskp); 62758a72cb2SAndrew Rybchenko unsigned int el; 62858a72cb2SAndrew Rybchenko unsigned int el_min; 62958a72cb2SAndrew Rybchenko unsigned int el_max; 63058a72cb2SAndrew Rybchenko unsigned int low; 63158a72cb2SAndrew Rybchenko unsigned int high; 63258a72cb2SAndrew Rybchenko unsigned int width; 63358a72cb2SAndrew Rybchenko efx_rc_t rc; 63458a72cb2SAndrew Rybchenko 63558a72cb2SAndrew Rybchenko if ((mask_npages * EFX_MAC_STATS_MASK_BITS_PER_PAGE) <= 63658a72cb2SAndrew Rybchenko (unsigned int)rngp->last) { 63758a72cb2SAndrew Rybchenko rc = EINVAL; 63858a72cb2SAndrew Rybchenko goto fail1; 63958a72cb2SAndrew Rybchenko } 64058a72cb2SAndrew Rybchenko 64158a72cb2SAndrew Rybchenko EFSYS_ASSERT3U(rngp->first, <=, rngp->last); 64258a72cb2SAndrew Rybchenko EFSYS_ASSERT3U(rngp->last, <, EFX_MAC_NSTATS); 64358a72cb2SAndrew Rybchenko 64458a72cb2SAndrew Rybchenko for (el = 0; el < mask_npages; ++el) { 64558a72cb2SAndrew Rybchenko el_min = el * EFX_MAC_STATS_MASK_BITS_PER_PAGE; 64658a72cb2SAndrew Rybchenko el_max = 64758a72cb2SAndrew Rybchenko el_min + (EFX_MAC_STATS_MASK_BITS_PER_PAGE - 1); 64858a72cb2SAndrew Rybchenko if ((unsigned int)rngp->first > el_max || 64958a72cb2SAndrew Rybchenko (unsigned int)rngp->last < el_min) 65058a72cb2SAndrew Rybchenko continue; 65158a72cb2SAndrew Rybchenko low = MAX((unsigned int)rngp->first, el_min); 65258a72cb2SAndrew Rybchenko high = MIN((unsigned int)rngp->last, el_max); 65358a72cb2SAndrew Rybchenko width = high - low + 1; 65458a72cb2SAndrew Rybchenko maskp[el] |= 65558a72cb2SAndrew Rybchenko (width == EFX_MAC_STATS_MASK_BITS_PER_PAGE) ? 65658a72cb2SAndrew Rybchenko (~0ULL) : (((1ULL << width) - 1) << (low - el_min)); 65758a72cb2SAndrew Rybchenko } 65858a72cb2SAndrew Rybchenko 65958a72cb2SAndrew Rybchenko return (0); 66058a72cb2SAndrew Rybchenko 66158a72cb2SAndrew Rybchenko fail1: 66258a72cb2SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 66358a72cb2SAndrew Rybchenko 66458a72cb2SAndrew Rybchenko return (rc); 66558a72cb2SAndrew Rybchenko } 66658a72cb2SAndrew Rybchenko 66758a72cb2SAndrew Rybchenko efx_rc_t 66858a72cb2SAndrew Rybchenko efx_mac_stats_mask_add_ranges( 66958a72cb2SAndrew Rybchenko __inout_bcount(mask_size) uint32_t *maskp, 67058a72cb2SAndrew Rybchenko __in size_t mask_size, 67158a72cb2SAndrew Rybchenko __in_ecount(rng_count) const struct efx_mac_stats_range *rngp, 67258a72cb2SAndrew Rybchenko __in unsigned int rng_count) 67358a72cb2SAndrew Rybchenko { 67458a72cb2SAndrew Rybchenko unsigned int i; 67558a72cb2SAndrew Rybchenko efx_rc_t rc; 67658a72cb2SAndrew Rybchenko 67758a72cb2SAndrew Rybchenko for (i = 0; i < rng_count; ++i) { 67858a72cb2SAndrew Rybchenko if ((rc = efx_mac_stats_mask_add_range(maskp, mask_size, 67958a72cb2SAndrew Rybchenko &rngp[i])) != 0) 68058a72cb2SAndrew Rybchenko goto fail1; 68158a72cb2SAndrew Rybchenko } 68258a72cb2SAndrew Rybchenko 68358a72cb2SAndrew Rybchenko return (0); 68458a72cb2SAndrew Rybchenko 68558a72cb2SAndrew Rybchenko fail1: 68658a72cb2SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 68758a72cb2SAndrew Rybchenko 68858a72cb2SAndrew Rybchenko return (rc); 68958a72cb2SAndrew Rybchenko } 69058a72cb2SAndrew Rybchenko 69158a72cb2SAndrew Rybchenko __checkReturn efx_rc_t 69258a72cb2SAndrew Rybchenko efx_mac_stats_get_mask( 69358a72cb2SAndrew Rybchenko __in efx_nic_t *enp, 69458a72cb2SAndrew Rybchenko __out_bcount(mask_size) uint32_t *maskp, 69558a72cb2SAndrew Rybchenko __in size_t mask_size) 69658a72cb2SAndrew Rybchenko { 69758a72cb2SAndrew Rybchenko efx_port_t *epp = &(enp->en_port); 69858a72cb2SAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop; 69958a72cb2SAndrew Rybchenko efx_rc_t rc; 70058a72cb2SAndrew Rybchenko 70158a72cb2SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 70258a72cb2SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); 70358a72cb2SAndrew Rybchenko EFSYS_ASSERT(maskp != NULL); 70458a72cb2SAndrew Rybchenko EFSYS_ASSERT(mask_size % sizeof (maskp[0]) == 0); 70558a72cb2SAndrew Rybchenko 70658a72cb2SAndrew Rybchenko (void) memset(maskp, 0, mask_size); 70758a72cb2SAndrew Rybchenko 70858a72cb2SAndrew Rybchenko if ((rc = emop->emo_stats_get_mask(enp, maskp, mask_size)) != 0) 70958a72cb2SAndrew Rybchenko goto fail1; 71058a72cb2SAndrew Rybchenko 71158a72cb2SAndrew Rybchenko return (0); 71258a72cb2SAndrew Rybchenko 71358a72cb2SAndrew Rybchenko fail1: 71458a72cb2SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 71558a72cb2SAndrew Rybchenko 71658a72cb2SAndrew Rybchenko return (rc); 71758a72cb2SAndrew Rybchenko } 71858a72cb2SAndrew Rybchenko 719460cb568SAndrew Rybchenko __checkReturn efx_rc_t 720e948693eSPhilip Paeps efx_mac_stats_upload( 721e948693eSPhilip Paeps __in efx_nic_t *enp, 722e948693eSPhilip Paeps __in efsys_mem_t *esmp) 723e948693eSPhilip Paeps { 724e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port); 725ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop; 726460cb568SAndrew Rybchenko efx_rc_t rc; 727e948693eSPhilip Paeps 728e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 729e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 730e948693eSPhilip Paeps EFSYS_ASSERT(emop != NULL); 731e948693eSPhilip Paeps 732e948693eSPhilip Paeps /* 733e948693eSPhilip Paeps * Don't assert !ep_mac_stats_pending, because the client might 734e948693eSPhilip Paeps * have failed to finalise statistics when previously stopping 735e948693eSPhilip Paeps * the port. 736e948693eSPhilip Paeps */ 737e948693eSPhilip Paeps if ((rc = emop->emo_stats_upload(enp, esmp)) != 0) 738e948693eSPhilip Paeps goto fail1; 739e948693eSPhilip Paeps 740e948693eSPhilip Paeps epp->ep_mac_stats_pending = B_TRUE; 741e948693eSPhilip Paeps 742e948693eSPhilip Paeps return (0); 743e948693eSPhilip Paeps 744e948693eSPhilip Paeps fail1: 745460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 746e948693eSPhilip Paeps 747e948693eSPhilip Paeps return (rc); 748e948693eSPhilip Paeps } 749e948693eSPhilip Paeps 750460cb568SAndrew Rybchenko __checkReturn efx_rc_t 751e948693eSPhilip Paeps efx_mac_stats_periodic( 752e948693eSPhilip Paeps __in efx_nic_t *enp, 753e948693eSPhilip Paeps __in efsys_mem_t *esmp, 754e948693eSPhilip Paeps __in uint16_t period_ms, 755e948693eSPhilip Paeps __in boolean_t events) 756e948693eSPhilip Paeps { 757e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port); 758ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop; 759460cb568SAndrew Rybchenko efx_rc_t rc; 760e948693eSPhilip Paeps 761e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 762e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 763e948693eSPhilip Paeps 764e948693eSPhilip Paeps EFSYS_ASSERT(emop != NULL); 765e948693eSPhilip Paeps 766e948693eSPhilip Paeps if (emop->emo_stats_periodic == NULL) { 767e948693eSPhilip Paeps rc = EINVAL; 768e948693eSPhilip Paeps goto fail1; 769e948693eSPhilip Paeps } 770e948693eSPhilip Paeps 771e948693eSPhilip Paeps if ((rc = emop->emo_stats_periodic(enp, esmp, period_ms, events)) != 0) 772e948693eSPhilip Paeps goto fail2; 773e948693eSPhilip Paeps 774e948693eSPhilip Paeps return (0); 775e948693eSPhilip Paeps 776e948693eSPhilip Paeps fail2: 777e948693eSPhilip Paeps EFSYS_PROBE(fail2); 778e948693eSPhilip Paeps fail1: 779460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 780e948693eSPhilip Paeps 781e948693eSPhilip Paeps return (rc); 782e948693eSPhilip Paeps } 783e948693eSPhilip Paeps 784e948693eSPhilip Paeps 785460cb568SAndrew Rybchenko __checkReturn efx_rc_t 786e948693eSPhilip Paeps efx_mac_stats_update( 787e948693eSPhilip Paeps __in efx_nic_t *enp, 788e948693eSPhilip Paeps __in efsys_mem_t *esmp, 789e948693eSPhilip Paeps __inout_ecount(EFX_MAC_NSTATS) efsys_stat_t *essp, 79014c3e490SAndrew Rybchenko __inout_opt uint32_t *generationp) 791e948693eSPhilip Paeps { 792e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port); 793ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop; 794460cb568SAndrew Rybchenko efx_rc_t rc; 795e948693eSPhilip Paeps 796e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 797e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 798e948693eSPhilip Paeps EFSYS_ASSERT(emop != NULL); 799e948693eSPhilip Paeps 800e948693eSPhilip Paeps rc = emop->emo_stats_update(enp, esmp, essp, generationp); 801e948693eSPhilip Paeps if (rc == 0) 802e948693eSPhilip Paeps epp->ep_mac_stats_pending = B_FALSE; 803e948693eSPhilip Paeps 804e948693eSPhilip Paeps return (rc); 805e948693eSPhilip Paeps } 806e948693eSPhilip Paeps 807e948693eSPhilip Paeps #endif /* EFSYS_OPT_MAC_STATS */ 808e948693eSPhilip Paeps 809460cb568SAndrew Rybchenko __checkReturn efx_rc_t 810e948693eSPhilip Paeps efx_mac_select( 811e948693eSPhilip Paeps __in efx_nic_t *enp) 812e948693eSPhilip Paeps { 813e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port); 814e948693eSPhilip Paeps efx_mac_type_t type = EFX_MAC_INVALID; 815ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop; 816e948693eSPhilip Paeps int rc = EINVAL; 817e948693eSPhilip Paeps 81895812f27SAndrew Rybchenko switch (enp->en_family) { 819c15d6d21SAndrew Rybchenko #if EFSYS_OPT_SIENA 82095812f27SAndrew Rybchenko case EFX_FAMILY_SIENA: 82195812f27SAndrew Rybchenko emop = &__efx_siena_mac_ops; 822c15d6d21SAndrew Rybchenko type = EFX_MAC_SIENA; 82395812f27SAndrew Rybchenko break; 82495812f27SAndrew Rybchenko #endif /* EFSYS_OPT_SIENA */ 825c15d6d21SAndrew Rybchenko 8263c838a9fSAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON 82795812f27SAndrew Rybchenko case EFX_FAMILY_HUNTINGTON: 82895812f27SAndrew Rybchenko emop = &__efx_ef10_mac_ops; 8293c838a9fSAndrew Rybchenko type = EFX_MAC_HUNTINGTON; 83095812f27SAndrew Rybchenko break; 83195812f27SAndrew Rybchenko #endif /* EFSYS_OPT_HUNTINGTON */ 8323c838a9fSAndrew Rybchenko 833c15d6d21SAndrew Rybchenko #if EFSYS_OPT_MEDFORD 83495812f27SAndrew Rybchenko case EFX_FAMILY_MEDFORD: 83595812f27SAndrew Rybchenko emop = &__efx_ef10_mac_ops; 836c15d6d21SAndrew Rybchenko type = EFX_MAC_MEDFORD; 83795812f27SAndrew Rybchenko break; 83895812f27SAndrew Rybchenko #endif /* EFSYS_OPT_MEDFORD */ 839e948693eSPhilip Paeps 84095812f27SAndrew Rybchenko default: 84195812f27SAndrew Rybchenko rc = EINVAL; 84295812f27SAndrew Rybchenko goto fail1; 84395812f27SAndrew Rybchenko } 84495812f27SAndrew Rybchenko 845e948693eSPhilip Paeps EFSYS_ASSERT(type != EFX_MAC_INVALID); 846e948693eSPhilip Paeps EFSYS_ASSERT3U(type, <, EFX_MAC_NTYPES); 847e948693eSPhilip Paeps EFSYS_ASSERT(emop != NULL); 848e948693eSPhilip Paeps 84995812f27SAndrew Rybchenko epp->ep_emop = emop; 850e948693eSPhilip Paeps epp->ep_mac_type = type; 851e948693eSPhilip Paeps 852e948693eSPhilip Paeps return (0); 853e948693eSPhilip Paeps 854e948693eSPhilip Paeps fail1: 855460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 856e948693eSPhilip Paeps 857e948693eSPhilip Paeps return (rc); 858e948693eSPhilip Paeps } 8593c838a9fSAndrew Rybchenko 8603c838a9fSAndrew Rybchenko 861e75412c9SAndrew Rybchenko #if EFSYS_OPT_SIENA 8623c838a9fSAndrew Rybchenko 86374bb0ed8SAndrew Rybchenko #define EFX_MAC_HASH_BITS (1 << 8) 86474bb0ed8SAndrew Rybchenko 8653c838a9fSAndrew Rybchenko /* Compute the multicast hash as used on Falcon and Siena. */ 8663c838a9fSAndrew Rybchenko static void 8675cab4fc7SAndrew Rybchenko siena_mac_multicast_hash_compute( 8683c838a9fSAndrew Rybchenko __in_ecount(6*count) uint8_t const *addrs, 8693c838a9fSAndrew Rybchenko __in int count, 8703c838a9fSAndrew Rybchenko __out efx_oword_t *hash_low, 8713c838a9fSAndrew Rybchenko __out efx_oword_t *hash_high) 8723c838a9fSAndrew Rybchenko { 8733c838a9fSAndrew Rybchenko uint32_t crc, index; 8743c838a9fSAndrew Rybchenko int i; 8753c838a9fSAndrew Rybchenko 8763c838a9fSAndrew Rybchenko EFSYS_ASSERT(hash_low != NULL); 8773c838a9fSAndrew Rybchenko EFSYS_ASSERT(hash_high != NULL); 8783c838a9fSAndrew Rybchenko 8793c838a9fSAndrew Rybchenko EFX_ZERO_OWORD(*hash_low); 8803c838a9fSAndrew Rybchenko EFX_ZERO_OWORD(*hash_high); 8813c838a9fSAndrew Rybchenko 8823c838a9fSAndrew Rybchenko for (i = 0; i < count; i++) { 8833c838a9fSAndrew Rybchenko /* Calculate hash bucket (IEEE 802.3 CRC32 of the MAC addr) */ 8843c838a9fSAndrew Rybchenko crc = efx_crc32_calculate(0xffffffff, addrs, EFX_MAC_ADDR_LEN); 8853c838a9fSAndrew Rybchenko index = crc % EFX_MAC_HASH_BITS; 8863c838a9fSAndrew Rybchenko if (index < 128) { 8873c838a9fSAndrew Rybchenko EFX_SET_OWORD_BIT(*hash_low, index); 8883c838a9fSAndrew Rybchenko } else { 8893c838a9fSAndrew Rybchenko EFX_SET_OWORD_BIT(*hash_high, index - 128); 8903c838a9fSAndrew Rybchenko } 8913c838a9fSAndrew Rybchenko 8923c838a9fSAndrew Rybchenko addrs += EFX_MAC_ADDR_LEN; 8933c838a9fSAndrew Rybchenko } 8943c838a9fSAndrew Rybchenko } 8953c838a9fSAndrew Rybchenko 896460cb568SAndrew Rybchenko static __checkReturn efx_rc_t 8975cab4fc7SAndrew Rybchenko siena_mac_multicast_list_set( 8983c838a9fSAndrew Rybchenko __in efx_nic_t *enp) 8993c838a9fSAndrew Rybchenko { 9003c838a9fSAndrew Rybchenko efx_port_t *epp = &(enp->en_port); 901ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop; 9023c838a9fSAndrew Rybchenko efx_oword_t old_hash[2]; 903460cb568SAndrew Rybchenko efx_rc_t rc; 9043c838a9fSAndrew Rybchenko 9053c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 9063c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); 9073c838a9fSAndrew Rybchenko 9083c838a9fSAndrew Rybchenko memcpy(old_hash, epp->ep_multicst_hash, sizeof (old_hash)); 9093c838a9fSAndrew Rybchenko 9105cab4fc7SAndrew Rybchenko siena_mac_multicast_hash_compute( 9115cab4fc7SAndrew Rybchenko epp->ep_mulcst_addr_list, 9123c838a9fSAndrew Rybchenko epp->ep_mulcst_addr_count, 9133c838a9fSAndrew Rybchenko &epp->ep_multicst_hash[0], 9143c838a9fSAndrew Rybchenko &epp->ep_multicst_hash[1]); 9153c838a9fSAndrew Rybchenko 9163c838a9fSAndrew Rybchenko if ((rc = emop->emo_reconfigure(enp)) != 0) 9173c838a9fSAndrew Rybchenko goto fail1; 9183c838a9fSAndrew Rybchenko 9193c838a9fSAndrew Rybchenko return (0); 9203c838a9fSAndrew Rybchenko 9213c838a9fSAndrew Rybchenko fail1: 922460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 9233c838a9fSAndrew Rybchenko 9243c838a9fSAndrew Rybchenko memcpy(epp->ep_multicst_hash, old_hash, sizeof (old_hash)); 9253c838a9fSAndrew Rybchenko 9263c838a9fSAndrew Rybchenko return (rc); 9273c838a9fSAndrew Rybchenko } 9283c838a9fSAndrew Rybchenko 929e75412c9SAndrew Rybchenko #endif /* EFSYS_OPT_SIENA */ 930