mlxsw: core_linecards: Probe active line cards for devices and expose FW version
authorJiri Pirko <jiri@nvidia.com>
Mon, 25 Jul 2022 08:29:20 +0000 (10:29 +0200)
committerJakub Kicinski <kuba@kernel.org>
Tue, 26 Jul 2022 20:56:10 +0000 (13:56 -0700)
In case the line card is active, go over all possible existing
devices (gearboxes) on it and expose FW version of the flashable one.

Example:

$ devlink dev info auxiliary/mlxsw_core.lc.0
auxiliary/mlxsw_core.lc.0:
  versions:
      fixed:
        hw.revision 0
      running:
        ini.version 4
        fw 19.2010.1312

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Documentation/networking/devlink/mlxsw.rst
drivers/net/ethernet/mellanox/mlxsw/core.h
drivers/net/ethernet/mellanox/mlxsw/core_linecards.c

index aededcf68df4fb466b537990c4c9f2ad8ad90fc4..65ceed98f94da18bcf2d5329deb7ef0b711b0f76 100644 (file)
@@ -75,6 +75,9 @@ The ``mlxsw`` driver reports the following versions for line card auxiliary devi
    * - ``ini.version``
      - running
      - Version of line card INI loaded
+   * - ``fw.version``
+     - running
+     - Three digit firmware version of line card device
 
 Driver-specific Traps
 =====================
index f833b4d248e65914955e5a8f477efbeb98ea02cf..e4c6f8a6e016c651d6a6346bcc60711a6ab2dff1 100644 (file)
@@ -566,6 +566,12 @@ enum mlxsw_linecard_status_event_type {
 
 struct mlxsw_linecard_bdev;
 
+struct mlxsw_linecard_device_info {
+       u16 fw_major;
+       u16 fw_minor;
+       u16 fw_sub_minor;
+};
+
 struct mlxsw_linecard {
        u8 slot_index;
        struct mlxsw_linecards *linecards;
@@ -581,6 +587,9 @@ struct mlxsw_linecard {
        u16 hw_revision;
        u16 ini_version;
        struct mlxsw_linecard_bdev *bdev;
+       struct {
+               struct mlxsw_linecard_device_info info;
+       } device;
 };
 
 struct mlxsw_linecard_types_info;
index ee986dd2c4863a664c6aeb6edaab93f696f70219..a9568d72ba1bff1cb00959395a33605619a531fd 100644 (file)
@@ -87,6 +87,47 @@ static const char *mlxsw_linecard_type_name(struct mlxsw_linecard *linecard)
        return linecard->name;
 }
 
+static int mlxsw_linecard_device_info_update(struct mlxsw_linecard *linecard)
+{
+       struct mlxsw_core *mlxsw_core = linecard->linecards->mlxsw_core;
+       bool flashable_found = false;
+       u8 msg_seq = 0;
+
+       do {
+               struct mlxsw_linecard_device_info info;
+               char mddq_pl[MLXSW_REG_MDDQ_LEN];
+               bool flash_owner;
+               bool data_valid;
+               u8 device_index;
+               int err;
+
+               mlxsw_reg_mddq_device_info_pack(mddq_pl, linecard->slot_index,
+                                               msg_seq);
+               err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mddq), mddq_pl);
+               if (err)
+                       return err;
+               mlxsw_reg_mddq_device_info_unpack(mddq_pl, &msg_seq,
+                                                 &data_valid, &flash_owner,
+                                                 &device_index,
+                                                 &info.fw_major,
+                                                 &info.fw_minor,
+                                                 &info.fw_sub_minor);
+               if (!data_valid)
+                       break;
+               if (!flash_owner) /* We care only about flashable ones. */
+                       continue;
+               if (flashable_found) {
+                       dev_warn_once(linecard->linecards->bus_info->dev, "linecard %u: More flashable devices present, exposing only the first one\n",
+                                     linecard->slot_index);
+                       return 0;
+               }
+               linecard->device.info = info;
+               flashable_found = true;
+       } while (msg_seq);
+
+       return 0;
+}
+
 static void mlxsw_linecard_provision_fail(struct mlxsw_linecard *linecard)
 {
        linecard->provisioned = false;
@@ -249,6 +290,18 @@ int mlxsw_linecard_devlink_info_get(struct mlxsw_linecard *linecard,
        if (err)
                goto unlock;
 
+       if (linecard->active) {
+               struct mlxsw_linecard_device_info *info = &linecard->device.info;
+
+               sprintf(buf, "%u.%u.%u", info->fw_major, info->fw_minor,
+                       info->fw_sub_minor);
+               err = devlink_info_version_running_put(req,
+                                                      DEVLINK_INFO_VERSION_GENERIC_FW,
+                                                      buf);
+               if (err)
+                       goto unlock;
+       }
+
 unlock:
        mutex_unlock(&linecard->lock);
        return err;
@@ -308,6 +361,10 @@ static int mlxsw_linecard_ready_set(struct mlxsw_linecard *linecard)
        char mddc_pl[MLXSW_REG_MDDC_LEN];
        int err;
 
+       err = mlxsw_linecard_device_info_update(linecard);
+       if (err)
+               return err;
+
        mlxsw_reg_mddc_pack(mddc_pl, linecard->slot_index, false, true);
        err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(mddc), mddc_pl);
        if (err)