Commit e5b9642a authored by Shay Drory's avatar Shay Drory Committed by Jakub Kicinski
Browse files

net/mlx5: E-Switch, Implement devlink port function cmds to control migratable



Implement devlink port function commands to enable / disable migratable.
This is used to control the migratable capability of the device.

Signed-off-by: default avatarShay Drory <shayd@nvidia.com>
Reviewed-by: default avatarMark Bloch <mbloch@nvidia.com>
Acked-by: default avatarSaeed Mahameed <saeedm@nvidia.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent a8ce7b26
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -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
+2 −0
Original line number Diff line number Diff line
@@ -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,
+8 −0
Original line number Diff line number Diff line
@@ -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;
+5 −0
Original line number Diff line number Diff line
@@ -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,
+101 −0
Original line number Diff line number Diff line
@@ -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)
{