Skip to content
This repository has been archived by the owner on Nov 21, 2022. It is now read-only.

Commit

Permalink
Merge branch 'mlxsw-introduce-modular-system-support-by-minimal-driver'
Browse files Browse the repository at this point in the history
Petr Machata says:

====================
mlxsw: Introduce modular system support by minimal driver

Vadim Pasternak writes:

This patchset adds line cards support in mlxsw_minimal, which is used
for monitoring purposes on BMC systems. The BMC is connected to the
ASIC over I2C bus, unlike the host CPU that is connected to the ASIC
via PCI bus.

The BMC system needs to be notified whenever line cards become active
or inactive, so that, for example, netdevs will be registered /
unregistered by mlxsw_minimal. However, traps cannot be generated
towards the BMC over the I2C bus. To overcome that, the I2C bus driver
(i.e., mlxsw_i2c) registers an handler for an IRQ that is fired upon
specific system wide changes, like line card activation and
deactivation.

The generated event is handled by mlxsw_core, which checks whether
anything changed in the state of available line cards. If a line card
becomes active or inactive, interested parties such as mlxsw_minimal
are notified via their registered line card event callback.

Patch set overview:

Patches #1 is preparations.

Patches #2-#3 extend mlxsw_core with an infrastructure to handle the
	previously mentioned system events.

Patch #4 extends the I2C bus driver to register an handler for the IRQ
	fired upon specific system wide changes.

Patches #5-#8 gradually add line cards support in mlxsw_minimal by
	dynamically registering / unregistering netdevs for ports found on
	line cards, whenever a line card becomes active / inactive.
====================

