]> git.itanic.dy.fi Git - linux-stable/commitdiff
net/mlx5: E-Switch, Implement devlink port function cmds to control migratable
authorShay Drory <shayd@nvidia.com>
Tue, 6 Dec 2022 18:51:19 +0000 (20:51 +0200)
committerJakub Kicinski <kuba@kernel.org>
Thu, 8 Dec 2022 04:09:18 +0000 (20:09 -0800)
Implement devlink port function commands to enable / disable migratable.
This is used to control the migratable capability of the device.

Signed-off-by: Shay Drory <shayd@nvidia.com>
Reviewed-by: Mark Bloch <mbloch@nvidia.com>
Acked-by: Saeed Mahameed <saeedm@nvidia.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Documentation/networking/device_drivers/ethernet/mellanox/mlx5.rst
drivers/net/ethernet/mellanox/mlx5/core/devlink.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c

index 8b8f95d1293aec80c77ce07bdbdb9a8bc3ddf7f4..6969652f593c9346f3c31c85b4dc6e9ff4bb2b7a 100644 (file)
@@ -364,6 +364,14 @@ PCI devices/SF.
 mlx5 driver support devlink port function attr mechanism to setup RoCE
 capability. (refer to Documentation/networking/devlink/devlink-port.rst)
 
+migratable capability setup
+---------------------------
+User who wants mlx5 PCI VFs to be able to perform live migration need to
+explicitly enable the VF migratable capability.
+
+mlx5 driver support devlink port function attr mechanism to setup migratable
+capability. (refer to Documentation/networking/devlink/devlink-port.rst)
+
 SF state setup
 --------------
 To use the SF, the user must activate the SF using the SF function state
index 336c7b7fa49452f519be90e7e8b0af4a2ce39602..ddb197970c22c5c8994db59f964f439f41e39ffa 100644 (file)
@@ -316,6 +316,8 @@ static const struct devlink_ops mlx5_devlink_ops = {
        .rate_leaf_parent_set = mlx5_esw_devlink_rate_parent_set,
        .port_fn_roce_get = mlx5_devlink_port_fn_roce_get,
        .port_fn_roce_set = mlx5_devlink_port_fn_roce_set,
+       .port_fn_migratable_get = mlx5_devlink_port_fn_migratable_get,
+       .port_fn_migratable_set = mlx5_devlink_port_fn_migratable_set,
 #endif
 #ifdef CONFIG_MLX5_SF_MANAGER
        .port_new = mlx5_devlink_sf_port_new,
index 001fb1e62135e9e415dbc9bd7dd03844f9b7e0b5..527e4bffda8d4696ad9a858bafbf0fcba6f42fb9 100644 (file)
@@ -794,6 +794,14 @@ static int mlx5_esw_vport_caps_get(struct mlx5_eswitch *esw, struct mlx5_vport *
        hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability);
        vport->info.roce_enabled = MLX5_GET(cmd_hca_cap, hca_caps, roce);
 
+       memset(query_ctx, 0, query_out_sz);
+       err = mlx5_vport_get_other_func_cap(esw->dev, vport->vport, query_ctx,
+                                           MLX5_CAP_GENERAL_2);
+       if (err)
+               goto out_free;
+
+       hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability);
+       vport->info.mig_enabled = MLX5_GET(cmd_hca_cap_2, hca_caps, migratable);
 out_free:
        kfree(query_ctx);
        return err;
index eea0521729dfa9a1ae17109bb5443e50610c869a..5a85a5d32be7e1829075e7cc72bf9c64b9f14e5c 100644 (file)
@@ -154,6 +154,7 @@ struct mlx5_vport_info {
        u8                      spoofchk: 1;
        u8                      trusted: 1;
        u8                      roce_enabled: 1;
+       u8                      mig_enabled: 1;
 };
 
 /* Vport context events */
@@ -513,6 +514,10 @@ int mlx5_devlink_port_fn_roce_get(struct devlink_port *port, bool *is_enabled,
                                  struct netlink_ext_ack *extack);
 int mlx5_devlink_port_fn_roce_set(struct devlink_port *port, bool enable,
                                  struct netlink_ext_ack *extack);
