diff options
Diffstat (limited to 'drivers/net/ethernet/mellanox/mlxsw')
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/core.c | 16 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/core.h | 9 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/pci.c | 40 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 57 |
4 files changed, 92 insertions, 30 deletions
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index 2488662aa35e..c93512b16121 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -1800,6 +1800,22 @@ void mlxsw_core_flush_owq(void) } EXPORT_SYMBOL(mlxsw_core_flush_owq); +int mlxsw_core_kvd_sizes_get(struct mlxsw_core *mlxsw_core, + const struct mlxsw_config_profile *profile, + u64 *p_single_size, u64 *p_double_size, + u64 *p_linear_size) +{ + struct mlxsw_driver *driver = mlxsw_core->driver; + + if (!driver->kvd_sizes_get) + return -EINVAL; + + return driver->kvd_sizes_get(mlxsw_core, profile, + p_single_size, p_double_size, + p_linear_size); +} +EXPORT_SYMBOL(mlxsw_core_kvd_sizes_get); + static int __init mlxsw_core_module_init(void) { int err; diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index e23f83b14910..e44061dfe8c7 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -309,10 +309,19 @@ struct mlxsw_driver { void (*txhdr_construct)(struct sk_buff *skb, const struct mlxsw_tx_info *tx_info); int (*resources_register)(struct mlxsw_core *mlxsw_core); + int (*kvd_sizes_get)(struct mlxsw_core *mlxsw_core, + const struct mlxsw_config_profile *profile, + u64 *p_single_size, u64 *p_double_size, + u64 *p_linear_size); u8 txhdr_len; const struct mlxsw_config_profile *profile; }; +int mlxsw_core_kvd_sizes_get(struct mlxsw_core *mlxsw_core, + const struct mlxsw_config_profile *profile, + u64 *p_single_size, u64 *p_double_size, + u64 *p_linear_size); + bool mlxsw_core_res_valid(struct mlxsw_core *mlxsw_core, enum mlxsw_res_id res_id); diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c index d3f836bc2c79..58ab18845928 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.c +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c @@ -1053,38 +1053,18 @@ static int mlxsw_pci_resources_query(struct mlxsw_pci *mlxsw_pci, char *mbox, } static int -mlxsw_pci_profile_get_kvd_sizes(const struct mlxsw_config_profile *profile, +mlxsw_pci_profile_get_kvd_sizes(const struct mlxsw_pci *mlxsw_pci, + const struct mlxsw_config_profile *profile, struct mlxsw_res *res) { - u32 single_size, double_size, linear_size; - - if (!MLXSW_RES_VALID(res, KVD_SINGLE_MIN_SIZE) || - !MLXSW_RES_VALID(res, KVD_DOUBLE_MIN_SIZE) || - !profile->used_kvd_split_data) - return -EIO; - - linear_size = profile->kvd_linear_size; + u64 single_size, double_size, linear_size; + int err; - /* The hash part is what left of the kvd without the - * linear part. It is split to the single size and - * double size by the parts ratio from the profile. - * Both sizes must be a multiplications of the - * granularity from the profile. - */ - double_size = MLXSW_RES_GET(res, 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 /= profile->kvd_hash_granularity; - double_size *= profile->kvd_hash_granularity; - single_size = MLXSW_RES_GET(res, KVD_SIZE) - double_size - - linear_size; - - /* Check results are legal. */ - if (single_size < MLXSW_RES_GET(res, KVD_SINGLE_MIN_SIZE) || - double_size < MLXSW_RES_GET(res, KVD_DOUBLE_MIN_SIZE) || - MLXSW_RES_GET(res, KVD_SIZE) < linear_size) - return -EIO; + err = mlxsw_core_kvd_sizes_get(mlxsw_pci->core, profile, + &single_size, &double_size, + &linear_size); + if (err) + return err; MLXSW_RES_SET(res, KVD_SINGLE_SIZE, single_size); MLXSW_RES_SET(res, KVD_DOUBLE_SIZE, double_size); @@ -1185,7 +1165,7 @@ static int mlxsw_pci_config_profile(struct mlxsw_pci *mlxsw_pci, char *mbox, mbox, profile->adaptive_routing_group_cap); } if (MLXSW_RES_VALID(res, KVD_SIZE)) { - err = mlxsw_pci_profile_get_kvd_sizes(profile, res); + err = mlxsw_pci_profile_get_kvd_sizes(mlxsw_pci, profile, res); if (err) return err; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 87f8a74118d9..ed92e04309ba 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -4182,6 +4182,62 @@ static int mlxsw_sp_resources_register(struct mlxsw_core *mlxsw_core) return 0; } +static int mlxsw_sp_kvd_sizes_get(struct mlxsw_core *mlxsw_core, + const struct mlxsw_config_profile *profile, + u64 *p_single_size, u64 *p_double_size, + u64 *p_linear_size) +{ + struct devlink *devlink = priv_to_devlink(mlxsw_core); + u32 double_size; + int err; + + if (!MLXSW_CORE_RES_VALID(mlxsw_core, KVD_SINGLE_MIN_SIZE) || + !MLXSW_CORE_RES_VALID(mlxsw_core, KVD_DOUBLE_MIN_SIZE) || + !profile->used_kvd_split_data) + return -EIO; + + /* The hash part is what left of the kvd without the + * linear part. It is split to the single size and + * double size by the parts ratio from the profile. + * Both sizes must be a multiplications of the + * granularity from the profile. In case the user + * provided the sizes they are obtained via devlink. + */ + err = devlink_resource_size_get(devlink, + MLXSW_SP_RESOURCE_KVD_LINEAR, + p_linear_size); + if (err) + *p_linear_size = profile->kvd_linear_size; + + err = devlink_resource_size_get(devlink, + MLXSW_SP_RESOURCE_KVD_HASH_DOUBLE, + p_double_size); + if (err) { + double_size = MLXSW_CORE_RES_GET(mlxsw_core, KVD_SIZE) - + *p_linear_size; + double_size *= profile->kvd_hash_double_parts; + double_size /= profile->kvd_hash_double_parts + + profile->kvd_hash_single_parts; + *p_double_size = rounddown(double_size, + profile->kvd_hash_granularity); + } + + err = devlink_resource_size_get(devlink, + MLXSW_SP_RESOURCE_KVD_HASH_SINGLE, + p_single_size); + if (err) + *p_single_size = MLXSW_CORE_RES_GET(mlxsw_core, KVD_SIZE) - + *p_double_size - *p_linear_size; + + /* Check results are legal. */ + if (*p_single_size < MLXSW_CORE_RES_GET(mlxsw_core, KVD_SINGLE_MIN_SIZE) || + *p_double_size < MLXSW_CORE_RES_GET(mlxsw_core, KVD_DOUBLE_MIN_SIZE) || + MLXSW_CORE_RES_GET(mlxsw_core, KVD_SIZE) < *p_linear_size) + return -EIO; + + return 0; +} + static struct mlxsw_driver mlxsw_sp_driver = { .kind = mlxsw_sp_driver_name, .priv_size = sizeof(struct mlxsw_sp), @@ -4202,6 +4258,7 @@ static struct mlxsw_driver mlxsw_sp_driver = { .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, + .kvd_sizes_get = mlxsw_sp_kvd_sizes_get, .txhdr_len = MLXSW_TXHDR_LEN, .profile = &mlxsw_sp_config_profile, }; |