Skip to content

Commit 24cc68a

Browse files
Arkadi Sharshevskydavem330
authored andcommitted
mlxsw: core: Add support for reload
Add support for hot reload. First, all the driver/core resources are released but the PCI and devlink instances, then reset is performed through the PCI interface. Finally the driver performs initialization. In case of reload failure the driver is left in a partially initialized state. Special care is taken during the driver removal in order to properly handle this state. Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com> Signed-off-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent e21d21c commit 24cc68a

File tree

4 files changed

+65
-23
lines changed

4 files changed

+65
-23
lines changed

drivers/net/ethernet/mellanox/mlxsw/core.c

Lines changed: 56 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ struct mlxsw_core {
113113
struct mlxsw_thermal *thermal;
114114
struct mlxsw_core_port *ports;
115115
unsigned int max_ports;
116+
bool reload_fail;
116117
unsigned long driver_priv[0];
117118
/* driver_priv has to be always the last item */
118119
};
@@ -962,7 +963,28 @@ mlxsw_devlink_sb_occ_tc_port_bind_get(struct devlink_port *devlink_port,
962963
pool_type, p_cur, p_max);
963964
}
964965

966+
static int mlxsw_devlink_core_bus_device_reload(struct devlink *devlink)
967+
{
968+
struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
969+
const struct mlxsw_bus *mlxsw_bus = mlxsw_core->bus;
970+
int err;
971+
972+
if (!mlxsw_bus->reset)
973+
return -EOPNOTSUPP;
974+
975+
mlxsw_core_bus_device_unregister(mlxsw_core, true);
976+
mlxsw_bus->reset(mlxsw_core->bus_priv);
977+
err = mlxsw_core_bus_device_register(mlxsw_core->bus_info,
978+
mlxsw_core->bus,
979+
mlxsw_core->bus_priv, true,
980+
devlink);
981+
if (err)
982+
mlxsw_core->reload_fail = true;
983+
return err;
984+
}
985+
965986
static const struct devlink_ops mlxsw_devlink_ops = {
987+
.reload = mlxsw_devlink_core_bus_device_reload,
966988
.port_type_set = mlxsw_devlink_port_type_set,
967989
.port_split = mlxsw_devlink_port_split,
968990
.port_unsplit = mlxsw_devlink_port_unsplit,
@@ -980,23 +1002,26 @@ static const struct devlink_ops mlxsw_devlink_ops = {
9801002

9811003
int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info,
9821004
const struct mlxsw_bus *mlxsw_bus,
983-
void *bus_priv)
1005+
void *bus_priv, bool reload,
1006+
struct devlink *devlink)
9841007
{
9851008
const char *device_kind = mlxsw_bus_info->device_kind;
9861009
struct mlxsw_core *mlxsw_core;
9871010
struct mlxsw_driver *mlxsw_driver;
988-
struct devlink *devlink;
9891011
size_t alloc_size;
9901012
int err;
9911013

9921014
mlxsw_driver = mlxsw_core_driver_get(device_kind);
9931015
if (!mlxsw_driver)
9941016
return -EINVAL;
995-
alloc_size = sizeof(*mlxsw_core) + mlxsw_driver->priv_size;
996-
devlink = devlink_alloc(&mlxsw_devlink_ops, alloc_size);
997-
if (!devlink) {
998-
err = -ENOMEM;
999-
goto err_devlink_alloc;
1017+
1018+
if (!reload) {
1019+
alloc_size = sizeof(*mlxsw_core) + mlxsw_driver->priv_size;
1020+
devlink = devlink_alloc(&mlxsw_devlink_ops, alloc_size);
1021+
if (!devlink) {
1022+
err = -ENOMEM;
1023+
goto err_devlink_alloc;
1024+
}
10001025
}
10011026

10021027
mlxsw_core = devlink_priv(devlink);
@@ -1012,7 +1037,7 @@ int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info,
10121037
if (err)
10131038
goto err_bus_init;
10141039

1015-
if (mlxsw_driver->resources_register) {
1040+
if (mlxsw_driver->resources_register && !reload) {
10161041
err = mlxsw_driver->resources_register(mlxsw_core);
10171042
if (err)
10181043
goto err_register_resources;
@@ -1038,9 +1063,11 @@ int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info,
10381063
if (err)
10391064
goto err_emad_init;
10401065

1041-
err = devlink_register(devlink, mlxsw_bus_info->dev);
1042-
if (err)
1043-
goto err_devlink_register;
1066+
if (!reload) {
1067+
err = devlink_register(devlink, mlxsw_bus_info->dev);
1068+
if (err)
1069+
goto err_devlink_register;
1070+
}
10441071

10451072
err = mlxsw_hwmon_init(mlxsw_core, mlxsw_bus_info, &mlxsw_core->hwmon);
10461073
if (err)
@@ -1063,7 +1090,8 @@ int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info,
10631090
mlxsw_thermal_fini(mlxsw_core->thermal);
10641091
err_thermal_init:
10651092
err_hwmon_init:
1066-
devlink_unregister(devlink);
1093+
if (!reload)
1094+
devlink_unregister(devlink);
10671095
err_devlink_register:
10681096
mlxsw_emad_fini(mlxsw_core);
10691097
err_emad_init:
@@ -1073,29 +1101,40 @@ int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info,
10731101
err_ports_init:
10741102
mlxsw_bus->fini(bus_priv);
10751103
err_bus_init:
1076-
devlink_resources_unregister(devlink, NULL);
1104+
if (!reload)
1105+
devlink_resources_unregister(devlink, NULL);
10771106
err_register_resources:
1078-
devlink_free(devlink);
1107+
if (!reload)
1108+
devlink_free(devlink);
10791109
err_devlink_alloc:
10801110
mlxsw_core_driver_put(device_kind);
10811111
return err;
10821112
}
10831113
EXPORT_SYMBOL(mlxsw_core_bus_device_register);
10841114

1085-
void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core)
1115+
void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core,
1116+
bool reload)
10861117
{
10871118
const char *device_kind = mlxsw_core->bus_info->device_kind;
10881119
struct devlink *devlink = priv_to_devlink(mlxsw_core);
10891120

1121+
if (mlxsw_core->reload_fail)
1122+
goto reload_fail;
1123+
10901124
if (mlxsw_core->driver->fini)
10911125
mlxsw_core->driver->fini(mlxsw_core);
10921126
mlxsw_thermal_fini(mlxsw_core->thermal);
1093-
devlink_unregister(devlink);
1127+
if (!reload)
1128+
devlink_unregister(devlink);
10941129
mlxsw_emad_fini(mlxsw_core);
10951130
kfree(mlxsw_core->lag.mapping);
10961131
mlxsw_ports_fini(mlxsw_core);
1097-
devlink_resources_unregister(devlink, NULL);
1132+
if (!reload)
1133+
devlink_resources_unregister(devlink, NULL);
10981134
mlxsw_core->bus->fini(mlxsw_core->bus_priv);
1135+
if (reload)
1136+
return;
1137+
reload_fail:
10991138
devlink_free(devlink);
11001139
mlxsw_core_driver_put(device_kind);
11011140
}

drivers/net/ethernet/mellanox/mlxsw/core.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,9 @@ void mlxsw_core_driver_unregister(struct mlxsw_driver *mlxsw_driver);
6666

6767
int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info,
6868
const struct mlxsw_bus *mlxsw_bus,
69-
void *bus_priv);
70-
void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core);
69+
void *bus_priv, bool reload,
70+
struct devlink *devlink);
71+
void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core, bool reload);
7172

