diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ecpf.c b/drivers/net/ethernet/mellanox/mlx5/core/ecpf.c index d000236ddbac..15cb27aea2c9 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ecpf.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/ecpf.c @@ -2,6 +2,7 @@ /* Copyright (c) 2019 Mellanox Technologies. */ #include "ecpf.h" +#include "eswitch.h" bool mlx5_read_embedded_cpu(struct mlx5_core_dev *dev) { @@ -49,7 +50,7 @@ static int mlx5_host_pf_init(struct mlx5_core_dev *dev) /* ECPF shall enable HCA for host PF in the same way a PF * does this for its VFs when ECPF is not a eswitch manager. */ - err = mlx5_cmd_host_pf_enable_hca(dev); + err = mlx5_esw_host_pf_enable_hca(dev); if (err) mlx5_core_err(dev, "Failed to enable external host PF HCA err(%d)\n", err); @@ -63,7 +64,7 @@ static void mlx5_host_pf_cleanup(struct mlx5_core_dev *dev) if (mlx5_ecpf_esw_admins_host_pf(dev)) return; - err = mlx5_cmd_host_pf_disable_hca(dev); + err = mlx5_esw_host_pf_disable_hca(dev); if (err) { mlx5_core_err(dev, "Failed to disable external host PF HCA err(%d)\n", err); return; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c index 89a58dee50b3..cd60bc500ec5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c @@ -99,6 +99,8 @@ static const struct devlink_port_ops mlx5_esw_pf_vf_dl_port_ops = { .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, + .port_fn_state_get = mlx5_devlink_pf_port_fn_state_get, + .port_fn_state_set = mlx5_devlink_pf_port_fn_state_set, #ifdef CONFIG_XFRM_OFFLOAD .port_fn_ipsec_crypto_get = mlx5_devlink_port_fn_ipsec_crypto_get, .port_fn_ipsec_crypto_set = mlx5_devlink_port_fn_ipsec_crypto_set, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 4b7a1ce7f406..5fbfabe28bdb 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -1304,24 +1304,52 @@ static int mlx5_eswitch_load_ec_vf_vports(struct mlx5_eswitch *esw, u16 num_ec_v return err; } -static int host_pf_enable_hca(struct mlx5_core_dev *dev) +int mlx5_esw_host_pf_enable_hca(struct mlx5_core_dev *dev) { - if (!mlx5_core_is_ecpf(dev)) + struct mlx5_eswitch *esw = dev->priv.eswitch; + struct mlx5_vport *vport; + int err; + + if (!mlx5_core_is_ecpf(dev) || !mlx5_esw_allowed(esw)) return 0; + vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_PF); + if (IS_ERR(vport)) + return PTR_ERR(vport); + /* Once vport and representor are ready, take out the external host PF * out of initializing state. Enabling HCA clears the iser->initializing * bit and host PF driver loading can progress. */ - return mlx5_cmd_host_pf_enable_hca(dev); + err = mlx5_cmd_host_pf_enable_hca(dev); + if (err) + return err; + + vport->pf_activated = true; + + return 0; } -static void host_pf_disable_hca(struct mlx5_core_dev *dev) +int mlx5_esw_host_pf_disable_hca(struct mlx5_core_dev *dev) { - if (!mlx5_core_is_ecpf(dev)) - return; + struct mlx5_eswitch *esw = dev->priv.eswitch; + struct mlx5_vport *vport; + int err; - mlx5_cmd_host_pf_disable_hca(dev); + if (!mlx5_core_is_ecpf(dev) || !mlx5_esw_allowed(esw)) + return 0; + + vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_PF); + if (IS_ERR(vport)) + return PTR_ERR(vport); + + err = mlx5_cmd_host_pf_disable_hca(dev); + if (err) + return err; + + vport->pf_activated = false; + + return 0; } /* mlx5_eswitch_enable_pf_vf_vports() enables vports of PF, ECPF and VFs @@ -1347,7 +1375,7 @@ mlx5_eswitch_enable_pf_vf_vports(struct mlx5_eswitch *esw, if (mlx5_esw_host_functions_enabled(esw->dev)) { /* Enable external host PF HCA */ - ret = host_pf_enable_hca(esw->dev); + ret = mlx5_esw_host_pf_enable_hca(esw->dev); if (ret) goto pf_hca_err; } @@ -1391,7 +1419,7 @@ mlx5_eswitch_enable_pf_vf_vports(struct mlx5_eswitch *esw, mlx5_eswitch_unload_pf_vf_vport(esw, MLX5_VPORT_ECPF); ecpf_err: if (mlx5_esw_host_functions_enabled(esw->dev)) - host_pf_disable_hca(esw->dev); + mlx5_esw_host_pf_disable_hca(esw->dev); pf_hca_err: if (pf_needed && mlx5_esw_host_functions_enabled(esw->dev)) mlx5_eswitch_unload_pf_vf_vport(esw, MLX5_VPORT_PF); @@ -1416,7 +1444,7 @@ void mlx5_eswitch_disable_pf_vf_vports(struct mlx5_eswitch *esw) } if (mlx5_esw_host_functions_enabled(esw->dev)) - host_pf_disable_hca(esw->dev); + mlx5_esw_host_pf_disable_hca(esw->dev); if ((mlx5_core_is_ecpf_esw_manager(esw->dev) || esw->mode == MLX5_ESWITCH_LEGACY) && diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index 714ad28e8445..6841caef02d1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -243,6 +243,7 @@ struct mlx5_vport { u16 vport; bool enabled; bool max_eqs_set; + bool pf_activated; enum mlx5_eswitch_vport_event enabled_events; int index; struct mlx5_devlink_port *dl_port; @@ -587,6 +588,13 @@ int mlx5_devlink_port_fn_migratable_get(struct devlink_port *port, bool *is_enab struct netlink_ext_ack *extack); int mlx5_devlink_port_fn_migratable_set(struct devlink_port *port, bool enable, struct netlink_ext_ack *extack); +int mlx5_devlink_pf_port_fn_state_get(struct devlink_port *port, + enum devlink_port_fn_state *state, + enum devlink_port_fn_opstate *opstate, + struct netlink_ext_ack *extack); +int mlx5_devlink_pf_port_fn_state_set(struct devlink_port *port, + enum devlink_port_fn_state state, + struct netlink_ext_ack *extack); #ifdef CONFIG_XFRM_OFFLOAD int mlx5_devlink_port_fn_ipsec_crypto_get(struct devlink_port *port, bool *is_enabled, struct netlink_ext_ack *extack); @@ -634,6 +642,8 @@ bool mlx5_esw_multipath_prereq(struct mlx5_core_dev *dev0, struct mlx5_core_dev *dev1); const u32 *mlx5_esw_query_functions(struct mlx5_core_dev *dev); +int mlx5_esw_host_pf_enable_hca(struct mlx5_core_dev *dev); +int mlx5_esw_host_pf_disable_hca(struct mlx5_core_dev *dev); void mlx5_esw_adjacent_vhcas_setup(struct mlx5_eswitch *esw); void mlx5_esw_adjacent_vhcas_cleanup(struct mlx5_eswitch *esw); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 02b7e474586d..1b439cef3719 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -4696,6 +4696,61 @@ int mlx5_devlink_port_fn_roce_set(struct devlink_port *port, bool enable, return err; } +int mlx5_devlink_pf_port_fn_state_get(struct devlink_port *port, + enum devlink_port_fn_state *state, + enum devlink_port_fn_opstate *opstate, + struct netlink_ext_ack *extack) +{ + struct mlx5_vport *vport = mlx5_devlink_port_vport_get(port); + const u32 *query_out; + bool pf_disabled; + + if (vport->vport != MLX5_VPORT_PF) { + NL_SET_ERR_MSG_MOD(extack, "State get is not supported for VF"); + return -EOPNOTSUPP; + } + + *state = vport->pf_activated ? + DEVLINK_PORT_FN_STATE_ACTIVE : DEVLINK_PORT_FN_STATE_INACTIVE; + + query_out = mlx5_esw_query_functions(vport->dev); + if (IS_ERR(query_out)) + return PTR_ERR(query_out); + + pf_disabled = MLX5_GET(query_esw_functions_out, query_out, + host_params_context.host_pf_disabled); + + *opstate = pf_disabled ? DEVLINK_PORT_FN_OPSTATE_DETACHED : + DEVLINK_PORT_FN_OPSTATE_ATTACHED; + + kvfree(query_out); + return 0; +} + +int mlx5_devlink_pf_port_fn_state_set(struct devlink_port *port, + enum devlink_port_fn_state state, + struct netlink_ext_ack *extack) +{ + struct mlx5_vport *vport = mlx5_devlink_port_vport_get(port); + struct mlx5_core_dev *dev; + + if (vport->vport != MLX5_VPORT_PF) { + NL_SET_ERR_MSG_MOD(extack, "State set is not supported for VF"); + return -EOPNOTSUPP; + } + + dev = vport->dev; + + switch (state) { + case DEVLINK_PORT_FN_STATE_ACTIVE: + return mlx5_esw_host_pf_enable_hca(dev); + case DEVLINK_PORT_FN_STATE_INACTIVE: + return mlx5_esw_host_pf_disable_hca(dev); + default: + return -EOPNOTSUPP; + } +} + int mlx5_eswitch_restore_ipsec_rule(struct mlx5_eswitch *esw, struct mlx5_flow_handle *rule, struct mlx5_esw_flow_attr *esw_attr, int attr_idx)