Skip to content

Commit

Permalink
mlxsw: core_linecards: Separate line card init and fini flow
Browse files Browse the repository at this point in the history
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: Vadim Pasternak <vadimp@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: Petr Machata <petrm@nvidia.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Vadim Pasternak authored and Jakub Kicinski committed Aug 24, 2022
1 parent 510156a commit 4be4779
Showing 1 changed file with 50 additions and 21 deletions.
71 changes: 50 additions & 21 deletions drivers/net/ethernet/mellanox/mlxsw/core_linecards.c
Original file line number Diff line number Diff line change
Expand Up @@ -1238,7 +1238,6 @@ static int mlxsw_linecard_init(struct mlxsw_core *mlxsw_core,
{
struct devlink_linecard *devlink_linecard;
struct mlxsw_linecard *linecard;
int err;

linecard = mlxsw_linecard_get(linecards, slot_index);
linecard->slot_index = slot_index;
Expand All @@ -1248,17 +1247,45 @@ static int mlxsw_linecard_init(struct mlxsw_core *mlxsw_core,
devlink_linecard = devlink_linecard_create(priv_to_devlink(mlxsw_core),
slot_index, &mlxsw_linecard_ops,
linecard);
if (IS_ERR(devlink_linecard)) {
err = PTR_ERR(devlink_linecard);
goto err_devlink_linecard_create;
}
if (IS_ERR(devlink_linecard))
return PTR_ERR(devlink_linecard);

linecard->devlink_linecard = devlink_linecard;
INIT_DELAYED_WORK(&linecard->status_event_to_dw,
&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);
if (err)
goto err_event_delivery_set;
return err;

err = mlxsw_linecard_status_get_and_process(mlxsw_core, linecards,
linecard);
Expand All @@ -1269,29 +1296,18 @@ static int mlxsw_linecard_init(struct mlxsw_core *mlxsw_core,

err_status_get_and_process:
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;
}

static void mlxsw_linecard_fini(struct mlxsw_core *mlxsw_core,
struct mlxsw_linecards *linecards,
u8 slot_index)
static void
mlxsw_linecard_event_delivery_fini(struct mlxsw_core *mlxsw_core,
struct mlxsw_linecards *linecards,
u8 slot_index)
{
struct mlxsw_linecard *linecard;

linecard = mlxsw_linecard_get(linecards, slot_index);
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
Expand Down Expand Up @@ -1513,8 +1529,19 @@ int mlxsw_linecards_init(struct mlxsw_core *mlxsw_core,
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;

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:
for (i--; i >= 0; i--)
mlxsw_linecard_fini(mlxsw_core, linecards, i + 1);
Expand All @@ -1535,6 +1562,8 @@ void mlxsw_linecards_fini(struct mlxsw_core *mlxsw_core)

if (!linecards)
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++)
mlxsw_linecard_fini(mlxsw_core, linecards, i + 1);
mlxsw_core_traps_unregister(mlxsw_core, mlxsw_linecard_listener,
Expand Down

0 comments on commit 4be4779

Please sign in to comment.