e286869b24
- Why I did it 1. Update Mellanox HW-MGMT package to newer version V.7.0030.1011 2. Replace the SONiC PMON Thermal control algorithm with the one inside the HW-MGMT package on all Nvidia platforms 3. Support Spectrum-4 systems - How I did it 1. Update the HW-MGMT package version number and submodule pointer 2. Remove the thermal control algorithm implementation from Mellanox platform API 3. Revise the patch to HW-MGMT package which will disable HW-MGMT from running on SIMX 4. Update the downstream kernel patch list Signed-off-by: Kebo Liu <kebol@nvidia.com>
456 lines
13 KiB
Diff
456 lines
13 KiB
Diff
From f00081a6e0b7af5a0b85db3121afe3cc6a62f9e7 Mon Sep 17 00:00:00 2001
|
|
From: Vadim Pasternak <vadimp@nvidia.com>
|
|
Date: Sun, 11 Dec 2022 11:08:07 +0200
|
|
Subject: [PATCH backport 5.10 072/150] platform: mellanox: Split logic in init
|
|
and exit flow
|
|
|
|
Split logic in mlxplat_init()/mlxplat_exit() routines.
|
|
Separate initialization of I2C infrastructure and others platform
|
|
drivers.
|
|
|
|
Motivation is to provide synchronization between I2C bus and mux
|
|
drivers and other drivers using this infrastructure.
|
|
I2C main bus and MUX busses are implemented in FPGA logic. On some new
|
|
systems the numbers allocated for these busses could be variable
|
|
depending on order of initialization of I2C native busses. Since bus
|
|
numbers are passed to some other platform drivers during initialization
|
|
flow, it is necessary to synchronize completion of I2C infrastructure
|
|
drivers and activation of rest of drivers.
|
|
|
|
Thus initialization flow will be performed in synchronized order.
|
|
|
|
Signed-off-by: Vadim Pasternak <vadimp@nvidia.com>
|
|
---
|
|
drivers/platform/x86/mlx-platform.c | 313 ++++++++++++++++++----------
|
|
1 file changed, 204 insertions(+), 109 deletions(-)
|
|
|
|
diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c
|
|
index 199f22d72..05a630135 100644
|
|
--- a/drivers/platform/x86/mlx-platform.c
|
|
+++ b/drivers/platform/x86/mlx-platform.c
|
|
@@ -321,6 +321,9 @@
|
|
/* Default value for PWM control register for rack switch system */
|
|
#define MLXPLAT_REGMAP_NVSWITCH_PWM_DEFAULT 0xf4
|
|
|
|
+#define MLXPLAT_I2C_MAIN_BUS_NOTIFIED 0x01
|
|
+#define MLXPLAT_I2C_MAIN_BUS_HANDLE_CREATED 0x02
|
|
+
|
|
/* mlxplat_priv - platform private data
|
|
* @pdev_i2c - i2c controller platform device
|
|
* @pdev_mux - array of mux platform devices
|
|
@@ -332,6 +335,7 @@
|
|
* @regmap: device register map
|
|
* @hotplug_resources: system hotplug resources
|
|
* @hotplug_resources_size: size of system hotplug resources
|
|
+ * @hi2c_main_init_status: init status of I2C main bus
|
|
*/
|
|
struct mlxplat_priv {
|
|
struct platform_device *pdev_i2c;
|
|
@@ -344,9 +348,11 @@ struct mlxplat_priv {
|
|
void *regmap;
|
|
struct resource *hotplug_resources;
|
|
unsigned int hotplug_resources_size;
|
|
+ u8 i2c_main_init_status;
|
|
};
|
|
|
|
static struct platform_device *mlxplat_dev;
|
|
+static int mlxplat_i2c_main_complition_notify(void *handle, int id);
|
|
|
|
/* Regions for LPC I2C controller and LPC base register space */
|
|
static const struct resource mlxplat_lpc_resources[] = {
|
|
@@ -381,6 +387,7 @@ static struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_i2c_ng_data = {
|
|
.mask = MLXPLAT_CPLD_AGGR_MASK_COMEX,
|
|
.cell_low = MLXPLAT_CPLD_LPC_REG_AGGRCO_OFFSET,
|
|
.mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_I2C,
|
|
+ .completion_notify = mlxplat_i2c_main_complition_notify,
|
|
};
|
|
|
|
/* Platform default channels */
|
|
@@ -6413,68 +6420,9 @@ static void mlxplat_post_exit(void)
|
|
mlxplat_lpc_cpld_device_exit();
|
|
}
|
|
|
|
-static int __init mlxplat_init(void)
|
|
+static int mlxplat_post_init(struct mlxplat_priv *priv)
|
|
{
|
|
- unsigned int hotplug_resources_size;
|
|
- struct resource *hotplug_resources;
|
|
- struct mlxplat_priv *priv;
|
|
- int i, j, nr, err;
|
|
-
|
|
- if (!dmi_check_system(mlxplat_dmi_table))
|
|
- return -ENODEV;
|
|
-
|
|
- err = mlxplat_pre_init(&hotplug_resources, &hotplug_resources_size);
|
|
- if (err)
|
|
- return err;
|
|
-
|
|
- priv = devm_kzalloc(&mlxplat_dev->dev, sizeof(struct mlxplat_priv),
|
|
- GFP_KERNEL);
|
|
- if (!priv) {
|
|
- err = -ENOMEM;
|
|
- goto fail_alloc;
|
|
- }
|
|
- platform_set_drvdata(mlxplat_dev, priv);
|
|
-
|
|
- priv->hotplug_resources = hotplug_resources;
|
|
- priv->hotplug_resources_size = hotplug_resources_size;
|
|
-
|
|
- if (!mlxplat_regmap_config)
|
|
- mlxplat_regmap_config = &mlxplat_mlxcpld_regmap_config;
|
|
-
|
|
- priv->regmap = devm_regmap_init(&mlxplat_dev->dev, NULL,
|
|
- &mlxplat_mlxcpld_regmap_ctx,
|
|
- mlxplat_regmap_config);
|
|
- if (IS_ERR(priv->regmap)) {
|
|
- err = PTR_ERR(priv->regmap);
|
|
- goto fail_alloc;
|
|
- }
|
|
-
|
|
- err = mlxplat_mlxcpld_verify_bus_topology(&nr);
|
|
- if (nr < 0)
|
|
- goto fail_alloc;
|
|
-
|
|
- nr = (nr == mlxplat_max_adap_num) ? -1 : nr;
|
|
- if (mlxplat_i2c)
|
|
- mlxplat_i2c->regmap = priv->regmap;
|
|
- priv->pdev_i2c = platform_device_register_resndata(&mlxplat_dev->dev, "i2c_mlxcpld",
|
|
- nr, priv->hotplug_resources,
|
|
- priv->hotplug_resources_size,
|
|
- mlxplat_i2c, sizeof(*mlxplat_i2c));
|
|
- if (IS_ERR(priv->pdev_i2c)) {
|
|
- err = PTR_ERR(priv->pdev_i2c);
|
|
- goto fail_alloc;
|
|
- }
|
|
-
|
|
- for (i = 0; i < mlxplat_mux_num; i++) {
|
|
- priv->pdev_mux[i] = platform_device_register_resndata(&priv->pdev_i2c->dev,
|
|
- "i2c-mux-reg", i, NULL, 0,
|
|
- &mlxplat_mux_data[i],
|
|
- sizeof(mlxplat_mux_data[i]));
|
|
- if (IS_ERR(priv->pdev_mux[i])) {
|
|
- err = PTR_ERR(priv->pdev_mux[i]);
|
|
- goto fail_platform_mux_register;
|
|
- }
|
|
- }
|
|
+ int i = 0, err;
|
|
|
|
/* Add hotplug driver */
|
|
if (mlxplat_hotplug) {
|
|
@@ -6487,19 +6435,10 @@ static int __init mlxplat_init(void)
|
|
mlxplat_hotplug, sizeof(*mlxplat_hotplug));
|
|
if (IS_ERR(priv->pdev_hotplug)) {
|
|
err = PTR_ERR(priv->pdev_hotplug);
|
|
- goto fail_platform_mux_register;
|
|
+ goto fail_platform_hotplug_register;
|
|
}
|
|
}
|
|
|
|
- /* Set default registers. */
|
|
- for (j = 0; j < mlxplat_regmap_config->num_reg_defaults; j++) {
|
|
- err = regmap_write(priv->regmap,
|
|
- mlxplat_regmap_config->reg_defaults[j].reg,
|
|
- mlxplat_regmap_config->reg_defaults[j].def);
|
|
- if (err)
|
|
- goto fail_platform_mux_register;
|
|
- }
|
|
-
|
|
/* Add LED driver. */
|
|
if (mlxplat_led) {
|
|
mlxplat_led->regmap = priv->regmap;
|
|
@@ -6509,7 +6448,7 @@ static int __init mlxplat_init(void)
|
|
sizeof(*mlxplat_led));
|
|
if (IS_ERR(priv->pdev_led)) {
|
|
err = PTR_ERR(priv->pdev_led);
|
|
- goto fail_platform_hotplug_register;
|
|
+ goto fail_platform_leds_register;
|
|
}
|
|
}
|
|
|
|
@@ -6523,7 +6462,7 @@ static int __init mlxplat_init(void)
|
|
sizeof(*mlxplat_regs_io));
|
|
if (IS_ERR(priv->pdev_io_regs)) {
|
|
err = PTR_ERR(priv->pdev_io_regs);
|
|
- goto fail_platform_led_register;
|
|
+ goto fail_platform_io_register;
|
|
}
|
|
}
|
|
|
|
@@ -6536,7 +6475,7 @@ static int __init mlxplat_init(void)
|
|
sizeof(*mlxplat_fan));
|
|
if (IS_ERR(priv->pdev_fan)) {
|
|
err = PTR_ERR(priv->pdev_fan);
|
|
- goto fail_platform_io_regs_register;
|
|
+ goto fail_platform_fan_register;
|
|
}
|
|
}
|
|
|
|
@@ -6547,59 +6486,42 @@ static int __init mlxplat_init(void)
|
|
err = mlxplat_mlxcpld_check_wd_capability(priv->regmap);
|
|
if (err)
|
|
goto fail_platform_wd_register;
|
|
- for (j = 0; j < MLXPLAT_CPLD_WD_MAX_DEVS; j++) {
|
|
- if (mlxplat_wd_data[j]) {
|
|
- mlxplat_wd_data[j]->regmap = priv->regmap;
|
|
- priv->pdev_wd[j] =
|
|
- platform_device_register_resndata(&mlxplat_dev->dev, "mlx-wdt", j,
|
|
- NULL, 0, mlxplat_wd_data[j],
|
|
- sizeof(*mlxplat_wd_data[j]));
|
|
- if (IS_ERR(priv->pdev_wd[j])) {
|
|
- err = PTR_ERR(priv->pdev_wd[j]);
|
|
+ for (i = 0; i < MLXPLAT_CPLD_WD_MAX_DEVS; i++) {
|
|
+ if (mlxplat_wd_data[i]) {
|
|
+ mlxplat_wd_data[i]->regmap = priv->regmap;
|
|
+ priv->pdev_wd[i] =
|
|
+ platform_device_register_resndata(&mlxplat_dev->dev, "mlx-wdt", i,
|
|
+ NULL, 0, mlxplat_wd_data[i],
|
|
+ sizeof(*mlxplat_wd_data[i]));
|
|
+ if (IS_ERR(priv->pdev_wd[i])) {
|
|
+ err = PTR_ERR(priv->pdev_wd[i]);
|
|
goto fail_platform_wd_register;
|
|
}
|
|
}
|
|
}
|
|
|
|
- /* Sync registers with hardware. */
|
|
- regcache_mark_dirty(priv->regmap);
|
|
- err = regcache_sync(priv->regmap);
|
|
- if (err)
|
|
- goto fail_platform_wd_register;
|
|
-
|
|
return 0;
|
|
|
|
fail_platform_wd_register:
|
|
- while (--j >= 0)
|
|
- platform_device_unregister(priv->pdev_wd[j]);
|
|
- if (mlxplat_fan)
|
|
- platform_device_unregister(priv->pdev_fan);
|
|
-fail_platform_io_regs_register:
|
|
+ while (--i >= 0)
|
|
+ platform_device_unregister(priv->pdev_wd[i]);
|
|
+fail_platform_fan_register:
|
|
if (mlxplat_regs_io)
|
|
platform_device_unregister(priv->pdev_io_regs);
|
|
-fail_platform_led_register:
|
|
+fail_platform_io_register:
|
|
if (mlxplat_led)
|
|
platform_device_unregister(priv->pdev_led);
|
|
-fail_platform_hotplug_register:
|
|
+fail_platform_leds_register:
|
|
if (mlxplat_hotplug)
|
|
platform_device_unregister(priv->pdev_hotplug);
|
|
-fail_platform_mux_register:
|
|
- while (--i >= 0)
|
|
- platform_device_unregister(priv->pdev_mux[i]);
|
|
- platform_device_unregister(priv->pdev_i2c);
|
|
-fail_alloc:
|
|
-
|
|
+fail_platform_hotplug_register:
|
|
return err;
|
|
}
|
|
-module_init(mlxplat_init);
|
|
|
|
-static void __exit mlxplat_exit(void)
|
|
+static void mlxplat_pre_exit(struct mlxplat_priv *priv)
|
|
{
|
|
- struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev);
|
|
int i;
|
|
|
|
- if (pm_power_off)
|
|
- pm_power_off = NULL;
|
|
for (i = MLXPLAT_CPLD_WD_MAX_DEVS - 1; i >= 0 ; i--)
|
|
platform_device_unregister(priv->pdev_wd[i]);
|
|
if (priv->pdev_fan)
|
|
@@ -6610,13 +6532,186 @@ static void __exit mlxplat_exit(void)
|
|
platform_device_unregister(priv->pdev_led);
|
|
if (priv->pdev_hotplug)
|
|
platform_device_unregister(priv->pdev_hotplug);
|
|
+}
|
|
+
|
|
+static int
|
|
+mlxplat_i2c_mux_complition_notify(void *handle, struct i2c_adapter *parent,
|
|
+ struct i2c_adapter *adapters[])
|
|
+{
|
|
+ struct mlxplat_priv *priv = handle;
|
|
+
|
|
+ return mlxplat_post_init(priv);
|
|
+}
|
|
|
|
- for (i = mlxplat_mux_num - 1; i >= 0 ; i--)
|
|
+static int mlxplat_i2c_mux_topolgy_init(struct mlxplat_priv *priv)
|
|
+{
|
|
+ int i, err;
|
|
+
|
|
+ if (!priv->pdev_i2c) {
|
|
+ priv->i2c_main_init_status = MLXPLAT_I2C_MAIN_BUS_NOTIFIED;
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ priv->i2c_main_init_status = MLXPLAT_I2C_MAIN_BUS_HANDLE_CREATED;
|
|
+ for (i = 0; i < mlxplat_mux_num; i++) {
|
|
+ priv->pdev_mux[i] = platform_device_register_resndata(&priv->pdev_i2c->dev,
|
|
+ "i2c-mux-reg", i, NULL, 0,
|
|
+ &mlxplat_mux_data[i],
|
|
+ sizeof(mlxplat_mux_data[i]));
|
|
+ if (IS_ERR(priv->pdev_mux[i])) {
|
|
+ err = PTR_ERR(priv->pdev_mux[i]);
|
|
+ goto fail_platform_mux_register;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return mlxplat_i2c_mux_complition_notify(priv, NULL, NULL);
|
|
+
|
|
+fail_platform_mux_register:
|
|
+ while (--i >= 0)
|
|
platform_device_unregister(priv->pdev_mux[i]);
|
|
+ return err;
|
|
+}
|
|
+
|
|
+static void mlxplat_i2c_mux_topolgy_exit(struct mlxplat_priv *priv)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ for (i = mlxplat_mux_num - 1; i >= 0 ; i--) {
|
|
+ if (priv->pdev_mux[i])
|
|
+ platform_device_unregister(priv->pdev_mux[i]);
|
|
+ }
|
|
|
|
- platform_device_unregister(priv->pdev_i2c);
|
|
mlxplat_post_exit();
|
|
}
|
|
+
|
|
+static int mlxplat_i2c_main_complition_notify(void *handle, int id)
|
|
+{
|
|
+ struct mlxplat_priv *priv = handle;
|
|
+
|
|
+ return mlxplat_i2c_mux_topolgy_init(priv);
|
|
+}
|
|
+
|
|
+static int mlxplat_i2c_main_init(struct mlxplat_priv *priv)
|
|
+{
|
|
+ int nr, err;
|
|
+
|
|
+ if (!mlxplat_i2c)
|
|
+ return 0;
|
|
+
|
|
+ err = mlxplat_mlxcpld_verify_bus_topology(&nr);
|
|
+ if (nr < 0)
|
|
+ goto fail_mlxplat_mlxcpld_verify_bus_topology;
|
|
+
|
|
+ nr = (nr == mlxplat_max_adap_num) ? -1 : nr;
|
|
+ mlxplat_i2c->regmap = priv->regmap;
|
|
+ mlxplat_i2c->handle = priv;
|
|
+
|
|
+ priv->pdev_i2c = platform_device_register_resndata(&mlxplat_dev->dev, "i2c_mlxcpld",
|
|
+ nr, priv->hotplug_resources,
|
|
+ priv->hotplug_resources_size,
|
|
+ mlxplat_i2c, sizeof(*mlxplat_i2c));
|
|
+ if (IS_ERR(priv->pdev_i2c)) {
|
|
+ err = PTR_ERR(priv->pdev_i2c);
|
|
+ goto fail_platform_i2c_register;
|
|
+ }
|
|
+
|
|
+ if (priv->i2c_main_init_status == MLXPLAT_I2C_MAIN_BUS_NOTIFIED) {
|
|
+ err = mlxplat_i2c_mux_topolgy_init(priv);
|
|
+ if (err)
|
|
+ goto fail_mlxplat_i2c_mux_topolgy_init;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+
|
|
+fail_mlxplat_i2c_mux_topolgy_init:
|
|
+fail_platform_i2c_register:
|
|
+fail_mlxplat_mlxcpld_verify_bus_topology:
|
|
+ return err;
|
|
+}
|
|
+
|
|
+static void mlxplat_i2c_main_exit(struct mlxplat_priv *priv)
|
|
+{
|
|
+ mlxplat_i2c_mux_topolgy_exit(priv);
|
|
+ if (priv->pdev_i2c)
|
|
+ platform_device_unregister(priv->pdev_i2c);
|
|
+}
|
|
+
|
|
+static int __init mlxplat_init(void)
|
|
+{
|
|
+ unsigned int hotplug_resources_size;
|
|
+ struct resource *hotplug_resources;
|
|
+ struct mlxplat_priv *priv;
|
|
+ int i, err;
|
|
+
|
|
+ if (!dmi_check_system(mlxplat_dmi_table))
|
|
+ return -ENODEV;
|
|
+
|
|
+ err = mlxplat_pre_init(&hotplug_resources, &hotplug_resources_size);
|
|
+ if (err)
|
|
+ return err;
|
|
+
|
|
+ priv = devm_kzalloc(&mlxplat_dev->dev, sizeof(struct mlxplat_priv),
|
|
+ GFP_KERNEL);
|
|
+ if (!priv) {
|
|
+ err = -ENOMEM;
|
|
+ goto fail_alloc;
|
|
+ }
|
|
+ platform_set_drvdata(mlxplat_dev, priv);
|
|
+ priv->hotplug_resources = hotplug_resources;
|
|
+ priv->hotplug_resources_size = hotplug_resources_size;
|
|
+
|
|
+ if (!mlxplat_regmap_config)
|
|
+ mlxplat_regmap_config = &mlxplat_mlxcpld_regmap_config;
|
|
+
|
|
+ priv->regmap = devm_regmap_init(&mlxplat_dev->dev, NULL,
|
|
+ &mlxplat_mlxcpld_regmap_ctx,
|
|
+ mlxplat_regmap_config);
|
|
+ if (IS_ERR(priv->regmap)) {
|
|
+ err = PTR_ERR(priv->regmap);
|
|
+ goto fail_alloc;
|
|
+ }
|
|
+
|
|
+ /* Set default registers. */
|
|
+ for (i = 0; i < mlxplat_regmap_config->num_reg_defaults; i++) {
|
|
+ err = regmap_write(priv->regmap,
|
|
+ mlxplat_regmap_config->reg_defaults[i].reg,
|
|
+ mlxplat_regmap_config->reg_defaults[i].def);
|
|
+ if (err)
|
|
+ goto fail_regmap_write;
|
|
+ }
|
|
+
|
|
+ err = mlxplat_i2c_main_init(priv);
|
|
+ if (err)
|
|
+ goto fail_mlxplat_i2c_main_init;
|
|
+
|
|
+ /* Sync registers with hardware. */
|
|
+ regcache_mark_dirty(priv->regmap);
|
|
+ err = regcache_sync(priv->regmap);
|
|
+ if (err)
|
|
+ goto fail_regcache_sync;
|
|
+
|
|
+ return 0;
|
|
+
|
|
+fail_regcache_sync:
|
|
+ mlxplat_pre_exit(priv);
|
|
+fail_mlxplat_i2c_main_init:
|
|
+fail_regmap_write:
|
|
+fail_alloc:
|
|
+ mlxplat_post_exit();
|
|
+
|
|
+ return err;
|
|
+}
|
|
+module_init(mlxplat_init);
|
|
+
|
|
+static void __exit mlxplat_exit(void)
|
|
+{
|
|
+ struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev);
|
|
+
|
|
+ if (pm_power_off)
|
|
+ pm_power_off = NULL;
|
|
+ mlxplat_pre_exit(priv);
|
|
+ mlxplat_i2c_main_exit(priv);
|
|
+}
|
|
module_exit(mlxplat_exit);
|
|
|
|
MODULE_AUTHOR("Vadim Pasternak (vadimp@mellanox.com)");
|
|
--
|
|
2.20.1
|
|
|