net/sfc/base: add driver version string registration
authorRichard Houldsworth <rhouldsworth@solarflare.com>
Mon, 10 Jun 2019 07:38:21 +0000 (08:38 +0100)
committerFerruh Yigit <ferruh.yigit@intel.com>
Thu, 20 Jun 2019 21:42:04 +0000 (23:42 +0200)
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 <rhouldsworth@solarflare.com>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
drivers/net/sfc/base/efx.h
drivers/net/sfc/base/efx_impl.h
drivers/net/sfc/base/efx_mcdi.c
drivers/net/sfc/base/efx_nic.c

index 8a2bb39..700c998 100644 (file)
@@ -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 */
index f148c87..b5ac84d 100644 (file)
@@ -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;
index adc2eb8..584fd4d 100644 (file)
@@ -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) {
index 3ec5cbc..c1285bf 100644 (file)
@@ -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,