1*49ef7e06SGarrett D'Amore /* 2*49ef7e06SGarrett D'Amore * Copyright (c) 2007-2015 Solarflare Communications Inc. 3*49ef7e06SGarrett D'Amore * All rights reserved. 4*49ef7e06SGarrett D'Amore * 5*49ef7e06SGarrett D'Amore * Redistribution and use in source and binary forms, with or without 6*49ef7e06SGarrett D'Amore * modification, are permitted provided that the following conditions are met: 7*49ef7e06SGarrett D'Amore * 8*49ef7e06SGarrett D'Amore * 1. Redistributions of source code must retain the above copyright notice, 9*49ef7e06SGarrett D'Amore * this list of conditions and the following disclaimer. 10*49ef7e06SGarrett D'Amore * 2. Redistributions in binary form must reproduce the above copyright notice, 11*49ef7e06SGarrett D'Amore * this list of conditions and the following disclaimer in the documentation 12*49ef7e06SGarrett D'Amore * and/or other materials provided with the distribution. 13*49ef7e06SGarrett D'Amore * 14*49ef7e06SGarrett D'Amore * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15*49ef7e06SGarrett D'Amore * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16*49ef7e06SGarrett D'Amore * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17*49ef7e06SGarrett D'Amore * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 18*49ef7e06SGarrett D'Amore * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19*49ef7e06SGarrett D'Amore * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20*49ef7e06SGarrett D'Amore * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21*49ef7e06SGarrett D'Amore * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22*49ef7e06SGarrett D'Amore * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23*49ef7e06SGarrett D'Amore * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 24*49ef7e06SGarrett D'Amore * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25*49ef7e06SGarrett D'Amore * 26*49ef7e06SGarrett D'Amore * The views and conclusions contained in the software and documentation are 27*49ef7e06SGarrett D'Amore * those of the authors and should not be interpreted as representing official 28*49ef7e06SGarrett D'Amore * policies, either expressed or implied, of the FreeBSD Project. 29*49ef7e06SGarrett D'Amore */ 30*49ef7e06SGarrett D'Amore 31*49ef7e06SGarrett D'Amore #include "efx.h" 32*49ef7e06SGarrett D'Amore #include "efx_impl.h" 33*49ef7e06SGarrett D'Amore #if EFSYS_OPT_MON_MCDI 34*49ef7e06SGarrett D'Amore #include "mcdi_mon.h" 35*49ef7e06SGarrett D'Amore #endif 36*49ef7e06SGarrett D'Amore 37*49ef7e06SGarrett D'Amore #if EFSYS_OPT_QSTATS 38*49ef7e06SGarrett D'Amore #define EFX_EV_QSTAT_INCR(_eep, _stat) \ 39*49ef7e06SGarrett D'Amore do { \ 40*49ef7e06SGarrett D'Amore (_eep)->ee_stat[_stat]++; \ 41*49ef7e06SGarrett D'Amore _NOTE(CONSTANTCONDITION) \ 42*49ef7e06SGarrett D'Amore } while (B_FALSE) 43*49ef7e06SGarrett D'Amore #else 44*49ef7e06SGarrett D'Amore #define EFX_EV_QSTAT_INCR(_eep, _stat) 45*49ef7e06SGarrett D'Amore #endif 46*49ef7e06SGarrett D'Amore 47*49ef7e06SGarrett D'Amore #define EFX_EV_PRESENT(_qword) \ 48*49ef7e06SGarrett D'Amore (EFX_QWORD_FIELD((_qword), EFX_DWORD_0) != 0xffffffff && \ 49*49ef7e06SGarrett D'Amore EFX_QWORD_FIELD((_qword), EFX_DWORD_1) != 0xffffffff) 50*49ef7e06SGarrett D'Amore 51*49ef7e06SGarrett D'Amore 52*49ef7e06SGarrett D'Amore 53*49ef7e06SGarrett D'Amore #if EFSYS_OPT_SIENA 54*49ef7e06SGarrett D'Amore 55*49ef7e06SGarrett D'Amore static __checkReturn efx_rc_t 56*49ef7e06SGarrett D'Amore siena_ev_init( 57*49ef7e06SGarrett D'Amore __in efx_nic_t *enp); 58*49ef7e06SGarrett D'Amore 59*49ef7e06SGarrett D'Amore static void 60*49ef7e06SGarrett D'Amore siena_ev_fini( 61*49ef7e06SGarrett D'Amore __in efx_nic_t *enp); 62*49ef7e06SGarrett D'Amore 63*49ef7e06SGarrett D'Amore static __checkReturn efx_rc_t 64*49ef7e06SGarrett D'Amore siena_ev_qcreate( 65*49ef7e06SGarrett D'Amore __in efx_nic_t *enp, 66*49ef7e06SGarrett D'Amore __in unsigned int index, 67*49ef7e06SGarrett D'Amore __in efsys_mem_t *esmp, 68*49ef7e06SGarrett D'Amore __in size_t n, 69*49ef7e06SGarrett D'Amore __in uint32_t id, 70*49ef7e06SGarrett D'Amore __in efx_evq_t *eep); 71*49ef7e06SGarrett D'Amore 72*49ef7e06SGarrett D'Amore static void 73*49ef7e06SGarrett D'Amore siena_ev_qdestroy( 74*49ef7e06SGarrett D'Amore __in efx_evq_t *eep); 75*49ef7e06SGarrett D'Amore 76*49ef7e06SGarrett D'Amore static __checkReturn efx_rc_t 77*49ef7e06SGarrett D'Amore siena_ev_qprime( 78*49ef7e06SGarrett D'Amore __in efx_evq_t *eep, 79*49ef7e06SGarrett D'Amore __in unsigned int count); 80*49ef7e06SGarrett D'Amore 81*49ef7e06SGarrett D'Amore static void 82*49ef7e06SGarrett D'Amore siena_ev_qpoll( 83*49ef7e06SGarrett D'Amore __in efx_evq_t *eep, 84*49ef7e06SGarrett D'Amore __inout unsigned int *countp, 85*49ef7e06SGarrett D'Amore __in const efx_ev_callbacks_t *eecp, 86*49ef7e06SGarrett D'Amore __in_opt void *arg); 87*49ef7e06SGarrett D'Amore 88*49ef7e06SGarrett D'Amore static void 89*49ef7e06SGarrett D'Amore siena_ev_qpost( 90*49ef7e06SGarrett D'Amore __in efx_evq_t *eep, 91*49ef7e06SGarrett D'Amore __in uint16_t data); 92*49ef7e06SGarrett D'Amore 93*49ef7e06SGarrett D'Amore static __checkReturn efx_rc_t 94*49ef7e06SGarrett D'Amore siena_ev_qmoderate( 95*49ef7e06SGarrett D'Amore __in efx_evq_t *eep, 96*49ef7e06SGarrett D'Amore __in unsigned int us); 97*49ef7e06SGarrett D'Amore 98*49ef7e06SGarrett D'Amore #if EFSYS_OPT_QSTATS 99*49ef7e06SGarrett D'Amore static void 100*49ef7e06SGarrett D'Amore siena_ev_qstats_update( 101*49ef7e06SGarrett D'Amore __in efx_evq_t *eep, 102*49ef7e06SGarrett D'Amore __inout_ecount(EV_NQSTATS) efsys_stat_t *stat); 103*49ef7e06SGarrett D'Amore 104*49ef7e06SGarrett D'Amore #endif 105*49ef7e06SGarrett D'Amore 106*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_SIENA */ 107*49ef7e06SGarrett D'Amore 108*49ef7e06SGarrett D'Amore #if EFSYS_OPT_SIENA 109*49ef7e06SGarrett D'Amore static const efx_ev_ops_t __efx_ev_siena_ops = { 110*49ef7e06SGarrett D'Amore siena_ev_init, /* eevo_init */ 111*49ef7e06SGarrett D'Amore siena_ev_fini, /* eevo_fini */ 112*49ef7e06SGarrett D'Amore siena_ev_qcreate, /* eevo_qcreate */ 113*49ef7e06SGarrett D'Amore siena_ev_qdestroy, /* eevo_qdestroy */ 114*49ef7e06SGarrett D'Amore siena_ev_qprime, /* eevo_qprime */ 115*49ef7e06SGarrett D'Amore siena_ev_qpost, /* eevo_qpost */ 116*49ef7e06SGarrett D'Amore siena_ev_qmoderate, /* eevo_qmoderate */ 117*49ef7e06SGarrett D'Amore #if EFSYS_OPT_QSTATS 118*49ef7e06SGarrett D'Amore siena_ev_qstats_update, /* eevo_qstats_update */ 119*49ef7e06SGarrett D'Amore #endif 120*49ef7e06SGarrett D'Amore }; 121*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_SIENA */ 122*49ef7e06SGarrett D'Amore 123*49ef7e06SGarrett D'Amore #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD 124*49ef7e06SGarrett D'Amore static const efx_ev_ops_t __efx_ev_ef10_ops = { 125*49ef7e06SGarrett D'Amore ef10_ev_init, /* eevo_init */ 126*49ef7e06SGarrett D'Amore ef10_ev_fini, /* eevo_fini */ 127*49ef7e06SGarrett D'Amore ef10_ev_qcreate, /* eevo_qcreate */ 128*49ef7e06SGarrett D'Amore ef10_ev_qdestroy, /* eevo_qdestroy */ 129*49ef7e06SGarrett D'Amore ef10_ev_qprime, /* eevo_qprime */ 130*49ef7e06SGarrett D'Amore ef10_ev_qpost, /* eevo_qpost */ 131*49ef7e06SGarrett D'Amore ef10_ev_qmoderate, /* eevo_qmoderate */ 132*49ef7e06SGarrett D'Amore #if EFSYS_OPT_QSTATS 133*49ef7e06SGarrett D'Amore ef10_ev_qstats_update, /* eevo_qstats_update */ 134*49ef7e06SGarrett D'Amore #endif 135*49ef7e06SGarrett D'Amore }; 136*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */ 137*49ef7e06SGarrett D'Amore 138*49ef7e06SGarrett D'Amore 139*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t 140*49ef7e06SGarrett D'Amore efx_ev_init( 141*49ef7e06SGarrett D'Amore __in efx_nic_t *enp) 142*49ef7e06SGarrett D'Amore { 143*49ef7e06SGarrett D'Amore const efx_ev_ops_t *eevop; 144*49ef7e06SGarrett D'Amore efx_rc_t rc; 145*49ef7e06SGarrett D'Amore 146*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 147*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR); 148*49ef7e06SGarrett D'Amore 149*49ef7e06SGarrett D'Amore if (enp->en_mod_flags & EFX_MOD_EV) { 150*49ef7e06SGarrett D'Amore rc = EINVAL; 151*49ef7e06SGarrett D'Amore goto fail1; 152*49ef7e06SGarrett D'Amore } 153*49ef7e06SGarrett D'Amore 154*49ef7e06SGarrett D'Amore switch (enp->en_family) { 155*49ef7e06SGarrett D'Amore #if EFSYS_OPT_SIENA 156*49ef7e06SGarrett D'Amore case EFX_FAMILY_SIENA: 157*49ef7e06SGarrett D'Amore eevop = &__efx_ev_siena_ops; 158*49ef7e06SGarrett D'Amore break; 159*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_SIENA */ 160*49ef7e06SGarrett D'Amore 161*49ef7e06SGarrett D'Amore #if EFSYS_OPT_HUNTINGTON 162*49ef7e06SGarrett D'Amore case EFX_FAMILY_HUNTINGTON: 163*49ef7e06SGarrett D'Amore eevop = &__efx_ev_ef10_ops; 164*49ef7e06SGarrett D'Amore break; 165*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_HUNTINGTON */ 166*49ef7e06SGarrett D'Amore 167*49ef7e06SGarrett D'Amore #if EFSYS_OPT_MEDFORD 168*49ef7e06SGarrett D'Amore case EFX_FAMILY_MEDFORD: 169*49ef7e06SGarrett D'Amore eevop = &__efx_ev_ef10_ops; 170*49ef7e06SGarrett D'Amore break; 171*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_MEDFORD */ 172*49ef7e06SGarrett D'Amore 173*49ef7e06SGarrett D'Amore default: 174*49ef7e06SGarrett D'Amore EFSYS_ASSERT(0); 175*49ef7e06SGarrett D'Amore rc = ENOTSUP; 176*49ef7e06SGarrett D'Amore goto fail1; 177*49ef7e06SGarrett D'Amore } 178*49ef7e06SGarrett D'Amore 179*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_ev_qcount, ==, 0); 180*49ef7e06SGarrett D'Amore 181*49ef7e06SGarrett D'Amore if ((rc = eevop->eevo_init(enp)) != 0) 182*49ef7e06SGarrett D'Amore goto fail2; 183*49ef7e06SGarrett D'Amore 184*49ef7e06SGarrett D'Amore enp->en_eevop = eevop; 185*49ef7e06SGarrett D'Amore enp->en_mod_flags |= EFX_MOD_EV; 186*49ef7e06SGarrett D'Amore return (0); 187*49ef7e06SGarrett D'Amore 188*49ef7e06SGarrett D'Amore fail2: 189*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail2); 190*49ef7e06SGarrett D'Amore 191*49ef7e06SGarrett D'Amore fail1: 192*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc); 193*49ef7e06SGarrett D'Amore 194*49ef7e06SGarrett D'Amore enp->en_eevop = NULL; 195*49ef7e06SGarrett D'Amore enp->en_mod_flags &= ~EFX_MOD_EV; 196*49ef7e06SGarrett D'Amore return (rc); 197*49ef7e06SGarrett D'Amore } 198*49ef7e06SGarrett D'Amore 199*49ef7e06SGarrett D'Amore void 200*49ef7e06SGarrett D'Amore efx_ev_fini( 201*49ef7e06SGarrett D'Amore __in efx_nic_t *enp) 202*49ef7e06SGarrett D'Amore { 203*49ef7e06SGarrett D'Amore const efx_ev_ops_t *eevop = enp->en_eevop; 204*49ef7e06SGarrett D'Amore 205*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 206*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR); 207*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_EV); 208*49ef7e06SGarrett D'Amore EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX)); 209*49ef7e06SGarrett D'Amore EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX)); 210*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_ev_qcount, ==, 0); 211*49ef7e06SGarrett D'Amore 212*49ef7e06SGarrett D'Amore eevop->eevo_fini(enp); 213*49ef7e06SGarrett D'Amore 214*49ef7e06SGarrett D'Amore enp->en_eevop = NULL; 215*49ef7e06SGarrett D'Amore enp->en_mod_flags &= ~EFX_MOD_EV; 216*49ef7e06SGarrett D'Amore } 217*49ef7e06SGarrett D'Amore 218*49ef7e06SGarrett D'Amore 219*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t 220*49ef7e06SGarrett D'Amore efx_ev_qcreate( 221*49ef7e06SGarrett D'Amore __in efx_nic_t *enp, 222*49ef7e06SGarrett D'Amore __in unsigned int index, 223*49ef7e06SGarrett D'Amore __in efsys_mem_t *esmp, 224*49ef7e06SGarrett D'Amore __in size_t n, 225*49ef7e06SGarrett D'Amore __in uint32_t id, 226*49ef7e06SGarrett D'Amore __deref_out efx_evq_t **eepp) 227*49ef7e06SGarrett D'Amore { 228*49ef7e06SGarrett D'Amore const efx_ev_ops_t *eevop = enp->en_eevop; 229*49ef7e06SGarrett D'Amore efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 230*49ef7e06SGarrett D'Amore efx_evq_t *eep; 231*49ef7e06SGarrett D'Amore efx_rc_t rc; 232*49ef7e06SGarrett D'Amore 233*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 234*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_EV); 235*49ef7e06SGarrett D'Amore 236*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_ev_qcount + 1, <, encp->enc_evq_limit); 237*49ef7e06SGarrett D'Amore 238*49ef7e06SGarrett D'Amore /* Allocate an EVQ object */ 239*49ef7e06SGarrett D'Amore EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (efx_evq_t), eep); 240*49ef7e06SGarrett D'Amore if (eep == NULL) { 241*49ef7e06SGarrett D'Amore rc = ENOMEM; 242*49ef7e06SGarrett D'Amore goto fail1; 243*49ef7e06SGarrett D'Amore } 244*49ef7e06SGarrett D'Amore 245*49ef7e06SGarrett D'Amore eep->ee_magic = EFX_EVQ_MAGIC; 246*49ef7e06SGarrett D'Amore eep->ee_enp = enp; 247*49ef7e06SGarrett D'Amore eep->ee_index = index; 248*49ef7e06SGarrett D'Amore eep->ee_mask = n - 1; 249*49ef7e06SGarrett D'Amore eep->ee_esmp = esmp; 250*49ef7e06SGarrett D'Amore 251*49ef7e06SGarrett D'Amore if ((rc = eevop->eevo_qcreate(enp, index, esmp, n, id, eep)) != 0) 252*49ef7e06SGarrett D'Amore goto fail2; 253*49ef7e06SGarrett D'Amore 254*49ef7e06SGarrett D'Amore enp->en_ev_qcount++; 255*49ef7e06SGarrett D'Amore *eepp = eep; 256*49ef7e06SGarrett D'Amore 257*49ef7e06SGarrett D'Amore return (0); 258*49ef7e06SGarrett D'Amore 259*49ef7e06SGarrett D'Amore fail2: 260*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail2); 261*49ef7e06SGarrett D'Amore EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_evq_t), eep); 262*49ef7e06SGarrett D'Amore fail1: 263*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc); 264*49ef7e06SGarrett D'Amore return (rc); 265*49ef7e06SGarrett D'Amore } 266*49ef7e06SGarrett D'Amore 267*49ef7e06SGarrett D'Amore void 268*49ef7e06SGarrett D'Amore efx_ev_qdestroy( 269*49ef7e06SGarrett D'Amore __in efx_evq_t *eep) 270*49ef7e06SGarrett D'Amore { 271*49ef7e06SGarrett D'Amore efx_nic_t *enp = eep->ee_enp; 272*49ef7e06SGarrett D'Amore const efx_ev_ops_t *eevop = enp->en_eevop; 273*49ef7e06SGarrett D'Amore 274*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC); 275*49ef7e06SGarrett D'Amore 276*49ef7e06SGarrett D'Amore EFSYS_ASSERT(enp->en_ev_qcount != 0); 277*49ef7e06SGarrett D'Amore --enp->en_ev_qcount; 278*49ef7e06SGarrett D'Amore 279*49ef7e06SGarrett D'Amore eevop->eevo_qdestroy(eep); 280*49ef7e06SGarrett D'Amore 281*49ef7e06SGarrett D'Amore /* Free the EVQ object */ 282*49ef7e06SGarrett D'Amore EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_evq_t), eep); 283*49ef7e06SGarrett D'Amore } 284*49ef7e06SGarrett D'Amore 285*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t 286*49ef7e06SGarrett D'Amore efx_ev_qprime( 287*49ef7e06SGarrett D'Amore __in efx_evq_t *eep, 288*49ef7e06SGarrett D'Amore __in unsigned int count) 289*49ef7e06SGarrett D'Amore { 290*49ef7e06SGarrett D'Amore efx_nic_t *enp = eep->ee_enp; 291*49ef7e06SGarrett D'Amore const efx_ev_ops_t *eevop = enp->en_eevop; 292*49ef7e06SGarrett D'Amore efx_rc_t rc; 293*49ef7e06SGarrett D'Amore 294*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC); 295*49ef7e06SGarrett D'Amore 296*49ef7e06SGarrett D'Amore if (!(enp->en_mod_flags & EFX_MOD_INTR)) { 297*49ef7e06SGarrett D'Amore rc = EINVAL; 298*49ef7e06SGarrett D'Amore goto fail1; 299*49ef7e06SGarrett D'Amore } 300*49ef7e06SGarrett D'Amore 301*49ef7e06SGarrett D'Amore if ((rc = eevop->eevo_qprime(eep, count)) != 0) 302*49ef7e06SGarrett D'Amore goto fail2; 303*49ef7e06SGarrett D'Amore 304*49ef7e06SGarrett D'Amore return (0); 305*49ef7e06SGarrett D'Amore 306*49ef7e06SGarrett D'Amore fail2: 307*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail2); 308*49ef7e06SGarrett D'Amore fail1: 309*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc); 310*49ef7e06SGarrett D'Amore return (rc); 311*49ef7e06SGarrett D'Amore } 312*49ef7e06SGarrett D'Amore 313*49ef7e06SGarrett D'Amore __checkReturn boolean_t 314*49ef7e06SGarrett D'Amore efx_ev_qpending( 315*49ef7e06SGarrett D'Amore __in efx_evq_t *eep, 316*49ef7e06SGarrett D'Amore __in unsigned int count) 317*49ef7e06SGarrett D'Amore { 318*49ef7e06SGarrett D'Amore size_t offset; 319*49ef7e06SGarrett D'Amore efx_qword_t qword; 320*49ef7e06SGarrett D'Amore 321*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC); 322*49ef7e06SGarrett D'Amore 323*49ef7e06SGarrett D'Amore offset = (count & eep->ee_mask) * sizeof (efx_qword_t); 324*49ef7e06SGarrett D'Amore EFSYS_MEM_READQ(eep->ee_esmp, offset, &qword); 325*49ef7e06SGarrett D'Amore 326*49ef7e06SGarrett D'Amore return (EFX_EV_PRESENT(qword)); 327*49ef7e06SGarrett D'Amore } 328*49ef7e06SGarrett D'Amore 329*49ef7e06SGarrett D'Amore #if EFSYS_OPT_EV_PREFETCH 330*49ef7e06SGarrett D'Amore 331*49ef7e06SGarrett D'Amore void 332*49ef7e06SGarrett D'Amore efx_ev_qprefetch( 333*49ef7e06SGarrett D'Amore __in efx_evq_t *eep, 334*49ef7e06SGarrett D'Amore __in unsigned int count) 335*49ef7e06SGarrett D'Amore { 336*49ef7e06SGarrett D'Amore efx_nic_t *enp = eep->ee_enp; 337*49ef7e06SGarrett D'Amore unsigned int offset; 338*49ef7e06SGarrett D'Amore 339*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC); 340*49ef7e06SGarrett D'Amore 341*49ef7e06SGarrett D'Amore offset = (count & eep->ee_mask) * sizeof (efx_qword_t); 342*49ef7e06SGarrett D'Amore EFSYS_MEM_PREFETCH(eep->ee_esmp, offset); 343*49ef7e06SGarrett D'Amore } 344*49ef7e06SGarrett D'Amore 345*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_EV_PREFETCH */ 346*49ef7e06SGarrett D'Amore 347*49ef7e06SGarrett D'Amore void 348*49ef7e06SGarrett D'Amore efx_ev_qpoll( 349*49ef7e06SGarrett D'Amore __in efx_evq_t *eep, 350*49ef7e06SGarrett D'Amore __inout unsigned int *countp, 351*49ef7e06SGarrett D'Amore __in const efx_ev_callbacks_t *eecp, 352*49ef7e06SGarrett D'Amore __in_opt void *arg) 353*49ef7e06SGarrett D'Amore { 354*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC); 355*49ef7e06SGarrett D'Amore 356*49ef7e06SGarrett D'Amore /* 357*49ef7e06SGarrett D'Amore * FIXME: Huntington will require support for hardware event batching 358*49ef7e06SGarrett D'Amore * and merging, which will need a different ev_qpoll implementation. 359*49ef7e06SGarrett D'Amore * 360*49ef7e06SGarrett D'Amore * Without those features the Falcon/Siena code can be used unchanged. 361*49ef7e06SGarrett D'Amore */ 362*49ef7e06SGarrett D'Amore EFX_STATIC_ASSERT(ESF_DZ_EV_CODE_LBN == FSF_AZ_EV_CODE_LBN); 363*49ef7e06SGarrett D'Amore EFX_STATIC_ASSERT(ESF_DZ_EV_CODE_WIDTH == FSF_AZ_EV_CODE_WIDTH); 364*49ef7e06SGarrett D'Amore 365*49ef7e06SGarrett D'Amore EFX_STATIC_ASSERT(ESE_DZ_EV_CODE_RX_EV == FSE_AZ_EV_CODE_RX_EV); 366*49ef7e06SGarrett D'Amore EFX_STATIC_ASSERT(ESE_DZ_EV_CODE_TX_EV == FSE_AZ_EV_CODE_TX_EV); 367*49ef7e06SGarrett D'Amore EFX_STATIC_ASSERT(ESE_DZ_EV_CODE_DRIVER_EV == FSE_AZ_EV_CODE_DRIVER_EV); 368*49ef7e06SGarrett D'Amore EFX_STATIC_ASSERT(ESE_DZ_EV_CODE_DRV_GEN_EV == 369*49ef7e06SGarrett D'Amore FSE_AZ_EV_CODE_DRV_GEN_EV); 370*49ef7e06SGarrett D'Amore #if EFSYS_OPT_MCDI 371*49ef7e06SGarrett D'Amore EFX_STATIC_ASSERT(ESE_DZ_EV_CODE_MCDI_EV == 372*49ef7e06SGarrett D'Amore FSE_AZ_EV_CODE_MCDI_EVRESPONSE); 373*49ef7e06SGarrett D'Amore #endif 374*49ef7e06SGarrett D'Amore siena_ev_qpoll(eep, countp, eecp, arg); 375*49ef7e06SGarrett D'Amore } 376*49ef7e06SGarrett D'Amore 377*49ef7e06SGarrett D'Amore void 378*49ef7e06SGarrett D'Amore efx_ev_qpost( 379*49ef7e06SGarrett D'Amore __in efx_evq_t *eep, 380*49ef7e06SGarrett D'Amore __in uint16_t data) 381*49ef7e06SGarrett D'Amore { 382*49ef7e06SGarrett D'Amore efx_nic_t *enp = eep->ee_enp; 383*49ef7e06SGarrett D'Amore const efx_ev_ops_t *eevop = enp->en_eevop; 384*49ef7e06SGarrett D'Amore 385*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC); 386*49ef7e06SGarrett D'Amore 387*49ef7e06SGarrett D'Amore EFSYS_ASSERT(eevop != NULL && 388*49ef7e06SGarrett D'Amore eevop->eevo_qpost != NULL); 389*49ef7e06SGarrett D'Amore 390*49ef7e06SGarrett D'Amore eevop->eevo_qpost(eep, data); 391*49ef7e06SGarrett D'Amore } 392*49ef7e06SGarrett D'Amore 393*49ef7e06SGarrett D'Amore __checkReturn efx_rc_t 394*49ef7e06SGarrett D'Amore efx_ev_qmoderate( 395*49ef7e06SGarrett D'Amore __in efx_evq_t *eep, 396*49ef7e06SGarrett D'Amore __in unsigned int us) 397*49ef7e06SGarrett D'Amore { 398*49ef7e06SGarrett D'Amore efx_nic_t *enp = eep->ee_enp; 399*49ef7e06SGarrett D'Amore const efx_ev_ops_t *eevop = enp->en_eevop; 400*49ef7e06SGarrett D'Amore efx_rc_t rc; 401*49ef7e06SGarrett D'Amore 402*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC); 403*49ef7e06SGarrett D'Amore 404*49ef7e06SGarrett D'Amore if ((rc = eevop->eevo_qmoderate(eep, us)) != 0) 405*49ef7e06SGarrett D'Amore goto fail1; 406*49ef7e06SGarrett D'Amore 407*49ef7e06SGarrett D'Amore return (0); 408*49ef7e06SGarrett D'Amore 409*49ef7e06SGarrett D'Amore fail1: 410*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc); 411*49ef7e06SGarrett D'Amore return (rc); 412*49ef7e06SGarrett D'Amore } 413*49ef7e06SGarrett D'Amore 414*49ef7e06SGarrett D'Amore #if EFSYS_OPT_QSTATS 415*49ef7e06SGarrett D'Amore void 416*49ef7e06SGarrett D'Amore efx_ev_qstats_update( 417*49ef7e06SGarrett D'Amore __in efx_evq_t *eep, 418*49ef7e06SGarrett D'Amore __inout_ecount(EV_NQSTATS) efsys_stat_t *stat) 419*49ef7e06SGarrett D'Amore 420*49ef7e06SGarrett D'Amore { efx_nic_t *enp = eep->ee_enp; 421*49ef7e06SGarrett D'Amore const efx_ev_ops_t *eevop = enp->en_eevop; 422*49ef7e06SGarrett D'Amore 423*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC); 424*49ef7e06SGarrett D'Amore 425*49ef7e06SGarrett D'Amore eevop->eevo_qstats_update(eep, stat); 426*49ef7e06SGarrett D'Amore } 427*49ef7e06SGarrett D'Amore 428*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_QSTATS */ 429*49ef7e06SGarrett D'Amore 430*49ef7e06SGarrett D'Amore #if EFSYS_OPT_SIENA 431*49ef7e06SGarrett D'Amore 432*49ef7e06SGarrett D'Amore static __checkReturn efx_rc_t 433*49ef7e06SGarrett D'Amore siena_ev_init( 434*49ef7e06SGarrett D'Amore __in efx_nic_t *enp) 435*49ef7e06SGarrett D'Amore { 436*49ef7e06SGarrett D'Amore efx_oword_t oword; 437*49ef7e06SGarrett D'Amore 438*49ef7e06SGarrett D'Amore /* 439*49ef7e06SGarrett D'Amore * Program the event queue for receive and transmit queue 440*49ef7e06SGarrett D'Amore * flush events. 441*49ef7e06SGarrett D'Amore */ 442*49ef7e06SGarrett D'Amore EFX_BAR_READO(enp, FR_AZ_DP_CTRL_REG, &oword); 443*49ef7e06SGarrett D'Amore EFX_SET_OWORD_FIELD(oword, FRF_AZ_FLS_EVQ_ID, 0); 444*49ef7e06SGarrett D'Amore EFX_BAR_WRITEO(enp, FR_AZ_DP_CTRL_REG, &oword); 445*49ef7e06SGarrett D'Amore 446*49ef7e06SGarrett D'Amore return (0); 447*49ef7e06SGarrett D'Amore 448*49ef7e06SGarrett D'Amore } 449*49ef7e06SGarrett D'Amore 450*49ef7e06SGarrett D'Amore static __checkReturn boolean_t 451*49ef7e06SGarrett D'Amore siena_ev_rx_not_ok( 452*49ef7e06SGarrett D'Amore __in efx_evq_t *eep, 453*49ef7e06SGarrett D'Amore __in efx_qword_t *eqp, 454*49ef7e06SGarrett D'Amore __in uint32_t label, 455*49ef7e06SGarrett D'Amore __in uint32_t id, 456*49ef7e06SGarrett D'Amore __inout uint16_t *flagsp) 457*49ef7e06SGarrett D'Amore { 458*49ef7e06SGarrett D'Amore boolean_t ignore = B_FALSE; 459*49ef7e06SGarrett D'Amore 460*49ef7e06SGarrett D'Amore if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_TOBE_DISC) != 0) { 461*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX_TOBE_DISC); 462*49ef7e06SGarrett D'Amore EFSYS_PROBE(tobe_disc); 463*49ef7e06SGarrett D'Amore /* 464*49ef7e06SGarrett D'Amore * Assume this is a unicast address mismatch, unless below 465*49ef7e06SGarrett D'Amore * we find either FSF_AZ_RX_EV_ETH_CRC_ERR or 466*49ef7e06SGarrett D'Amore * EV_RX_PAUSE_FRM_ERR is set. 467*49ef7e06SGarrett D'Amore */ 468*49ef7e06SGarrett D'Amore (*flagsp) |= EFX_ADDR_MISMATCH; 469*49ef7e06SGarrett D'Amore } 470*49ef7e06SGarrett D'Amore 471*49ef7e06SGarrett D'Amore if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_FRM_TRUNC) != 0) { 472*49ef7e06SGarrett D'Amore EFSYS_PROBE2(frm_trunc, uint32_t, label, uint32_t, id); 473*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX_FRM_TRUNC); 474*49ef7e06SGarrett D'Amore (*flagsp) |= EFX_DISCARD; 475*49ef7e06SGarrett D'Amore 476*49ef7e06SGarrett D'Amore #if EFSYS_OPT_RX_SCATTER 477*49ef7e06SGarrett D'Amore /* 478*49ef7e06SGarrett D'Amore * Lookout for payload queue ran dry errors and ignore them. 479*49ef7e06SGarrett D'Amore * 480*49ef7e06SGarrett D'Amore * Sadly for the header/data split cases, the descriptor 481*49ef7e06SGarrett D'Amore * pointer in this event refers to the header queue and 482*49ef7e06SGarrett D'Amore * therefore cannot be easily detected as duplicate. 483*49ef7e06SGarrett D'Amore * So we drop these and rely on the receive processing seeing 484*49ef7e06SGarrett D'Amore * a subsequent packet with FSF_AZ_RX_EV_SOP set to discard 485*49ef7e06SGarrett D'Amore * the partially received packet. 486*49ef7e06SGarrett D'Amore */ 487*49ef7e06SGarrett D'Amore if ((EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_SOP) == 0) && 488*49ef7e06SGarrett D'Amore (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_JUMBO_CONT) == 0) && 489*49ef7e06SGarrett D'Amore (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_BYTE_CNT) == 0)) 490*49ef7e06SGarrett D'Amore ignore = B_TRUE; 491*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_RX_SCATTER */ 492*49ef7e06SGarrett D'Amore } 493*49ef7e06SGarrett D'Amore 494*49ef7e06SGarrett D'Amore if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_ETH_CRC_ERR) != 0) { 495*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX_ETH_CRC_ERR); 496*49ef7e06SGarrett D'Amore EFSYS_PROBE(crc_err); 497*49ef7e06SGarrett D'Amore (*flagsp) &= ~EFX_ADDR_MISMATCH; 498*49ef7e06SGarrett D'Amore (*flagsp) |= EFX_DISCARD; 499*49ef7e06SGarrett D'Amore } 500*49ef7e06SGarrett D'Amore 501*49ef7e06SGarrett D'Amore if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_PAUSE_FRM_ERR) != 0) { 502*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX_PAUSE_FRM_ERR); 503*49ef7e06SGarrett D'Amore EFSYS_PROBE(pause_frm_err); 504*49ef7e06SGarrett D'Amore (*flagsp) &= ~EFX_ADDR_MISMATCH; 505*49ef7e06SGarrett D'Amore (*flagsp) |= EFX_DISCARD; 506*49ef7e06SGarrett D'Amore } 507*49ef7e06SGarrett D'Amore 508*49ef7e06SGarrett D'Amore if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_BUF_OWNER_ID_ERR) != 0) { 509*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX_BUF_OWNER_ID_ERR); 510*49ef7e06SGarrett D'Amore EFSYS_PROBE(owner_id_err); 511*49ef7e06SGarrett D'Amore (*flagsp) |= EFX_DISCARD; 512*49ef7e06SGarrett D'Amore } 513*49ef7e06SGarrett D'Amore 514*49ef7e06SGarrett D'Amore if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_IP_HDR_CHKSUM_ERR) != 0) { 515*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX_IPV4_HDR_CHKSUM_ERR); 516*49ef7e06SGarrett D'Amore EFSYS_PROBE(ipv4_err); 517*49ef7e06SGarrett D'Amore (*flagsp) &= ~EFX_CKSUM_IPV4; 518*49ef7e06SGarrett D'Amore } 519*49ef7e06SGarrett D'Amore 520*49ef7e06SGarrett D'Amore if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_TCP_UDP_CHKSUM_ERR) != 0) { 521*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX_TCP_UDP_CHKSUM_ERR); 522*49ef7e06SGarrett D'Amore EFSYS_PROBE(udp_chk_err); 523*49ef7e06SGarrett D'Amore (*flagsp) &= ~EFX_CKSUM_TCPUDP; 524*49ef7e06SGarrett D'Amore } 525*49ef7e06SGarrett D'Amore 526*49ef7e06SGarrett D'Amore if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_IP_FRAG_ERR) != 0) { 527*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX_IP_FRAG_ERR); 528*49ef7e06SGarrett D'Amore 529*49ef7e06SGarrett D'Amore /* 530*49ef7e06SGarrett D'Amore * If IP is fragmented FSF_AZ_RX_EV_IP_FRAG_ERR is set. This 531*49ef7e06SGarrett D'Amore * causes FSF_AZ_RX_EV_PKT_OK to be clear. This is not an error 532*49ef7e06SGarrett D'Amore * condition. 533*49ef7e06SGarrett D'Amore */ 534*49ef7e06SGarrett D'Amore (*flagsp) &= ~(EFX_PKT_TCP | EFX_PKT_UDP | EFX_CKSUM_TCPUDP); 535*49ef7e06SGarrett D'Amore } 536*49ef7e06SGarrett D'Amore 537*49ef7e06SGarrett D'Amore return (ignore); 538*49ef7e06SGarrett D'Amore } 539*49ef7e06SGarrett D'Amore 540*49ef7e06SGarrett D'Amore static __checkReturn boolean_t 541*49ef7e06SGarrett D'Amore siena_ev_rx( 542*49ef7e06SGarrett D'Amore __in efx_evq_t *eep, 543*49ef7e06SGarrett D'Amore __in efx_qword_t *eqp, 544*49ef7e06SGarrett D'Amore __in const efx_ev_callbacks_t *eecp, 545*49ef7e06SGarrett D'Amore __in_opt void *arg) 546*49ef7e06SGarrett D'Amore { 547*49ef7e06SGarrett D'Amore uint32_t id; 548*49ef7e06SGarrett D'Amore uint32_t size; 549*49ef7e06SGarrett D'Amore uint32_t label; 550*49ef7e06SGarrett D'Amore boolean_t ok; 551*49ef7e06SGarrett D'Amore #if EFSYS_OPT_RX_SCATTER 552*49ef7e06SGarrett D'Amore boolean_t sop; 553*49ef7e06SGarrett D'Amore boolean_t jumbo_cont; 554*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_RX_SCATTER */ 555*49ef7e06SGarrett D'Amore uint32_t hdr_type; 556*49ef7e06SGarrett D'Amore boolean_t is_v6; 557*49ef7e06SGarrett D'Amore uint16_t flags; 558*49ef7e06SGarrett D'Amore boolean_t ignore; 559*49ef7e06SGarrett D'Amore boolean_t should_abort; 560*49ef7e06SGarrett D'Amore 561*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX); 562*49ef7e06SGarrett D'Amore 563*49ef7e06SGarrett D'Amore /* Basic packet information */ 564*49ef7e06SGarrett D'Amore id = EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_DESC_PTR); 565*49ef7e06SGarrett D'Amore size = EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_BYTE_CNT); 566*49ef7e06SGarrett D'Amore label = EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_Q_LABEL); 567*49ef7e06SGarrett D'Amore ok = (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_PKT_OK) != 0); 568*49ef7e06SGarrett D'Amore 569*49ef7e06SGarrett D'Amore #if EFSYS_OPT_RX_SCATTER 570*49ef7e06SGarrett D'Amore sop = (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_SOP) != 0); 571*49ef7e06SGarrett D'Amore jumbo_cont = (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_JUMBO_CONT) != 0); 572*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_RX_SCATTER */ 573*49ef7e06SGarrett D'Amore 574*49ef7e06SGarrett D'Amore hdr_type = EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_HDR_TYPE); 575*49ef7e06SGarrett D'Amore 576*49ef7e06SGarrett D'Amore is_v6 = (EFX_QWORD_FIELD(*eqp, FSF_CZ_RX_EV_IPV6_PKT) != 0); 577*49ef7e06SGarrett D'Amore 578*49ef7e06SGarrett D'Amore /* 579*49ef7e06SGarrett D'Amore * If packet is marked as OK and packet type is TCP/IP or 580*49ef7e06SGarrett D'Amore * UDP/IP or other IP, then we can rely on the hardware checksums. 581*49ef7e06SGarrett D'Amore */ 582*49ef7e06SGarrett D'Amore switch (hdr_type) { 583*49ef7e06SGarrett D'Amore case FSE_AZ_RX_EV_HDR_TYPE_IPV4V6_TCP: 584*49ef7e06SGarrett D'Amore flags = EFX_PKT_TCP | EFX_CKSUM_TCPUDP; 585*49ef7e06SGarrett D'Amore if (is_v6) { 586*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX_TCP_IPV6); 587*49ef7e06SGarrett D'Amore flags |= EFX_PKT_IPV6; 588*49ef7e06SGarrett D'Amore } else { 589*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX_TCP_IPV4); 590*49ef7e06SGarrett D'Amore flags |= EFX_PKT_IPV4 | EFX_CKSUM_IPV4; 591*49ef7e06SGarrett D'Amore } 592*49ef7e06SGarrett D'Amore break; 593*49ef7e06SGarrett D'Amore 594*49ef7e06SGarrett D'Amore case FSE_AZ_RX_EV_HDR_TYPE_IPV4V6_UDP: 595*49ef7e06SGarrett D'Amore flags = EFX_PKT_UDP | EFX_CKSUM_TCPUDP; 596*49ef7e06SGarrett D'Amore if (is_v6) { 597*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX_UDP_IPV6); 598*49ef7e06SGarrett D'Amore flags |= EFX_PKT_IPV6; 599*49ef7e06SGarrett D'Amore } else { 600*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX_UDP_IPV4); 601*49ef7e06SGarrett D'Amore flags |= EFX_PKT_IPV4 | EFX_CKSUM_IPV4; 602*49ef7e06SGarrett D'Amore } 603*49ef7e06SGarrett D'Amore break; 604*49ef7e06SGarrett D'Amore 605*49ef7e06SGarrett D'Amore case FSE_AZ_RX_EV_HDR_TYPE_IPV4V6_OTHER: 606*49ef7e06SGarrett D'Amore if (is_v6) { 607*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX_OTHER_IPV6); 608*49ef7e06SGarrett D'Amore flags = EFX_PKT_IPV6; 609*49ef7e06SGarrett D'Amore } else { 610*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX_OTHER_IPV4); 611*49ef7e06SGarrett D'Amore flags = EFX_PKT_IPV4 | EFX_CKSUM_IPV4; 612*49ef7e06SGarrett D'Amore } 613*49ef7e06SGarrett D'Amore break; 614*49ef7e06SGarrett D'Amore 615*49ef7e06SGarrett D'Amore case FSE_AZ_RX_EV_HDR_TYPE_OTHER: 616*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX_NON_IP); 617*49ef7e06SGarrett D'Amore flags = 0; 618*49ef7e06SGarrett D'Amore break; 619*49ef7e06SGarrett D'Amore 620*49ef7e06SGarrett D'Amore default: 621*49ef7e06SGarrett D'Amore EFSYS_ASSERT(B_FALSE); 622*49ef7e06SGarrett D'Amore flags = 0; 623*49ef7e06SGarrett D'Amore break; 624*49ef7e06SGarrett D'Amore } 625*49ef7e06SGarrett D'Amore 626*49ef7e06SGarrett D'Amore #if EFSYS_OPT_RX_SCATTER 627*49ef7e06SGarrett D'Amore /* Report scatter and header/lookahead split buffer flags */ 628*49ef7e06SGarrett D'Amore if (sop) 629*49ef7e06SGarrett D'Amore flags |= EFX_PKT_START; 630*49ef7e06SGarrett D'Amore if (jumbo_cont) 631*49ef7e06SGarrett D'Amore flags |= EFX_PKT_CONT; 632*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_RX_SCATTER */ 633*49ef7e06SGarrett D'Amore 634*49ef7e06SGarrett D'Amore /* Detect errors included in the FSF_AZ_RX_EV_PKT_OK indication */ 635*49ef7e06SGarrett D'Amore if (!ok) { 636*49ef7e06SGarrett D'Amore ignore = siena_ev_rx_not_ok(eep, eqp, label, id, &flags); 637*49ef7e06SGarrett D'Amore if (ignore) { 638*49ef7e06SGarrett D'Amore EFSYS_PROBE4(rx_complete, uint32_t, label, uint32_t, id, 639*49ef7e06SGarrett D'Amore uint32_t, size, uint16_t, flags); 640*49ef7e06SGarrett D'Amore 641*49ef7e06SGarrett D'Amore return (B_FALSE); 642*49ef7e06SGarrett D'Amore } 643*49ef7e06SGarrett D'Amore } 644*49ef7e06SGarrett D'Amore 645*49ef7e06SGarrett D'Amore /* If we're not discarding the packet then it is ok */ 646*49ef7e06SGarrett D'Amore if (~flags & EFX_DISCARD) 647*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX_OK); 648*49ef7e06SGarrett D'Amore 649*49ef7e06SGarrett D'Amore /* Detect multicast packets that didn't match the filter */ 650*49ef7e06SGarrett D'Amore if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_MCAST_PKT) != 0) { 651*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX_MCAST_PKT); 652*49ef7e06SGarrett D'Amore 653*49ef7e06SGarrett D'Amore if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_MCAST_HASH_MATCH) != 0) { 654*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_RX_MCAST_HASH_MATCH); 655*49ef7e06SGarrett D'Amore } else { 656*49ef7e06SGarrett D'Amore EFSYS_PROBE(mcast_mismatch); 657*49ef7e06SGarrett D'Amore flags |= EFX_ADDR_MISMATCH; 658*49ef7e06SGarrett D'Amore } 659*49ef7e06SGarrett D'Amore } else { 660*49ef7e06SGarrett D'Amore flags |= EFX_PKT_UNICAST; 661*49ef7e06SGarrett D'Amore } 662*49ef7e06SGarrett D'Amore 663*49ef7e06SGarrett D'Amore /* 664*49ef7e06SGarrett D'Amore * The packet parser in Siena can abort parsing packets under 665*49ef7e06SGarrett D'Amore * certain error conditions, setting the PKT_NOT_PARSED bit 666*49ef7e06SGarrett D'Amore * (which clears PKT_OK). If this is set, then don't trust 667*49ef7e06SGarrett D'Amore * the PKT_TYPE field. 668*49ef7e06SGarrett D'Amore */ 669*49ef7e06SGarrett D'Amore if (!ok) { 670*49ef7e06SGarrett D'Amore uint32_t parse_err; 671*49ef7e06SGarrett D'Amore 672*49ef7e06SGarrett D'Amore parse_err = EFX_QWORD_FIELD(*eqp, FSF_CZ_RX_EV_PKT_NOT_PARSED); 673*49ef7e06SGarrett D'Amore if (parse_err != 0) 674*49ef7e06SGarrett D'Amore flags |= EFX_CHECK_VLAN; 675*49ef7e06SGarrett D'Amore } 676*49ef7e06SGarrett D'Amore 677*49ef7e06SGarrett D'Amore if (~flags & EFX_CHECK_VLAN) { 678*49ef7e06SGarrett D'Amore uint32_t pkt_type; 679*49ef7e06SGarrett D'Amore 680*49ef7e06SGarrett D'Amore pkt_type = EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_PKT_TYPE); 681*49ef7e06SGarrett D'Amore if (pkt_type >= FSE_AZ_RX_EV_PKT_TYPE_VLAN) 682*49ef7e06SGarrett D'Amore flags |= EFX_PKT_VLAN_TAGGED; 683*49ef7e06SGarrett D'Amore } 684*49ef7e06SGarrett D'Amore 685*49ef7e06SGarrett D'Amore EFSYS_PROBE4(rx_complete, uint32_t, label, uint32_t, id, 686*49ef7e06SGarrett D'Amore uint32_t, size, uint16_t, flags); 687*49ef7e06SGarrett D'Amore 688*49ef7e06SGarrett D'Amore EFSYS_ASSERT(eecp->eec_rx != NULL); 689*49ef7e06SGarrett D'Amore should_abort = eecp->eec_rx(arg, label, id, size, flags); 690*49ef7e06SGarrett D'Amore 691*49ef7e06SGarrett D'Amore return (should_abort); 692*49ef7e06SGarrett D'Amore } 693*49ef7e06SGarrett D'Amore 694*49ef7e06SGarrett D'Amore static __checkReturn boolean_t 695*49ef7e06SGarrett D'Amore siena_ev_tx( 696*49ef7e06SGarrett D'Amore __in efx_evq_t *eep, 697*49ef7e06SGarrett D'Amore __in efx_qword_t *eqp, 698*49ef7e06SGarrett D'Amore __in const efx_ev_callbacks_t *eecp, 699*49ef7e06SGarrett D'Amore __in_opt void *arg) 700*49ef7e06SGarrett D'Amore { 701*49ef7e06SGarrett D'Amore uint32_t id; 702*49ef7e06SGarrett D'Amore uint32_t label; 703*49ef7e06SGarrett D'Amore boolean_t should_abort; 704*49ef7e06SGarrett D'Amore 705*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_TX); 706*49ef7e06SGarrett D'Amore 707*49ef7e06SGarrett D'Amore if (EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_COMP) != 0 && 708*49ef7e06SGarrett D'Amore EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_PKT_ERR) == 0 && 709*49ef7e06SGarrett D'Amore EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_PKT_TOO_BIG) == 0 && 710*49ef7e06SGarrett D'Amore EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_WQ_FF_FULL) == 0) { 711*49ef7e06SGarrett D'Amore 712*49ef7e06SGarrett D'Amore id = EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_DESC_PTR); 713*49ef7e06SGarrett D'Amore label = EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_Q_LABEL); 714*49ef7e06SGarrett D'Amore 715*49ef7e06SGarrett D'Amore EFSYS_PROBE2(tx_complete, uint32_t, label, uint32_t, id); 716*49ef7e06SGarrett D'Amore 717*49ef7e06SGarrett D'Amore EFSYS_ASSERT(eecp->eec_tx != NULL); 718*49ef7e06SGarrett D'Amore should_abort = eecp->eec_tx(arg, label, id); 719*49ef7e06SGarrett D'Amore 720*49ef7e06SGarrett D'Amore return (should_abort); 721*49ef7e06SGarrett D'Amore } 722*49ef7e06SGarrett D'Amore 723*49ef7e06SGarrett D'Amore if (EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_COMP) != 0) 724*49ef7e06SGarrett D'Amore EFSYS_PROBE3(bad_event, unsigned int, eep->ee_index, 725*49ef7e06SGarrett D'Amore uint32_t, EFX_QWORD_FIELD(*eqp, EFX_DWORD_1), 726*49ef7e06SGarrett D'Amore uint32_t, EFX_QWORD_FIELD(*eqp, EFX_DWORD_0)); 727*49ef7e06SGarrett D'Amore 728*49ef7e06SGarrett D'Amore if (EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_PKT_ERR) != 0) 729*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_TX_PKT_ERR); 730*49ef7e06SGarrett D'Amore 731*49ef7e06SGarrett D'Amore if (EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_PKT_TOO_BIG) != 0) 732*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_TX_PKT_TOO_BIG); 733*49ef7e06SGarrett D'Amore 734*49ef7e06SGarrett D'Amore if (EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_WQ_FF_FULL) != 0) 735*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_TX_WQ_FF_FULL); 736*49ef7e06SGarrett D'Amore 737*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_TX_UNEXPECTED); 738*49ef7e06SGarrett D'Amore return (B_FALSE); 739*49ef7e06SGarrett D'Amore } 740*49ef7e06SGarrett D'Amore 741*49ef7e06SGarrett D'Amore static __checkReturn boolean_t 742*49ef7e06SGarrett D'Amore siena_ev_global( 743*49ef7e06SGarrett D'Amore __in efx_evq_t *eep, 744*49ef7e06SGarrett D'Amore __in efx_qword_t *eqp, 745*49ef7e06SGarrett D'Amore __in const efx_ev_callbacks_t *eecp, 746*49ef7e06SGarrett D'Amore __in_opt void *arg) 747*49ef7e06SGarrett D'Amore { 748*49ef7e06SGarrett D'Amore _NOTE(ARGUNUSED(eqp, eecp, arg)) 749*49ef7e06SGarrett D'Amore 750*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_GLOBAL); 751*49ef7e06SGarrett D'Amore 752*49ef7e06SGarrett D'Amore return (B_FALSE); 753*49ef7e06SGarrett D'Amore } 754*49ef7e06SGarrett D'Amore 755*49ef7e06SGarrett D'Amore static __checkReturn boolean_t 756*49ef7e06SGarrett D'Amore siena_ev_driver( 757*49ef7e06SGarrett D'Amore __in efx_evq_t *eep, 758*49ef7e06SGarrett D'Amore __in efx_qword_t *eqp, 759*49ef7e06SGarrett D'Amore __in const efx_ev_callbacks_t *eecp, 760*49ef7e06SGarrett D'Amore __in_opt void *arg) 761*49ef7e06SGarrett D'Amore { 762*49ef7e06SGarrett D'Amore boolean_t should_abort; 763*49ef7e06SGarrett D'Amore 764*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_DRIVER); 765*49ef7e06SGarrett D'Amore should_abort = B_FALSE; 766*49ef7e06SGarrett D'Amore 767*49ef7e06SGarrett D'Amore switch (EFX_QWORD_FIELD(*eqp, FSF_AZ_DRIVER_EV_SUBCODE)) { 768*49ef7e06SGarrett D'Amore case FSE_AZ_TX_DESCQ_FLS_DONE_EV: { 769*49ef7e06SGarrett D'Amore uint32_t txq_index; 770*49ef7e06SGarrett D'Amore 771*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_DRIVER_TX_DESCQ_FLS_DONE); 772*49ef7e06SGarrett D'Amore 773*49ef7e06SGarrett D'Amore txq_index = EFX_QWORD_FIELD(*eqp, FSF_AZ_DRIVER_EV_SUBDATA); 774*49ef7e06SGarrett D'Amore 775*49ef7e06SGarrett D'Amore EFSYS_PROBE1(tx_descq_fls_done, uint32_t, txq_index); 776*49ef7e06SGarrett D'Amore 777*49ef7e06SGarrett D'Amore EFSYS_ASSERT(eecp->eec_txq_flush_done != NULL); 778*49ef7e06SGarrett D'Amore should_abort = eecp->eec_txq_flush_done(arg, txq_index); 779*49ef7e06SGarrett D'Amore 780*49ef7e06SGarrett D'Amore break; 781*49ef7e06SGarrett D'Amore } 782*49ef7e06SGarrett D'Amore case FSE_AZ_RX_DESCQ_FLS_DONE_EV: { 783*49ef7e06SGarrett D'Amore uint32_t rxq_index; 784*49ef7e06SGarrett D'Amore uint32_t failed; 785*49ef7e06SGarrett D'Amore 786*49ef7e06SGarrett D'Amore rxq_index = EFX_QWORD_FIELD(*eqp, FSF_AZ_DRIVER_EV_RX_DESCQ_ID); 787*49ef7e06SGarrett D'Amore failed = EFX_QWORD_FIELD(*eqp, FSF_AZ_DRIVER_EV_RX_FLUSH_FAIL); 788*49ef7e06SGarrett D'Amore 789*49ef7e06SGarrett D'Amore EFSYS_ASSERT(eecp->eec_rxq_flush_done != NULL); 790*49ef7e06SGarrett D'Amore EFSYS_ASSERT(eecp->eec_rxq_flush_failed != NULL); 791*49ef7e06SGarrett D'Amore 792*49ef7e06SGarrett D'Amore if (failed) { 793*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_DRIVER_RX_DESCQ_FLS_FAILED); 794*49ef7e06SGarrett D'Amore 795*49ef7e06SGarrett D'Amore EFSYS_PROBE1(rx_descq_fls_failed, uint32_t, rxq_index); 796*49ef7e06SGarrett D'Amore 797*49ef7e06SGarrett D'Amore should_abort = eecp->eec_rxq_flush_failed(arg, 798*49ef7e06SGarrett D'Amore rxq_index); 799*49ef7e06SGarrett D'Amore } else { 800*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_DRIVER_RX_DESCQ_FLS_DONE); 801*49ef7e06SGarrett D'Amore 802*49ef7e06SGarrett D'Amore EFSYS_PROBE1(rx_descq_fls_done, uint32_t, rxq_index); 803*49ef7e06SGarrett D'Amore 804*49ef7e06SGarrett D'Amore should_abort = eecp->eec_rxq_flush_done(arg, rxq_index); 805*49ef7e06SGarrett D'Amore } 806*49ef7e06SGarrett D'Amore 807*49ef7e06SGarrett D'Amore break; 808*49ef7e06SGarrett D'Amore } 809*49ef7e06SGarrett D'Amore case FSE_AZ_EVQ_INIT_DONE_EV: 810*49ef7e06SGarrett D'Amore EFSYS_ASSERT(eecp->eec_initialized != NULL); 811*49ef7e06SGarrett D'Amore should_abort = eecp->eec_initialized(arg); 812*49ef7e06SGarrett D'Amore 813*49ef7e06SGarrett D'Amore break; 814*49ef7e06SGarrett D'Amore 815*49ef7e06SGarrett D'Amore case FSE_AZ_EVQ_NOT_EN_EV: 816*49ef7e06SGarrett D'Amore EFSYS_PROBE(evq_not_en); 817*49ef7e06SGarrett D'Amore break; 818*49ef7e06SGarrett D'Amore 819*49ef7e06SGarrett D'Amore case FSE_AZ_SRM_UPD_DONE_EV: { 820*49ef7e06SGarrett D'Amore uint32_t code; 821*49ef7e06SGarrett D'Amore 822*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_DRIVER_SRM_UPD_DONE); 823*49ef7e06SGarrett D'Amore 824*49ef7e06SGarrett D'Amore code = EFX_QWORD_FIELD(*eqp, FSF_AZ_DRIVER_EV_SUBDATA); 825*49ef7e06SGarrett D'Amore 826*49ef7e06SGarrett D'Amore EFSYS_ASSERT(eecp->eec_sram != NULL); 827*49ef7e06SGarrett D'Amore should_abort = eecp->eec_sram(arg, code); 828*49ef7e06SGarrett D'Amore 829*49ef7e06SGarrett D'Amore break; 830*49ef7e06SGarrett D'Amore } 831*49ef7e06SGarrett D'Amore case FSE_AZ_WAKE_UP_EV: { 832*49ef7e06SGarrett D'Amore uint32_t id; 833*49ef7e06SGarrett D'Amore 834*49ef7e06SGarrett D'Amore id = EFX_QWORD_FIELD(*eqp, FSF_AZ_DRIVER_EV_SUBDATA); 835*49ef7e06SGarrett D'Amore 836*49ef7e06SGarrett D'Amore EFSYS_ASSERT(eecp->eec_wake_up != NULL); 837*49ef7e06SGarrett D'Amore should_abort = eecp->eec_wake_up(arg, id); 838*49ef7e06SGarrett D'Amore 839*49ef7e06SGarrett D'Amore break; 840*49ef7e06SGarrett D'Amore } 841*49ef7e06SGarrett D'Amore case FSE_AZ_TX_PKT_NON_TCP_UDP: 842*49ef7e06SGarrett D'Amore EFSYS_PROBE(tx_pkt_non_tcp_udp); 843*49ef7e06SGarrett D'Amore break; 844*49ef7e06SGarrett D'Amore 845*49ef7e06SGarrett D'Amore case FSE_AZ_TIMER_EV: { 846*49ef7e06SGarrett D'Amore uint32_t id; 847*49ef7e06SGarrett D'Amore 848*49ef7e06SGarrett D'Amore id = EFX_QWORD_FIELD(*eqp, FSF_AZ_DRIVER_EV_SUBDATA); 849*49ef7e06SGarrett D'Amore 850*49ef7e06SGarrett D'Amore EFSYS_ASSERT(eecp->eec_timer != NULL); 851*49ef7e06SGarrett D'Amore should_abort = eecp->eec_timer(arg, id); 852*49ef7e06SGarrett D'Amore 853*49ef7e06SGarrett D'Amore break; 854*49ef7e06SGarrett D'Amore } 855*49ef7e06SGarrett D'Amore case FSE_AZ_RX_DSC_ERROR_EV: 856*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_DRIVER_RX_DSC_ERROR); 857*49ef7e06SGarrett D'Amore 858*49ef7e06SGarrett D'Amore EFSYS_PROBE(rx_dsc_error); 859*49ef7e06SGarrett D'Amore 860*49ef7e06SGarrett D'Amore EFSYS_ASSERT(eecp->eec_exception != NULL); 861*49ef7e06SGarrett D'Amore should_abort = eecp->eec_exception(arg, 862*49ef7e06SGarrett D'Amore EFX_EXCEPTION_RX_DSC_ERROR, 0); 863*49ef7e06SGarrett D'Amore 864*49ef7e06SGarrett D'Amore break; 865*49ef7e06SGarrett D'Amore 866*49ef7e06SGarrett D'Amore case FSE_AZ_TX_DSC_ERROR_EV: 867*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_DRIVER_TX_DSC_ERROR); 868*49ef7e06SGarrett D'Amore 869*49ef7e06SGarrett D'Amore EFSYS_PROBE(tx_dsc_error); 870*49ef7e06SGarrett D'Amore 871*49ef7e06SGarrett D'Amore EFSYS_ASSERT(eecp->eec_exception != NULL); 872*49ef7e06SGarrett D'Amore should_abort = eecp->eec_exception(arg, 873*49ef7e06SGarrett D'Amore EFX_EXCEPTION_TX_DSC_ERROR, 0); 874*49ef7e06SGarrett D'Amore 875*49ef7e06SGarrett D'Amore break; 876*49ef7e06SGarrett D'Amore 877*49ef7e06SGarrett D'Amore default: 878*49ef7e06SGarrett D'Amore break; 879*49ef7e06SGarrett D'Amore } 880*49ef7e06SGarrett D'Amore 881*49ef7e06SGarrett D'Amore return (should_abort); 882*49ef7e06SGarrett D'Amore } 883*49ef7e06SGarrett D'Amore 884*49ef7e06SGarrett D'Amore static __checkReturn boolean_t 885*49ef7e06SGarrett D'Amore siena_ev_drv_gen( 886*49ef7e06SGarrett D'Amore __in efx_evq_t *eep, 887*49ef7e06SGarrett D'Amore __in efx_qword_t *eqp, 888*49ef7e06SGarrett D'Amore __in const efx_ev_callbacks_t *eecp, 889*49ef7e06SGarrett D'Amore __in_opt void *arg) 890*49ef7e06SGarrett D'Amore { 891*49ef7e06SGarrett D'Amore uint32_t data; 892*49ef7e06SGarrett D'Amore boolean_t should_abort; 893*49ef7e06SGarrett D'Amore 894*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_DRV_GEN); 895*49ef7e06SGarrett D'Amore 896*49ef7e06SGarrett D'Amore data = EFX_QWORD_FIELD(*eqp, FSF_AZ_EV_DATA_DW0); 897*49ef7e06SGarrett D'Amore if (data >= ((uint32_t)1 << 16)) { 898*49ef7e06SGarrett D'Amore EFSYS_PROBE3(bad_event, unsigned int, eep->ee_index, 899*49ef7e06SGarrett D'Amore uint32_t, EFX_QWORD_FIELD(*eqp, EFX_DWORD_1), 900*49ef7e06SGarrett D'Amore uint32_t, EFX_QWORD_FIELD(*eqp, EFX_DWORD_0)); 901*49ef7e06SGarrett D'Amore return (B_TRUE); 902*49ef7e06SGarrett D'Amore } 903*49ef7e06SGarrett D'Amore 904*49ef7e06SGarrett D'Amore EFSYS_ASSERT(eecp->eec_software != NULL); 905*49ef7e06SGarrett D'Amore should_abort = eecp->eec_software(arg, (uint16_t)data); 906*49ef7e06SGarrett D'Amore 907*49ef7e06SGarrett D'Amore return (should_abort); 908*49ef7e06SGarrett D'Amore } 909*49ef7e06SGarrett D'Amore 910*49ef7e06SGarrett D'Amore #if EFSYS_OPT_MCDI 911*49ef7e06SGarrett D'Amore 912*49ef7e06SGarrett D'Amore static __checkReturn boolean_t 913*49ef7e06SGarrett D'Amore siena_ev_mcdi( 914*49ef7e06SGarrett D'Amore __in efx_evq_t *eep, 915*49ef7e06SGarrett D'Amore __in efx_qword_t *eqp, 916*49ef7e06SGarrett D'Amore __in const efx_ev_callbacks_t *eecp, 917*49ef7e06SGarrett D'Amore __in_opt void *arg) 918*49ef7e06SGarrett D'Amore { 919*49ef7e06SGarrett D'Amore efx_nic_t *enp = eep->ee_enp; 920*49ef7e06SGarrett D'Amore unsigned code; 921*49ef7e06SGarrett D'Amore boolean_t should_abort = B_FALSE; 922*49ef7e06SGarrett D'Amore 923*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA); 924*49ef7e06SGarrett D'Amore 925*49ef7e06SGarrett D'Amore if (enp->en_family != EFX_FAMILY_SIENA) 926*49ef7e06SGarrett D'Amore goto out; 927*49ef7e06SGarrett D'Amore 928*49ef7e06SGarrett D'Amore EFSYS_ASSERT(eecp->eec_link_change != NULL); 929*49ef7e06SGarrett D'Amore EFSYS_ASSERT(eecp->eec_exception != NULL); 930*49ef7e06SGarrett D'Amore #if EFSYS_OPT_MON_STATS 931*49ef7e06SGarrett D'Amore EFSYS_ASSERT(eecp->eec_monitor != NULL); 932*49ef7e06SGarrett D'Amore #endif 933*49ef7e06SGarrett D'Amore 934*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_MCDI_RESPONSE); 935*49ef7e06SGarrett D'Amore 936*49ef7e06SGarrett D'Amore code = EFX_QWORD_FIELD(*eqp, MCDI_EVENT_CODE); 937*49ef7e06SGarrett D'Amore switch (code) { 938*49ef7e06SGarrett D'Amore case MCDI_EVENT_CODE_BADSSERT: 939*49ef7e06SGarrett D'Amore efx_mcdi_ev_death(enp, EINTR); 940*49ef7e06SGarrett D'Amore break; 941*49ef7e06SGarrett D'Amore 942*49ef7e06SGarrett D'Amore case MCDI_EVENT_CODE_CMDDONE: 943*49ef7e06SGarrett D'Amore efx_mcdi_ev_cpl(enp, 944*49ef7e06SGarrett D'Amore MCDI_EV_FIELD(eqp, CMDDONE_SEQ), 945*49ef7e06SGarrett D'Amore MCDI_EV_FIELD(eqp, CMDDONE_DATALEN), 946*49ef7e06SGarrett D'Amore MCDI_EV_FIELD(eqp, CMDDONE_ERRNO)); 947*49ef7e06SGarrett D'Amore break; 948*49ef7e06SGarrett D'Amore 949*49ef7e06SGarrett D'Amore case MCDI_EVENT_CODE_LINKCHANGE: { 950*49ef7e06SGarrett D'Amore efx_link_mode_t link_mode; 951*49ef7e06SGarrett D'Amore 952*49ef7e06SGarrett D'Amore siena_phy_link_ev(enp, eqp, &link_mode); 953*49ef7e06SGarrett D'Amore should_abort = eecp->eec_link_change(arg, link_mode); 954*49ef7e06SGarrett D'Amore break; 955*49ef7e06SGarrett D'Amore } 956*49ef7e06SGarrett D'Amore case MCDI_EVENT_CODE_SENSOREVT: { 957*49ef7e06SGarrett D'Amore #if EFSYS_OPT_MON_STATS 958*49ef7e06SGarrett D'Amore efx_mon_stat_t id; 959*49ef7e06SGarrett D'Amore efx_mon_stat_value_t value; 960*49ef7e06SGarrett D'Amore efx_rc_t rc; 961*49ef7e06SGarrett D'Amore 962*49ef7e06SGarrett D'Amore if ((rc = mcdi_mon_ev(enp, eqp, &id, &value)) == 0) 963*49ef7e06SGarrett D'Amore should_abort = eecp->eec_monitor(arg, id, value); 964*49ef7e06SGarrett D'Amore else if (rc == ENOTSUP) { 965*49ef7e06SGarrett D'Amore should_abort = eecp->eec_exception(arg, 966*49ef7e06SGarrett D'Amore EFX_EXCEPTION_UNKNOWN_SENSOREVT, 967*49ef7e06SGarrett D'Amore MCDI_EV_FIELD(eqp, DATA)); 968*49ef7e06SGarrett D'Amore } else 969*49ef7e06SGarrett D'Amore EFSYS_ASSERT(rc == ENODEV); /* Wrong port */ 970*49ef7e06SGarrett D'Amore #else 971*49ef7e06SGarrett D'Amore should_abort = B_FALSE; 972*49ef7e06SGarrett D'Amore #endif 973*49ef7e06SGarrett D'Amore break; 974*49ef7e06SGarrett D'Amore } 975*49ef7e06SGarrett D'Amore case MCDI_EVENT_CODE_SCHEDERR: 976*49ef7e06SGarrett D'Amore /* Informational only */ 977*49ef7e06SGarrett D'Amore break; 978*49ef7e06SGarrett D'Amore 979*49ef7e06SGarrett D'Amore case MCDI_EVENT_CODE_REBOOT: 980*49ef7e06SGarrett D'Amore efx_mcdi_ev_death(enp, EIO); 981*49ef7e06SGarrett D'Amore break; 982*49ef7e06SGarrett D'Amore 983*49ef7e06SGarrett D'Amore case MCDI_EVENT_CODE_MAC_STATS_DMA: 984*49ef7e06SGarrett D'Amore #if EFSYS_OPT_MAC_STATS 985*49ef7e06SGarrett D'Amore if (eecp->eec_mac_stats != NULL) { 986*49ef7e06SGarrett D'Amore eecp->eec_mac_stats(arg, 987*49ef7e06SGarrett D'Amore MCDI_EV_FIELD(eqp, MAC_STATS_DMA_GENERATION)); 988*49ef7e06SGarrett D'Amore } 989*49ef7e06SGarrett D'Amore #endif 990*49ef7e06SGarrett D'Amore break; 991*49ef7e06SGarrett D'Amore 992*49ef7e06SGarrett D'Amore case MCDI_EVENT_CODE_FWALERT: { 993*49ef7e06SGarrett D'Amore uint32_t reason = MCDI_EV_FIELD(eqp, FWALERT_REASON); 994*49ef7e06SGarrett D'Amore 995*49ef7e06SGarrett D'Amore if (reason == MCDI_EVENT_FWALERT_REASON_SRAM_ACCESS) 996*49ef7e06SGarrett D'Amore should_abort = eecp->eec_exception(arg, 997*49ef7e06SGarrett D'Amore EFX_EXCEPTION_FWALERT_SRAM, 998*49ef7e06SGarrett D'Amore MCDI_EV_FIELD(eqp, FWALERT_DATA)); 999*49ef7e06SGarrett D'Amore else 1000*49ef7e06SGarrett D'Amore should_abort = eecp->eec_exception(arg, 1001*49ef7e06SGarrett D'Amore EFX_EXCEPTION_UNKNOWN_FWALERT, 1002*49ef7e06SGarrett D'Amore MCDI_EV_FIELD(eqp, DATA)); 1003*49ef7e06SGarrett D'Amore break; 1004*49ef7e06SGarrett D'Amore } 1005*49ef7e06SGarrett D'Amore 1006*49ef7e06SGarrett D'Amore default: 1007*49ef7e06SGarrett D'Amore EFSYS_PROBE1(mc_pcol_error, int, code); 1008*49ef7e06SGarrett D'Amore break; 1009*49ef7e06SGarrett D'Amore } 1010*49ef7e06SGarrett D'Amore 1011*49ef7e06SGarrett D'Amore out: 1012*49ef7e06SGarrett D'Amore return (should_abort); 1013*49ef7e06SGarrett D'Amore } 1014*49ef7e06SGarrett D'Amore 1015*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_MCDI */ 1016*49ef7e06SGarrett D'Amore 1017*49ef7e06SGarrett D'Amore static __checkReturn efx_rc_t 1018*49ef7e06SGarrett D'Amore siena_ev_qprime( 1019*49ef7e06SGarrett D'Amore __in efx_evq_t *eep, 1020*49ef7e06SGarrett D'Amore __in unsigned int count) 1021*49ef7e06SGarrett D'Amore { 1022*49ef7e06SGarrett D'Amore efx_nic_t *enp = eep->ee_enp; 1023*49ef7e06SGarrett D'Amore uint32_t rptr; 1024*49ef7e06SGarrett D'Amore efx_dword_t dword; 1025*49ef7e06SGarrett D'Amore 1026*49ef7e06SGarrett D'Amore rptr = count & eep->ee_mask; 1027*49ef7e06SGarrett D'Amore 1028*49ef7e06SGarrett D'Amore EFX_POPULATE_DWORD_1(dword, FRF_AZ_EVQ_RPTR, rptr); 1029*49ef7e06SGarrett D'Amore 1030*49ef7e06SGarrett D'Amore EFX_BAR_TBL_WRITED(enp, FR_AZ_EVQ_RPTR_REG, eep->ee_index, 1031*49ef7e06SGarrett D'Amore &dword, B_FALSE); 1032*49ef7e06SGarrett D'Amore 1033*49ef7e06SGarrett D'Amore return (0); 1034*49ef7e06SGarrett D'Amore } 1035*49ef7e06SGarrett D'Amore 1036*49ef7e06SGarrett D'Amore #define EFX_EV_BATCH 8 1037*49ef7e06SGarrett D'Amore 1038*49ef7e06SGarrett D'Amore static void 1039*49ef7e06SGarrett D'Amore siena_ev_qpoll( 1040*49ef7e06SGarrett D'Amore __in efx_evq_t *eep, 1041*49ef7e06SGarrett D'Amore __inout unsigned int *countp, 1042*49ef7e06SGarrett D'Amore __in const efx_ev_callbacks_t *eecp, 1043*49ef7e06SGarrett D'Amore __in_opt void *arg) 1044*49ef7e06SGarrett D'Amore { 1045*49ef7e06SGarrett D'Amore efx_qword_t ev[EFX_EV_BATCH]; 1046*49ef7e06SGarrett D'Amore unsigned int batch; 1047*49ef7e06SGarrett D'Amore unsigned int total; 1048*49ef7e06SGarrett D'Amore unsigned int count; 1049*49ef7e06SGarrett D'Amore unsigned int index; 1050*49ef7e06SGarrett D'Amore size_t offset; 1051*49ef7e06SGarrett D'Amore 1052*49ef7e06SGarrett D'Amore EFSYS_ASSERT(countp != NULL); 1053*49ef7e06SGarrett D'Amore EFSYS_ASSERT(eecp != NULL); 1054*49ef7e06SGarrett D'Amore 1055*49ef7e06SGarrett D'Amore count = *countp; 1056*49ef7e06SGarrett D'Amore do { 1057*49ef7e06SGarrett D'Amore /* Read up until the end of the batch period */ 1058*49ef7e06SGarrett D'Amore batch = EFX_EV_BATCH - (count & (EFX_EV_BATCH - 1)); 1059*49ef7e06SGarrett D'Amore offset = (count & eep->ee_mask) * sizeof (efx_qword_t); 1060*49ef7e06SGarrett D'Amore for (total = 0; total < batch; ++total) { 1061*49ef7e06SGarrett D'Amore EFSYS_MEM_READQ(eep->ee_esmp, offset, &(ev[total])); 1062*49ef7e06SGarrett D'Amore 1063*49ef7e06SGarrett D'Amore if (!EFX_EV_PRESENT(ev[total])) 1064*49ef7e06SGarrett D'Amore break; 1065*49ef7e06SGarrett D'Amore 1066*49ef7e06SGarrett D'Amore EFSYS_PROBE3(event, unsigned int, eep->ee_index, 1067*49ef7e06SGarrett D'Amore uint32_t, EFX_QWORD_FIELD(ev[total], EFX_DWORD_1), 1068*49ef7e06SGarrett D'Amore uint32_t, EFX_QWORD_FIELD(ev[total], EFX_DWORD_0)); 1069*49ef7e06SGarrett D'Amore 1070*49ef7e06SGarrett D'Amore offset += sizeof (efx_qword_t); 1071*49ef7e06SGarrett D'Amore } 1072*49ef7e06SGarrett D'Amore 1073*49ef7e06SGarrett D'Amore #if EFSYS_OPT_EV_PREFETCH && (EFSYS_OPT_EV_PREFETCH_PERIOD > 1) 1074*49ef7e06SGarrett D'Amore /* 1075*49ef7e06SGarrett D'Amore * Prefetch the next batch when we get within PREFETCH_PERIOD 1076*49ef7e06SGarrett D'Amore * of a completed batch. If the batch is smaller, then prefetch 1077*49ef7e06SGarrett D'Amore * immediately. 1078*49ef7e06SGarrett D'Amore */ 1079*49ef7e06SGarrett D'Amore if (total == batch && total < EFSYS_OPT_EV_PREFETCH_PERIOD) 1080*49ef7e06SGarrett D'Amore EFSYS_MEM_PREFETCH(eep->ee_esmp, offset); 1081*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_EV_PREFETCH */ 1082*49ef7e06SGarrett D'Amore 1083*49ef7e06SGarrett D'Amore /* Process the batch of events */ 1084*49ef7e06SGarrett D'Amore for (index = 0; index < total; ++index) { 1085*49ef7e06SGarrett D'Amore boolean_t should_abort; 1086*49ef7e06SGarrett D'Amore uint32_t code; 1087*49ef7e06SGarrett D'Amore 1088*49ef7e06SGarrett D'Amore #if EFSYS_OPT_EV_PREFETCH 1089*49ef7e06SGarrett D'Amore /* Prefetch if we've now reached the batch period */ 1090*49ef7e06SGarrett D'Amore if (total == batch && 1091*49ef7e06SGarrett D'Amore index + EFSYS_OPT_EV_PREFETCH_PERIOD == total) { 1092*49ef7e06SGarrett D'Amore offset = (count + batch) & eep->ee_mask; 1093*49ef7e06SGarrett D'Amore offset *= sizeof (efx_qword_t); 1094*49ef7e06SGarrett D'Amore 1095*49ef7e06SGarrett D'Amore EFSYS_MEM_PREFETCH(eep->ee_esmp, offset); 1096*49ef7e06SGarrett D'Amore } 1097*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_EV_PREFETCH */ 1098*49ef7e06SGarrett D'Amore 1099*49ef7e06SGarrett D'Amore EFX_EV_QSTAT_INCR(eep, EV_ALL); 1100*49ef7e06SGarrett D'Amore 1101*49ef7e06SGarrett D'Amore code = EFX_QWORD_FIELD(ev[index], FSF_AZ_EV_CODE); 1102*49ef7e06SGarrett D'Amore switch (code) { 1103*49ef7e06SGarrett D'Amore case FSE_AZ_EV_CODE_RX_EV: 1104*49ef7e06SGarrett D'Amore should_abort = eep->ee_rx(eep, 1105*49ef7e06SGarrett D'Amore &(ev[index]), eecp, arg); 1106*49ef7e06SGarrett D'Amore break; 1107*49ef7e06SGarrett D'Amore case FSE_AZ_EV_CODE_TX_EV: 1108*49ef7e06SGarrett D'Amore should_abort = eep->ee_tx(eep, 1109*49ef7e06SGarrett D'Amore &(ev[index]), eecp, arg); 1110*49ef7e06SGarrett D'Amore break; 1111*49ef7e06SGarrett D'Amore case FSE_AZ_EV_CODE_DRIVER_EV: 1112*49ef7e06SGarrett D'Amore should_abort = eep->ee_driver(eep, 1113*49ef7e06SGarrett D'Amore &(ev[index]), eecp, arg); 1114*49ef7e06SGarrett D'Amore break; 1115*49ef7e06SGarrett D'Amore case FSE_AZ_EV_CODE_DRV_GEN_EV: 1116*49ef7e06SGarrett D'Amore should_abort = eep->ee_drv_gen(eep, 1117*49ef7e06SGarrett D'Amore &(ev[index]), eecp, arg); 1118*49ef7e06SGarrett D'Amore break; 1119*49ef7e06SGarrett D'Amore #if EFSYS_OPT_MCDI 1120*49ef7e06SGarrett D'Amore case FSE_AZ_EV_CODE_MCDI_EVRESPONSE: 1121*49ef7e06SGarrett D'Amore should_abort = eep->ee_mcdi(eep, 1122*49ef7e06SGarrett D'Amore &(ev[index]), eecp, arg); 1123*49ef7e06SGarrett D'Amore break; 1124*49ef7e06SGarrett D'Amore #endif 1125*49ef7e06SGarrett D'Amore case FSE_AZ_EV_CODE_GLOBAL_EV: 1126*49ef7e06SGarrett D'Amore if (eep->ee_global) { 1127*49ef7e06SGarrett D'Amore should_abort = eep->ee_global(eep, 1128*49ef7e06SGarrett D'Amore &(ev[index]), eecp, arg); 1129*49ef7e06SGarrett D'Amore break; 1130*49ef7e06SGarrett D'Amore } 1131*49ef7e06SGarrett D'Amore /* else fallthrough */ 1132*49ef7e06SGarrett D'Amore default: 1133*49ef7e06SGarrett D'Amore EFSYS_PROBE3(bad_event, 1134*49ef7e06SGarrett D'Amore unsigned int, eep->ee_index, 1135*49ef7e06SGarrett D'Amore uint32_t, 1136*49ef7e06SGarrett D'Amore EFX_QWORD_FIELD(ev[index], EFX_DWORD_1), 1137*49ef7e06SGarrett D'Amore uint32_t, 1138*49ef7e06SGarrett D'Amore EFX_QWORD_FIELD(ev[index], EFX_DWORD_0)); 1139*49ef7e06SGarrett D'Amore 1140*49ef7e06SGarrett D'Amore EFSYS_ASSERT(eecp->eec_exception != NULL); 1141*49ef7e06SGarrett D'Amore (void) eecp->eec_exception(arg, 1142*49ef7e06SGarrett D'Amore EFX_EXCEPTION_EV_ERROR, code); 1143*49ef7e06SGarrett D'Amore should_abort = B_TRUE; 1144*49ef7e06SGarrett D'Amore } 1145*49ef7e06SGarrett D'Amore if (should_abort) { 1146*49ef7e06SGarrett D'Amore /* Ignore subsequent events */ 1147*49ef7e06SGarrett D'Amore total = index + 1; 1148*49ef7e06SGarrett D'Amore break; 1149*49ef7e06SGarrett D'Amore } 1150*49ef7e06SGarrett D'Amore } 1151*49ef7e06SGarrett D'Amore 1152*49ef7e06SGarrett D'Amore /* 1153*49ef7e06SGarrett D'Amore * Now that the hardware has most likely moved onto dma'ing 1154*49ef7e06SGarrett D'Amore * into the next cache line, clear the processed events. Take 1155*49ef7e06SGarrett D'Amore * care to only clear out events that we've processed 1156*49ef7e06SGarrett D'Amore */ 1157*49ef7e06SGarrett D'Amore EFX_SET_QWORD(ev[0]); 1158*49ef7e06SGarrett D'Amore offset = (count & eep->ee_mask) * sizeof (efx_qword_t); 1159*49ef7e06SGarrett D'Amore for (index = 0; index < total; ++index) { 1160*49ef7e06SGarrett D'Amore EFSYS_MEM_WRITEQ(eep->ee_esmp, offset, &(ev[0])); 1161*49ef7e06SGarrett D'Amore offset += sizeof (efx_qword_t); 1162*49ef7e06SGarrett D'Amore } 1163*49ef7e06SGarrett D'Amore 1164*49ef7e06SGarrett D'Amore count += total; 1165*49ef7e06SGarrett D'Amore 1166*49ef7e06SGarrett D'Amore } while (total == batch); 1167*49ef7e06SGarrett D'Amore 1168*49ef7e06SGarrett D'Amore *countp = count; 1169*49ef7e06SGarrett D'Amore } 1170*49ef7e06SGarrett D'Amore 1171*49ef7e06SGarrett D'Amore static void 1172*49ef7e06SGarrett D'Amore siena_ev_qpost( 1173*49ef7e06SGarrett D'Amore __in efx_evq_t *eep, 1174*49ef7e06SGarrett D'Amore __in uint16_t data) 1175*49ef7e06SGarrett D'Amore { 1176*49ef7e06SGarrett D'Amore efx_nic_t *enp = eep->ee_enp; 1177*49ef7e06SGarrett D'Amore efx_qword_t ev; 1178*49ef7e06SGarrett D'Amore efx_oword_t oword; 1179*49ef7e06SGarrett D'Amore 1180*49ef7e06SGarrett D'Amore EFX_POPULATE_QWORD_2(ev, FSF_AZ_EV_CODE, FSE_AZ_EV_CODE_DRV_GEN_EV, 1181*49ef7e06SGarrett D'Amore FSF_AZ_EV_DATA_DW0, (uint32_t)data); 1182*49ef7e06SGarrett D'Amore 1183*49ef7e06SGarrett D'Amore EFX_POPULATE_OWORD_3(oword, FRF_AZ_DRV_EV_QID, eep->ee_index, 1184*49ef7e06SGarrett D'Amore EFX_DWORD_0, EFX_QWORD_FIELD(ev, EFX_DWORD_0), 1185*49ef7e06SGarrett D'Amore EFX_DWORD_1, EFX_QWORD_FIELD(ev, EFX_DWORD_1)); 1186*49ef7e06SGarrett D'Amore 1187*49ef7e06SGarrett D'Amore EFX_BAR_WRITEO(enp, FR_AZ_DRV_EV_REG, &oword); 1188*49ef7e06SGarrett D'Amore } 1189*49ef7e06SGarrett D'Amore 1190*49ef7e06SGarrett D'Amore static __checkReturn efx_rc_t 1191*49ef7e06SGarrett D'Amore siena_ev_qmoderate( 1192*49ef7e06SGarrett D'Amore __in efx_evq_t *eep, 1193*49ef7e06SGarrett D'Amore __in unsigned int us) 1194*49ef7e06SGarrett D'Amore { 1195*49ef7e06SGarrett D'Amore efx_nic_t *enp = eep->ee_enp; 1196*49ef7e06SGarrett D'Amore efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 1197*49ef7e06SGarrett D'Amore unsigned int locked; 1198*49ef7e06SGarrett D'Amore efx_dword_t dword; 1199*49ef7e06SGarrett D'Amore efx_rc_t rc; 1200*49ef7e06SGarrett D'Amore 1201*49ef7e06SGarrett D'Amore if (us > encp->enc_evq_timer_max_us) { 1202*49ef7e06SGarrett D'Amore rc = EINVAL; 1203*49ef7e06SGarrett D'Amore goto fail1; 1204*49ef7e06SGarrett D'Amore } 1205*49ef7e06SGarrett D'Amore 1206*49ef7e06SGarrett D'Amore /* If the value is zero then disable the timer */ 1207*49ef7e06SGarrett D'Amore if (us == 0) { 1208*49ef7e06SGarrett D'Amore EFX_POPULATE_DWORD_2(dword, 1209*49ef7e06SGarrett D'Amore FRF_CZ_TC_TIMER_MODE, FFE_CZ_TIMER_MODE_DIS, 1210*49ef7e06SGarrett D'Amore FRF_CZ_TC_TIMER_VAL, 0); 1211*49ef7e06SGarrett D'Amore } else { 1212*49ef7e06SGarrett D'Amore uint32_t timer_val; 1213*49ef7e06SGarrett D'Amore 1214*49ef7e06SGarrett D'Amore /* Calculate the timer value in quanta */ 1215*49ef7e06SGarrett D'Amore timer_val = us * 1000 / encp->enc_evq_timer_quantum_ns; 1216*49ef7e06SGarrett D'Amore 1217*49ef7e06SGarrett D'Amore /* Moderation value is base 0 so we need to deduct 1 */ 1218*49ef7e06SGarrett D'Amore if (timer_val > 0) 1219*49ef7e06SGarrett D'Amore timer_val--; 1220*49ef7e06SGarrett D'Amore 1221*49ef7e06SGarrett D'Amore EFX_POPULATE_DWORD_2(dword, 1222*49ef7e06SGarrett D'Amore FRF_CZ_TC_TIMER_MODE, FFE_CZ_TIMER_MODE_INT_HLDOFF, 1223*49ef7e06SGarrett D'Amore FRF_CZ_TC_TIMER_VAL, timer_val); 1224*49ef7e06SGarrett D'Amore } 1225*49ef7e06SGarrett D'Amore 1226*49ef7e06SGarrett D'Amore locked = (eep->ee_index == 0) ? 1 : 0; 1227*49ef7e06SGarrett D'Amore 1228*49ef7e06SGarrett D'Amore EFX_BAR_TBL_WRITED(enp, FR_BZ_TIMER_COMMAND_REGP0, 1229*49ef7e06SGarrett D'Amore eep->ee_index, &dword, locked); 1230*49ef7e06SGarrett D'Amore 1231*49ef7e06SGarrett D'Amore return (0); 1232*49ef7e06SGarrett D'Amore 1233*49ef7e06SGarrett D'Amore fail1: 1234*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc); 1235*49ef7e06SGarrett D'Amore 1236*49ef7e06SGarrett D'Amore return (rc); 1237*49ef7e06SGarrett D'Amore } 1238*49ef7e06SGarrett D'Amore 1239*49ef7e06SGarrett D'Amore static __checkReturn efx_rc_t 1240*49ef7e06SGarrett D'Amore siena_ev_qcreate( 1241*49ef7e06SGarrett D'Amore __in efx_nic_t *enp, 1242*49ef7e06SGarrett D'Amore __in unsigned int index, 1243*49ef7e06SGarrett D'Amore __in efsys_mem_t *esmp, 1244*49ef7e06SGarrett D'Amore __in size_t n, 1245*49ef7e06SGarrett D'Amore __in uint32_t id, 1246*49ef7e06SGarrett D'Amore __in efx_evq_t *eep) 1247*49ef7e06SGarrett D'Amore { 1248*49ef7e06SGarrett D'Amore efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 1249*49ef7e06SGarrett D'Amore uint32_t size; 1250*49ef7e06SGarrett D'Amore efx_oword_t oword; 1251*49ef7e06SGarrett D'Amore efx_rc_t rc; 1252*49ef7e06SGarrett D'Amore 1253*49ef7e06SGarrett D'Amore _NOTE(ARGUNUSED(esmp)); 1254*49ef7e06SGarrett D'Amore 1255*49ef7e06SGarrett D'Amore EFX_STATIC_ASSERT(ISP2(EFX_EVQ_MAXNEVS)); 1256*49ef7e06SGarrett D'Amore EFX_STATIC_ASSERT(ISP2(EFX_EVQ_MINNEVS)); 1257*49ef7e06SGarrett D'Amore 1258*49ef7e06SGarrett D'Amore if (!ISP2(n) || (n < EFX_EVQ_MINNEVS) || (n > EFX_EVQ_MAXNEVS)) { 1259*49ef7e06SGarrett D'Amore rc = EINVAL; 1260*49ef7e06SGarrett D'Amore goto fail1; 1261*49ef7e06SGarrett D'Amore } 1262*49ef7e06SGarrett D'Amore if (index >= encp->enc_evq_limit) { 1263*49ef7e06SGarrett D'Amore rc = EINVAL; 1264*49ef7e06SGarrett D'Amore goto fail2; 1265*49ef7e06SGarrett D'Amore } 1266*49ef7e06SGarrett D'Amore #if EFSYS_OPT_RX_SCALE 1267*49ef7e06SGarrett D'Amore if (enp->en_intr.ei_type == EFX_INTR_LINE && 1268*49ef7e06SGarrett D'Amore index >= EFX_MAXRSS_LEGACY) { 1269*49ef7e06SGarrett D'Amore rc = EINVAL; 1270*49ef7e06SGarrett D'Amore goto fail3; 1271*49ef7e06SGarrett D'Amore } 1272*49ef7e06SGarrett D'Amore #endif 1273*49ef7e06SGarrett D'Amore for (size = 0; (1 << size) <= (EFX_EVQ_MAXNEVS / EFX_EVQ_MINNEVS); 1274*49ef7e06SGarrett D'Amore size++) 1275*49ef7e06SGarrett D'Amore if ((1 << size) == (int)(n / EFX_EVQ_MINNEVS)) 1276*49ef7e06SGarrett D'Amore break; 1277*49ef7e06SGarrett D'Amore if (id + (1 << size) >= encp->enc_buftbl_limit) { 1278*49ef7e06SGarrett D'Amore rc = EINVAL; 1279*49ef7e06SGarrett D'Amore goto fail4; 1280*49ef7e06SGarrett D'Amore } 1281*49ef7e06SGarrett D'Amore 1282*49ef7e06SGarrett D'Amore /* Set up the handler table */ 1283*49ef7e06SGarrett D'Amore eep->ee_rx = siena_ev_rx; 1284*49ef7e06SGarrett D'Amore eep->ee_tx = siena_ev_tx; 1285*49ef7e06SGarrett D'Amore eep->ee_driver = siena_ev_driver; 1286*49ef7e06SGarrett D'Amore eep->ee_global = siena_ev_global; 1287*49ef7e06SGarrett D'Amore eep->ee_drv_gen = siena_ev_drv_gen; 1288*49ef7e06SGarrett D'Amore #if EFSYS_OPT_MCDI 1289*49ef7e06SGarrett D'Amore eep->ee_mcdi = siena_ev_mcdi; 1290*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_MCDI */ 1291*49ef7e06SGarrett D'Amore 1292*49ef7e06SGarrett D'Amore /* Set up the new event queue */ 1293*49ef7e06SGarrett D'Amore EFX_POPULATE_OWORD_1(oword, FRF_CZ_TIMER_Q_EN, 1); 1294*49ef7e06SGarrett D'Amore EFX_BAR_TBL_WRITEO(enp, FR_AZ_TIMER_TBL, index, &oword, B_TRUE); 1295*49ef7e06SGarrett D'Amore 1296*49ef7e06SGarrett D'Amore EFX_POPULATE_OWORD_3(oword, FRF_AZ_EVQ_EN, 1, FRF_AZ_EVQ_SIZE, size, 1297*49ef7e06SGarrett D'Amore FRF_AZ_EVQ_BUF_BASE_ID, id); 1298*49ef7e06SGarrett D'Amore 1299*49ef7e06SGarrett D'Amore EFX_BAR_TBL_WRITEO(enp, FR_AZ_EVQ_PTR_TBL, index, &oword, B_TRUE); 1300*49ef7e06SGarrett D'Amore 1301*49ef7e06SGarrett D'Amore return (0); 1302*49ef7e06SGarrett D'Amore 1303*49ef7e06SGarrett D'Amore fail4: 1304*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail4); 1305*49ef7e06SGarrett D'Amore #if EFSYS_OPT_RX_SCALE 1306*49ef7e06SGarrett D'Amore fail3: 1307*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail3); 1308*49ef7e06SGarrett D'Amore #endif 1309*49ef7e06SGarrett D'Amore fail2: 1310*49ef7e06SGarrett D'Amore EFSYS_PROBE(fail2); 1311*49ef7e06SGarrett D'Amore fail1: 1312*49ef7e06SGarrett D'Amore EFSYS_PROBE1(fail1, efx_rc_t, rc); 1313*49ef7e06SGarrett D'Amore 1314*49ef7e06SGarrett D'Amore return (rc); 1315*49ef7e06SGarrett D'Amore } 1316*49ef7e06SGarrett D'Amore 1317*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_SIENA */ 1318*49ef7e06SGarrett D'Amore 1319*49ef7e06SGarrett D'Amore #if EFSYS_OPT_QSTATS 1320*49ef7e06SGarrett D'Amore #if EFSYS_OPT_NAMES 1321*49ef7e06SGarrett D'Amore /* START MKCONFIG GENERATED EfxEventQueueStatNamesBlock b693ddf85aee1bfd */ 1322*49ef7e06SGarrett D'Amore static const char *__efx_ev_qstat_name[] = { 1323*49ef7e06SGarrett D'Amore "all", 1324*49ef7e06SGarrett D'Amore "rx", 1325*49ef7e06SGarrett D'Amore "rx_ok", 1326*49ef7e06SGarrett D'Amore "rx_frm_trunc", 1327*49ef7e06SGarrett D'Amore "rx_tobe_disc", 1328*49ef7e06SGarrett D'Amore "rx_pause_frm_err", 1329*49ef7e06SGarrett D'Amore "rx_buf_owner_id_err", 1330*49ef7e06SGarrett D'Amore "rx_ipv4_hdr_chksum_err", 1331*49ef7e06SGarrett D'Amore "rx_tcp_udp_chksum_err", 1332*49ef7e06SGarrett D'Amore "rx_eth_crc_err", 1333*49ef7e06SGarrett D'Amore "rx_ip_frag_err", 1334*49ef7e06SGarrett D'Amore "rx_mcast_pkt", 1335*49ef7e06SGarrett D'Amore "rx_mcast_hash_match", 1336*49ef7e06SGarrett D'Amore "rx_tcp_ipv4", 1337*49ef7e06SGarrett D'Amore "rx_tcp_ipv6", 1338*49ef7e06SGarrett D'Amore "rx_udp_ipv4", 1339*49ef7e06SGarrett D'Amore "rx_udp_ipv6", 1340*49ef7e06SGarrett D'Amore "rx_other_ipv4", 1341*49ef7e06SGarrett D'Amore "rx_other_ipv6", 1342*49ef7e06SGarrett D'Amore "rx_non_ip", 1343*49ef7e06SGarrett D'Amore "rx_batch", 1344*49ef7e06SGarrett D'Amore "tx", 1345*49ef7e06SGarrett D'Amore "tx_wq_ff_full", 1346*49ef7e06SGarrett D'Amore "tx_pkt_err", 1347*49ef7e06SGarrett D'Amore "tx_pkt_too_big", 1348*49ef7e06SGarrett D'Amore "tx_unexpected", 1349*49ef7e06SGarrett D'Amore "global", 1350*49ef7e06SGarrett D'Amore "global_mnt", 1351*49ef7e06SGarrett D'Amore "driver", 1352*49ef7e06SGarrett D'Amore "driver_srm_upd_done", 1353*49ef7e06SGarrett D'Amore "driver_tx_descq_fls_done", 1354*49ef7e06SGarrett D'Amore "driver_rx_descq_fls_done", 1355*49ef7e06SGarrett D'Amore "driver_rx_descq_fls_failed", 1356*49ef7e06SGarrett D'Amore "driver_rx_dsc_error", 1357*49ef7e06SGarrett D'Amore "driver_tx_dsc_error", 1358*49ef7e06SGarrett D'Amore "drv_gen", 1359*49ef7e06SGarrett D'Amore "mcdi_response", 1360*49ef7e06SGarrett D'Amore }; 1361*49ef7e06SGarrett D'Amore /* END MKCONFIG GENERATED EfxEventQueueStatNamesBlock */ 1362*49ef7e06SGarrett D'Amore 1363*49ef7e06SGarrett D'Amore const char * 1364*49ef7e06SGarrett D'Amore efx_ev_qstat_name( 1365*49ef7e06SGarrett D'Amore __in efx_nic_t *enp, 1366*49ef7e06SGarrett D'Amore __in unsigned int id) 1367*49ef7e06SGarrett D'Amore { 1368*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1369*49ef7e06SGarrett D'Amore EFSYS_ASSERT3U(id, <, EV_NQSTATS); 1370*49ef7e06SGarrett D'Amore 1371*49ef7e06SGarrett D'Amore return (__efx_ev_qstat_name[id]); 1372*49ef7e06SGarrett D'Amore } 1373*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_NAMES */ 1374*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_QSTATS */ 1375*49ef7e06SGarrett D'Amore 1376*49ef7e06SGarrett D'Amore #if EFSYS_OPT_SIENA 1377*49ef7e06SGarrett D'Amore 1378*49ef7e06SGarrett D'Amore #if EFSYS_OPT_QSTATS 1379*49ef7e06SGarrett D'Amore static void 1380*49ef7e06SGarrett D'Amore siena_ev_qstats_update( 1381*49ef7e06SGarrett D'Amore __in efx_evq_t *eep, 1382*49ef7e06SGarrett D'Amore __inout_ecount(EV_NQSTATS) efsys_stat_t *stat) 1383*49ef7e06SGarrett D'Amore { 1384*49ef7e06SGarrett D'Amore unsigned int id; 1385*49ef7e06SGarrett D'Amore 1386*49ef7e06SGarrett D'Amore for (id = 0; id < EV_NQSTATS; id++) { 1387*49ef7e06SGarrett D'Amore efsys_stat_t *essp = &stat[id]; 1388*49ef7e06SGarrett D'Amore 1389*49ef7e06SGarrett D'Amore EFSYS_STAT_INCR(essp, eep->ee_stat[id]); 1390*49ef7e06SGarrett D'Amore eep->ee_stat[id] = 0; 1391*49ef7e06SGarrett D'Amore } 1392*49ef7e06SGarrett D'Amore } 1393*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_QSTATS */ 1394*49ef7e06SGarrett D'Amore 1395*49ef7e06SGarrett D'Amore static void 1396*49ef7e06SGarrett D'Amore siena_ev_qdestroy( 1397*49ef7e06SGarrett D'Amore __in efx_evq_t *eep) 1398*49ef7e06SGarrett D'Amore { 1399*49ef7e06SGarrett D'Amore efx_nic_t *enp = eep->ee_enp; 1400*49ef7e06SGarrett D'Amore efx_oword_t oword; 1401*49ef7e06SGarrett D'Amore 1402*49ef7e06SGarrett D'Amore /* Purge event queue */ 1403*49ef7e06SGarrett D'Amore EFX_ZERO_OWORD(oword); 1404*49ef7e06SGarrett D'Amore 1405*49ef7e06SGarrett D'Amore EFX_BAR_TBL_WRITEO(enp, FR_AZ_EVQ_PTR_TBL, 1406*49ef7e06SGarrett D'Amore eep->ee_index, &oword, B_TRUE); 1407*49ef7e06SGarrett D'Amore 1408*49ef7e06SGarrett D'Amore EFX_ZERO_OWORD(oword); 1409*49ef7e06SGarrett D'Amore EFX_BAR_TBL_WRITEO(enp, FR_AZ_TIMER_TBL, eep->ee_index, &oword, B_TRUE); 1410*49ef7e06SGarrett D'Amore } 1411*49ef7e06SGarrett D'Amore 1412*49ef7e06SGarrett D'Amore static void 1413*49ef7e06SGarrett D'Amore siena_ev_fini( 1414*49ef7e06SGarrett D'Amore __in efx_nic_t *enp) 1415*49ef7e06SGarrett D'Amore { 1416*49ef7e06SGarrett D'Amore _NOTE(ARGUNUSED(enp)) 1417*49ef7e06SGarrett D'Amore } 1418*49ef7e06SGarrett D'Amore 1419*49ef7e06SGarrett D'Amore #endif /* EFSYS_OPT_SIENA */ 1420