_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
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);
(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;
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.
*/
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;
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;
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)
*/
#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(
__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
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));
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;
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:
_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) {
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;
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;
}
}
- 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) {
__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;
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);
#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 */
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;
/* 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))
/* 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;