X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fcommon%2Fsfc_efx%2Fbase%2Fef10_ev.c;h=c0cbc427b9601b0ecfa5004ca333758bc10ad445;hb=3dee345ab31a8cc685c9fe5ba3f90aa322ee1d48;hp=f0a135ed5747404a0c4d091ed3083782deb9a0aa;hpb=5e111ed87999b2df4084b4d9c95643c98df1ba48;p=dpdk.git diff --git a/drivers/common/sfc_efx/base/ef10_ev.c b/drivers/common/sfc_efx/base/ef10_ev.c index f0a135ed57..c0cbc427b9 100644 --- a/drivers/common/sfc_efx/base/ef10_ev.c +++ b/drivers/common/sfc_efx/base/ef10_ev.c @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause * - * Copyright(c) 2019-2020 Xilinx, Inc. + * Copyright(c) 2019-2021 Xilinx, Inc. * Copyright(c) 2012-2019 Solarflare Communications Inc. */ @@ -47,13 +47,6 @@ ef10_ev_drv_gen( __in const efx_ev_callbacks_t *eecp, __in_opt void *arg); -static __checkReturn boolean_t -ef10_ev_mcdi( - __in efx_evq_t *eep, - __in efx_qword_t *eqp, - __in const efx_ev_callbacks_t *eecp, - __in_opt void *arg); - static __checkReturn efx_rc_t efx_mcdi_set_evq_tmr( @@ -100,310 +93,6 @@ fail1: return (rc); } -static __checkReturn efx_rc_t -efx_mcdi_init_evq( - __in efx_nic_t *enp, - __in unsigned int instance, - __in efsys_mem_t *esmp, - __in size_t nevs, - __in uint32_t irq, - __in uint32_t us, - __in uint32_t flags, - __in boolean_t low_latency) -{ - efx_mcdi_req_t req; - EFX_MCDI_DECLARE_BUF(payload, - MC_CMD_INIT_EVQ_IN_LEN(EF10_EVQ_MAXNBUFS), - MC_CMD_INIT_EVQ_OUT_LEN); - efx_qword_t *dma_addr; - uint64_t addr; - int npages; - int i; - boolean_t interrupting; - int ev_cut_through; - efx_rc_t rc; - - npages = efx_evq_nbufs(enp, nevs); - if (npages > EF10_EVQ_MAXNBUFS) { - rc = EINVAL; - goto fail1; - } - - req.emr_cmd = MC_CMD_INIT_EVQ; - req.emr_in_buf = payload; - req.emr_in_length = MC_CMD_INIT_EVQ_IN_LEN(npages); - req.emr_out_buf = payload; - req.emr_out_length = MC_CMD_INIT_EVQ_OUT_LEN; - - MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_SIZE, nevs); - MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_INSTANCE, instance); - MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_IRQ_NUM, irq); - - interrupting = ((flags & EFX_EVQ_FLAGS_NOTIFY_MASK) == - EFX_EVQ_FLAGS_NOTIFY_INTERRUPT); - - /* - * On Huntington RX and TX event batching can only be requested together - * (even if the datapath firmware doesn't actually support RX - * batching). If event cut through is enabled no RX batching will occur. - * - * So always enable RX and TX event batching, and enable event cut - * through if we want low latency operation. - */ - switch (flags & EFX_EVQ_FLAGS_TYPE_MASK) { - case EFX_EVQ_FLAGS_TYPE_AUTO: - ev_cut_through = low_latency ? 1 : 0; - break; - case EFX_EVQ_FLAGS_TYPE_THROUGHPUT: - ev_cut_through = 0; - break; - case EFX_EVQ_FLAGS_TYPE_LOW_LATENCY: - ev_cut_through = 1; - break; - default: - rc = EINVAL; - goto fail2; - } - MCDI_IN_POPULATE_DWORD_6(req, INIT_EVQ_IN_FLAGS, - INIT_EVQ_IN_FLAG_INTERRUPTING, interrupting, - INIT_EVQ_IN_FLAG_RPTR_DOS, 0, - INIT_EVQ_IN_FLAG_INT_ARMD, 0, - INIT_EVQ_IN_FLAG_CUT_THRU, ev_cut_through, - INIT_EVQ_IN_FLAG_RX_MERGE, 1, - INIT_EVQ_IN_FLAG_TX_MERGE, 1); - - /* If the value is zero then disable the timer */ - if (us == 0) { - MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_MODE, - MC_CMD_INIT_EVQ_IN_TMR_MODE_DIS); - MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_LOAD, 0); - MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_RELOAD, 0); - } else { - unsigned int ticks; - - if ((rc = efx_ev_usecs_to_ticks(enp, us, &ticks)) != 0) - goto fail3; - - MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_MODE, - MC_CMD_INIT_EVQ_IN_TMR_INT_HLDOFF); - MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_LOAD, ticks); - MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_TMR_RELOAD, ticks); - } - - MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_COUNT_MODE, - MC_CMD_INIT_EVQ_IN_COUNT_MODE_DIS); - MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_COUNT_THRSHLD, 0); - - dma_addr = MCDI_IN2(req, efx_qword_t, INIT_EVQ_IN_DMA_ADDR); - addr = EFSYS_MEM_ADDR(esmp); - - for (i = 0; i < npages; i++) { - EFX_POPULATE_QWORD_2(*dma_addr, - EFX_DWORD_1, (uint32_t)(addr >> 32), - EFX_DWORD_0, (uint32_t)(addr & 0xffffffff)); - - dma_addr++; - addr += EFX_BUF_SIZE; - } - - efx_mcdi_execute(enp, &req); - - if (req.emr_rc != 0) { - rc = req.emr_rc; - goto fail4; - } - - if (req.emr_out_length_used < MC_CMD_INIT_EVQ_OUT_LEN) { - rc = EMSGSIZE; - goto fail5; - } - - /* NOTE: ignore the returned IRQ param as firmware does not set it. */ - - return (0); - -fail5: - EFSYS_PROBE(fail5); -fail4: - EFSYS_PROBE(fail4); -fail3: - EFSYS_PROBE(fail3); -fail2: - EFSYS_PROBE(fail2); -fail1: - EFSYS_PROBE1(fail1, efx_rc_t, rc); - - return (rc); -} - - -static __checkReturn efx_rc_t -efx_mcdi_init_evq_v2( - __in efx_nic_t *enp, - __in unsigned int instance, - __in efsys_mem_t *esmp, - __in size_t nevs, - __in uint32_t irq, - __in uint32_t us, - __in uint32_t flags) -{ - efx_mcdi_req_t req; - EFX_MCDI_DECLARE_BUF(payload, - MC_CMD_INIT_EVQ_V2_IN_LEN(EF10_EVQ_MAXNBUFS), - MC_CMD_INIT_EVQ_V2_OUT_LEN); - boolean_t interrupting; - unsigned int evq_type; - efx_qword_t *dma_addr; - uint64_t addr; - int npages; - int i; - efx_rc_t rc; - - npages = efx_evq_nbufs(enp, nevs); - if (npages > EF10_EVQ_MAXNBUFS) { - rc = EINVAL; - goto fail1; - } - - req.emr_cmd = MC_CMD_INIT_EVQ; - req.emr_in_buf = payload; - req.emr_in_length = MC_CMD_INIT_EVQ_V2_IN_LEN(npages); - req.emr_out_buf = payload; - req.emr_out_length = MC_CMD_INIT_EVQ_V2_OUT_LEN; - - MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_SIZE, nevs); - MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_INSTANCE, instance); - MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_IRQ_NUM, irq); - - interrupting = ((flags & EFX_EVQ_FLAGS_NOTIFY_MASK) == - EFX_EVQ_FLAGS_NOTIFY_INTERRUPT); - - switch (flags & EFX_EVQ_FLAGS_TYPE_MASK) { - case EFX_EVQ_FLAGS_TYPE_AUTO: - evq_type = MC_CMD_INIT_EVQ_V2_IN_FLAG_TYPE_AUTO; - break; - case EFX_EVQ_FLAGS_TYPE_THROUGHPUT: - evq_type = MC_CMD_INIT_EVQ_V2_IN_FLAG_TYPE_THROUGHPUT; - break; - case EFX_EVQ_FLAGS_TYPE_LOW_LATENCY: - evq_type = MC_CMD_INIT_EVQ_V2_IN_FLAG_TYPE_LOW_LATENCY; - break; - default: - rc = EINVAL; - goto fail2; - } - MCDI_IN_POPULATE_DWORD_4(req, INIT_EVQ_V2_IN_FLAGS, - INIT_EVQ_V2_IN_FLAG_INTERRUPTING, interrupting, - INIT_EVQ_V2_IN_FLAG_RPTR_DOS, 0, - INIT_EVQ_V2_IN_FLAG_INT_ARMD, 0, - INIT_EVQ_V2_IN_FLAG_TYPE, evq_type); - - /* If the value is zero then disable the timer */ - if (us == 0) { - MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_TMR_MODE, - MC_CMD_INIT_EVQ_V2_IN_TMR_MODE_DIS); - MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_TMR_LOAD, 0); - MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_TMR_RELOAD, 0); - } else { - unsigned int ticks; - - if ((rc = efx_ev_usecs_to_ticks(enp, us, &ticks)) != 0) - goto fail3; - - MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_TMR_MODE, - MC_CMD_INIT_EVQ_V2_IN_TMR_INT_HLDOFF); - MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_TMR_LOAD, ticks); - MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_TMR_RELOAD, ticks); - } - - MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_COUNT_MODE, - MC_CMD_INIT_EVQ_V2_IN_COUNT_MODE_DIS); - MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_COUNT_THRSHLD, 0); - - dma_addr = MCDI_IN2(req, efx_qword_t, INIT_EVQ_V2_IN_DMA_ADDR); - addr = EFSYS_MEM_ADDR(esmp); - - for (i = 0; i < npages; i++) { - EFX_POPULATE_QWORD_2(*dma_addr, - EFX_DWORD_1, (uint32_t)(addr >> 32), - EFX_DWORD_0, (uint32_t)(addr & 0xffffffff)); - - dma_addr++; - addr += EFX_BUF_SIZE; - } - - efx_mcdi_execute(enp, &req); - - if (req.emr_rc != 0) { - rc = req.emr_rc; - goto fail4; - } - - if (req.emr_out_length_used < MC_CMD_INIT_EVQ_V2_OUT_LEN) { - rc = EMSGSIZE; - goto fail5; - } - - /* NOTE: ignore the returned IRQ param as firmware does not set it. */ - - EFSYS_PROBE1(mcdi_evq_flags, uint32_t, - MCDI_OUT_DWORD(req, INIT_EVQ_V2_OUT_FLAGS)); - - return (0); - -fail5: - EFSYS_PROBE(fail5); -fail4: - EFSYS_PROBE(fail4); -fail3: - EFSYS_PROBE(fail3); -fail2: - EFSYS_PROBE(fail2); -fail1: - EFSYS_PROBE1(fail1, efx_rc_t, rc); - - return (rc); -} - -static __checkReturn efx_rc_t -efx_mcdi_fini_evq( - __in efx_nic_t *enp, - __in uint32_t instance) -{ - efx_mcdi_req_t req; - EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FINI_EVQ_IN_LEN, - MC_CMD_FINI_EVQ_OUT_LEN); - efx_rc_t rc; - - req.emr_cmd = MC_CMD_FINI_EVQ; - req.emr_in_buf = payload; - req.emr_in_length = MC_CMD_FINI_EVQ_IN_LEN; - req.emr_out_buf = payload; - req.emr_out_length = MC_CMD_FINI_EVQ_OUT_LEN; - - MCDI_IN_SET_DWORD(req, FINI_EVQ_IN_INSTANCE, instance); - - efx_mcdi_execute_quiet(enp, &req); - - if (req.emr_rc != 0) { - rc = req.emr_rc; - goto fail1; - } - - return (0); - -fail1: - /* - * EALREADY is not an error, but indicates that the MC has rebooted and - * that the EVQ has already been destroyed. - */ - if (rc != EALREADY) - EFSYS_PROBE1(fail1, efx_rc_t, rc); - - return (rc); -} - - __checkReturn efx_rc_t ef10_ev_init( @@ -432,20 +121,14 @@ ef10_ev_qcreate( __in efx_evq_t *eep) { efx_nic_cfg_t *encp = &(enp->en_nic_cfg); - uint32_t irq; + uint32_t irq = 0; + uint32_t target_evq = 0; efx_rc_t rc; + boolean_t low_latency; _NOTE(ARGUNUSED(id)) /* buftbl id managed by MC */ - if (index >= encp->enc_evq_limit) { - rc = EINVAL; - goto fail1; - } - - if (us > encp->enc_evq_timer_max_us) { - rc = EINVAL; - goto fail2; - } + EFSYS_ASSERT((flags & EFX_EVQ_FLAGS_EXTENDED_WIDTH) == 0); /* * NO_CONT_EV mode is only requested from the firmware when creating @@ -460,7 +143,7 @@ ef10_ev_qcreate( if (flags & EFX_EVQ_FLAGS_NO_CONT_EV) { if (enp->en_nic_cfg.enc_no_cont_ev_mode_supported == B_FALSE) { rc = EINVAL; - goto fail3; + goto fail1; } } @@ -477,11 +160,12 @@ ef10_ev_qcreate( EFX_EVQ_FLAGS_NOTIFY_INTERRUPT) { irq = index; } else if (index == EFX_EF10_ALWAYS_INTERRUPTING_EVQ_INDEX) { - irq = index; + /* Use the first interrupt for always interrupting EvQ */ + irq = 0; flags = (flags & ~EFX_EVQ_FLAGS_NOTIFY_MASK) | EFX_EVQ_FLAGS_NOTIFY_INTERRUPT; } else { - irq = EFX_EF10_ALWAYS_INTERRUPTING_EVQ_INDEX; + target_evq = EFX_EF10_ALWAYS_INTERRUPTING_EVQ_INDEX; } /* @@ -489,46 +173,29 @@ ef10_ev_qcreate( * created. See bug58606. */ - if (encp->enc_init_evq_v2_supported) { - /* - * On Medford the low latency license is required to enable RX - * and event cut through and to disable RX batching. If event - * queue type in flags is auto, we let the firmware decide the - * settings to use. If the adapter has a low latency license, - * it will choose the best settings for low latency, otherwise - * it will choose the best settings for throughput. - */ - rc = efx_mcdi_init_evq_v2(enp, index, esmp, ndescs, irq, us, - flags); - if (rc != 0) - goto fail4; - } else { - /* - * On Huntington we need to specify the settings to use. - * If event queue type in flags is auto, we favour throughput - * if the adapter is running virtualization supporting firmware - * (i.e. the full featured firmware variant) - * and latency otherwise. The Ethernet Virtual Bridging - * capability is used to make this decision. (Note though that - * the low latency firmware variant is also best for - * throughput and corresponding type should be specified - * to choose it.) - */ - boolean_t low_latency = encp->enc_datapath_cap_evb ? 0 : 1; - rc = efx_mcdi_init_evq(enp, index, esmp, ndescs, irq, us, flags, - low_latency); - if (rc != 0) - goto fail5; - } + /* + * On Huntington we need to specify the settings to use. + * If event queue type in flags is auto, we favour throughput + * if the adapter is running virtualization supporting firmware + * (i.e. the full featured firmware variant) + * and latency otherwise. The Ethernet Virtual Bridging + * capability is used to make this decision. (Note though that + * the low latency firmware variant is also best for + * throughput and corresponding type should be specified + * to choose it.) + * + * If FW supports EvQ types (e.g. on Medford and Medford2) the + * type which is specified in flags is passed to FW to make the + * decision and low_latency hint is ignored. + */ + low_latency = encp->enc_datapath_cap_evb ? 0 : 1; + rc = efx_mcdi_init_evq(enp, index, esmp, ndescs, irq, target_evq, us, + flags, low_latency); + if (rc != 0) + goto fail2; return (0); -fail5: - EFSYS_PROBE(fail5); -fail4: - EFSYS_PROBE(fail4); -fail3: - EFSYS_PROBE(fail3); fail2: EFSYS_PROBE(fail2); fail1: @@ -1187,7 +854,11 @@ ef10_ev_drv_gen( return (should_abort); } -static __checkReturn boolean_t +#endif /* EFX_OPTS_EF10() */ + +#if EFSYS_OPT_RIVERHEAD || EFX_OPTS_EF10() + + __checkReturn boolean_t ef10_ev_mcdi( __in efx_evq_t *eep, __in efx_qword_t *eqp, @@ -1394,6 +1065,10 @@ ef10_ev_mcdi( return (should_abort); } +#endif /* EFSYS_OPT_RIVERHEAD || EFX_OPTS_EF10() */ + +#if EFX_OPTS_EF10() + void ef10_ev_rxlabel_init( __in efx_evq_t *eep,