mlxsw: minimal: Add validation for FW version
authorVadim Pasternak <vadimp@mellanox.com>
Sun, 6 Oct 2019 06:34:52 +0000 (09:34 +0300)
committerDavid S. Miller <davem@davemloft.net>
Sun, 6 Oct 2019 16:31:39 +0000 (18:31 +0200)
Add validation for FW version in order to prevent driver initialization
in case FW version is older than expected. FW version validation is
necessary, because use of a new field 'num_of_modules' in MGPIR register
is not backward compatible. FW 'minor' and 'subminor' versions are
expected to be greater than or equal to 2000 and 1886, respectively.

Signed-off-by: Vadim Pasternak <vadimp@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlxsw/minimal.c

index 5edd8de57a24778367205c36d885466269e8615d..2b543911ae001dac34815dd0d466038a1c8dd97f 100644 (file)
 
 static const char mlxsw_m_driver_name[] = "mlxsw_minimal";
 
+#define MLXSW_M_FWREV_MINOR    2000
+#define MLXSW_M_FWREV_SUBMINOR 1886
+
+static const struct mlxsw_fw_rev mlxsw_m_fw_rev = {
+       .minor = MLXSW_M_FWREV_MINOR,
+       .subminor = MLXSW_M_FWREV_SUBMINOR,
+};
+
 struct mlxsw_m_port;
 
 struct mlxsw_m {
@@ -326,6 +334,24 @@ static void mlxsw_m_ports_remove(struct mlxsw_m *mlxsw_m)
        kfree(mlxsw_m->ports);
 }
 
+static int mlxsw_m_fw_rev_validate(struct mlxsw_m *mlxsw_m)
+{
+       const struct mlxsw_fw_rev *rev = &mlxsw_m->bus_info->fw_rev;
+
+       /* Validate driver and FW are compatible.
+        * Do not check major version, since it defines chip type, while
+        * driver is supposed to support any type.
+        */
+       if (mlxsw_core_fw_rev_minor_subminor_validate(rev, &mlxsw_m_fw_rev))
+               return 0;
+
+       dev_err(mlxsw_m->bus_info->dev, "The firmware version %d.%d.%d is incompatible with the driver (required >= %d.%d.%d)\n",
+               rev->major, rev->minor, rev->subminor, rev->major,
+               mlxsw_m_fw_rev.minor, mlxsw_m_fw_rev.subminor);
+
+       return -EINVAL;
+}
+
 static int mlxsw_m_init(struct mlxsw_core *mlxsw_core,
                        const struct mlxsw_bus_info *mlxsw_bus_info,
                        struct netlink_ext_ack *extack)
@@ -336,6 +362,10 @@ static int mlxsw_m_init(struct mlxsw_core *mlxsw_core,
        mlxsw_m->core = mlxsw_core;
        mlxsw_m->bus_info = mlxsw_bus_info;
 
+       err = mlxsw_m_fw_rev_validate(mlxsw_m);
+       if (err)
+               return err;
+
        err = mlxsw_m_base_mac_get(mlxsw_m);
        if (err) {
                dev_err(mlxsw_m->bus_info->dev, "Failed to get base mac\n");