15e111ed8SAndrew Rybchenko /* SPDX-License-Identifier: BSD-3-Clause 25e111ed8SAndrew Rybchenko * 35e111ed8SAndrew Rybchenko * Copyright(c) 2019-2020 Xilinx, Inc. 45e111ed8SAndrew Rybchenko * Copyright(c) 2007-2019 Solarflare Communications Inc. 55e111ed8SAndrew Rybchenko */ 65e111ed8SAndrew Rybchenko 75e111ed8SAndrew Rybchenko #include "efx.h" 85e111ed8SAndrew Rybchenko #include "efx_impl.h" 95e111ed8SAndrew Rybchenko #if EFSYS_OPT_MON_MCDI 105e111ed8SAndrew Rybchenko #include "mcdi_mon.h" 115e111ed8SAndrew Rybchenko #endif 125e111ed8SAndrew Rybchenko 135e111ed8SAndrew Rybchenko #define EFX_EV_PRESENT(_qword) \ 145e111ed8SAndrew Rybchenko (EFX_QWORD_FIELD((_qword), EFX_DWORD_0) != 0xffffffff && \ 155e111ed8SAndrew Rybchenko EFX_QWORD_FIELD((_qword), EFX_DWORD_1) != 0xffffffff) 165e111ed8SAndrew Rybchenko 175e111ed8SAndrew Rybchenko 185e111ed8SAndrew Rybchenko 195e111ed8SAndrew Rybchenko #if EFSYS_OPT_SIENA 205e111ed8SAndrew Rybchenko 215e111ed8SAndrew Rybchenko static __checkReturn efx_rc_t 225e111ed8SAndrew Rybchenko siena_ev_init( 235e111ed8SAndrew Rybchenko __in efx_nic_t *enp); 245e111ed8SAndrew Rybchenko 255e111ed8SAndrew Rybchenko static void 265e111ed8SAndrew Rybchenko siena_ev_fini( 275e111ed8SAndrew Rybchenko __in efx_nic_t *enp); 285e111ed8SAndrew Rybchenko 295e111ed8SAndrew Rybchenko static __checkReturn efx_rc_t 305e111ed8SAndrew Rybchenko siena_ev_qcreate( 315e111ed8SAndrew Rybchenko __in efx_nic_t *enp, 325e111ed8SAndrew Rybchenko __in unsigned int index, 335e111ed8SAndrew Rybchenko __in efsys_mem_t *esmp, 345e111ed8SAndrew Rybchenko __in size_t ndescs, 355e111ed8SAndrew Rybchenko __in uint32_t id, 365e111ed8SAndrew Rybchenko __in uint32_t us, 375e111ed8SAndrew Rybchenko __in uint32_t flags, 385e111ed8SAndrew Rybchenko __in efx_evq_t *eep); 395e111ed8SAndrew Rybchenko 405e111ed8SAndrew Rybchenko static void 415e111ed8SAndrew Rybchenko siena_ev_qdestroy( 425e111ed8SAndrew Rybchenko __in efx_evq_t *eep); 435e111ed8SAndrew Rybchenko 445e111ed8SAndrew Rybchenko static __checkReturn efx_rc_t 455e111ed8SAndrew Rybchenko siena_ev_qprime( 465e111ed8SAndrew Rybchenko __in efx_evq_t *eep, 475e111ed8SAndrew Rybchenko __in unsigned int count); 485e111ed8SAndrew Rybchenko 495e111ed8SAndrew Rybchenko static void 505e111ed8SAndrew Rybchenko siena_ev_qpost( 515e111ed8SAndrew Rybchenko __in efx_evq_t *eep, 525e111ed8SAndrew Rybchenko __in uint16_t data); 535e111ed8SAndrew Rybchenko 545e111ed8SAndrew Rybchenko static __checkReturn efx_rc_t 555e111ed8SAndrew Rybchenko siena_ev_qmoderate( 565e111ed8SAndrew Rybchenko __in efx_evq_t *eep, 575e111ed8SAndrew Rybchenko __in unsigned int us); 585e111ed8SAndrew Rybchenko 595e111ed8SAndrew Rybchenko #if EFSYS_OPT_QSTATS 605e111ed8SAndrew Rybchenko static void 615e111ed8SAndrew Rybchenko siena_ev_qstats_update( 625e111ed8SAndrew Rybchenko __in efx_evq_t *eep, 635e111ed8SAndrew Rybchenko __inout_ecount(EV_NQSTATS) efsys_stat_t *stat); 645e111ed8SAndrew Rybchenko 655e111ed8SAndrew Rybchenko #endif 665e111ed8SAndrew Rybchenko 675e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_SIENA */ 685e111ed8SAndrew Rybchenko 69ad1e3ed8SAndrew Rybchenko #if EFX_OPTS_EF10() || EFSYS_OPT_SIENA 70ad1e3ed8SAndrew Rybchenko 71ad1e3ed8SAndrew Rybchenko static void 72ad1e3ed8SAndrew Rybchenko siena_ef10_ev_qpoll( 73ad1e3ed8SAndrew Rybchenko __in efx_evq_t *eep, 74ad1e3ed8SAndrew Rybchenko __inout unsigned int *countp, 75ad1e3ed8SAndrew Rybchenko __in const efx_ev_callbacks_t *eecp, 76ad1e3ed8SAndrew Rybchenko __in_opt void *arg); 77ad1e3ed8SAndrew Rybchenko 78ad1e3ed8SAndrew Rybchenko #endif /* EFX_OPTS_EF10() || EFSYS_OPT_SIENA */ 79ad1e3ed8SAndrew Rybchenko 805e111ed8SAndrew Rybchenko #if EFSYS_OPT_SIENA 815e111ed8SAndrew Rybchenko static const efx_ev_ops_t __efx_ev_siena_ops = { 825e111ed8SAndrew Rybchenko siena_ev_init, /* eevo_init */ 835e111ed8SAndrew Rybchenko siena_ev_fini, /* eevo_fini */ 845e111ed8SAndrew Rybchenko siena_ev_qcreate, /* eevo_qcreate */ 855e111ed8SAndrew Rybchenko siena_ev_qdestroy, /* eevo_qdestroy */ 865e111ed8SAndrew Rybchenko siena_ev_qprime, /* eevo_qprime */ 875e111ed8SAndrew Rybchenko siena_ev_qpost, /* eevo_qpost */ 88ad1e3ed8SAndrew Rybchenko siena_ef10_ev_qpoll, /* eevo_qpoll */ 895e111ed8SAndrew Rybchenko siena_ev_qmoderate, /* eevo_qmoderate */ 905e111ed8SAndrew Rybchenko #if EFSYS_OPT_QSTATS 915e111ed8SAndrew Rybchenko siena_ev_qstats_update, /* eevo_qstats_update */ 925e111ed8SAndrew Rybchenko #endif 935e111ed8SAndrew Rybchenko }; 945e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_SIENA */ 955e111ed8SAndrew Rybchenko 965e111ed8SAndrew Rybchenko #if EFX_OPTS_EF10() 975e111ed8SAndrew Rybchenko static const efx_ev_ops_t __efx_ev_ef10_ops = { 985e111ed8SAndrew Rybchenko ef10_ev_init, /* eevo_init */ 995e111ed8SAndrew Rybchenko ef10_ev_fini, /* eevo_fini */ 1005e111ed8SAndrew Rybchenko ef10_ev_qcreate, /* eevo_qcreate */ 1015e111ed8SAndrew Rybchenko ef10_ev_qdestroy, /* eevo_qdestroy */ 1025e111ed8SAndrew Rybchenko ef10_ev_qprime, /* eevo_qprime */ 1035e111ed8SAndrew Rybchenko ef10_ev_qpost, /* eevo_qpost */ 104ad1e3ed8SAndrew Rybchenko siena_ef10_ev_qpoll, /* eevo_qpoll */ 1055e111ed8SAndrew Rybchenko ef10_ev_qmoderate, /* eevo_qmoderate */ 1065e111ed8SAndrew Rybchenko #if EFSYS_OPT_QSTATS 1075e111ed8SAndrew Rybchenko ef10_ev_qstats_update, /* eevo_qstats_update */ 1085e111ed8SAndrew Rybchenko #endif 1095e111ed8SAndrew Rybchenko }; 1105e111ed8SAndrew Rybchenko #endif /* EFX_OPTS_EF10() */ 1115e111ed8SAndrew Rybchenko 112b97bf1caSAndrew Rybchenko #if EFSYS_OPT_RIVERHEAD 113b97bf1caSAndrew Rybchenko static const efx_ev_ops_t __efx_ev_rhead_ops = { 114b97bf1caSAndrew Rybchenko rhead_ev_init, /* eevo_init */ 115b97bf1caSAndrew Rybchenko rhead_ev_fini, /* eevo_fini */ 116b97bf1caSAndrew Rybchenko rhead_ev_qcreate, /* eevo_qcreate */ 117b97bf1caSAndrew Rybchenko rhead_ev_qdestroy, /* eevo_qdestroy */ 118b97bf1caSAndrew Rybchenko rhead_ev_qprime, /* eevo_qprime */ 119b97bf1caSAndrew Rybchenko rhead_ev_qpost, /* eevo_qpost */ 120b97bf1caSAndrew Rybchenko rhead_ev_qpoll, /* eevo_qpoll */ 121b97bf1caSAndrew Rybchenko rhead_ev_qmoderate, /* eevo_qmoderate */ 122b97bf1caSAndrew Rybchenko #if EFSYS_OPT_QSTATS 123b97bf1caSAndrew Rybchenko rhead_ev_qstats_update, /* eevo_qstats_update */ 124b97bf1caSAndrew Rybchenko #endif 125b97bf1caSAndrew Rybchenko }; 126b97bf1caSAndrew Rybchenko #endif /* EFSYS_OPT_RIVERHEAD */ 127b97bf1caSAndrew Rybchenko 1285e111ed8SAndrew Rybchenko 1295e111ed8SAndrew Rybchenko __checkReturn efx_rc_t 1305e111ed8SAndrew Rybchenko efx_ev_init( 1315e111ed8SAndrew Rybchenko __in efx_nic_t *enp) 1325e111ed8SAndrew Rybchenko { 1335e111ed8SAndrew Rybchenko const efx_ev_ops_t *eevop; 1345e111ed8SAndrew Rybchenko efx_rc_t rc; 1355e111ed8SAndrew Rybchenko 1365e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 1375e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR); 1385e111ed8SAndrew Rybchenko 1395e111ed8SAndrew Rybchenko if (enp->en_mod_flags & EFX_MOD_EV) { 1405e111ed8SAndrew Rybchenko rc = EINVAL; 1415e111ed8SAndrew Rybchenko goto fail1; 1425e111ed8SAndrew Rybchenko } 1435e111ed8SAndrew Rybchenko 1445e111ed8SAndrew Rybchenko switch (enp->en_family) { 1455e111ed8SAndrew Rybchenko #if EFSYS_OPT_SIENA 1465e111ed8SAndrew Rybchenko case EFX_FAMILY_SIENA: 1475e111ed8SAndrew Rybchenko eevop = &__efx_ev_siena_ops; 1485e111ed8SAndrew Rybchenko break; 1495e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_SIENA */ 1505e111ed8SAndrew Rybchenko 1515e111ed8SAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON 1525e111ed8SAndrew Rybchenko case EFX_FAMILY_HUNTINGTON: 1535e111ed8SAndrew Rybchenko eevop = &__efx_ev_ef10_ops; 1545e111ed8SAndrew Rybchenko break; 1555e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_HUNTINGTON */ 1565e111ed8SAndrew Rybchenko 1575e111ed8SAndrew Rybchenko #if EFSYS_OPT_MEDFORD 1585e111ed8SAndrew Rybchenko case EFX_FAMILY_MEDFORD: 1595e111ed8SAndrew Rybchenko eevop = &__efx_ev_ef10_ops; 1605e111ed8SAndrew Rybchenko break; 1615e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_MEDFORD */ 1625e111ed8SAndrew Rybchenko 1635e111ed8SAndrew Rybchenko #if EFSYS_OPT_MEDFORD2 1645e111ed8SAndrew Rybchenko case EFX_FAMILY_MEDFORD2: 1655e111ed8SAndrew Rybchenko eevop = &__efx_ev_ef10_ops; 1665e111ed8SAndrew Rybchenko break; 1675e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_MEDFORD2 */ 1685e111ed8SAndrew Rybchenko 169b97bf1caSAndrew Rybchenko #if EFSYS_OPT_RIVERHEAD 170b97bf1caSAndrew Rybchenko case EFX_FAMILY_RIVERHEAD: 171b97bf1caSAndrew Rybchenko eevop = &__efx_ev_rhead_ops; 172b97bf1caSAndrew Rybchenko break; 173b97bf1caSAndrew Rybchenko #endif /* EFSYS_OPT_RIVERHEAD */ 174b97bf1caSAndrew Rybchenko 1755e111ed8SAndrew Rybchenko default: 1765e111ed8SAndrew Rybchenko EFSYS_ASSERT(0); 1775e111ed8SAndrew Rybchenko rc = ENOTSUP; 1785e111ed8SAndrew Rybchenko goto fail1; 1795e111ed8SAndrew Rybchenko } 1805e111ed8SAndrew Rybchenko 1815e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_ev_qcount, ==, 0); 1825e111ed8SAndrew Rybchenko 1835e111ed8SAndrew Rybchenko if ((rc = eevop->eevo_init(enp)) != 0) 1845e111ed8SAndrew Rybchenko goto fail2; 1855e111ed8SAndrew Rybchenko 1865e111ed8SAndrew Rybchenko enp->en_eevop = eevop; 1875e111ed8SAndrew Rybchenko enp->en_mod_flags |= EFX_MOD_EV; 1885e111ed8SAndrew Rybchenko return (0); 1895e111ed8SAndrew Rybchenko 1905e111ed8SAndrew Rybchenko fail2: 1915e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2); 1925e111ed8SAndrew Rybchenko 1935e111ed8SAndrew Rybchenko fail1: 1945e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 1955e111ed8SAndrew Rybchenko 1965e111ed8SAndrew Rybchenko enp->en_eevop = NULL; 1975e111ed8SAndrew Rybchenko enp->en_mod_flags &= ~EFX_MOD_EV; 1985e111ed8SAndrew Rybchenko return (rc); 1995e111ed8SAndrew Rybchenko } 2005e111ed8SAndrew Rybchenko 2015e111ed8SAndrew Rybchenko __checkReturn size_t 2025e111ed8SAndrew Rybchenko efx_evq_size( 2035e111ed8SAndrew Rybchenko __in const efx_nic_t *enp, 204*f8a60f76SAndy Moreton __in unsigned int ndescs, 205*f8a60f76SAndy Moreton __in uint32_t flags) 2065e111ed8SAndrew Rybchenko { 2075e111ed8SAndrew Rybchenko const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); 208*f8a60f76SAndy Moreton size_t desc_size; 2095e111ed8SAndrew Rybchenko 210*f8a60f76SAndy Moreton desc_size = encp->enc_ev_desc_size; 211*f8a60f76SAndy Moreton 212*f8a60f76SAndy Moreton #if EFSYS_OPT_EV_EXTENDED_WIDTH 213*f8a60f76SAndy Moreton if (flags & EFX_EVQ_FLAGS_EXTENDED_WIDTH) 214*f8a60f76SAndy Moreton desc_size = encp->enc_ev_ew_desc_size; 215*f8a60f76SAndy Moreton #else 216*f8a60f76SAndy Moreton EFSYS_ASSERT((flags & EFX_EVQ_FLAGS_EXTENDED_WIDTH) == 0); 217*f8a60f76SAndy Moreton #endif 218*f8a60f76SAndy Moreton 219*f8a60f76SAndy Moreton return (ndescs * desc_size); 2205e111ed8SAndrew Rybchenko } 2215e111ed8SAndrew Rybchenko 2225e111ed8SAndrew Rybchenko __checkReturn unsigned int 2235e111ed8SAndrew Rybchenko efx_evq_nbufs( 2245e111ed8SAndrew Rybchenko __in const efx_nic_t *enp, 225*f8a60f76SAndy Moreton __in unsigned int ndescs, 226*f8a60f76SAndy Moreton __in uint32_t flags) 2275e111ed8SAndrew Rybchenko { 228*f8a60f76SAndy Moreton size_t size; 229*f8a60f76SAndy Moreton 230*f8a60f76SAndy Moreton size = efx_evq_size(enp, ndescs, flags); 231*f8a60f76SAndy Moreton 232*f8a60f76SAndy Moreton return (EFX_DIV_ROUND_UP(size, EFX_BUF_SIZE)); 2335e111ed8SAndrew Rybchenko } 2345e111ed8SAndrew Rybchenko 2355e111ed8SAndrew Rybchenko void 2365e111ed8SAndrew Rybchenko efx_ev_fini( 2375e111ed8SAndrew Rybchenko __in efx_nic_t *enp) 2385e111ed8SAndrew Rybchenko { 2395e111ed8SAndrew Rybchenko const efx_ev_ops_t *eevop = enp->en_eevop; 2405e111ed8SAndrew Rybchenko 2415e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 2425e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR); 2435e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_EV); 2445e111ed8SAndrew Rybchenko EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX)); 2455e111ed8SAndrew Rybchenko EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX)); 2465e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_ev_qcount, ==, 0); 2475e111ed8SAndrew Rybchenko 2485e111ed8SAndrew Rybchenko eevop->eevo_fini(enp); 2495e111ed8SAndrew Rybchenko 2505e111ed8SAndrew Rybchenko enp->en_eevop = NULL; 2515e111ed8SAndrew Rybchenko enp->en_mod_flags &= ~EFX_MOD_EV; 2525e111ed8SAndrew Rybchenko } 2535e111ed8SAndrew Rybchenko 2545e111ed8SAndrew Rybchenko 2555e111ed8SAndrew Rybchenko __checkReturn efx_rc_t 2565e111ed8SAndrew Rybchenko efx_ev_qcreate( 2575e111ed8SAndrew Rybchenko __in efx_nic_t *enp, 2585e111ed8SAndrew Rybchenko __in unsigned int index, 2595e111ed8SAndrew Rybchenko __in efsys_mem_t *esmp, 2605e111ed8SAndrew Rybchenko __in size_t ndescs, 2615e111ed8SAndrew Rybchenko __in uint32_t id, 2625e111ed8SAndrew Rybchenko __in uint32_t us, 2635e111ed8SAndrew Rybchenko __in uint32_t flags, 2645e111ed8SAndrew Rybchenko __deref_out efx_evq_t **eepp) 2655e111ed8SAndrew Rybchenko { 2665e111ed8SAndrew Rybchenko const efx_ev_ops_t *eevop = enp->en_eevop; 2675e111ed8SAndrew Rybchenko efx_evq_t *eep; 2685e111ed8SAndrew Rybchenko const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); 2695e111ed8SAndrew Rybchenko efx_rc_t rc; 2705e111ed8SAndrew Rybchenko 2715e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 2725e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_EV); 2735e111ed8SAndrew Rybchenko 2745e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_ev_qcount + 1, <, 2755e111ed8SAndrew Rybchenko enp->en_nic_cfg.enc_evq_limit); 2765e111ed8SAndrew Rybchenko 2772e5819a5SAndrew Rybchenko if (index >= encp->enc_evq_limit) { 2782e5819a5SAndrew Rybchenko rc = EINVAL; 2792e5819a5SAndrew Rybchenko goto fail1; 2802e5819a5SAndrew Rybchenko } 2812e5819a5SAndrew Rybchenko 2822e5819a5SAndrew Rybchenko if (us > encp->enc_evq_timer_max_us) { 2832e5819a5SAndrew Rybchenko rc = EINVAL; 2842e5819a5SAndrew Rybchenko goto fail2; 2852e5819a5SAndrew Rybchenko } 2862e5819a5SAndrew Rybchenko 2875e111ed8SAndrew Rybchenko switch (flags & EFX_EVQ_FLAGS_NOTIFY_MASK) { 2885e111ed8SAndrew Rybchenko case EFX_EVQ_FLAGS_NOTIFY_INTERRUPT: 2895e111ed8SAndrew Rybchenko break; 2905e111ed8SAndrew Rybchenko case EFX_EVQ_FLAGS_NOTIFY_DISABLED: 2915e111ed8SAndrew Rybchenko if (us != 0) { 2925e111ed8SAndrew Rybchenko rc = EINVAL; 2932e5819a5SAndrew Rybchenko goto fail3; 2945e111ed8SAndrew Rybchenko } 2955e111ed8SAndrew Rybchenko break; 2965e111ed8SAndrew Rybchenko default: 2975e111ed8SAndrew Rybchenko rc = EINVAL; 2982e5819a5SAndrew Rybchenko goto fail4; 2995e111ed8SAndrew Rybchenko } 3005e111ed8SAndrew Rybchenko 301*f8a60f76SAndy Moreton if ((flags & EFX_EVQ_FLAGS_EXTENDED_WIDTH) && 302*f8a60f76SAndy Moreton (encp->enc_ev_ew_desc_size == 0)) { 303*f8a60f76SAndy Moreton /* Extended width event descriptors are not supported. */ 304*f8a60f76SAndy Moreton rc = EINVAL; 305*f8a60f76SAndy Moreton goto fail5; 306*f8a60f76SAndy Moreton } 307*f8a60f76SAndy Moreton 3085e111ed8SAndrew Rybchenko EFSYS_ASSERT(ISP2(encp->enc_evq_max_nevs)); 3095e111ed8SAndrew Rybchenko EFSYS_ASSERT(ISP2(encp->enc_evq_min_nevs)); 3105e111ed8SAndrew Rybchenko 3115e111ed8SAndrew Rybchenko if (!ISP2(ndescs) || 3125e111ed8SAndrew Rybchenko ndescs < encp->enc_evq_min_nevs || 3135e111ed8SAndrew Rybchenko ndescs > encp->enc_evq_max_nevs) { 3145e111ed8SAndrew Rybchenko rc = EINVAL; 315*f8a60f76SAndy Moreton goto fail6; 316*f8a60f76SAndy Moreton } 317*f8a60f76SAndy Moreton 318*f8a60f76SAndy Moreton if (EFSYS_MEM_SIZE(esmp) < (ndescs * encp->enc_ev_desc_size)) { 319*f8a60f76SAndy Moreton /* Buffer too small for event queue descriptors. */ 320*f8a60f76SAndy Moreton rc = EINVAL; 321*f8a60f76SAndy Moreton goto fail7; 3225e111ed8SAndrew Rybchenko } 3235e111ed8SAndrew Rybchenko 3245e111ed8SAndrew Rybchenko /* Allocate an EVQ object */ 3255e111ed8SAndrew Rybchenko EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (efx_evq_t), eep); 3265e111ed8SAndrew Rybchenko if (eep == NULL) { 3275e111ed8SAndrew Rybchenko rc = ENOMEM; 328*f8a60f76SAndy Moreton goto fail8; 3295e111ed8SAndrew Rybchenko } 3305e111ed8SAndrew Rybchenko 3315e111ed8SAndrew Rybchenko eep->ee_magic = EFX_EVQ_MAGIC; 3325e111ed8SAndrew Rybchenko eep->ee_enp = enp; 3335e111ed8SAndrew Rybchenko eep->ee_index = index; 3345e111ed8SAndrew Rybchenko eep->ee_mask = ndescs - 1; 3355e111ed8SAndrew Rybchenko eep->ee_flags = flags; 3365e111ed8SAndrew Rybchenko eep->ee_esmp = esmp; 3375e111ed8SAndrew Rybchenko 3385e111ed8SAndrew Rybchenko /* 3395e111ed8SAndrew Rybchenko * Set outputs before the queue is created because interrupts may be 3405e111ed8SAndrew Rybchenko * raised for events immediately after the queue is created, before the 3415e111ed8SAndrew Rybchenko * function call below returns. See bug58606. 3425e111ed8SAndrew Rybchenko * 3435e111ed8SAndrew Rybchenko * The eepp pointer passed in by the client must therefore point to data 3445e111ed8SAndrew Rybchenko * shared with the client's event processing context. 3455e111ed8SAndrew Rybchenko */ 3465e111ed8SAndrew Rybchenko enp->en_ev_qcount++; 3475e111ed8SAndrew Rybchenko *eepp = eep; 3485e111ed8SAndrew Rybchenko 3495e111ed8SAndrew Rybchenko if ((rc = eevop->eevo_qcreate(enp, index, esmp, ndescs, id, us, flags, 3505e111ed8SAndrew Rybchenko eep)) != 0) 351*f8a60f76SAndy Moreton goto fail9; 3525e111ed8SAndrew Rybchenko 3535e111ed8SAndrew Rybchenko return (0); 3545e111ed8SAndrew Rybchenko 355*f8a60f76SAndy Moreton fail9: 356*f8a60f76SAndy Moreton EFSYS_PROBE(fail9); 3575e111ed8SAndrew Rybchenko 3585e111ed8SAndrew Rybchenko *eepp = NULL; 3595e111ed8SAndrew Rybchenko enp->en_ev_qcount--; 3605e111ed8SAndrew Rybchenko EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_evq_t), eep); 361*f8a60f76SAndy Moreton fail8: 362*f8a60f76SAndy Moreton EFSYS_PROBE(fail8); 363*f8a60f76SAndy Moreton fail7: 364*f8a60f76SAndy Moreton EFSYS_PROBE(fail7); 3652e5819a5SAndrew Rybchenko fail6: 3662e5819a5SAndrew Rybchenko EFSYS_PROBE(fail6); 3672e5819a5SAndrew Rybchenko fail5: 3682e5819a5SAndrew Rybchenko EFSYS_PROBE(fail5); 3695e111ed8SAndrew Rybchenko fail4: 3705e111ed8SAndrew Rybchenko EFSYS_PROBE(fail4); 3715e111ed8SAndrew Rybchenko fail3: 3725e111ed8SAndrew Rybchenko EFSYS_PROBE(fail3); 3735e111ed8SAndrew Rybchenko fail2: 3745e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2); 3755e111ed8SAndrew Rybchenko fail1: 3765e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 3775e111ed8SAndrew Rybchenko return (rc); 3785e111ed8SAndrew Rybchenko } 3795e111ed8SAndrew Rybchenko 3805e111ed8SAndrew Rybchenko void 3815e111ed8SAndrew Rybchenko efx_ev_qdestroy( 3825e111ed8SAndrew Rybchenko __in efx_evq_t *eep) 3835e111ed8SAndrew Rybchenko { 3845e111ed8SAndrew Rybchenko efx_nic_t *enp = eep->ee_enp; 3855e111ed8SAndrew Rybchenko const efx_ev_ops_t *eevop = enp->en_eevop; 3865e111ed8SAndrew Rybchenko 3875e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC); 3885e111ed8SAndrew Rybchenko 3895e111ed8SAndrew Rybchenko EFSYS_ASSERT(enp->en_ev_qcount != 0); 3905e111ed8SAndrew Rybchenko --enp->en_ev_qcount; 3915e111ed8SAndrew Rybchenko 3925e111ed8SAndrew Rybchenko eevop->eevo_qdestroy(eep); 3935e111ed8SAndrew Rybchenko 3945e111ed8SAndrew Rybchenko /* Free the EVQ object */ 3955e111ed8SAndrew Rybchenko EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_evq_t), eep); 3965e111ed8SAndrew Rybchenko } 3975e111ed8SAndrew Rybchenko 3985e111ed8SAndrew Rybchenko __checkReturn efx_rc_t 3995e111ed8SAndrew Rybchenko efx_ev_qprime( 4005e111ed8SAndrew Rybchenko __in efx_evq_t *eep, 4015e111ed8SAndrew Rybchenko __in unsigned int count) 4025e111ed8SAndrew Rybchenko { 4035e111ed8SAndrew Rybchenko efx_nic_t *enp = eep->ee_enp; 4045e111ed8SAndrew Rybchenko const efx_ev_ops_t *eevop = enp->en_eevop; 4055e111ed8SAndrew Rybchenko efx_rc_t rc; 4065e111ed8SAndrew Rybchenko 4075e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC); 4085e111ed8SAndrew Rybchenko 4095e111ed8SAndrew Rybchenko if (!(enp->en_mod_flags & EFX_MOD_INTR)) { 4105e111ed8SAndrew Rybchenko rc = EINVAL; 4115e111ed8SAndrew Rybchenko goto fail1; 4125e111ed8SAndrew Rybchenko } 4135e111ed8SAndrew Rybchenko 4145e111ed8SAndrew Rybchenko if ((rc = eevop->eevo_qprime(eep, count)) != 0) 4155e111ed8SAndrew Rybchenko goto fail2; 4165e111ed8SAndrew Rybchenko 4175e111ed8SAndrew Rybchenko return (0); 4185e111ed8SAndrew Rybchenko 4195e111ed8SAndrew Rybchenko fail2: 4205e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2); 4215e111ed8SAndrew Rybchenko fail1: 4225e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 4235e111ed8SAndrew Rybchenko return (rc); 4245e111ed8SAndrew Rybchenko } 4255e111ed8SAndrew Rybchenko 4265e111ed8SAndrew Rybchenko __checkReturn boolean_t 4275e111ed8SAndrew Rybchenko efx_ev_qpending( 4285e111ed8SAndrew Rybchenko __in efx_evq_t *eep, 4295e111ed8SAndrew Rybchenko __in unsigned int count) 4305e111ed8SAndrew Rybchenko { 4315e111ed8SAndrew Rybchenko size_t offset; 4325e111ed8SAndrew Rybchenko efx_qword_t qword; 4335e111ed8SAndrew Rybchenko 4345e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC); 4355e111ed8SAndrew Rybchenko 4365e111ed8SAndrew Rybchenko offset = (count & eep->ee_mask) * sizeof (efx_qword_t); 4375e111ed8SAndrew Rybchenko EFSYS_MEM_READQ(eep->ee_esmp, offset, &qword); 4385e111ed8SAndrew Rybchenko 4395e111ed8SAndrew Rybchenko return (EFX_EV_PRESENT(qword)); 4405e111ed8SAndrew Rybchenko } 4415e111ed8SAndrew Rybchenko 4425e111ed8SAndrew Rybchenko #if EFSYS_OPT_EV_PREFETCH 4435e111ed8SAndrew Rybchenko 4445e111ed8SAndrew Rybchenko void 4455e111ed8SAndrew Rybchenko efx_ev_qprefetch( 4465e111ed8SAndrew Rybchenko __in efx_evq_t *eep, 4475e111ed8SAndrew Rybchenko __in unsigned int count) 4485e111ed8SAndrew Rybchenko { 4495e111ed8SAndrew Rybchenko unsigned int offset; 4505e111ed8SAndrew Rybchenko 4515e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC); 4525e111ed8SAndrew Rybchenko 4535e111ed8SAndrew Rybchenko offset = (count & eep->ee_mask) * sizeof (efx_qword_t); 4545e111ed8SAndrew Rybchenko EFSYS_MEM_PREFETCH(eep->ee_esmp, offset); 4555e111ed8SAndrew Rybchenko } 4565e111ed8SAndrew Rybchenko 4575e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_EV_PREFETCH */ 4585e111ed8SAndrew Rybchenko 45992fedcd3SIvan Malov /* 46092fedcd3SIvan Malov * This method is needed to ensure that eec_initialized callback 46192fedcd3SIvan Malov * is invoked after queue creation. The callback will be invoked 46292fedcd3SIvan Malov * on Riverhead boards which have no support for INIT_DONE events 46392fedcd3SIvan Malov * and will do nothing on other boards. 46492fedcd3SIvan Malov * 46592fedcd3SIvan Malov * The client drivers must call this method after calling efx_ev_create(). 46692fedcd3SIvan Malov * The call must be done with the same locks being held (if any) which are 46792fedcd3SIvan Malov * normally acquired around efx_ev_qpoll() calls to ensure that 46892fedcd3SIvan Malov * eec_initialized callback is invoked within the same locking context. 46992fedcd3SIvan Malov */ 47092fedcd3SIvan Malov void 47192fedcd3SIvan Malov efx_ev_qcreate_check_init_done( 47292fedcd3SIvan Malov __in efx_evq_t *eep, 47392fedcd3SIvan Malov __in const efx_ev_callbacks_t *eecp, 47492fedcd3SIvan Malov __in_opt void *arg) 47592fedcd3SIvan Malov { 47692fedcd3SIvan Malov const efx_nic_cfg_t *encp; 47792fedcd3SIvan Malov 47892fedcd3SIvan Malov EFSYS_ASSERT(eep != NULL); 47992fedcd3SIvan Malov EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC); 48092fedcd3SIvan Malov EFSYS_ASSERT(eecp != NULL); 48192fedcd3SIvan Malov EFSYS_ASSERT(eecp->eec_initialized != NULL); 48292fedcd3SIvan Malov 48392fedcd3SIvan Malov encp = efx_nic_cfg_get(eep->ee_enp); 48492fedcd3SIvan Malov 48592fedcd3SIvan Malov if (encp->enc_evq_init_done_ev_supported == B_FALSE) 48692fedcd3SIvan Malov (void) eecp->eec_initialized(arg); 48792fedcd3SIvan Malov } 48892fedcd3SIvan Malov 4895e111ed8SAndrew Rybchenko void 4905e111ed8SAndrew Rybchenko efx_ev_qpoll( 4915e111ed8SAndrew Rybchenko __in efx_evq_t *eep, 4925e111ed8SAndrew Rybchenko __inout unsigned int *countp, 4935e111ed8SAndrew Rybchenko __in const efx_ev_callbacks_t *eecp, 4945e111ed8SAndrew Rybchenko __in_opt void *arg) 4955e111ed8SAndrew Rybchenko { 496ad1e3ed8SAndrew Rybchenko efx_nic_t *enp = eep->ee_enp; 497ad1e3ed8SAndrew Rybchenko const efx_ev_ops_t *eevop = enp->en_eevop; 4985e111ed8SAndrew Rybchenko 4995e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC); 5005e111ed8SAndrew Rybchenko 501ad1e3ed8SAndrew Rybchenko EFSYS_ASSERT(eevop != NULL && 502ad1e3ed8SAndrew Rybchenko eevop->eevo_qpoll != NULL); 5035e111ed8SAndrew Rybchenko 504ad1e3ed8SAndrew Rybchenko eevop->eevo_qpoll(eep, countp, eecp, arg); 5055e111ed8SAndrew Rybchenko } 5065e111ed8SAndrew Rybchenko 5075e111ed8SAndrew Rybchenko void 5085e111ed8SAndrew Rybchenko efx_ev_qpost( 5095e111ed8SAndrew Rybchenko __in efx_evq_t *eep, 5105e111ed8SAndrew Rybchenko __in uint16_t data) 5115e111ed8SAndrew Rybchenko { 5125e111ed8SAndrew Rybchenko efx_nic_t *enp = eep->ee_enp; 5135e111ed8SAndrew Rybchenko const efx_ev_ops_t *eevop = enp->en_eevop; 5145e111ed8SAndrew Rybchenko 5155e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC); 5165e111ed8SAndrew Rybchenko 5175e111ed8SAndrew Rybchenko EFSYS_ASSERT(eevop != NULL && 5185e111ed8SAndrew Rybchenko eevop->eevo_qpost != NULL); 5195e111ed8SAndrew Rybchenko 5205e111ed8SAndrew Rybchenko eevop->eevo_qpost(eep, data); 5215e111ed8SAndrew Rybchenko } 5225e111ed8SAndrew Rybchenko 5235e111ed8SAndrew Rybchenko __checkReturn efx_rc_t 5245e111ed8SAndrew Rybchenko efx_ev_usecs_to_ticks( 5255e111ed8SAndrew Rybchenko __in efx_nic_t *enp, 5265e111ed8SAndrew Rybchenko __in unsigned int us, 5275e111ed8SAndrew Rybchenko __out unsigned int *ticksp) 5285e111ed8SAndrew Rybchenko { 5295e111ed8SAndrew Rybchenko efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 5305e111ed8SAndrew Rybchenko unsigned int ticks; 5315e111ed8SAndrew Rybchenko efx_rc_t rc; 5325e111ed8SAndrew Rybchenko 5335e111ed8SAndrew Rybchenko if (encp->enc_evq_timer_quantum_ns == 0) { 5345e111ed8SAndrew Rybchenko rc = ENOTSUP; 5355e111ed8SAndrew Rybchenko goto fail1; 5365e111ed8SAndrew Rybchenko } 5375e111ed8SAndrew Rybchenko 5385e111ed8SAndrew Rybchenko /* Convert microseconds to a timer tick count */ 5395e111ed8SAndrew Rybchenko if (us == 0) 5405e111ed8SAndrew Rybchenko ticks = 0; 5415e111ed8SAndrew Rybchenko else if (us * 1000 < encp->enc_evq_timer_quantum_ns) 5425e111ed8SAndrew Rybchenko ticks = 1; /* Never round down to zero */ 5435e111ed8SAndrew Rybchenko else 5445e111ed8SAndrew Rybchenko ticks = us * 1000 / encp->enc_evq_timer_quantum_ns; 5455e111ed8SAndrew Rybchenko 5465e111ed8SAndrew Rybchenko *ticksp = ticks; 5475e111ed8SAndrew Rybchenko return (0); 5485e111ed8SAndrew Rybchenko 5495e111ed8SAndrew Rybchenko fail1: 5505e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 5515e111ed8SAndrew Rybchenko return (rc); 5525e111ed8SAndrew Rybchenko } 5535e111ed8SAndrew Rybchenko 5545e111ed8SAndrew Rybchenko __checkReturn efx_rc_t 5555e111ed8SAndrew Rybchenko efx_ev_qmoderate( 5565e111ed8SAndrew Rybchenko __in efx_evq_t *eep, 5575e111ed8SAndrew Rybchenko __in unsigned int us) 5585e111ed8SAndrew Rybchenko { 5595e111ed8SAndrew Rybchenko efx_nic_t *enp = eep->ee_enp; 5605e111ed8SAndrew Rybchenko const efx_ev_ops_t *eevop = enp->en_eevop; 5615e111ed8SAndrew Rybchenko efx_rc_t rc; 5625e111ed8SAndrew Rybchenko 5635e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC); 5645e111ed8SAndrew Rybchenko 5655e111ed8SAndrew Rybchenko if ((eep->ee_flags & EFX_EVQ_FLAGS_NOTIFY_MASK) == 5665e111ed8SAndrew Rybchenko EFX_EVQ_FLAGS_NOTIFY_DISABLED) { 5675e111ed8SAndrew Rybchenko rc = EINVAL; 5685e111ed8SAndrew Rybchenko goto fail1; 5695e111ed8SAndrew Rybchenko } 5705e111ed8SAndrew Rybchenko 5715e111ed8SAndrew Rybchenko if ((rc = eevop->eevo_qmoderate(eep, us)) != 0) 5725e111ed8SAndrew Rybchenko goto fail2; 5735e111ed8SAndrew Rybchenko 5745e111ed8SAndrew Rybchenko return (0); 5755e111ed8SAndrew Rybchenko 5765e111ed8SAndrew Rybchenko fail2: 5775e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2); 5785e111ed8SAndrew Rybchenko fail1: 5795e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 5805e111ed8SAndrew Rybchenko return (rc); 5815e111ed8SAndrew Rybchenko } 5825e111ed8SAndrew Rybchenko 5835e111ed8SAndrew Rybchenko #if EFSYS_OPT_QSTATS 5845e111ed8SAndrew Rybchenko void 5855e111ed8SAndrew Rybchenko efx_ev_qstats_update( 5865e111ed8SAndrew Rybchenko __in efx_evq_t *eep, 5875e111ed8SAndrew Rybchenko __inout_ecount(EV_NQSTATS) efsys_stat_t *stat) 5885e111ed8SAndrew Rybchenko 5895e111ed8SAndrew Rybchenko { efx_nic_t *enp = eep->ee_enp; 5905e111ed8SAndrew Rybchenko const efx_ev_ops_t *eevop = enp->en_eevop; 5915e111ed8SAndrew Rybchenko 5925e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC); 5935e111ed8SAndrew Rybchenko 5945e111ed8SAndrew Rybchenko eevop->eevo_qstats_update(eep, stat); 5955e111ed8SAndrew Rybchenko } 5965e111ed8SAndrew Rybchenko 5975e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_QSTATS */ 5985e111ed8SAndrew Rybchenko 5995e111ed8SAndrew Rybchenko #if EFSYS_OPT_SIENA 6005e111ed8SAndrew Rybchenko 6015e111ed8SAndrew Rybchenko static __checkReturn efx_rc_t 6025e111ed8SAndrew Rybchenko siena_ev_init( 6035e111ed8SAndrew Rybchenko __in efx_nic_t *enp) 6045e111ed8SAndrew Rybchenko { 6055e111ed8SAndrew Rybchenko efx_oword_t oword; 6065e111ed8SAndrew Rybchenko 6075e111ed8SAndrew Rybchenko /* 6085e111ed8SAndrew Rybchenko * Program the event queue for receive and transmit queue 6095e111ed8SAndrew Rybchenko * flush events. 6105e111ed8SAndrew Rybchenko */ 6115e111ed8SAndrew Rybchenko EFX_BAR_READO(enp, FR_AZ_DP_CTRL_REG, &oword); 6125e111ed8SAndrew Rybchenko EFX_SET_OWORD_FIELD(oword, FRF_AZ_FLS_EVQ_ID, 0); 6135e111ed8SAndrew Rybchenko EFX_BAR_WRITEO(enp, FR_AZ_DP_CTRL_REG, &oword); 6145e111ed8SAndrew Rybchenko 6155e111ed8SAndrew Rybchenko return (0); 6165e111ed8SAndrew Rybchenko 6175e111ed8SAndrew Rybchenko } 6185e111ed8SAndrew Rybchenko 6195e111ed8SAndrew Rybchenko static __checkReturn boolean_t 6205e111ed8SAndrew Rybchenko siena_ev_rx_not_ok( 6215e111ed8SAndrew Rybchenko __in efx_evq_t *eep, 6225e111ed8SAndrew Rybchenko __in efx_qword_t *eqp, 6235e111ed8SAndrew Rybchenko __in uint32_t label, 6245e111ed8SAndrew Rybchenko __in uint32_t id, 6255e111ed8SAndrew Rybchenko __inout uint16_t *flagsp) 6265e111ed8SAndrew Rybchenko { 6275e111ed8SAndrew Rybchenko boolean_t ignore = B_FALSE; 6285e111ed8SAndrew Rybchenko 6295e111ed8SAndrew Rybchenko if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_TOBE_DISC) != 0) { 6305e111ed8SAndrew Rybchenko EFX_EV_QSTAT_INCR(eep, EV_RX_TOBE_DISC); 6315e111ed8SAndrew Rybchenko EFSYS_PROBE(tobe_disc); 6325e111ed8SAndrew Rybchenko /* 6335e111ed8SAndrew Rybchenko * Assume this is a unicast address mismatch, unless below 6345e111ed8SAndrew Rybchenko * we find either FSF_AZ_RX_EV_ETH_CRC_ERR or 6355e111ed8SAndrew Rybchenko * EV_RX_PAUSE_FRM_ERR is set. 6365e111ed8SAndrew Rybchenko */ 6375e111ed8SAndrew Rybchenko (*flagsp) |= EFX_ADDR_MISMATCH; 6385e111ed8SAndrew Rybchenko } 6395e111ed8SAndrew Rybchenko 6405e111ed8SAndrew Rybchenko if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_FRM_TRUNC) != 0) { 6415e111ed8SAndrew Rybchenko EFSYS_PROBE2(frm_trunc, uint32_t, label, uint32_t, id); 6425e111ed8SAndrew Rybchenko EFX_EV_QSTAT_INCR(eep, EV_RX_FRM_TRUNC); 6435e111ed8SAndrew Rybchenko (*flagsp) |= EFX_DISCARD; 6445e111ed8SAndrew Rybchenko 6455e111ed8SAndrew Rybchenko #if EFSYS_OPT_RX_SCATTER 6465e111ed8SAndrew Rybchenko /* 6475e111ed8SAndrew Rybchenko * Lookout for payload queue ran dry errors and ignore them. 6485e111ed8SAndrew Rybchenko * 6495e111ed8SAndrew Rybchenko * Sadly for the header/data split cases, the descriptor 6505e111ed8SAndrew Rybchenko * pointer in this event refers to the header queue and 6515e111ed8SAndrew Rybchenko * therefore cannot be easily detected as duplicate. 6525e111ed8SAndrew Rybchenko * So we drop these and rely on the receive processing seeing 6535e111ed8SAndrew Rybchenko * a subsequent packet with FSF_AZ_RX_EV_SOP set to discard 6545e111ed8SAndrew Rybchenko * the partially received packet. 6555e111ed8SAndrew Rybchenko */ 6565e111ed8SAndrew Rybchenko if ((EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_SOP) == 0) && 6575e111ed8SAndrew Rybchenko (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_JUMBO_CONT) == 0) && 6585e111ed8SAndrew Rybchenko (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_BYTE_CNT) == 0)) 6595e111ed8SAndrew Rybchenko ignore = B_TRUE; 6605e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_RX_SCATTER */ 6615e111ed8SAndrew Rybchenko } 6625e111ed8SAndrew Rybchenko 6635e111ed8SAndrew Rybchenko if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_ETH_CRC_ERR) != 0) { 6645e111ed8SAndrew Rybchenko EFX_EV_QSTAT_INCR(eep, EV_RX_ETH_CRC_ERR); 6655e111ed8SAndrew Rybchenko EFSYS_PROBE(crc_err); 6665e111ed8SAndrew Rybchenko (*flagsp) &= ~EFX_ADDR_MISMATCH; 6675e111ed8SAndrew Rybchenko (*flagsp) |= EFX_DISCARD; 6685e111ed8SAndrew Rybchenko } 6695e111ed8SAndrew Rybchenko 6705e111ed8SAndrew Rybchenko if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_PAUSE_FRM_ERR) != 0) { 6715e111ed8SAndrew Rybchenko EFX_EV_QSTAT_INCR(eep, EV_RX_PAUSE_FRM_ERR); 6725e111ed8SAndrew Rybchenko EFSYS_PROBE(pause_frm_err); 6735e111ed8SAndrew Rybchenko (*flagsp) &= ~EFX_ADDR_MISMATCH; 6745e111ed8SAndrew Rybchenko (*flagsp) |= EFX_DISCARD; 6755e111ed8SAndrew Rybchenko } 6765e111ed8SAndrew Rybchenko 6775e111ed8SAndrew Rybchenko if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_BUF_OWNER_ID_ERR) != 0) { 6785e111ed8SAndrew Rybchenko EFX_EV_QSTAT_INCR(eep, EV_RX_BUF_OWNER_ID_ERR); 6795e111ed8SAndrew Rybchenko EFSYS_PROBE(owner_id_err); 6805e111ed8SAndrew Rybchenko (*flagsp) |= EFX_DISCARD; 6815e111ed8SAndrew Rybchenko } 6825e111ed8SAndrew Rybchenko 6835e111ed8SAndrew Rybchenko if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_IP_HDR_CHKSUM_ERR) != 0) { 6845e111ed8SAndrew Rybchenko EFX_EV_QSTAT_INCR(eep, EV_RX_IPV4_HDR_CHKSUM_ERR); 6855e111ed8SAndrew Rybchenko EFSYS_PROBE(ipv4_err); 6865e111ed8SAndrew Rybchenko (*flagsp) &= ~EFX_CKSUM_IPV4; 6875e111ed8SAndrew Rybchenko } 6885e111ed8SAndrew Rybchenko 6895e111ed8SAndrew Rybchenko if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_TCP_UDP_CHKSUM_ERR) != 0) { 6905e111ed8SAndrew Rybchenko EFX_EV_QSTAT_INCR(eep, EV_RX_TCP_UDP_CHKSUM_ERR); 6915e111ed8SAndrew Rybchenko EFSYS_PROBE(udp_chk_err); 6925e111ed8SAndrew Rybchenko (*flagsp) &= ~EFX_CKSUM_TCPUDP; 6935e111ed8SAndrew Rybchenko } 6945e111ed8SAndrew Rybchenko 6955e111ed8SAndrew Rybchenko if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_IP_FRAG_ERR) != 0) { 6965e111ed8SAndrew Rybchenko EFX_EV_QSTAT_INCR(eep, EV_RX_IP_FRAG_ERR); 6975e111ed8SAndrew Rybchenko 6985e111ed8SAndrew Rybchenko /* 6995e111ed8SAndrew Rybchenko * If IP is fragmented FSF_AZ_RX_EV_IP_FRAG_ERR is set. This 7005e111ed8SAndrew Rybchenko * causes FSF_AZ_RX_EV_PKT_OK to be clear. This is not an error 7015e111ed8SAndrew Rybchenko * condition. 7025e111ed8SAndrew Rybchenko */ 7035e111ed8SAndrew Rybchenko (*flagsp) &= ~(EFX_PKT_TCP | EFX_PKT_UDP | EFX_CKSUM_TCPUDP); 7045e111ed8SAndrew Rybchenko } 7055e111ed8SAndrew Rybchenko 7065e111ed8SAndrew Rybchenko return (ignore); 7075e111ed8SAndrew Rybchenko } 7085e111ed8SAndrew Rybchenko 7095e111ed8SAndrew Rybchenko static __checkReturn boolean_t 7105e111ed8SAndrew Rybchenko siena_ev_rx( 7115e111ed8SAndrew Rybchenko __in efx_evq_t *eep, 7125e111ed8SAndrew Rybchenko __in efx_qword_t *eqp, 7135e111ed8SAndrew Rybchenko __in const efx_ev_callbacks_t *eecp, 7145e111ed8SAndrew Rybchenko __in_opt void *arg) 7155e111ed8SAndrew Rybchenko { 7165e111ed8SAndrew Rybchenko uint32_t id; 7175e111ed8SAndrew Rybchenko uint32_t size; 7185e111ed8SAndrew Rybchenko uint32_t label; 7195e111ed8SAndrew Rybchenko boolean_t ok; 7205e111ed8SAndrew Rybchenko #if EFSYS_OPT_RX_SCATTER 7215e111ed8SAndrew Rybchenko boolean_t sop; 7225e111ed8SAndrew Rybchenko boolean_t jumbo_cont; 7235e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_RX_SCATTER */ 7245e111ed8SAndrew Rybchenko uint32_t hdr_type; 7255e111ed8SAndrew Rybchenko boolean_t is_v6; 7265e111ed8SAndrew Rybchenko uint16_t flags; 7275e111ed8SAndrew Rybchenko boolean_t ignore; 7285e111ed8SAndrew Rybchenko boolean_t should_abort; 7295e111ed8SAndrew Rybchenko 7305e111ed8SAndrew Rybchenko EFX_EV_QSTAT_INCR(eep, EV_RX); 7315e111ed8SAndrew Rybchenko 7325e111ed8SAndrew Rybchenko /* Basic packet information */ 7335e111ed8SAndrew Rybchenko id = EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_DESC_PTR); 7345e111ed8SAndrew Rybchenko size = EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_BYTE_CNT); 7355e111ed8SAndrew Rybchenko label = EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_Q_LABEL); 7365e111ed8SAndrew Rybchenko ok = (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_PKT_OK) != 0); 7375e111ed8SAndrew Rybchenko 7385e111ed8SAndrew Rybchenko #if EFSYS_OPT_RX_SCATTER 7395e111ed8SAndrew Rybchenko sop = (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_SOP) != 0); 7405e111ed8SAndrew Rybchenko jumbo_cont = (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_JUMBO_CONT) != 0); 7415e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_RX_SCATTER */ 7425e111ed8SAndrew Rybchenko 7435e111ed8SAndrew Rybchenko hdr_type = EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_HDR_TYPE); 7445e111ed8SAndrew Rybchenko 7455e111ed8SAndrew Rybchenko is_v6 = (EFX_QWORD_FIELD(*eqp, FSF_CZ_RX_EV_IPV6_PKT) != 0); 7465e111ed8SAndrew Rybchenko 7475e111ed8SAndrew Rybchenko /* 7485e111ed8SAndrew Rybchenko * If packet is marked as OK and packet type is TCP/IP or 7495e111ed8SAndrew Rybchenko * UDP/IP or other IP, then we can rely on the hardware checksums. 7505e111ed8SAndrew Rybchenko */ 7515e111ed8SAndrew Rybchenko switch (hdr_type) { 7525e111ed8SAndrew Rybchenko case FSE_AZ_RX_EV_HDR_TYPE_IPV4V6_TCP: 7535e111ed8SAndrew Rybchenko flags = EFX_PKT_TCP | EFX_CKSUM_TCPUDP; 7545e111ed8SAndrew Rybchenko if (is_v6) { 7555e111ed8SAndrew Rybchenko EFX_EV_QSTAT_INCR(eep, EV_RX_TCP_IPV6); 7565e111ed8SAndrew Rybchenko flags |= EFX_PKT_IPV6; 7575e111ed8SAndrew Rybchenko } else { 7585e111ed8SAndrew Rybchenko EFX_EV_QSTAT_INCR(eep, EV_RX_TCP_IPV4); 7595e111ed8SAndrew Rybchenko flags |= EFX_PKT_IPV4 | EFX_CKSUM_IPV4; 7605e111ed8SAndrew Rybchenko } 7615e111ed8SAndrew Rybchenko break; 7625e111ed8SAndrew Rybchenko 7635e111ed8SAndrew Rybchenko case FSE_AZ_RX_EV_HDR_TYPE_IPV4V6_UDP: 7645e111ed8SAndrew Rybchenko flags = EFX_PKT_UDP | EFX_CKSUM_TCPUDP; 7655e111ed8SAndrew Rybchenko if (is_v6) { 7665e111ed8SAndrew Rybchenko EFX_EV_QSTAT_INCR(eep, EV_RX_UDP_IPV6); 7675e111ed8SAndrew Rybchenko flags |= EFX_PKT_IPV6; 7685e111ed8SAndrew Rybchenko } else { 7695e111ed8SAndrew Rybchenko EFX_EV_QSTAT_INCR(eep, EV_RX_UDP_IPV4); 7705e111ed8SAndrew Rybchenko flags |= EFX_PKT_IPV4 | EFX_CKSUM_IPV4; 7715e111ed8SAndrew Rybchenko } 7725e111ed8SAndrew Rybchenko break; 7735e111ed8SAndrew Rybchenko 7745e111ed8SAndrew Rybchenko case FSE_AZ_RX_EV_HDR_TYPE_IPV4V6_OTHER: 7755e111ed8SAndrew Rybchenko if (is_v6) { 7765e111ed8SAndrew Rybchenko EFX_EV_QSTAT_INCR(eep, EV_RX_OTHER_IPV6); 7775e111ed8SAndrew Rybchenko flags = EFX_PKT_IPV6; 7785e111ed8SAndrew Rybchenko } else { 7795e111ed8SAndrew Rybchenko EFX_EV_QSTAT_INCR(eep, EV_RX_OTHER_IPV4); 7805e111ed8SAndrew Rybchenko flags = EFX_PKT_IPV4 | EFX_CKSUM_IPV4; 7815e111ed8SAndrew Rybchenko } 7825e111ed8SAndrew Rybchenko break; 7835e111ed8SAndrew Rybchenko 7845e111ed8SAndrew Rybchenko case FSE_AZ_RX_EV_HDR_TYPE_OTHER: 7855e111ed8SAndrew Rybchenko EFX_EV_QSTAT_INCR(eep, EV_RX_NON_IP); 7865e111ed8SAndrew Rybchenko flags = 0; 7875e111ed8SAndrew Rybchenko break; 7885e111ed8SAndrew Rybchenko 7895e111ed8SAndrew Rybchenko default: 7905e111ed8SAndrew Rybchenko EFSYS_ASSERT(B_FALSE); 7915e111ed8SAndrew Rybchenko flags = 0; 7925e111ed8SAndrew Rybchenko break; 7935e111ed8SAndrew Rybchenko } 7945e111ed8SAndrew Rybchenko 7955e111ed8SAndrew Rybchenko #if EFSYS_OPT_RX_SCATTER 7965e111ed8SAndrew Rybchenko /* Report scatter and header/lookahead split buffer flags */ 7975e111ed8SAndrew Rybchenko if (sop) 7985e111ed8SAndrew Rybchenko flags |= EFX_PKT_START; 7995e111ed8SAndrew Rybchenko if (jumbo_cont) 8005e111ed8SAndrew Rybchenko flags |= EFX_PKT_CONT; 8015e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_RX_SCATTER */ 8025e111ed8SAndrew Rybchenko 8035e111ed8SAndrew Rybchenko /* Detect errors included in the FSF_AZ_RX_EV_PKT_OK indication */ 8045e111ed8SAndrew Rybchenko if (!ok) { 8055e111ed8SAndrew Rybchenko ignore = siena_ev_rx_not_ok(eep, eqp, label, id, &flags); 8065e111ed8SAndrew Rybchenko if (ignore) { 8075e111ed8SAndrew Rybchenko EFSYS_PROBE4(rx_complete, uint32_t, label, uint32_t, id, 8085e111ed8SAndrew Rybchenko uint32_t, size, uint16_t, flags); 8095e111ed8SAndrew Rybchenko 8105e111ed8SAndrew Rybchenko return (B_FALSE); 8115e111ed8SAndrew Rybchenko } 8125e111ed8SAndrew Rybchenko } 8135e111ed8SAndrew Rybchenko 8145e111ed8SAndrew Rybchenko /* If we're not discarding the packet then it is ok */ 8155e111ed8SAndrew Rybchenko if (~flags & EFX_DISCARD) 8165e111ed8SAndrew Rybchenko EFX_EV_QSTAT_INCR(eep, EV_RX_OK); 8175e111ed8SAndrew Rybchenko 8185e111ed8SAndrew Rybchenko /* Detect multicast packets that didn't match the filter */ 8195e111ed8SAndrew Rybchenko if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_MCAST_PKT) != 0) { 8205e111ed8SAndrew Rybchenko EFX_EV_QSTAT_INCR(eep, EV_RX_MCAST_PKT); 8215e111ed8SAndrew Rybchenko 8225e111ed8SAndrew Rybchenko if (EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_MCAST_HASH_MATCH) != 0) { 8235e111ed8SAndrew Rybchenko EFX_EV_QSTAT_INCR(eep, EV_RX_MCAST_HASH_MATCH); 8245e111ed8SAndrew Rybchenko } else { 8255e111ed8SAndrew Rybchenko EFSYS_PROBE(mcast_mismatch); 8265e111ed8SAndrew Rybchenko flags |= EFX_ADDR_MISMATCH; 8275e111ed8SAndrew Rybchenko } 8285e111ed8SAndrew Rybchenko } else { 8295e111ed8SAndrew Rybchenko flags |= EFX_PKT_UNICAST; 8305e111ed8SAndrew Rybchenko } 8315e111ed8SAndrew Rybchenko 8325e111ed8SAndrew Rybchenko /* 8335e111ed8SAndrew Rybchenko * The packet parser in Siena can abort parsing packets under 8345e111ed8SAndrew Rybchenko * certain error conditions, setting the PKT_NOT_PARSED bit 8355e111ed8SAndrew Rybchenko * (which clears PKT_OK). If this is set, then don't trust 8365e111ed8SAndrew Rybchenko * the PKT_TYPE field. 8375e111ed8SAndrew Rybchenko */ 8385e111ed8SAndrew Rybchenko if (!ok) { 8395e111ed8SAndrew Rybchenko uint32_t parse_err; 8405e111ed8SAndrew Rybchenko 8415e111ed8SAndrew Rybchenko parse_err = EFX_QWORD_FIELD(*eqp, FSF_CZ_RX_EV_PKT_NOT_PARSED); 8425e111ed8SAndrew Rybchenko if (parse_err != 0) 8435e111ed8SAndrew Rybchenko flags |= EFX_CHECK_VLAN; 8445e111ed8SAndrew Rybchenko } 8455e111ed8SAndrew Rybchenko 8465e111ed8SAndrew Rybchenko if (~flags & EFX_CHECK_VLAN) { 8475e111ed8SAndrew Rybchenko uint32_t pkt_type; 8485e111ed8SAndrew Rybchenko 8495e111ed8SAndrew Rybchenko pkt_type = EFX_QWORD_FIELD(*eqp, FSF_AZ_RX_EV_PKT_TYPE); 8505e111ed8SAndrew Rybchenko if (pkt_type >= FSE_AZ_RX_EV_PKT_TYPE_VLAN) 8515e111ed8SAndrew Rybchenko flags |= EFX_PKT_VLAN_TAGGED; 8525e111ed8SAndrew Rybchenko } 8535e111ed8SAndrew Rybchenko 8545e111ed8SAndrew Rybchenko EFSYS_PROBE4(rx_complete, uint32_t, label, uint32_t, id, 8555e111ed8SAndrew Rybchenko uint32_t, size, uint16_t, flags); 8565e111ed8SAndrew Rybchenko 8575e111ed8SAndrew Rybchenko EFSYS_ASSERT(eecp->eec_rx != NULL); 8585e111ed8SAndrew Rybchenko should_abort = eecp->eec_rx(arg, label, id, size, flags); 8595e111ed8SAndrew Rybchenko 8605e111ed8SAndrew Rybchenko return (should_abort); 8615e111ed8SAndrew Rybchenko } 8625e111ed8SAndrew Rybchenko 8635e111ed8SAndrew Rybchenko static __checkReturn boolean_t 8645e111ed8SAndrew Rybchenko siena_ev_tx( 8655e111ed8SAndrew Rybchenko __in efx_evq_t *eep, 8665e111ed8SAndrew Rybchenko __in efx_qword_t *eqp, 8675e111ed8SAndrew Rybchenko __in const efx_ev_callbacks_t *eecp, 8685e111ed8SAndrew Rybchenko __in_opt void *arg) 8695e111ed8SAndrew Rybchenko { 8705e111ed8SAndrew Rybchenko uint32_t id; 8715e111ed8SAndrew Rybchenko uint32_t label; 8725e111ed8SAndrew Rybchenko boolean_t should_abort; 8735e111ed8SAndrew Rybchenko 8745e111ed8SAndrew Rybchenko EFX_EV_QSTAT_INCR(eep, EV_TX); 8755e111ed8SAndrew Rybchenko 8765e111ed8SAndrew Rybchenko if (EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_COMP) != 0 && 8775e111ed8SAndrew Rybchenko EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_PKT_ERR) == 0 && 8785e111ed8SAndrew Rybchenko EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_PKT_TOO_BIG) == 0 && 8795e111ed8SAndrew Rybchenko EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_WQ_FF_FULL) == 0) { 8805e111ed8SAndrew Rybchenko 8815e111ed8SAndrew Rybchenko id = EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_DESC_PTR); 8825e111ed8SAndrew Rybchenko label = EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_Q_LABEL); 8835e111ed8SAndrew Rybchenko 8845e111ed8SAndrew Rybchenko EFSYS_PROBE2(tx_complete, uint32_t, label, uint32_t, id); 8855e111ed8SAndrew Rybchenko 8865e111ed8SAndrew Rybchenko EFSYS_ASSERT(eecp->eec_tx != NULL); 8875e111ed8SAndrew Rybchenko should_abort = eecp->eec_tx(arg, label, id); 8885e111ed8SAndrew Rybchenko 8895e111ed8SAndrew Rybchenko return (should_abort); 8905e111ed8SAndrew Rybchenko } 8915e111ed8SAndrew Rybchenko 8925e111ed8SAndrew Rybchenko if (EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_COMP) != 0) 8935e111ed8SAndrew Rybchenko EFSYS_PROBE3(bad_event, unsigned int, eep->ee_index, 8945e111ed8SAndrew Rybchenko uint32_t, EFX_QWORD_FIELD(*eqp, EFX_DWORD_1), 8955e111ed8SAndrew Rybchenko uint32_t, EFX_QWORD_FIELD(*eqp, EFX_DWORD_0)); 8965e111ed8SAndrew Rybchenko 8975e111ed8SAndrew Rybchenko if (EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_PKT_ERR) != 0) 8985e111ed8SAndrew Rybchenko EFX_EV_QSTAT_INCR(eep, EV_TX_PKT_ERR); 8995e111ed8SAndrew Rybchenko 9005e111ed8SAndrew Rybchenko if (EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_PKT_TOO_BIG) != 0) 9015e111ed8SAndrew Rybchenko EFX_EV_QSTAT_INCR(eep, EV_TX_PKT_TOO_BIG); 9025e111ed8SAndrew Rybchenko 9035e111ed8SAndrew Rybchenko if (EFX_QWORD_FIELD(*eqp, FSF_AZ_TX_EV_WQ_FF_FULL) != 0) 9045e111ed8SAndrew Rybchenko EFX_EV_QSTAT_INCR(eep, EV_TX_WQ_FF_FULL); 9055e111ed8SAndrew Rybchenko 9065e111ed8SAndrew Rybchenko EFX_EV_QSTAT_INCR(eep, EV_TX_UNEXPECTED); 9075e111ed8SAndrew Rybchenko return (B_FALSE); 9085e111ed8SAndrew Rybchenko } 9095e111ed8SAndrew Rybchenko 9105e111ed8SAndrew Rybchenko static __checkReturn boolean_t 9115e111ed8SAndrew Rybchenko siena_ev_global( 9125e111ed8SAndrew Rybchenko __in efx_evq_t *eep, 9135e111ed8SAndrew Rybchenko __in efx_qword_t *eqp, 9145e111ed8SAndrew Rybchenko __in const efx_ev_callbacks_t *eecp, 9155e111ed8SAndrew Rybchenko __in_opt void *arg) 9165e111ed8SAndrew Rybchenko { 9175e111ed8SAndrew Rybchenko _NOTE(ARGUNUSED(eqp, eecp, arg)) 9185e111ed8SAndrew Rybchenko 9195e111ed8SAndrew Rybchenko EFX_EV_QSTAT_INCR(eep, EV_GLOBAL); 9205e111ed8SAndrew Rybchenko 9215e111ed8SAndrew Rybchenko return (B_FALSE); 9225e111ed8SAndrew Rybchenko } 9235e111ed8SAndrew Rybchenko 9245e111ed8SAndrew Rybchenko static __checkReturn boolean_t 9255e111ed8SAndrew Rybchenko siena_ev_driver( 9265e111ed8SAndrew Rybchenko __in efx_evq_t *eep, 9275e111ed8SAndrew Rybchenko __in efx_qword_t *eqp, 9285e111ed8SAndrew Rybchenko __in const efx_ev_callbacks_t *eecp, 9295e111ed8SAndrew Rybchenko __in_opt void *arg) 9305e111ed8SAndrew Rybchenko { 9315e111ed8SAndrew Rybchenko boolean_t should_abort; 9325e111ed8SAndrew Rybchenko 9335e111ed8SAndrew Rybchenko EFX_EV_QSTAT_INCR(eep, EV_DRIVER); 9345e111ed8SAndrew Rybchenko should_abort = B_FALSE; 9355e111ed8SAndrew Rybchenko 9365e111ed8SAndrew Rybchenko switch (EFX_QWORD_FIELD(*eqp, FSF_AZ_DRIVER_EV_SUBCODE)) { 9375e111ed8SAndrew Rybchenko case FSE_AZ_TX_DESCQ_FLS_DONE_EV: { 9385e111ed8SAndrew Rybchenko uint32_t txq_index; 9395e111ed8SAndrew Rybchenko 9405e111ed8SAndrew Rybchenko EFX_EV_QSTAT_INCR(eep, EV_DRIVER_TX_DESCQ_FLS_DONE); 9415e111ed8SAndrew Rybchenko 9425e111ed8SAndrew Rybchenko txq_index = EFX_QWORD_FIELD(*eqp, FSF_AZ_DRIVER_EV_SUBDATA); 9435e111ed8SAndrew Rybchenko 9445e111ed8SAndrew Rybchenko EFSYS_PROBE1(tx_descq_fls_done, uint32_t, txq_index); 9455e111ed8SAndrew Rybchenko 9465e111ed8SAndrew Rybchenko EFSYS_ASSERT(eecp->eec_txq_flush_done != NULL); 9475e111ed8SAndrew Rybchenko should_abort = eecp->eec_txq_flush_done(arg, txq_index); 9485e111ed8SAndrew Rybchenko 9495e111ed8SAndrew Rybchenko break; 9505e111ed8SAndrew Rybchenko } 9515e111ed8SAndrew Rybchenko case FSE_AZ_RX_DESCQ_FLS_DONE_EV: { 9525e111ed8SAndrew Rybchenko uint32_t rxq_index; 9535e111ed8SAndrew Rybchenko uint32_t failed; 9545e111ed8SAndrew Rybchenko 9555e111ed8SAndrew Rybchenko rxq_index = EFX_QWORD_FIELD(*eqp, FSF_AZ_DRIVER_EV_RX_DESCQ_ID); 9565e111ed8SAndrew Rybchenko failed = EFX_QWORD_FIELD(*eqp, FSF_AZ_DRIVER_EV_RX_FLUSH_FAIL); 9575e111ed8SAndrew Rybchenko 9585e111ed8SAndrew Rybchenko EFSYS_ASSERT(eecp->eec_rxq_flush_done != NULL); 9595e111ed8SAndrew Rybchenko EFSYS_ASSERT(eecp->eec_rxq_flush_failed != NULL); 9605e111ed8SAndrew Rybchenko 9615e111ed8SAndrew Rybchenko if (failed) { 9625e111ed8SAndrew Rybchenko EFX_EV_QSTAT_INCR(eep, EV_DRIVER_RX_DESCQ_FLS_FAILED); 9635e111ed8SAndrew Rybchenko 9645e111ed8SAndrew Rybchenko EFSYS_PROBE1(rx_descq_fls_failed, uint32_t, rxq_index); 9655e111ed8SAndrew Rybchenko 9665e111ed8SAndrew Rybchenko should_abort = eecp->eec_rxq_flush_failed(arg, 9675e111ed8SAndrew Rybchenko rxq_index); 9685e111ed8SAndrew Rybchenko } else { 9695e111ed8SAndrew Rybchenko EFX_EV_QSTAT_INCR(eep, EV_DRIVER_RX_DESCQ_FLS_DONE); 9705e111ed8SAndrew Rybchenko 9715e111ed8SAndrew Rybchenko EFSYS_PROBE1(rx_descq_fls_done, uint32_t, rxq_index); 9725e111ed8SAndrew Rybchenko 9735e111ed8SAndrew Rybchenko should_abort = eecp->eec_rxq_flush_done(arg, rxq_index); 9745e111ed8SAndrew Rybchenko } 9755e111ed8SAndrew Rybchenko 9765e111ed8SAndrew Rybchenko break; 9775e111ed8SAndrew Rybchenko } 9785e111ed8SAndrew Rybchenko case FSE_AZ_EVQ_INIT_DONE_EV: 9795e111ed8SAndrew Rybchenko EFSYS_ASSERT(eecp->eec_initialized != NULL); 9805e111ed8SAndrew Rybchenko should_abort = eecp->eec_initialized(arg); 9815e111ed8SAndrew Rybchenko 9825e111ed8SAndrew Rybchenko break; 9835e111ed8SAndrew Rybchenko 9845e111ed8SAndrew Rybchenko case FSE_AZ_EVQ_NOT_EN_EV: 9855e111ed8SAndrew Rybchenko EFSYS_PROBE(evq_not_en); 9865e111ed8SAndrew Rybchenko break; 9875e111ed8SAndrew Rybchenko 9885e111ed8SAndrew Rybchenko case FSE_AZ_SRM_UPD_DONE_EV: { 9895e111ed8SAndrew Rybchenko uint32_t code; 9905e111ed8SAndrew Rybchenko 9915e111ed8SAndrew Rybchenko EFX_EV_QSTAT_INCR(eep, EV_DRIVER_SRM_UPD_DONE); 9925e111ed8SAndrew Rybchenko 9935e111ed8SAndrew Rybchenko code = EFX_QWORD_FIELD(*eqp, FSF_AZ_DRIVER_EV_SUBDATA); 9945e111ed8SAndrew Rybchenko 9955e111ed8SAndrew Rybchenko EFSYS_ASSERT(eecp->eec_sram != NULL); 9965e111ed8SAndrew Rybchenko should_abort = eecp->eec_sram(arg, code); 9975e111ed8SAndrew Rybchenko 9985e111ed8SAndrew Rybchenko break; 9995e111ed8SAndrew Rybchenko } 10005e111ed8SAndrew Rybchenko case FSE_AZ_WAKE_UP_EV: { 10015e111ed8SAndrew Rybchenko uint32_t id; 10025e111ed8SAndrew Rybchenko 10035e111ed8SAndrew Rybchenko id = EFX_QWORD_FIELD(*eqp, FSF_AZ_DRIVER_EV_SUBDATA); 10045e111ed8SAndrew Rybchenko 10055e111ed8SAndrew Rybchenko EFSYS_ASSERT(eecp->eec_wake_up != NULL); 10065e111ed8SAndrew Rybchenko should_abort = eecp->eec_wake_up(arg, id); 10075e111ed8SAndrew Rybchenko 10085e111ed8SAndrew Rybchenko break; 10095e111ed8SAndrew Rybchenko } 10105e111ed8SAndrew Rybchenko case FSE_AZ_TX_PKT_NON_TCP_UDP: 10115e111ed8SAndrew Rybchenko EFSYS_PROBE(tx_pkt_non_tcp_udp); 10125e111ed8SAndrew Rybchenko break; 10135e111ed8SAndrew Rybchenko 10145e111ed8SAndrew Rybchenko case FSE_AZ_TIMER_EV: { 10155e111ed8SAndrew Rybchenko uint32_t id; 10165e111ed8SAndrew Rybchenko 10175e111ed8SAndrew Rybchenko id = EFX_QWORD_FIELD(*eqp, FSF_AZ_DRIVER_EV_SUBDATA); 10185e111ed8SAndrew Rybchenko 10195e111ed8SAndrew Rybchenko EFSYS_ASSERT(eecp->eec_timer != NULL); 10205e111ed8SAndrew Rybchenko should_abort = eecp->eec_timer(arg, id); 10215e111ed8SAndrew Rybchenko 10225e111ed8SAndrew Rybchenko break; 10235e111ed8SAndrew Rybchenko } 10245e111ed8SAndrew Rybchenko case FSE_AZ_RX_DSC_ERROR_EV: 10255e111ed8SAndrew Rybchenko EFX_EV_QSTAT_INCR(eep, EV_DRIVER_RX_DSC_ERROR); 10265e111ed8SAndrew Rybchenko 10275e111ed8SAndrew Rybchenko EFSYS_PROBE(rx_dsc_error); 10285e111ed8SAndrew Rybchenko 10295e111ed8SAndrew Rybchenko EFSYS_ASSERT(eecp->eec_exception != NULL); 10305e111ed8SAndrew Rybchenko should_abort = eecp->eec_exception(arg, 10315e111ed8SAndrew Rybchenko EFX_EXCEPTION_RX_DSC_ERROR, 0); 10325e111ed8SAndrew Rybchenko 10335e111ed8SAndrew Rybchenko break; 10345e111ed8SAndrew Rybchenko 10355e111ed8SAndrew Rybchenko case FSE_AZ_TX_DSC_ERROR_EV: 10365e111ed8SAndrew Rybchenko EFX_EV_QSTAT_INCR(eep, EV_DRIVER_TX_DSC_ERROR); 10375e111ed8SAndrew Rybchenko 10385e111ed8SAndrew Rybchenko EFSYS_PROBE(tx_dsc_error); 10395e111ed8SAndrew Rybchenko 10405e111ed8SAndrew Rybchenko EFSYS_ASSERT(eecp->eec_exception != NULL); 10415e111ed8SAndrew Rybchenko should_abort = eecp->eec_exception(arg, 10425e111ed8SAndrew Rybchenko EFX_EXCEPTION_TX_DSC_ERROR, 0); 10435e111ed8SAndrew Rybchenko 10445e111ed8SAndrew Rybchenko break; 10455e111ed8SAndrew Rybchenko 10465e111ed8SAndrew Rybchenko default: 10475e111ed8SAndrew Rybchenko break; 10485e111ed8SAndrew Rybchenko } 10495e111ed8SAndrew Rybchenko 10505e111ed8SAndrew Rybchenko return (should_abort); 10515e111ed8SAndrew Rybchenko } 10525e111ed8SAndrew Rybchenko 10535e111ed8SAndrew Rybchenko static __checkReturn boolean_t 10545e111ed8SAndrew Rybchenko siena_ev_drv_gen( 10555e111ed8SAndrew Rybchenko __in efx_evq_t *eep, 10565e111ed8SAndrew Rybchenko __in efx_qword_t *eqp, 10575e111ed8SAndrew Rybchenko __in const efx_ev_callbacks_t *eecp, 10585e111ed8SAndrew Rybchenko __in_opt void *arg) 10595e111ed8SAndrew Rybchenko { 10605e111ed8SAndrew Rybchenko uint32_t data; 10615e111ed8SAndrew Rybchenko boolean_t should_abort; 10625e111ed8SAndrew Rybchenko 10635e111ed8SAndrew Rybchenko EFX_EV_QSTAT_INCR(eep, EV_DRV_GEN); 10645e111ed8SAndrew Rybchenko 10655e111ed8SAndrew Rybchenko data = EFX_QWORD_FIELD(*eqp, FSF_AZ_EV_DATA_DW0); 10665e111ed8SAndrew Rybchenko if (data >= ((uint32_t)1 << 16)) { 10675e111ed8SAndrew Rybchenko EFSYS_PROBE3(bad_event, unsigned int, eep->ee_index, 10685e111ed8SAndrew Rybchenko uint32_t, EFX_QWORD_FIELD(*eqp, EFX_DWORD_1), 10695e111ed8SAndrew Rybchenko uint32_t, EFX_QWORD_FIELD(*eqp, EFX_DWORD_0)); 10705e111ed8SAndrew Rybchenko return (B_TRUE); 10715e111ed8SAndrew Rybchenko } 10725e111ed8SAndrew Rybchenko 10735e111ed8SAndrew Rybchenko EFSYS_ASSERT(eecp->eec_software != NULL); 10745e111ed8SAndrew Rybchenko should_abort = eecp->eec_software(arg, (uint16_t)data); 10755e111ed8SAndrew Rybchenko 10765e111ed8SAndrew Rybchenko return (should_abort); 10775e111ed8SAndrew Rybchenko } 10785e111ed8SAndrew Rybchenko 10795e111ed8SAndrew Rybchenko #if EFSYS_OPT_MCDI 10805e111ed8SAndrew Rybchenko 10815e111ed8SAndrew Rybchenko static __checkReturn boolean_t 10825e111ed8SAndrew Rybchenko siena_ev_mcdi( 10835e111ed8SAndrew Rybchenko __in efx_evq_t *eep, 10845e111ed8SAndrew Rybchenko __in efx_qword_t *eqp, 10855e111ed8SAndrew Rybchenko __in const efx_ev_callbacks_t *eecp, 10865e111ed8SAndrew Rybchenko __in_opt void *arg) 10875e111ed8SAndrew Rybchenko { 10885e111ed8SAndrew Rybchenko efx_nic_t *enp = eep->ee_enp; 10895e111ed8SAndrew Rybchenko unsigned int code; 10905e111ed8SAndrew Rybchenko boolean_t should_abort = B_FALSE; 10915e111ed8SAndrew Rybchenko 10925e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA); 10935e111ed8SAndrew Rybchenko 10945e111ed8SAndrew Rybchenko if (enp->en_family != EFX_FAMILY_SIENA) 10955e111ed8SAndrew Rybchenko goto out; 10965e111ed8SAndrew Rybchenko 10975e111ed8SAndrew Rybchenko EFSYS_ASSERT(eecp->eec_link_change != NULL); 10985e111ed8SAndrew Rybchenko EFSYS_ASSERT(eecp->eec_exception != NULL); 10995e111ed8SAndrew Rybchenko #if EFSYS_OPT_MON_STATS 11005e111ed8SAndrew Rybchenko EFSYS_ASSERT(eecp->eec_monitor != NULL); 11015e111ed8SAndrew Rybchenko #endif 11025e111ed8SAndrew Rybchenko 11035e111ed8SAndrew Rybchenko EFX_EV_QSTAT_INCR(eep, EV_MCDI_RESPONSE); 11045e111ed8SAndrew Rybchenko 11055e111ed8SAndrew Rybchenko code = EFX_QWORD_FIELD(*eqp, MCDI_EVENT_CODE); 11065e111ed8SAndrew Rybchenko switch (code) { 11075e111ed8SAndrew Rybchenko case MCDI_EVENT_CODE_BADSSERT: 11085e111ed8SAndrew Rybchenko efx_mcdi_ev_death(enp, EINTR); 11095e111ed8SAndrew Rybchenko break; 11105e111ed8SAndrew Rybchenko 11115e111ed8SAndrew Rybchenko case MCDI_EVENT_CODE_CMDDONE: 11125e111ed8SAndrew Rybchenko efx_mcdi_ev_cpl(enp, 11135e111ed8SAndrew Rybchenko MCDI_EV_FIELD(eqp, CMDDONE_SEQ), 11145e111ed8SAndrew Rybchenko MCDI_EV_FIELD(eqp, CMDDONE_DATALEN), 11155e111ed8SAndrew Rybchenko MCDI_EV_FIELD(eqp, CMDDONE_ERRNO)); 11165e111ed8SAndrew Rybchenko break; 11175e111ed8SAndrew Rybchenko 11185e111ed8SAndrew Rybchenko case MCDI_EVENT_CODE_LINKCHANGE: { 11195e111ed8SAndrew Rybchenko efx_link_mode_t link_mode; 11205e111ed8SAndrew Rybchenko 11215e111ed8SAndrew Rybchenko siena_phy_link_ev(enp, eqp, &link_mode); 11225e111ed8SAndrew Rybchenko should_abort = eecp->eec_link_change(arg, link_mode); 11235e111ed8SAndrew Rybchenko break; 11245e111ed8SAndrew Rybchenko } 11255e111ed8SAndrew Rybchenko case MCDI_EVENT_CODE_SENSOREVT: { 11265e111ed8SAndrew Rybchenko #if EFSYS_OPT_MON_STATS 11275e111ed8SAndrew Rybchenko efx_mon_stat_t id; 11285e111ed8SAndrew Rybchenko efx_mon_stat_value_t value; 11295e111ed8SAndrew Rybchenko efx_rc_t rc; 11305e111ed8SAndrew Rybchenko 11315e111ed8SAndrew Rybchenko if ((rc = mcdi_mon_ev(enp, eqp, &id, &value)) == 0) 11325e111ed8SAndrew Rybchenko should_abort = eecp->eec_monitor(arg, id, value); 11335e111ed8SAndrew Rybchenko else if (rc == ENOTSUP) { 11345e111ed8SAndrew Rybchenko should_abort = eecp->eec_exception(arg, 11355e111ed8SAndrew Rybchenko EFX_EXCEPTION_UNKNOWN_SENSOREVT, 11365e111ed8SAndrew Rybchenko MCDI_EV_FIELD(eqp, DATA)); 11375e111ed8SAndrew Rybchenko } else 11385e111ed8SAndrew Rybchenko EFSYS_ASSERT(rc == ENODEV); /* Wrong port */ 11395e111ed8SAndrew Rybchenko #else 11405e111ed8SAndrew Rybchenko should_abort = B_FALSE; 11415e111ed8SAndrew Rybchenko #endif 11425e111ed8SAndrew Rybchenko break; 11435e111ed8SAndrew Rybchenko } 11445e111ed8SAndrew Rybchenko case MCDI_EVENT_CODE_SCHEDERR: 11455e111ed8SAndrew Rybchenko /* Informational only */ 11465e111ed8SAndrew Rybchenko break; 11475e111ed8SAndrew Rybchenko 11485e111ed8SAndrew Rybchenko case MCDI_EVENT_CODE_REBOOT: 11495e111ed8SAndrew Rybchenko efx_mcdi_ev_death(enp, EIO); 11505e111ed8SAndrew Rybchenko break; 11515e111ed8SAndrew Rybchenko 11525e111ed8SAndrew Rybchenko case MCDI_EVENT_CODE_MAC_STATS_DMA: 11535e111ed8SAndrew Rybchenko #if EFSYS_OPT_MAC_STATS 11545e111ed8SAndrew Rybchenko if (eecp->eec_mac_stats != NULL) { 11555e111ed8SAndrew Rybchenko eecp->eec_mac_stats(arg, 11565e111ed8SAndrew Rybchenko MCDI_EV_FIELD(eqp, MAC_STATS_DMA_GENERATION)); 11575e111ed8SAndrew Rybchenko } 11585e111ed8SAndrew Rybchenko #endif 11595e111ed8SAndrew Rybchenko break; 11605e111ed8SAndrew Rybchenko 11615e111ed8SAndrew Rybchenko case MCDI_EVENT_CODE_FWALERT: { 11625e111ed8SAndrew Rybchenko uint32_t reason = MCDI_EV_FIELD(eqp, FWALERT_REASON); 11635e111ed8SAndrew Rybchenko 11645e111ed8SAndrew Rybchenko if (reason == MCDI_EVENT_FWALERT_REASON_SRAM_ACCESS) 11655e111ed8SAndrew Rybchenko should_abort = eecp->eec_exception(arg, 11665e111ed8SAndrew Rybchenko EFX_EXCEPTION_FWALERT_SRAM, 11675e111ed8SAndrew Rybchenko MCDI_EV_FIELD(eqp, FWALERT_DATA)); 11685e111ed8SAndrew Rybchenko else 11695e111ed8SAndrew Rybchenko should_abort = eecp->eec_exception(arg, 11705e111ed8SAndrew Rybchenko EFX_EXCEPTION_UNKNOWN_FWALERT, 11715e111ed8SAndrew Rybchenko MCDI_EV_FIELD(eqp, DATA)); 11725e111ed8SAndrew Rybchenko break; 11735e111ed8SAndrew Rybchenko } 11745e111ed8SAndrew Rybchenko 11755e111ed8SAndrew Rybchenko default: 11765e111ed8SAndrew Rybchenko EFSYS_PROBE1(mc_pcol_error, int, code); 11775e111ed8SAndrew Rybchenko break; 11785e111ed8SAndrew Rybchenko } 11795e111ed8SAndrew Rybchenko 11805e111ed8SAndrew Rybchenko out: 11815e111ed8SAndrew Rybchenko return (should_abort); 11825e111ed8SAndrew Rybchenko } 11835e111ed8SAndrew Rybchenko 11845e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_MCDI */ 11855e111ed8SAndrew Rybchenko 11865e111ed8SAndrew Rybchenko static __checkReturn efx_rc_t 11875e111ed8SAndrew Rybchenko siena_ev_qprime( 11885e111ed8SAndrew Rybchenko __in efx_evq_t *eep, 11895e111ed8SAndrew Rybchenko __in unsigned int count) 11905e111ed8SAndrew Rybchenko { 11915e111ed8SAndrew Rybchenko efx_nic_t *enp = eep->ee_enp; 11925e111ed8SAndrew Rybchenko uint32_t rptr; 11935e111ed8SAndrew Rybchenko efx_dword_t dword; 11945e111ed8SAndrew Rybchenko 11955e111ed8SAndrew Rybchenko rptr = count & eep->ee_mask; 11965e111ed8SAndrew Rybchenko 11975e111ed8SAndrew Rybchenko EFX_POPULATE_DWORD_1(dword, FRF_AZ_EVQ_RPTR, rptr); 11985e111ed8SAndrew Rybchenko 11995e111ed8SAndrew Rybchenko EFX_BAR_TBL_WRITED(enp, FR_AZ_EVQ_RPTR_REG, eep->ee_index, 12005e111ed8SAndrew Rybchenko &dword, B_FALSE); 12015e111ed8SAndrew Rybchenko 12025e111ed8SAndrew Rybchenko return (0); 12035e111ed8SAndrew Rybchenko } 12045e111ed8SAndrew Rybchenko 12055e111ed8SAndrew Rybchenko static void 12065e111ed8SAndrew Rybchenko siena_ev_qpost( 12075e111ed8SAndrew Rybchenko __in efx_evq_t *eep, 12085e111ed8SAndrew Rybchenko __in uint16_t data) 12095e111ed8SAndrew Rybchenko { 12105e111ed8SAndrew Rybchenko efx_nic_t *enp = eep->ee_enp; 12115e111ed8SAndrew Rybchenko efx_qword_t ev; 12125e111ed8SAndrew Rybchenko efx_oword_t oword; 12135e111ed8SAndrew Rybchenko 12145e111ed8SAndrew Rybchenko EFX_POPULATE_QWORD_2(ev, FSF_AZ_EV_CODE, FSE_AZ_EV_CODE_DRV_GEN_EV, 12155e111ed8SAndrew Rybchenko FSF_AZ_EV_DATA_DW0, (uint32_t)data); 12165e111ed8SAndrew Rybchenko 12175e111ed8SAndrew Rybchenko EFX_POPULATE_OWORD_3(oword, FRF_AZ_DRV_EV_QID, eep->ee_index, 12185e111ed8SAndrew Rybchenko EFX_DWORD_0, EFX_QWORD_FIELD(ev, EFX_DWORD_0), 12195e111ed8SAndrew Rybchenko EFX_DWORD_1, EFX_QWORD_FIELD(ev, EFX_DWORD_1)); 12205e111ed8SAndrew Rybchenko 12215e111ed8SAndrew Rybchenko EFX_BAR_WRITEO(enp, FR_AZ_DRV_EV_REG, &oword); 12225e111ed8SAndrew Rybchenko } 12235e111ed8SAndrew Rybchenko 12245e111ed8SAndrew Rybchenko static __checkReturn efx_rc_t 12255e111ed8SAndrew Rybchenko siena_ev_qmoderate( 12265e111ed8SAndrew Rybchenko __in efx_evq_t *eep, 12275e111ed8SAndrew Rybchenko __in unsigned int us) 12285e111ed8SAndrew Rybchenko { 12295e111ed8SAndrew Rybchenko efx_nic_t *enp = eep->ee_enp; 12305e111ed8SAndrew Rybchenko efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 12315e111ed8SAndrew Rybchenko unsigned int locked; 12325e111ed8SAndrew Rybchenko efx_dword_t dword; 12335e111ed8SAndrew Rybchenko efx_rc_t rc; 12345e111ed8SAndrew Rybchenko 12355e111ed8SAndrew Rybchenko if (us > encp->enc_evq_timer_max_us) { 12365e111ed8SAndrew Rybchenko rc = EINVAL; 12375e111ed8SAndrew Rybchenko goto fail1; 12385e111ed8SAndrew Rybchenko } 12395e111ed8SAndrew Rybchenko 12405e111ed8SAndrew Rybchenko /* If the value is zero then disable the timer */ 12415e111ed8SAndrew Rybchenko if (us == 0) { 12425e111ed8SAndrew Rybchenko EFX_POPULATE_DWORD_2(dword, 12435e111ed8SAndrew Rybchenko FRF_CZ_TC_TIMER_MODE, FFE_CZ_TIMER_MODE_DIS, 12445e111ed8SAndrew Rybchenko FRF_CZ_TC_TIMER_VAL, 0); 12455e111ed8SAndrew Rybchenko } else { 12465e111ed8SAndrew Rybchenko unsigned int ticks; 12475e111ed8SAndrew Rybchenko 12485e111ed8SAndrew Rybchenko if ((rc = efx_ev_usecs_to_ticks(enp, us, &ticks)) != 0) 12495e111ed8SAndrew Rybchenko goto fail2; 12505e111ed8SAndrew Rybchenko 12515e111ed8SAndrew Rybchenko EFSYS_ASSERT(ticks > 0); 12525e111ed8SAndrew Rybchenko EFX_POPULATE_DWORD_2(dword, 12535e111ed8SAndrew Rybchenko FRF_CZ_TC_TIMER_MODE, FFE_CZ_TIMER_MODE_INT_HLDOFF, 12545e111ed8SAndrew Rybchenko FRF_CZ_TC_TIMER_VAL, ticks - 1); 12555e111ed8SAndrew Rybchenko } 12565e111ed8SAndrew Rybchenko 12575e111ed8SAndrew Rybchenko locked = (eep->ee_index == 0) ? 1 : 0; 12585e111ed8SAndrew Rybchenko 12595e111ed8SAndrew Rybchenko EFX_BAR_TBL_WRITED(enp, FR_BZ_TIMER_COMMAND_REGP0, 12605e111ed8SAndrew Rybchenko eep->ee_index, &dword, locked); 12615e111ed8SAndrew Rybchenko 12625e111ed8SAndrew Rybchenko return (0); 12635e111ed8SAndrew Rybchenko 12645e111ed8SAndrew Rybchenko fail2: 12655e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2); 12665e111ed8SAndrew Rybchenko fail1: 12675e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 12685e111ed8SAndrew Rybchenko 12695e111ed8SAndrew Rybchenko return (rc); 12705e111ed8SAndrew Rybchenko } 12715e111ed8SAndrew Rybchenko 12725e111ed8SAndrew Rybchenko static __checkReturn efx_rc_t 12735e111ed8SAndrew Rybchenko siena_ev_qcreate( 12745e111ed8SAndrew Rybchenko __in efx_nic_t *enp, 12755e111ed8SAndrew Rybchenko __in unsigned int index, 12765e111ed8SAndrew Rybchenko __in efsys_mem_t *esmp, 12775e111ed8SAndrew Rybchenko __in size_t ndescs, 12785e111ed8SAndrew Rybchenko __in uint32_t id, 12795e111ed8SAndrew Rybchenko __in uint32_t us, 12805e111ed8SAndrew Rybchenko __in uint32_t flags, 12815e111ed8SAndrew Rybchenko __in efx_evq_t *eep) 12825e111ed8SAndrew Rybchenko { 12835e111ed8SAndrew Rybchenko efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 12845e111ed8SAndrew Rybchenko uint32_t size; 12855e111ed8SAndrew Rybchenko efx_oword_t oword; 12865e111ed8SAndrew Rybchenko efx_rc_t rc; 12875e111ed8SAndrew Rybchenko boolean_t notify_mode; 12885e111ed8SAndrew Rybchenko 12895e111ed8SAndrew Rybchenko _NOTE(ARGUNUSED(esmp)) 12905e111ed8SAndrew Rybchenko 1291*f8a60f76SAndy Moreton EFSYS_ASSERT((flags & EFX_EVQ_FLAGS_EXTENDED_WIDTH) == 0); 1292*f8a60f76SAndy Moreton 12935e111ed8SAndrew Rybchenko #if EFSYS_OPT_RX_SCALE 12945e111ed8SAndrew Rybchenko if (enp->en_intr.ei_type == EFX_INTR_LINE && 12955e111ed8SAndrew Rybchenko index >= EFX_MAXRSS_LEGACY) { 12965e111ed8SAndrew Rybchenko rc = EINVAL; 12972e5819a5SAndrew Rybchenko goto fail1; 12985e111ed8SAndrew Rybchenko } 12995e111ed8SAndrew Rybchenko #endif 13005e111ed8SAndrew Rybchenko for (size = 0; 13015e111ed8SAndrew Rybchenko (1U << size) <= encp->enc_evq_max_nevs / encp->enc_evq_min_nevs; 13025e111ed8SAndrew Rybchenko size++) 13035e111ed8SAndrew Rybchenko if ((1U << size) == (uint32_t)ndescs / encp->enc_evq_min_nevs) 13045e111ed8SAndrew Rybchenko break; 13055e111ed8SAndrew Rybchenko if (id + (1 << size) >= encp->enc_buftbl_limit) { 13065e111ed8SAndrew Rybchenko rc = EINVAL; 13072e5819a5SAndrew Rybchenko goto fail2; 13085e111ed8SAndrew Rybchenko } 13095e111ed8SAndrew Rybchenko 13105e111ed8SAndrew Rybchenko /* Set up the handler table */ 13115e111ed8SAndrew Rybchenko eep->ee_rx = siena_ev_rx; 13125e111ed8SAndrew Rybchenko eep->ee_tx = siena_ev_tx; 13135e111ed8SAndrew Rybchenko eep->ee_driver = siena_ev_driver; 13145e111ed8SAndrew Rybchenko eep->ee_global = siena_ev_global; 13155e111ed8SAndrew Rybchenko eep->ee_drv_gen = siena_ev_drv_gen; 13165e111ed8SAndrew Rybchenko #if EFSYS_OPT_MCDI 13175e111ed8SAndrew Rybchenko eep->ee_mcdi = siena_ev_mcdi; 13185e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_MCDI */ 13195e111ed8SAndrew Rybchenko 13205e111ed8SAndrew Rybchenko notify_mode = ((flags & EFX_EVQ_FLAGS_NOTIFY_MASK) != 13215e111ed8SAndrew Rybchenko EFX_EVQ_FLAGS_NOTIFY_INTERRUPT); 13225e111ed8SAndrew Rybchenko 13235e111ed8SAndrew Rybchenko /* Set up the new event queue */ 13245e111ed8SAndrew Rybchenko EFX_POPULATE_OWORD_3(oword, FRF_CZ_TIMER_Q_EN, 1, 13255e111ed8SAndrew Rybchenko FRF_CZ_HOST_NOTIFY_MODE, notify_mode, 13265e111ed8SAndrew Rybchenko FRF_CZ_TIMER_MODE, FFE_CZ_TIMER_MODE_DIS); 13275e111ed8SAndrew Rybchenko EFX_BAR_TBL_WRITEO(enp, FR_AZ_TIMER_TBL, index, &oword, B_TRUE); 13285e111ed8SAndrew Rybchenko 13295e111ed8SAndrew Rybchenko EFX_POPULATE_OWORD_3(oword, FRF_AZ_EVQ_EN, 1, FRF_AZ_EVQ_SIZE, size, 13305e111ed8SAndrew Rybchenko FRF_AZ_EVQ_BUF_BASE_ID, id); 13315e111ed8SAndrew Rybchenko 13325e111ed8SAndrew Rybchenko EFX_BAR_TBL_WRITEO(enp, FR_AZ_EVQ_PTR_TBL, index, &oword, B_TRUE); 13335e111ed8SAndrew Rybchenko 13345e111ed8SAndrew Rybchenko /* Set initial interrupt moderation */ 13355e111ed8SAndrew Rybchenko siena_ev_qmoderate(eep, us); 13365e111ed8SAndrew Rybchenko 13375e111ed8SAndrew Rybchenko return (0); 13385e111ed8SAndrew Rybchenko 13395e111ed8SAndrew Rybchenko fail2: 13405e111ed8SAndrew Rybchenko EFSYS_PROBE(fail2); 13412e5819a5SAndrew Rybchenko #if EFSYS_OPT_RX_SCALE 13425e111ed8SAndrew Rybchenko fail1: 13432e5819a5SAndrew Rybchenko #endif 13445e111ed8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc); 13455e111ed8SAndrew Rybchenko 13465e111ed8SAndrew Rybchenko return (rc); 13475e111ed8SAndrew Rybchenko } 13485e111ed8SAndrew Rybchenko 13495e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_SIENA */ 13505e111ed8SAndrew Rybchenko 13515e111ed8SAndrew Rybchenko #if EFSYS_OPT_QSTATS 13525e111ed8SAndrew Rybchenko #if EFSYS_OPT_NAMES 13535e111ed8SAndrew Rybchenko /* START MKCONFIG GENERATED EfxEventQueueStatNamesBlock ac223f7134058b4f */ 13545e111ed8SAndrew Rybchenko static const char * const __efx_ev_qstat_name[] = { 13555e111ed8SAndrew Rybchenko "all", 13565e111ed8SAndrew Rybchenko "rx", 13575e111ed8SAndrew Rybchenko "rx_ok", 13585e111ed8SAndrew Rybchenko "rx_frm_trunc", 13595e111ed8SAndrew Rybchenko "rx_tobe_disc", 13605e111ed8SAndrew Rybchenko "rx_pause_frm_err", 13615e111ed8SAndrew Rybchenko "rx_buf_owner_id_err", 13625e111ed8SAndrew Rybchenko "rx_ipv4_hdr_chksum_err", 13635e111ed8SAndrew Rybchenko "rx_tcp_udp_chksum_err", 13645e111ed8SAndrew Rybchenko "rx_eth_crc_err", 13655e111ed8SAndrew Rybchenko "rx_ip_frag_err", 13665e111ed8SAndrew Rybchenko "rx_mcast_pkt", 13675e111ed8SAndrew Rybchenko "rx_mcast_hash_match", 13685e111ed8SAndrew Rybchenko "rx_tcp_ipv4", 13695e111ed8SAndrew Rybchenko "rx_tcp_ipv6", 13705e111ed8SAndrew Rybchenko "rx_udp_ipv4", 13715e111ed8SAndrew Rybchenko "rx_udp_ipv6", 13725e111ed8SAndrew Rybchenko "rx_other_ipv4", 13735e111ed8SAndrew Rybchenko "rx_other_ipv6", 13745e111ed8SAndrew Rybchenko "rx_non_ip", 13755e111ed8SAndrew Rybchenko "rx_batch", 13765e111ed8SAndrew Rybchenko "tx", 13775e111ed8SAndrew Rybchenko "tx_wq_ff_full", 13785e111ed8SAndrew Rybchenko "tx_pkt_err", 13795e111ed8SAndrew Rybchenko "tx_pkt_too_big", 13805e111ed8SAndrew Rybchenko "tx_unexpected", 13815e111ed8SAndrew Rybchenko "global", 13825e111ed8SAndrew Rybchenko "global_mnt", 13835e111ed8SAndrew Rybchenko "driver", 13845e111ed8SAndrew Rybchenko "driver_srm_upd_done", 13855e111ed8SAndrew Rybchenko "driver_tx_descq_fls_done", 13865e111ed8SAndrew Rybchenko "driver_rx_descq_fls_done", 13875e111ed8SAndrew Rybchenko "driver_rx_descq_fls_failed", 13885e111ed8SAndrew Rybchenko "driver_rx_dsc_error", 13895e111ed8SAndrew Rybchenko "driver_tx_dsc_error", 13905e111ed8SAndrew Rybchenko "drv_gen", 13915e111ed8SAndrew Rybchenko "mcdi_response", 13925e111ed8SAndrew Rybchenko "rx_parse_incomplete", 13935e111ed8SAndrew Rybchenko }; 13945e111ed8SAndrew Rybchenko /* END MKCONFIG GENERATED EfxEventQueueStatNamesBlock */ 13955e111ed8SAndrew Rybchenko 13965e111ed8SAndrew Rybchenko const char * 13975e111ed8SAndrew Rybchenko efx_ev_qstat_name( 13985e111ed8SAndrew Rybchenko __in efx_nic_t *enp, 13995e111ed8SAndrew Rybchenko __in unsigned int id) 14005e111ed8SAndrew Rybchenko { 14015e111ed8SAndrew Rybchenko _NOTE(ARGUNUSED(enp)) 14025e111ed8SAndrew Rybchenko 14035e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); 14045e111ed8SAndrew Rybchenko EFSYS_ASSERT3U(id, <, EV_NQSTATS); 14055e111ed8SAndrew Rybchenko 14065e111ed8SAndrew Rybchenko return (__efx_ev_qstat_name[id]); 14075e111ed8SAndrew Rybchenko } 14085e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_NAMES */ 14095e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_QSTATS */ 14105e111ed8SAndrew Rybchenko 14115e111ed8SAndrew Rybchenko #if EFSYS_OPT_SIENA 14125e111ed8SAndrew Rybchenko 14135e111ed8SAndrew Rybchenko #if EFSYS_OPT_QSTATS 14145e111ed8SAndrew Rybchenko static void 14155e111ed8SAndrew Rybchenko siena_ev_qstats_update( 14165e111ed8SAndrew Rybchenko __in efx_evq_t *eep, 14175e111ed8SAndrew Rybchenko __inout_ecount(EV_NQSTATS) efsys_stat_t *stat) 14185e111ed8SAndrew Rybchenko { 14195e111ed8SAndrew Rybchenko unsigned int id; 14205e111ed8SAndrew Rybchenko 14215e111ed8SAndrew Rybchenko for (id = 0; id < EV_NQSTATS; id++) { 14225e111ed8SAndrew Rybchenko efsys_stat_t *essp = &stat[id]; 14235e111ed8SAndrew Rybchenko 14245e111ed8SAndrew Rybchenko EFSYS_STAT_INCR(essp, eep->ee_stat[id]); 14255e111ed8SAndrew Rybchenko eep->ee_stat[id] = 0; 14265e111ed8SAndrew Rybchenko } 14275e111ed8SAndrew Rybchenko } 14285e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_QSTATS */ 14295e111ed8SAndrew Rybchenko 14305e111ed8SAndrew Rybchenko static void 14315e111ed8SAndrew Rybchenko siena_ev_qdestroy( 14325e111ed8SAndrew Rybchenko __in efx_evq_t *eep) 14335e111ed8SAndrew Rybchenko { 14345e111ed8SAndrew Rybchenko efx_nic_t *enp = eep->ee_enp; 14355e111ed8SAndrew Rybchenko efx_oword_t oword; 14365e111ed8SAndrew Rybchenko 14375e111ed8SAndrew Rybchenko /* Purge event queue */ 14385e111ed8SAndrew Rybchenko EFX_ZERO_OWORD(oword); 14395e111ed8SAndrew Rybchenko 14405e111ed8SAndrew Rybchenko EFX_BAR_TBL_WRITEO(enp, FR_AZ_EVQ_PTR_TBL, 14415e111ed8SAndrew Rybchenko eep->ee_index, &oword, B_TRUE); 14425e111ed8SAndrew Rybchenko 14435e111ed8SAndrew Rybchenko EFX_ZERO_OWORD(oword); 14445e111ed8SAndrew Rybchenko EFX_BAR_TBL_WRITEO(enp, FR_AZ_TIMER_TBL, eep->ee_index, &oword, B_TRUE); 14455e111ed8SAndrew Rybchenko } 14465e111ed8SAndrew Rybchenko 14475e111ed8SAndrew Rybchenko static void 14485e111ed8SAndrew Rybchenko siena_ev_fini( 14495e111ed8SAndrew Rybchenko __in efx_nic_t *enp) 14505e111ed8SAndrew Rybchenko { 14515e111ed8SAndrew Rybchenko _NOTE(ARGUNUSED(enp)) 14525e111ed8SAndrew Rybchenko } 14535e111ed8SAndrew Rybchenko 14545e111ed8SAndrew Rybchenko #endif /* EFSYS_OPT_SIENA */ 1455ad1e3ed8SAndrew Rybchenko 1456ad1e3ed8SAndrew Rybchenko #if EFX_OPTS_EF10() || EFSYS_OPT_SIENA 1457ad1e3ed8SAndrew Rybchenko 1458ad1e3ed8SAndrew Rybchenko #define EFX_EV_BATCH 8 1459ad1e3ed8SAndrew Rybchenko 1460ad1e3ed8SAndrew Rybchenko static void 1461ad1e3ed8SAndrew Rybchenko siena_ef10_ev_qpoll( 1462ad1e3ed8SAndrew Rybchenko __in efx_evq_t *eep, 1463ad1e3ed8SAndrew Rybchenko __inout unsigned int *countp, 1464ad1e3ed8SAndrew Rybchenko __in const efx_ev_callbacks_t *eecp, 1465ad1e3ed8SAndrew Rybchenko __in_opt void *arg) 1466ad1e3ed8SAndrew Rybchenko { 1467ad1e3ed8SAndrew Rybchenko efx_qword_t ev[EFX_EV_BATCH]; 1468ad1e3ed8SAndrew Rybchenko unsigned int batch; 1469ad1e3ed8SAndrew Rybchenko unsigned int total; 1470ad1e3ed8SAndrew Rybchenko unsigned int count; 1471ad1e3ed8SAndrew Rybchenko unsigned int index; 1472ad1e3ed8SAndrew Rybchenko size_t offset; 1473ad1e3ed8SAndrew Rybchenko 1474ad1e3ed8SAndrew Rybchenko /* Ensure events codes match for EF10 (Huntington/Medford) and Siena */ 1475ad1e3ed8SAndrew Rybchenko EFX_STATIC_ASSERT(ESF_DZ_EV_CODE_LBN == FSF_AZ_EV_CODE_LBN); 1476ad1e3ed8SAndrew Rybchenko EFX_STATIC_ASSERT(ESF_DZ_EV_CODE_WIDTH == FSF_AZ_EV_CODE_WIDTH); 1477ad1e3ed8SAndrew Rybchenko 1478ad1e3ed8SAndrew Rybchenko EFX_STATIC_ASSERT(ESE_DZ_EV_CODE_RX_EV == FSE_AZ_EV_CODE_RX_EV); 1479ad1e3ed8SAndrew Rybchenko EFX_STATIC_ASSERT(ESE_DZ_EV_CODE_TX_EV == FSE_AZ_EV_CODE_TX_EV); 1480ad1e3ed8SAndrew Rybchenko EFX_STATIC_ASSERT(ESE_DZ_EV_CODE_DRIVER_EV == FSE_AZ_EV_CODE_DRIVER_EV); 1481ad1e3ed8SAndrew Rybchenko EFX_STATIC_ASSERT(ESE_DZ_EV_CODE_DRV_GEN_EV == 1482ad1e3ed8SAndrew Rybchenko FSE_AZ_EV_CODE_DRV_GEN_EV); 1483ad1e3ed8SAndrew Rybchenko #if EFSYS_OPT_MCDI 1484ad1e3ed8SAndrew Rybchenko EFX_STATIC_ASSERT(ESE_DZ_EV_CODE_MCDI_EV == 1485ad1e3ed8SAndrew Rybchenko FSE_AZ_EV_CODE_MCDI_EVRESPONSE); 1486ad1e3ed8SAndrew Rybchenko #endif 1487ad1e3ed8SAndrew Rybchenko 1488ad1e3ed8SAndrew Rybchenko EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC); 1489ad1e3ed8SAndrew Rybchenko EFSYS_ASSERT(countp != NULL); 1490ad1e3ed8SAndrew Rybchenko EFSYS_ASSERT(eecp != NULL); 1491ad1e3ed8SAndrew Rybchenko 1492ad1e3ed8SAndrew Rybchenko count = *countp; 1493ad1e3ed8SAndrew Rybchenko do { 1494ad1e3ed8SAndrew Rybchenko /* Read up until the end of the batch period */ 1495ad1e3ed8SAndrew Rybchenko batch = EFX_EV_BATCH - (count & (EFX_EV_BATCH - 1)); 1496ad1e3ed8SAndrew Rybchenko offset = (count & eep->ee_mask) * sizeof (efx_qword_t); 1497ad1e3ed8SAndrew Rybchenko for (total = 0; total < batch; ++total) { 1498ad1e3ed8SAndrew Rybchenko EFSYS_MEM_READQ(eep->ee_esmp, offset, &(ev[total])); 1499ad1e3ed8SAndrew Rybchenko 1500ad1e3ed8SAndrew Rybchenko if (!EFX_EV_PRESENT(ev[total])) 1501ad1e3ed8SAndrew Rybchenko break; 1502ad1e3ed8SAndrew Rybchenko 1503ad1e3ed8SAndrew Rybchenko EFSYS_PROBE3(event, unsigned int, eep->ee_index, 1504ad1e3ed8SAndrew Rybchenko uint32_t, EFX_QWORD_FIELD(ev[total], EFX_DWORD_1), 1505ad1e3ed8SAndrew Rybchenko uint32_t, EFX_QWORD_FIELD(ev[total], EFX_DWORD_0)); 1506ad1e3ed8SAndrew Rybchenko 1507ad1e3ed8SAndrew Rybchenko offset += sizeof (efx_qword_t); 1508ad1e3ed8SAndrew Rybchenko } 1509ad1e3ed8SAndrew Rybchenko 1510ad1e3ed8SAndrew Rybchenko #if EFSYS_OPT_EV_PREFETCH && (EFSYS_OPT_EV_PREFETCH_PERIOD > 1) 1511ad1e3ed8SAndrew Rybchenko /* 1512ad1e3ed8SAndrew Rybchenko * Prefetch the next batch when we get within PREFETCH_PERIOD 1513ad1e3ed8SAndrew Rybchenko * of a completed batch. If the batch is smaller, then prefetch 1514ad1e3ed8SAndrew Rybchenko * immediately. 1515ad1e3ed8SAndrew Rybchenko */ 1516ad1e3ed8SAndrew Rybchenko if (total == batch && total < EFSYS_OPT_EV_PREFETCH_PERIOD) 1517ad1e3ed8SAndrew Rybchenko EFSYS_MEM_PREFETCH(eep->ee_esmp, offset); 1518ad1e3ed8SAndrew Rybchenko #endif /* EFSYS_OPT_EV_PREFETCH */ 1519ad1e3ed8SAndrew Rybchenko 1520ad1e3ed8SAndrew Rybchenko /* Process the batch of events */ 1521ad1e3ed8SAndrew Rybchenko for (index = 0; index < total; ++index) { 1522ad1e3ed8SAndrew Rybchenko boolean_t should_abort; 1523ad1e3ed8SAndrew Rybchenko uint32_t code; 1524ad1e3ed8SAndrew Rybchenko 1525ad1e3ed8SAndrew Rybchenko #if EFSYS_OPT_EV_PREFETCH 1526ad1e3ed8SAndrew Rybchenko /* Prefetch if we've now reached the batch period */ 1527ad1e3ed8SAndrew Rybchenko if (total == batch && 1528ad1e3ed8SAndrew Rybchenko index + EFSYS_OPT_EV_PREFETCH_PERIOD == total) { 1529ad1e3ed8SAndrew Rybchenko offset = (count + batch) & eep->ee_mask; 1530ad1e3ed8SAndrew Rybchenko offset *= sizeof (efx_qword_t); 1531ad1e3ed8SAndrew Rybchenko 1532ad1e3ed8SAndrew Rybchenko EFSYS_MEM_PREFETCH(eep->ee_esmp, offset); 1533ad1e3ed8SAndrew Rybchenko } 1534ad1e3ed8SAndrew Rybchenko #endif /* EFSYS_OPT_EV_PREFETCH */ 1535ad1e3ed8SAndrew Rybchenko 1536ad1e3ed8SAndrew Rybchenko EFX_EV_QSTAT_INCR(eep, EV_ALL); 1537ad1e3ed8SAndrew Rybchenko 1538ad1e3ed8SAndrew Rybchenko code = EFX_QWORD_FIELD(ev[index], FSF_AZ_EV_CODE); 1539ad1e3ed8SAndrew Rybchenko switch (code) { 1540ad1e3ed8SAndrew Rybchenko case FSE_AZ_EV_CODE_RX_EV: 1541ad1e3ed8SAndrew Rybchenko should_abort = eep->ee_rx(eep, 1542ad1e3ed8SAndrew Rybchenko &(ev[index]), eecp, arg); 1543ad1e3ed8SAndrew Rybchenko break; 1544ad1e3ed8SAndrew Rybchenko case FSE_AZ_EV_CODE_TX_EV: 1545ad1e3ed8SAndrew Rybchenko should_abort = eep->ee_tx(eep, 1546ad1e3ed8SAndrew Rybchenko &(ev[index]), eecp, arg); 1547ad1e3ed8SAndrew Rybchenko break; 1548ad1e3ed8SAndrew Rybchenko case FSE_AZ_EV_CODE_DRIVER_EV: 1549ad1e3ed8SAndrew Rybchenko should_abort = eep->ee_driver(eep, 1550ad1e3ed8SAndrew Rybchenko &(ev[index]), eecp, arg); 1551ad1e3ed8SAndrew Rybchenko break; 1552ad1e3ed8SAndrew Rybchenko case FSE_AZ_EV_CODE_DRV_GEN_EV: 1553ad1e3ed8SAndrew Rybchenko should_abort = eep->ee_drv_gen(eep, 1554ad1e3ed8SAndrew Rybchenko &(ev[index]), eecp, arg); 1555ad1e3ed8SAndrew Rybchenko break; 1556ad1e3ed8SAndrew Rybchenko #if EFSYS_OPT_MCDI 1557ad1e3ed8SAndrew Rybchenko case FSE_AZ_EV_CODE_MCDI_EVRESPONSE: 1558ad1e3ed8SAndrew Rybchenko should_abort = eep->ee_mcdi(eep, 1559ad1e3ed8SAndrew Rybchenko &(ev[index]), eecp, arg); 1560ad1e3ed8SAndrew Rybchenko break; 1561ad1e3ed8SAndrew Rybchenko #endif 1562ad1e3ed8SAndrew Rybchenko case FSE_AZ_EV_CODE_GLOBAL_EV: 1563ad1e3ed8SAndrew Rybchenko if (eep->ee_global) { 1564ad1e3ed8SAndrew Rybchenko should_abort = eep->ee_global(eep, 1565ad1e3ed8SAndrew Rybchenko &(ev[index]), eecp, arg); 1566ad1e3ed8SAndrew Rybchenko break; 1567ad1e3ed8SAndrew Rybchenko } 1568ad1e3ed8SAndrew Rybchenko /* else fallthrough */ 1569ad1e3ed8SAndrew Rybchenko default: 1570ad1e3ed8SAndrew Rybchenko EFSYS_PROBE3(bad_event, 1571ad1e3ed8SAndrew Rybchenko unsigned int, eep->ee_index, 1572ad1e3ed8SAndrew Rybchenko uint32_t, 1573ad1e3ed8SAndrew Rybchenko EFX_QWORD_FIELD(ev[index], EFX_DWORD_1), 1574ad1e3ed8SAndrew Rybchenko uint32_t, 1575ad1e3ed8SAndrew Rybchenko EFX_QWORD_FIELD(ev[index], EFX_DWORD_0)); 1576ad1e3ed8SAndrew Rybchenko 1577ad1e3ed8SAndrew Rybchenko EFSYS_ASSERT(eecp->eec_exception != NULL); 1578ad1e3ed8SAndrew Rybchenko (void) eecp->eec_exception(arg, 1579ad1e3ed8SAndrew Rybchenko EFX_EXCEPTION_EV_ERROR, code); 1580ad1e3ed8SAndrew Rybchenko should_abort = B_TRUE; 1581ad1e3ed8SAndrew Rybchenko } 1582ad1e3ed8SAndrew Rybchenko if (should_abort) { 1583ad1e3ed8SAndrew Rybchenko /* Ignore subsequent events */ 1584ad1e3ed8SAndrew Rybchenko total = index + 1; 1585ad1e3ed8SAndrew Rybchenko 1586ad1e3ed8SAndrew Rybchenko /* 1587ad1e3ed8SAndrew Rybchenko * Poison batch to ensure the outer 1588ad1e3ed8SAndrew Rybchenko * loop is broken out of. 1589ad1e3ed8SAndrew Rybchenko */ 1590ad1e3ed8SAndrew Rybchenko EFSYS_ASSERT(batch <= EFX_EV_BATCH); 1591ad1e3ed8SAndrew Rybchenko batch += (EFX_EV_BATCH << 1); 1592ad1e3ed8SAndrew Rybchenko EFSYS_ASSERT(total != batch); 1593ad1e3ed8SAndrew Rybchenko break; 1594ad1e3ed8SAndrew Rybchenko } 1595ad1e3ed8SAndrew Rybchenko } 1596ad1e3ed8SAndrew Rybchenko 1597ad1e3ed8SAndrew Rybchenko /* 1598ad1e3ed8SAndrew Rybchenko * Now that the hardware has most likely moved onto dma'ing 1599ad1e3ed8SAndrew Rybchenko * into the next cache line, clear the processed events. Take 1600ad1e3ed8SAndrew Rybchenko * care to only clear out events that we've processed 1601ad1e3ed8SAndrew Rybchenko */ 1602ad1e3ed8SAndrew Rybchenko EFX_SET_QWORD(ev[0]); 1603ad1e3ed8SAndrew Rybchenko offset = (count & eep->ee_mask) * sizeof (efx_qword_t); 1604ad1e3ed8SAndrew Rybchenko for (index = 0; index < total; ++index) { 1605ad1e3ed8SAndrew Rybchenko EFSYS_MEM_WRITEQ(eep->ee_esmp, offset, &(ev[0])); 1606ad1e3ed8SAndrew Rybchenko offset += sizeof (efx_qword_t); 1607ad1e3ed8SAndrew Rybchenko } 1608ad1e3ed8SAndrew Rybchenko 1609ad1e3ed8SAndrew Rybchenko count += total; 1610ad1e3ed8SAndrew Rybchenko 1611ad1e3ed8SAndrew Rybchenko } while (total == batch); 1612ad1e3ed8SAndrew Rybchenko 1613ad1e3ed8SAndrew Rybchenko *countp = count; 1614ad1e3ed8SAndrew Rybchenko } 1615ad1e3ed8SAndrew Rybchenko 1616ad1e3ed8SAndrew Rybchenko #endif /* EFX_OPTS_EF10() || EFSYS_OPT_SIENA */ 1617