mirror of https://gitee.com/openkylin/linux.git
mlxsw: spectrum_router: Query number of LPM trees from firmware
Instead of hard coding the number of LPM trees in the driver, query it from the firmware, as it may change in future devices. Signed-off-by: Ido Schimmel <idosch@mellanox.com> Signed-off-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
ba82427d4a
commit
8494ab06e0
|
@ -61,6 +61,7 @@ enum mlxsw_res_id {
|
||||||
MLXSW_RES_ID_MAX_CPU_POLICERS,
|
MLXSW_RES_ID_MAX_CPU_POLICERS,
|
||||||
MLXSW_RES_ID_MAX_VRS,
|
MLXSW_RES_ID_MAX_VRS,
|
||||||
MLXSW_RES_ID_MAX_RIFS,
|
MLXSW_RES_ID_MAX_RIFS,
|
||||||
|
MLXSW_RES_ID_MAX_LPM_TREES,
|
||||||
|
|
||||||
/* Internal resources.
|
/* Internal resources.
|
||||||
* Determined by the SW, not queried from the HW.
|
* Determined by the SW, not queried from the HW.
|
||||||
|
@ -95,6 +96,7 @@ static u16 mlxsw_res_ids[] = {
|
||||||
[MLXSW_RES_ID_MAX_CPU_POLICERS] = 0x2A13,
|
[MLXSW_RES_ID_MAX_CPU_POLICERS] = 0x2A13,
|
||||||
[MLXSW_RES_ID_MAX_VRS] = 0x2C01,
|
[MLXSW_RES_ID_MAX_VRS] = 0x2C01,
|
||||||
[MLXSW_RES_ID_MAX_RIFS] = 0x2C02,
|
[MLXSW_RES_ID_MAX_RIFS] = 0x2C02,
|
||||||
|
[MLXSW_RES_ID_MAX_LPM_TREES] = 0x2C30,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mlxsw_res {
|
struct mlxsw_res {
|
||||||
|
|
|
@ -63,10 +63,6 @@
|
||||||
|
|
||||||
#define MLXSW_SP_PORTS_PER_CLUSTER_MAX 4
|
#define MLXSW_SP_PORTS_PER_CLUSTER_MAX 4
|
||||||
|
|
||||||
#define MLXSW_SP_LPM_TREE_MIN 2 /* trees 0 and 1 are reserved */
|
|
||||||
#define MLXSW_SP_LPM_TREE_MAX 22
|
|
||||||
#define MLXSW_SP_LPM_TREE_COUNT (MLXSW_SP_LPM_TREE_MAX - MLXSW_SP_LPM_TREE_MIN)
|
|
||||||
|
|
||||||
#define MLXSW_SP_PORT_BASE_SPEED 25000 /* Mb/s */
|
#define MLXSW_SP_PORT_BASE_SPEED 25000 /* Mb/s */
|
||||||
|
|
||||||
#define MLXSW_SP_BYTES_PER_CELL 96
|
#define MLXSW_SP_BYTES_PER_CELL 96
|
||||||
|
@ -230,11 +226,14 @@ struct mlxsw_sp_port_mall_tc_entry {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mlxsw_sp_router {
|
struct mlxsw_sp_router {
|
||||||
struct mlxsw_sp_lpm_tree lpm_trees[MLXSW_SP_LPM_TREE_COUNT];
|
|
||||||
struct mlxsw_sp_vr *vrs;
|
struct mlxsw_sp_vr *vrs;
|
||||||
struct rhashtable neigh_ht;
|
struct rhashtable neigh_ht;
|
||||||
struct rhashtable nexthop_group_ht;
|
struct rhashtable nexthop_group_ht;
|
||||||
struct rhashtable nexthop_ht;
|
struct rhashtable nexthop_ht;
|
||||||
|
struct {
|
||||||
|
struct mlxsw_sp_lpm_tree *trees;
|
||||||
|
unsigned int tree_count;
|
||||||
|
} lpm;
|
||||||
struct {
|
struct {
|
||||||
struct delayed_work dw;
|
struct delayed_work dw;
|
||||||
unsigned long interval; /* ms */
|
unsigned long interval; /* ms */
|
||||||
|
|
|
@ -206,8 +206,8 @@ mlxsw_sp_lpm_tree_find_unused(struct mlxsw_sp *mlxsw_sp)
|
||||||
static struct mlxsw_sp_lpm_tree *lpm_tree;
|
static struct mlxsw_sp_lpm_tree *lpm_tree;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < MLXSW_SP_LPM_TREE_COUNT; i++) {
|
for (i = 0; i < mlxsw_sp->router.lpm.tree_count; i++) {
|
||||||
lpm_tree = &mlxsw_sp->router.lpm_trees[i];
|
lpm_tree = &mlxsw_sp->router.lpm.trees[i];
|
||||||
if (lpm_tree->ref_count == 0)
|
if (lpm_tree->ref_count == 0)
|
||||||
return lpm_tree;
|
return lpm_tree;
|
||||||
}
|
}
|
||||||
|
@ -303,8 +303,8 @@ mlxsw_sp_lpm_tree_get(struct mlxsw_sp *mlxsw_sp,
|
||||||
struct mlxsw_sp_lpm_tree *lpm_tree;
|
struct mlxsw_sp_lpm_tree *lpm_tree;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < MLXSW_SP_LPM_TREE_COUNT; i++) {
|
for (i = 0; i < mlxsw_sp->router.lpm.tree_count; i++) {
|
||||||
lpm_tree = &mlxsw_sp->router.lpm_trees[i];
|
lpm_tree = &mlxsw_sp->router.lpm.trees[i];
|
||||||
if (lpm_tree->ref_count != 0 &&
|
if (lpm_tree->ref_count != 0 &&
|
||||||
lpm_tree->proto == proto &&
|
lpm_tree->proto == proto &&
|
||||||
mlxsw_sp_prefix_usage_eq(&lpm_tree->prefix_usage,
|
mlxsw_sp_prefix_usage_eq(&lpm_tree->prefix_usage,
|
||||||
|
@ -329,15 +329,36 @@ static int mlxsw_sp_lpm_tree_put(struct mlxsw_sp *mlxsw_sp,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mlxsw_sp_lpm_init(struct mlxsw_sp *mlxsw_sp)
|
#define MLXSW_SP_LPM_TREE_MIN 2 /* trees 0 and 1 are reserved */
|
||||||
|
|
||||||
|
static int mlxsw_sp_lpm_init(struct mlxsw_sp *mlxsw_sp)
|
||||||
{
|
{
|
||||||
struct mlxsw_sp_lpm_tree *lpm_tree;
|
struct mlxsw_sp_lpm_tree *lpm_tree;
|
||||||
|
u64 max_trees;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < MLXSW_SP_LPM_TREE_COUNT; i++) {
|
if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_LPM_TREES))
|
||||||
lpm_tree = &mlxsw_sp->router.lpm_trees[i];
|
return -EIO;
|
||||||
|
|
||||||
|
max_trees = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_LPM_TREES);
|
||||||
|
mlxsw_sp->router.lpm.tree_count = max_trees - MLXSW_SP_LPM_TREE_MIN;
|
||||||
|
mlxsw_sp->router.lpm.trees = kcalloc(mlxsw_sp->router.lpm.tree_count,
|
||||||
|
sizeof(struct mlxsw_sp_lpm_tree),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!mlxsw_sp->router.lpm.trees)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
for (i = 0; i < mlxsw_sp->router.lpm.tree_count; i++) {
|
||||||
|
lpm_tree = &mlxsw_sp->router.lpm.trees[i];
|
||||||
lpm_tree->id = i + MLXSW_SP_LPM_TREE_MIN;
|
lpm_tree->id = i + MLXSW_SP_LPM_TREE_MIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mlxsw_sp_lpm_fini(struct mlxsw_sp *mlxsw_sp)
|
||||||
|
{
|
||||||
|
kfree(mlxsw_sp->router.lpm.trees);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool mlxsw_sp_vr_is_used(const struct mlxsw_sp_vr *vr)
|
static bool mlxsw_sp_vr_is_used(const struct mlxsw_sp_vr *vr)
|
||||||
|
@ -3372,7 +3393,10 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp)
|
||||||
if (err)
|
if (err)
|
||||||
goto err_nexthop_group_ht_init;
|
goto err_nexthop_group_ht_init;
|
||||||
|
|
||||||
mlxsw_sp_lpm_init(mlxsw_sp);
|
err = mlxsw_sp_lpm_init(mlxsw_sp);
|
||||||
|
if (err)
|
||||||
|
goto err_lpm_init;
|
||||||
|
|
||||||
err = mlxsw_sp_vrs_init(mlxsw_sp);
|
err = mlxsw_sp_vrs_init(mlxsw_sp);
|
||||||
if (err)
|
if (err)
|
||||||
goto err_vrs_init;
|
goto err_vrs_init;
|
||||||
|
@ -3394,6 +3418,8 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp)
|
||||||
err_neigh_init:
|
err_neigh_init:
|
||||||
mlxsw_sp_vrs_fini(mlxsw_sp);
|
mlxsw_sp_vrs_fini(mlxsw_sp);
|
||||||
err_vrs_init:
|
err_vrs_init:
|
||||||
|
mlxsw_sp_lpm_fini(mlxsw_sp);
|
||||||
|
err_lpm_init:
|
||||||
rhashtable_destroy(&mlxsw_sp->router.nexthop_group_ht);
|
rhashtable_destroy(&mlxsw_sp->router.nexthop_group_ht);
|
||||||
err_nexthop_group_ht_init:
|
err_nexthop_group_ht_init:
|
||||||
rhashtable_destroy(&mlxsw_sp->router.nexthop_ht);
|
rhashtable_destroy(&mlxsw_sp->router.nexthop_ht);
|
||||||
|
@ -3407,6 +3433,7 @@ void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp)
|
||||||
unregister_fib_notifier(&mlxsw_sp->fib_nb);
|
unregister_fib_notifier(&mlxsw_sp->fib_nb);
|
||||||
mlxsw_sp_neigh_fini(mlxsw_sp);
|
mlxsw_sp_neigh_fini(mlxsw_sp);
|
||||||
mlxsw_sp_vrs_fini(mlxsw_sp);
|
mlxsw_sp_vrs_fini(mlxsw_sp);
|
||||||
|
mlxsw_sp_lpm_fini(mlxsw_sp);
|
||||||
rhashtable_destroy(&mlxsw_sp->router.nexthop_group_ht);
|
rhashtable_destroy(&mlxsw_sp->router.nexthop_group_ht);
|
||||||
rhashtable_destroy(&mlxsw_sp->router.nexthop_ht);
|
rhashtable_destroy(&mlxsw_sp->router.nexthop_ht);
|
||||||
__mlxsw_sp_router_fini(mlxsw_sp);
|
__mlxsw_sp_router_fini(mlxsw_sp);
|
||||||
|
|
Loading…
Reference in New Issue