mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-28 05:08:09 +07:00
mlxsw: spectrum_router: Pass multiple routes to work item
Prepare the driver to process IPv6 multipath notifications by passing an array of 'struct fib6_info' instead of just one route. A reference is taken on each sibling route in order to prevent them from being freed until they are processed by the workqueue. v2: * Remove 'multipath_rt' usage Signed-off-by: Ido Schimmel <idosch@mellanox.com> Acked-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
ccd56a5f50
commit
928c0b534f
@ -5893,10 +5893,15 @@ static void mlxsw_sp_router_fib_abort(struct mlxsw_sp *mlxsw_sp)
|
||||
dev_warn(mlxsw_sp->bus_info->dev, "Failed to set abort trap.\n");
|
||||
}
|
||||
|
||||
struct mlxsw_sp_fib6_event_work {
|
||||
struct fib6_info **rt_arr;
|
||||
unsigned int nrt6;
|
||||
};
|
||||
|
||||
struct mlxsw_sp_fib_event_work {
|
||||
struct work_struct work;
|
||||
union {
|
||||
struct fib6_entry_notifier_info fen6_info;
|
||||
struct mlxsw_sp_fib6_event_work fib6_work;
|
||||
struct fib_entry_notifier_info fen_info;
|
||||
struct fib_rule_notifier_info fr_info;
|
||||
struct fib_nh_notifier_info fnh_info;
|
||||
@ -5907,6 +5912,54 @@ struct mlxsw_sp_fib_event_work {
|
||||
unsigned long event;
|
||||
};
|
||||
|
||||
static int
|
||||
mlxsw_sp_router_fib6_work_init(struct mlxsw_sp_fib6_event_work *fib6_work,
|
||||
struct fib6_entry_notifier_info *fen6_info)
|
||||
{
|
||||
struct fib6_info *rt = fen6_info->rt;
|
||||
struct fib6_info **rt_arr;
|
||||
struct fib6_info *iter;
|
||||
unsigned int nrt6;
|
||||
int i = 0;
|
||||
|
||||
nrt6 = fen6_info->nsiblings + 1;
|
||||
|
||||
rt_arr = kcalloc(nrt6, sizeof(struct fib6_info *), GFP_ATOMIC);
|
||||
if (!rt_arr)
|
||||
return -ENOMEM;
|
||||
|
||||
fib6_work->rt_arr = rt_arr;
|
||||
fib6_work->nrt6 = nrt6;
|
||||
|
||||
rt_arr[0] = rt;
|
||||
fib6_info_hold(rt);
|
||||
|
||||
if (!fen6_info->nsiblings)
|
||||
return 0;
|
||||
|
||||
list_for_each_entry(iter, &rt->fib6_siblings, fib6_siblings) {
|
||||
if (i == fen6_info->nsiblings)
|
||||
break;
|
||||
|
||||
rt_arr[i + 1] = iter;
|
||||
fib6_info_hold(iter);
|
||||
i++;
|
||||
}
|
||||
WARN_ON_ONCE(i != fen6_info->nsiblings);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mlxsw_sp_router_fib6_work_fini(struct mlxsw_sp_fib6_event_work *fib6_work)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < fib6_work->nrt6; i++)
|
||||
mlxsw_sp_rt6_release(fib6_work->rt_arr[i]);
|
||||
kfree(fib6_work->rt_arr);
|
||||
}
|
||||
|
||||
static void mlxsw_sp_router_fib4_event_work(struct work_struct *work)
|
||||
{
|
||||
struct mlxsw_sp_fib_event_work *fib_work =
|
||||
@ -5968,14 +6021,16 @@ static void mlxsw_sp_router_fib6_event_work(struct work_struct *work)
|
||||
case FIB_EVENT_ENTRY_ADD:
|
||||
replace = fib_work->event == FIB_EVENT_ENTRY_REPLACE;
|
||||
err = mlxsw_sp_router_fib6_add(mlxsw_sp,
|
||||
fib_work->fen6_info.rt, replace);
|
||||
fib_work->fib6_work.rt_arr[0],
|
||||
replace);
|
||||
if (err)
|
||||
mlxsw_sp_router_fib_abort(mlxsw_sp);
|
||||
mlxsw_sp_rt6_release(fib_work->fen6_info.rt);
|
||||
mlxsw_sp_router_fib6_work_fini(&fib_work->fib6_work);
|
||||
break;
|
||||
case FIB_EVENT_ENTRY_DEL:
|
||||
mlxsw_sp_router_fib6_del(mlxsw_sp, fib_work->fen6_info.rt);
|
||||
mlxsw_sp_rt6_release(fib_work->fen6_info.rt);
|
||||
mlxsw_sp_router_fib6_del(mlxsw_sp,
|
||||
fib_work->fib6_work.rt_arr[0]);
|
||||
mlxsw_sp_router_fib6_work_fini(&fib_work->fib6_work);
|
||||
break;
|
||||
case FIB_EVENT_RULE_ADD:
|
||||
/* if we get here, a rule was added that we do not support.
|
||||
@ -6068,6 +6123,7 @@ static int mlxsw_sp_router_fib6_event(struct mlxsw_sp_fib_event_work *fib_work,
|
||||
struct fib_notifier_info *info)
|
||||
{
|
||||
struct fib6_entry_notifier_info *fen6_info;
|
||||
int err;
|
||||
|
||||
switch (fib_work->event) {
|
||||
case FIB_EVENT_ENTRY_REPLACE: /* fall through */
|
||||
@ -6075,8 +6131,10 @@ static int mlxsw_sp_router_fib6_event(struct mlxsw_sp_fib_event_work *fib_work,
|
||||
case FIB_EVENT_ENTRY_DEL:
|
||||
fen6_info = container_of(info, struct fib6_entry_notifier_info,
|
||||
info);
|
||||
fib_work->fen6_info = *fen6_info;
|
||||
fib6_info_hold(fib_work->fen6_info.rt);
|
||||
err = mlxsw_sp_router_fib6_work_init(&fib_work->fib6_work,
|
||||
fen6_info);
|
||||
if (err)
|
||||
return err;
|
||||
break;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user