Link: https://lore.kernel.org/r/cover.1661093502.git.petrm@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
kuba-moo committed Aug 24, 2022
2 parents 510156a + 706ddb7 commit 3de1484
Show file tree
Hide file tree
Showing 5 changed files with 546 additions and 86 deletions.
68 changes: 68 additions & 0 deletions drivers/net/ethernet/mellanox/mlxsw/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ struct mlxsw_core {
struct workqueue_struct *emad_wq;
struct list_head rx_listener_list;
struct list_head event_listener_list;
struct list_head irq_event_handler_list;
struct mutex irq_event_handler_lock; /* Locks access to handlers list */
struct {
atomic64_t tid;
struct list_head trans_list;
Expand Down Expand Up @@ -2090,6 +2092,18 @@ static void mlxsw_core_health_fini(struct mlxsw_core *mlxsw_core)
devlink_health_reporter_destroy(mlxsw_core->health.fw_fatal);
}

static void mlxsw_core_irq_event_handler_init(struct mlxsw_core *mlxsw_core)
{
INIT_LIST_HEAD(&mlxsw_core->irq_event_handler_list);
mutex_init(&mlxsw_core->irq_event_handler_lock);
}

static void mlxsw_core_irq_event_handler_fini(struct mlxsw_core *mlxsw_core)
{
mutex_destroy(&mlxsw_core->irq_event_handler_lock);
WARN_ON(!list_empty(&mlxsw_core->irq_event_handler_list));
}

static int
__mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info,
const struct mlxsw_bus *mlxsw_bus,
Expand Down Expand Up @@ -2125,6 +2139,7 @@ __mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info,
mlxsw_core->bus = mlxsw_bus;
mlxsw_core->bus_priv = bus_priv;
mlxsw_core->bus_info = mlxsw_bus_info;
mlxsw_core_irq_event_handler_init(mlxsw_core);

err = mlxsw_bus->init(bus_priv, mlxsw_core, mlxsw_driver->profile,
&mlxsw_core->res);
Expand Down Expand Up @@ -2233,6 +2248,7 @@ __mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info,
err_register_resources:
mlxsw_bus->fini(bus_priv);
err_bus_init:
mlxsw_core_irq_event_handler_fini(mlxsw_core);
if (!reload) {
devl_unlock(devlink);
devlink_free(devlink);
Expand Down Expand Up @@ -2302,6 +2318,7 @@ void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core,
if (!reload)
devl_resources_unregister(devlink);
mlxsw_core->bus->fini(mlxsw_core->bus_priv);
mlxsw_core_irq_event_handler_fini(mlxsw_core);
if (!reload) {
devl_unlock(devlink);
devlink_free(devlink);
Expand Down Expand Up @@ -2772,6 +2789,57 @@ int mlxsw_reg_trans_bulk_wait(struct list_head *bulk_list)
}
EXPORT_SYMBOL(mlxsw_reg_trans_bulk_wait);

struct mlxsw_core_irq_event_handler_item {
struct list_head list;
void (*cb)(struct mlxsw_core *mlxsw_core);
};

int mlxsw_core_irq_event_handler_register(struct mlxsw_core *mlxsw_core,
mlxsw_irq_event_cb_t cb)
{
struct mlxsw_core_irq_event_handler_item *item;

item = kzalloc(sizeof(*item), GFP_KERNEL);
if (!item)
return -ENOMEM;
item->cb = cb;
mutex_lock(&mlxsw_core->irq_event_handler_lock);
list_add_tail(&item->list, &mlxsw_core->irq_event_handler_list);
mutex_unlock(&mlxsw_core->irq_event_handler_lock);
return 0;
}
EXPORT_SYMBOL(mlxsw_core_irq_event_handler_register);

void mlxsw_core_irq_event_handler_unregister(struct mlxsw_core *mlxsw_core,
mlxsw_irq_event_cb_t cb)
{
struct mlxsw_core_irq_event_handler_item *item, *tmp;

mutex_lock(&mlxsw_core->irq_event_handler_lock);
list_for_each_entry_safe(item, tmp,
&mlxsw_core->irq_event_handler_list, list) {
if (item->cb == cb) {
list_del(&item->list);
kfree(item);
}
}
mutex_unlock(&mlxsw_core->irq_event_handler_lock);
}
EXPORT_SYMBOL(mlxsw_core_irq_event_handler_unregister);

void mlxsw_core_irq_event_handlers_call(struct mlxsw_core *mlxsw_core)
{
struct mlxsw_core_irq_event_handler_item *item;

mutex_lock(&mlxsw_core->irq_event_handler_lock);
list_for_each_entry(item, &mlxsw_core->irq_event_handler_list, list) {
if (item->cb)
item->cb(mlxsw_core);
}
mutex_unlock(&mlxsw_core->irq_event_handler_lock);
}
EXPORT_SYMBOL(mlxsw_core_irq_event_handlers_call);

static int mlxsw_core_reg_access_cmd(struct mlxsw_core *mlxsw_core,
const struct mlxsw_reg_info *reg,
char *payload,
Expand Down
8 changes: 8 additions & 0 deletions drivers/net/ethernet/mellanox/mlxsw/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,14 @@ int mlxsw_reg_trans_write(struct mlxsw_core *mlxsw_core,
mlxsw_reg_trans_cb_t *cb, unsigned long cb_priv);
int mlxsw_reg_trans_bulk_wait(struct list_head *bulk_list);

typedef void mlxsw_irq_event_cb_t(struct mlxsw_core *mlxsw_core);

int mlxsw_core_irq_event_handler_register(struct mlxsw_core *mlxsw_core,
mlxsw_irq_event_cb_t cb);
void mlxsw_core_irq_event_handler_unregister(struct mlxsw_core *mlxsw_core,
mlxsw_irq_event_cb_t cb);
void mlxsw_core_irq_event_handlers_call(struct mlxsw_core *mlxsw_core);

int mlxsw_reg_query(struct mlxsw_core *mlxsw_core,
const struct mlxsw_reg_info *reg, char *payload);
int mlxsw_reg_write(struct mlxsw_core *mlxsw_core,
Expand Down
96 changes: 75 additions & 21 deletions drivers/net/ethernet/mellanox/mlxsw/core_linecards.c
Original file line number Diff line number Diff line change
Expand Up @@ -785,6 +785,21 @@ static int mlxsw_linecard_status_get_and_process(struct mlxsw_core *mlxsw_core,
return mlxsw_linecard_status_process(linecards, linecard, mddq_pl);
}

static void mlxsw_linecards_irq_event_handler(struct mlxsw_core *mlxsw_core)
{
struct mlxsw_linecards *linecards = mlxsw_core_linecards(mlxsw_core);
int i;

/* Handle change of line card active state. */
for (i = 0; i < linecards->count; i++) {
struct mlxsw_linecard *linecard = mlxsw_linecard_get(linecards,
i + 1);

mlxsw_linecard_status_get_and_process(mlxsw_core, linecards,
linecard);
}
}

static const char * const mlxsw_linecard_status_event_type_name[] = {
[MLXSW_LINECARD_STATUS_EVENT_TYPE_PROVISION] = "provision",
[MLXSW_LINECARD_STATUS_EVENT_TYPE_UNPROVISION] = "unprovision",
Expand Down Expand Up @@ -1238,7 +1253,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 +1262,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 +1311,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 @@ -1505,6 +1536,11 @@ int mlxsw_linecards_init(struct mlxsw_core *mlxsw_core,
if (err)
goto err_traps_register;

err = mlxsw_core_irq_event_handler_register(mlxsw_core,
mlxsw_linecards_irq_event_handler);
if (err)
goto err_irq_event_handler_register;

mlxsw_core_linecards_set(mlxsw_core, linecards);

for (i = 0; i < linecards->count; i++) {
Expand All @@ -1513,11 +1549,25 @@ 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);
mlxsw_core_irq_event_handler_unregister(mlxsw_core,
mlxsw_linecards_irq_event_handler);
err_irq_event_handler_register:
mlxsw_core_traps_unregister(mlxsw_core, mlxsw_linecard_listener,
ARRAY_SIZE(mlxsw_linecard_listener),
mlxsw_core);
Expand All @@ -1535,8 +1585,12 @@ 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_irq_event_handler_unregister(mlxsw_core,
mlxsw_linecards_irq_event_handler);
mlxsw_core_traps_unregister(mlxsw_core, mlxsw_linecard_listener,
ARRAY_SIZE(mlxsw_linecard_listener),
mlxsw_core);
Expand Down
Loading

0 comments on commit 3de1484

Please sign in to comment.