From: Andy Moreton Date: Thu, 24 Sep 2020 12:12:31 +0000 (+0100) Subject: common/sfc_efx/base: support creation of extended width EvQ X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=f8a60f76b3c611d42d7883845fff7567de26df1d;p=dpdk.git common/sfc_efx/base: support creation of extended width EvQ Add a flag to request an extended width event queue, and check that the supplied buffer is large enough to hold the event queue descriptors. Signed-off-by: Andy Moreton Signed-off-by: Andrew Rybchenko --- diff --git a/drivers/common/sfc_efx/base/ef10_ev.c b/drivers/common/sfc_efx/base/ef10_ev.c index aec1c468a4..8e7cc27d63 100644 --- a/drivers/common/sfc_efx/base/ef10_ev.c +++ b/drivers/common/sfc_efx/base/ef10_ev.c @@ -127,6 +127,8 @@ ef10_ev_qcreate( _NOTE(ARGUNUSED(id)) /* buftbl id managed by MC */ + EFSYS_ASSERT((flags & EFX_EVQ_FLAGS_EXTENDED_WIDTH) == 0); + /* * NO_CONT_EV mode is only requested from the firmware when creating * receive queues, but here it needs to be specified at event queue diff --git a/drivers/common/sfc_efx/base/ef10_nic.c b/drivers/common/sfc_efx/base/ef10_nic.c index 7a11930242..81cd436424 100644 --- a/drivers/common/sfc_efx/base/ef10_nic.c +++ b/drivers/common/sfc_efx/base/ef10_nic.c @@ -1043,14 +1043,14 @@ ef10_get_datapath_caps( efx_nic_cfg_t *encp = &(enp->en_nic_cfg); efx_mcdi_req_t req; EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_CAPABILITIES_IN_LEN, - MC_CMD_GET_CAPABILITIES_V5_OUT_LEN); + MC_CMD_GET_CAPABILITIES_V7_OUT_LEN); efx_rc_t rc; req.emr_cmd = MC_CMD_GET_CAPABILITIES; req.emr_in_buf = payload; req.emr_in_length = MC_CMD_GET_CAPABILITIES_IN_LEN; req.emr_out_buf = payload; - req.emr_out_length = MC_CMD_GET_CAPABILITIES_V5_OUT_LEN; + req.emr_out_length = MC_CMD_GET_CAPABILITIES_V7_OUT_LEN; efx_mcdi_execute_quiet(enp, &req); @@ -1073,6 +1073,11 @@ ef10_get_datapath_caps( (MCDI_OUT_DWORD((_req), GET_CAPABILITIES_V2_OUT_FLAGS2) & \ (1u << (MC_CMD_GET_CAPABILITIES_V2_OUT_ ## _flag ## _LBN)))) +#define CAP_FLAGS3(_req, _flag) \ + (((_req).emr_out_length_used >= MC_CMD_GET_CAPABILITIES_V7_OUT_LEN) && \ + (MCDI_OUT_DWORD((_req), GET_CAPABILITIES_V7_OUT_FLAGS3) & \ + (1u << (MC_CMD_GET_CAPABILITIES_V7_OUT_ ## _flag ## _LBN)))) + /* Check if RXDP firmware inserts 14 byte prefix */ if (CAP_FLAGS1(req, RX_PREFIX_LEN_14)) encp->enc_rx_prefix_size = 14; @@ -1202,6 +1207,15 @@ ef10_get_datapath_caps( else encp->enc_init_evq_v2_supported = B_FALSE; + /* + * Check if firmware supports extended width event queues, which have + * a different event descriptor layout. + */ + if (CAP_FLAGS3(req, EXTENDED_WIDTH_EVQS_SUPPORTED)) + encp->enc_init_evq_extended_width_supported = B_TRUE; + else + encp->enc_init_evq_extended_width_supported = B_FALSE; + /* * Check if the NO_CONT_EV mode for RX events is supported. */ diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h index 7e747e6122..ecd16712ba 100644 --- a/drivers/common/sfc_efx/base/efx.h +++ b/drivers/common/sfc_efx/base/efx.h @@ -1456,6 +1456,7 @@ typedef struct efx_nic_cfg_s { uint32_t enc_evq_timer_quantum_ns; uint32_t enc_evq_timer_max_us; uint32_t enc_clk_mult; + uint32_t enc_ev_ew_desc_size; uint32_t enc_ev_desc_size; uint32_t enc_rx_desc_size; uint32_t enc_tx_desc_size; @@ -1557,6 +1558,7 @@ typedef struct efx_nic_cfg_s { boolean_t enc_allow_set_mac_with_installed_filters; boolean_t enc_enhanced_set_mac_supported; boolean_t enc_init_evq_v2_supported; + boolean_t enc_init_evq_extended_width_supported; boolean_t enc_no_cont_ev_mode_supported; boolean_t enc_init_rxq_with_buffer_size; boolean_t enc_rx_packed_stream_supported; @@ -2264,13 +2266,15 @@ LIBEFX_API extern __checkReturn size_t efx_evq_size( __in const efx_nic_t *enp, - __in unsigned int ndescs); + __in unsigned int ndescs, + __in uint32_t flags); LIBEFX_API extern __checkReturn unsigned int efx_evq_nbufs( __in const efx_nic_t *enp, - __in unsigned int ndescs); + __in unsigned int ndescs, + __in uint32_t flags); #define EFX_EVQ_FLAGS_TYPE_MASK (0x3) #define EFX_EVQ_FLAGS_TYPE_AUTO (0x0) @@ -2291,6 +2295,10 @@ efx_evq_nbufs( */ #define EFX_EVQ_FLAGS_NO_CONT_EV (0x10) +/* Configure EVQ for extended width events (EF100 only) */ +#define EFX_EVQ_FLAGS_EXTENDED_WIDTH (0x20) + + LIBEFX_API extern __checkReturn efx_rc_t efx_ev_qcreate( diff --git a/drivers/common/sfc_efx/base/efx_ev.c b/drivers/common/sfc_efx/base/efx_ev.c index 99a7743edb..32e7fff3af 100644 --- a/drivers/common/sfc_efx/base/efx_ev.c +++ b/drivers/common/sfc_efx/base/efx_ev.c @@ -201,19 +201,35 @@ fail1: __checkReturn size_t efx_evq_size( __in const efx_nic_t *enp, - __in unsigned int ndescs) + __in unsigned int ndescs, + __in uint32_t flags) { const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); + size_t desc_size; - return (ndescs * encp->enc_ev_desc_size); + desc_size = encp->enc_ev_desc_size; + +#if EFSYS_OPT_EV_EXTENDED_WIDTH + if (flags & EFX_EVQ_FLAGS_EXTENDED_WIDTH) + desc_size = encp->enc_ev_ew_desc_size; +#else + EFSYS_ASSERT((flags & EFX_EVQ_FLAGS_EXTENDED_WIDTH) == 0); +#endif + + return (ndescs * desc_size); } __checkReturn unsigned int efx_evq_nbufs( __in const efx_nic_t *enp, - __in unsigned int ndescs) + __in unsigned int ndescs, + __in uint32_t flags) { - return (EFX_DIV_ROUND_UP(efx_evq_size(enp, ndescs), EFX_BUF_SIZE)); + size_t size; + + size = efx_evq_size(enp, ndescs, flags); + + return (EFX_DIV_ROUND_UP(size, EFX_BUF_SIZE)); } void @@ -282,6 +298,13 @@ efx_ev_qcreate( goto fail4; } + if ((flags & EFX_EVQ_FLAGS_EXTENDED_WIDTH) && + (encp->enc_ev_ew_desc_size == 0)) { + /* Extended width event descriptors are not supported. */ + rc = EINVAL; + goto fail5; + } + EFSYS_ASSERT(ISP2(encp->enc_evq_max_nevs)); EFSYS_ASSERT(ISP2(encp->enc_evq_min_nevs)); @@ -289,14 +312,20 @@ efx_ev_qcreate( ndescs < encp->enc_evq_min_nevs || ndescs > encp->enc_evq_max_nevs) { rc = EINVAL; - goto fail5; + goto fail6; + } + + if (EFSYS_MEM_SIZE(esmp) < (ndescs * encp->enc_ev_desc_size)) { + /* Buffer too small for event queue descriptors. */ + rc = EINVAL; + goto fail7; } /* Allocate an EVQ object */ EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (efx_evq_t), eep); if (eep == NULL) { rc = ENOMEM; - goto fail6; + goto fail8; } eep->ee_magic = EFX_EVQ_MAGIC; @@ -319,16 +348,20 @@ efx_ev_qcreate( if ((rc = eevop->eevo_qcreate(enp, index, esmp, ndescs, id, us, flags, eep)) != 0) - goto fail7; + goto fail9; return (0); -fail7: - EFSYS_PROBE(fail7); +fail9: + EFSYS_PROBE(fail9); *eepp = NULL; enp->en_ev_qcount--; EFSYS_KMEM_FREE(enp->en_esip, sizeof (efx_evq_t), eep); +fail8: + EFSYS_PROBE(fail8); +fail7: + EFSYS_PROBE(fail7); fail6: EFSYS_PROBE(fail6); fail5: @@ -1255,6 +1288,8 @@ siena_ev_qcreate( _NOTE(ARGUNUSED(esmp)) + EFSYS_ASSERT((flags & EFX_EVQ_FLAGS_EXTENDED_WIDTH) == 0); + #if EFSYS_OPT_RX_SCALE if (enp->en_intr.ei_type == EFX_INTR_LINE && index >= EFX_MAXRSS_LEGACY) { diff --git a/drivers/common/sfc_efx/base/efx_mcdi.c b/drivers/common/sfc_efx/base/efx_mcdi.c index b8e45b458d..ede052a26a 100644 --- a/drivers/common/sfc_efx/base/efx_mcdi.c +++ b/drivers/common/sfc_efx/base/efx_mcdi.c @@ -2475,6 +2475,7 @@ efx_mcdi_init_evq( MC_CMD_INIT_EVQ_V2_IN_LEN(INIT_EVQ_MAXNBUFS), MC_CMD_INIT_EVQ_V2_OUT_LEN); boolean_t interrupting; + int ev_extended_width; int ev_cut_through; int ev_merge; unsigned int evq_type; @@ -2484,7 +2485,7 @@ efx_mcdi_init_evq( int i; efx_rc_t rc; - npages = efx_evq_nbufs(enp, nevs); + npages = efx_evq_nbufs(enp, nevs, flags); if (npages > INIT_EVQ_MAXNBUFS) { rc = EINVAL; goto fail1; @@ -2558,14 +2559,27 @@ efx_mcdi_init_evq( } } - MCDI_IN_POPULATE_DWORD_7(req, INIT_EVQ_V2_IN_FLAGS, + /* + * On EF100, extended width event queues have a different event + * descriptor layout and are used to support descriptor proxy queues. + */ + ev_extended_width = 0; +#if EFSYS_OPT_EV_EXTENDED_WIDTH + if (encp->enc_init_evq_extended_width_supported) { + if (flags & EFX_EVQ_FLAGS_EXTENDED_WIDTH) + ev_extended_width = 1; + } +#endif + + MCDI_IN_POPULATE_DWORD_8(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_CUT_THRU, ev_cut_through, INIT_EVQ_V2_IN_FLAG_RX_MERGE, ev_merge, INIT_EVQ_V2_IN_FLAG_TX_MERGE, ev_merge, - INIT_EVQ_V2_IN_FLAG_TYPE, evq_type); + INIT_EVQ_V2_IN_FLAG_TYPE, evq_type, + INIT_EVQ_V2_IN_FLAG_EXT_WIDTH, ev_extended_width); /* If the value is zero then disable the timer */ if (us == 0) { diff --git a/drivers/common/sfc_efx/base/rhead_ev.c b/drivers/common/sfc_efx/base/rhead_ev.c index 8392a2be5b..a83c6150d8 100644 --- a/drivers/common/sfc_efx/base/rhead_ev.c +++ b/drivers/common/sfc_efx/base/rhead_ev.c @@ -66,11 +66,26 @@ rhead_ev_qcreate( __in uint32_t flags, __in efx_evq_t *eep) { + const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); + size_t desc_size; uint32_t irq; efx_rc_t rc; _NOTE(ARGUNUSED(id)) /* buftbl id managed by MC */ + desc_size = encp->enc_ev_desc_size; +#if EFSYS_OPT_EV_EXTENDED_WIDTH + if (flags & EFX_EVQ_FLAGS_EXTENDED_WIDTH) + desc_size = encp->enc_ev_ew_desc_size; +#endif + EFSYS_ASSERT(desc_size != 0); + + if (EFSYS_MEM_SIZE(esmp) < (ndescs * desc_size)) { + /* Buffer too small for event queue descriptors */ + rc = EINVAL; + goto fail1; + } + /* Set up the handler table */ eep->ee_rx = rhead_ev_rx_packets; eep->ee_tx = rhead_ev_tx_completion; @@ -98,10 +113,12 @@ rhead_ev_qcreate( rc = efx_mcdi_init_evq(enp, index, esmp, ndescs, irq, us, flags, B_FALSE); if (rc != 0) - goto fail1; + goto fail2; return (0); +fail2: + EFSYS_PROBE(fail2); fail1: EFSYS_PROBE1(fail1, efx_rc_t, rc); diff --git a/drivers/common/sfc_efx/base/rhead_impl.h b/drivers/common/sfc_efx/base/rhead_impl.h index 3383c47ec6..09a991f566 100644 --- a/drivers/common/sfc_efx/base/rhead_impl.h +++ b/drivers/common/sfc_efx/base/rhead_impl.h @@ -32,6 +32,10 @@ extern "C" { #define RHEAD_RXQ_DESC_SIZE (sizeof (efx_qword_t)) #define RHEAD_TXQ_DESC_SIZE (sizeof (efx_oword_t)) +#if EFSYS_OPT_EV_EXTENDED_WIDTH +#define RHEAD_EVQ_EW_DESC_SIZE (sizeof (efx_xword_t)) +#endif + /* NIC */ diff --git a/drivers/common/sfc_efx/base/rhead_nic.c b/drivers/common/sfc_efx/base/rhead_nic.c index 9b8f09d12c..66db68b384 100644 --- a/drivers/common/sfc_efx/base/rhead_nic.c +++ b/drivers/common/sfc_efx/base/rhead_nic.c @@ -129,6 +129,12 @@ rhead_board_cfg( encp->enc_evq_timer_quantum_ns = 0; encp->enc_evq_timer_max_us = 0; +#if EFSYS_OPT_EV_EXTENDED_WIDTH + encp->enc_ev_ew_desc_size = RHEAD_EVQ_EW_DESC_SIZE; +#else + encp->enc_ev_ew_desc_size = 0; +#endif + encp->enc_ev_desc_size = RHEAD_EVQ_DESC_SIZE; encp->enc_rx_desc_size = RHEAD_RXQ_DESC_SIZE; encp->enc_tx_desc_size = RHEAD_TXQ_DESC_SIZE; diff --git a/drivers/net/sfc/sfc_ev.c b/drivers/net/sfc/sfc_ev.c index 7e5676fa45..cc7d5d1179 100644 --- a/drivers/net/sfc/sfc_ev.c +++ b/drivers/net/sfc/sfc_ev.c @@ -600,7 +600,7 @@ sfc_ev_qstart(struct sfc_evq *evq, unsigned int hw_index) /* Clear all events */ (void)memset((void *)esmp->esm_base, 0xff, - efx_evq_size(sa->nic, evq->entries)); + efx_evq_size(sa->nic, evq->entries, evq_flags)); if ((sa->intr.lsc_intr && hw_index == sa->mgmt_evq_index) || (sa->intr.rxq_intr && evq->dp_rxq != NULL)) @@ -833,8 +833,8 @@ sfc_ev_qinit(struct sfc_adapter *sa, /* Allocate DMA space */ rc = sfc_dma_alloc(sa, sfc_evq_type2str(type), type_index, - efx_evq_size(sa->nic, evq->entries), socket_id, - &evq->mem); + efx_evq_size(sa->nic, evq->entries, sa->evq_flags), + socket_id, &evq->mem); if (rc != 0) goto fail_dma_alloc;