From 4be4779b6ccd19728040b8bc8db5887de08f29cc Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Sun, 21 Aug 2022 18:20:11 +0200 Subject: 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: Vadim Pasternak Reviewed-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: Petr Machata Signed-off-by: Jakub Kicinski --- .../net/ethernet/mellanox/mlxsw/core_linecards.c | 71 +++++++++++++++------- 1 file changed, 50 insertions(+), 21 deletions(-) (limited to 'drivers/net/ethernet/mellanox/mlxsw') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c index ca59f0b946da..8549ccbcfe8e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c @@ -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; @@ -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); @@ -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 @@ -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); @@ -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, -- cgit From 2ab4e70966a2ed5c67b7b04aba1aeb200b0ad82c Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Sun, 21 Aug 2022 18:20:12 +0200 Subject: mlxsw: core: Add registration APIs for system event handler The purpose of system event handler is to handle system interrupts. Such interrupts are raised to CPU from system programmable logic devices, upon specific system wide changes, like line card activation and deactivation. The purpose is to create an alternative to trap mechanism, which delivers these events to driver over PCI bus, but not available for the driver working over I2C bus. Mechanism is system dependent and applicable only for the systems equipped with programmable devices with custom logic. Add APIs for event handler registration and un-registration and API which should be invoked from the registered callbacks when system interrupt is raised to CPU. Signed-off-by: Vadim Pasternak Reviewed-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: Petr Machata Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/core.c | 68 ++++++++++++++++++++++++++++++ drivers/net/ethernet/mellanox/mlxsw/core.h | 8 ++++ 2 files changed, 76 insertions(+) (limited to 'drivers/net/ethernet/mellanox/mlxsw') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index 75553eb2c7f2..450dcd9951bb 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -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; @@ -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, @@ -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); @@ -2233,6 +2248,7 @@ err_ports_init: 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); @@ -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); @@ -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, diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index 02d9cc2ef0c8..c7c0b3cefd8d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -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, -- cgit From 508c29bf15ea5e106b0b3e84076cd5bd90a11b48 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Sun, 21 Aug 2022 18:20:13 +0200 Subject: mlxsw: core_linecards: Register a system event handler Add line card system event handler. Register it with core. It is triggered by system interrupts raised from chassis programmable logic devices to CPU. The purpose is to handle line card state changes over I2C bus. Signed-off-by: Vadim Pasternak Reviewed-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: Petr Machata Signed-off-by: Jakub Kicinski --- .../net/ethernet/mellanox/mlxsw/core_linecards.c | 25 ++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'drivers/net/ethernet/mellanox/mlxsw') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c index 8549ccbcfe8e..83d2dc91ba2c 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_linecards.c @@ -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", @@ -1521,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++) { @@ -1545,6 +1565,9 @@ err_linecard_event_delivery_init: 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); @@ -1566,6 +1589,8 @@ void mlxsw_linecards_fini(struct mlxsw_core *mlxsw_core) 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); -- cgit From 33fa6909a263d70e01ac0cd1bd11ddc15d05f97b Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Sun, 21 Aug 2022 18:20:14 +0200 Subject: mlxsw: i2c: Add support for system interrupt handling Extend i2c bus driver with interrupt handler to support system specific hotplug events, related to line card state change. Provide system IRQ line for interrupt handler. IRQ line Id could be provided through the platform data if available, or could be set to the default value. Signed-off-by: Vadim Pasternak Reviewed-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: Petr Machata Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/i2c.c | 87 ++++++++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 1 deletion(-) (limited to 'drivers/net/ethernet/mellanox/mlxsw') diff --git a/drivers/net/ethernet/mellanox/mlxsw/i2c.c b/drivers/net/ethernet/mellanox/mlxsw/i2c.c index ce843ea91464..716c73e4fd59 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/i2c.c +++ b/drivers/net/ethernet/mellanox/mlxsw/i2c.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include "cmd.h" @@ -51,6 +52,15 @@ #define MLXSW_I2C_TIMEOUT_MSECS 5000 #define MLXSW_I2C_MAX_DATA_SIZE 256 +/* Driver can be initialized by kernel platform driver or from the user + * space. In the first case IRQ line number is passed through the platform + * data, otherwise default IRQ line is to be used. Default IRQ is relevant + * only for specific I2C slave address, allowing 3.4 MHz I2C path to the chip + * (special hardware feature for I2C acceleration). + */ +#define MLXSW_I2C_DEFAULT_IRQ 17 +#define MLXSW_FAST_I2C_SLAVE 0x37 + /** * struct mlxsw_i2c - device private data: * @cmd: command attributes; @@ -63,6 +73,9 @@ * @core: switch core pointer; * @bus_info: bus info block; * @block_size: maximum block size allowed to pass to under layer; + * @pdata: device platform data; + * @irq_work: interrupts work item; + * @irq: IRQ line number; */ struct mlxsw_i2c { struct { @@ -76,6 +89,9 @@ struct mlxsw_i2c { struct mlxsw_core *core; struct mlxsw_bus_info bus_info; u16 block_size; + struct mlxreg_core_hotplug_platform_data *pdata; + struct work_struct irq_work; + int irq; }; #define MLXSW_I2C_READ_MSG(_client, _addr_buf, _buf, _len) { \ @@ -546,6 +562,67 @@ static void mlxsw_i2c_fini(void *bus_priv) mlxsw_i2c->core = NULL; } +static void mlxsw_i2c_work_handler(struct work_struct *work) +{ + struct mlxsw_i2c *mlxsw_i2c; + + mlxsw_i2c = container_of(work, struct mlxsw_i2c, irq_work); + mlxsw_core_irq_event_handlers_call(mlxsw_i2c->core); +} + +static irqreturn_t mlxsw_i2c_irq_handler(int irq, void *dev) +{ + struct mlxsw_i2c *mlxsw_i2c = dev; + + mlxsw_core_schedule_work(&mlxsw_i2c->irq_work); + + /* Interrupt handler shares IRQ line with 'main' interrupt handler. + * Return here IRQ_NONE, while main handler will return IRQ_HANDLED. + */ + return IRQ_NONE; +} + +static int mlxsw_i2c_irq_init(struct mlxsw_i2c *mlxsw_i2c, u8 addr) +{ + int err; + + /* Initialize interrupt handler if system hotplug driver is reachable, + * otherwise interrupt line is not enabled and interrupts will not be + * raised to CPU. Also request_irq() call will be not valid. + */ + if (!IS_REACHABLE(CONFIG_MLXREG_HOTPLUG)) + return 0; + + /* Set default interrupt line. */ + if (mlxsw_i2c->pdata && mlxsw_i2c->pdata->irq) + mlxsw_i2c->irq = mlxsw_i2c->pdata->irq; + else if (addr == MLXSW_FAST_I2C_SLAVE) + mlxsw_i2c->irq = MLXSW_I2C_DEFAULT_IRQ; + + if (!mlxsw_i2c->irq) + return 0; + + INIT_WORK(&mlxsw_i2c->irq_work, mlxsw_i2c_work_handler); + err = request_irq(mlxsw_i2c->irq, mlxsw_i2c_irq_handler, + IRQF_TRIGGER_FALLING | IRQF_SHARED, "mlxsw-i2c", + mlxsw_i2c); + if (err) { + dev_err(mlxsw_i2c->bus_info.dev, "Failed to request irq: %d\n", + err); + return err; + } + + return 0; +} + +static void mlxsw_i2c_irq_fini(struct mlxsw_i2c *mlxsw_i2c) +{ + if (!IS_REACHABLE(CONFIG_MLXREG_HOTPLUG) || !mlxsw_i2c->irq) + return; + cancel_work_sync(&mlxsw_i2c->irq_work); + free_irq(mlxsw_i2c->irq, mlxsw_i2c); +} + static const struct mlxsw_bus mlxsw_i2c_bus = { .kind = "i2c", .init = mlxsw_i2c_init, @@ -638,17 +715,24 @@ static int mlxsw_i2c_probe(struct i2c_client *client, mlxsw_i2c->bus_info.dev = &client->dev; mlxsw_i2c->bus_info.low_frequency = true; mlxsw_i2c->dev = &client->dev; + mlxsw_i2c->pdata = client->dev.platform_data; + + err = mlxsw_i2c_irq_init(mlxsw_i2c, client->addr); + if (err) + goto errout; err = mlxsw_core_bus_device_register(&mlxsw_i2c->bus_info, &mlxsw_i2c_bus, mlxsw_i2c, false, NULL, NULL); if (err) { dev_err(&client->dev, "Fail to register core bus\n"); - return err; + goto err_bus_device_register; } return 0; +err_bus_device_register: + mlxsw_i2c_irq_fini(mlxsw_i2c); errout: mutex_destroy(&mlxsw_i2c->cmd.lock); i2c_set_clientdata(client, NULL); @@ -661,6 +745,7 @@ static int mlxsw_i2c_remove(struct i2c_client *client) struct mlxsw_i2c *mlxsw_i2c = i2c_get_clientdata(client); mlxsw_core_bus_device_unregister(mlxsw_i2c->core, false); + mlxsw_i2c_irq_fini(mlxsw_i2c); mutex_destroy(&mlxsw_i2c->cmd.lock); return 0; -- cgit From c7ea08badd5f462c285d55e5d09774665441a2ab Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Sun, 21 Aug 2022 18:20:15 +0200 Subject: mlxsw: minimal: Extend APIs with slot index for modular system support Add 'slot_index' field to port structure. Replace zero slot_index argument with 'slot_index' in 'ethtool' related APIs. Add 'slot_index' argument to port initialization and de-initialization related APIs. Motivation is to prepare minimal driver for modular system support. Signed-off-by: Vadim Pasternak Reviewed-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: Petr Machata Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/minimal.c | 38 +++++++++++++++++---------- 1 file changed, 24 insertions(+), 14 deletions(-) (limited to 'drivers/net/ethernet/mellanox/mlxsw') diff --git a/drivers/net/ethernet/mellanox/mlxsw/minimal.c b/drivers/net/ethernet/mellanox/mlxsw/minimal.c index bb1cd4bae82e..ecb9f7b6f564 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/minimal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/minimal.c @@ -39,6 +39,7 @@ struct mlxsw_m_port { struct net_device *dev; struct mlxsw_m *mlxsw_m; u16 local_port; + u8 slot_index; u8 module; }; @@ -111,8 +112,9 @@ static int mlxsw_m_get_module_info(struct net_device *netdev, struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev); struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core; - return mlxsw_env_get_module_info(netdev, core, 0, mlxsw_m_port->module, - modinfo); + return mlxsw_env_get_module_info(netdev, core, + mlxsw_m_port->slot_index, + mlxsw_m_port->module, modinfo); } static int @@ -122,7 +124,8 @@ mlxsw_m_get_module_eeprom(struct net_device *netdev, struct ethtool_eeprom *ee, struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev); struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core; - return mlxsw_env_get_module_eeprom(netdev, core, 0, + return mlxsw_env_get_module_eeprom(netdev, core, + mlxsw_m_port->slot_index, mlxsw_m_port->module, ee, data); } @@ -134,7 +137,8 @@ mlxsw_m_get_module_eeprom_by_page(struct net_device *netdev, struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev); struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core; - return mlxsw_env_get_module_eeprom_by_page(core, 0, + return mlxsw_env_get_module_eeprom_by_page(core, + mlxsw_m_port->slot_index, mlxsw_m_port->module, page, extack); } @@ -144,7 +148,8 @@ static int mlxsw_m_reset(struct net_device *netdev, u32 *flags) struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev); struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core; - return mlxsw_env_reset_module(netdev, core, 0, mlxsw_m_port->module, + return mlxsw_env_reset_module(netdev, core, mlxsw_m_port->slot_index, + mlxsw_m_port->module, flags); } @@ -156,7 +161,8 @@ mlxsw_m_get_module_power_mode(struct net_device *netdev, struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev); struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core; - return mlxsw_env_get_module_power_mode(core, 0, mlxsw_m_port->module, + return mlxsw_env_get_module_power_mode(core, mlxsw_m_port->slot_index, + mlxsw_m_port->module, params, extack); } @@ -168,7 +174,8 @@ mlxsw_m_set_module_power_mode(struct net_device *netdev, struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev); struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core; - return mlxsw_env_set_module_power_mode(core, 0, mlxsw_m_port->module, + return mlxsw_env_set_module_power_mode(core, mlxsw_m_port->slot_index, + mlxsw_m_port->module, params->policy, extack); } @@ -217,13 +224,14 @@ mlxsw_m_port_dev_addr_get(struct mlxsw_m_port *mlxsw_m_port) } static int -mlxsw_m_port_create(struct mlxsw_m *mlxsw_m, u16 local_port, u8 module) +mlxsw_m_port_create(struct mlxsw_m *mlxsw_m, u16 local_port, u8 slot_index, + u8 module) { struct mlxsw_m_port *mlxsw_m_port; struct net_device *dev; int err; - err = mlxsw_core_port_init(mlxsw_m->core, local_port, 0, + err = mlxsw_core_port_init(mlxsw_m->core, local_port, slot_index, module + 1, false, 0, false, 0, mlxsw_m->base_mac, sizeof(mlxsw_m->base_mac)); @@ -246,6 +254,7 @@ mlxsw_m_port_create(struct mlxsw_m *mlxsw_m, u16 local_port, u8 module) mlxsw_m_port->mlxsw_m = mlxsw_m; mlxsw_m_port->local_port = local_port; mlxsw_m_port->module = module; + mlxsw_m_port->slot_index = slot_index; dev->netdev_ops = &mlxsw_m_port_netdev_ops; dev->ethtool_ops = &mlxsw_m_port_ethtool_ops; @@ -319,10 +328,11 @@ static int mlxsw_m_port_module_map(struct mlxsw_m *mlxsw_m, u16 local_port, return 0; } -static void mlxsw_m_port_module_unmap(struct mlxsw_m *mlxsw_m, u8 module) +static void +mlxsw_m_port_module_unmap(struct mlxsw_m *mlxsw_m, u8 slot_index, u8 module) { mlxsw_m->module_to_port[module] = -1; - mlxsw_env_module_port_unmap(mlxsw_m->core, 0, module); + mlxsw_env_module_port_unmap(mlxsw_m->core, slot_index, module); } static int mlxsw_m_ports_create(struct mlxsw_m *mlxsw_m) @@ -360,7 +370,7 @@ static int mlxsw_m_ports_create(struct mlxsw_m *mlxsw_m) if (mlxsw_m->module_to_port[i] > 0) { err = mlxsw_m_port_create(mlxsw_m, mlxsw_m->module_to_port[i], - i); + 0, i); if (err) goto err_module_to_port_create; } @@ -377,7 +387,7 @@ err_module_to_port_create: i = max_ports; err_module_to_port_map: for (i--; i > 0; i--) - mlxsw_m_port_module_unmap(mlxsw_m, i); + mlxsw_m_port_module_unmap(mlxsw_m, 0, i); kfree(mlxsw_m->module_to_port); err_module_to_port_alloc: kfree(mlxsw_m->ports); @@ -392,7 +402,7 @@ static void mlxsw_m_ports_remove(struct mlxsw_m *mlxsw_m) if (mlxsw_m->module_to_port[i] > 0) { mlxsw_m_port_remove(mlxsw_m, mlxsw_m->module_to_port[i]); - mlxsw_m_port_module_unmap(mlxsw_m, i); + mlxsw_m_port_module_unmap(mlxsw_m, 0, i); } } -- cgit From 9421c8b89dbbd3b164ac09f84f1bc8e83232ebb4 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Sun, 21 Aug 2022 18:20:16 +0200 Subject: mlxsw: minimal: Move ports allocation to separate routine Perform ports allocation in a separate routine. Motivation is to re-use this routine for ports found on line cards. Signed-off-by: Vadim Pasternak Reviewed-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: Petr Machata Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/minimal.c | 42 ++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 8 deletions(-) (limited to 'drivers/net/ethernet/mellanox/mlxsw') diff --git a/drivers/net/ethernet/mellanox/mlxsw/minimal.c b/drivers/net/ethernet/mellanox/mlxsw/minimal.c index ecb9f7b6f564..f8dee111d25b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/minimal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/minimal.c @@ -335,12 +335,10 @@ mlxsw_m_port_module_unmap(struct mlxsw_m *mlxsw_m, u8 slot_index, u8 module) mlxsw_env_module_port_unmap(mlxsw_m->core, slot_index, module); } -static int mlxsw_m_ports_create(struct mlxsw_m *mlxsw_m) +static int mlxsw_m_linecards_init(struct mlxsw_m *mlxsw_m) { unsigned int max_ports = mlxsw_core_max_ports(mlxsw_m->core); - u8 last_module = max_ports; - int i; - int err; + int i, err; mlxsw_m->ports = kcalloc(max_ports, sizeof(*mlxsw_m->ports), GFP_KERNEL); @@ -358,6 +356,26 @@ static int mlxsw_m_ports_create(struct mlxsw_m *mlxsw_m) for (i = 0; i < max_ports; i++) mlxsw_m->module_to_port[i] = -1; + return 0; + +err_module_to_port_alloc: + kfree(mlxsw_m->ports); + return err; +} + +static void mlxsw_m_linecards_fini(struct mlxsw_m *mlxsw_m) +{ + kfree(mlxsw_m->module_to_port); + kfree(mlxsw_m->ports); +} + +static int mlxsw_m_ports_create(struct mlxsw_m *mlxsw_m) +{ + unsigned int max_ports = mlxsw_core_max_ports(mlxsw_m->core); + u8 last_module = max_ports; + int i; + int err; + /* Fill out module to local port mapping array */ for (i = 1; i < max_ports; i++) { err = mlxsw_m_port_module_map(mlxsw_m, i, &last_module); @@ -388,9 +406,6 @@ err_module_to_port_create: err_module_to_port_map: for (i--; i > 0; i--) mlxsw_m_port_module_unmap(mlxsw_m, 0, i); - kfree(mlxsw_m->module_to_port); -err_module_to_port_alloc: - kfree(mlxsw_m->ports); return err; } @@ -448,13 +463,23 @@ static int mlxsw_m_init(struct mlxsw_core *mlxsw_core, return err; } + err = mlxsw_m_linecards_init(mlxsw_m); + if (err) { + dev_err(mlxsw_m->bus_info->dev, "Failed to create line cards\n"); + return err; + } + err = mlxsw_m_ports_create(mlxsw_m); if (err) { dev_err(mlxsw_m->bus_info->dev, "Failed to create ports\n"); - return err; + goto err_ports_create; } return 0; + +err_ports_create: + mlxsw_m_linecards_fini(mlxsw_m); + return err; } static void mlxsw_m_fini(struct mlxsw_core *mlxsw_core) @@ -462,6 +487,7 @@ static void mlxsw_m_fini(struct mlxsw_core *mlxsw_core) struct mlxsw_m *mlxsw_m = mlxsw_core_driver_priv(mlxsw_core); mlxsw_m_ports_remove(mlxsw_m); + mlxsw_m_linecards_fini(mlxsw_m); } static const struct mlxsw_config_profile mlxsw_m_config_profile; -- cgit From 01328e23a476a47179b07125eabac439bc1d5fd3 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Sun, 21 Aug 2022 18:20:17 +0200 Subject: mlxsw: minimal: Extend module to port mapping with slot index The interfaces for ports found on line card are created and removed dynamically after line card is getting active or inactive. Introduce per line card array with module to port mapping. For each port get 'slot_index' through PMLP register and set port mapping for the relevant [slot_index][module] entry. Split module and port allocation into separate routines. Split per line card port creation and removing into separate routines. Motivation to re-use these routines for line card operations. Signed-off-by: Vadim Pasternak Reviewed-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: Petr Machata Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/minimal.c | 215 +++++++++++++++++++------- 1 file changed, 163 insertions(+), 52 deletions(-) (limited to 'drivers/net/ethernet/mellanox/mlxsw') diff --git a/drivers/net/ethernet/mellanox/mlxsw/minimal.c b/drivers/net/ethernet/mellanox/mlxsw/minimal.c index f8dee111d25b..7fc5ebb8e0ba 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/minimal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/minimal.c @@ -26,13 +26,20 @@ static const struct mlxsw_fw_rev mlxsw_m_fw_rev = { struct mlxsw_m_port; +struct mlxsw_m_line_card { + bool active; + int module_to_port[]; +}; + struct mlxsw_m { struct mlxsw_m_port **ports; - int *module_to_port; struct mlxsw_core *core; const struct mlxsw_bus_info *bus_info; u8 base_mac[ETH_ALEN]; u8 max_ports; + u8 max_modules_per_slot; /* Maximum number of modules per-slot. */ + u8 num_of_slots; /* Including the main board. */ + struct mlxsw_m_line_card **line_cards; }; struct mlxsw_m_port { @@ -191,7 +198,7 @@ static const struct ethtool_ops mlxsw_m_port_ethtool_ops = { static int mlxsw_m_port_module_info_get(struct mlxsw_m *mlxsw_m, u16 local_port, - u8 *p_module, u8 *p_width) + u8 *p_module, u8 *p_width, u8 *p_slot_index) { char pmlp_pl[MLXSW_REG_PMLP_LEN]; int err; @@ -202,6 +209,7 @@ mlxsw_m_port_module_info_get(struct mlxsw_m *mlxsw_m, u16 local_port, return err; *p_module = mlxsw_reg_pmlp_module_get(pmlp_pl, 0); *p_width = mlxsw_reg_pmlp_width_get(pmlp_pl); + *p_slot_index = mlxsw_reg_pmlp_slot_index_get(pmlp_pl, 0); return 0; } @@ -223,6 +231,11 @@ mlxsw_m_port_dev_addr_get(struct mlxsw_m_port *mlxsw_m_port) return 0; } +static bool mlxsw_m_port_created(struct mlxsw_m *mlxsw_m, u16 local_port) +{ + return mlxsw_m->ports[local_port]; +} + static int mlxsw_m_port_create(struct mlxsw_m *mlxsw_m, u16 local_port, u8 slot_index, u8 module) @@ -300,16 +313,23 @@ static void mlxsw_m_port_remove(struct mlxsw_m *mlxsw_m, u16 local_port) mlxsw_core_port_fini(mlxsw_m->core, local_port); } +static int* +mlxsw_m_port_mapping_get(struct mlxsw_m *mlxsw_m, u8 slot_index, u8 module) +{ + return &mlxsw_m->line_cards[slot_index]->module_to_port[module]; +} + static int mlxsw_m_port_module_map(struct mlxsw_m *mlxsw_m, u16 local_port, u8 *last_module) { unsigned int max_ports = mlxsw_core_max_ports(mlxsw_m->core); - u8 module, width; + u8 module, width, slot_index; + int *module_to_port; int err; /* Fill out to local port mapping array */ err = mlxsw_m_port_module_info_get(mlxsw_m, local_port, &module, - &width); + &width, &slot_index); if (err) return err; @@ -322,8 +342,9 @@ static int mlxsw_m_port_module_map(struct mlxsw_m *mlxsw_m, u16 local_port, if (WARN_ON_ONCE(module >= max_ports)) return -EINVAL; - mlxsw_env_module_port_map(mlxsw_m->core, 0, module); - mlxsw_m->module_to_port[module] = ++mlxsw_m->max_ports; + mlxsw_env_module_port_map(mlxsw_m->core, slot_index, module); + module_to_port = mlxsw_m_port_mapping_get(mlxsw_m, slot_index, module); + *module_to_port = local_port; return 0; } @@ -331,98 +352,188 @@ static int mlxsw_m_port_module_map(struct mlxsw_m *mlxsw_m, u16 local_port, static void mlxsw_m_port_module_unmap(struct mlxsw_m *mlxsw_m, u8 slot_index, u8 module) { - mlxsw_m->module_to_port[module] = -1; + int *module_to_port = mlxsw_m_port_mapping_get(mlxsw_m, slot_index, + module); + *module_to_port = -1; mlxsw_env_module_port_unmap(mlxsw_m->core, slot_index, module); } static int mlxsw_m_linecards_init(struct mlxsw_m *mlxsw_m) { unsigned int max_ports = mlxsw_core_max_ports(mlxsw_m->core); - int i, err; + char mgpir_pl[MLXSW_REG_MGPIR_LEN]; + u8 num_of_modules; + int i, j, err; + + mlxsw_reg_mgpir_pack(mgpir_pl, 0); + err = mlxsw_reg_query(mlxsw_m->core, MLXSW_REG(mgpir), mgpir_pl); + if (err) + return err; + + mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL, &num_of_modules, + &mlxsw_m->num_of_slots); + /* If the system is modular, get the maximum number of modules per-slot. + * Otherwise, get the maximum number of modules on the main board. + */ + if (mlxsw_m->num_of_slots) + mlxsw_m->max_modules_per_slot = + mlxsw_reg_mgpir_max_modules_per_slot_get(mgpir_pl); + else + mlxsw_m->max_modules_per_slot = num_of_modules; + /* Add slot for main board. */ + mlxsw_m->num_of_slots += 1; mlxsw_m->ports = kcalloc(max_ports, sizeof(*mlxsw_m->ports), GFP_KERNEL); if (!mlxsw_m->ports) return -ENOMEM; - mlxsw_m->module_to_port = kmalloc_array(max_ports, sizeof(int), - GFP_KERNEL); - if (!mlxsw_m->module_to_port) { - err = -ENOMEM; - goto err_module_to_port_alloc; + mlxsw_m->line_cards = kcalloc(mlxsw_m->num_of_slots, + sizeof(*mlxsw_m->line_cards), + GFP_KERNEL); + if (!mlxsw_m->line_cards) + goto err_kcalloc; + + for (i = 0; i < mlxsw_m->num_of_slots; i++) { + mlxsw_m->line_cards[i] = + kzalloc(struct_size(mlxsw_m->line_cards[i], + module_to_port, + mlxsw_m->max_modules_per_slot), + GFP_KERNEL); + if (!mlxsw_m->line_cards[i]) + goto err_kmalloc_array; + + /* Invalidate the entries of module to local port mapping array. */ + for (j = 0; j < mlxsw_m->max_modules_per_slot; j++) + mlxsw_m->line_cards[i]->module_to_port[j] = -1; } - /* Invalidate the entries of module to local port mapping array */ - for (i = 0; i < max_ports; i++) - mlxsw_m->module_to_port[i] = -1; - return 0; -err_module_to_port_alloc: +err_kmalloc_array: + for (i--; i >= 0; i--) + kfree(mlxsw_m->line_cards[i]); +err_kcalloc: kfree(mlxsw_m->ports); return err; } static void mlxsw_m_linecards_fini(struct mlxsw_m *mlxsw_m) { - kfree(mlxsw_m->module_to_port); + int i = mlxsw_m->num_of_slots; + + for (i--; i >= 0; i--) + kfree(mlxsw_m->line_cards[i]); + kfree(mlxsw_m->line_cards); kfree(mlxsw_m->ports); } -static int mlxsw_m_ports_create(struct mlxsw_m *mlxsw_m) +static void +mlxsw_m_linecard_port_module_unmap(struct mlxsw_m *mlxsw_m, u8 slot_index) { - unsigned int max_ports = mlxsw_core_max_ports(mlxsw_m->core); - u8 last_module = max_ports; int i; - int err; - /* Fill out module to local port mapping array */ - for (i = 1; i < max_ports; i++) { - err = mlxsw_m_port_module_map(mlxsw_m, i, &last_module); - if (err) - goto err_module_to_port_map; + for (i = mlxsw_m->max_modules_per_slot - 1; i >= 0; i--) { + int *module_to_port; + + module_to_port = mlxsw_m_port_mapping_get(mlxsw_m, slot_index, i); + if (*module_to_port > 0) + mlxsw_m_port_module_unmap(mlxsw_m, slot_index, i); } +} - /* Create port objects for each valid entry */ - for (i = 0; i < mlxsw_m->max_ports; i++) { - if (mlxsw_m->module_to_port[i] > 0) { - err = mlxsw_m_port_create(mlxsw_m, - mlxsw_m->module_to_port[i], - 0, i); +static int +mlxsw_m_linecard_ports_create(struct mlxsw_m *mlxsw_m, u8 slot_index) +{ + int *module_to_port; + int i, err; + + for (i = 0; i < mlxsw_m->max_modules_per_slot; i++) { + module_to_port = mlxsw_m_port_mapping_get(mlxsw_m, slot_index, i); + if (*module_to_port > 0) { + err = mlxsw_m_port_create(mlxsw_m, *module_to_port, + slot_index, i); if (err) - goto err_module_to_port_create; + goto err_port_create; + /* Mark slot as active */ + if (!mlxsw_m->line_cards[slot_index]->active) + mlxsw_m->line_cards[slot_index]->active = true; } } - return 0; -err_module_to_port_create: +err_port_create: for (i--; i >= 0; i--) { - if (mlxsw_m->module_to_port[i] > 0) - mlxsw_m_port_remove(mlxsw_m, - mlxsw_m->module_to_port[i]); + module_to_port = mlxsw_m_port_mapping_get(mlxsw_m, slot_index, i); + if (*module_to_port > 0 && + mlxsw_m_port_created(mlxsw_m, *module_to_port)) { + mlxsw_m_port_remove(mlxsw_m, *module_to_port); + /* Mark slot as inactive */ + if (mlxsw_m->line_cards[slot_index]->active) + mlxsw_m->line_cards[slot_index]->active = false; + } } - i = max_ports; -err_module_to_port_map: - for (i--; i > 0; i--) - mlxsw_m_port_module_unmap(mlxsw_m, 0, i); return err; } -static void mlxsw_m_ports_remove(struct mlxsw_m *mlxsw_m) +static void +mlxsw_m_linecard_ports_remove(struct mlxsw_m *mlxsw_m, u8 slot_index) { int i; - for (i = 0; i < mlxsw_m->max_ports; i++) { - if (mlxsw_m->module_to_port[i] > 0) { - mlxsw_m_port_remove(mlxsw_m, - mlxsw_m->module_to_port[i]); - mlxsw_m_port_module_unmap(mlxsw_m, 0, i); + for (i = 0; i < mlxsw_m->max_modules_per_slot; i++) { + int *module_to_port = mlxsw_m_port_mapping_get(mlxsw_m, + slot_index, i); + + if (*module_to_port > 0 && + mlxsw_m_port_created(mlxsw_m, *module_to_port)) { + mlxsw_m_port_remove(mlxsw_m, *module_to_port); + mlxsw_m_port_module_unmap(mlxsw_m, slot_index, i); } } +} - kfree(mlxsw_m->module_to_port); - kfree(mlxsw_m->ports); +static int mlxsw_m_ports_module_map(struct mlxsw_m *mlxsw_m) +{ + unsigned int max_ports = mlxsw_core_max_ports(mlxsw_m->core); + u8 last_module = max_ports; + int i, err; + + for (i = 1; i < max_ports; i++) { + err = mlxsw_m_port_module_map(mlxsw_m, i, &last_module); + if (err) + return err; + } + + return 0; +} + +static int mlxsw_m_ports_create(struct mlxsw_m *mlxsw_m) +{ + int err; + + /* Fill out module to local port mapping array */ + err = mlxsw_m_ports_module_map(mlxsw_m); + if (err) + goto err_ports_module_map; + + /* Create port objects for each valid entry */ + err = mlxsw_m_linecard_ports_create(mlxsw_m, 0); + if (err) + goto err_linecard_ports_create; + + return 0; + +err_linecard_ports_create: +err_ports_module_map: + mlxsw_m_linecard_port_module_unmap(mlxsw_m, 0); + + return err; +} + +static void mlxsw_m_ports_remove(struct mlxsw_m *mlxsw_m) +{ + mlxsw_m_linecard_ports_remove(mlxsw_m, 0); } static int mlxsw_m_fw_rev_validate(struct mlxsw_m *mlxsw_m) -- cgit From 706ddb7821be8c95f07de7e540d824e5c2267001 Mon Sep 17 00:00:00 2001 From: Vadim Pasternak Date: Sun, 21 Aug 2022 18:20:18 +0200 Subject: mlxsw: minimal: Extend to support line card dynamic operations Implement line card operation callbacks got_active() / got_inactive(). The purpose of these callback to create / remove line card ports after line card is getting active / inactive. Implement line ports_remove_selected() callback to support line card un-provisioning flow through 'devlink'. Add line card operation registration and de-registration APIs. Add module offset for line card. Offset for main board iz zero. For line card in slot #n offset is calculated as (#n - 1) multiplied by maximum modules number. Signed-off-by: Vadim Pasternak Reviewed-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: Petr Machata Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/minimal.c | 100 +++++++++++++++++++++++++- 1 file changed, 99 insertions(+), 1 deletion(-) (limited to 'drivers/net/ethernet/mellanox/mlxsw') diff --git a/drivers/net/ethernet/mellanox/mlxsw/minimal.c b/drivers/net/ethernet/mellanox/mlxsw/minimal.c index 7fc5ebb8e0ba..7d3fa2883e8b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/minimal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/minimal.c @@ -48,6 +48,7 @@ struct mlxsw_m_port { u16 local_port; u8 slot_index; u8 module; + u8 module_offset; }; static int mlxsw_m_base_mac_get(struct mlxsw_m *mlxsw_m) @@ -227,7 +228,8 @@ mlxsw_m_port_dev_addr_get(struct mlxsw_m_port *mlxsw_m_port) if (err) return err; mlxsw_reg_ppad_mac_memcpy_from(ppad_pl, addr); - eth_hw_addr_gen(mlxsw_m_port->dev, addr, mlxsw_m_port->module + 1); + eth_hw_addr_gen(mlxsw_m_port->dev, addr, mlxsw_m_port->module + 1 + + mlxsw_m_port->module_offset); return 0; } @@ -268,6 +270,14 @@ mlxsw_m_port_create(struct mlxsw_m *mlxsw_m, u16 local_port, u8 slot_index, mlxsw_m_port->local_port = local_port; mlxsw_m_port->module = module; mlxsw_m_port->slot_index = slot_index; + /* Add module offset for line card. Offset for main board iz zero. + * For line card in slot #n offset is calculated as (#n - 1) + * multiplied by maximum modules number, which could be found on a line + * card. + */ + mlxsw_m_port->module_offset = mlxsw_m_port->slot_index ? + (mlxsw_m_port->slot_index - 1) * + mlxsw_m->max_modules_per_slot : 0; dev->netdev_ops = &mlxsw_m_port_netdev_ops; dev->ethtool_ops = &mlxsw_m_port_ethtool_ops; @@ -333,6 +343,9 @@ static int mlxsw_m_port_module_map(struct mlxsw_m *mlxsw_m, u16 local_port, if (err) return err; + /* Skip if line card has been already configured */ + if (mlxsw_m->line_cards[slot_index]->active) + return 0; if (!width) return 0; /* Skip, if port belongs to the cluster */ @@ -536,6 +549,24 @@ static void mlxsw_m_ports_remove(struct mlxsw_m *mlxsw_m) mlxsw_m_linecard_ports_remove(mlxsw_m, 0); } +static void +mlxsw_m_ports_remove_selected(struct mlxsw_core *mlxsw_core, + bool (*selector)(void *priv, u16 local_port), + void *priv) +{ + struct mlxsw_m *mlxsw_m = mlxsw_core_driver_priv(mlxsw_core); + struct mlxsw_linecard *linecard_priv = priv; + struct mlxsw_m_line_card *linecard; + + linecard = mlxsw_m->line_cards[linecard_priv->slot_index]; + + if (WARN_ON(!linecard->active)) + return; + + mlxsw_m_linecard_ports_remove(mlxsw_m, linecard_priv->slot_index); + linecard->active = false; +} + static int mlxsw_m_fw_rev_validate(struct mlxsw_m *mlxsw_m) { const struct mlxsw_fw_rev *rev = &mlxsw_m->bus_info->fw_rev; @@ -554,6 +585,60 @@ static int mlxsw_m_fw_rev_validate(struct mlxsw_m *mlxsw_m) return -EINVAL; } +static void +mlxsw_m_got_active(struct mlxsw_core *mlxsw_core, u8 slot_index, void *priv) +{ + struct mlxsw_m_line_card *linecard; + struct mlxsw_m *mlxsw_m = priv; + int err; + + linecard = mlxsw_m->line_cards[slot_index]; + /* Skip if line card has been already configured during init */ + if (linecard->active) + return; + + /* Fill out module to local port mapping array */ + err = mlxsw_m_ports_module_map(mlxsw_m); + if (err) + goto err_ports_module_map; + + /* Create port objects for each valid entry */ + err = mlxsw_m_linecard_ports_create(mlxsw_m, slot_index); + if (err) { + dev_err(mlxsw_m->bus_info->dev, "Failed to create port for line card at slot %d\n", + slot_index); + goto err_linecard_ports_create; + } + + linecard->active = true; + + return; + +err_linecard_ports_create: +err_ports_module_map: + mlxsw_m_linecard_port_module_unmap(mlxsw_m, slot_index); +} + +static void +mlxsw_m_got_inactive(struct mlxsw_core *mlxsw_core, u8 slot_index, void *priv) +{ + struct mlxsw_m_line_card *linecard; + struct mlxsw_m *mlxsw_m = priv; + + linecard = mlxsw_m->line_cards[slot_index]; + + if (WARN_ON(!linecard->active)) + return; + + mlxsw_m_linecard_ports_remove(mlxsw_m, slot_index); + linecard->active = false; +} + +static struct mlxsw_linecards_event_ops mlxsw_m_event_ops = { + .got_active = mlxsw_m_got_active, + .got_inactive = mlxsw_m_got_inactive, +}; + static int mlxsw_m_init(struct mlxsw_core *mlxsw_core, const struct mlxsw_bus_info *mlxsw_bus_info, struct netlink_ext_ack *extack) @@ -580,6 +665,13 @@ static int mlxsw_m_init(struct mlxsw_core *mlxsw_core, return err; } + err = mlxsw_linecards_event_ops_register(mlxsw_core, + &mlxsw_m_event_ops, mlxsw_m); + if (err) { + dev_err(mlxsw_m->bus_info->dev, "Failed to register line cards operations\n"); + goto linecards_event_ops_register; + } + err = mlxsw_m_ports_create(mlxsw_m); if (err) { dev_err(mlxsw_m->bus_info->dev, "Failed to create ports\n"); @@ -589,6 +681,9 @@ static int mlxsw_m_init(struct mlxsw_core *mlxsw_core, return 0; err_ports_create: + mlxsw_linecards_event_ops_unregister(mlxsw_core, + &mlxsw_m_event_ops, mlxsw_m); +linecards_event_ops_register: mlxsw_m_linecards_fini(mlxsw_m); return err; } @@ -598,6 +693,8 @@ static void mlxsw_m_fini(struct mlxsw_core *mlxsw_core) struct mlxsw_m *mlxsw_m = mlxsw_core_driver_priv(mlxsw_core); mlxsw_m_ports_remove(mlxsw_m); + mlxsw_linecards_event_ops_unregister(mlxsw_core, + &mlxsw_m_event_ops, mlxsw_m); mlxsw_m_linecards_fini(mlxsw_m); } @@ -608,6 +705,7 @@ static struct mlxsw_driver mlxsw_m_driver = { .priv_size = sizeof(struct mlxsw_m), .init = mlxsw_m_init, .fini = mlxsw_m_fini, + .ports_remove_selected = mlxsw_m_ports_remove_selected, .profile = &mlxsw_m_config_profile, }; -- cgit From 3471ac9b22c18aeae8d1c3ff6d32d10a861931f3 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 24 Aug 2022 17:18:49 +0200 Subject: mlxsw: Remove unused IB stuff There are some IB leftovers that are no longer used in the code. So remove them. Signed-off-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: Petr Machata Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/core.c | 12 ---- drivers/net/ethernet/mellanox/mlxsw/core.h | 2 - drivers/net/ethernet/mellanox/mlxsw/reg.h | 92 ------------------------------ 3 files changed, 106 deletions(-) (limited to 'drivers/net/ethernet/mellanox/mlxsw') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index 450dcd9951bb..d28c0f999f76 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -3183,18 +3183,6 @@ void mlxsw_core_port_eth_set(struct mlxsw_core *mlxsw_core, u16 local_port, } EXPORT_SYMBOL(mlxsw_core_port_eth_set); -void mlxsw_core_port_ib_set(struct mlxsw_core *mlxsw_core, u16 local_port, - void *port_driver_priv) -{ - struct mlxsw_core_port *mlxsw_core_port = - &mlxsw_core->ports[local_port]; - struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port; - - mlxsw_core_port->port_driver_priv = port_driver_priv; - devlink_port_type_ib_set(devlink_port, NULL); -} -EXPORT_SYMBOL(mlxsw_core_port_ib_set); - void mlxsw_core_port_clear(struct mlxsw_core *mlxsw_core, u16 local_port, void *port_driver_priv) { diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index c7c0b3cefd8d..ca42783f143f 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -264,8 +264,6 @@ int mlxsw_core_cpu_port_init(struct mlxsw_core *mlxsw_core, void mlxsw_core_cpu_port_fini(struct mlxsw_core *mlxsw_core); void mlxsw_core_port_eth_set(struct mlxsw_core *mlxsw_core, u16 local_port, void *port_driver_priv, struct net_device *dev); -void mlxsw_core_port_ib_set(struct mlxsw_core *mlxsw_core, u16 local_port, - void *port_driver_priv); void mlxsw_core_port_clear(struct mlxsw_core *mlxsw_core, u16 local_port, void *port_driver_priv); enum devlink_port_type mlxsw_core_port_type_get(struct mlxsw_core *mlxsw_core, diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index f27bdecdf952..d71d7f9a20f1 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -4729,25 +4729,6 @@ MLXSW_ITEM32(reg, ptys, ext_eth_proto_cap, 0x08, 0, 32); */ MLXSW_ITEM32(reg, ptys, eth_proto_cap, 0x0C, 0, 32); -/* reg_ptys_ib_link_width_cap - * IB port supported widths. - * Access: RO - */ -MLXSW_ITEM32(reg, ptys, ib_link_width_cap, 0x10, 16, 16); - -#define MLXSW_REG_PTYS_IB_SPEED_SDR BIT(0) -#define MLXSW_REG_PTYS_IB_SPEED_DDR BIT(1) -#define MLXSW_REG_PTYS_IB_SPEED_QDR BIT(2) -#define MLXSW_REG_PTYS_IB_SPEED_FDR10 BIT(3) -#define MLXSW_REG_PTYS_IB_SPEED_FDR BIT(4) -#define MLXSW_REG_PTYS_IB_SPEED_EDR BIT(5) - -/* reg_ptys_ib_proto_cap - * IB port supported speeds and protocols. - * Access: RO - */ -MLXSW_ITEM32(reg, ptys, ib_proto_cap, 0x10, 0, 16); - /* reg_ptys_ext_eth_proto_admin * Extended speed and protocol to set port to. * Access: RW @@ -4760,18 +4741,6 @@ MLXSW_ITEM32(reg, ptys, ext_eth_proto_admin, 0x14, 0, 32); */ MLXSW_ITEM32(reg, ptys, eth_proto_admin, 0x18, 0, 32); -/* reg_ptys_ib_link_width_admin - * IB width to set port to. - * Access: RW - */ -MLXSW_ITEM32(reg, ptys, ib_link_width_admin, 0x1C, 16, 16); - -/* reg_ptys_ib_proto_admin - * IB speeds and protocols to set port to. - * Access: RW - */ -MLXSW_ITEM32(reg, ptys, ib_proto_admin, 0x1C, 0, 16); - /* reg_ptys_ext_eth_proto_oper * The extended current speed and protocol configured for the port. * Access: RO @@ -4784,18 +4753,6 @@ MLXSW_ITEM32(reg, ptys, ext_eth_proto_oper, 0x20, 0, 32); */ MLXSW_ITEM32(reg, ptys, eth_proto_oper, 0x24, 0, 32); -/* reg_ptys_ib_link_width_oper - * The current IB width to set port to. - * Access: RO - */ -MLXSW_ITEM32(reg, ptys, ib_link_width_oper, 0x28, 16, 16); - -/* reg_ptys_ib_proto_oper - * The current IB speed and protocol. - * Access: RO - */ -MLXSW_ITEM32(reg, ptys, ib_proto_oper, 0x28, 0, 16); - enum mlxsw_reg_ptys_connector_type { MLXSW_REG_PTYS_CONNECTOR_TYPE_UNKNOWN_OR_NO_CONNECTOR, MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_NONE, @@ -4866,33 +4823,6 @@ static inline void mlxsw_reg_ptys_ext_eth_unpack(char *payload, mlxsw_reg_ptys_ext_eth_proto_oper_get(payload); } -static inline void mlxsw_reg_ptys_ib_pack(char *payload, u16 local_port, - u16 proto_admin, u16 link_width) -{ - MLXSW_REG_ZERO(ptys, payload); - mlxsw_reg_ptys_local_port_set(payload, local_port); - mlxsw_reg_ptys_proto_mask_set(payload, MLXSW_REG_PTYS_PROTO_MASK_IB); - mlxsw_reg_ptys_ib_proto_admin_set(payload, proto_admin); - mlxsw_reg_ptys_ib_link_width_admin_set(payload, link_width); -} - -static inline void mlxsw_reg_ptys_ib_unpack(char *payload, u16 *p_ib_proto_cap, - u16 *p_ib_link_width_cap, - u16 *p_ib_proto_oper, - u16 *p_ib_link_width_oper) -{ - if (p_ib_proto_cap) - *p_ib_proto_cap = mlxsw_reg_ptys_ib_proto_cap_get(payload); - if (p_ib_link_width_cap) - *p_ib_link_width_cap = - mlxsw_reg_ptys_ib_link_width_cap_get(payload); - if (p_ib_proto_oper) - *p_ib_proto_oper = mlxsw_reg_ptys_ib_proto_oper_get(payload); - if (p_ib_link_width_oper) - *p_ib_link_width_oper = - mlxsw_reg_ptys_ib_link_width_oper_get(payload); -} - /* PPAD - Port Physical Address Register * ------------------------------------- * The PPAD register configures the per port physical MAC address. @@ -5666,27 +5596,6 @@ static inline void mlxsw_reg_ppcnt_pack(char *payload, u16 local_port, mlxsw_reg_ppcnt_prio_tc_set(payload, prio_tc); } -/* PLIB - Port Local to InfiniBand Port - * ------------------------------------ - * The PLIB register performs mapping from Local Port into InfiniBand Port. - */ -#define MLXSW_REG_PLIB_ID 0x500A -#define MLXSW_REG_PLIB_LEN 0x10 - -MLXSW_REG_DEFINE(plib, MLXSW_REG_PLIB_ID, MLXSW_REG_PLIB_LEN); - -/* reg_plib_local_port - * Local port number. - * Access: Index - */ -MLXSW_ITEM32_LP(reg, plib, 0x00, 16, 0x00, 12); - -/* reg_plib_ib_port - * InfiniBand port remapping for local_port. - * Access: RW - */ -MLXSW_ITEM32(reg, plib, ib_port, 0x00, 0, 8); - /* PPTB - Port Prio To Buffer Register * ----------------------------------- * Configures the switch priority to buffer table. @@ -12962,7 +12871,6 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { MLXSW_REG(paos), MLXSW_REG(pfcc), MLXSW_REG(ppcnt), - MLXSW_REG(plib), MLXSW_REG(pptb), MLXSW_REG(pbmc), MLXSW_REG(pspa), -- cgit From 04a1b674d655119ed6a42fe534f24632c793d4f7 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 24 Aug 2022 17:18:50 +0200 Subject: mlxsw: Remove unused port_type_set devlink op port_type_set devlink op is no longer used by any mlxsw driver, so remove it. Signed-off-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: Petr Machata Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/core.c | 16 ---------------- drivers/net/ethernet/mellanox/mlxsw/core.h | 2 -- 2 files changed, 18 deletions(-) (limited to 'drivers/net/ethernet/mellanox/mlxsw') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index d28c0f999f76..250e1236b308 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -1307,21 +1307,6 @@ mlxsw_devlink_sb_pool_set(struct devlink *devlink, extack); } -static int mlxsw_devlink_port_type_set(struct devlink_port *devlink_port, - enum devlink_port_type port_type) -{ - struct mlxsw_core *mlxsw_core = devlink_priv(devlink_port->devlink); - struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver; - struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port); - - if (!mlxsw_driver->port_type_set) - return -EOPNOTSUPP; - - return mlxsw_driver->port_type_set(mlxsw_core, - mlxsw_core_port->local_port, - port_type); -} - static int mlxsw_devlink_sb_port_pool_get(struct devlink_port *devlink_port, unsigned int sb_index, u16 pool_index, u32 *p_threshold) @@ -1652,7 +1637,6 @@ static const struct devlink_ops mlxsw_devlink_ops = { BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE), .reload_down = mlxsw_devlink_core_bus_device_reload_down, .reload_up = mlxsw_devlink_core_bus_device_reload_up, - .port_type_set = mlxsw_devlink_port_type_set, .port_split = mlxsw_devlink_port_split, .port_unsplit = mlxsw_devlink_port_unsplit, .sb_pool_get = mlxsw_devlink_sb_pool_get, diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index ca42783f143f..8100a7efef90 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -347,8 +347,6 @@ struct mlxsw_driver { const struct mlxsw_bus_info *mlxsw_bus_info, struct netlink_ext_ack *extack); void (*fini)(struct mlxsw_core *mlxsw_core); - int (*port_type_set)(struct mlxsw_core *mlxsw_core, u16 local_port, - enum devlink_port_type new_type); int (*port_split)(struct mlxsw_core *mlxsw_core, u16 local_port, unsigned int count, struct netlink_ext_ack *extack); int (*port_unsplit)(struct mlxsw_core *mlxsw_core, u16 local_port, -- cgit From 12be3edfa827b12fc543e620350a089d73db9a68 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 24 Aug 2022 17:18:51 +0200 Subject: mlxsw: Remove unused mlxsw_core_port_type_get() Function mlxsw_core_port_type_get() is no longer used. So remove it. Signed-off-by: Jiri Pirko Reviewed-by: Ido Schimmel Signed-off-by: Petr Machata Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/core.c | 12 ------------ drivers/net/ethernet/mellanox/mlxsw/core.h | 2 -- 2 files changed, 14 deletions(-) (limited to 'drivers/net/ethernet/mellanox/mlxsw') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index 250e1236b308..afbe046b35a0 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -3179,18 +3179,6 @@ void mlxsw_core_port_clear(struct mlxsw_core *mlxsw_core, u16 local_port, } EXPORT_SYMBOL(mlxsw_core_port_clear); -enum devlink_port_type mlxsw_core_port_type_get(struct mlxsw_core *mlxsw_core, - u16 local_port) -{ - struct mlxsw_core_port *mlxsw_core_port = - &mlxsw_core->ports[local_port]; - struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port; - - return devlink_port->type; -} -EXPORT_SYMBOL(mlxsw_core_port_type_get); - - struct devlink_port * mlxsw_core_port_devlink_port_get(struct mlxsw_core *mlxsw_core, u16 local_port) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index 8100a7efef90..9de9fa24f27c 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -266,8 +266,6 @@ void mlxsw_core_port_eth_set(struct mlxsw_core *mlxsw_core, u16 local_port, void *port_driver_priv, struct net_device *dev); void mlxsw_core_port_clear(struct mlxsw_core *mlxsw_core, u16 local_port, void *port_driver_priv); -enum devlink_port_type mlxsw_core_port_type_get(struct mlxsw_core *mlxsw_core, - u16 local_port); struct devlink_port * mlxsw_core_port_devlink_port_get(struct mlxsw_core *mlxsw_core, u16 local_port); -- cgit From 57688eb887af3db7f1d7f43f2c1babb548b01a34 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 26 Aug 2022 18:03:30 +0300 Subject: mlxsw: minimal: Return -ENOMEM on allocation failure These error paths return success but they should return -ENOMEM. Fixes: 01328e23a476 ("mlxsw: minimal: Extend module to port mapping with slot index") Signed-off-by: Dan Carpenter Reviewed-by: Petr Machata Reviewed-by: Ido Schimmel Link: https://lore.kernel.org/r/YwjgwoJ3M7Kdq9VK@kili Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/minimal.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/net/ethernet/mellanox/mlxsw') diff --git a/drivers/net/ethernet/mellanox/mlxsw/minimal.c b/drivers/net/ethernet/mellanox/mlxsw/minimal.c index 7d3fa2883e8b..c7f7e49251f4 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/minimal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/minimal.c @@ -404,8 +404,10 @@ static int mlxsw_m_linecards_init(struct mlxsw_m *mlxsw_m) mlxsw_m->line_cards = kcalloc(mlxsw_m->num_of_slots, sizeof(*mlxsw_m->line_cards), GFP_KERNEL); - if (!mlxsw_m->line_cards) + if (!mlxsw_m->line_cards) { + err = -ENOMEM; goto err_kcalloc; + } for (i = 0; i < mlxsw_m->num_of_slots; i++) { mlxsw_m->line_cards[i] = @@ -413,8 +415,10 @@ static int mlxsw_m_linecards_init(struct mlxsw_m *mlxsw_m) module_to_port, mlxsw_m->max_modules_per_slot), GFP_KERNEL); - if (!mlxsw_m->line_cards[i]) + if (!mlxsw_m->line_cards[i]) { + err = -ENOMEM; goto err_kmalloc_array; + } /* Invalidate the entries of module to local port mapping array. */ for (j = 0; j < mlxsw_m->max_modules_per_slot; j++) -- cgit From 95484760f03d684da522a15682776a090db738da Mon Sep 17 00:00:00 2001 From: Amit Cohen Date: Fri, 26 Aug 2022 18:06:49 +0200 Subject: mlxsw: cmd: Edit the comment of 'max_lag' field in CONFIG_PROFILE Starting from Spectrum-4, the maximum number of LAG IDs can be configured by software via CONFIG_PROFILE command during driver initialization. Edit the comment of 'max_lag' field to mention that this field is reserved in Spectrum-1/2/3 and describe firmware behavior. Signed-off-by: Amit Cohen Reviewed-by: Ido Schimmel Reviewed-by: Petr Machata Signed-off-by: Petr Machata Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/cmd.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net/ethernet/mellanox/mlxsw') diff --git a/drivers/net/ethernet/mellanox/mlxsw/cmd.h b/drivers/net/ethernet/mellanox/mlxsw/cmd.h index 60232fb8ccd7..09bef04b11d1 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/cmd.h +++ b/drivers/net/ethernet/mellanox/mlxsw/cmd.h @@ -703,6 +703,9 @@ MLXSW_ITEM32(cmd_mbox, config_profile, max_vepa_channels, 0x10, 0, 8); /* cmd_mbox_config_profile_max_lag * Maximum number of LAG IDs requested. + * Reserved when Spectrum-1/2/3, supported from Spectrum-4 and above. + * For Spectrum-4, firmware sets 128 for values between 1-128 and 256 for values + * between 129-256. */ MLXSW_ITEM32(cmd_mbox, config_profile, max_lag, 0x14, 0, 16); -- cgit From eb907e9779ca48e3f3fe3796ed88de017dd59414 Mon Sep 17 00:00:00 2001 From: Amit Cohen Date: Fri, 26 Aug 2022 18:06:50 +0200 Subject: mlxsw: Support configuring 'max_lag' via CONFIG_PROFILE In the device, LAG identifiers are stored in the port group table (PGT). During initialization, firmware reserves a certain amount of entries at the beginning of this table for LAG identifiers. In Spectrum-4, the size of the PGT table did not increase, but the maximum number of LAG identifiers was doubled, leaving less room for others entries (e.g., flood entries) that also reside in the PGT. Therefore, in order to avoid a regression and as long as there is no explicit requirement to support 256 LAGs, mlxsw driver will configure the firmware to allocate the same amount of LAG entries (128) as in Spectrum-{2,3}. This configuration is done using 'max_lag' field in CONFIG_PROFILE command. Extend 'struct mlxsw_config_profile' to support 'max_lag' field and configure firmware accordingly. A next patch will adjust Spectrum-4 to configure 'max_lag' field. Signed-off-by: Amit Cohen Reviewed-by: Petr Machata Reviewed-by: Ido Schimmel Signed-off-by: Petr Machata Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/core.h | 2 ++ drivers/net/ethernet/mellanox/mlxsw/pci.c | 5 +++++ 2 files changed, 7 insertions(+) (limited to 'drivers/net/ethernet/mellanox/mlxsw') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index 9de9fa24f27c..383c423c3ef8 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -295,6 +295,7 @@ struct mlxsw_swid_config { struct mlxsw_config_profile { u16 used_max_vepa_channels:1, + used_max_lag:1, used_max_mid:1, used_max_pgt:1, used_max_system_port:1, @@ -310,6 +311,7 @@ struct mlxsw_config_profile { used_kvd_sizes:1, used_cqe_time_stamp_type:1; u8 max_vepa_channels; + u16 max_lag; u16 max_mid; u16 max_pgt; u16 max_system_port; diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c index 50527adc5b5a..c968309657dd 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.c +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c @@ -1187,6 +1187,11 @@ static int mlxsw_pci_config_profile(struct mlxsw_pci *mlxsw_pci, char *mbox, mlxsw_cmd_mbox_config_profile_max_vepa_channels_set( mbox, profile->max_vepa_channels); } + if (profile->used_max_lag) { + mlxsw_cmd_mbox_config_profile_set_max_lag_set(mbox, 1); + mlxsw_cmd_mbox_config_profile_max_lag_set(mbox, + profile->max_lag); + } if (profile->used_max_mid) { mlxsw_cmd_mbox_config_profile_set_max_mid_set( mbox, 1); -- cgit From cf735d4c9bab8398259a3635fcd698726a2f1bbe Mon Sep 17 00:00:00 2001 From: Amit Cohen Date: Fri, 26 Aug 2022 18:06:51 +0200 Subject: mlxsw: Add a helper function for getting maximum LAG ID Currently the driver queries the maximum supported LAG ID from firmware. This will not be accurate anymore once the driver will configure 'max_lag' via CONFIG_PROFILE command. For resource query, firmware returns the maximum LAG ID which is supported by hardware. Software can configure firmware to do not allocate entries for all the supported LAGs, and to limit LAG IDs. In this case, the resource query will not return the actual maximum LAG ID. Add a helper function for getting this value. In case that 'max_lag' field was set during initialization, return the value which was used, otherwise, query firmware for the maximum supported ID. Signed-off-by: Amit Cohen Reviewed-by: Petr Machata Reviewed-by: Ido Schimmel Signed-off-by: Petr Machata Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/core.c | 25 +++++++++++++++++++++---- drivers/net/ethernet/mellanox/mlxsw/core.h | 2 ++ drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 20 +++++++++++++------- 3 files changed, 36 insertions(+), 11 deletions(-) (limited to 'drivers/net/ethernet/mellanox/mlxsw') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index afbe046b35a0..1d14b1d8c500 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -186,6 +186,23 @@ unsigned int mlxsw_core_max_ports(const struct mlxsw_core *mlxsw_core) } EXPORT_SYMBOL(mlxsw_core_max_ports); +int mlxsw_core_max_lag(struct mlxsw_core *mlxsw_core, u16 *p_max_lag) +{ + struct mlxsw_driver *driver = mlxsw_core->driver; + + if (driver->profile->used_max_lag) { + *p_max_lag = driver->profile->max_lag; + return 0; + } + + if (!MLXSW_CORE_RES_VALID(mlxsw_core, MAX_LAG)) + return -EIO; + + *p_max_lag = MLXSW_CORE_RES_GET(mlxsw_core, MAX_LAG); + return 0; +} +EXPORT_SYMBOL(mlxsw_core_max_lag); + void *mlxsw_core_driver_priv(struct mlxsw_core *mlxsw_core) { return mlxsw_core->driver_priv; @@ -2099,6 +2116,7 @@ __mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info, struct mlxsw_core *mlxsw_core; struct mlxsw_driver *mlxsw_driver; size_t alloc_size; + u16 max_lag; int err; mlxsw_driver = mlxsw_core_driver_get(device_kind); @@ -2140,10 +2158,9 @@ __mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info, if (err) goto err_ports_init; - if (MLXSW_CORE_RES_VALID(mlxsw_core, MAX_LAG) && - MLXSW_CORE_RES_VALID(mlxsw_core, MAX_LAG_MEMBERS)) { - alloc_size = sizeof(*mlxsw_core->lag.mapping) * - MLXSW_CORE_RES_GET(mlxsw_core, MAX_LAG) * + err = mlxsw_core_max_lag(mlxsw_core, &max_lag); + if (!err && MLXSW_CORE_RES_VALID(mlxsw_core, MAX_LAG_MEMBERS)) { + alloc_size = sizeof(*mlxsw_core->lag.mapping) * max_lag * MLXSW_CORE_RES_GET(mlxsw_core, MAX_LAG_MEMBERS); mlxsw_core->lag.mapping = kzalloc(alloc_size, GFP_KERNEL); if (!mlxsw_core->lag.mapping) { diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index 383c423c3ef8..ca0c3d2bee6b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -35,6 +35,8 @@ struct mlxsw_fw_rev; unsigned int mlxsw_core_max_ports(const struct mlxsw_core *mlxsw_core); +int mlxsw_core_max_lag(struct mlxsw_core *mlxsw_core, u16 *p_max_lag); + void *mlxsw_core_driver_priv(struct mlxsw_core *mlxsw_core); struct mlxsw_linecards *mlxsw_core_linecards(struct mlxsw_core *mlxsw_core); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 30c7b0e15721..c71a04050279 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -2691,6 +2691,7 @@ static void mlxsw_sp_traps_fini(struct mlxsw_sp *mlxsw_sp) static int mlxsw_sp_lag_init(struct mlxsw_sp *mlxsw_sp) { char slcr_pl[MLXSW_REG_SLCR_LEN]; + u16 max_lag; u32 seed; int err; @@ -2709,12 +2710,14 @@ static int mlxsw_sp_lag_init(struct mlxsw_sp *mlxsw_sp) if (err) return err; - if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_LAG) || - !MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_LAG_MEMBERS)) + err = mlxsw_core_max_lag(mlxsw_sp->core, &max_lag); + if (err) + return err; + + if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_LAG_MEMBERS)) return -EIO; - mlxsw_sp->lags = kcalloc(MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_LAG), - sizeof(struct mlxsw_sp_upper), + mlxsw_sp->lags = kcalloc(max_lag, sizeof(struct mlxsw_sp_upper), GFP_KERNEL); if (!mlxsw_sp->lags) return -ENOMEM; @@ -4263,10 +4266,13 @@ static int mlxsw_sp_lag_index_get(struct mlxsw_sp *mlxsw_sp, { struct mlxsw_sp_upper *lag; int free_lag_id = -1; - u64 max_lag; - int i; + u16 max_lag; + int err, i; + + err = mlxsw_core_max_lag(mlxsw_sp->core, &max_lag); + if (err) + return err; - max_lag = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_LAG); for (i = 0; i < max_lag; i++) { lag = mlxsw_sp_lag_get(mlxsw_sp, i); if (lag->ref_count) { -- cgit From c503d8ae48f2443345ba82ef66a9dfc22389a66f Mon Sep 17 00:00:00 2001 From: Amit Cohen Date: Fri, 26 Aug 2022 18:06:52 +0200 Subject: mlxsw: spectrum: Add a copy of 'struct mlxsw_config_profile' for Spectrum-4 Starting from Spectrum-4, the maximum number of LAG IDs can be configured by software via CONFIG_PROFILE command during driver initialization. Add a dedicated instance of 'struct mlxsw_config_profile' for Spectrum-4 and set the 'max_lag' field to 128, which is the same amount of LAG entries as in Spectrum-{2,3}. Without this configuration, firmware reserves 256 (the value of 'cap_max_lag' resource) entries at beginning of PGT table for LAG identifiers, which means that less entries in PGT will be available. Signed-off-by: Amit Cohen Reviewed-by: Ido Schimmel Reviewed-by: Petr Machata Signed-off-by: Petr Machata Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 29 +++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) (limited to 'drivers/net/ethernet/mellanox/mlxsw') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index c71a04050279..5bcf5bceff71 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -3512,6 +3512,33 @@ static const struct mlxsw_config_profile mlxsw_sp2_config_profile = { .cqe_time_stamp_type = MLXSW_CMD_MBOX_CONFIG_PROFILE_CQE_TIME_STAMP_TYPE_UTC, }; +/* Reduce number of LAGs from full capacity (256) to the maximum supported LAGs + * in Spectrum-2/3, to avoid regression in number of free entries in the PGT + * table. + */ +#define MLXSW_SP4_CONFIG_PROFILE_MAX_LAG 128 + +static const struct mlxsw_config_profile mlxsw_sp4_config_profile = { + .used_max_lag = 1, + .max_lag = MLXSW_SP4_CONFIG_PROFILE_MAX_LAG, + .used_flood_mode = 1, + .flood_mode = MLXSW_CMD_MBOX_CONFIG_PROFILE_FLOOD_MODE_CONTROLLED, + .used_max_ib_mc = 1, + .max_ib_mc = 0, + .used_max_pkey = 1, + .max_pkey = 0, + .used_ubridge = 1, + .ubridge = 1, + .swid_config = { + { + .used_type = 1, + .type = MLXSW_PORT_SWID_TYPE_ETH, + } + }, + .used_cqe_time_stamp_type = 1, + .cqe_time_stamp_type = MLXSW_CMD_MBOX_CONFIG_PROFILE_CQE_TIME_STAMP_TYPE_UTC, +}; + static void mlxsw_sp_resource_size_params_prepare(struct mlxsw_core *mlxsw_core, struct devlink_resource_size_params *kvd_size_params, @@ -4042,7 +4069,7 @@ static struct mlxsw_driver mlxsw_sp4_driver = { .params_unregister = mlxsw_sp2_params_unregister, .ptp_transmitted = mlxsw_sp_ptp_transmitted, .txhdr_len = MLXSW_TXHDR_LEN, - .profile = &mlxsw_sp2_config_profile, + .profile = &mlxsw_sp4_config_profile, .sdq_supports_cqe_v2 = true, }; -- cgit From f029c781dd6d8e2f13593c927c66db7e8826ed28 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 30 Aug 2022 22:14:54 +0200 Subject: net: ethernet: move from strlcpy with unused retval to strscpy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow the advice of the below link and prefer 'strscpy' in this subsystem. Conversion is 1:1 because the return value is not used. Generated by a coccinelle script. Link: https://lore.kernel.org/r/CAHk-=wgfRnXz0W3D37d01q3JFkr_i_uTL=V6A6G1oUZcprmknw@mail.gmail.com/ Signed-off-by: Wolfram Sang Reviewed-by: Petr Machata # For drivers/net/ethernet/mellanox/mlxsw Acked-by: Geoff Levand # For ps3_gelic_net and spider_net_ethtool Acked-by: Tom Lendacky # For drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c Acked-by: Marcin Wojtas # For drivers/net/ethernet/marvell/mvpp2 Reviewed-by: Leon Romanovsky # For drivers/net/ethernet/mellanox/mlx{4|5} Reviewed-by: Shay Agroskin # For drivers/net/ethernet/amazon/ena Acked-by: Krzysztof HaƂasa # For IXP4xx Ethernet Link: https://lore.kernel.org/r/20220830201457.7984-3-wsa+renesas@sang-engineering.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/core.c | 2 +- drivers/net/ethernet/mellanox/mlxsw/minimal.c | 4 ++-- drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/net/ethernet/mellanox/mlxsw') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index 1d14b1d8c500..e2a985ec2c76 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -652,7 +652,7 @@ static void mlxsw_emad_process_string_tlv(const struct sk_buff *skb, return; string = mlxsw_emad_string_tlv_string_data(string_tlv); - strlcpy(trans->emad_err_string, string, + strscpy(trans->emad_err_string, string, MLXSW_EMAD_STRING_TLV_STRING_LEN); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/minimal.c b/drivers/net/ethernet/mellanox/mlxsw/minimal.c index c7f7e49251f4..55b3c42bb007 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/minimal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/minimal.c @@ -103,14 +103,14 @@ static void mlxsw_m_module_get_drvinfo(struct net_device *dev, struct mlxsw_m_port *mlxsw_m_port = netdev_priv(dev); struct mlxsw_m *mlxsw_m = mlxsw_m_port->mlxsw_m; - strlcpy(drvinfo->driver, mlxsw_m->bus_info->device_kind, + strscpy(drvinfo->driver, mlxsw_m->bus_info->device_kind, sizeof(drvinfo->driver)); snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), "%d.%d.%d", mlxsw_m->bus_info->fw_rev.major, mlxsw_m->bus_info->fw_rev.minor, mlxsw_m->bus_info->fw_rev.subminor); - strlcpy(drvinfo->bus_info, mlxsw_m->bus_info->device_name, + strscpy(drvinfo->bus_info, mlxsw_m->bus_info->device_name, sizeof(drvinfo->bus_info)); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c index 915dffb85a1c..dcd79d7e2af4 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c @@ -14,16 +14,16 @@ static void mlxsw_sp_port_get_drvinfo(struct net_device *dev, struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; - strlcpy(drvinfo->driver, mlxsw_sp->bus_info->device_kind, + strscpy(drvinfo->driver, mlxsw_sp->bus_info->device_kind, sizeof(drvinfo->driver)); - strlcpy(drvinfo->version, mlxsw_sp_driver_version, + strscpy(drvinfo->version, mlxsw_sp_driver_version, sizeof(drvinfo->version)); snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), "%d.%d.%d", mlxsw_sp->bus_info->fw_rev.major, mlxsw_sp->bus_info->fw_rev.minor, mlxsw_sp->bus_info->fw_rev.subminor); - strlcpy(drvinfo->bus_info, mlxsw_sp->bus_info->device_name, + strscpy(drvinfo->bus_info, mlxsw_sp->bus_info->device_name, sizeof(drvinfo->bus_info)); } -- cgit From a292c25607ea3f259afb318f03e05b84108348bf Mon Sep 17 00:00:00 2001 From: wangjianli Date: Thu, 8 Sep 2022 20:43:50 +0800 Subject: mellanox/mlxsw: fix repeated words in comments Delete the redundant word 'in'. Signed-off-by: wangjianli Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/ethernet/mellanox/mlxsw') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 2c4443c6b964..48f1fa62a4fd 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -1819,7 +1819,7 @@ void mlxsw_sp_ipip_entry_demote_tunnel(struct mlxsw_sp *mlxsw_sp, /* The configuration where several tunnels have the same local address in the * same underlay table needs special treatment in the HW. That is currently not * implemented in the driver. This function finds and demotes the first tunnel - * with a given source address, except the one passed in in the argument + * with a given source address, except the one passed in the argument * `except'. */ bool -- cgit From a9c3abf4e5765568c4d4567388230d746286c52e Mon Sep 17 00:00:00 2001 From: Gaosheng Cui Date: Thu, 22 Sep 2022 16:38:54 +0800 Subject: mlxsw: reg: Remove deprecated code about SFTR-V2 Register Remove all the code about SFTR-V2 Register which have been deprecated since commit 77b7f83d5c25 ("mlxsw: Enable unified bridge model"). Signed-off-by: Gaosheng Cui Reviewed-by: Ido Schimmel Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 71 ------------------------------- 1 file changed, 71 deletions(-) (limited to 'drivers/net/ethernet/mellanox/mlxsw') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index d71d7f9a20f1..0777bed5bb1a 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -2218,76 +2218,6 @@ static inline void mlxsw_reg_smpe_pack(char *payload, u16 local_port, mlxsw_reg_smpe_evid_set(payload, evid); } -/* SFTR-V2 - Switch Flooding Table Version 2 Register - * -------------------------------------------------- - * The switch flooding table is used for flooding packet replication. The table - * defines a bit mask of ports for packet replication. - */ -#define MLXSW_REG_SFTR2_ID 0x202F -#define MLXSW_REG_SFTR2_LEN 0x120 - -MLXSW_REG_DEFINE(sftr2, MLXSW_REG_SFTR2_ID, MLXSW_REG_SFTR2_LEN); - -/* reg_sftr2_swid - * Switch partition ID with which to associate the port. - * Access: Index - */ -MLXSW_ITEM32(reg, sftr2, swid, 0x00, 24, 8); - -/* reg_sftr2_flood_table - * Flooding table index to associate with the specific type on the specific - * switch partition. - * Access: Index - */ -MLXSW_ITEM32(reg, sftr2, flood_table, 0x00, 16, 6); - -/* reg_sftr2_index - * Index. Used as an index into the Flooding Table in case the table is - * configured to use VID / FID or FID Offset. - * Access: Index - */ -MLXSW_ITEM32(reg, sftr2, index, 0x00, 0, 16); - -/* reg_sftr2_table_type - * See mlxsw_flood_table_type - * Access: RW - */ -MLXSW_ITEM32(reg, sftr2, table_type, 0x04, 16, 3); - -/* reg_sftr2_range - * Range of entries to update - * Access: Index - */ -MLXSW_ITEM32(reg, sftr2, range, 0x04, 0, 16); - -/* reg_sftr2_port - * Local port membership (1 bit per port). - * Access: RW - */ -MLXSW_ITEM_BIT_ARRAY(reg, sftr2, port, 0x20, 0x80, 1); - -/* reg_sftr2_port_mask - * Local port mask (1 bit per port). - * Access: WO - */ -MLXSW_ITEM_BIT_ARRAY(reg, sftr2, port_mask, 0xA0, 0x80, 1); - -static inline void mlxsw_reg_sftr2_pack(char *payload, - unsigned int flood_table, - unsigned int index, - enum mlxsw_flood_table_type table_type, - unsigned int range, u16 port, bool set) -{ - MLXSW_REG_ZERO(sftr2, payload); - mlxsw_reg_sftr2_swid_set(payload, 0); - mlxsw_reg_sftr2_flood_table_set(payload, flood_table); - mlxsw_reg_sftr2_index_set(payload, index); - mlxsw_reg_sftr2_table_type_set(payload, table_type); - mlxsw_reg_sftr2_range_set(payload, range); - mlxsw_reg_sftr2_port_set(payload, port, set); - mlxsw_reg_sftr2_port_mask_set(payload, port, 1); -} - /* SMID-V2 - Switch Multicast ID Version 2 Register * ------------------------------------------------ * The MID record maps from a MID (Multicast ID), which is a unique identifier @@ -12833,7 +12763,6 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { MLXSW_REG(spvc), MLXSW_REG(spevet), MLXSW_REG(smpe), - MLXSW_REG(sftr2), MLXSW_REG(smid2), MLXSW_REG(cwtp), MLXSW_REG(cwtpm), -- cgit From d89318bbdf2b8f472d7f1225bbe44ead7b57c5e4 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Mon, 26 Sep 2022 17:40:33 -0700 Subject: mlxsw: core_acl_flex_actions: Split memcpy() of struct flow_action_cookie flexible array To work around a misbehavior of the compiler's ability to see into composite flexible array structs (as detailed in the coming memcpy() hardening series[1]), split the memcpy() of the header and the payload so no false positive run-time overflow warning will be generated. [1] https://lore.kernel.org/linux-hardening/20220901065914.1417829-2-keescook@chromium.org Cc: Ido Schimmel Signed-off-by: Kees Cook Reviewed-by: Gustavo A. R. Silva Reviewed-by: Petr Machata Link: https://lore.kernel.org/r/20220927004033.1942992-1-keescook@chromium.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net/ethernet/mellanox/mlxsw') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c index 636db9a87457..9dfe7148199f 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c @@ -737,8 +737,9 @@ mlxsw_afa_cookie_create(struct mlxsw_afa *mlxsw_afa, if (!cookie) return ERR_PTR(-ENOMEM); refcount_set(&cookie->ref_count, 1); - memcpy(&cookie->fa_cookie, fa_cookie, - sizeof(*fa_cookie) + fa_cookie->cookie_len); + cookie->fa_cookie = *fa_cookie; + memcpy(cookie->fa_cookie.cookie, fa_cookie->cookie, + fa_cookie->cookie_len); err = rhashtable_insert_fast(&mlxsw_afa->cookie_ht, &cookie->ht_node, mlxsw_afa_cookie_ht_params); -- cgit