+int mlx5_devlink_port_fn_migratable_get(struct devlink_port *port, bool *is_enabled,
+                                       struct netlink_ext_ack *extack);
+int mlx5_devlink_port_fn_migratable_set(struct devlink_port *port, bool enable,
+                                       struct netlink_ext_ack *extack);
 void *mlx5_eswitch_get_uplink_priv(struct mlx5_eswitch *esw, u8 rep_type);
 
 int mlx5_eswitch_add_vlan_action(struct mlx5_eswitch *esw,
index 7618c51351cac10fb48f951303a0763f19db4512..c6a14202c62c0c2c94ebaf2659281441a9bc582a 100644 (file)
@@ -4038,6 +4038,107 @@ mlx5_devlink_port_fn_get_vport(struct devlink_port *port, struct mlx5_eswitch *e
        return mlx5_eswitch_get_vport(esw, vport_num);
 }
 
+int mlx5_devlink_port_fn_migratable_get(struct devlink_port *port, bool *is_enabled,
+                                       struct netlink_ext_ack *extack)
+{
+       struct mlx5_eswitch *esw;
+       struct mlx5_vport *vport;
+       int err = -EOPNOTSUPP;
+
+       esw = mlx5_devlink_eswitch_get(port->devlink);
+       if (IS_ERR(esw))
+               return PTR_ERR(esw);
+
+       if (!MLX5_CAP_GEN(esw->dev, migration)) {
+               NL_SET_ERR_MSG_MOD(extack, "Device doesn't support migration");
+               return err;
+       }
+
+       vport = mlx5_devlink_port_fn_get_vport(port, esw);
+       if (IS_ERR(vport)) {
+               NL_SET_ERR_MSG_MOD(extack, "Invalid port");
+               return PTR_ERR(vport);
+       }
+
+       mutex_lock(&esw->state_lock);
+       if (vport->enabled) {
+               *is_enabled = vport->info.mig_enabled;
+               err = 0;
+       }
+       mutex_unlock(&esw->state_lock);
+       return err;
+}
+
+int mlx5_devlink_port_fn_migratable_set(struct devlink_port *port, bool enable,
+                                       struct netlink_ext_ack *extack)
+{
+       int query_out_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out);
+       struct mlx5_eswitch *esw;
+       struct mlx5_vport *vport;
+       void *query_ctx;
+       void *hca_caps;
+       int err = -EOPNOTSUPP;
+
+       esw = mlx5_devlink_eswitch_get(port->devlink);
+       if (IS_ERR(esw))
+               return PTR_ERR(esw);
+
+       if (!MLX5_CAP_GEN(esw->dev, migration)) {
+               NL_SET_ERR_MSG_MOD(extack, "Device doesn't support migration");
+               return err;
+       }
+
+       vport = mlx5_devlink_port_fn_get_vport(port, esw);
+       if (IS_ERR(vport)) {
+               NL_SET_ERR_MSG_MOD(extack, "Invalid port");
+               return PTR_ERR(vport);
+       }
+
+       mutex_lock(&esw->state_lock);
+       if (!vport->enabled) {
+               NL_SET_ERR_MSG_MOD(extack, "Eswitch vport is disabled");
+               goto out;
+       }
+
+       if (vport->info.mig_enabled == enable) {
+               err = 0;
+               goto out;
+       }
+
+       query_ctx = kzalloc(query_out_sz, GFP_KERNEL);
+       if (!query_ctx) {
+               err = -ENOMEM;
+               goto out;
+       }
+
+       err = mlx5_vport_get_other_func_cap(esw->dev, vport->vport, query_ctx,
+                                           MLX5_CAP_GENERAL_2);
+       if (err) {
+               NL_SET_ERR_MSG_MOD(extack, "Failed getting HCA caps");
+               goto out_free;
+       }
+
+       hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability);
+       memcpy(hca_caps, MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability),
+              MLX5_UN_SZ_BYTES(hca_cap_union));
+       MLX5_SET(cmd_hca_cap_2, hca_caps, migratable, 1);
+
+       err = mlx5_vport_set_other_func_cap(esw->dev, hca_caps, vport->vport,
+                                           MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE2);
+       if (err) {
+               NL_SET_ERR_MSG_MOD(extack, "Failed setting HCA migratable cap");
+               goto out_free;
+       }
+
+       vport->info.mig_enabled = enable;
+
+out_free:
+       kfree(query_ctx);
+out:
+       mutex_unlock(&esw->state_lock);
+       return err;
+}
+
 int mlx5_devlink_port_fn_roce_get(struct devlink_port *port, bool *is_enabled,
                                  struct netlink_ext_ack *extack)
 {