diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index f3315bc874adf8228f6277936c961d7afca95353..2488662aa35e0110fe91f7d79cf9f549ed61ac30 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -1012,6 +1012,12 @@ int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info, if (err) goto err_bus_init; + if (mlxsw_driver->resources_register) { + err = mlxsw_driver->resources_register(mlxsw_core); + if (err) + goto err_register_resources; + } + err = mlxsw_ports_init(mlxsw_core); if (err) goto err_ports_init; @@ -1067,6 +1073,8 @@ int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info, err_ports_init: mlxsw_bus->fini(bus_priv); err_bus_init: + devlink_resources_unregister(devlink, NULL); +err_register_resources: devlink_free(devlink); err_devlink_alloc: mlxsw_core_driver_put(device_kind); @@ -1086,6 +1094,7 @@ void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core) mlxsw_emad_fini(mlxsw_core); kfree(mlxsw_core->lag.mapping); mlxsw_ports_fini(mlxsw_core); + devlink_resources_unregister(devlink, NULL); mlxsw_core->bus->fini(mlxsw_core->bus_priv); devlink_free(devlink); mlxsw_core_driver_put(device_kind); diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index 34dda964dcbd009ae3aecc91b73b917bb37640d1..e23f83b14910ef96774d73e1d809b5e05b31692b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -308,6 +308,7 @@ struct mlxsw_driver { u32 *p_cur, u32 *p_max); void (*txhdr_construct)(struct sk_buff *skb, const struct mlxsw_tx_info *tx_info); + int (*resources_register)(struct mlxsw_core *mlxsw_core); u8 txhdr_len; const struct mlxsw_config_profile *profile; }; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index f78bfe39496644e7354e005f7fd22162224cd16b..53b16ddc6accfefebdc6e038036d65195c2b7bf9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -3991,6 +3991,188 @@ static const struct mlxsw_config_profile mlxsw_sp_config_profile = { .resource_query_enable = 1, }; +static bool +mlxsw_sp_resource_kvd_granularity_validate(struct netlink_ext_ack *extack, + u64 size) +{ + const struct mlxsw_config_profile *profile; + + profile = &mlxsw_sp_config_profile; + if (size % profile->kvd_hash_granularity) { + NL_SET_ERR_MSG_MOD(extack, "resource set with wrong granularity"); + return false; + } + return true; +} + +static int +mlxsw_sp_resource_kvd_size_validate(struct devlink *devlink, u64 size, + struct netlink_ext_ack *extack) +{ + NL_SET_ERR_MSG_MOD(extack, "kvd size cannot be changed"); + return -EINVAL; +} + +static int +mlxsw_sp_resource_kvd_linear_size_validate(struct devlink *devlink, u64 size, + struct netlink_ext_ack *extack) +{ + if (!mlxsw_sp_resource_kvd_granularity_validate(extack, size)) + return -EINVAL; + + return 0; +} + +static int +mlxsw_sp_resource_kvd_hash_single_size_validate(struct devlink *devlink, u64 size, + struct netlink_ext_ack *extack) +{ + struct mlxsw_core *mlxsw_core = devlink_priv(devlink); + + if (!mlxsw_sp_resource_kvd_granularity_validate(extack, size)) + return -EINVAL; + + if (size < MLXSW_CORE_RES_GET(mlxsw_core, KVD_SINGLE_MIN_SIZE)) { + NL_SET_ERR_MSG_MOD(extack, "hash single size is smaller than minimum"); + return -EINVAL; + } + return 0; +} + +static int +mlxsw_sp_resource_kvd_hash_double_size_validate(struct devlink *devlink, u64 size, + struct netlink_ext_ack *extack) +{ + struct mlxsw_core *mlxsw_core = devlink_priv(devlink); + + if (!mlxsw_sp_resource_kvd_granularity_validate(extack, size)) + return -EINVAL; + + if (size < MLXSW_CORE_RES_GET(mlxsw_core, KVD_DOUBLE_MIN_SIZE)) { + NL_SET_ERR_MSG_MOD(extack, "hash double size is smaller than minimum"); + return -EINVAL; + } + return 0; +} + +static struct devlink_resource_ops mlxsw_sp_resource_kvd_ops = { + .size_validate = mlxsw_sp_resource_kvd_size_validate, +}; + +static struct devlink_resource_ops mlxsw_sp_resource_kvd_linear_ops = { + .size_validate = mlxsw_sp_resource_kvd_linear_size_validate, +}; + +static struct devlink_resource_ops mlxsw_sp_resource_kvd_hash_single_ops = { + .size_validate = mlxsw_sp_resource_kvd_hash_single_size_validate, +}; + +static struct devlink_resource_ops mlxsw_sp_resource_kvd_hash_double_ops = { + .size_validate = mlxsw_sp_resource_kvd_hash_double_size_validate, +}; + +static struct devlink_resource_size_params mlxsw_sp_kvd_size_params; +static struct devlink_resource_size_params mlxsw_sp_linear_size_params; +static struct devlink_resource_size_params mlxsw_sp_hash_single_size_params; +static struct devlink_resource_size_params mlxsw_sp_hash_double_size_params; + +static void +mlxsw_sp_resource_size_params_prepare(struct mlxsw_core *mlxsw_core) +{ + u32 single_size_min = MLXSW_CORE_RES_GET(mlxsw_core, + KVD_SINGLE_MIN_SIZE); + u32 double_size_min = MLXSW_CORE_RES_GET(mlxsw_core, + KVD_DOUBLE_MIN_SIZE); + u32 kvd_size = MLXSW_CORE_RES_GET(mlxsw_core, KVD_SIZE); + u32 linear_size_min = 0; + + /* KVD top resource */ + mlxsw_sp_kvd_size_params.size_min = kvd_size; + mlxsw_sp_kvd_size_params.size_max = kvd_size; + mlxsw_sp_kvd_size_params.size_granularity = MLXSW_SP_KVD_GRANULARITY; + mlxsw_sp_kvd_size_params.unit = DEVLINK_RESOURCE_UNIT_ENTRY; + + /* Linear part init */ + mlxsw_sp_linear_size_params.size_min = linear_size_min; + mlxsw_sp_linear_size_params.size_max = kvd_size - single_size_min - + double_size_min; + mlxsw_sp_linear_size_params.size_granularity = MLXSW_SP_KVD_GRANULARITY; + mlxsw_sp_linear_size_params.unit = DEVLINK_RESOURCE_UNIT_ENTRY; + + /* Hash double part init */ + mlxsw_sp_hash_double_size_params.size_min = double_size_min; + mlxsw_sp_hash_double_size_params.size_max = kvd_size - single_size_min - + linear_size_min; + mlxsw_sp_hash_double_size_params.size_granularity = MLXSW_SP_KVD_GRANULARITY; + mlxsw_sp_hash_double_size_params.unit = DEVLINK_RESOURCE_UNIT_ENTRY; + + /* Hash single part init */ + mlxsw_sp_hash_single_size_params.size_min = single_size_min; + mlxsw_sp_hash_single_size_params.size_max = kvd_size - double_size_min - + linear_size_min; + mlxsw_sp_hash_single_size_params.size_granularity = MLXSW_SP_KVD_GRANULARITY; + mlxsw_sp_hash_single_size_params.unit = DEVLINK_RESOURCE_UNIT_ENTRY; +} + +static int mlxsw_sp_resources_register(struct mlxsw_core *mlxsw_core) +{ + struct devlink *devlink = priv_to_devlink(mlxsw_core); + u32 kvd_size, single_size, double_size, linear_size; + const struct mlxsw_config_profile *profile; + int err; + + profile = &mlxsw_sp_config_profile; + if (!MLXSW_CORE_RES_VALID(mlxsw_core, KVD_SIZE)) + return -EIO; + + mlxsw_sp_resource_size_params_prepare(mlxsw_core); + kvd_size = MLXSW_CORE_RES_GET(mlxsw_core, KVD_SIZE); + err = devlink_resource_register(devlink, MLXSW_SP_RESOURCE_NAME_KVD, + true, kvd_size, + MLXSW_SP_RESOURCE_KVD, + DEVLINK_RESOURCE_ID_PARENT_TOP, + &mlxsw_sp_kvd_size_params, + &mlxsw_sp_resource_kvd_ops); + if (err) + return err; + + linear_size = profile->kvd_linear_size; + err = devlink_resource_register(devlink, MLXSW_SP_RESOURCE_NAME_KVD_LINEAR, + false, linear_size, + MLXSW_SP_RESOURCE_KVD_LINEAR, + MLXSW_SP_RESOURCE_KVD, + &mlxsw_sp_linear_size_params, + &mlxsw_sp_resource_kvd_linear_ops); + if (err) + return err; + + double_size = kvd_size - linear_size; + double_size *= profile->kvd_hash_double_parts; + double_size /= profile->kvd_hash_double_parts + + profile->kvd_hash_single_parts; + double_size = rounddown(double_size, profile->kvd_hash_granularity); + err = devlink_resource_register(devlink, MLXSW_SP_RESOURCE_NAME_KVD_HASH_DOUBLE, + false, double_size, + MLXSW_SP_RESOURCE_KVD_HASH_DOUBLE, + MLXSW_SP_RESOURCE_KVD, + &mlxsw_sp_hash_double_size_params, + &mlxsw_sp_resource_kvd_hash_double_ops); + if (err) + return err; + + single_size = kvd_size - double_size - linear_size; + err = devlink_resource_register(devlink, MLXSW_SP_RESOURCE_NAME_KVD_HASH_SINGLE, + false, single_size, + MLXSW_SP_RESOURCE_KVD_HASH_SINGLE, + MLXSW_SP_RESOURCE_KVD, + &mlxsw_sp_hash_single_size_params, + &mlxsw_sp_resource_kvd_hash_single_ops); + if (err) + return err; + + return 0; +} + static struct mlxsw_driver mlxsw_sp_driver = { .kind = mlxsw_sp_driver_name, .priv_size = sizeof(struct mlxsw_sp), @@ -4010,6 +4192,7 @@ static struct mlxsw_driver mlxsw_sp_driver = { .sb_occ_port_pool_get = mlxsw_sp_sb_occ_port_pool_get, .sb_occ_tc_port_bind_get = mlxsw_sp_sb_occ_tc_port_bind_get, .txhdr_construct = mlxsw_sp_txhdr_construct, + .resources_register = mlxsw_sp_resources_register, .txhdr_len = MLXSW_TXHDR_LEN, .profile = &mlxsw_sp_config_profile, }; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 16f8fbda0891a2fa4721060fedfd2299adcdfb39..435e0f2225f69bddb379bb2e51ba5af0c25734df 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -66,6 +66,18 @@ #define MLXSW_SP_KVD_LINEAR_SIZE 98304 /* entries */ #define MLXSW_SP_KVD_GRANULARITY 128 +#define MLXSW_SP_RESOURCE_NAME_KVD "kvd" +#define MLXSW_SP_RESOURCE_NAME_KVD_LINEAR "linear" +#define MLXSW_SP_RESOURCE_NAME_KVD_HASH_SINGLE "hash_single" +#define MLXSW_SP_RESOURCE_NAME_KVD_HASH_DOUBLE "hash_double" + +enum mlxsw_sp_resource_id { + MLXSW_SP_RESOURCE_KVD, + MLXSW_SP_RESOURCE_KVD_LINEAR, + MLXSW_SP_RESOURCE_KVD_HASH_SINGLE, + MLXSW_SP_RESOURCE_KVD_HASH_DOUBLE, +}; + struct mlxsw_sp_port; struct mlxsw_sp_rif;