From 46d2b38ba9cd35dc9c8a67cbe7562e9426b7ce99 Mon Sep 17 00:00:00 2001 From: Vijay Kumar Srivastava Date: Tue, 16 Mar 2021 11:58:28 +0300 Subject: [PATCH] common/sfc_efx/base: support getting virtio features Add an API to get virtio features supported by device. Signed-off-by: Vijay Kumar Srivastava Signed-off-by: Andrew Rybchenko --- drivers/common/sfc_efx/base/efx.h | 14 ++++++ drivers/common/sfc_efx/base/efx_impl.h | 2 + drivers/common/sfc_efx/base/efx_virtio.c | 45 +++++++++++++++++++ drivers/common/sfc_efx/base/rhead_impl.h | 7 +++ drivers/common/sfc_efx/base/rhead_virtio.c | 52 ++++++++++++++++++++++ 5 files changed, 120 insertions(+) diff --git a/drivers/common/sfc_efx/base/efx.h b/drivers/common/sfc_efx/base/efx.h index d4b7d7f47e..e3ac51eae0 100644 --- a/drivers/common/sfc_efx/base/efx.h +++ b/drivers/common/sfc_efx/base/efx.h @@ -4433,6 +4433,13 @@ typedef struct efx_virtio_vq_cfg_s { typedef struct efx_virtio_vq_s efx_virtio_vq_t; +typedef enum efx_virtio_device_type_e { + EFX_VIRTIO_DEVICE_TYPE_RESERVED, + EFX_VIRTIO_DEVICE_TYPE_NET, + EFX_VIRTIO_DEVICE_TYPE_BLOCK, + EFX_VIRTIO_DEVICE_NTYPES +} efx_virtio_device_type_t; + LIBEFX_API extern __checkReturn efx_rc_t efx_virtio_init( @@ -4487,6 +4494,13 @@ efx_virtio_get_doorbell_offset( __in efx_virtio_vq_t *evvp, __out uint32_t *offsetp); +LIBEFX_API +extern __checkReturn efx_rc_t +efx_virtio_get_features( + __in efx_nic_t *enp, + __in efx_virtio_device_type_t type, + __out uint64_t *featuresp); + #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 d6742f4a8c..758206d382 100644 --- a/drivers/common/sfc_efx/base/efx_impl.h +++ b/drivers/common/sfc_efx/base/efx_impl.h @@ -318,6 +318,8 @@ typedef struct efx_virtio_ops_s { efx_virtio_vq_dyncfg_t *); efx_rc_t (*evo_get_doorbell_offset)(efx_virtio_vq_t *, uint32_t *); + efx_rc_t (*evo_get_features)(efx_nic_t *, + efx_virtio_device_type_t, uint64_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 7303c00a0c..925dcc342b 100644 --- a/drivers/common/sfc_efx/base/efx_virtio.c +++ b/drivers/common/sfc_efx/base/efx_virtio.c @@ -13,6 +13,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 */ + rhead_virtio_get_features, /* evo_get_features */ }; #endif /* EFSYS_OPT_RIVERHEAD */ @@ -254,4 +255,48 @@ fail1: return (rc); } + __checkReturn efx_rc_t +efx_virtio_get_features( + __in efx_nic_t *enp, + __in efx_virtio_device_type_t type, + __out uint64_t *featuresp) +{ + const efx_virtio_ops_t *evop = enp->en_evop; + efx_rc_t rc; + + if (featuresp == NULL) { + rc = EINVAL; + goto fail1; + } + + if (type >= EFX_VIRTIO_DEVICE_NTYPES) { + rc = EINVAL; + goto fail2; + } + + EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); + EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_VIRTIO); + + if (evop == NULL) { + rc = ENOTSUP; + goto fail3; + } + + if ((rc = evop->evo_get_features(enp, type, featuresp)) != 0) + goto fail4; + + return (0); + +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_VIRTIO */ diff --git a/drivers/common/sfc_efx/base/rhead_impl.h b/drivers/common/sfc_efx/base/rhead_impl.h index 4304f63f4c..69d701a47e 100644 --- a/drivers/common/sfc_efx/base/rhead_impl.h +++ b/drivers/common/sfc_efx/base/rhead_impl.h @@ -498,6 +498,13 @@ rhead_virtio_get_doorbell_offset( __in efx_virtio_vq_t *evvp, __out uint32_t *offsetp); +LIBEFX_INTERNAL +extern __checkReturn efx_rc_t +rhead_virtio_get_features( + __in efx_nic_t *enp, + __in efx_virtio_device_type_t type, + __out uint64_t *featuresp); + #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 e69671394a..c49ac10b72 100644 --- a/drivers/common/sfc_efx/base/rhead_virtio.c +++ b/drivers/common/sfc_efx/base/rhead_virtio.c @@ -280,4 +280,56 @@ fail1: return (rc); } + __checkReturn efx_rc_t +rhead_virtio_get_features( + __in efx_nic_t *enp, + __in efx_virtio_device_type_t type, + __out uint64_t *featuresp) +{ + efx_mcdi_req_t req; + uint32_t features_lo; + uint32_t features_hi; + EFX_MCDI_DECLARE_BUF(payload, MC_CMD_VIRTIO_GET_FEATURES_IN_LEN, + MC_CMD_VIRTIO_GET_FEATURES_OUT_LEN); + efx_rc_t rc; + + EFX_STATIC_ASSERT(EFX_VIRTIO_DEVICE_TYPE_NET == + MC_CMD_VIRTIO_GET_FEATURES_IN_NET); + EFX_STATIC_ASSERT(EFX_VIRTIO_DEVICE_TYPE_BLOCK == + MC_CMD_VIRTIO_GET_FEATURES_IN_BLOCK); + + req.emr_cmd = MC_CMD_VIRTIO_GET_FEATURES; + req.emr_in_buf = payload; + req.emr_in_length = MC_CMD_VIRTIO_GET_FEATURES_IN_LEN; + req.emr_out_buf = payload; + req.emr_out_length = MC_CMD_VIRTIO_GET_FEATURES_OUT_LEN; + + MCDI_IN_SET_DWORD(req, VIRTIO_GET_FEATURES_IN_DEVICE_ID, type); + + efx_mcdi_execute(enp, &req); + + if (req.emr_rc != 0) { + rc = req.emr_rc; + goto fail1; + } + + if (req.emr_out_length_used < MC_CMD_VIRTIO_GET_FEATURES_OUT_LEN) { + rc = EMSGSIZE; + goto fail2; + } + + features_lo = MCDI_OUT_DWORD(req, VIRTIO_GET_FEATURES_OUT_FEATURES_LO); + features_hi = MCDI_OUT_DWORD(req, VIRTIO_GET_FEATURES_OUT_FEATURES_HI); + *featuresp = ((uint64_t)features_hi << 32) | features_lo; + + return (0); + +fail2: + EFSYS_PROBE(fail2); +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + #endif /* EFSYS_OPT_RIVERHEAD && EFSYS_OPT_VIRTIO */ -- 2.20.1