Provide devlink .info_get() callback implementation to allow the
driver to report detailed version information. The following info
is reported:

 "serial_number" -> The PCI DSN of the adapter
 "fw.bundle_id" -> Unique identifier for the combined flash image
 "fw.undi" -> Version of the Option ROM containing the UEFI driver
 "board.id" -> The PBA ID string

Reviewed-by: Mateusz Polchlopek <mateusz.polchlo...@intel.com>
Tested-by: Bharath R <bharat...@intel.com>
Signed-off-by: Jedrzej Jagielski <jedrzej.jagiel...@intel.com>
---
v2: zero the ctx buff when chance it won't be filled out
v4: use devlink_priv()
v6: fix devlink_*_put() labels
---
 Documentation/networking/devlink/ixgbe.rst    |  32 ++++++
 .../ethernet/intel/ixgbe/devlink/devlink.c    | 101 ++++++++++++++++++
 2 files changed, 133 insertions(+)

diff --git a/Documentation/networking/devlink/ixgbe.rst 
b/Documentation/networking/devlink/ixgbe.rst
index c04ac51c6d85..b63645de37e8 100644
--- a/Documentation/networking/devlink/ixgbe.rst
+++ b/Documentation/networking/devlink/ixgbe.rst
@@ -6,3 +6,35 @@ ixgbe devlink support
 
 This document describes the devlink features implemented by the ``ixgbe``
 device driver.
+
+Info versions
+=============
+
+The ``ixgbe`` driver reports the following versions
+
+.. list-table:: devlink info versions implemented
+    :widths: 5 5 5 90
+
+    * - Name
+      - Type
+      - Example
+      - Description
+    * - ``board.id``
+      - fixed
+      - H49289-000
+      - The Product Board Assembly (PBA) identifier of the board.
+    * - ``fw.undi``
+      - running
+      - 1.1937.0
+      - Version of the Option ROM containing the UEFI driver. The version is
+        reported in ``major.minor.patch`` format. The major version is
+        incremented whenever a major breaking change occurs, or when the
+        minor version would overflow. The minor version is incremented for
+        non-breaking changes and reset to 1 when the major version is
+        incremented. The patch version is normally 0 but is incremented when
+        a fix is delivered as a patch against an older base Option ROM.
+    * - ``fw.bundle_id``
+      - running
+      - 0x80000d0d
+      - Unique identifier of the firmware image file that was loaded onto
+        the device. Also referred to as the EETRACK identifier of the NVM.
diff --git a/drivers/net/ethernet/intel/ixgbe/devlink/devlink.c 
b/drivers/net/ethernet/intel/ixgbe/devlink/devlink.c
index 6c3452cf5d7d..d91252da4a61 100644
--- a/drivers/net/ethernet/intel/ixgbe/devlink/devlink.c
+++ b/drivers/net/ethernet/intel/ixgbe/devlink/devlink.c
@@ -4,7 +4,108 @@
 #include "ixgbe.h"
 #include "devlink.h"
 
+struct ixgbe_info_ctx {
+       char buf[128];
+};
+
+static void ixgbe_info_get_dsn(struct ixgbe_adapter *adapter,
+                              struct ixgbe_info_ctx *ctx)
+{
+       u8 dsn[8];
+
+       /* Copy the DSN into an array in Big Endian format */
+       put_unaligned_be64(pci_get_dsn(adapter->pdev), dsn);
+
+       snprintf(ctx->buf, sizeof(ctx->buf), "%8phD", dsn);
+}
+
+static void ixgbe_info_nvm_ver(struct ixgbe_adapter *adapter,
+                              struct ixgbe_info_ctx *ctx)
+{
+       struct ixgbe_hw *hw = &adapter->hw;
+       struct ixgbe_nvm_version nvm_ver;
+
+       ctx->buf[0] = '\0';
+
+       ixgbe_get_oem_prod_version(hw, &nvm_ver);
+       if (nvm_ver.oem_valid) {
+               snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x",
+                        nvm_ver.oem_major, nvm_ver.oem_minor,
+                        nvm_ver.oem_release);
+
+               return;
+       }
+
+       ixgbe_get_orom_version(hw, &nvm_ver);
+       if (nvm_ver.or_valid)
+               snprintf(ctx->buf, sizeof(ctx->buf), "%d.%d.%d",
+                        nvm_ver.or_major, nvm_ver.or_build, nvm_ver.or_patch);
+}
+
+static void ixgbe_info_eetrack(struct ixgbe_adapter *adapter,
+                              struct ixgbe_info_ctx *ctx)
+{
+       struct ixgbe_hw *hw = &adapter->hw;
+       struct ixgbe_nvm_version nvm_ver;
+
+       ixgbe_get_oem_prod_version(hw, &nvm_ver);
+
+       /* No ETRACK version for OEM */
+       if (nvm_ver.oem_valid) {
+               ctx->buf[0] = '\0';
+               return;
+       }
+
+       ixgbe_get_etk_id(hw, &nvm_ver);
+       snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm_ver.etk_id);
+}
+
+static int ixgbe_devlink_info_get(struct devlink *devlink,
+                                 struct devlink_info_req *req,
+                                 struct netlink_ext_ack *extack)
+{
+       struct ixgbe_adapter *adapter = devlink_priv(devlink);
+       struct ixgbe_hw *hw = &adapter->hw;
+       struct ixgbe_info_ctx *ctx;
+       int err;
+
+       ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
+       if (!ctx)
+               return -ENOMEM;
+
+       ixgbe_info_get_dsn(adapter, ctx);
+       err = devlink_info_serial_number_put(req, ctx->buf);
+       if (err)
+               goto free_ctx;
+
+       err = ixgbe_read_pba_string_generic(hw, ctx->buf, sizeof(ctx->buf));
+       if (err)
+               goto free_ctx;
+
+       err = devlink_info_version_fixed_put(req,
+                                       DEVLINK_INFO_VERSION_GENERIC_BOARD_ID,
+                                       ctx->buf);
+       if (err)
+               goto free_ctx;
+
+       ixgbe_info_nvm_ver(adapter, ctx);
+       err = devlink_info_version_running_put(req,
+                                       DEVLINK_INFO_VERSION_GENERIC_FW_UNDI,
+                                       ctx->buf);
+       if (err)
+               goto free_ctx;
+
+       ixgbe_info_eetrack(adapter, ctx);
+       err = devlink_info_version_running_put(req,
+                                       
DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID,
+                                       ctx->buf);
+free_ctx:
+       kfree(ctx);
+       return err;
+}
+
 static const struct devlink_ops ixgbe_devlink_ops = {
+       .info_get = ixgbe_devlink_info_get,
 };
 
 /**
-- 
2.31.1

Reply via email to