From: Vijay Kumar Srivastava <vsriv...@xilinx.com> Add an API to query the virtqueue doorbell offset in the BAR for a VI. For vDPA, the virtio net driver notifies the device directly by writing doorbell. This API would be invoked from vDPA client driver.
Signed-off-by: Vijay Kumar Srivastava <vsriv...@xilinx.com> Signed-off-by: Andrew Rybchenko <andrew.rybche...@oktetlabs.ru> --- drivers/common/sfc_efx/base/efx.h | 12 +++ drivers/common/sfc_efx/base/efx_impl.h | 2 + drivers/common/sfc_efx/base/efx_virtio.c | 41 ++++++++++ drivers/common/sfc_efx/base/rhead_impl.h | 6 ++ drivers/common/sfc_efx/base/rhead_virtio.c | 93 ++++++++++++++++++++++ drivers/common/sfc_efx/version.map | 1 + 6 files changed, 155 insertions(+) diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h index f9004ae2a4..733ef4a115 100644 --- a/drivers/common/sfc_efx/base/efx.h +++ b/drivers/common/sfc_efx/base/efx.h @@ -4475,6 +4475,18 @@ extern void efx_virtio_qdestroy( __in efx_virtio_vq_t *evvp); +/* + * Get the offset in the BAR of the doorbells for a VI. + * net device : doorbell offset of RX & TX queues + * block device : request doorbell offset in the BAR. + * For further details refer section of 4 of SF-119689 + */ +LIBEFX_API +extern __checkReturn efx_rc_t +efx_virtio_get_doorbell_offset( + __in efx_virtio_vq_t *evvp, + __out uint32_t *offsetp); + #endif /* EFSYS_OPT_VIRTIO */ #ifdef __cplusplus diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h index 374b14d253..dee9d936df 100644 --- a/drivers/common/sfc_efx/base/efx_impl.h +++ b/drivers/common/sfc_efx/base/efx_impl.h @@ -316,6 +316,8 @@ typedef struct efx_virtio_ops_s { efx_virtio_vq_dyncfg_t *); efx_rc_t (*evo_virtio_qstop)(efx_virtio_vq_t *, efx_virtio_vq_dyncfg_t *); + efx_rc_t (*evo_get_doorbell_offset)(efx_virtio_vq_t *, + uint32_t *); } efx_virtio_ops_t; #endif /* EFSYS_OPT_VIRTIO */ diff --git a/drivers/common/sfc_efx/base/efx_virtio.c b/drivers/common/sfc_efx/base/efx_virtio.c index 1b7b01556e..de998fcad9 100644 --- a/drivers/common/sfc_efx/base/efx_virtio.c +++ b/drivers/common/sfc_efx/base/efx_virtio.c @@ -12,6 +12,7 @@ static const efx_virtio_ops_t __efx_virtio_rhead_ops = { rhead_virtio_qstart, /* evo_virtio_qstart */ rhead_virtio_qstop, /* evo_virtio_qstop */ + rhead_virtio_get_doorbell_offset, /* evo_get_doorbell_offset */ }; #endif /* EFSYS_OPT_RIVERHEAD */ @@ -213,4 +214,44 @@ efx_virtio_qdestroy( } } + __checkReturn efx_rc_t +efx_virtio_get_doorbell_offset( + __in efx_virtio_vq_t *evvp, + __out uint32_t *offsetp) +{ + efx_nic_t *enp; + const efx_virtio_ops_t *evop; + efx_rc_t rc; + + if ((evvp == NULL) || (offsetp == NULL)) { + rc = EINVAL; + goto fail1; + } + + enp = evvp->evv_enp; + evop = enp->en_evop; + + EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); + EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VIRTIO); + + if (evop == NULL) { + rc = ENOTSUP; + goto fail2; + } + + if ((rc = evop->evo_get_doorbell_offset(evvp, offsetp)) != 0) + goto fail3; + + return (0); + +fail3: + EFSYS_PROBE(fail3); +fail2: + EFSYS_PROBE(fail2); +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + #endif /* EFSYS_OPT_VIRTIO */ diff --git a/drivers/common/sfc_efx/base/rhead_impl.h b/drivers/common/sfc_efx/base/rhead_impl.h index e22c3e9b1a..4601e491fd 100644 --- a/drivers/common/sfc_efx/base/rhead_impl.h +++ b/drivers/common/sfc_efx/base/rhead_impl.h @@ -492,6 +492,12 @@ rhead_virtio_qstop( __in efx_virtio_vq_t *evvp, __out_opt efx_virtio_vq_dyncfg_t *evvdp); +LIBEFX_INTERNAL +extern __checkReturn efx_rc_t +rhead_virtio_get_doorbell_offset( + __in efx_virtio_vq_t *evvp, + __out uint32_t *offsetp); + #endif /* EFSYS_OPT_VIRTIO */ #ifdef __cplusplus diff --git a/drivers/common/sfc_efx/base/rhead_virtio.c b/drivers/common/sfc_efx/base/rhead_virtio.c index d1719f834e..147460c95c 100644 --- a/drivers/common/sfc_efx/base/rhead_virtio.c +++ b/drivers/common/sfc_efx/base/rhead_virtio.c @@ -187,4 +187,97 @@ rhead_virtio_qstop( return (rc); } + __checkReturn efx_rc_t +rhead_virtio_get_doorbell_offset( + __in efx_virtio_vq_t *evvp, + __out uint32_t *offsetp) +{ + efx_nic_t *enp = evvp->evv_enp; + efx_mcdi_req_t req; + uint32_t type; + EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VIRTIO_GET_DOORBELL_OFFSET_REQ_LEN, + MC_CMD_VIRTIO_GET_NET_DOORBELL_OFFSET_RESP_LEN); + efx_rc_t rc; + + req.emr_cmd = MC_CMD_VIRTIO_GET_DOORBELL_OFFSET; + req.emr_in_buf = payload; + req.emr_in_length = MC_CMD_VIRTIO_GET_DOORBELL_OFFSET_REQ_LEN; + req.emr_out_buf = payload; + req.emr_out_length = MC_CMD_VIRTIO_GET_NET_DOORBELL_OFFSET_RESP_LEN; + + switch (evvp->evv_type) { + case EFX_VIRTIO_VQ_TYPE_NET_RXQ: + case EFX_VIRTIO_VQ_TYPE_NET_TXQ: + type = MC_CMD_VIRTIO_GET_FEATURES_IN_NET; + break; + case EFX_VIRTIO_VQ_TYPE_BLOCK: + type = MC_CMD_VIRTIO_GET_FEATURES_IN_BLOCK; + break; + default: + rc = EINVAL; + goto fail1; + } + + MCDI_IN_SET_BYTE(req, VIRTIO_GET_DOORBELL_OFFSET_REQ_DEVICE_ID, + type); + MCDI_IN_SET_WORD(req, VIRTIO_GET_DOORBELL_OFFSET_REQ_TARGET_VF, + evvp->evv_target_vf); + MCDI_IN_SET_DWORD(req, VIRTIO_GET_DOORBELL_OFFSET_REQ_INSTANCE, + evvp->evv_vi_index); + + efx_mcdi_execute(enp, &req); + + if (req.emr_rc != 0) { + rc = req.emr_rc; + goto fail2; + } + + switch (type) { + case MC_CMD_VIRTIO_GET_FEATURES_IN_NET: + if (req.emr_out_length_used < + MC_CMD_VIRTIO_GET_NET_DOORBELL_OFFSET_RESP_LEN) { + rc = EMSGSIZE; + goto fail3; + } + + if (evvp->evv_type == EFX_VIRTIO_VQ_TYPE_NET_RXQ) { + *offsetp = MCDI_OUT_DWORD(req, + VIRTIO_GET_NET_DOORBELL_OFFSET_RESP_RX_DBL_OFFSET); + } else if (evvp->evv_type == EFX_VIRTIO_VQ_TYPE_NET_TXQ) { + *offsetp = MCDI_OUT_DWORD(req, + VIRTIO_GET_NET_DOORBELL_OFFSET_RESP_TX_DBL_OFFSET); + } + break; + case MC_CMD_VIRTIO_GET_FEATURES_IN_BLOCK: + if (req.emr_out_length_used < + MC_CMD_VIRTIO_GET_BLOCK_DOORBELL_OFFSET_RESP_LEN) { + rc = EMSGSIZE; + goto fail4; + } + + *offsetp = MCDI_OUT_DWORD(req, + VIRTIO_GET_BLOCK_DOORBELL_OFFSET_RESP_DBL_OFFSET); + break; + default: + EFSYS_ASSERT(0); + rc = EINVAL; + goto fail5; + } + + 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); +} + #endif /* EFSYS_OPT_RIVERHEAD && EFSYS_OPT_VIRTIO */ diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map index b4da2ee5e6..0e41fd84fe 100644 --- a/drivers/common/sfc_efx/version.map +++ b/drivers/common/sfc_efx/version.map @@ -222,6 +222,7 @@ INTERNAL { efx_txq_size; efx_virtio_fini; + efx_virtio_get_doorbell_offset; efx_virtio_init; efx_virtio_qcreate; efx_virtio_qdestroy; -- 2.30.1