From ea42cae43de6ea83972ee18b7ced8d8c2b3b9299 Mon Sep 17 00:00:00 2001 From: Andy Moreton Date: Thu, 24 Sep 2020 13:12:35 +0100 Subject: [PATCH] common/sfc_efx/base: handle descriptor proxy queue events The TXQ_DESC and VIRTQ_DESC events are used to pass host descriptors over an extended width event queue to an application processor for handling. See SF-122927-TC and SF-122966-SW for details. Signed-off-by: Andy Moreton Signed-off-by: Andrew Rybchenko --- drivers/common/sfc_efx/base/efx.h | 32 +++++++++ drivers/common/sfc_efx/base/efx_impl.h | 10 +++ drivers/common/sfc_efx/base/rhead_ev.c | 95 ++++++++++++++++++++++++++ 3 files changed, 137 insertions(+) diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h index ecd16712ba..07a7e3c952 100644 --- a/drivers/common/sfc_efx/base/efx.h +++ b/drivers/common/sfc_efx/base/efx.h @@ -2487,6 +2487,33 @@ typedef __checkReturn boolean_t #endif /* EFSYS_OPT_MAC_STATS */ +#if EFSYS_OPT_DESC_PROXY + +/* + * NOTE: This callback returns the raw descriptor data, which has not been + * converted to host endian. The callback must use the EFX_OWORD macros + * to extract the descriptor fields as host endian values. + */ +typedef __checkReturn boolean_t +(*efx_desc_proxy_txq_desc_ev_t)( + __in_opt void *arg, + __in uint16_t vi_id, + __in efx_oword_t txq_desc); + +/* + * NOTE: This callback returns the raw descriptor data, which has not been + * converted to host endian. The callback must use the EFX_OWORD macros + * to extract the descriptor fields as host endian values. + */ +typedef __checkReturn boolean_t +(*efx_desc_proxy_virtq_desc_ev_t)( + __in_opt void *arg, + __in uint16_t vi_id, + __in uint16_t avail, + __in efx_oword_t virtq_desc); + +#endif /* EFSYS_OPT_DESC_PROXY */ + typedef struct efx_ev_callbacks_s { efx_initialized_ev_t eec_initialized; efx_rx_ev_t eec_rx; @@ -2511,6 +2538,11 @@ typedef struct efx_ev_callbacks_s { #if EFSYS_OPT_MAC_STATS efx_mac_stats_ev_t eec_mac_stats; #endif /* EFSYS_OPT_MAC_STATS */ +#if EFSYS_OPT_DESC_PROXY + efx_desc_proxy_txq_desc_ev_t eec_desc_proxy_txq_desc; + efx_desc_proxy_virtq_desc_ev_t eec_desc_proxy_virtq_desc; +#endif /* EFSYS_OPT_DESC_PROXY */ + } efx_ev_callbacks_t; LIBEFX_API diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h index f58586bee0..196fd4a79c 100644 --- a/drivers/common/sfc_efx/base/efx_impl.h +++ b/drivers/common/sfc_efx/base/efx_impl.h @@ -902,6 +902,11 @@ struct efx_nic_s { typedef boolean_t (*efx_ev_handler_t)(efx_evq_t *, efx_qword_t *, const efx_ev_callbacks_t *, void *); +#if EFSYS_OPT_EV_EXTENDED_WIDTH +typedef boolean_t (*efx_ev_ew_handler_t)(efx_evq_t *, efx_xword_t *, + const efx_ev_callbacks_t *, void *); +#endif /* EFSYS_OPT_EV_EXTENDED_WIDTH */ + typedef struct efx_evq_rxq_state_s { unsigned int eers_rx_read_ptr; unsigned int eers_rx_mask; @@ -934,6 +939,11 @@ struct efx_evq_s { efx_ev_handler_t ee_mcdi; #endif /* EFSYS_OPT_MCDI */ +#if EFSYS_OPT_DESC_PROXY + efx_ev_ew_handler_t ee_ew_txq_desc; + efx_ev_ew_handler_t ee_ew_virtq_desc; +#endif /* EFSYS_OPT_DESC_PROXY */ + efx_evq_rxq_state_t ee_rxq_state[EFX_EV_RX_NLABELS]; }; diff --git a/drivers/common/sfc_efx/base/rhead_ev.c b/drivers/common/sfc_efx/base/rhead_ev.c index 5bda315171..2b5635f1cd 100644 --- a/drivers/common/sfc_efx/base/rhead_ev.c +++ b/drivers/common/sfc_efx/base/rhead_ev.c @@ -58,6 +58,22 @@ rhead_ev_ew_qpoll( __inout unsigned int *countp, __in const efx_ev_callbacks_t *eecp, __in_opt void *arg); + +#if EFSYS_OPT_DESC_PROXY +static boolean_t +rhead_ev_ew_txq_desc( + __in efx_evq_t *eep, + __in efx_xword_t *eventp, + __in const efx_ev_callbacks_t *eecp, + __in_opt void *arg); + +static boolean_t +rhead_ev_ew_virtq_desc( + __in efx_evq_t *eep, + __in efx_xword_t *eventp, + __in const efx_ev_callbacks_t *eecp, + __in_opt void *arg); +#endif /* EFSYS_OPT_DESC_PROXY */ #endif /* EFSYS_OPT_EV_EXTENDED_WIDTH */ @@ -115,6 +131,11 @@ rhead_ev_qcreate( eep->ee_drv_gen = NULL; /* FIXME */ eep->ee_mcdi = rhead_ev_mcdi; +#if EFSYS_OPT_DESC_PROXY + eep->ee_ew_txq_desc = rhead_ev_ew_txq_desc; + eep->ee_ew_virtq_desc = rhead_ev_ew_virtq_desc; +#endif /* EFSYS_OPT_DESC_PROXY */ + /* Set up the event queue */ /* INIT_EVQ expects function-relative vector number */ if ((flags & EFX_EVQ_FLAGS_NOTIFY_MASK) == @@ -345,6 +366,16 @@ rhead_ev_ew_dispatch( rhead_ev_dispatch(eep, &eventp->ex_qword[0], eecp, arg); break; +#if EFSYS_OPT_DESC_PROXY + case ESE_GZ_EF100_EVEW_TXQ_DESC: + should_abort = eep->ee_ew_txq_desc(eep, eventp, eecp, arg); + break; + + case ESE_GZ_EF100_EVEW_VIRTQ_DESC: + should_abort = eep->ee_ew_virtq_desc(eep, eventp, eecp, arg); + break; +#endif /* EFSYS_OPT_DESC_PROXY */ + default: /* Omit currently unused reserved bits from the probe. */ EFSYS_PROBE7(ew_bad_event, unsigned int, eep->ee_index, @@ -589,4 +620,68 @@ rhead_ev_mcdi( return (ret); } +#if EFSYS_OPT_DESC_PROXY +static boolean_t +rhead_ev_ew_txq_desc( + __in efx_evq_t *eep, + __in efx_xword_t *eventp, + __in const efx_ev_callbacks_t *eecp, + __in_opt void *arg) +{ + efx_oword_t txq_desc; + uint16_t vi_id; + boolean_t should_abort; + + _NOTE(ARGUNUSED(eep)) + + vi_id = EFX_XWORD_FIELD(*eventp, ESF_GZ_EV_TXQ_DP_VI_ID); + + /* + * NOTE: This is the raw descriptor data, and has not been converted + * to host endian. The handler callback must use the EFX_OWORD macros + * to extract the descriptor fields as host endian values. + */ + txq_desc = eventp->ex_oword[0]; + + EFSYS_ASSERT(eecp->eec_desc_proxy_txq_desc != NULL); + should_abort = eecp->eec_desc_proxy_txq_desc(arg, vi_id, txq_desc); + + return (should_abort); +} +#endif /* EFSYS_OPT_DESC_PROXY */ + + +#if EFSYS_OPT_DESC_PROXY +static boolean_t +rhead_ev_ew_virtq_desc( + __in efx_evq_t *eep, + __in efx_xword_t *eventp, + __in const efx_ev_callbacks_t *eecp, + __in_opt void *arg) +{ + efx_oword_t virtq_desc; + uint16_t vi_id; + uint16_t avail; + boolean_t should_abort; + + _NOTE(ARGUNUSED(eep)) + + vi_id = EFX_XWORD_FIELD(*eventp, ESF_GZ_EV_VQ_DP_VI_ID); + avail = EFX_XWORD_FIELD(*eventp, ESF_GZ_EV_VQ_DP_AVAIL_ENTRY); + + /* + * NOTE: This is the raw descriptor data, and has not been converted + * to host endian. The handler callback must use the EFX_OWORD macros + * to extract the descriptor fields as host endian values. + */ + virtq_desc = eventp->ex_oword[0]; + + EFSYS_ASSERT(eecp->eec_desc_proxy_virtq_desc != NULL); + should_abort = + eecp->eec_desc_proxy_virtq_desc(arg, vi_id, avail, virtq_desc); + + return (should_abort); +} +#endif /* EFSYS_OPT_DESC_PROXY */ + #endif /* EFSYS_OPT_RIVERHEAD */ -- 2.20.1