7273
struct mlxsw_tx_info {
7374
u8 local_port;

drivers/net/ethernet/mellanox/mlxsw/i2c.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -539,7 +539,8 @@ static int mlxsw_i2c_probe(struct i2c_client *client,
539539
mlxsw_i2c->dev = &client->dev;
540540

541541
err = mlxsw_core_bus_device_register(&mlxsw_i2c->bus_info,
542-
&mlxsw_i2c_bus, mlxsw_i2c);
542+
&mlxsw_i2c_bus, mlxsw_i2c, false,
543+
NULL);
543544
if (err) {
544545
dev_err(&client->dev, "Fail to register core bus\n");
545546
return err;
@@ -557,7 +558,7 @@ static int mlxsw_i2c_remove(struct i2c_client *client)
557558
{
558559
struct mlxsw_i2c *mlxsw_i2c = i2c_get_clientdata(client);
559560

560-
mlxsw_core_bus_device_unregister(mlxsw_i2c->core);
561+
mlxsw_core_bus_device_unregister(mlxsw_i2c->core, false);
561562
mutex_destroy(&mlxsw_i2c->cmd.lock);
562563

563564
return 0;

drivers/net/ethernet/mellanox/mlxsw/pci.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1739,7 +1739,8 @@ static int mlxsw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
17391739
mlxsw_pci->id = id;
17401740

17411741
err = mlxsw_core_bus_device_register(&mlxsw_pci->bus_info,
1742-
&mlxsw_pci_bus, mlxsw_pci);
1742+
&mlxsw_pci_bus, mlxsw_pci, false,
1743+
NULL);
17431744
if (err) {
17441745
dev_err(&pdev->dev, "cannot register bus device\n");
17451746
goto err_bus_device_register;
@@ -1767,7 +1768,7 @@ static void mlxsw_pci_remove(struct pci_dev *pdev)
17671768
{
17681769
struct mlxsw_pci *mlxsw_pci = pci_get_drvdata(pdev);
17691770

1770-
mlxsw_core_bus_device_unregister(mlxsw_pci->core);
1771+
mlxsw_core_bus_device_unregister(mlxsw_pci->core, false);
17711772
mlxsw_pci_free_irq_vectors(mlxsw_pci);
17721773
iounmap(mlxsw_pci->hw_addr);
17731774
pci_release_regions(mlxsw_pci->pdev);

0 commit comments

Comments
 (0)