Skip to content

Commit 7db9839

Browse files
Yishai Hadaskuba-moo
authored andcommitted
net/mlx5: E-Switch, Implement devlink port function cmds to control RoCE
Implement devlink port function commands to enable / disable RoCE. This is used to control the RoCE device capabilities. This patch implement infrastructure which will be used by downstream patches that will add additional capabilities. Signed-off-by: Yishai Hadas <[email protected]> Signed-off-by: Daniel Jurgens <[email protected]> Signed-off-by: Shay Drory <[email protected]> Reviewed-by: Parav Pandit <[email protected]> Reviewed-by: Mark Bloch <[email protected]> Acked-by: Saeed Mahameed <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 47d0c50 commit 7db9839

File tree

7 files changed

+186
-1
lines changed

7 files changed

+186
-1
lines changed

Documentation/networking/device_drivers/ethernet/mellanox/mlx5.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,16 @@ MAC address setup
354354
mlx5 driver support devlink port function attr mechanism to setup MAC
355355
address. (refer to Documentation/networking/devlink/devlink-port.rst)
356356

357+
RoCE capability setup
358+
---------------------
359+
Not all mlx5 PCI devices/SFs require RoCE capability.
360+
361+
When RoCE capability is disabled, it saves 1 Mbytes worth of system memory per
362+
PCI devices/SF.
363+
364+
mlx5 driver support devlink port function attr mechanism to setup RoCE
365+
capability. (refer to Documentation/networking/devlink/devlink-port.rst)
366+
357367
SF state setup
358368
--------------
359369
To use the SF, the user must activate the SF using the SF function state

drivers/net/ethernet/mellanox/mlx5/core/devlink.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,8 @@ static const struct devlink_ops mlx5_devlink_ops = {
314314
.rate_node_new = mlx5_esw_devlink_rate_node_new,
315315
.rate_node_del = mlx5_esw_devlink_rate_node_del,
316316
.rate_leaf_parent_set = mlx5_esw_devlink_rate_parent_set,
317+
.port_fn_roce_get = mlx5_devlink_port_fn_roce_get,
318+
.port_fn_roce_set = mlx5_devlink_port_fn_roce_set,
317319
#endif
318320
#ifdef CONFIG_MLX5_SF_MANAGER
319321
.port_new = mlx5_devlink_sf_port_new,

drivers/net/ethernet/mellanox/mlx5/core/eswitch.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -772,6 +772,33 @@ static void esw_vport_cleanup_acl(struct mlx5_eswitch *esw,
772772
esw_vport_destroy_offloads_acl_tables(esw, vport);
773773
}
774774

775+
static int mlx5_esw_vport_caps_get(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
776+
{
777+
int query_out_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out);
778+
void *query_ctx;
779+
void *hca_caps;
780+
int err;
781+
782+
if (!MLX5_CAP_GEN(esw->dev, vhca_resource_manager))
783+
return 0;
784+
785+
query_ctx = kzalloc(query_out_sz, GFP_KERNEL);
786+
if (!query_ctx)
787+
return -ENOMEM;
788+
789+
err = mlx5_vport_get_other_func_cap(esw->dev, vport->vport, query_ctx,
790+
MLX5_CAP_GENERAL);
791+
if (err)
792+
goto out_free;
793+
794+
hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability);
795+
vport->info.roce_enabled = MLX5_GET(cmd_hca_cap, hca_caps, roce);
796+
797+
out_free:
798+
kfree(query_ctx);
799+
return err;
800+
}
801+
775802
static int esw_vport_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
776803
{
777804
u16 vport_num = vport->vport;
@@ -785,6 +812,10 @@ static int esw_vport_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
785812
if (mlx5_esw_is_manager_vport(esw, vport_num))
786813
return 0;
787814

815+
err = mlx5_esw_vport_caps_get(esw, vport);
816+
if (err)
817+
goto err_caps;
818+
788819
mlx5_modify_vport_admin_state(esw->dev,
789820
MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
790821
vport_num, 1,
@@ -804,6 +835,10 @@ static int esw_vport_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
804835
vport->info.qos, flags);
805836

806837
return 0;
838+
839+
err_caps:
840+
esw_vport_cleanup_acl(esw, vport);
841+
return err;
807842
}
808843

