1283514Sarybchik/*- 2301388Sarybchik * Copyright (c) 2012-2016 Solarflare Communications Inc. 3283514Sarybchik * All rights reserved. 4283514Sarybchik * 5283514Sarybchik * Redistribution and use in source and binary forms, with or without 6283514Sarybchik * modification, are permitted provided that the following conditions are met: 7283514Sarybchik * 8283514Sarybchik * 1. Redistributions of source code must retain the above copyright notice, 9283514Sarybchik * this list of conditions and the following disclaimer. 10283514Sarybchik * 2. Redistributions in binary form must reproduce the above copyright notice, 11283514Sarybchik * this list of conditions and the following disclaimer in the documentation 12283514Sarybchik * and/or other materials provided with the distribution. 13283514Sarybchik * 14283514Sarybchik * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15283514Sarybchik * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16283514Sarybchik * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17283514Sarybchik * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 18283514Sarybchik * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19283514Sarybchik * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20283514Sarybchik * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21283514Sarybchik * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22283514Sarybchik * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23283514Sarybchik * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 24283514Sarybchik * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25283514Sarybchik * 26283514Sarybchik * The views and conclusions contained in the software and documentation are 27283514Sarybchik * those of the authors and should not be interpreted as representing official 28283514Sarybchik * policies, either expressed or implied, of the FreeBSD Project. 29283514Sarybchik */ 30283514Sarybchik 31283514Sarybchik#include <sys/cdefs.h> 32283514Sarybchik__FBSDID("$FreeBSD: stable/10/sys/dev/sfxge/common/ef10_ev.c 342516 2018-12-26 10:25:01Z arybchik $"); 33283514Sarybchik 34283514Sarybchik#include "efx.h" 35283514Sarybchik#include "efx_impl.h" 36283514Sarybchik#if EFSYS_OPT_MON_STATS 37283514Sarybchik#include "mcdi_mon.h" 38283514Sarybchik#endif 39283514Sarybchik 40299596Sarybchik#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD 41283514Sarybchik 42283514Sarybchik#if EFSYS_OPT_QSTATS 43283514Sarybchik#define EFX_EV_QSTAT_INCR(_eep, _stat) \ 44283514Sarybchik do { \ 45283514Sarybchik (_eep)->ee_stat[_stat]++; \ 46283514Sarybchik _NOTE(CONSTANTCONDITION) \ 47283514Sarybchik } while (B_FALSE) 48283514Sarybchik#else 49283514Sarybchik#define EFX_EV_QSTAT_INCR(_eep, _stat) 50283514Sarybchik#endif 51283514Sarybchik 52311094Sarybchik/* 53311094Sarybchik * Non-interrupting event queue requires interrrupting event queue to 54311094Sarybchik * refer to for wake-up events even if wake ups are never used. 55311094Sarybchik * It could be even non-allocated event queue. 56311094Sarybchik */ 57311094Sarybchik#define EFX_EF10_ALWAYS_INTERRUPTING_EVQ_INDEX (0) 58283514Sarybchik 59283514Sarybchikstatic __checkReturn boolean_t 60293752Sarybchikef10_ev_rx( 61283514Sarybchik __in efx_evq_t *eep, 62283514Sarybchik __in efx_qword_t *eqp, 63283514Sarybchik __in const efx_ev_callbacks_t *eecp, 64283514Sarybchik __in_opt void *arg); 65283514Sarybchik 66283514Sarybchikstatic __checkReturn boolean_t 67293752Sarybchikef10_ev_tx( 68283514Sarybchik __in efx_evq_t *eep, 69283514Sarybchik __in efx_qword_t *eqp, 70283514Sarybchik __in const efx_ev_callbacks_t *eecp, 71283514Sarybchik __in_opt void *arg); 72283514Sarybchik 73283514Sarybchikstatic __checkReturn boolean_t 74293752Sarybchikef10_ev_driver( 75283514Sarybchik __in efx_evq_t *eep, 76283514Sarybchik __in efx_qword_t *eqp, 77283514Sarybchik __in const efx_ev_callbacks_t *eecp, 78283514Sarybchik __in_opt void *arg); 79283514Sarybchik 80283514Sarybchikstatic __checkReturn boolean_t 81293752Sarybchikef10_ev_drv_gen( 82283514Sarybchik __in efx_evq_t *eep, 83283514Sarybchik __in efx_qword_t *eqp, 84283514Sarybchik __in const efx_ev_callbacks_t *eecp, 85283514Sarybchik __in_opt void *arg); 86283514Sarybchik 87283514Sarybchikstatic __checkReturn boolean_t 88293752Sarybchikef10_ev_mcdi( 89283514Sarybchik __in efx_evq_t *eep, 90283514Sarybchik __in efx_qword_t *eqp, 91283514Sarybchik __in const efx_ev_callbacks_t *eecp, 92283514Sarybchik __in_opt void *arg); 93283514Sarybchik 94283514Sarybchik 95291436Sarybchikstatic __checkReturn efx_rc_t 96301983Sarybchikefx_mcdi_set_evq_tmr( 97301983Sarybchik __in efx_nic_t *enp, 98301983Sarybchik __in uint32_t instance, 99301983Sarybchik __in uint32_t mode, 100301983Sarybchik __in uint32_t timer_ns) 101301983Sarybchik{ 102301983Sarybchik efx_mcdi_req_t req; 103342516Sarybchik EFX_MCDI_DECLARE_BUF(payload, MC_CMD_SET_EVQ_TMR_IN_LEN, 104342516Sarybchik MC_CMD_SET_EVQ_TMR_OUT_LEN); 105301983Sarybchik efx_rc_t rc; 106301983Sarybchik 107301983Sarybchik req.emr_cmd = MC_CMD_SET_EVQ_TMR; 108301983Sarybchik req.emr_in_buf = payload; 109301983Sarybchik req.emr_in_length = MC_CMD_SET_EVQ_TMR_IN_LEN; 110301983Sarybchik req.emr_out_buf = payload; 111301983Sarybchik req.emr_out_length = MC_CMD_SET_EVQ_TMR_OUT_LEN; 112301983Sarybchik 113301983Sarybchik MCDI_IN_SET_DWORD(req, SET_EVQ_TMR_IN_INSTANCE, instance); 114301983Sarybchik MCDI_IN_SET_DWORD(req, SET_EVQ_TMR_IN_TMR_LOAD_REQ_NS, timer_ns); 115301983Sarybchik MCDI_IN_SET_DWORD(req, SET_EVQ_TMR_IN_TMR_RELOAD_REQ_NS, timer_ns); 116301983Sarybchik MCDI_IN_SET_DWORD(req, SET_EVQ_TMR_IN_TMR_MODE, mode); 117301983Sarybchik 118301983Sarybchik efx_mcdi_execute(enp, &req); 119301983Sarybchik 120301983Sarybchik if (req.emr_rc != 0) { 121301983Sarybchik rc = req.emr_rc; 122301983Sarybchik goto fail1; 123301983Sarybchik } 124301983Sarybchik 125301983Sarybchik if (req.emr_out_length_used < MC_CMD_SET_EVQ_TMR_OUT_LEN) { 126301983Sarybchik rc = EMSGSIZE; 127301983Sarybchik goto fail2; 128301983Sarybchik } 129301983Sarybchik 130301983Sarybchik return (0); 131301983Sarybchik 132301983Sarybchikfail2: 133301983Sarybchik EFSYS_PROBE(fail2); 134301983Sarybchikfail1: 135301983Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 136301983Sarybchik 137301983Sarybchik return (rc); 138301983Sarybchik} 139301983Sarybchik 140301983Sarybchikstatic __checkReturn efx_rc_t 141283514Sarybchikefx_mcdi_init_evq( 142283514Sarybchik __in efx_nic_t *enp, 143283514Sarybchik __in unsigned int instance, 144283514Sarybchik __in efsys_mem_t *esmp, 145283514Sarybchik __in size_t nevs, 146301980Sarybchik __in uint32_t irq, 147301986Sarybchik __in uint32_t us, 148311070Sarybchik __in uint32_t flags, 149301986Sarybchik __in boolean_t low_latency) 150283514Sarybchik{ 151283514Sarybchik efx_mcdi_req_t req; 152342516Sarybchik EFX_MCDI_DECLARE_BUF(payload, 153342516Sarybchik MC_CMD_INIT_EVQ_IN_LEN(EFX_EVQ_NBUFS(EFX_EVQ_MAXNEVS)), 154342516Sarybchik MC_CMD_INIT_EVQ_OUT_LEN); 155283514Sarybchik efx_qword_t *dma_addr; 156283514Sarybchik uint64_t addr; 157283514Sarybchik int npages; 158283514Sarybchik int i; 159311094Sarybchik boolean_t interrupting; 160301986Sarybchik int ev_cut_through; 161291436Sarybchik efx_rc_t rc; 162283514Sarybchik 163283514Sarybchik npages = EFX_EVQ_NBUFS(nevs); 164283514Sarybchik if (MC_CMD_INIT_EVQ_IN_LEN(npages) > MC_CMD_INIT_EVQ_IN_LENMAX) { 165283514Sarybchik rc = EINVAL; 166283514Sarybchik goto fail1; 167283514Sarybchik } 168283514Sarybchik 169283514Sarybchik req.emr_cmd = MC_CMD_INIT_EVQ; 170283514Sarybchik req.emr_in_buf = payload; 171283514Sarybchik req.emr_in_length = MC_CMD_INIT_EVQ_IN_LEN(npages); 172283514Sarybchik req.emr_out_buf = payload; 173283514Sarybchik req.emr_out_length = MC_CMD_INIT_EVQ_OUT_LEN; 174283514Sarybchik 175283514Sarybchik MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_SIZE, nevs); 176283514Sarybchik MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_INSTANCE, instance); 177283514Sarybchik MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_IRQ_NUM, irq); 178283514Sarybchik 179311094Sarybchik interrupting = ((flags & EFX_EVQ_FLAGS_NOTIFY_MASK) == 180311094Sarybchik EFX_EVQ_FLAGS_NOTIFY_INTERRUPT); 181311094Sarybchik 182283514Sarybchik /* 183301986Sarybchik * On Huntington RX and TX event batching can only be requested together 184301986Sarybchik * (even if the datapath firmware doesn't actually support RX 185301986Sarybchik * batching). If event cut through is enabled no RX batching will occur. 186283514Sarybchik * 187301986Sarybchik * So always enable RX and TX event batching, and enable event cut 188301986Sarybchik * through if we want low latency operation. 189283514Sarybchik */ 190311070Sarybchik switch (flags & EFX_EVQ_FLAGS_TYPE_MASK) { 191311070Sarybchik case EFX_EVQ_FLAGS_TYPE_AUTO: 192311070Sarybchik ev_cut_through = low_latency ? 1 : 0; 193311070Sarybchik break; 194311070Sarybchik case EFX_EVQ_FLAGS_TYPE_THROUGHPUT: 195311070Sarybchik ev_cut_through = 0; 196311070Sarybchik break; 197311070Sarybchik case EFX_EVQ_FLAGS_TYPE_LOW_LATENCY: 198311070Sarybchik ev_cut_through = 1; 199311070Sarybchik break; 200311070Sarybchik default: 201311070Sarybchik rc = EINVAL; 202311070Sarybchik goto fail2; 203311070Sarybchik } 204283514Sarybchik MCDI_IN_POPULATE_DWORD_6(req, INIT_EVQ_IN_FLAGS, 205311094Sarybchik INIT_EVQ_IN_FLAG_INTERRUPTING, interrupting, 206283514Sarybchik INIT_EVQ_IN_FLAG_RPTR_DOS, 0, 207283514Sarybchik INIT_EVQ_IN_FLAG_INT_ARMD, 0, 208301986Sarybchik INIT_EVQ_IN_FLAG_CUT_THRU, ev_cut_through, 209283514Sarybchik INIT_EVQ_IN_FLAG_RX_MERGE, 1, 210283514Sarybchik INIT_EVQ_IN_FLAG_TX_MERGE, 1); 211283514Sarybchik 212301984Sarybchik /* If the value is zero then disable the timer */ 213301980Sarybchik if (us == 0) { 214301980Sarybchik MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_MODE, 215301980Sarybchik MC_CMD_INIT_EVQ_IN_TMR_MODE_DIS); 216301980Sarybchik MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_LOAD, 0); 217301980Sarybchik MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_RELOAD, 0); 218301980Sarybchik } else { 219301984Sarybchik unsigned int ticks; 220283514Sarybchik 221301984Sarybchik if ((rc = efx_ev_usecs_to_ticks(enp, us, &ticks)) != 0) 222311070Sarybchik goto fail3; 223301980Sarybchik 224301980Sarybchik MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_MODE, 225301980Sarybchik MC_CMD_INIT_EVQ_IN_TMR_INT_HLDOFF); 226301984Sarybchik MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_LOAD, ticks); 227301984Sarybchik MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_RELOAD, ticks); 228301980Sarybchik } 229301980Sarybchik 230283514Sarybchik MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_COUNT_MODE, 231283514Sarybchik MC_CMD_INIT_EVQ_IN_COUNT_MODE_DIS); 232283514Sarybchik MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_COUNT_THRSHLD, 0); 233283514Sarybchik 234283514Sarybchik dma_addr = MCDI_IN2(req, efx_qword_t, INIT_EVQ_IN_DMA_ADDR); 235283514Sarybchik addr = EFSYS_MEM_ADDR(esmp); 236283514Sarybchik 237283514Sarybchik for (i = 0; i < npages; i++) { 238283514Sarybchik EFX_POPULATE_QWORD_2(*dma_addr, 239283514Sarybchik EFX_DWORD_1, (uint32_t)(addr >> 32), 240283514Sarybchik EFX_DWORD_0, (uint32_t)(addr & 0xffffffff)); 241283514Sarybchik 242283514Sarybchik dma_addr++; 243283514Sarybchik addr += EFX_BUF_SIZE; 244283514Sarybchik } 245283514Sarybchik 246283514Sarybchik efx_mcdi_execute(enp, &req); 247283514Sarybchik 248283514Sarybchik if (req.emr_rc != 0) { 249283514Sarybchik rc = req.emr_rc; 250311070Sarybchik goto fail4; 251283514Sarybchik } 252283514Sarybchik 253283514Sarybchik if (req.emr_out_length_used < MC_CMD_INIT_EVQ_OUT_LEN) { 254283514Sarybchik rc = EMSGSIZE; 255311070Sarybchik goto fail5; 256283514Sarybchik } 257283514Sarybchik 258301375Sarybchik /* NOTE: ignore the returned IRQ param as firmware does not set it. */ 259283514Sarybchik 260283514Sarybchik return (0); 261283514Sarybchik 262311070Sarybchikfail5: 263311070Sarybchik EFSYS_PROBE(fail5); 264301984Sarybchikfail4: 265301984Sarybchik EFSYS_PROBE(fail4); 266283514Sarybchikfail3: 267283514Sarybchik EFSYS_PROBE(fail3); 268283514Sarybchikfail2: 269283514Sarybchik EFSYS_PROBE(fail2); 270283514Sarybchikfail1: 271291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 272283514Sarybchik 273283514Sarybchik return (rc); 274283514Sarybchik} 275283514Sarybchik 276301986Sarybchik 277291436Sarybchikstatic __checkReturn efx_rc_t 278301986Sarybchikefx_mcdi_init_evq_v2( 279301986Sarybchik __in efx_nic_t *enp, 280301986Sarybchik __in unsigned int instance, 281301986Sarybchik __in efsys_mem_t *esmp, 282301986Sarybchik __in size_t nevs, 283301986Sarybchik __in uint32_t irq, 284311070Sarybchik __in uint32_t us, 285311070Sarybchik __in uint32_t flags) 286301986Sarybchik{ 287301986Sarybchik efx_mcdi_req_t req; 288342516Sarybchik EFX_MCDI_DECLARE_BUF(payload, 289342516Sarybchik MC_CMD_INIT_EVQ_V2_IN_LEN(EFX_EVQ_NBUFS(EFX_EVQ_MAXNEVS)), 290342516Sarybchik MC_CMD_INIT_EVQ_V2_OUT_LEN); 291311094Sarybchik boolean_t interrupting; 292311070Sarybchik unsigned int evq_type; 293301986Sarybchik efx_qword_t *dma_addr; 294301986Sarybchik uint64_t addr; 295301986Sarybchik int npages; 296301986Sarybchik int i; 297301986Sarybchik efx_rc_t rc; 298301986Sarybchik 299301986Sarybchik npages = EFX_EVQ_NBUFS(nevs); 300301986Sarybchik if (MC_CMD_INIT_EVQ_V2_IN_LEN(npages) > MC_CMD_INIT_EVQ_V2_IN_LENMAX) { 301301986Sarybchik rc = EINVAL; 302301986Sarybchik goto fail1; 303301986Sarybchik } 304301986Sarybchik 305301986Sarybchik req.emr_cmd = MC_CMD_INIT_EVQ; 306301986Sarybchik req.emr_in_buf = payload; 307301986Sarybchik req.emr_in_length = MC_CMD_INIT_EVQ_V2_IN_LEN(npages); 308301986Sarybchik req.emr_out_buf = payload; 309301986Sarybchik req.emr_out_length = MC_CMD_INIT_EVQ_V2_OUT_LEN; 310301986Sarybchik 311301986Sarybchik MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_SIZE, nevs); 312301986Sarybchik MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_INSTANCE, instance); 313301986Sarybchik MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_IRQ_NUM, irq); 314301986Sarybchik 315311094Sarybchik interrupting = ((flags & EFX_EVQ_FLAGS_NOTIFY_MASK) == 316311094Sarybchik EFX_EVQ_FLAGS_NOTIFY_INTERRUPT); 317311094Sarybchik 318311070Sarybchik switch (flags & EFX_EVQ_FLAGS_TYPE_MASK) { 319311070Sarybchik case EFX_EVQ_FLAGS_TYPE_AUTO: 320311070Sarybchik evq_type = MC_CMD_INIT_EVQ_V2_IN_FLAG_TYPE_AUTO; 321311070Sarybchik break; 322311070Sarybchik case EFX_EVQ_FLAGS_TYPE_THROUGHPUT: 323311070Sarybchik evq_type = MC_CMD_INIT_EVQ_V2_IN_FLAG_TYPE_THROUGHPUT; 324311070Sarybchik break; 325311070Sarybchik case EFX_EVQ_FLAGS_TYPE_LOW_LATENCY: 326311070Sarybchik evq_type = MC_CMD_INIT_EVQ_V2_IN_FLAG_TYPE_LOW_LATENCY; 327311070Sarybchik break; 328311070Sarybchik default: 329311070Sarybchik rc = EINVAL; 330311070Sarybchik goto fail2; 331311070Sarybchik } 332301986Sarybchik MCDI_IN_POPULATE_DWORD_4(req, INIT_EVQ_V2_IN_FLAGS, 333311094Sarybchik INIT_EVQ_V2_IN_FLAG_INTERRUPTING, interrupting, 334301986Sarybchik INIT_EVQ_V2_IN_FLAG_RPTR_DOS, 0, 335301986Sarybchik INIT_EVQ_V2_IN_FLAG_INT_ARMD, 0, 336311070Sarybchik INIT_EVQ_V2_IN_FLAG_TYPE, evq_type); 337301986Sarybchik 338301986Sarybchik /* If the value is zero then disable the timer */ 339301986Sarybchik if (us == 0) { 340301986Sarybchik MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_TMR_MODE, 341301986Sarybchik MC_CMD_INIT_EVQ_V2_IN_TMR_MODE_DIS); 342301986Sarybchik MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_TMR_LOAD, 0); 343301986Sarybchik MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_TMR_RELOAD, 0); 344301986Sarybchik } else { 345301986Sarybchik unsigned int ticks; 346301986Sarybchik 347301986Sarybchik if ((rc = efx_ev_usecs_to_ticks(enp, us, &ticks)) != 0) 348311070Sarybchik goto fail3; 349301986Sarybchik 350301986Sarybchik MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_TMR_MODE, 351301986Sarybchik MC_CMD_INIT_EVQ_V2_IN_TMR_INT_HLDOFF); 352301986Sarybchik MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_TMR_LOAD, ticks); 353301986Sarybchik MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_TMR_RELOAD, ticks); 354301986Sarybchik } 355301986Sarybchik 356301986Sarybchik MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_COUNT_MODE, 357301986Sarybchik MC_CMD_INIT_EVQ_V2_IN_COUNT_MODE_DIS); 358301986Sarybchik MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_COUNT_THRSHLD, 0); 359301986Sarybchik 360301986Sarybchik dma_addr = MCDI_IN2(req, efx_qword_t, INIT_EVQ_V2_IN_DMA_ADDR); 361301986Sarybchik addr = EFSYS_MEM_ADDR(esmp); 362301986Sarybchik 363301986Sarybchik for (i = 0; i < npages; i++) { 364301986Sarybchik EFX_POPULATE_QWORD_2(*dma_addr, 365301986Sarybchik EFX_DWORD_1, (uint32_t)(addr >> 32), 366301986Sarybchik EFX_DWORD_0, (uint32_t)(addr & 0xffffffff)); 367301986Sarybchik 368301986Sarybchik dma_addr++; 369301986Sarybchik addr += EFX_BUF_SIZE; 370301986Sarybchik } 371301986Sarybchik 372301986Sarybchik efx_mcdi_execute(enp, &req); 373301986Sarybchik 374301986Sarybchik if (req.emr_rc != 0) { 375301986Sarybchik rc = req.emr_rc; 376311070Sarybchik goto fail4; 377301986Sarybchik } 378301986Sarybchik 379301986Sarybchik if (req.emr_out_length_used < MC_CMD_INIT_EVQ_V2_OUT_LEN) { 380301986Sarybchik rc = EMSGSIZE; 381311070Sarybchik goto fail5; 382301986Sarybchik } 383301986Sarybchik 384301986Sarybchik /* NOTE: ignore the returned IRQ param as firmware does not set it. */ 385301986Sarybchik 386301986Sarybchik EFSYS_PROBE1(mcdi_evq_flags, uint32_t, 387301986Sarybchik MCDI_OUT_DWORD(req, INIT_EVQ_V2_OUT_FLAGS)); 388301986Sarybchik 389301986Sarybchik return (0); 390301986Sarybchik 391311070Sarybchikfail5: 392311070Sarybchik EFSYS_PROBE(fail5); 393301986Sarybchikfail4: 394301986Sarybchik EFSYS_PROBE(fail4); 395301986Sarybchikfail3: 396301986Sarybchik EFSYS_PROBE(fail3); 397301986Sarybchikfail2: 398301986Sarybchik EFSYS_PROBE(fail2); 399301986Sarybchikfail1: 400301986Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 401301986Sarybchik 402301986Sarybchik return (rc); 403301986Sarybchik} 404301986Sarybchik 405301986Sarybchikstatic __checkReturn efx_rc_t 406283514Sarybchikefx_mcdi_fini_evq( 407283514Sarybchik __in efx_nic_t *enp, 408283514Sarybchik __in uint32_t instance) 409283514Sarybchik{ 410283514Sarybchik efx_mcdi_req_t req; 411342516Sarybchik EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FINI_EVQ_IN_LEN, 412342516Sarybchik MC_CMD_FINI_EVQ_OUT_LEN); 413291436Sarybchik efx_rc_t rc; 414283514Sarybchik 415283514Sarybchik req.emr_cmd = MC_CMD_FINI_EVQ; 416283514Sarybchik req.emr_in_buf = payload; 417283514Sarybchik req.emr_in_length = MC_CMD_FINI_EVQ_IN_LEN; 418283514Sarybchik req.emr_out_buf = payload; 419283514Sarybchik req.emr_out_length = MC_CMD_FINI_EVQ_OUT_LEN; 420283514Sarybchik 421283514Sarybchik MCDI_IN_SET_DWORD(req, FINI_EVQ_IN_INSTANCE, instance); 422283514Sarybchik 423301378Sarybchik efx_mcdi_execute_quiet(enp, &req); 424283514Sarybchik 425283514Sarybchik if (req.emr_rc != 0) { 426283514Sarybchik rc = req.emr_rc; 427283514Sarybchik goto fail1; 428283514Sarybchik } 429283514Sarybchik 430283514Sarybchik return (0); 431283514Sarybchik 432283514Sarybchikfail1: 433342483Sarybchik /* 434342483Sarybchik * EALREADY is not an error, but indicates that the MC has rebooted and 435342483Sarybchik * that the EVQ has already been destroyed. 436342483Sarybchik */ 437342483Sarybchik if (rc != EALREADY) 438342483Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 439283514Sarybchik 440283514Sarybchik return (rc); 441283514Sarybchik} 442283514Sarybchik 443283514Sarybchik 444283514Sarybchik 445291436Sarybchik __checkReturn efx_rc_t 446293752Sarybchikef10_ev_init( 447283514Sarybchik __in efx_nic_t *enp) 448283514Sarybchik{ 449283514Sarybchik _NOTE(ARGUNUSED(enp)) 450283514Sarybchik return (0); 451283514Sarybchik} 452283514Sarybchik 453283514Sarybchik void 454293752Sarybchikef10_ev_fini( 455283514Sarybchik __in efx_nic_t *enp) 456283514Sarybchik{ 457283514Sarybchik _NOTE(ARGUNUSED(enp)) 458283514Sarybchik} 459283514Sarybchik 460291436Sarybchik __checkReturn efx_rc_t 461293752Sarybchikef10_ev_qcreate( 462283514Sarybchik __in efx_nic_t *enp, 463283514Sarybchik __in unsigned int index, 464283514Sarybchik __in efsys_mem_t *esmp, 465283514Sarybchik __in size_t n, 466283514Sarybchik __in uint32_t id, 467301980Sarybchik __in uint32_t us, 468311070Sarybchik __in uint32_t flags, 469283514Sarybchik __in efx_evq_t *eep) 470283514Sarybchik{ 471283514Sarybchik efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 472283514Sarybchik uint32_t irq; 473291436Sarybchik efx_rc_t rc; 474283514Sarybchik 475283514Sarybchik _NOTE(ARGUNUSED(id)) /* buftbl id managed by MC */ 476283514Sarybchik EFX_STATIC_ASSERT(ISP2(EFX_EVQ_MAXNEVS)); 477283514Sarybchik EFX_STATIC_ASSERT(ISP2(EFX_EVQ_MINNEVS)); 478283514Sarybchik 479283514Sarybchik if (!ISP2(n) || (n < EFX_EVQ_MINNEVS) || (n > EFX_EVQ_MAXNEVS)) { 480283514Sarybchik rc = EINVAL; 481283514Sarybchik goto fail1; 482283514Sarybchik } 483283514Sarybchik 484283514Sarybchik if (index >= encp->enc_evq_limit) { 485283514Sarybchik rc = EINVAL; 486283514Sarybchik goto fail2; 487283514Sarybchik } 488283514Sarybchik 489301980Sarybchik if (us > encp->enc_evq_timer_max_us) { 490301980Sarybchik rc = EINVAL; 491301980Sarybchik goto fail3; 492301980Sarybchik } 493301980Sarybchik 494283514Sarybchik /* Set up the handler table */ 495293752Sarybchik eep->ee_rx = ef10_ev_rx; 496293752Sarybchik eep->ee_tx = ef10_ev_tx; 497293752Sarybchik eep->ee_driver = ef10_ev_driver; 498293752Sarybchik eep->ee_drv_gen = ef10_ev_drv_gen; 499293752Sarybchik eep->ee_mcdi = ef10_ev_mcdi; 500283514Sarybchik 501301375Sarybchik /* Set up the event queue */ 502311094Sarybchik /* INIT_EVQ expects function-relative vector number */ 503311094Sarybchik if ((flags & EFX_EVQ_FLAGS_NOTIFY_MASK) == 504311094Sarybchik EFX_EVQ_FLAGS_NOTIFY_INTERRUPT) { 505311094Sarybchik irq = index; 506311094Sarybchik } else if (index == EFX_EF10_ALWAYS_INTERRUPTING_EVQ_INDEX) { 507311094Sarybchik irq = index; 508311094Sarybchik flags = (flags & ~EFX_EVQ_FLAGS_NOTIFY_MASK) | 509311094Sarybchik EFX_EVQ_FLAGS_NOTIFY_INTERRUPT; 510311094Sarybchik } else { 511311094Sarybchik irq = EFX_EF10_ALWAYS_INTERRUPTING_EVQ_INDEX; 512311094Sarybchik } 513301386Sarybchik 514301386Sarybchik /* 515301386Sarybchik * Interrupts may be raised for events immediately after the queue is 516301386Sarybchik * created. See bug58606. 517301386Sarybchik */ 518283514Sarybchik 519301986Sarybchik if (encp->enc_init_evq_v2_supported) { 520301986Sarybchik /* 521301986Sarybchik * On Medford the low latency license is required to enable RX 522311070Sarybchik * and event cut through and to disable RX batching. If event 523311070Sarybchik * queue type in flags is auto, we let the firmware decide the 524311070Sarybchik * settings to use. If the adapter has a low latency license, 525311070Sarybchik * it will choose the best settings for low latency, otherwise 526311070Sarybchik * it will choose the best settings for throughput. 527301986Sarybchik */ 528311070Sarybchik rc = efx_mcdi_init_evq_v2(enp, index, esmp, n, irq, us, flags); 529301986Sarybchik if (rc != 0) 530301986Sarybchik goto fail4; 531301986Sarybchik } else { 532301986Sarybchik /* 533311070Sarybchik * On Huntington we need to specify the settings to use. 534311070Sarybchik * If event queue type in flags is auto, we favour throughput 535311070Sarybchik * if the adapter is running virtualization supporting firmware 536311070Sarybchik * (i.e. the full featured firmware variant) 537311070Sarybchik * and latency otherwise. The Ethernet Virtual Bridging 538311070Sarybchik * capability is used to make this decision. (Note though that 539311070Sarybchik * the low latency firmware variant is also best for 540311070Sarybchik * throughput and corresponding type should be specified 541311070Sarybchik * to choose it.) 542301986Sarybchik */ 543311070Sarybchik boolean_t low_latency = encp->enc_datapath_cap_evb ? 0 : 1; 544311070Sarybchik rc = efx_mcdi_init_evq(enp, index, esmp, n, irq, us, flags, 545311070Sarybchik low_latency); 546301986Sarybchik if (rc != 0) 547301986Sarybchik goto fail5; 548301986Sarybchik } 549301986Sarybchik 550283514Sarybchik return (0); 551283514Sarybchik 552301986Sarybchikfail5: 553301986Sarybchik EFSYS_PROBE(fail5); 554301980Sarybchikfail4: 555301980Sarybchik EFSYS_PROBE(fail4); 556283514Sarybchikfail3: 557283514Sarybchik EFSYS_PROBE(fail3); 558283514Sarybchikfail2: 559283514Sarybchik EFSYS_PROBE(fail2); 560283514Sarybchikfail1: 561291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 562283514Sarybchik 563283514Sarybchik return (rc); 564283514Sarybchik} 565283514Sarybchik 566283514Sarybchik void 567293752Sarybchikef10_ev_qdestroy( 568283514Sarybchik __in efx_evq_t *eep) 569283514Sarybchik{ 570283514Sarybchik efx_nic_t *enp = eep->ee_enp; 571283514Sarybchik 572293752Sarybchik EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 573293752Sarybchik enp->en_family == EFX_FAMILY_MEDFORD); 574283514Sarybchik 575342502Sarybchik (void) efx_mcdi_fini_evq(enp, eep->ee_index); 576283514Sarybchik} 577283514Sarybchik 578291436Sarybchik __checkReturn efx_rc_t 579293752Sarybchikef10_ev_qprime( 580283514Sarybchik __in efx_evq_t *eep, 581283514Sarybchik __in unsigned int count) 582283514Sarybchik{ 583283514Sarybchik efx_nic_t *enp = eep->ee_enp; 584283514Sarybchik uint32_t rptr; 585283514Sarybchik efx_dword_t dword; 586283514Sarybchik 587283514Sarybchik rptr = count & eep->ee_mask; 588283514Sarybchik 589283514Sarybchik if (enp->en_nic_cfg.enc_bug35388_workaround) { 590283514Sarybchik EFX_STATIC_ASSERT(EFX_EVQ_MINNEVS > 591283514Sarybchik (1 << ERF_DD_EVQ_IND_RPTR_WIDTH)); 592283514Sarybchik EFX_STATIC_ASSERT(EFX_EVQ_MAXNEVS < 593283514Sarybchik (1 << 2 * ERF_DD_EVQ_IND_RPTR_WIDTH)); 594283514Sarybchik 595283514Sarybchik EFX_POPULATE_DWORD_2(dword, 596283514Sarybchik ERF_DD_EVQ_IND_RPTR_FLAGS, 597283514Sarybchik EFE_DD_EVQ_IND_RPTR_FLAGS_HIGH, 598283514Sarybchik ERF_DD_EVQ_IND_RPTR, 599283514Sarybchik (rptr >> ERF_DD_EVQ_IND_RPTR_WIDTH)); 600283514Sarybchik EFX_BAR_TBL_WRITED(enp, ER_DD_EVQ_INDIRECT, eep->ee_index, 601283514Sarybchik &dword, B_FALSE); 602283514Sarybchik 603283514Sarybchik EFX_POPULATE_DWORD_2(dword, 604283514Sarybchik ERF_DD_EVQ_IND_RPTR_FLAGS, 605283514Sarybchik EFE_DD_EVQ_IND_RPTR_FLAGS_LOW, 606283514Sarybchik ERF_DD_EVQ_IND_RPTR, 607283514Sarybchik rptr & ((1 << ERF_DD_EVQ_IND_RPTR_WIDTH) - 1)); 608283514Sarybchik EFX_BAR_TBL_WRITED(enp, ER_DD_EVQ_INDIRECT, eep->ee_index, 609283514Sarybchik &dword, B_FALSE); 610283514Sarybchik } else { 611283514Sarybchik EFX_POPULATE_DWORD_1(dword, ERF_DZ_EVQ_RPTR, rptr); 612283514Sarybchik EFX_BAR_TBL_WRITED(enp, ER_DZ_EVQ_RPTR_REG, eep->ee_index, 613283514Sarybchik &dword, B_FALSE); 614283514Sarybchik } 615283514Sarybchik 616283514Sarybchik return (0); 617283514Sarybchik} 618283514Sarybchik 619291436Sarybchikstatic __checkReturn efx_rc_t 620283514Sarybchikefx_mcdi_driver_event( 621283514Sarybchik __in efx_nic_t *enp, 622283514Sarybchik __in uint32_t evq, 623283514Sarybchik __in efx_qword_t data) 624283514Sarybchik{ 625283514Sarybchik efx_mcdi_req_t req; 626342516Sarybchik EFX_MCDI_DECLARE_BUF(payload, MC_CMD_DRIVER_EVENT_IN_LEN, 627342516Sarybchik MC_CMD_DRIVER_EVENT_OUT_LEN); 628291436Sarybchik efx_rc_t rc; 629283514Sarybchik 630283514Sarybchik req.emr_cmd = MC_CMD_DRIVER_EVENT; 631283514Sarybchik req.emr_in_buf = payload; 632283514Sarybchik req.emr_in_length = MC_CMD_DRIVER_EVENT_IN_LEN; 633283514Sarybchik req.emr_out_buf = payload; 634283514Sarybchik req.emr_out_length = MC_CMD_DRIVER_EVENT_OUT_LEN; 635283514Sarybchik 636283514Sarybchik MCDI_IN_SET_DWORD(req, DRIVER_EVENT_IN_EVQ, evq); 637283514Sarybchik 638283514Sarybchik MCDI_IN_SET_DWORD(req, DRIVER_EVENT_IN_DATA_LO, 639283514Sarybchik EFX_QWORD_FIELD(data, EFX_DWORD_0)); 640283514Sarybchik MCDI_IN_SET_DWORD(req, DRIVER_EVENT_IN_DATA_HI, 641283514Sarybchik EFX_QWORD_FIELD(data, EFX_DWORD_1)); 642283514Sarybchik 643283514Sarybchik efx_mcdi_execute(enp, &req); 644283514Sarybchik 645283514Sarybchik if (req.emr_rc != 0) { 646283514Sarybchik rc = req.emr_rc; 647283514Sarybchik goto fail1; 648283514Sarybchik } 649283514Sarybchik 650283514Sarybchik return (0); 651283514Sarybchik 652283514Sarybchikfail1: 653291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 654283514Sarybchik 655283514Sarybchik return (rc); 656283514Sarybchik} 657283514Sarybchik 658283514Sarybchik void 659293752Sarybchikef10_ev_qpost( 660283514Sarybchik __in efx_evq_t *eep, 661283514Sarybchik __in uint16_t data) 662283514Sarybchik{ 663283514Sarybchik efx_nic_t *enp = eep->ee_enp; 664283514Sarybchik efx_qword_t event; 665283514Sarybchik 666283514Sarybchik EFX_POPULATE_QWORD_3(event, 667283514Sarybchik ESF_DZ_DRV_CODE, ESE_DZ_EV_CODE_DRV_GEN_EV, 668283514Sarybchik ESF_DZ_DRV_SUB_CODE, 0, 669283514Sarybchik ESF_DZ_DRV_SUB_DATA_DW0, (uint32_t)data); 670283514Sarybchik 671283514Sarybchik (void) efx_mcdi_driver_event(enp, eep->ee_index, event); 672283514Sarybchik} 673283514Sarybchik 674291436Sarybchik __checkReturn efx_rc_t 675293752Sarybchikef10_ev_qmoderate( 676283514Sarybchik __in efx_evq_t *eep, 677283514Sarybchik __in unsigned int us) 678283514Sarybchik{ 679283514Sarybchik efx_nic_t *enp = eep->ee_enp; 680283514Sarybchik efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 681283514Sarybchik efx_dword_t dword; 682301984Sarybchik uint32_t mode; 683291436Sarybchik efx_rc_t rc; 684283514Sarybchik 685301983Sarybchik /* Check that hardware and MCDI use the same timer MODE values */ 686301983Sarybchik EFX_STATIC_ASSERT(FFE_CZ_TIMER_MODE_DIS == 687301983Sarybchik MC_CMD_SET_EVQ_TMR_IN_TIMER_MODE_DIS); 688301983Sarybchik EFX_STATIC_ASSERT(FFE_CZ_TIMER_MODE_IMMED_START == 689301983Sarybchik MC_CMD_SET_EVQ_TMR_IN_TIMER_MODE_IMMED_START); 690301983Sarybchik EFX_STATIC_ASSERT(FFE_CZ_TIMER_MODE_TRIG_START == 691301983Sarybchik MC_CMD_SET_EVQ_TMR_IN_TIMER_MODE_TRIG_START); 692301983Sarybchik EFX_STATIC_ASSERT(FFE_CZ_TIMER_MODE_INT_HLDOFF == 693301983Sarybchik MC_CMD_SET_EVQ_TMR_IN_TIMER_MODE_INT_HLDOFF); 694301983Sarybchik 695283514Sarybchik if (us > encp->enc_evq_timer_max_us) { 696283514Sarybchik rc = EINVAL; 697283514Sarybchik goto fail1; 698283514Sarybchik } 699283514Sarybchik 700283514Sarybchik /* If the value is zero then disable the timer */ 701283514Sarybchik if (us == 0) { 702283514Sarybchik mode = FFE_CZ_TIMER_MODE_DIS; 703283514Sarybchik } else { 704301983Sarybchik mode = FFE_CZ_TIMER_MODE_INT_HLDOFF; 705301983Sarybchik } 706301983Sarybchik 707301983Sarybchik if (encp->enc_bug61265_workaround) { 708301984Sarybchik uint32_t ns = us * 1000; 709301984Sarybchik 710301984Sarybchik rc = efx_mcdi_set_evq_tmr(enp, eep->ee_index, mode, ns); 711301983Sarybchik if (rc != 0) 712301983Sarybchik goto fail2; 713301983Sarybchik } else { 714301984Sarybchik unsigned int ticks; 715283514Sarybchik 716301984Sarybchik if ((rc = efx_ev_usecs_to_ticks(enp, us, &ticks)) != 0) 717301984Sarybchik goto fail3; 718283514Sarybchik 719301983Sarybchik if (encp->enc_bug35388_workaround) { 720301983Sarybchik EFX_POPULATE_DWORD_3(dword, 721301983Sarybchik ERF_DD_EVQ_IND_TIMER_FLAGS, 722301983Sarybchik EFE_DD_EVQ_IND_TIMER_FLAGS, 723301983Sarybchik ERF_DD_EVQ_IND_TIMER_MODE, mode, 724301984Sarybchik ERF_DD_EVQ_IND_TIMER_VAL, ticks); 725301983Sarybchik EFX_BAR_TBL_WRITED(enp, ER_DD_EVQ_INDIRECT, 726301983Sarybchik eep->ee_index, &dword, 0); 727301983Sarybchik } else { 728301983Sarybchik EFX_POPULATE_DWORD_2(dword, 729301983Sarybchik ERF_DZ_TC_TIMER_MODE, mode, 730301984Sarybchik ERF_DZ_TC_TIMER_VAL, ticks); 731301983Sarybchik EFX_BAR_TBL_WRITED(enp, ER_DZ_EVQ_TMR_REG, 732301983Sarybchik eep->ee_index, &dword, 0); 733301983Sarybchik } 734283514Sarybchik } 735283514Sarybchik 736283514Sarybchik return (0); 737283514Sarybchik 738301984Sarybchikfail3: 739301984Sarybchik EFSYS_PROBE(fail3); 740301983Sarybchikfail2: 741301983Sarybchik EFSYS_PROBE(fail2); 742283514Sarybchikfail1: 743291436Sarybchik EFSYS_PROBE1(fail1, efx_rc_t, rc); 744283514Sarybchik 745283514Sarybchik return (rc); 746283514Sarybchik} 747283514Sarybchik 748283514Sarybchik 749283514Sarybchik#if EFSYS_OPT_QSTATS 750283514Sarybchik void 751293752Sarybchikef10_ev_qstats_update( 752283514Sarybchik __in efx_evq_t *eep, 753283514Sarybchik __inout_ecount(EV_NQSTATS) efsys_stat_t *stat) 754283514Sarybchik{ 755283514Sarybchik unsigned int id; 756283514Sarybchik 757283514Sarybchik for (id = 0; id < EV_NQSTATS; id++) { 758283514Sarybchik efsys_stat_t *essp = &stat[id]; 759283514Sarybchik 760283514Sarybchik EFSYS_STAT_INCR(essp, eep->ee_stat[id]); 761283514Sarybchik eep->ee_stat[id] = 0; 762283514Sarybchik } 763283514Sarybchik} 764283514Sarybchik#endif /* EFSYS_OPT_QSTATS */ 765283514Sarybchik 766283514Sarybchik 767283514Sarybchikstatic __checkReturn boolean_t 768293752Sarybchikef10_ev_rx( 769283514Sarybchik __in efx_evq_t *eep, 770283514Sarybchik __in efx_qword_t *eqp, 771283514Sarybchik __in const efx_ev_callbacks_t *eecp, 772283514Sarybchik __in_opt void *arg) 773283514Sarybchik{ 774283514Sarybchik efx_nic_t *enp = eep->ee_enp; 775283514Sarybchik uint32_t size; 776283514Sarybchik uint32_t label; 777294310Sarybchik uint32_t mac_class; 778283514Sarybchik uint32_t eth_tag_class; 779283514Sarybchik uint32_t l3_class; 780283514Sarybchik uint32_t l4_class; 781283514Sarybchik uint32_t next_read_lbits; 782283514Sarybchik uint16_t flags; 783294310Sarybchik boolean_t cont; 784283514Sarybchik boolean_t should_abort; 785283514Sarybchik efx_evq_rxq_state_t *eersp; 786283514Sarybchik unsigned int desc_count; 787283514Sarybchik unsigned int last_used_id; 788283514Sarybchik 789283514Sarybchik EFX_EV_QSTAT_INCR(eep, EV_RX); 790283514Sarybchik 791283514Sarybchik /* Discard events after RXQ/TXQ errors */ 792283514Sarybchik if (enp->en_reset_flags & (EFX_RESET_RXQ_ERR | EFX_RESET_TXQ_ERR)) 793283514Sarybchik return (B_FALSE); 794283514Sarybchik 795294310Sarybchik /* Basic packet information */ 796294310Sarybchik size = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_BYTES); 797294310Sarybchik next_read_lbits = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_DSC_PTR_LBITS); 798294310Sarybchik label = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_QLABEL); 799294310Sarybchik eth_tag_class = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_ETH_TAG_CLASS); 800294310Sarybchik mac_class = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_MAC_CLASS); 801294310Sarybchik l3_class = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_L3_CLASS); 802294310Sarybchik l4_class = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_L4_CLASS); 803294310Sarybchik cont = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_CONT); 804283514Sarybchik 805283514Sarybchik if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_DROP_EVENT) != 0) { 806283514Sarybchik /* Drop this event */ 807283514Sarybchik return (B_FALSE); 808283514Sarybchik } 809283514Sarybchik flags = 0; 810283514Sarybchik 811294310Sarybchik if (cont != 0) { 812283514Sarybchik /* 813291747Sarybchik * This may be part of a scattered frame, or it may be a 814291747Sarybchik * truncated frame if scatter is disabled on this RXQ. 815291747Sarybchik * Overlength frames can be received if e.g. a VF is configured 816291747Sarybchik * for 1500 MTU but connected to a port set to 9000 MTU 817291747Sarybchik * (see bug56567). 818283514Sarybchik * FIXME: There is not yet any driver that supports scatter on 819283514Sarybchik * Huntington. Scatter support is required for OSX. 820283514Sarybchik */ 821283514Sarybchik flags |= EFX_PKT_CONT; 822283514Sarybchik } 823283514Sarybchik 824294310Sarybchik if (mac_class == ESE_DZ_MAC_CLASS_UCAST) 825283514Sarybchik flags |= EFX_PKT_UNICAST; 826283514Sarybchik 827283514Sarybchik /* Increment the count of descriptors read */ 828283514Sarybchik eersp = &eep->ee_rxq_state[label]; 829283514Sarybchik desc_count = (next_read_lbits - eersp->eers_rx_read_ptr) & 830283514Sarybchik EFX_MASK32(ESF_DZ_RX_DSC_PTR_LBITS); 831283514Sarybchik eersp->eers_rx_read_ptr += desc_count; 832283514Sarybchik 833283514Sarybchik /* 834283514Sarybchik * FIXME: add error checking to make sure this a batched event. 835283514Sarybchik * This could also be an aborted scatter, see Bug36629. 836283514Sarybchik */ 837283514Sarybchik if (desc_count > 1) { 838283514Sarybchik EFX_EV_QSTAT_INCR(eep, EV_RX_BATCH); 839283514Sarybchik flags |= EFX_PKT_PREFIX_LEN; 840283514Sarybchik } 841283514Sarybchik 842283514Sarybchik /* Calculate the index of the the last descriptor consumed */ 843283514Sarybchik last_used_id = (eersp->eers_rx_read_ptr - 1) & eersp->eers_rx_mask; 844283514Sarybchik 845294310Sarybchik /* Check for errors that invalidate checksum and L3/L4 fields */ 846294310Sarybchik if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_ECC_ERR) != 0) { 847294310Sarybchik /* RX frame truncated (error flag is misnamed) */ 848294310Sarybchik EFX_EV_QSTAT_INCR(eep, EV_RX_FRM_TRUNC); 849294310Sarybchik flags |= EFX_DISCARD; 850294310Sarybchik goto deliver; 851283514Sarybchik } 852294310Sarybchik if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_ECRC_ERR) != 0) { 853294310Sarybchik /* Bad Ethernet frame CRC */ 854294310Sarybchik EFX_EV_QSTAT_INCR(eep, EV_RX_ETH_CRC_ERR); 855294310Sarybchik flags |= EFX_DISCARD; 856294310Sarybchik goto deliver; 857294310Sarybchik } 858294310Sarybchik if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_PARSE_INCOMPLETE)) { 859294310Sarybchik /* 860294310Sarybchik * Hardware parse failed, due to malformed headers 861294310Sarybchik * or headers that are too long for the parser. 862294310Sarybchik * Headers and checksums must be validated by the host. 863294310Sarybchik */ 864311050Sarybchik /* TODO: EFX_EV_QSTAT_INCR(eep, EV_RX_PARSE_INCOMPLETE); */ 865294310Sarybchik goto deliver; 866294310Sarybchik } 867283514Sarybchik 868294310Sarybchik if ((eth_tag_class == ESE_DZ_ETH_TAG_CLASS_VLAN1) || 869294310Sarybchik (eth_tag_class == ESE_DZ_ETH_TAG_CLASS_VLAN2)) { 870283514Sarybchik flags |= EFX_PKT_VLAN_TAGGED; 871283514Sarybchik } 872283514Sarybchik 873283514Sarybchik switch (l3_class) { 874294310Sarybchik case ESE_DZ_L3_CLASS_IP4: 875294310Sarybchik case ESE_DZ_L3_CLASS_IP4_FRAG: 876294310Sarybchik flags |= EFX_PKT_IPV4; 877294310Sarybchik if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_IPCKSUM_ERR)) { 878294310Sarybchik EFX_EV_QSTAT_INCR(eep, EV_RX_IPV4_HDR_CHKSUM_ERR); 879294310Sarybchik } else { 880294310Sarybchik flags |= EFX_CKSUM_IPV4; 881294310Sarybchik } 882283514Sarybchik 883294310Sarybchik if (l4_class == ESE_DZ_L4_CLASS_TCP) { 884294310Sarybchik EFX_EV_QSTAT_INCR(eep, EV_RX_TCP_IPV4); 885294310Sarybchik flags |= EFX_PKT_TCP; 886294310Sarybchik } else if (l4_class == ESE_DZ_L4_CLASS_UDP) { 887294310Sarybchik EFX_EV_QSTAT_INCR(eep, EV_RX_UDP_IPV4); 888294310Sarybchik flags |= EFX_PKT_UDP; 889294310Sarybchik } else { 890294310Sarybchik EFX_EV_QSTAT_INCR(eep, EV_RX_OTHER_IPV4); 891294310Sarybchik } 892283514Sarybchik break; 893283514Sarybchik 894294310Sarybchik case ESE_DZ_L3_CLASS_IP6: 895283514Sarybchik case ESE_DZ_L3_CLASS_IP6_FRAG: 896283514Sarybchik flags |= EFX_PKT_IPV6; 897283514Sarybchik 898294310Sarybchik if (l4_class == ESE_DZ_L4_CLASS_TCP) { 899294310Sarybchik EFX_EV_QSTAT_INCR(eep, EV_RX_TCP_IPV6); 900294310Sarybchik flags |= EFX_PKT_TCP; 901294310Sarybchik } else if (l4_class == ESE_DZ_L4_CLASS_UDP) { 902294310Sarybchik EFX_EV_QSTAT_INCR(eep, EV_RX_UDP_IPV6); 903294310Sarybchik flags |= EFX_PKT_UDP; 904294310Sarybchik } else { 905294310Sarybchik EFX_EV_QSTAT_INCR(eep, EV_RX_OTHER_IPV6); 906294310Sarybchik } 907283514Sarybchik break; 908283514Sarybchik 909283514Sarybchik default: 910294310Sarybchik EFX_EV_QSTAT_INCR(eep, EV_RX_NON_IP); 911283514Sarybchik break; 912283514Sarybchik } 913283514Sarybchik 914294310Sarybchik if (flags & (EFX_PKT_TCP | EFX_PKT_UDP)) { 915294310Sarybchik if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_TCPUDP_CKSUM_ERR)) { 916294310Sarybchik EFX_EV_QSTAT_INCR(eep, EV_RX_TCP_UDP_CHKSUM_ERR); 917294310Sarybchik } else { 918283514Sarybchik flags |= EFX_CKSUM_TCPUDP; 919294310Sarybchik } 920283514Sarybchik } 921283514Sarybchik 922294310Sarybchikdeliver: 923283514Sarybchik /* If we're not discarding the packet then it is ok */ 924283514Sarybchik if (~flags & EFX_DISCARD) 925283514Sarybchik EFX_EV_QSTAT_INCR(eep, EV_RX_OK); 926283514Sarybchik 927283514Sarybchik EFSYS_ASSERT(eecp->eec_rx != NULL); 928283514Sarybchik should_abort = eecp->eec_rx(arg, label, last_used_id, size, flags); 929283514Sarybchik 930283514Sarybchik return (should_abort); 931283514Sarybchik} 932283514Sarybchik 933283514Sarybchikstatic __checkReturn boolean_t 934293752Sarybchikef10_ev_tx( 935283514Sarybchik __in efx_evq_t *eep, 936283514Sarybchik __in efx_qword_t *eqp, 937283514Sarybchik __in const efx_ev_callbacks_t *eecp, 938283514Sarybchik __in_opt void *arg) 939283514Sarybchik{ 940283514Sarybchik efx_nic_t *enp = eep->ee_enp; 941283514Sarybchik uint32_t id; 942283514Sarybchik uint32_t label; 943283514Sarybchik boolean_t should_abort; 944283514Sarybchik 945283514Sarybchik EFX_EV_QSTAT_INCR(eep, EV_TX); 946283514Sarybchik 947283514Sarybchik /* Discard events after RXQ/TXQ errors */ 948283514Sarybchik if (enp->en_reset_flags & (EFX_RESET_RXQ_ERR | EFX_RESET_TXQ_ERR)) 949283514Sarybchik return (B_FALSE); 950283514Sarybchik 951283514Sarybchik if (EFX_QWORD_FIELD(*eqp, ESF_DZ_TX_DROP_EVENT) != 0) { 952283514Sarybchik /* Drop this event */ 953283514Sarybchik return (B_FALSE); 954283514Sarybchik } 955283514Sarybchik 956283514Sarybchik /* Per-packet TX completion (was per-descriptor for Falcon/Siena) */ 957283514Sarybchik id = EFX_QWORD_FIELD(*eqp, ESF_DZ_TX_DESCR_INDX); 958283514Sarybchik label = EFX_QWORD_FIELD(*eqp, ESF_DZ_TX_QLABEL); 959283514Sarybchik 960283514Sarybchik EFSYS_PROBE2(tx_complete, uint32_t, label, uint32_t, id); 961283514Sarybchik 962283514Sarybchik EFSYS_ASSERT(eecp->eec_tx != NULL); 963283514Sarybchik should_abort = eecp->eec_tx(arg, label, id); 964283514Sarybchik 965283514Sarybchik return (should_abort); 966283514Sarybchik} 967283514Sarybchik 968283514Sarybchikstatic __checkReturn boolean_t 969293752Sarybchikef10_ev_driver( 970283514Sarybchik __in efx_evq_t *eep, 971283514Sarybchik __in efx_qword_t *eqp, 972283514Sarybchik __in const efx_ev_callbacks_t *eecp, 973283514Sarybchik __in_opt void *arg) 974283514Sarybchik{ 975283514Sarybchik unsigned int code; 976283514Sarybchik boolean_t should_abort; 977283514Sarybchik 978283514Sarybchik EFX_EV_QSTAT_INCR(eep, EV_DRIVER); 979283514Sarybchik should_abort = B_FALSE; 980283514Sarybchik 981283514Sarybchik code = EFX_QWORD_FIELD(*eqp, ESF_DZ_DRV_SUB_CODE); 982283514Sarybchik switch (code) { 983283514Sarybchik case ESE_DZ_DRV_TIMER_EV: { 984283514Sarybchik uint32_t id; 985283514Sarybchik 986283514Sarybchik id = EFX_QWORD_FIELD(*eqp, ESF_DZ_DRV_TMR_ID); 987283514Sarybchik 988283514Sarybchik EFSYS_ASSERT(eecp->eec_timer != NULL); 989283514Sarybchik should_abort = eecp->eec_timer(arg, id); 990283514Sarybchik break; 991283514Sarybchik } 992283514Sarybchik 993283514Sarybchik case ESE_DZ_DRV_WAKE_UP_EV: { 994283514Sarybchik uint32_t id; 995283514Sarybchik 996283514Sarybchik id = EFX_QWORD_FIELD(*eqp, ESF_DZ_DRV_EVQ_ID); 997283514Sarybchik 998283514Sarybchik EFSYS_ASSERT(eecp->eec_wake_up != NULL); 999283514Sarybchik should_abort = eecp->eec_wake_up(arg, id); 1000283514Sarybchik break; 1001283514Sarybchik } 1002283514Sarybchik 1003283514Sarybchik case ESE_DZ_DRV_START_UP_EV: 1004283514Sarybchik EFSYS_ASSERT(eecp->eec_initialized != NULL); 1005283514Sarybchik should_abort = eecp->eec_initialized(arg); 1006283514Sarybchik break; 1007283514Sarybchik 1008283514Sarybchik default: 1009283514Sarybchik EFSYS_PROBE3(bad_event, unsigned int, eep->ee_index, 1010283514Sarybchik uint32_t, EFX_QWORD_FIELD(*eqp, EFX_DWORD_1), 1011283514Sarybchik uint32_t, EFX_QWORD_FIELD(*eqp, EFX_DWORD_0)); 1012283514Sarybchik break; 1013283514Sarybchik } 1014283514Sarybchik 1015283514Sarybchik return (should_abort); 1016283514Sarybchik} 1017283514Sarybchik 1018283514Sarybchikstatic __checkReturn boolean_t 1019293752Sarybchikef10_ev_drv_gen( 1020283514Sarybchik __in efx_evq_t *eep, 1021283514Sarybchik __in efx_qword_t *eqp, 1022283514Sarybchik __in const efx_ev_callbacks_t *eecp, 1023283514Sarybchik __in_opt void *arg) 1024283514Sarybchik{ 1025283514Sarybchik uint32_t data; 1026283514Sarybchik boolean_t should_abort; 1027283514Sarybchik 1028283514Sarybchik EFX_EV_QSTAT_INCR(eep, EV_DRV_GEN); 1029283514Sarybchik should_abort = B_FALSE; 1030283514Sarybchik 1031283514Sarybchik data = EFX_QWORD_FIELD(*eqp, ESF_DZ_DRV_SUB_DATA_DW0); 1032283514Sarybchik if (data >= ((uint32_t)1 << 16)) { 1033283514Sarybchik EFSYS_PROBE3(bad_event, unsigned int, eep->ee_index, 1034283514Sarybchik uint32_t, EFX_QWORD_FIELD(*eqp, EFX_DWORD_1), 1035283514Sarybchik uint32_t, EFX_QWORD_FIELD(*eqp, EFX_DWORD_0)); 1036283514Sarybchik 1037283514Sarybchik return (B_TRUE); 1038283514Sarybchik } 1039283514Sarybchik 1040283514Sarybchik EFSYS_ASSERT(eecp->eec_software != NULL); 1041283514Sarybchik should_abort = eecp->eec_software(arg, (uint16_t)data); 1042283514Sarybchik 1043283514Sarybchik return (should_abort); 1044283514Sarybchik} 1045283514Sarybchik 1046283514Sarybchikstatic __checkReturn boolean_t 1047293752Sarybchikef10_ev_mcdi( 1048283514Sarybchik __in efx_evq_t *eep, 1049283514Sarybchik __in efx_qword_t *eqp, 1050283514Sarybchik __in const efx_ev_callbacks_t *eecp, 1051283514Sarybchik __in_opt void *arg) 1052283514Sarybchik{ 1053283514Sarybchik efx_nic_t *enp = eep->ee_enp; 1054311062Sarybchik unsigned int code; 1055283514Sarybchik boolean_t should_abort = B_FALSE; 1056283514Sarybchik 1057283514Sarybchik EFX_EV_QSTAT_INCR(eep, EV_MCDI_RESPONSE); 1058283514Sarybchik 1059283514Sarybchik code = EFX_QWORD_FIELD(*eqp, MCDI_EVENT_CODE); 1060283514Sarybchik switch (code) { 1061283514Sarybchik case MCDI_EVENT_CODE_BADSSERT: 1062283514Sarybchik efx_mcdi_ev_death(enp, EINTR); 1063283514Sarybchik break; 1064283514Sarybchik 1065283514Sarybchik case MCDI_EVENT_CODE_CMDDONE: 1066283514Sarybchik efx_mcdi_ev_cpl(enp, 1067283514Sarybchik MCDI_EV_FIELD(eqp, CMDDONE_SEQ), 1068283514Sarybchik MCDI_EV_FIELD(eqp, CMDDONE_DATALEN), 1069283514Sarybchik MCDI_EV_FIELD(eqp, CMDDONE_ERRNO)); 1070283514Sarybchik break; 1071283514Sarybchik 1072292051Sarybchik#if EFSYS_OPT_MCDI_PROXY_AUTH 1073292051Sarybchik case MCDI_EVENT_CODE_PROXY_RESPONSE: 1074292051Sarybchik /* 1075292051Sarybchik * This event notifies a function that an authorization request 1076292051Sarybchik * has been processed. If the request was authorized then the 1077292051Sarybchik * function can now re-send the original MCDI request. 1078292051Sarybchik * See SF-113652-SW "SR-IOV Proxied Network Access Control". 1079292051Sarybchik */ 1080292051Sarybchik efx_mcdi_ev_proxy_response(enp, 1081292051Sarybchik MCDI_EV_FIELD(eqp, PROXY_RESPONSE_HANDLE), 1082292051Sarybchik MCDI_EV_FIELD(eqp, PROXY_RESPONSE_RC)); 1083292051Sarybchik break; 1084292051Sarybchik#endif /* EFSYS_OPT_MCDI_PROXY_AUTH */ 1085292051Sarybchik 1086283514Sarybchik case MCDI_EVENT_CODE_LINKCHANGE: { 1087283514Sarybchik efx_link_mode_t link_mode; 1088283514Sarybchik 1089294091Sarybchik ef10_phy_link_ev(enp, eqp, &link_mode); 1090283514Sarybchik should_abort = eecp->eec_link_change(arg, link_mode); 1091283514Sarybchik break; 1092283514Sarybchik } 1093283514Sarybchik 1094283514Sarybchik case MCDI_EVENT_CODE_SENSOREVT: { 1095283514Sarybchik#if EFSYS_OPT_MON_STATS 1096283514Sarybchik efx_mon_stat_t id; 1097283514Sarybchik efx_mon_stat_value_t value; 1098291436Sarybchik efx_rc_t rc; 1099283514Sarybchik 1100283514Sarybchik /* Decode monitor stat for MCDI sensor (if supported) */ 1101283514Sarybchik if ((rc = mcdi_mon_ev(enp, eqp, &id, &value)) == 0) { 1102283514Sarybchik /* Report monitor stat change */ 1103283514Sarybchik should_abort = eecp->eec_monitor(arg, id, value); 1104283514Sarybchik } else if (rc == ENOTSUP) { 1105283514Sarybchik should_abort = eecp->eec_exception(arg, 1106283514Sarybchik EFX_EXCEPTION_UNKNOWN_SENSOREVT, 1107283514Sarybchik MCDI_EV_FIELD(eqp, DATA)); 1108283514Sarybchik } else { 1109283514Sarybchik EFSYS_ASSERT(rc == ENODEV); /* Wrong port */ 1110283514Sarybchik } 1111283514Sarybchik#endif 1112283514Sarybchik break; 1113283514Sarybchik } 1114283514Sarybchik 1115283514Sarybchik case MCDI_EVENT_CODE_SCHEDERR: 1116283514Sarybchik /* Informational only */ 1117283514Sarybchik break; 1118283514Sarybchik 1119283514Sarybchik case MCDI_EVENT_CODE_REBOOT: 1120283514Sarybchik /* Falcon/Siena only (should not been seen with Huntington). */ 1121283514Sarybchik efx_mcdi_ev_death(enp, EIO); 1122283514Sarybchik break; 1123283514Sarybchik 1124283514Sarybchik case MCDI_EVENT_CODE_MC_REBOOT: 1125283514Sarybchik /* MC_REBOOT event is used for Huntington (EF10) and later. */ 1126283514Sarybchik efx_mcdi_ev_death(enp, EIO); 1127283514Sarybchik break; 1128283514Sarybchik 1129283514Sarybchik case MCDI_EVENT_CODE_MAC_STATS_DMA: 1130283514Sarybchik#if EFSYS_OPT_MAC_STATS 1131283514Sarybchik if (eecp->eec_mac_stats != NULL) { 1132283514Sarybchik eecp->eec_mac_stats(arg, 1133283514Sarybchik MCDI_EV_FIELD(eqp, MAC_STATS_DMA_GENERATION)); 1134283514Sarybchik } 1135283514Sarybchik#endif 1136283514Sarybchik break; 1137283514Sarybchik 1138283514Sarybchik case MCDI_EVENT_CODE_FWALERT: { 1139283514Sarybchik uint32_t reason = MCDI_EV_FIELD(eqp, FWALERT_REASON); 1140283514Sarybchik 1141283514Sarybchik if (reason == MCDI_EVENT_FWALERT_REASON_SRAM_ACCESS) 1142283514Sarybchik should_abort = eecp->eec_exception(arg, 1143283514Sarybchik EFX_EXCEPTION_FWALERT_SRAM, 1144283514Sarybchik MCDI_EV_FIELD(eqp, FWALERT_DATA)); 1145283514Sarybchik else 1146283514Sarybchik should_abort = eecp->eec_exception(arg, 1147283514Sarybchik EFX_EXCEPTION_UNKNOWN_FWALERT, 1148283514Sarybchik MCDI_EV_FIELD(eqp, DATA)); 1149283514Sarybchik break; 1150283514Sarybchik } 1151283514Sarybchik 1152283514Sarybchik case MCDI_EVENT_CODE_TX_ERR: { 1153283514Sarybchik /* 1154283514Sarybchik * After a TXQ error is detected, firmware sends a TX_ERR event. 1155283514Sarybchik * This may be followed by TX completions (which we discard), 1156283514Sarybchik * and then finally by a TX_FLUSH event. Firmware destroys the 1157283514Sarybchik * TXQ automatically after sending the TX_FLUSH event. 1158283514Sarybchik */ 1159283514Sarybchik enp->en_reset_flags |= EFX_RESET_TXQ_ERR; 1160283514Sarybchik 1161301371Sarybchik EFSYS_PROBE2(tx_descq_err, 1162301371Sarybchik uint32_t, EFX_QWORD_FIELD(*eqp, EFX_DWORD_1), 1163301371Sarybchik uint32_t, EFX_QWORD_FIELD(*eqp, EFX_DWORD_0)); 1164283514Sarybchik 1165283514Sarybchik /* Inform the driver that a reset is required. */ 1166283514Sarybchik eecp->eec_exception(arg, EFX_EXCEPTION_TX_ERROR, 1167283514Sarybchik MCDI_EV_FIELD(eqp, TX_ERR_DATA)); 1168283514Sarybchik break; 1169283514Sarybchik } 1170283514Sarybchik 1171283514Sarybchik case MCDI_EVENT_CODE_TX_FLUSH: { 1172283514Sarybchik uint32_t txq_index = MCDI_EV_FIELD(eqp, TX_FLUSH_TXQ); 1173283514Sarybchik 1174283514Sarybchik /* 1175283514Sarybchik * EF10 firmware sends two TX_FLUSH events: one to the txq's 1176283514Sarybchik * event queue, and one to evq 0 (with TX_FLUSH_TO_DRIVER set). 1177283514Sarybchik * We want to wait for all completions, so ignore the events 1178283514Sarybchik * with TX_FLUSH_TO_DRIVER. 1179283514Sarybchik */ 1180283514Sarybchik if (MCDI_EV_FIELD(eqp, TX_FLUSH_TO_DRIVER) != 0) { 1181283514Sarybchik should_abort = B_FALSE; 1182283514Sarybchik break; 1183283514Sarybchik } 1184283514Sarybchik 1185283514Sarybchik EFX_EV_QSTAT_INCR(eep, EV_DRIVER_TX_DESCQ_FLS_DONE); 1186283514Sarybchik 1187283514Sarybchik EFSYS_PROBE1(tx_descq_fls_done, uint32_t, txq_index); 1188283514Sarybchik 1189283514Sarybchik EFSYS_ASSERT(eecp->eec_txq_flush_done != NULL); 1190283514Sarybchik should_abort = eecp->eec_txq_flush_done(arg, txq_index); 1191283514Sarybchik break; 1192283514Sarybchik } 1193283514Sarybchik 1194283514Sarybchik case MCDI_EVENT_CODE_RX_ERR: { 1195283514Sarybchik /* 1196283514Sarybchik * After an RXQ error is detected, firmware sends an RX_ERR 1197283514Sarybchik * event. This may be followed by RX events (which we discard), 1198283514Sarybchik * and then finally by an RX_FLUSH event. Firmware destroys the 1199283514Sarybchik * RXQ automatically after sending the RX_FLUSH event. 1200283514Sarybchik */ 1201283514Sarybchik enp->en_reset_flags |= EFX_RESET_RXQ_ERR; 1202283514Sarybchik 1203301371Sarybchik EFSYS_PROBE2(rx_descq_err, 1204301371Sarybchik uint32_t, EFX_QWORD_FIELD(*eqp, EFX_DWORD_1), 1205301371Sarybchik uint32_t, EFX_QWORD_FIELD(*eqp, EFX_DWORD_0)); 1206283514Sarybchik 1207283514Sarybchik /* Inform the driver that a reset is required. */ 1208283514Sarybchik eecp->eec_exception(arg, EFX_EXCEPTION_RX_ERROR, 1209283514Sarybchik MCDI_EV_FIELD(eqp, RX_ERR_DATA)); 1210283514Sarybchik break; 1211283514Sarybchik } 1212283514Sarybchik 1213283514Sarybchik case MCDI_EVENT_CODE_RX_FLUSH: { 1214283514Sarybchik uint32_t rxq_index = MCDI_EV_FIELD(eqp, RX_FLUSH_RXQ); 1215283514Sarybchik 1216283514Sarybchik /* 1217283514Sarybchik * EF10 firmware sends two RX_FLUSH events: one to the rxq's 1218283514Sarybchik * event queue, and one to evq 0 (with RX_FLUSH_TO_DRIVER set). 1219283514Sarybchik * We want to wait for all completions, so ignore the events 1220283514Sarybchik * with RX_FLUSH_TO_DRIVER. 1221283514Sarybchik */ 1222283514Sarybchik if (MCDI_EV_FIELD(eqp, RX_FLUSH_TO_DRIVER) != 0) { 1223283514Sarybchik should_abort = B_FALSE; 1224283514Sarybchik break; 1225283514Sarybchik } 1226283514Sarybchik 1227283514Sarybchik EFX_EV_QSTAT_INCR(eep, EV_DRIVER_RX_DESCQ_FLS_DONE); 1228283514Sarybchik 1229283514Sarybchik EFSYS_PROBE1(rx_descq_fls_done, uint32_t, rxq_index); 1230283514Sarybchik 1231283514Sarybchik EFSYS_ASSERT(eecp->eec_rxq_flush_done != NULL); 1232283514Sarybchik should_abort = eecp->eec_rxq_flush_done(arg, rxq_index); 1233283514Sarybchik break; 1234283514Sarybchik } 1235283514Sarybchik 1236283514Sarybchik default: 1237283514Sarybchik EFSYS_PROBE3(bad_event, unsigned int, eep->ee_index, 1238283514Sarybchik uint32_t, EFX_QWORD_FIELD(*eqp, EFX_DWORD_1), 1239283514Sarybchik uint32_t, EFX_QWORD_FIELD(*eqp, EFX_DWORD_0)); 1240283514Sarybchik break; 1241283514Sarybchik } 1242283514Sarybchik 1243283514Sarybchik return (should_abort); 1244283514Sarybchik} 1245283514Sarybchik 1246283514Sarybchik void 1247293752Sarybchikef10_ev_rxlabel_init( 1248283514Sarybchik __in efx_evq_t *eep, 1249283514Sarybchik __in efx_rxq_t *erp, 1250283514Sarybchik __in unsigned int label) 1251283514Sarybchik{ 1252283514Sarybchik efx_evq_rxq_state_t *eersp; 1253283514Sarybchik 1254283514Sarybchik EFSYS_ASSERT3U(label, <, EFX_ARRAY_SIZE(eep->ee_rxq_state)); 1255283514Sarybchik eersp = &eep->ee_rxq_state[label]; 1256283514Sarybchik 1257283514Sarybchik EFSYS_ASSERT3U(eersp->eers_rx_mask, ==, 0); 1258283514Sarybchik 1259283514Sarybchik eersp->eers_rx_read_ptr = 0; 1260283514Sarybchik eersp->eers_rx_mask = erp->er_mask; 1261283514Sarybchik} 1262283514Sarybchik 1263283514Sarybchik void 1264293752Sarybchikef10_ev_rxlabel_fini( 1265283514Sarybchik __in efx_evq_t *eep, 1266283514Sarybchik __in unsigned int label) 1267283514Sarybchik{ 1268283514Sarybchik efx_evq_rxq_state_t *eersp; 1269283514Sarybchik 1270283514Sarybchik EFSYS_ASSERT3U(label, <, EFX_ARRAY_SIZE(eep->ee_rxq_state)); 1271283514Sarybchik eersp = &eep->ee_rxq_state[label]; 1272283514Sarybchik 1273283514Sarybchik EFSYS_ASSERT3U(eersp->eers_rx_mask, !=, 0); 1274283514Sarybchik 1275283514Sarybchik eersp->eers_rx_read_ptr = 0; 1276283514Sarybchik eersp->eers_rx_mask = 0; 1277283514Sarybchik} 1278283514Sarybchik 1279299596Sarybchik#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */ 1280