diff options
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/core.c | 73 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/core.h | 5 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/i2c.c | 5 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/pci.c | 5 |
4 files changed, 65 insertions, 23 deletions
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index c93512b16121..3529b545675d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c | |||
@@ -113,6 +113,7 @@ struct mlxsw_core { | |||
113 | struct mlxsw_thermal *thermal; | 113 | struct mlxsw_thermal *thermal; |
114 | struct mlxsw_core_port *ports; | 114 | struct mlxsw_core_port *ports; |
115 | unsigned int max_ports; | 115 | unsigned int max_ports; |
116 | bool reload_fail; | ||
116 | unsigned long driver_priv[0]; | 117 | unsigned long driver_priv[0]; |
117 | /* driver_priv has to be always the last item */ | 118 | /* driver_priv has to be always the last item */ |
118 | }; | 119 | }; |
@@ -962,7 +963,28 @@ mlxsw_devlink_sb_occ_tc_port_bind_get(struct devlink_port *devlink_port, | |||
962 | pool_type, p_cur, p_max); | 963 | pool_type, p_cur, p_max); |
963 | } | 964 | } |
964 | 965 | ||
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 | |||
965 | static const struct devlink_ops mlxsw_devlink_ops = { | 986 | static const struct devlink_ops mlxsw_devlink_ops = { |
987 | .reload = mlxsw_devlink_core_bus_device_reload, | ||
966 | .port_type_set = mlxsw_devlink_port_type_set, | 988 | .port_type_set = mlxsw_devlink_port_type_set, |
967 | .port_split = mlxsw_devlink_port_split, | 989 | .port_split = mlxsw_devlink_port_split, |
968 | .port_unsplit = mlxsw_devlink_port_unsplit, | 990 | .port_unsplit = mlxsw_devlink_port_unsplit, |
@@ -980,23 +1002,26 @@ static const struct devlink_ops mlxsw_devlink_ops = { | |||
980 | 1002 | ||
981 | int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info, | 1003 | int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info, |
982 | const struct mlxsw_bus *mlxsw_bus, | 1004 | const struct mlxsw_bus *mlxsw_bus, |
983 | void *bus_priv) | 1005 | void *bus_priv, bool reload, |
1006 | struct devlink *devlink) | ||
984 | { | 1007 | { |
985 | const char *device_kind = mlxsw_bus_info->device_kind; | 1008 | const char *device_kind = mlxsw_bus_info->device_kind; |
986 | struct mlxsw_core *mlxsw_core; | 1009 | struct mlxsw_core *mlxsw_core; |
987 | struct mlxsw_driver *mlxsw_driver; | 1010 | struct mlxsw_driver *mlxsw_driver; |
988 | struct devlink *devlink; | ||
989 | size_t alloc_size; | 1011 | size_t alloc_size; |
990 | int err; | 1012 | int err; |
991 | 1013 | ||
992 | mlxsw_driver = mlxsw_core_driver_get(device_kind); | 1014 | mlxsw_driver = mlxsw_core_driver_get(device_kind); |
993 | if (!mlxsw_driver) | 1015 | if (!mlxsw_driver) |
994 | return -EINVAL; | 1016 | return -EINVAL; |
995 | alloc_size = sizeof(*mlxsw_core) + mlxsw_driver->priv_size; | 1017 | |
996 | devlink = devlink_alloc(&mlxsw_devlink_ops, alloc_size); | 1018 | if (!reload) { |
997 | if (!devlink) { | 1019 | alloc_size = sizeof(*mlxsw_core) + mlxsw_driver->priv_size; |
998 | err = -ENOMEM; | 1020 | devlink = devlink_alloc(&mlxsw_devlink_ops, alloc_size); |
999 | goto err_devlink_alloc; | 1021 | if (!devlink) { |
1022 | err = -ENOMEM; | ||
1023 | goto err_devlink_alloc; | ||
1024 | } | ||
1000 | } | 1025 | } |
1001 | 1026 | ||
1002 | mlxsw_core = devlink_priv(devlink); | 1027 | mlxsw_core = devlink_priv(devlink); |
@@ -1012,7 +1037,7 @@ int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info, | |||
1012 | if (err) | 1037 | if (err) |
1013 | goto err_bus_init; | 1038 | goto err_bus_init; |
1014 | 1039 | ||
1015 | if (mlxsw_driver->resources_register) { | 1040 | if (mlxsw_driver->resources_register && !reload) { |
1016 | err = mlxsw_driver->resources_register(mlxsw_core); | 1041 | err = mlxsw_driver->resources_register(mlxsw_core); |
1017 | if (err) | 1042 | if (err) |
1018 | goto err_register_resources; | 1043 | goto err_register_resources; |
@@ -1038,9 +1063,11 @@ int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info, | |||
1038 | if (err) | 1063 | if (err) |
1039 | goto err_emad_init; | 1064 | goto err_emad_init; |
1040 | 1065 | ||
1041 | err = devlink_register(devlink, mlxsw_bus_info->dev); | 1066 | if (!reload) { |
1042 | if (err) | 1067 | err = devlink_register(devlink, mlxsw_bus_info->dev); |
1043 | goto err_devlink_register; | 1068 | if (err) |
1069 | goto err_devlink_register; | ||
1070 | } | ||
1044 | 1071 | ||
1045 | err = mlxsw_hwmon_init(mlxsw_core, mlxsw_bus_info, &mlxsw_core->hwmon); | 1072 | err = mlxsw_hwmon_init(mlxsw_core, mlxsw_bus_info, &mlxsw_core->hwmon); |
1046 | if (err) | 1073 | if (err) |
@@ -1063,7 +1090,8 @@ err_driver_init: | |||
1063 | mlxsw_thermal_fini(mlxsw_core->thermal); | 1090 | mlxsw_thermal_fini(mlxsw_core->thermal); |
1064 | err_thermal_init: | 1091 | err_thermal_init: |
1065 | err_hwmon_init: | 1092 | err_hwmon_init: |
1066 | devlink_unregister(devlink); | 1093 | if (!reload) |
1094 | devlink_unregister(devlink); | ||
1067 | err_devlink_register: | 1095 | err_devlink_register: |
1068 | mlxsw_emad_fini(mlxsw_core); | 1096 | mlxsw_emad_fini(mlxsw_core); |
1069 | err_emad_init: | 1097 | err_emad_init: |
@@ -1073,29 +1101,40 @@ err_alloc_lag_mapping: | |||
1073 | err_ports_init: | 1101 | err_ports_init: |
1074 | mlxsw_bus->fini(bus_priv); | 1102 | mlxsw_bus->fini(bus_priv); |
1075 | err_bus_init: | 1103 | err_bus_init: |
1076 | devlink_resources_unregister(devlink, NULL); | 1104 | if (!reload) |
1105 | devlink_resources_unregister(devlink, NULL); | ||
1077 | err_register_resources: | 1106 | err_register_resources: |
1078 | devlink_free(devlink); | 1107 | if (!reload) |
1108 | devlink_free(devlink); | ||
1079 | err_devlink_alloc: | 1109 | err_devlink_alloc: |
1080 | mlxsw_core_driver_put(device_kind); | 1110 | mlxsw_core_driver_put(device_kind); |
1081 | return err; | 1111 | return err; |
1082 | } | 1112 | } |
1083 | EXPORT_SYMBOL(mlxsw_core_bus_device_register); | 1113 | EXPORT_SYMBOL(mlxsw_core_bus_device_register); |
1084 | 1114 | ||
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) | ||
1086 | { | 1117 | { |
1087 | const char *device_kind = mlxsw_core->bus_info->device_kind; | 1118 | const char *device_kind = mlxsw_core->bus_info->device_kind; |
1088 | struct devlink *devlink = priv_to_devlink(mlxsw_core); | 1119 | struct devlink *devlink = priv_to_devlink(mlxsw_core); |
1089 | 1120 | ||
1121 | if (mlxsw_core->reload_fail) | ||
1122 | goto reload_fail; | ||
1123 | |||
1090 | if (mlxsw_core->driver->fini) | 1124 | if (mlxsw_core->driver->fini) |
1091 | mlxsw_core->driver->fini(mlxsw_core); | 1125 | mlxsw_core->driver->fini(mlxsw_core); |
1092 | mlxsw_thermal_fini(mlxsw_core->thermal); | 1126 | mlxsw_thermal_fini(mlxsw_core->thermal); |
1093 | devlink_unregister(devlink); | 1127 | if (!reload) |
1128 | devlink_unregister(devlink); | ||
1094 | mlxsw_emad_fini(mlxsw_core); | 1129 | mlxsw_emad_fini(mlxsw_core); |
1095 | kfree(mlxsw_core->lag.mapping); | 1130 | kfree(mlxsw_core->lag.mapping); |
1096 | mlxsw_ports_fini(mlxsw_core); | 1131 | mlxsw_ports_fini(mlxsw_core); |
1097 | devlink_resources_unregister(devlink, NULL); | 1132 | if (!reload) |
1133 | devlink_resources_unregister(devlink, NULL); | ||
1098 | mlxsw_core->bus->fini(mlxsw_core->bus_priv); | 1134 | mlxsw_core->bus->fini(mlxsw_core->bus_priv); |
1135 | if (reload) | ||
1136 | return; | ||
1137 | reload_fail: | ||
1099 | devlink_free(devlink); | 1138 | devlink_free(devlink); |
1100 | mlxsw_core_driver_put(device_kind); | 1139 | mlxsw_core_driver_put(device_kind); |
1101 | } | 1140 | } |
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index e44061dfe8c7..5ddafd74dc00 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h | |||
@@ -66,8 +66,9 @@ void mlxsw_core_driver_unregister(struct mlxsw_driver *mlxsw_driver); | |||
66 | 66 | ||
67 | int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info, | 67 | int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info, |
68 | const struct mlxsw_bus *mlxsw_bus, | 68 | const struct mlxsw_bus *mlxsw_bus, |
69 | void *bus_priv); | 69 | void *bus_priv, bool reload, |
70 | void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core); | 70 | struct devlink *devlink); |
71 | void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core, bool reload); | ||
71 | 72 | ||
72 | struct mlxsw_tx_info { | 73 | struct mlxsw_tx_info { |
73 | u8 local_port; | 74 | u8 local_port; |
diff --git a/drivers/net/ethernet/mellanox/mlxsw/i2c.c b/drivers/net/ethernet/mellanox/mlxsw/i2c.c index c0dcfa05b077..25f9915ebd82 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/i2c.c +++ b/drivers/net/ethernet/mellanox/mlxsw/i2c.c | |||
@@ -539,7 +539,8 @@ static int mlxsw_i2c_probe(struct i2c_client *client, | |||
539 | mlxsw_i2c->dev = &client->dev; | 539 | mlxsw_i2c->dev = &client->dev; |
540 | 540 | ||
541 | err = mlxsw_core_bus_device_register(&mlxsw_i2c->bus_info, | 541 | 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); | ||
543 | if (err) { | 544 | if (err) { |
544 | dev_err(&client->dev, "Fail to register core bus\n"); | 545 | dev_err(&client->dev, "Fail to register core bus\n"); |
545 | return err; | 546 | return err; |
@@ -557,7 +558,7 @@ static int mlxsw_i2c_remove(struct i2c_client *client) | |||
557 | { | 558 | { |
558 | struct mlxsw_i2c *mlxsw_i2c = i2c_get_clientdata(client); | 559 | struct mlxsw_i2c *mlxsw_i2c = i2c_get_clientdata(client); |
559 | 560 | ||
560 | mlxsw_core_bus_device_unregister(mlxsw_i2c->core); | 561 | mlxsw_core_bus_device_unregister(mlxsw_i2c->core, false); |
561 | mutex_destroy(&mlxsw_i2c->cmd.lock); | 562 | mutex_destroy(&mlxsw_i2c->cmd.lock); |
562 | 563 | ||
563 | return 0; | 564 | return 0; |
diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c index 58ab18845928..85faa87bf42d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.c +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c | |||
@@ -1739,7 +1739,8 @@ static int mlxsw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1739 | mlxsw_pci->id = id; | 1739 | mlxsw_pci->id = id; |
1740 | 1740 | ||
1741 | err = mlxsw_core_bus_device_register(&mlxsw_pci->bus_info, | 1741 | 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); | ||
1743 | if (err) { | 1744 | if (err) { |
1744 | dev_err(&pdev->dev, "cannot register bus device\n"); | 1745 | dev_err(&pdev->dev, "cannot register bus device\n"); |
1745 | goto err_bus_device_register; | 1746 | goto err_bus_device_register; |
@@ -1767,7 +1768,7 @@ static void mlxsw_pci_remove(struct pci_dev *pdev) | |||
1767 | { | 1768 | { |
1768 | struct mlxsw_pci *mlxsw_pci = pci_get_drvdata(pdev); | 1769 | struct mlxsw_pci *mlxsw_pci = pci_get_drvdata(pdev); |
1769 | 1770 | ||
1770 | mlxsw_core_bus_device_unregister(mlxsw_pci->core); | 1771 | mlxsw_core_bus_device_unregister(mlxsw_pci->core, false); |
1771 | mlxsw_pci_free_irq_vectors(mlxsw_pci); | 1772 | mlxsw_pci_free_irq_vectors(mlxsw_pci); |
1772 | iounmap(mlxsw_pci->hw_addr); | 1773 | iounmap(mlxsw_pci->hw_addr); |
1773 | pci_release_regions(mlxsw_pci->pdev); | 1774 | pci_release_regions(mlxsw_pci->pdev); |