From e5ba497b7e366a247d5c801ec9f965a0268eac37 Mon Sep 17 00:00:00 2001 From: Richard Houldsworth Date: Mon, 10 Jun 2019 08:38:21 +0100 Subject: [PATCH] net/sfc/base: add driver version string registration Support the registration of a version string by the libefx client. The string is passed on to the MC in efx_nic_probe only to allow the MC to advertise the OS driver version in NC-SI, and the content is considered opaque for libefx. Signed-off-by: Richard Houldsworth Signed-off-by: Andrew Rybchenko --- drivers/net/sfc/base/efx.h | 13 ++++++++++++ drivers/net/sfc/base/efx_impl.h | 3 +++ drivers/net/sfc/base/efx_mcdi.c | 16 +++++++++++++-- drivers/net/sfc/base/efx_nic.c | 35 +++++++++++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 2 deletions(-) diff --git a/drivers/net/sfc/base/efx.h b/drivers/net/sfc/base/efx.h index 8a2bb39150..700c99841c 100644 --- a/drivers/net/sfc/base/efx.h +++ b/drivers/net/sfc/base/efx.h @@ -1463,6 +1463,19 @@ efx_nic_set_drv_limits( __inout efx_nic_t *enp, __in efx_drv_limits_t *edlp); +/* + * Register the OS driver version string for management agents + * (e.g. via NC-SI). The content length is provided (i.e. no + * NUL terminator). Use length 0 to indicate no version string + * should be advertised. It is valid to set the version string + * only before efx_nic_probe() is called. + */ +extern __checkReturn efx_rc_t +efx_nic_set_drv_version( + __inout efx_nic_t *enp, + __in_ecount(length) char const *verp, + __in size_t length); + typedef enum efx_nic_region_e { EFX_REGION_VI, /* Memory BAR UC mapping */ EFX_REGION_PIO_WRITE_VI, /* Memory BAR WC mapping */ diff --git a/drivers/net/sfc/base/efx_impl.h b/drivers/net/sfc/base/efx_impl.h index f148c870ce..b5ac84d78b 100644 --- a/drivers/net/sfc/base/efx_impl.h +++ b/drivers/net/sfc/base/efx_impl.h @@ -647,6 +647,8 @@ typedef struct efx_lic_ops_s { #endif +#define EFX_DRV_VER_MAX 20 + typedef struct efx_drv_cfg_s { uint32_t edc_min_vi_count; uint32_t edc_max_vi_count; @@ -677,6 +679,7 @@ struct efx_nic_s { const efx_tx_ops_t *en_etxop; const efx_rx_ops_t *en_erxop; efx_fw_variant_t efv; + char en_drv_version[EFX_DRV_VER_MAX]; #if EFSYS_OPT_FILTER efx_filter_t en_filter; const efx_filter_ops_t *en_efop; diff --git a/drivers/net/sfc/base/efx_mcdi.c b/drivers/net/sfc/base/efx_mcdi.c index adc2eb8e8d..584fd4d2f7 100644 --- a/drivers/net/sfc/base/efx_mcdi.c +++ b/drivers/net/sfc/base/efx_mcdi.c @@ -1256,13 +1256,17 @@ efx_mcdi_drv_attach( __in boolean_t attach) { efx_mcdi_req_t req; - EFX_MCDI_DECLARE_BUF(payload, MC_CMD_DRV_ATTACH_IN_LEN, + EFX_MCDI_DECLARE_BUF(payload, MC_CMD_DRV_ATTACH_IN_V2_LEN, MC_CMD_DRV_ATTACH_EXT_OUT_LEN); efx_rc_t rc; req.emr_cmd = MC_CMD_DRV_ATTACH; req.emr_in_buf = payload; - req.emr_in_length = MC_CMD_DRV_ATTACH_IN_LEN; + if (enp->en_drv_version[0] == '\0') { + req.emr_in_length = MC_CMD_DRV_ATTACH_IN_LEN; + } else { + req.emr_in_length = MC_CMD_DRV_ATTACH_IN_V2_LEN; + } req.emr_out_buf = payload; req.emr_out_length = MC_CMD_DRV_ATTACH_EXT_OUT_LEN; @@ -1283,6 +1287,14 @@ efx_mcdi_drv_attach( MCDI_IN_SET_DWORD(req, DRV_ATTACH_IN_UPDATE, 1); MCDI_IN_SET_DWORD(req, DRV_ATTACH_IN_FIRMWARE_ID, enp->efv); + if (req.emr_in_length >= MC_CMD_DRV_ATTACH_IN_V2_LEN) { + EFX_STATIC_ASSERT(sizeof (enp->en_drv_version) == + MC_CMD_DRV_ATTACH_IN_V2_DRIVER_VERSION_LEN); + memcpy(MCDI_IN2(req, char, DRV_ATTACH_IN_V2_DRIVER_VERSION), + enp->en_drv_version, + MC_CMD_DRV_ATTACH_IN_V2_DRIVER_VERSION_LEN); + } + efx_mcdi_execute(enp, &req); if (req.emr_rc != 0) { diff --git a/drivers/net/sfc/base/efx_nic.c b/drivers/net/sfc/base/efx_nic.c index 3ec5cbc071..c1285bf429 100644 --- a/drivers/net/sfc/base/efx_nic.c +++ b/drivers/net/sfc/base/efx_nic.c @@ -379,6 +379,41 @@ fail1: return (rc); } + __checkReturn efx_rc_t +efx_nic_set_drv_version( + __inout efx_nic_t *enp, + __in_ecount(length) char const *verp, + __in size_t length) +{ + efx_rc_t rc; + + EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); + EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_PROBE)); + + /* + * length is the string content length in bytes. + * Accept any content which fits into the version + * buffer, excluding the last byte. This is reserved + * for an appended NUL terminator. + */ + if (length >= sizeof (enp->en_drv_version)) { + rc = E2BIG; + goto fail1; + } + + (void) memset(enp->en_drv_version, 0, + sizeof (enp->en_drv_version)); + memcpy(enp->en_drv_version, verp, length); + + return (0); + +fail1: + EFSYS_PROBE1(fail1, efx_rc_t, rc); + + return (rc); +} + + __checkReturn efx_rc_t efx_nic_get_bar_region( __in efx_nic_t *enp, -- 2.20.1