809844
/* Don't cleanup vport->info, it's needed to restore vport configuration */

drivers/net/ethernet/mellanox/mlx5/core/eswitch.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ struct mlx5_vport_info {
153153
u8 qos;
154154
u8 spoofchk: 1;
155155
u8 trusted: 1;
156+
u8 roce_enabled: 1;
156157
};
157158

158159
/* Vport context events */
@@ -508,7 +509,10 @@ int mlx5_devlink_port_function_hw_addr_get(struct devlink_port *port,
508509
int mlx5_devlink_port_function_hw_addr_set(struct devlink_port *port,
509510
const u8 *hw_addr, int hw_addr_len,
510511
struct netlink_ext_ack *extack);
511-
512+
int mlx5_devlink_port_fn_roce_get(struct devlink_port *port, bool *is_enabled,
513+
struct netlink_ext_ack *extack);
514+
int mlx5_devlink_port_fn_roce_set(struct devlink_port *port, bool enable,
515+
struct netlink_ext_ack *extack);
512516
void *mlx5_eswitch_get_uplink_priv(struct mlx5_eswitch *esw, u8 rep_type);
513517

514518
int mlx5_eswitch_add_vlan_action(struct mlx5_eswitch *esw,

drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4022,3 +4022,111 @@ int mlx5_devlink_port_function_hw_addr_set(struct devlink_port *port,
40224022

40234023
return mlx5_eswitch_set_vport_mac(esw, vport_num, hw_addr);
40244024
}
4025+
4026+
static struct mlx5_vport *
4027+
mlx5_devlink_port_fn_get_vport(struct devlink_port *port, struct mlx5_eswitch *esw)
4028+
{
4029+
u16 vport_num;
4030+
4031+
if (!MLX5_CAP_GEN(esw->dev, vhca_resource_manager))
4032+
return ERR_PTR(-EOPNOTSUPP);
4033+
4034+
vport_num = mlx5_esw_devlink_port_index_to_vport_num(port->index);
4035+
if (!is_port_function_supported(esw, vport_num))
4036+
return ERR_PTR(-EOPNOTSUPP);
4037+
4038+
return mlx5_eswitch_get_vport(esw, vport_num);
4039+
}
4040+
4041+
int mlx5_devlink_port_fn_roce_get(struct devlink_port *port, bool *is_enabled,
4042+
struct netlink_ext_ack *extack)
4043+
{
4044+
struct mlx5_eswitch *esw;
4045+
struct mlx5_vport *vport;
4046+
int err = -EOPNOTSUPP;
4047+
4048+
esw = mlx5_devlink_eswitch_get(port->devlink);
4049+
if (IS_ERR(esw))
4050+
return PTR_ERR(esw);
4051+
4052+
vport = mlx5_devlink_port_fn_get_vport(port, esw);
4053+
if (IS_ERR(vport)) {
4054+
NL_SET_ERR_MSG_MOD(extack, "Invalid port");
4055+
return PTR_ERR(vport);
4056+
}
4057+
4058+
mutex_lock(&esw->state_lock);
4059+
if (vport->enabled) {
4060+
*is_enabled = vport->info.roce_enabled;
4061+
err = 0;
4062+
}
4063+
mutex_unlock(&esw->state_lock);
4064+
return err;
4065+
}
4066+
4067+
int mlx5_devlink_port_fn_roce_set(struct devlink_port *port, bool enable,
4068+
struct netlink_ext_ack *extack)
4069+
{
4070+
int query_out_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out);
4071+
struct mlx5_eswitch *esw;
4072+
struct mlx5_vport *vport;
4073+
int err = -EOPNOTSUPP;
4074+
void *query_ctx;
4075+
void *hca_caps;
4076+
u16 vport_num;
4077+
4078+
esw = mlx5_devlink_eswitch_get(port->devlink);
4079+
if (IS_ERR(esw))
4080+
return PTR_ERR(esw);
4081+
4082+
vport = mlx5_devlink_port_fn_get_vport(port, esw);
4083+
if (IS_ERR(vport)) {
4084+
NL_SET_ERR_MSG_MOD(extack, "Invalid port");
4085+
return PTR_ERR(vport);
4086+
}
4087+
vport_num = vport->vport;
4088+
4089+
mutex_lock(&esw->state_lock);
4090+
if (!vport->enabled) {
4091+
NL_SET_ERR_MSG_MOD(extack, "Eswitch vport is disabled");
4092+
goto out;
4093+
}
4094+
4095+
if (vport->info.roce_enabled == enable) {
4096+
err = 0;
4097+
goto out;
4098+
}
4099+
4100+
query_ctx = kzalloc(query_out_sz, GFP_KERNEL);
4101+
if (!query_ctx) {
4102+
err = -ENOMEM;
4103+
goto out;
4104+
}
4105+
4106+
err = mlx5_vport_get_other_func_cap(esw->dev, vport_num, query_ctx,
4107+
MLX5_CAP_GENERAL);
4108+
if (err) {
4109+
NL_SET_ERR_MSG_MOD(extack, "Failed getting HCA caps");
4110+
goto out_free;
4111+
}
4112+
4113+
hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability);
4114+
memcpy(hca_caps, MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability),
4115+
MLX5_UN_SZ_BYTES(hca_cap_union));
4116+
MLX5_SET(cmd_hca_cap, hca_caps, roce, enable);
4117+
4118+
err = mlx5_vport_set_other_func_cap(esw->dev, hca_caps, vport_num,
4119+
MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE);
4120+
if (err) {
4121+
NL_SET_ERR_MSG_MOD(extack, "Failed setting HCA roce cap");
4122+
goto out_free;
4123+
}
4124+
4125+
vport->info.roce_enabled = enable;
4126+
4127+
out_free:
4128+
kfree(query_ctx);
4129+
out:
4130+
mutex_unlock(&esw->state_lock);
4131+
return err;
4132+
}

drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,8 @@ void mlx5_unload_one_devl_locked(struct mlx5_core_dev *dev);
324324
int mlx5_load_one(struct mlx5_core_dev *dev, bool recovery);
325325
int mlx5_load_one_devl_locked(struct mlx5_core_dev *dev, bool recovery);
326326

327+
int mlx5_vport_set_other_func_cap(struct mlx5_core_dev *dev, const void *hca_cap, u16 function_id,
328+
u16 opmod);
327329
#define mlx5_vport_get_other_func_general_cap(dev, fid, out) \
328330
mlx5_vport_get_other_func_cap(dev, fid, out, MLX5_CAP_GENERAL)
329331

drivers/net/ethernet/mellanox/mlx5/core/vport.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1173,3 +1173,27 @@ int mlx5_vport_get_other_func_cap(struct mlx5_core_dev *dev, u16 function_id, vo
11731173
return mlx5_cmd_exec_inout(dev, query_hca_cap, in, out);
11741174
}
11751175
EXPORT_SYMBOL_GPL(mlx5_vport_get_other_func_cap);
1176+
1177+
int mlx5_vport_set_other_func_cap(struct mlx5_core_dev *dev, const void *hca_cap,
1178+
u16 function_id, u16 opmod)
1179+
{
1180+
int set_sz = MLX5_ST_SZ_BYTES(set_hca_cap_in);
1181+
void *set_hca_cap;
1182+
void *set_ctx;
1183+
int ret;
1184+
1185+
set_ctx = kzalloc(set_sz, GFP_KERNEL);
1186+
if (!set_ctx)
1187+
return -ENOMEM;
1188+
1189+
MLX5_SET(set_hca_cap_in, set_ctx, opcode, MLX5_CMD_OP_SET_HCA_CAP);
1190+
MLX5_SET(set_hca_cap_in, set_ctx, op_mod, opmod << 1);
1191+
set_hca_cap = MLX5_ADDR_OF(set_hca_cap_in, set_ctx, capability);
1192+
memcpy(set_hca_cap, hca_cap, MLX5_ST_SZ_BYTES(cmd_hca_cap));
1193+
MLX5_SET(set_hca_cap_in, set_ctx, function_id, function_id);
1194+
MLX5_SET(set_hca_cap_in, set_ctx, other_function, true);
1195+
ret = mlx5_cmd_exec_in(dev, set_hca_cap, set_ctx);
1196+
1197+
kfree(set_ctx);
1198+
return ret;
1199+
}

0 commit comments

Comments
 (0)