Commit 4be4779b authored by Vadim Pasternak's avatar Vadim Pasternak Committed by Jakub Kicinski

mlxsw: core_linecards: Separate line card init and fini flow

Currently, each line card is initialized using the following steps:

1. Initializing its various fields (e.g., slot index).
2. Creating the corresponding devlink object.
3. Enabling events (i.e., traps) for changes in line card status.
4. Querying and processing line card status.

Unlike traps, the IRQ that notifies the CPU about line card status
changes cannot be enabled / disabled on a per line card basis.

If a handler is registered before the line cards are initialized, the
handler risks accessing uninitialized memory.

On the other hand, if the handler is registered after initialization,
we risk missing events. For example, in step 4, the driver might see
that a line card is in ready state and will tell the device to enable
it. When enablement is done, the line card will be activated and the
IRQ will be triggered. Since a handler was not registered, the event
will be missed.

Solve this by splitting the initialization sequence into two steps
(1-2 and 3-4). In a subsequent patch, the handler will be registered
between both steps.
Signed-off-by: default avatarVadim Pasternak <vadimp@nvidia.com>
Reviewed-by: default avatarJiri Pirko <jiri@nvidia.com>
Signed-off-by: default avatarIdo Schimmel <idosch@nvidia.com>
Signed-off-by: default avatarPetr Machata <petrm@nvidia.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 510156a7
...@@ -1238,7 +1238,6 @@ static int mlxsw_linecard_init(struct mlxsw_core *mlxsw_core, ...@@ -1238,7 +1238,6 @@ static int mlxsw_linecard_init(struct mlxsw_core *mlxsw_core,
{ {
struct devlink_linecard *devlink_linecard; struct devlink_linecard *devlink_linecard;
struct mlxsw_linecard *linecard; struct mlxsw_linecard *linecard;
int err;
linecard = mlxsw_linecard_get(linecards, slot_index); linecard = mlxsw_linecard_get(linecards, slot_index);
linecard->slot_index = slot_index; linecard->slot_index = slot_index;
...@@ -1248,17 +1247,45 @@ static int mlxsw_linecard_init(struct mlxsw_core *mlxsw_core, ...@@ -1248,17 +1247,45 @@ static int mlxsw_linecard_init(struct mlxsw_core *mlxsw_core,
devlink_linecard = devlink_linecard_create(priv_to_devlink(mlxsw_core), devlink_linecard = devlink_linecard_create(priv_to_devlink(mlxsw_core),
slot_index, &mlxsw_linecard_ops, slot_index, &mlxsw_linecard_ops,
linecard); linecard);
if (IS_ERR(devlink_linecard)) { if (IS_ERR(devlink_linecard))
err = PTR_ERR(devlink_linecard); return PTR_ERR(devlink_linecard);
goto err_devlink_linecard_create;
}
linecard->devlink_linecard = devlink_linecard; linecard->devlink_linecard = devlink_linecard;
INIT_DELAYED_WORK(&linecard->status_event_to_dw, INIT_DELAYED_WORK(&linecard->status_event_to_dw,
&mlxsw_linecard_status_event_to_work); &mlxsw_linecard_status_event_to_work);
return 0;
}
static void mlxsw_linecard_fini(struct mlxsw_core *mlxsw_core,
struct mlxsw_linecards *linecards,
u8 slot_index)
{
struct mlxsw_linecard *linecard;
linecard = mlxsw_linecard_get(linecards, slot_index);
cancel_delayed_work_sync(&linecard->status_event_to_dw);
/* Make sure all scheduled events are processed */
mlxsw_core_flush_owq();
if (linecard->active)
mlxsw_linecard_active_clear(linecard);
mlxsw_linecard_bdev_del(linecard);
devlink_linecard_destroy(linecard->devlink_linecard);
mutex_destroy(&linecard->lock);
}
static int
mlxsw_linecard_event_delivery_init(struct mlxsw_core *mlxsw_core,
struct mlxsw_linecards *linecards,
u8 slot_index)
{
struct mlxsw_linecard *linecard;
int err;
linecard = mlxsw_linecard_get(linecards, slot_index);
err = mlxsw_linecard_event_delivery_set(mlxsw_core, linecard, true); err = mlxsw_linecard_event_delivery_set(mlxsw_core, linecard, true);
if (err) if (err)
goto err_event_delivery_set; return err;
err = mlxsw_linecard_status_get_and_process(mlxsw_core, linecards, err = mlxsw_linecard_status_get_and_process(mlxsw_core, linecards,
linecard); linecard);
...@@ -1269,29 +1296,18 @@ static int mlxsw_linecard_init(struct mlxsw_core *mlxsw_core, ...@@ -1269,29 +1296,18 @@ static int mlxsw_linecard_init(struct mlxsw_core *mlxsw_core,
err_status_get_and_process: err_status_get_and_process:
mlxsw_linecard_event_delivery_set(mlxsw_core, linecard, false); mlxsw_linecard_event_delivery_set(mlxsw_core, linecard, false);
err_event_delivery_set:
devlink_linecard_destroy(linecard->devlink_linecard);
err_devlink_linecard_create:
mutex_destroy(&linecard->lock);
return err; return err;
} }
static void mlxsw_linecard_fini(struct mlxsw_core *mlxsw_core, static void
struct mlxsw_linecards *linecards, mlxsw_linecard_event_delivery_fini(struct mlxsw_core *mlxsw_core,
u8 slot_index) struct mlxsw_linecards *linecards,
u8 slot_index)
{ {
struct mlxsw_linecard *linecard; struct mlxsw_linecard *linecard;
linecard = mlxsw_linecard_get(linecards, slot_index); linecard = mlxsw_linecard_get(linecards, slot_index);
mlxsw_linecard_event_delivery_set(mlxsw_core, linecard, false); mlxsw_linecard_event_delivery_set(mlxsw_core, linecard, false);
cancel_delayed_work_sync(&linecard->status_event_to_dw);
/* Make sure all scheduled events are processed */
mlxsw_core_flush_owq();
if (linecard->active)
mlxsw_linecard_active_clear(linecard);
mlxsw_linecard_bdev_del(linecard);
devlink_linecard_destroy(linecard->devlink_linecard);
mutex_destroy(&linecard->lock);
} }
/* LINECARDS INI BUNDLE FILE /* LINECARDS INI BUNDLE FILE
...@@ -1513,8 +1529,19 @@ int mlxsw_linecards_init(struct mlxsw_core *mlxsw_core, ...@@ -1513,8 +1529,19 @@ int mlxsw_linecards_init(struct mlxsw_core *mlxsw_core,
goto err_linecard_init; goto err_linecard_init;
} }
for (i = 0; i < linecards->count; i++) {
err = mlxsw_linecard_event_delivery_init(mlxsw_core, linecards,
i + 1);
if (err)
goto err_linecard_event_delivery_init;
}
return 0; return 0;
err_linecard_event_delivery_init:
for (i--; i >= 0; i--)
mlxsw_linecard_event_delivery_fini(mlxsw_core, linecards, i + 1);
i = linecards->count;
err_linecard_init: err_linecard_init:
for (i--; i >= 0; i--) for (i--; i >= 0; i--)
mlxsw_linecard_fini(mlxsw_core, linecards, i + 1); mlxsw_linecard_fini(mlxsw_core, linecards, i + 1);
...@@ -1535,6 +1562,8 @@ void mlxsw_linecards_fini(struct mlxsw_core *mlxsw_core) ...@@ -1535,6 +1562,8 @@ void mlxsw_linecards_fini(struct mlxsw_core *mlxsw_core)
if (!linecards) if (!linecards)
return; return;
for (i = 0; i < linecards->count; i++)
mlxsw_linecard_event_delivery_fini(mlxsw_core, linecards, i + 1);
for (i = 0; i < linecards->count; i++) for (i = 0; i < linecards->count; i++)
mlxsw_linecard_fini(mlxsw_core, linecards, i + 1); mlxsw_linecard_fini(mlxsw_core, linecards, i + 1);
mlxsw_core_traps_unregister(mlxsw_core, mlxsw_linecard_listener, mlxsw_core_traps_unregister(mlxsw_core, mlxsw_linecard_listener,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment