mirror of
https://github.com/Telecominfraproject/OpenNetworkLinux.git
synced 2025-12-25 17:27:01 +00:00
Merge pull request #564 from MellanoxBSP/onl-tigris-upstream_merge
Add Mellanox MSN3800 (Tigris) system support
This commit is contained in:
@@ -0,0 +1,839 @@
|
||||
From a648f2856518f8884a7798469faf755d0f5dcd50 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Shych <michaelsh@mellanox.com>
|
||||
Date: Mon, 17 Dec 2018 12:32:45 +0000
|
||||
Subject: [PATCH v1 mlx-wdt 1/1] watchdog: mlx-wdt: introduce watchdog driver
|
||||
for Mellanox systems
|
||||
|
||||
Watchdog driver for Mellanox watchdog devices, implemented in
|
||||
programmable logic device.
|
||||
|
||||
Main and auxiliary watchdog devices can exist on the same system.
|
||||
There are several actions that can be defined in the watchdog:
|
||||
system reset, start fans on full speed and increase counter.
|
||||
The last 2 actions are performed without system reset.
|
||||
Actions without reset are provided for auxiliary watchdog devices,
|
||||
which is optional.
|
||||
Access to CPLD registers is performed through generic
|
||||
regmap interface.
|
||||
|
||||
There are 2 types of HW CPLD watchdog implementations.
|
||||
Type 1: actual HW timeout can be defined as power of 2 msec.
|
||||
e.g. timeout 20 sec will be rounded up to 32768 msec.;
|
||||
maximum timeout period is 32 sec (32768 msec.);
|
||||
get time-left isn't supported
|
||||
Type 2: actual HW timeout is defined in sec. and it's a same as
|
||||
user defined timeout;
|
||||
maximum timeout is 255 sec;
|
||||
get time-left is supported;
|
||||
|
||||
Watchdog driver is probed from common mlx_platform driver.
|
||||
|
||||
Signed-off-by: Michael Shych <michaelsh@mellanox.com>
|
||||
---
|
||||
drivers/platform/x86/mlx-platform.c | 202 +++++++++++++++++-
|
||||
drivers/watchdog/Kconfig | 15 ++
|
||||
drivers/watchdog/Makefile | 1 +
|
||||
drivers/watchdog/mlx_wdt.c | 391 +++++++++++++++++++++++++++++++++++
|
||||
include/linux/platform_data/mlxreg.h | 6 +
|
||||
5 files changed, 612 insertions(+), 3 deletions(-)
|
||||
create mode 100644 drivers/watchdog/mlx_wdt.c
|
||||
|
||||
diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c
|
||||
index 6e150b4..fc8d655 100644
|
||||
--- a/drivers/platform/x86/mlx-platform.c
|
||||
+++ b/drivers/platform/x86/mlx-platform.c
|
||||
@@ -55,6 +55,14 @@
|
||||
#define MLXPLAT_CPLD_LPC_REG_FAN_OFFSET 0x88
|
||||
#define MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET 0x89
|
||||
#define MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET 0x8a
|
||||
+#define MLXPLAT_CPLD_LPC_REG_WD_CLEAR_OFFSET 0xc7
|
||||
+#define MLXPLAT_CPLD_LPC_REG_WD_CLEAR_WP_OFFSET 0xc8
|
||||
+#define MLXPLAT_CPLD_LPC_REG_WD1_TMR_OFFSET 0xc9
|
||||
+#define MLXPLAT_CPLD_LPC_REG_WD1_ACT_OFFSET 0xcb
|
||||
+#define MLXPLAT_CPLD_LPC_REG_WD2_TMR_OFFSET 0xcd
|
||||
+#define MLXPLAT_CPLD_LPC_REG_WD2_ACT_OFFSET 0xcf
|
||||
+#define MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET 0xd1
|
||||
+#define MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET 0xd2
|
||||
#define MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET 0xe3
|
||||
#define MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET 0xe4
|
||||
#define MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET 0xe5
|
||||
@@ -128,6 +136,18 @@
|
||||
#define MLXPLAT_CPLD_FAN3_DEFAULT_NR 13
|
||||
#define MLXPLAT_CPLD_FAN4_DEFAULT_NR 14
|
||||
|
||||
+/* Masks and default values for watchdogs */
|
||||
+#define MLXPLAT_CPLD_WD1_CLEAR_MASK GENMASK(7, 1)
|
||||
+#define MLXPLAT_CPLD_WD2_CLEAR_MASK (GENMASK(7, 0) & ~BIT(1))
|
||||
+
|
||||
+#define MLXPLAT_CPLD_WD_TYPE1_TO_MASK GENMASK(7, 4)
|
||||
+#define MLXPLAT_CPLD_WD_TYPE2_TO_MASK 0
|
||||
+#define MLXPLAT_CPLD_WD_RESET_ACT_MASK GENMASK(7, 1)
|
||||
+#define MLXPLAT_CPLD_WD_FAN_ACT_MASK (GENMASK(7, 0) & ~BIT(4))
|
||||
+#define MLXPLAT_CPLD_WD_COUNT_ACT_MASK (GENMASK(7, 0) & ~BIT(7))
|
||||
+#define MLXPLAT_CPLD_WD_DFLT_TIMEOUT 30
|
||||
+#define MLXPLAT_CPLD_WD_MAX_DEVS 2
|
||||
+
|
||||
/* mlxplat_priv - platform private data
|
||||
* @pdev_i2c - i2c controller platform device
|
||||
* @pdev_mux - array of mux platform devices
|
||||
@@ -135,6 +155,7 @@
|
||||
* @pdev_led - led platform devices
|
||||
* @pdev_io_regs - register access platform devices
|
||||
* @pdev_fan - FAN platform devices
|
||||
+ * @pdev_wd - array of watchdog platform devices
|
||||
*/
|
||||
struct mlxplat_priv {
|
||||
struct platform_device *pdev_i2c;
|
||||
@@ -143,6 +164,7 @@ struct mlxplat_priv {
|
||||
struct platform_device *pdev_led;
|
||||
struct platform_device *pdev_io_regs;
|
||||
struct platform_device *pdev_fan;
|
||||
+ struct platform_device *pdev_wd[MLXPLAT_CPLD_WD_MAX_DEVS];
|
||||
};
|
||||
|
||||
/* Regions for LPC I2C controller and LPC base register space */
|
||||
@@ -1340,6 +1362,132 @@ static struct mlxreg_core_platform_data mlxplat_default_fan_data = {
|
||||
.counter = ARRAY_SIZE(mlxplat_mlxcpld_default_fan_data),
|
||||
};
|
||||
|
||||
+/* Type1 watchdog implementation on MSN2700, MSN2100 and MSN2140 systems */
|
||||
+static struct mlxreg_core_data mlxplat_mlxcpld_wd_main_regs_type1[] = {
|
||||
+ {
|
||||
+ .label = "action",
|
||||
+ .reg = MLXPLAT_CPLD_LPC_REG_WD1_ACT_OFFSET,
|
||||
+ .mask = MLXPLAT_CPLD_WD_RESET_ACT_MASK,
|
||||
+ .bit = 0,
|
||||
+ },
|
||||
+ {
|
||||
+ .label = "timeout",
|
||||
+ .reg = MLXPLAT_CPLD_LPC_REG_WD1_TMR_OFFSET,
|
||||
+ .mask = MLXPLAT_CPLD_WD_TYPE1_TO_MASK,
|
||||
+ .health_cntr = MLXPLAT_CPLD_WD_DFLT_TIMEOUT,
|
||||
+ },
|
||||
+ {
|
||||
+ .label = "ping",
|
||||
+ .reg = MLXPLAT_CPLD_LPC_REG_WD_CLEAR_OFFSET,
|
||||
+ .mask = MLXPLAT_CPLD_WD1_CLEAR_MASK,
|
||||
+ .bit = 0,
|
||||
+ },
|
||||
+ {
|
||||
+ .label = "reset",
|
||||
+ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
|
||||
+ .mask = GENMASK(7, 0) & ~BIT(6),
|
||||
+ .bit = 6,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct mlxreg_core_data mlxplat_mlxcpld_wd_aux_regs_type1[] = {
|
||||
+ {
|
||||
+ .label = "action",
|
||||
+ .reg = MLXPLAT_CPLD_LPC_REG_WD2_ACT_OFFSET,
|
||||
+ .mask = MLXPLAT_CPLD_WD_FAN_ACT_MASK,
|
||||
+ .bit = 4,
|
||||
+ },
|
||||
+ {
|
||||
+ .label = "timeout",
|
||||
+ .reg = MLXPLAT_CPLD_LPC_REG_WD2_TMR_OFFSET,
|
||||
+ .mask = MLXPLAT_CPLD_WD_TYPE1_TO_MASK,
|
||||
+ .health_cntr = MLXPLAT_CPLD_WD_DFLT_TIMEOUT,
|
||||
+ },
|
||||
+ {
|
||||
+ .label = "ping",
|
||||
+ .reg = MLXPLAT_CPLD_LPC_REG_WD_CLEAR_OFFSET,
|
||||
+ .mask = MLXPLAT_CPLD_WD1_CLEAR_MASK,
|
||||
+ .bit = 1,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct mlxreg_core_platform_data mlxplat_mlxcpld_wd_set_type1[] = {
|
||||
+ {
|
||||
+ .data = mlxplat_mlxcpld_wd_main_regs_type1,
|
||||
+ .counter = ARRAY_SIZE(mlxplat_mlxcpld_wd_main_regs_type1),
|
||||
+ .identity = "mlx-wdt-main",
|
||||
+ },
|
||||
+ {
|
||||
+ .data = mlxplat_mlxcpld_wd_aux_regs_type1,
|
||||
+ .counter = ARRAY_SIZE(mlxplat_mlxcpld_wd_aux_regs_type1),
|
||||
+ .identity = "mlx-wdt-aux",
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+/* Type2 watchdog implementation on MSB8700 and up systems
|
||||
+ * To differentiate: ping reg == action reg
|
||||
+ */
|
||||
+static struct mlxreg_core_data mlxplat_mlxcpld_wd_main_regs_type2[] = {
|
||||
+ {
|
||||
+ .label = "action",
|
||||
+ .reg = MLXPLAT_CPLD_LPC_REG_WD2_ACT_OFFSET,
|
||||
+ .mask = MLXPLAT_CPLD_WD_RESET_ACT_MASK,
|
||||
+ .bit = 0,
|
||||
+ },
|
||||
+ {
|
||||
+ .label = "timeout",
|
||||
+ .reg = MLXPLAT_CPLD_LPC_REG_WD2_TMR_OFFSET,
|
||||
+ .mask = MLXPLAT_CPLD_WD_TYPE2_TO_MASK,
|
||||
+ .health_cntr = MLXPLAT_CPLD_WD_DFLT_TIMEOUT,
|
||||
+ },
|
||||
+ {
|
||||
+ .label = "ping",
|
||||
+ .reg = MLXPLAT_CPLD_LPC_REG_WD2_ACT_OFFSET,
|
||||
+ .mask = MLXPLAT_CPLD_WD_RESET_ACT_MASK,
|
||||
+ .bit = 0,
|
||||
+ },
|
||||
+ {
|
||||
+ .label = "reset",
|
||||
+ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
|
||||
+ .mask = GENMASK(7, 0) & ~BIT(6),
|
||||
+ .bit = 6,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct mlxreg_core_data mlxplat_mlxcpld_wd_aux_regs_type2[] = {
|
||||
+ {
|
||||
+ .label = "action",
|
||||
+ .reg = MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET,
|
||||
+ .mask = MLXPLAT_CPLD_WD_FAN_ACT_MASK,
|
||||
+ .bit = 4,
|
||||
+ },
|
||||
+ {
|
||||
+ .label = "timeout",
|
||||
+ .reg = MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET,
|
||||
+ .mask = MLXPLAT_CPLD_WD_TYPE2_TO_MASK,
|
||||
+ .health_cntr = MLXPLAT_CPLD_WD_DFLT_TIMEOUT,
|
||||
+ },
|
||||
+ {
|
||||
+ .label = "ping",
|
||||
+ .reg = MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET,
|
||||
+ .mask = MLXPLAT_CPLD_WD_FAN_ACT_MASK,
|
||||
+ .bit = 4,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct mlxreg_core_platform_data mlxplat_mlxcpld_wd_set_type2[] = {
|
||||
+ {
|
||||
+ .data = mlxplat_mlxcpld_wd_main_regs_type2,
|
||||
+ .counter = ARRAY_SIZE(mlxplat_mlxcpld_wd_main_regs_type2),
|
||||
+ .identity = "mlx-wdt-main",
|
||||
+ },
|
||||
+ {
|
||||
+ .data = mlxplat_mlxcpld_wd_aux_regs_type2,
|
||||
+ .counter = ARRAY_SIZE(mlxplat_mlxcpld_wd_aux_regs_type2),
|
||||
+ .identity = "mlx-wdt-aux",
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
@@ -1362,6 +1510,14 @@ static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg)
|
||||
case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD_CLEAR_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD_CLEAR_WP_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD1_TMR_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD1_ACT_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD2_TMR_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD2_ACT_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET:
|
||||
return true;
|
||||
@@ -1404,6 +1560,14 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
|
||||
case MLXPLAT_CPLD_LPC_REG_FAN_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD_CLEAR_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD_CLEAR_WP_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD1_TMR_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD1_ACT_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD2_TMR_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD2_ACT_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET:
|
||||
@@ -1460,6 +1624,8 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg)
|
||||
case MLXPLAT_CPLD_LPC_REG_FAN_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD2_TMR_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET:
|
||||
@@ -1487,6 +1653,7 @@ static const struct reg_default mlxplat_mlxcpld_regmap_default[] = {
|
||||
{ MLXPLAT_CPLD_LPC_REG_WP1_OFFSET, 0x00 },
|
||||
{ MLXPLAT_CPLD_LPC_REG_WP2_OFFSET, 0x00 },
|
||||
{ MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, 0x00 },
|
||||
+ { MLXPLAT_CPLD_LPC_REG_WD_CLEAR_WP_OFFSET, 0x00 },
|
||||
};
|
||||
|
||||
struct mlxplat_mlxcpld_regmap_context {
|
||||
@@ -1536,6 +1703,8 @@ static struct mlxreg_core_hotplug_platform_data *mlxplat_hotplug;
|
||||
static struct mlxreg_core_platform_data *mlxplat_led;
|
||||
static struct mlxreg_core_platform_data *mlxplat_regs_io;
|
||||
static struct mlxreg_core_platform_data *mlxplat_fan;
|
||||
+static struct mlxreg_core_platform_data
|
||||
+ *mlxplat_wd_data[MLXPLAT_CPLD_WD_MAX_DEVS];
|
||||
|
||||
static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi)
|
||||
{
|
||||
@@ -1551,6 +1720,7 @@ static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi)
|
||||
mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
|
||||
mlxplat_led = &mlxplat_default_led_data;
|
||||
mlxplat_regs_io = &mlxplat_default_regs_io_data;
|
||||
+ mlxplat_wd_data[0] = &mlxplat_mlxcpld_wd_set_type1[0];
|
||||
|
||||
return 1;
|
||||
};
|
||||
@@ -1569,6 +1739,7 @@ static int __init mlxplat_dmi_msn21xx_matched(const struct dmi_system_id *dmi)
|
||||
mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
|
||||
mlxplat_led = &mlxplat_msn21xx_led_data;
|
||||
mlxplat_regs_io = &mlxplat_msn21xx_regs_io_data;
|
||||
+ mlxplat_wd_data[0] = &mlxplat_mlxcpld_wd_set_type1[0];
|
||||
|
||||
return 1;
|
||||
};
|
||||
@@ -1587,6 +1758,7 @@ static int __init mlxplat_dmi_msn274x_matched(const struct dmi_system_id *dmi)
|
||||
mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
|
||||
mlxplat_led = &mlxplat_default_led_data;
|
||||
mlxplat_regs_io = &mlxplat_msn21xx_regs_io_data;
|
||||
+ mlxplat_wd_data[0] = &mlxplat_mlxcpld_wd_set_type1[0];
|
||||
|
||||
return 1;
|
||||
};
|
||||
@@ -1605,6 +1777,7 @@ static int __init mlxplat_dmi_msn201x_matched(const struct dmi_system_id *dmi)
|
||||
mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
|
||||
mlxplat_led = &mlxplat_msn21xx_led_data;
|
||||
mlxplat_regs_io = &mlxplat_msn21xx_regs_io_data;
|
||||
+ mlxplat_wd_data[0] = &mlxplat_mlxcpld_wd_set_type1[0];
|
||||
|
||||
return 1;
|
||||
};
|
||||
@@ -1624,6 +1797,8 @@ static int __init mlxplat_dmi_qmb7xx_matched(const struct dmi_system_id *dmi)
|
||||
mlxplat_led = &mlxplat_default_ng_led_data;
|
||||
mlxplat_regs_io = &mlxplat_default_ng_regs_io_data;
|
||||
mlxplat_fan = &mlxplat_default_fan_data;
|
||||
+ for (i = 0; i < ARRAY_SIZE(mlxplat_mlxcpld_wd_set_type2); i++)
|
||||
+ mlxplat_wd_data[i] = &mlxplat_mlxcpld_wd_set_type2[i];
|
||||
|
||||
return 1;
|
||||
};
|
||||
@@ -1906,15 +2081,33 @@ static int __init mlxplat_init(void)
|
||||
}
|
||||
}
|
||||
|
||||
+ /* Add WD drivers. */
|
||||
+ for (j = 0; j < MLXPLAT_CPLD_WD_MAX_DEVS; j++) {
|
||||
+ if (mlxplat_wd_data[j]) {
|
||||
+ mlxplat_wd_data[j]->regmap = mlxplat_hotplug->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]);
|
||||
+ goto fail_platform_wd_register;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
/* Sync registers with hardware. */
|
||||
regcache_mark_dirty(mlxplat_hotplug->regmap);
|
||||
err = regcache_sync(mlxplat_hotplug->regmap);
|
||||
if (err)
|
||||
- goto fail_platform_fan_register;
|
||||
+ goto fail_platform_wd_register;
|
||||
|
||||
return 0;
|
||||
|
||||
-fail_platform_fan_register:
|
||||
+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:
|
||||
@@ -1946,7 +2139,10 @@ static void __exit mlxplat_exit(void)
|
||||
platform_device_unregister(priv->pdev_io_regs);
|
||||
platform_device_unregister(priv->pdev_led);
|
||||
platform_device_unregister(priv->pdev_hotplug);
|
||||
-
|
||||
+ for (i = MLXPLAT_CPLD_WD_MAX_DEVS - 1; i >= 0 ; i--) {
|
||||
+ if (mlxplat_wd_data[i])
|
||||
+ platform_device_unregister(priv->pdev_wd[i]);
|
||||
+ }
|
||||
for (i = ARRAY_SIZE(mlxplat_mux_data) - 1; i >= 0 ; i--)
|
||||
platform_device_unregister(priv->pdev_mux[i]);
|
||||
|
||||
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
|
||||
index 3eb58cb..ada5a33 100644
|
||||
--- a/drivers/watchdog/Kconfig
|
||||
+++ b/drivers/watchdog/Kconfig
|
||||
@@ -141,6 +141,21 @@ config MENF21BMC_WATCHDOG
|
||||
This driver can also be built as a module. If so the module
|
||||
will be called menf21bmc_wdt.
|
||||
|
||||
+config MLX_WDT
|
||||
+ tristate "Mellanox Watchdog"
|
||||
+ select WATCHDOG_CORE
|
||||
+ select REGMAP
|
||||
+ ---help---
|
||||
+ This is the driver for the hardware watchdog on Mellanox systems.
|
||||
+ If you are going to use it, say Y here, otherwise N.
|
||||
+ This driver can be used together with the watchdog daemon.
|
||||
+ It can also watch your kernel to make sure it doesn't freeze,
|
||||
+ and if it does, it reboots your system after a certain amount of
|
||||
+ time.
|
||||
+
|
||||
+ To compile this driver as a module, choose M here: the
|
||||
+ module will be called mlx-wdt.
|
||||
+
|
||||
config TANGOX_WATCHDOG
|
||||
tristate "Sigma Designs SMP86xx/SMP87xx watchdog"
|
||||
select WATCHDOG_CORE
|
||||
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
|
||||
index caa9f4a..50494df 100644
|
||||
--- a/drivers/watchdog/Makefile
|
||||
+++ b/drivers/watchdog/Makefile
|
||||
@@ -139,6 +139,7 @@ obj-$(CONFIG_INTEL_SCU_WATCHDOG) += intel_scu_watchdog.o
|
||||
obj-$(CONFIG_INTEL_MID_WATCHDOG) += intel-mid_wdt.o
|
||||
obj-$(CONFIG_INTEL_MEI_WDT) += mei_wdt.o
|
||||
obj-$(CONFIG_NI903X_WDT) += ni903x_wdt.o
|
||||
+obj-$(CONFIG_MLX_WDT) += mlx_wdt.o
|
||||
|
||||
# M32R Architecture
|
||||
|
||||
diff --git a/drivers/watchdog/mlx_wdt.c b/drivers/watchdog/mlx_wdt.c
|
||||
new file mode 100644
|
||||
index 0000000..7effe8c
|
||||
--- /dev/null
|
||||
+++ b/drivers/watchdog/mlx_wdt.c
|
||||
@@ -0,0 +1,391 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0+
|
||||
+/*
|
||||
+ * Mellanox watchdog driver
|
||||
+ *
|
||||
+ * Copyright (C) 2018 Mellanox Technologies
|
||||
+ * Copyright (C) 2018 Michael Shych <mshych@mellanox.com>
|
||||
+ */
|
||||
+
|
||||
+#include <linux/bitops.h>
|
||||
+#include <linux/device.h>
|
||||
+#include <linux/errno.h>
|
||||
+#include <linux/log2.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/platform_data/mlxreg.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/regmap.h>
|
||||
+#include <linux/spinlock.h>
|
||||
+#include <linux/types.h>
|
||||
+#include <linux/watchdog.h>
|
||||
+
|
||||
+#define MLXREG_WDT_CLOCK_SCALE 1000
|
||||
+#define MLXREG_WDT_MAX_TIMEOUT_TYPE1 32
|
||||
+#define MLXREG_WDT_MAX_TIMEOUT_TYPE2 255
|
||||
+#define MLXREG_WDT_MIN_TIMEOUT 1
|
||||
+#define MLXREG_WDT_HW_TIMEOUT_CONVERT(hw_timeout) ((1 << (hw_timeout)) \
|
||||
+ / MLXREG_WDT_CLOCK_SCALE)
|
||||
+
|
||||
+/**
|
||||
+ * enum mlxreg_wdt_type - type of HW watchdog
|
||||
+ *
|
||||
+ * TYPE1 can be differentiated by different register/mask
|
||||
+ * for WD action set and ping.
|
||||
+ */
|
||||
+enum mlxreg_wdt_type {
|
||||
+ MLX_WDT_TYPE1,
|
||||
+ MLX_WDT_TYPE2,
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * struct mlxreg_wdt - wd private data:
|
||||
+ *
|
||||
+ * @wdd: watchdog device;
|
||||
+ * @device: basic device;
|
||||
+ * @pdata: data received from platform driver;
|
||||
+ * @regmap: register map of parent device;
|
||||
+ * @timeout: defined timeout in sec.;
|
||||
+ * @hw_timeout: real timeout set in hw;
|
||||
+ * It will be roundup base of 2 in WD type 1,
|
||||
+ * in WD type 2 it will be same number of sec as timeout;
|
||||
+ * @action_idx: index for direct access to action register;
|
||||
+ * @timeout_idx:index for direct access to TO register;
|
||||
+ * @ping_idx: index for direct access to ping register;
|
||||
+ * @reset_idx: index for direct access to reset cause register;
|
||||
+ * @wd_type: watchdog HW type;
|
||||
+ * @hw_timeout: actual HW timeout;
|
||||
+ * @io_lock: spinlock for io access;
|
||||
+ */
|
||||
+struct mlxreg_wdt {
|
||||
+ struct watchdog_device wdd;
|
||||
+ struct mlxreg_core_platform_data *pdata;
|
||||
+ void *regmap;
|
||||
+ int action_idx;
|
||||
+ int timeout_idx;
|
||||
+ int ping_idx;
|
||||
+ int reset_idx;
|
||||
+ enum mlxreg_wdt_type wdt_type;
|
||||
+ u8 hw_timeout;
|
||||
+ spinlock_t io_lock; /* the lock for io operations */
|
||||
+};
|
||||
+
|
||||
+static int mlxreg_wdt_roundup_to_base_2(struct mlxreg_wdt *wdt, int timeout)
|
||||
+{
|
||||
+ timeout *= MLXREG_WDT_CLOCK_SCALE;
|
||||
+
|
||||
+ wdt->hw_timeout = order_base_2(timeout);
|
||||
+ dev_info(wdt->wdd.parent,
|
||||
+ "watchdog %s timeout %d was rounded up to %lu (msec)\n",
|
||||
+ wdt->wdd.info->identity, timeout, roundup_pow_of_two(timeout));
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static enum mlxreg_wdt_type
|
||||
+mlxreg_wdt_check_watchdog_type(struct mlxreg_wdt *wdt,
|
||||
+ struct mlxreg_core_platform_data *pdata)
|
||||
+{
|
||||
+ if ((pdata->data[wdt->action_idx].reg ==
|
||||
+ pdata->data[wdt->ping_idx].reg) &&
|
||||
+ (pdata->data[wdt->action_idx].mask ==
|
||||
+ pdata->data[wdt->ping_idx].mask))
|
||||
+ return MLX_WDT_TYPE2;
|
||||
+ else
|
||||
+ return MLX_WDT_TYPE1;
|
||||
+}
|
||||
+
|
||||
+static int mlxreg_wdt_check_card_reset(struct mlxreg_wdt *wdt)
|
||||
+{
|
||||
+ struct mlxreg_core_data *reg_data;
|
||||
+ u32 regval;
|
||||
+ int rc;
|
||||
+
|
||||
+ if (wdt->reset_idx == -EINVAL)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (!(wdt->wdd.info->options & WDIOF_CARDRESET))
|
||||
+ return 0;
|
||||
+
|
||||
+ spin_lock(&wdt->io_lock);
|
||||
+ reg_data = &wdt->pdata->data[wdt->reset_idx];
|
||||
+ rc = regmap_read(wdt->regmap, reg_data->reg, ®val);
|
||||
+ spin_unlock(&wdt->io_lock);
|
||||
+ if (rc)
|
||||
+ goto read_error;
|
||||
+
|
||||
+ if (regval & ~reg_data->mask) {
|
||||
+ wdt->wdd.bootstatus = WDIOF_CARDRESET;
|
||||
+ dev_info(wdt->wdd.parent,
|
||||
+ "watchdog previously reset the CPU\n");
|
||||
+ }
|
||||
+
|
||||
+read_error:
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static int mlxreg_wdt_start(struct watchdog_device *wdd)
|
||||
+{
|
||||
+ struct mlxreg_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||
+ struct mlxreg_core_data *reg_data = &wdt->pdata->data[wdt->action_idx];
|
||||
+ u32 regval;
|
||||
+ int rc;
|
||||
+
|
||||
+ spin_lock(&wdt->io_lock);
|
||||
+ rc = regmap_read(wdt->regmap, reg_data->reg, ®val);
|
||||
+ if (rc) {
|
||||
+ spin_unlock(&wdt->io_lock);
|
||||
+ goto read_error;
|
||||
+ }
|
||||
+
|
||||
+ regval = (regval & reg_data->mask) | BIT(reg_data->bit);
|
||||
+ rc = regmap_write(wdt->regmap, reg_data->reg, regval);
|
||||
+ spin_unlock(&wdt->io_lock);
|
||||
+ if (!rc) {
|
||||
+ set_bit(WDOG_HW_RUNNING, &wdt->wdd.status);
|
||||
+ dev_info(wdt->wdd.parent, "watchdog %s started\n",
|
||||
+ wdd->info->identity);
|
||||
+ }
|
||||
+
|
||||
+read_error:
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static int mlxreg_wdt_stop(struct watchdog_device *wdd)
|
||||
+{
|
||||
+ struct mlxreg_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||
+ struct mlxreg_core_data *reg_data = &wdt->pdata->data[wdt->action_idx];
|
||||
+ u32 regval;
|
||||
+ int rc;
|
||||
+
|
||||
+ spin_lock(&wdt->io_lock);
|
||||
+ rc = regmap_read(wdt->regmap, reg_data->reg, ®val);
|
||||
+ if (rc) {
|
||||
+ spin_unlock(&wdt->io_lock);
|
||||
+ goto read_error;
|
||||
+ }
|
||||
+
|
||||
+ regval = (regval & reg_data->mask) & ~BIT(reg_data->bit);
|
||||
+ rc = regmap_write(wdt->regmap, reg_data->reg, regval);
|
||||
+ spin_unlock(&wdt->io_lock);
|
||||
+ if (!rc)
|
||||
+ dev_info(wdt->wdd.parent, "watchdog %s stopped\n",
|
||||
+ wdd->info->identity);
|
||||
+
|
||||
+read_error:
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static int mlxreg_wdt_ping(struct watchdog_device *wdd)
|
||||
+{
|
||||
+ struct mlxreg_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||
+ struct mlxreg_core_data *reg_data = &wdt->pdata->data[wdt->ping_idx];
|
||||
+ u32 regval;
|
||||
+ int rc;
|
||||
+
|
||||
+ spin_lock(&wdt->io_lock);
|
||||
+ rc = regmap_read(wdt->regmap, reg_data->reg, ®val);
|
||||
+ if (rc)
|
||||
+ goto read_error;
|
||||
+
|
||||
+ regval = (regval & reg_data->mask) | BIT(reg_data->bit);
|
||||
+ rc = regmap_write(wdt->regmap, reg_data->reg, regval);
|
||||
+
|
||||
+read_error:
|
||||
+ spin_unlock(&wdt->io_lock);
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static int mlxreg_wdt_set_timeout(struct watchdog_device *wdd,
|
||||
+ unsigned int timeout)
|
||||
+{
|
||||
+ struct mlxreg_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||
+ struct mlxreg_core_data *reg_data = &wdt->pdata->data[wdt->timeout_idx];
|
||||
+ u32 regval;
|
||||
+ int rc;
|
||||
+
|
||||
+ spin_lock(&wdt->io_lock);
|
||||
+
|
||||
+ if (wdt->wdt_type == MLX_WDT_TYPE1) {
|
||||
+ rc = regmap_read(wdt->regmap, reg_data->reg, ®val);
|
||||
+ if (rc)
|
||||
+ goto read_error;
|
||||
+ regval = (regval & reg_data->mask) | wdt->hw_timeout;
|
||||
+ } else {
|
||||
+ wdt->hw_timeout = timeout;
|
||||
+ regval = timeout;
|
||||
+ }
|
||||
+
|
||||
+ rc = regmap_write(wdt->regmap, reg_data->reg, regval);
|
||||
+
|
||||
+read_error:
|
||||
+ spin_unlock(&wdt->io_lock);
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static unsigned int mlxreg_wdt_get_timeleft(struct watchdog_device *wdd)
|
||||
+{
|
||||
+ struct mlxreg_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||
+ struct mlxreg_core_data *reg_data = &wdt->pdata->data[wdt->timeout_idx];
|
||||
+ u32 regval;
|
||||
+ int rc;
|
||||
+
|
||||
+ if (wdt->wdt_type == MLX_WDT_TYPE1)
|
||||
+ return 0;
|
||||
+
|
||||
+ spin_lock(&wdt->io_lock);
|
||||
+ rc = regmap_read(wdt->regmap, reg_data->reg, ®val);
|
||||
+ if (rc)
|
||||
+ rc = 0;
|
||||
+ else
|
||||
+ rc = regval;
|
||||
+
|
||||
+ spin_unlock(&wdt->io_lock);
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static const struct watchdog_ops mlxreg_wdt_ops_type1 = {
|
||||
+ .start = mlxreg_wdt_start,
|
||||
+ .stop = mlxreg_wdt_stop,
|
||||
+ .ping = mlxreg_wdt_ping,
|
||||
+ .set_timeout = mlxreg_wdt_set_timeout,
|
||||
+ .owner = THIS_MODULE,
|
||||
+};
|
||||
+
|
||||
+static const struct watchdog_ops mlxreg_wdt_ops_type2 = {
|
||||
+ .start = mlxreg_wdt_start,
|
||||
+ .stop = mlxreg_wdt_stop,
|
||||
+ .ping = mlxreg_wdt_ping,
|
||||
+ .set_timeout = mlxreg_wdt_set_timeout,
|
||||
+ .get_timeleft = mlxreg_wdt_get_timeleft,
|
||||
+ .owner = THIS_MODULE,
|
||||
+};
|
||||
+
|
||||
+static const struct watchdog_info mlxreg_wdt_main_info = {
|
||||
+ .options = WDIOF_KEEPALIVEPING
|
||||
+ | WDIOF_MAGICCLOSE
|
||||
+ | WDIOF_SETTIMEOUT
|
||||
+ | WDIOF_CARDRESET,
|
||||
+ .identity = "mlx-wdt-main",
|
||||
+};
|
||||
+
|
||||
+static const struct watchdog_info mlxreg_wdt_aux_info = {
|
||||
+ .options = WDIOF_KEEPALIVEPING
|
||||
+ | WDIOF_MAGICCLOSE
|
||||
+ | WDIOF_SETTIMEOUT
|
||||
+ | WDIOF_ALARMONLY,
|
||||
+ .identity = "mlx-wdt-aux",
|
||||
+};
|
||||
+
|
||||
+static int mlxreg_wdt_config(struct mlxreg_wdt *wdt,
|
||||
+ struct mlxreg_core_platform_data *pdata)
|
||||
+{
|
||||
+ struct mlxreg_core_data *data = pdata->data;
|
||||
+ int i, timeout;
|
||||
+
|
||||
+ wdt->reset_idx = -EINVAL;
|
||||
+ for (i = 0; i < pdata->counter; i++, data++) {
|
||||
+ if (strnstr(data->label, "action", sizeof(data->label)))
|
||||
+ wdt->action_idx = i;
|
||||
+ else if (strnstr(data->label, "timeout", sizeof(data->label)))
|
||||
+ wdt->timeout_idx = i;
|
||||
+ else if (strnstr(data->label, "ping", sizeof(data->label)))
|
||||
+ wdt->ping_idx = i;
|
||||
+ else if (strnstr(data->label, "reset", sizeof(data->label)))
|
||||
+ wdt->reset_idx = i;
|
||||
+ }
|
||||
+
|
||||
+ wdt->pdata = pdata;
|
||||
+ if (strnstr(pdata->identity, mlxreg_wdt_main_info.identity,
|
||||
+ sizeof(mlxreg_wdt_main_info.identity)))
|
||||
+ wdt->wdd.info = &mlxreg_wdt_main_info;
|
||||
+ else
|
||||
+ wdt->wdd.info = &mlxreg_wdt_aux_info;
|
||||
+
|
||||
+ timeout = pdata->data[wdt->timeout_idx].health_cntr;
|
||||
+ wdt->wdt_type = mlxreg_wdt_check_watchdog_type(wdt, pdata);
|
||||
+ if (wdt->wdt_type == MLX_WDT_TYPE2) {
|
||||
+ wdt->hw_timeout = timeout;
|
||||
+ wdt->wdd.ops = &mlxreg_wdt_ops_type2;
|
||||
+ wdt->wdd.timeout = wdt->hw_timeout;
|
||||
+ wdt->wdd.max_timeout = MLXREG_WDT_MAX_TIMEOUT_TYPE2;
|
||||
+ } else {
|
||||
+ mlxreg_wdt_roundup_to_base_2(wdt, timeout);
|
||||
+ wdt->wdd.ops = &mlxreg_wdt_ops_type1;
|
||||
+ /* Rowndown to actual closest number of sec. */
|
||||
+ wdt->wdd.timeout =
|
||||
+ MLXREG_WDT_HW_TIMEOUT_CONVERT(wdt->hw_timeout);
|
||||
+ wdt->wdd.max_timeout = MLXREG_WDT_MAX_TIMEOUT_TYPE1;
|
||||
+ }
|
||||
+ wdt->wdd.min_timeout = MLXREG_WDT_MIN_TIMEOUT;
|
||||
+
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
+static int mlxreg_wdt_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct mlxreg_core_platform_data *pdata;
|
||||
+ struct mlxreg_wdt *wdt;
|
||||
+ int rc;
|
||||
+
|
||||
+ pdata = dev_get_platdata(&pdev->dev);
|
||||
+ if (!pdata) {
|
||||
+ dev_err(&pdev->dev, "Failed to get platform data.\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
|
||||
+ if (!wdt)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ spin_lock_init(&wdt->io_lock);
|
||||
+
|
||||
+ wdt->wdd.parent = &pdev->dev;
|
||||
+ wdt->regmap = pdata->regmap;
|
||||
+ mlxreg_wdt_config(wdt, pdata);
|
||||
+
|
||||
+ if ((pdata->features & MLXREG_CORE_WD_FEATURE_NOSTOP_AFTER_START))
|
||||
+ watchdog_set_nowayout(&wdt->wdd, WATCHDOG_NOWAYOUT);
|
||||
+ watchdog_stop_on_reboot(&wdt->wdd);
|
||||
+ watchdog_init_timeout(&wdt->wdd, 0, &pdev->dev);
|
||||
+ watchdog_set_drvdata(&wdt->wdd, wdt);
|
||||
+
|
||||
+ mlxreg_wdt_check_card_reset(wdt);
|
||||
+ rc = devm_watchdog_register_device(&pdev->dev, &wdt->wdd);
|
||||
+ if (rc) {
|
||||
+ dev_err(&pdev->dev,
|
||||
+ "Cannot register watchdog device (err=%d)\n", rc);
|
||||
+ return rc;
|
||||
+ }
|
||||
+
|
||||
+ mlxreg_wdt_set_timeout(&wdt->wdd, wdt->wdd.timeout);
|
||||
+ if ((pdata->features & MLXREG_CORE_WD_FEATURE_START_AT_BOOT))
|
||||
+ mlxreg_wdt_start(&wdt->wdd);
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static int mlxreg_wdt_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct mlxreg_wdt *wdt = dev_get_platdata(&pdev->dev);
|
||||
+
|
||||
+ mlxreg_wdt_stop(&wdt->wdd);
|
||||
+ watchdog_unregister_device(&wdt->wdd);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct platform_driver mlxreg_wdt_driver = {
|
||||
+ .probe = mlxreg_wdt_probe,
|
||||
+ .remove = mlxreg_wdt_remove,
|
||||
+ .driver = {
|
||||
+ .name = "mlx-wdt",
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+module_platform_driver(mlxreg_wdt_driver);
|
||||
+
|
||||
+MODULE_AUTHOR("Michael Shych <michaelsh@mellanox.com>");
|
||||
+MODULE_DESCRIPTION("Mellanox watchdog driver");
|
||||
+MODULE_LICENSE("GPL");
|
||||
+MODULE_ALIAS("platform:mlx-wdt");
|
||||
diff --git a/include/linux/platform_data/mlxreg.h b/include/linux/platform_data/mlxreg.h
|
||||
index 1b2f86f..4d70c00 100644
|
||||
--- a/include/linux/platform_data/mlxreg.h
|
||||
+++ b/include/linux/platform_data/mlxreg.h
|
||||
@@ -35,6 +35,8 @@
|
||||
#define __LINUX_PLATFORM_DATA_MLXREG_H
|
||||
|
||||
#define MLXREG_CORE_LABEL_MAX_SIZE 32
|
||||
+#define MLXREG_CORE_WD_FEATURE_NOSTOP_AFTER_START BIT(0)
|
||||
+#define MLXREG_CORE_WD_FEATURE_START_AT_BOOT BIT(1)
|
||||
|
||||
/**
|
||||
* struct mlxreg_hotplug_device - I2C device data:
|
||||
@@ -112,11 +114,15 @@ struct mlxreg_core_item {
|
||||
* @data: instance private data;
|
||||
* @regmap: register map of parent device;
|
||||
* @counter: number of instances;
|
||||
+ * @features: supported features of device;
|
||||
+ * @identity: device identity name;
|
||||
*/
|
||||
struct mlxreg_core_platform_data {
|
||||
struct mlxreg_core_data *data;
|
||||
void *regmap;
|
||||
int counter;
|
||||
+ u32 features;
|
||||
+ char identity[MLXREG_CORE_LABEL_MAX_SIZE];
|
||||
};
|
||||
|
||||
/**
|
||||
--
|
||||
2.1.4
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
From 81443e4927ec84223f8305e0e4cec647521856e4 Mon Sep 17 00:00:00 2001
|
||||
From: Vadim Pasternak <vadimp@mellanox.com>
|
||||
Date: Mon, 21 Jan 2019 14:54:58 +0000
|
||||
Subject: [PATCH hwmon] hwmon: (pmbus) Fix driver info initialization in probe
|
||||
routine
|
||||
|
||||
Fix tps53679_probe() by using dynamically allocated ?pmbus_driver_info?
|
||||
structure instead of static. Usage of static structures causes
|
||||
overwritten of the field ?vrm_version? - when the number of tps53679
|
||||
devices with the different ?vrm_version? are used within the same
|
||||
system, the last probed device overwrites this field for all others.
|
||||
|
||||
Fixes: 610526527a13e4c9 ("hwmon: (pmbus) Add support for Texas Instruments tps53679 device")
|
||||
Signed-off-by: Vadim Pasternak <vadimp@mellanox.com>
|
||||
---
|
||||
drivers/hwmon/pmbus/tps53679.c | 10 +++++++++-
|
||||
1 file changed, 9 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/hwmon/pmbus/tps53679.c b/drivers/hwmon/pmbus/tps53679.c
|
||||
index 85b515c..45eacc5 100644
|
||||
--- a/drivers/hwmon/pmbus/tps53679.c
|
||||
+++ b/drivers/hwmon/pmbus/tps53679.c
|
||||
@@ -80,7 +80,15 @@ static struct pmbus_driver_info tps53679_info = {
|
||||
static int tps53679_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
- return pmbus_do_probe(client, id, &tps53679_info);
|
||||
+ struct pmbus_driver_info *info;
|
||||
+
|
||||
+ info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL);
|
||||
+ if (!info)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ memcpy(info, &tps53679_info, sizeof(*info));
|
||||
+
|
||||
+ return pmbus_do_probe(client, id, info);
|
||||
}
|
||||
|
||||
static const struct i2c_device_id tps53679_id[] = {
|
||||
--
|
||||
2.1.4
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
From 5da6a599af1072f278b5f41ed648bed2142d42f0 Mon Sep 17 00:00:00 2001
|
||||
From: Vadim Pasternak <vadimp@mellanox.com>
|
||||
Date: Mon, 21 Jan 2019 19:13:29 +0000
|
||||
Subject: [PATCH mlxsw] mlxsw thermal: disable highest zone calculation
|
||||
|
||||
Signed-off-by: Vadim Pasternak <vadimp@mellanox.com>
|
||||
---
|
||||
drivers/net/ethernet/mellanox/mlxsw/core_thermal.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
|
||||
index 444455c..0a2e7a2 100644
|
||||
--- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
|
||||
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
|
||||
@@ -433,7 +433,7 @@ static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev,
|
||||
return err;
|
||||
}
|
||||
mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL);
|
||||
-
|
||||
+#if 0
|
||||
if (thermal->tz_module_arr) {
|
||||
err = mlxsw_thermal_highest_tz_notify(dev, tzdev, thermal,
|
||||
thermal->tz_module_num,
|
||||
@@ -441,7 +441,7 @@ static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev,
|
||||
if (err)
|
||||
dev_err(dev, "Failed to query module temp sensor\n");
|
||||
}
|
||||
-
|
||||
+#endif
|
||||
*p_temp = (int) temp;
|
||||
return 0;
|
||||
}
|
||||
--
|
||||
2.1.4
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
From 87859cbda6affc45fc8d513c12eb4318e2c81073 Mon Sep 17 00:00:00 2001
|
||||
From: Vadim Pasternak <vadimp@mellanox.com>
|
||||
Date: Thu, 24 Jan 2019 09:58:23 +0000
|
||||
Subject: [PATCH platform] platform/x86: mlx-platform: Add CPLD4 register
|
||||
|
||||
Signed-off-by: <Vadim Pasternal vadimp@mellanox.com>
|
||||
---
|
||||
drivers/platform/x86/mlx-platform.c | 11 ++++++++++-
|
||||
1 file changed, 10 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c
|
||||
index fc8d655..a80b968 100644
|
||||
--- a/drivers/platform/x86/mlx-platform.c
|
||||
+++ b/drivers/platform/x86/mlx-platform.c
|
||||
@@ -25,6 +25,7 @@
|
||||
#define MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET 0x00
|
||||
#define MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET 0x01
|
||||
#define MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET 0x02
|
||||
+#define MLXPLAT_CPLD_LPC_REG_CPLD4_VER_OFFSET 0x03
|
||||
#define MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET 0x1d
|
||||
#define MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET 0x1e
|
||||
#define MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET 0x1f
|
||||
@@ -1163,6 +1164,12 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = {
|
||||
.mode = 0444,
|
||||
},
|
||||
{
|
||||
+ .label = "cpld4_version",
|
||||
+ .reg = MLXPLAT_CPLD_LPC_REG_CPLD4_VER_OFFSET,
|
||||
+ .bit = GENMASK(7, 0),
|
||||
+ .mode = 0444,
|
||||
+ },
|
||||
+ {
|
||||
.label = "reset_long_pb",
|
||||
.reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
|
||||
.mask = GENMASK(7, 0) & ~BIT(0),
|
||||
@@ -1251,7 +1258,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = {
|
||||
.label = "fan_dir",
|
||||
.reg = MLXPLAT_CPLD_LPC_REG_FAN_DIRECTION,
|
||||
.bit = GENMASK(7, 0),
|
||||
- .mode = 0200,
|
||||
+ .mode = 0444,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1531,6 +1538,7 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
|
||||
case MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_CPLD4_VER_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET:
|
||||
@@ -1597,6 +1605,7 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg)
|
||||
case MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_CPLD3_VER_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_CPLD4_VER_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_RST_CAUSE1_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_RST_CAUSE2_OFFSET:
|
||||
--
|
||||
2.1.4
|
||||
|
||||
@@ -0,0 +1,564 @@
|
||||
From 4df1b8e3a873293a8ad59afe276bb4a48dd2f613 Mon Sep 17 00:00:00 2001
|
||||
From: Vadim Pasternak <vadimp@mellanox.com>
|
||||
Date: Mon, 25 Feb 2019 07:18:14 +0000
|
||||
Subject: [PATCH backport 5.1] mlxsw-Align-code-with-kernel-v-5.1.patch
|
||||
|
||||
Add latest hwmon and thermal ASIC modules amendments.
|
||||
|
||||
Fix LED driver.
|
||||
|
||||
Signed-off-by: Vadim Pasternak <vadimp@mellanox.com>
|
||||
---
|
||||
drivers/leds/leds-mlxreg.c | 21 ++-
|
||||
drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c | 8 +-
|
||||
drivers/net/ethernet/mellanox/mlxsw/core_thermal.c | 168 +--------------------
|
||||
drivers/net/ethernet/mellanox/mlxsw/i2c.c | 10 +-
|
||||
drivers/net/ethernet/mellanox/mlxsw/minimal.c | 85 ++++++-----
|
||||
5 files changed, 77 insertions(+), 215 deletions(-)
|
||||
|
||||
diff --git a/drivers/leds/leds-mlxreg.c b/drivers/leds/leds-mlxreg.c
|
||||
index 2db200075cfc..0c14a7406c6e 100644
|
||||
--- a/drivers/leds/leds-mlxreg.c
|
||||
+++ b/drivers/leds/leds-mlxreg.c
|
||||
@@ -22,6 +22,7 @@
|
||||
#define MLXREG_LED_AMBER_SOLID 0x09 /* Solid amber */
|
||||
#define MLXREG_LED_BLINK_3HZ 167 /* ~167 msec off/on - HW support */
|
||||
#define MLXREG_LED_BLINK_6HZ 83 /* ~83 msec off/on - HW support */
|
||||
+#define MLXREG_LED_CAPABILITY_CLEAR GENMASK(31, 8) /* Clear mask */
|
||||
|
||||
/**
|
||||
* struct mlxreg_led_data - led control data:
|
||||
@@ -100,7 +101,7 @@ mlxreg_led_get_hw(struct mlxreg_led_data *led_data)
|
||||
struct mlxreg_core_platform_data *led_pdata = priv->pdata;
|
||||
struct mlxreg_core_data *data = led_data->data;
|
||||
u32 regval;
|
||||
- int ret;
|
||||
+ int err;
|
||||
|
||||
/*
|
||||
* Each LED is controlled through low or high nibble of the relevant
|
||||
@@ -112,10 +113,10 @@ mlxreg_led_get_hw(struct mlxreg_led_data *led_data)
|
||||
* 0xf0 - lower nibble is to be used (bits from 0 to 3), mask 0x0f -
|
||||
* higher nibble (bits from 4 to 7).
|
||||
*/
|
||||
- ret = regmap_read(led_pdata->regmap, data->reg, ®val);
|
||||
- if (ret < 0) {
|
||||
+ err = regmap_read(led_pdata->regmap, data->reg, ®val);
|
||||
+ if (err < 0) {
|
||||
dev_warn(led_data->led_cdev.dev, "Failed to get current brightness, error: %d\n",
|
||||
- ret);
|
||||
+ err);
|
||||
/* Assume the LED is OFF */
|
||||
return LED_OFF;
|
||||
}
|
||||
@@ -125,11 +126,9 @@ mlxreg_led_get_hw(struct mlxreg_led_data *led_data)
|
||||
data->bit) : ror32(regval, data->bit + 4);
|
||||
if (regval >= led_data->base_color &&
|
||||
regval <= (led_data->base_color + MLXREG_LED_OFFSET_BLINK_6HZ))
|
||||
- ret = LED_FULL;
|
||||
- else
|
||||
- ret = LED_OFF;
|
||||
+ return LED_FULL;
|
||||
|
||||
- return ret;
|
||||
+ return LED_OFF;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -208,6 +207,12 @@ static int mlxreg_led_config(struct mlxreg_led_priv_data *priv)
|
||||
}
|
||||
if (!(regval & data->bit))
|
||||
continue;
|
||||
+ /*
|
||||
+ * Field "bit" can contain one capability bit in 0 byte
|
||||
+ * and offset bit in 1-3 bytes. Clear capability bit and
|
||||
+ * keep only offset bit.
|
||||
+ */
|
||||
+ data->bit &= MLXREG_LED_CAPABILITY_CLEAR;
|
||||
}
|
||||
|
||||
led_cdev = &led_data->led_cdev;
|
||||
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c
|
||||
index f1ada4cdbd6b..6956bbebe2f1 100644
|
||||
--- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c
|
||||
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c
|
||||
@@ -208,7 +208,7 @@ static ssize_t mlxsw_hwmon_module_temp_show(struct device *dev,
|
||||
1);
|
||||
err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtbr), mtbr_pl);
|
||||
if (err) {
|
||||
- dev_err(dev, "Failed to query module temprature sensor\n");
|
||||
+ dev_err(dev, "Failed to query module temperature sensor\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -251,7 +251,7 @@ static ssize_t mlxsw_hwmon_module_temp_fault_show(struct device *dev,
|
||||
1);
|
||||
err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtbr), mtbr_pl);
|
||||
if (err) {
|
||||
- dev_err(dev, "Failed to query module temprature sensor\n");
|
||||
+ dev_err(dev, "Failed to query module temperature sensor\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -291,7 +291,7 @@ mlxsw_hwmon_module_temp_critical_show(struct device *dev,
|
||||
err = mlxsw_env_module_temp_thresholds_get(mlxsw_hwmon->core, module,
|
||||
SFP_TEMP_HIGH_WARN, &temp);
|
||||
if (err) {
|
||||
- dev_err(dev, "Failed to query module temprature thresholds\n");
|
||||
+ dev_err(dev, "Failed to query module temperature thresholds\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -314,7 +314,7 @@ mlxsw_hwmon_module_temp_emergency_show(struct device *dev,
|
||||
err = mlxsw_env_module_temp_thresholds_get(mlxsw_hwmon->core, module,
|
||||
SFP_TEMP_HIGH_ALARM, &temp);
|
||||
if (err) {
|
||||
- dev_err(dev, "Failed to query module temprature thresholds\n");
|
||||
+ dev_err(dev, "Failed to query module temperature thresholds\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
|
||||
index 0a2e7a2f1569..002654918ee9 100644
|
||||
--- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
|
||||
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
|
||||
@@ -23,7 +23,6 @@
|
||||
#define MLXSW_THERMAL_HYSTERESIS_TEMP 5000 /* 5C */
|
||||
#define MLXSW_THERMAL_MODULE_TEMP_SHIFT (MLXSW_THERMAL_HYSTERESIS_TEMP * 2)
|
||||
#define MLXSW_THERMAL_ZONE_MAX_NAME 16
|
||||
-#define MLXSW_THERMAL_TEMP_SCORE_MAX 0xffffffff
|
||||
#define MLXSW_THERMAL_MAX_STATE 10
|
||||
#define MLXSW_THERMAL_MAX_DUTY 255
|
||||
/* Minimum and maximum fan allowed speed in percent: from 20% to 100%. Values
|
||||
@@ -113,8 +112,6 @@ struct mlxsw_thermal {
|
||||
enum thermal_device_mode mode;
|
||||
struct mlxsw_thermal_module *tz_module_arr;
|
||||
unsigned int tz_module_num;
|
||||
- int tz_highest;
|
||||
- struct mutex tz_update_lock;
|
||||
};
|
||||
|
||||
static inline u8 mlxsw_state_to_duty(int state)
|
||||
@@ -179,7 +176,7 @@ mlxsw_thermal_module_trips_update(struct device *dev, struct mlxsw_core *core,
|
||||
/* According to the system thermal requirements, the thermal zones are
|
||||
* defined with four trip points. The critical and emergency
|
||||
* temperature thresholds, provided by QSFP module are set as "active"
|
||||
- * and "hot" trip points, "normal" and "critical" trip points ar
|
||||
+ * and "hot" trip points, "normal" and "critical" trip points are
|
||||
* derived from "active" and "hot" by subtracting or adding double
|
||||
* hysteresis value.
|
||||
*/
|
||||
@@ -199,140 +196,6 @@ mlxsw_thermal_module_trips_update(struct device *dev, struct mlxsw_core *core,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static void mlxsw_thermal_tz_score_get(struct mlxsw_thermal_trip *trips,
|
||||
- int temp, int *score)
|
||||
-{
|
||||
- struct mlxsw_thermal_trip *trip = trips;
|
||||
- int delta, i, shift = 1;
|
||||
-
|
||||
- /* Calculate thermal zone score, if temperature is above the critical
|
||||
- * threshold score is set to MLXSW_THERMAL_TEMP_SCORE_MAX.
|
||||
- */
|
||||
- *score = MLXSW_THERMAL_TEMP_SCORE_MAX;
|
||||
- for (i = MLXSW_THERMAL_TEMP_TRIP_NORM; i < MLXSW_THERMAL_NUM_TRIPS;
|
||||
- i++, trip++) {
|
||||
- if (temp < trip->temp) {
|
||||
- delta = DIV_ROUND_CLOSEST(temp, trip->temp - temp);
|
||||
- *score = delta * shift;
|
||||
- break;
|
||||
- }
|
||||
- shift *= 256;
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-static int
|
||||
-mlxsw_thermal_highest_tz_get(struct device *dev, struct mlxsw_thermal *thermal,
|
||||
- int module_count, unsigned int seed_temp,
|
||||
- int *max_tz, int *max_score)
|
||||
-{
|
||||
- char mtbr_pl[MLXSW_REG_MTBR_LEN];
|
||||
- struct mlxsw_thermal_module *tz;
|
||||
- int i, j, index, off, score;
|
||||
- u16 temp;
|
||||
- int err;
|
||||
-
|
||||
- mlxsw_thermal_tz_score_get(thermal->trips, seed_temp, max_score);
|
||||
- /* Read modules temperature. */
|
||||
- index = 0;
|
||||
- while (index < module_count) {
|
||||
- off = min_t(u8, MLXSW_REG_MTBR_REC_MAX_COUNT,
|
||||
- module_count - index);
|
||||
- mlxsw_reg_mtbr_pack(mtbr_pl, MLXSW_REG_MTBR_BASE_MODULE_INDEX +
|
||||
- index, off);
|
||||
- err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtbr), mtbr_pl);
|
||||
- if (err) {
|
||||
- dev_err(dev, "Failed to get temp from index %d\n",
|
||||
- off);
|
||||
- return err;
|
||||
- }
|
||||
-
|
||||
- for (i = 0, j = index; i < off; i++, j++) {
|
||||
- mlxsw_reg_mtbr_temp_unpack(mtbr_pl, i, &temp, NULL);
|
||||
- /* Update status and temperature cache. */
|
||||
- switch (temp) {
|
||||
- case MLXSW_REG_MTBR_NO_CONN: /* fall-through */
|
||||
- case MLXSW_REG_MTBR_NO_TEMP_SENS: /* fall-through */
|
||||
- case MLXSW_REG_MTBR_INDEX_NA: /* fall-through */
|
||||
- case MLXSW_REG_MTBR_BAD_SENS_INFO:
|
||||
- temp = 0;
|
||||
- break;
|
||||
- default:
|
||||
- tz = &thermal->tz_module_arr[j];
|
||||
- if (!tz)
|
||||
- break;
|
||||
- /* Reset all trip point. */
|
||||
- mlxsw_thermal_module_trips_reset(tz);
|
||||
- temp = MLXSW_REG_MTMP_TEMP_TO_MC(temp);
|
||||
- /* Do not consider zero temperature. */
|
||||
- if (!temp)
|
||||
- break;
|
||||
-
|
||||
- err = mlxsw_thermal_module_trips_update(dev,
|
||||
- thermal->core,
|
||||
- tz);
|
||||
- if (err) {
|
||||
- dev_err(dev, "Failed to update trips for %s\n",
|
||||
- tz->tzdev->type);
|
||||
- return err;
|
||||
- }
|
||||
-
|
||||
- score = 0;
|
||||
- mlxsw_thermal_tz_score_get(tz->trips, temp,
|
||||
- &score);
|
||||
- if (score > *max_score) {
|
||||
- *max_score = score;
|
||||
- *max_tz = j + 1;
|
||||
- }
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
- index += off;
|
||||
- }
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static int
|
||||
-mlxsw_thermal_highest_tz_notify(struct device *dev,
|
||||
- struct thermal_zone_device *tzdev,
|
||||
- struct mlxsw_thermal *thermal,
|
||||
- int module_count, unsigned int temp)
|
||||
-{
|
||||
- char env_record[24];
|
||||
- char *envp[2] = { env_record, NULL };
|
||||
- struct mlxsw_thermal_module *tz_module;
|
||||
- struct thermal_zone_device *tz;
|
||||
- int max_tz = 0, max_score = 0;
|
||||
- int err;
|
||||
-
|
||||
- err = mlxsw_thermal_highest_tz_get(dev, thermal,
|
||||
- thermal->tz_module_num, temp,
|
||||
- &max_tz, &max_score);
|
||||
- if (err) {
|
||||
- dev_err(dev, "Failed to query module temp sensor\n");
|
||||
- return err;
|
||||
- }
|
||||
-
|
||||
- if (thermal->tz_highest != max_tz) {
|
||||
- sprintf(env_record, "TZ_HIGHEST==%u", max_score);
|
||||
- if (max_tz && (&thermal->tz_module_arr[max_tz - 1])) {
|
||||
- tz_module = &thermal->tz_module_arr[max_tz - 1];
|
||||
- tz = tz_module->tzdev;
|
||||
- err = kobject_uevent_env(&tz->device.kobj, KOBJ_CHANGE,
|
||||
- envp);
|
||||
- } else {
|
||||
- err = kobject_uevent_env(&tzdev->device.kobj,
|
||||
- KOBJ_CHANGE, envp);
|
||||
- }
|
||||
- if (err)
|
||||
- dev_err(dev, "Error sending uevent %s\n", envp[0]);
|
||||
- else
|
||||
- thermal->tz_highest = max_tz;
|
||||
- }
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
static int mlxsw_thermal_bind(struct thermal_zone_device *tzdev,
|
||||
struct thermal_cooling_device *cdev)
|
||||
{
|
||||
@@ -398,20 +261,15 @@ static int mlxsw_thermal_set_mode(struct thermal_zone_device *tzdev,
|
||||
|
||||
mutex_lock(&tzdev->lock);
|
||||
|
||||
- if (mode == THERMAL_DEVICE_ENABLED) {
|
||||
- thermal->tz_highest = 0;
|
||||
+ if (mode == THERMAL_DEVICE_ENABLED)
|
||||
tzdev->polling_delay = thermal->polling_delay;
|
||||
- } else {
|
||||
+ else
|
||||
tzdev->polling_delay = 0;
|
||||
- }
|
||||
|
||||
mutex_unlock(&tzdev->lock);
|
||||
|
||||
thermal->mode = mode;
|
||||
-
|
||||
- mutex_lock(&thermal->tz_update_lock);
|
||||
thermal_zone_device_update(tzdev, THERMAL_EVENT_UNSPECIFIED);
|
||||
- mutex_unlock(&thermal->tz_update_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -433,15 +291,7 @@ static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev,
|
||||
return err;
|
||||
}
|
||||
mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL);
|
||||
-#if 0
|
||||
- if (thermal->tz_module_arr) {
|
||||
- err = mlxsw_thermal_highest_tz_notify(dev, tzdev, thermal,
|
||||
- thermal->tz_module_num,
|
||||
- temp);
|
||||
- if (err)
|
||||
- dev_err(dev, "Failed to query module temp sensor\n");
|
||||
- }
|
||||
-#endif
|
||||
+
|
||||
*p_temp = (int) temp;
|
||||
return 0;
|
||||
}
|
||||
@@ -589,10 +439,7 @@ static int mlxsw_thermal_module_mode_set(struct thermal_zone_device *tzdev,
|
||||
mutex_unlock(&tzdev->lock);
|
||||
|
||||
tz->mode = mode;
|
||||
-
|
||||
- mutex_lock(&thermal->tz_update_lock);
|
||||
thermal_zone_device_update(tzdev, THERMAL_EVENT_UNSPECIFIED);
|
||||
- mutex_unlock(&thermal->tz_update_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -993,7 +840,6 @@ int mlxsw_thermal_init(struct mlxsw_core *core,
|
||||
|
||||
thermal->core = core;
|
||||
thermal->bus_info = bus_info;
|
||||
- mutex_init(&thermal->tz_update_lock);
|
||||
memcpy(thermal->trips, default_thermal_trips, sizeof(thermal->trips));
|
||||
|
||||
err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfcr), mfcr_pl);
|
||||
@@ -1028,8 +874,8 @@ int mlxsw_thermal_init(struct mlxsw_core *core,
|
||||
struct thermal_cooling_device *cdev;
|
||||
|
||||
cdev = thermal_cooling_device_register("mlxsw_fan",
|
||||
- thermal,
|
||||
- &mlxsw_cooling_ops);
|
||||
+ thermal,
|
||||
+ &mlxsw_cooling_ops);
|
||||
if (IS_ERR(cdev)) {
|
||||
err = PTR_ERR(cdev);
|
||||
dev_err(dev, "Failed to register cooling device\n");
|
||||
@@ -1069,6 +915,8 @@ int mlxsw_thermal_init(struct mlxsw_core *core,
|
||||
*p_thermal = thermal;
|
||||
return 0;
|
||||
|
||||
+err_unreg_modules_tzdev:
|
||||
+ mlxsw_thermal_modules_fini(thermal);
|
||||
err_unreg_tzdev:
|
||||
if (thermal->tzdev) {
|
||||
thermal_zone_device_unregister(thermal->tzdev);
|
||||
diff --git a/drivers/net/ethernet/mellanox/mlxsw/i2c.c b/drivers/net/ethernet/mellanox/mlxsw/i2c.c
|
||||
index b1471c2b6af2..307fd5fcd302 100644
|
||||
--- a/drivers/net/ethernet/mellanox/mlxsw/i2c.c
|
||||
+++ b/drivers/net/ethernet/mellanox/mlxsw/i2c.c
|
||||
@@ -399,7 +399,10 @@ mlxsw_i2c_cmd(struct device *dev, u16 opcode, u32 in_mod, size_t in_mbox_size,
|
||||
if (reg_size % MLXSW_I2C_BLK_MAX)
|
||||
num++;
|
||||
|
||||
- mutex_lock(&mlxsw_i2c->cmd.lock);
|
||||
+ if (mutex_lock_interruptible(&mlxsw_i2c->cmd.lock) < 0) {
|
||||
+ dev_err(&client->dev, "Could not acquire lock");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
|
||||
err = mlxsw_i2c_write(dev, reg_size, in_mbox, num, status);
|
||||
if (err)
|
||||
@@ -415,7 +418,10 @@ mlxsw_i2c_cmd(struct device *dev, u16 opcode, u32 in_mod, size_t in_mbox_size,
|
||||
reg_size = MLXSW_I2C_MAX_DATA_SIZE;
|
||||
num = reg_size / MLXSW_I2C_BLK_MAX;
|
||||
|
||||
- mutex_lock(&mlxsw_i2c->cmd.lock);
|
||||
+ if (mutex_lock_interruptible(&mlxsw_i2c->cmd.lock) < 0) {
|
||||
+ dev_err(&client->dev, "Could not acquire lock");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
|
||||
err = mlxsw_i2c_write_init_cmd(client, mlxsw_i2c, opcode,
|
||||
in_mod);
|
||||
diff --git a/drivers/net/ethernet/mellanox/mlxsw/minimal.c b/drivers/net/ethernet/mellanox/mlxsw/minimal.c
|
||||
index 9312f42c8f9b..740b3753de44 100644
|
||||
--- a/drivers/net/ethernet/mellanox/mlxsw/minimal.c
|
||||
+++ b/drivers/net/ethernet/mellanox/mlxsw/minimal.c
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
|
||||
-/* Copyright (c) 2016-2018 Mellanox Technologies. All rights reserved */
|
||||
+/* Copyright (c) 2016-2019 Mellanox Technologies. All rights reserved */
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
@@ -50,11 +50,8 @@ 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;
|
||||
- int err;
|
||||
-
|
||||
- err = mlxsw_env_get_module_info(core, mlxsw_m_port->module, modinfo);
|
||||
|
||||
- return err;
|
||||
+ return mlxsw_env_get_module_info(core, mlxsw_m_port->module, modinfo);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -63,12 +60,9 @@ 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;
|
||||
- int err;
|
||||
-
|
||||
- err = mlxsw_env_get_module_eeprom(netdev, core,
|
||||
- mlxsw_m_port->module, ee, data);
|
||||
|
||||
- return err;
|
||||
+ return mlxsw_env_get_module_eeprom(netdev, core, mlxsw_m_port->module,
|
||||
+ ee, data);
|
||||
}
|
||||
|
||||
static const struct ethtool_ops mlxsw_m_port_ethtool_ops = {
|
||||
@@ -199,7 +193,7 @@ static int mlxsw_m_port_module_map(struct mlxsw_m *mlxsw_m, u8 local_port,
|
||||
u8 module, width;
|
||||
int err;
|
||||
|
||||
- /* Fill out to local port mapping array */
|
||||
+ /* Fill out to local port mapping array */
|
||||
err = mlxsw_m_port_module_info_get(mlxsw_m, local_port, &module,
|
||||
&width);
|
||||
if (err)
|
||||
@@ -216,57 +210,39 @@ static int mlxsw_m_port_module_map(struct mlxsw_m *mlxsw_m, u8 local_port,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int 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 module)
|
||||
{
|
||||
mlxsw_m->module_to_port[module] = -1;
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static void mlxsw_m_ports_remove(struct mlxsw_m *mlxsw_m)
|
||||
-{
|
||||
- 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, i);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- kfree(mlxsw_m->module_to_port);
|
||||
- kfree(mlxsw_m->ports);
|
||||
}
|
||||
|
||||
static int mlxsw_m_ports_create(struct mlxsw_m *mlxsw_m)
|
||||
{
|
||||
- unsigned int max_port = mlxsw_core_max_ports(mlxsw_m->core);
|
||||
- u8 last_module = max_port;
|
||||
+ unsigned int max_ports = mlxsw_core_max_ports(mlxsw_m->core);
|
||||
+ u8 last_module = max_ports;
|
||||
int i;
|
||||
int err;
|
||||
|
||||
- mlxsw_m->ports = kcalloc(max_port, sizeof(*mlxsw_m->ports),
|
||||
+ 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_port, sizeof(int),
|
||||
+ mlxsw_m->module_to_port = kmalloc_array(max_ports, sizeof(int),
|
||||
GFP_KERNEL);
|
||||
if (!mlxsw_m->module_to_port) {
|
||||
err = -ENOMEM;
|
||||
- goto err_port_create;
|
||||
+ goto err_module_to_port_alloc;
|
||||
}
|
||||
|
||||
/* Invalidate the entries of module to local port mapping array */
|
||||
- for (i = 0; i < max_port; i++)
|
||||
+ for (i = 0; i < max_ports; i++)
|
||||
mlxsw_m->module_to_port[i] = -1;
|
||||
|
||||
/* Fill out module to local port mapping array */
|
||||
- for (i = 1; i < max_port; i++) {
|
||||
+ for (i = 1; i < max_ports; i++) {
|
||||
err = mlxsw_m_port_module_map(mlxsw_m, i, &last_module);
|
||||
if (err)
|
||||
- goto err_port_create;
|
||||
+ goto err_module_to_port_map;
|
||||
}
|
||||
|
||||
/* Create port objects for each valid entry */
|
||||
@@ -276,17 +252,44 @@ static int mlxsw_m_ports_create(struct mlxsw_m *mlxsw_m)
|
||||
mlxsw_m->module_to_port[i],
|
||||
i);
|
||||
if (err)
|
||||
- goto err_port_create;
|
||||
+ goto err_module_to_port_create;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
-err_port_create:
|
||||
- mlxsw_m_ports_remove(mlxsw_m);
|
||||
+err_module_to_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]);
|
||||
+ }
|
||||
+ i = max_ports;
|
||||
+err_module_to_port_map:
|
||||
+ for (i--; i > 0; i--)
|
||||
+ mlxsw_m_port_module_unmap(mlxsw_m, i);
|
||||
+ kfree(mlxsw_m->module_to_port);
|
||||
+err_module_to_port_alloc:
|
||||
+ kfree(mlxsw_m->ports);
|
||||
return err;
|
||||
}
|
||||
|
||||
+static void mlxsw_m_ports_remove(struct mlxsw_m *mlxsw_m)
|
||||
+{
|
||||
+ 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, i);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ kfree(mlxsw_m->module_to_port);
|
||||
+ kfree(mlxsw_m->ports);
|
||||
+}
|
||||
+
|
||||
static int mlxsw_m_init(struct mlxsw_core *mlxsw_core,
|
||||
const struct mlxsw_bus_info *mlxsw_bus_info)
|
||||
{
|
||||
--
|
||||
2.11.0
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
From d0e273393dd610f552ffbe9a9d1cf3448c8c028e Mon Sep 17 00:00:00 2001
|
||||
From: Vadim Pasternak <vadimp@mellanox.com>
|
||||
Date: Sun, 3 Mar 2019 08:50:49 +0000
|
||||
Subject: [PATCH backport 5.1] mlxsw: core: Add check for split port during
|
||||
thermal zone initialization
|
||||
|
||||
Skip thermal zone creation in case of split port.
|
||||
|
||||
Overwrite the first byte in base MAC address in
|
||||
minimal driver.
|
||||
|
||||
Signed-off-by: Vadim Pasternak <vadimp@mellanox.com>
|
||||
---
|
||||
drivers/net/ethernet/mellanox/mlxsw/core_thermal.c | 15 ++++++++++++---
|
||||
drivers/net/ethernet/mellanox/mlxsw/minimal.c | 2 +-
|
||||
2 files changed, 13 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
|
||||
index 002654918ee9..1f7ef90b2270 100644
|
||||
--- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
|
||||
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
|
||||
@@ -752,6 +752,9 @@ mlxsw_thermal_module_init(struct device *dev, struct mlxsw_core *core,
|
||||
|
||||
module = mlxsw_reg_pmlp_module_get(pmlp_pl, 0);
|
||||
module_tz = &thermal->tz_module_arr[module];
|
||||
+ /* Skip if parent is already set - could in in case of port split. */
|
||||
+ if (module_tz->parent)
|
||||
+ return 0;
|
||||
module_tz->module = module;
|
||||
module_tz->parent = thermal;
|
||||
memcpy(module_tz->trips, default_thermal_trips,
|
||||
@@ -773,6 +776,7 @@ static void mlxsw_thermal_module_fini(struct mlxsw_thermal_module *module_tz)
|
||||
if (module_tz && module_tz->tzdev) {
|
||||
mlxsw_thermal_module_tz_fini(module_tz->tzdev);
|
||||
module_tz->tzdev = NULL;
|
||||
+ module_tz->parent = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -781,6 +785,7 @@ mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core,
|
||||
struct mlxsw_thermal *thermal)
|
||||
{
|
||||
unsigned int module_count = mlxsw_core_max_ports(core);
|
||||
+ struct mlxsw_thermal_module *module_tz;
|
||||
int i, err;
|
||||
|
||||
thermal->tz_module_arr = kcalloc(module_count,
|
||||
@@ -795,8 +800,12 @@ mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core,
|
||||
goto err_unreg_tz_module_arr;
|
||||
}
|
||||
|
||||
- for (i = 0; i < thermal->tz_module_num; i++) {
|
||||
- err = mlxsw_thermal_module_tz_init(&thermal->tz_module_arr[i]);
|
||||
+ module_count -= 1;
|
||||
+ for (i = 0; i < module_count; i++) {
|
||||
+ module_tz = &thermal->tz_module_arr[i];
|
||||
+ if (!module_tz->parent)
|
||||
+ continue;
|
||||
+ err = mlxsw_thermal_module_tz_init(module_tz);
|
||||
if (err)
|
||||
goto err_unreg_tz_module_arr;
|
||||
}
|
||||
@@ -804,7 +813,7 @@ mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core,
|
||||
return 0;
|
||||
|
||||
err_unreg_tz_module_arr:
|
||||
- for (i = module_count - 1; i >= 0; i--)
|
||||
+ for (i = module_count; i >= 0; i--)
|
||||
mlxsw_thermal_module_fini(&thermal->tz_module_arr[i]);
|
||||
kfree(thermal->tz_module_arr);
|
||||
return err;
|
||||
diff --git a/drivers/net/ethernet/mellanox/mlxsw/minimal.c b/drivers/net/ethernet/mellanox/mlxsw/minimal.c
|
||||
index 740b3753de44..cac36c231864 100644
|
||||
--- a/drivers/net/ethernet/mellanox/mlxsw/minimal.c
|
||||
+++ b/drivers/net/ethernet/mellanox/mlxsw/minimal.c
|
||||
@@ -104,7 +104,7 @@ mlxsw_m_port_dev_addr_get(struct mlxsw_m_port *mlxsw_m_port)
|
||||
* to be such it does not overflow when adding local_port
|
||||
* value.
|
||||
*/
|
||||
- dev->dev_addr[ETH_ALEN - 1] += mlxsw_m_port->module + 1;
|
||||
+ dev->dev_addr[ETH_ALEN - 1] = mlxsw_m_port->module + 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
--
|
||||
2.11.0
|
||||
|
||||
@@ -0,0 +1,665 @@
|
||||
diff -Nur a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c
|
||||
--- a/drivers/platform/x86/mlx-platform.c 2019-02-21 13:41:06.654605472 +0000
|
||||
+++ b/drivers/platform/x86/mlx-platform.c 2019-02-21 13:48:22.670032634 +0000
|
||||
@@ -61,9 +61,11 @@
|
||||
#define MLXPLAT_CPLD_LPC_REG_WD1_TMR_OFFSET 0xc9
|
||||
#define MLXPLAT_CPLD_LPC_REG_WD1_ACT_OFFSET 0xcb
|
||||
#define MLXPLAT_CPLD_LPC_REG_WD2_TMR_OFFSET 0xcd
|
||||
+#define MLXPLAT_CPLD_LPC_REG_WD2_TLEFT_OFFSET 0xce
|
||||
#define MLXPLAT_CPLD_LPC_REG_WD2_ACT_OFFSET 0xcf
|
||||
#define MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET 0xd1
|
||||
-#define MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET 0xd2
|
||||
+#define MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET 0xd2
|
||||
+#define MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET 0xd3
|
||||
#define MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET 0xe3
|
||||
#define MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET 0xe4
|
||||
#define MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET 0xe5
|
||||
@@ -1369,7 +1371,9 @@
|
||||
.counter = ARRAY_SIZE(mlxplat_mlxcpld_default_fan_data),
|
||||
};
|
||||
|
||||
-/* Type1 watchdog implementation on MSN2700, MSN2100 and MSN2140 systems */
|
||||
+/* Watchdog type1: hardware implementation version1
|
||||
+ * (MSN2700, MSN2410, MSN2740, MSN2100 and MSN2140 systems).
|
||||
+ */
|
||||
static struct mlxreg_core_data mlxplat_mlxcpld_wd_main_regs_type1[] = {
|
||||
{
|
||||
.label = "action",
|
||||
@@ -1422,17 +1426,19 @@
|
||||
{
|
||||
.data = mlxplat_mlxcpld_wd_main_regs_type1,
|
||||
.counter = ARRAY_SIZE(mlxplat_mlxcpld_wd_main_regs_type1),
|
||||
+ .version = MLX_WDT_TYPE1,
|
||||
.identity = "mlx-wdt-main",
|
||||
},
|
||||
{
|
||||
.data = mlxplat_mlxcpld_wd_aux_regs_type1,
|
||||
.counter = ARRAY_SIZE(mlxplat_mlxcpld_wd_aux_regs_type1),
|
||||
+ .version = MLX_WDT_TYPE1,
|
||||
.identity = "mlx-wdt-aux",
|
||||
},
|
||||
};
|
||||
|
||||
-/* Type2 watchdog implementation on MSB8700 and up systems
|
||||
- * To differentiate: ping reg == action reg
|
||||
+/* Watchdog type2: hardware implementation version 2
|
||||
+ * (all systems except (MSN2700, MSN2410, MSN2740, MSN2100 and MSN2140).
|
||||
*/
|
||||
static struct mlxreg_core_data mlxplat_mlxcpld_wd_main_regs_type2[] = {
|
||||
{
|
||||
@@ -1448,6 +1454,11 @@
|
||||
.health_cntr = MLXPLAT_CPLD_WD_DFLT_TIMEOUT,
|
||||
},
|
||||
{
|
||||
+ .label = "timeleft",
|
||||
+ .reg = MLXPLAT_CPLD_LPC_REG_WD2_TLEFT_OFFSET,
|
||||
+ .mask = MLXPLAT_CPLD_WD_TYPE2_TO_MASK,
|
||||
+ },
|
||||
+ {
|
||||
.label = "ping",
|
||||
.reg = MLXPLAT_CPLD_LPC_REG_WD2_ACT_OFFSET,
|
||||
.mask = MLXPLAT_CPLD_WD_RESET_ACT_MASK,
|
||||
@@ -1475,6 +1486,11 @@
|
||||
.health_cntr = MLXPLAT_CPLD_WD_DFLT_TIMEOUT,
|
||||
},
|
||||
{
|
||||
+ .label = "timeleft",
|
||||
+ .reg = MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET,
|
||||
+ .mask = MLXPLAT_CPLD_WD_TYPE2_TO_MASK,
|
||||
+ },
|
||||
+ {
|
||||
.label = "ping",
|
||||
.reg = MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET,
|
||||
.mask = MLXPLAT_CPLD_WD_FAN_ACT_MASK,
|
||||
@@ -1486,11 +1502,13 @@
|
||||
{
|
||||
.data = mlxplat_mlxcpld_wd_main_regs_type2,
|
||||
.counter = ARRAY_SIZE(mlxplat_mlxcpld_wd_main_regs_type2),
|
||||
+ .version = MLX_WDT_TYPE2,
|
||||
.identity = "mlx-wdt-main",
|
||||
},
|
||||
{
|
||||
.data = mlxplat_mlxcpld_wd_aux_regs_type2,
|
||||
.counter = ARRAY_SIZE(mlxplat_mlxcpld_wd_aux_regs_type2),
|
||||
+ .version = MLX_WDT_TYPE2,
|
||||
.identity = "mlx-wdt-aux",
|
||||
},
|
||||
};
|
||||
@@ -1573,8 +1591,10 @@
|
||||
case MLXPLAT_CPLD_LPC_REG_WD1_TMR_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_WD1_ACT_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_WD2_TMR_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD2_TLEFT_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_WD2_ACT_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_WD3_ACT_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET:
|
||||
@@ -1634,7 +1654,9 @@
|
||||
case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_WD2_TMR_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD2_TLEFT_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_WD3_TMR_OFFSET:
|
||||
+ case MLXPLAT_CPLD_LPC_REG_WD3_TLEFT_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET:
|
||||
case MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET:
|
||||
@@ -2094,8 +2116,8 @@
|
||||
for (j = 0; j < MLXPLAT_CPLD_WD_MAX_DEVS; j++) {
|
||||
if (mlxplat_wd_data[j]) {
|
||||
mlxplat_wd_data[j]->regmap = mlxplat_hotplug->regmap;
|
||||
- priv->pdev_wd[j] = platform_device_register_resndata(
|
||||
- &mlxplat_dev->dev,
|
||||
+ 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]));
|
||||
@@ -2115,8 +2137,10 @@
|
||||
return 0;
|
||||
|
||||
fail_platform_wd_register:
|
||||
- while (--j >= 0)
|
||||
- platform_device_unregister(priv->pdev_wd[j]);
|
||||
+ while (--j >= 0) {
|
||||
+ if (priv->pdev_wd[j])
|
||||
+ platform_device_unregister(priv->pdev_wd[j]);
|
||||
+ }
|
||||
if (mlxplat_fan)
|
||||
platform_device_unregister(priv->pdev_fan);
|
||||
fail_platform_io_regs_register:
|
||||
@@ -2142,16 +2166,16 @@
|
||||
struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev);
|
||||
int i;
|
||||
|
||||
+ for (i = MLXPLAT_CPLD_WD_MAX_DEVS - 1; i >= 0 ; i--) {
|
||||
+ if (mlxplat_wd_data[i])
|
||||
+ platform_device_unregister(priv->pdev_wd[i]);
|
||||
+ }
|
||||
if (priv->pdev_fan)
|
||||
platform_device_unregister(priv->pdev_fan);
|
||||
if (priv->pdev_io_regs)
|
||||
platform_device_unregister(priv->pdev_io_regs);
|
||||
platform_device_unregister(priv->pdev_led);
|
||||
platform_device_unregister(priv->pdev_hotplug);
|
||||
- for (i = MLXPLAT_CPLD_WD_MAX_DEVS - 1; i >= 0 ; i--) {
|
||||
- if (mlxplat_wd_data[i])
|
||||
- platform_device_unregister(priv->pdev_wd[i]);
|
||||
- }
|
||||
for (i = ARRAY_SIZE(mlxplat_mux_data) - 1; i >= 0 ; i--)
|
||||
platform_device_unregister(priv->pdev_mux[i]);
|
||||
|
||||
diff -Nur a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
|
||||
--- a/drivers/watchdog/Kconfig 2019-02-21 13:41:44.518903255 +0000
|
||||
+++ b/drivers/watchdog/Kconfig 2019-02-21 13:54:11.964775375 +0000
|
||||
@@ -141,21 +141,6 @@
|
||||
This driver can also be built as a module. If so the module
|
||||
will be called menf21bmc_wdt.
|
||||
|
||||
-config MLX_WDT
|
||||
- tristate "Mellanox Watchdog"
|
||||
- select WATCHDOG_CORE
|
||||
- select REGMAP
|
||||
- ---help---
|
||||
- This is the driver for the hardware watchdog on Mellanox systems.
|
||||
- If you are going to use it, say Y here, otherwise N.
|
||||
- This driver can be used together with the watchdog daemon.
|
||||
- It can also watch your kernel to make sure it doesn't freeze,
|
||||
- and if it does, it reboots your system after a certain amount of
|
||||
- time.
|
||||
-
|
||||
- To compile this driver as a module, choose M here: the
|
||||
- module will be called mlx-wdt.
|
||||
-
|
||||
config TANGOX_WATCHDOG
|
||||
tristate "Sigma Designs SMP86xx/SMP87xx watchdog"
|
||||
select WATCHDOG_CORE
|
||||
@@ -218,6 +203,22 @@
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called ziirave_wdt.
|
||||
|
||||
+config MLX_WDT
|
||||
+ tristate "Mellanox Watchdog"
|
||||
+ depends on MELLANOX_PLATFORM
|
||||
+ select WATCHDOG_CORE
|
||||
+ select REGMAP
|
||||
+ help
|
||||
+ This is the driver for the hardware watchdog on Mellanox systems.
|
||||
+ If you are going to use it, say Y here, otherwise N.
|
||||
+ This driver can be used together with the watchdog daemon.
|
||||
+ It can also watch your kernel to make sure it doesn't freeze,
|
||||
+ and if it does, it reboots your system after a certain amount of
|
||||
+ time.
|
||||
+
|
||||
+ To compile this driver as a module, choose M here: the
|
||||
+ module will be called mlx-wdt.
|
||||
+
|
||||
# ALPHA Architecture
|
||||
|
||||
# ARM Architecture
|
||||
diff -Nur a/drivers/watchdog/mlx_wdt.c b/drivers/watchdog/mlx_wdt.c
|
||||
--- a/drivers/watchdog/mlx_wdt.c 2019-02-21 13:42:09.119096705 +0000
|
||||
+++ b/drivers/watchdog/mlx_wdt.c 2019-02-21 15:36:44.116225080 +0000
|
||||
@@ -2,8 +2,8 @@
|
||||
/*
|
||||
* Mellanox watchdog driver
|
||||
*
|
||||
- * Copyright (C) 2018 Mellanox Technologies
|
||||
- * Copyright (C) 2018 Michael Shych <mshych@mellanox.com>
|
||||
+ * Copyright (C) 2019 Mellanox Technologies
|
||||
+ * Copyright (C) 2019 Michael Shych <mshych@mellanox.com>
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
@@ -21,20 +21,9 @@
|
||||
#define MLXREG_WDT_CLOCK_SCALE 1000
|
||||
#define MLXREG_WDT_MAX_TIMEOUT_TYPE1 32
|
||||
#define MLXREG_WDT_MAX_TIMEOUT_TYPE2 255
|
||||
-#define MLXREG_WDT_MIN_TIMEOUT 1
|
||||
-#define MLXREG_WDT_HW_TIMEOUT_CONVERT(hw_timeout) ((1 << (hw_timeout)) \
|
||||
- / MLXREG_WDT_CLOCK_SCALE)
|
||||
-
|
||||
-/**
|
||||
- * enum mlxreg_wdt_type - type of HW watchdog
|
||||
- *
|
||||
- * TYPE1 can be differentiated by different register/mask
|
||||
- * for WD action set and ping.
|
||||
- */
|
||||
-enum mlxreg_wdt_type {
|
||||
- MLX_WDT_TYPE1,
|
||||
- MLX_WDT_TYPE2,
|
||||
-};
|
||||
+#define MLXREG_WDT_MIN_TIMEOUT 1
|
||||
+#define MLXREG_WDT_OPTIONS_BASE (WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE | \
|
||||
+ WDIOF_SETTIMEOUT)
|
||||
|
||||
/**
|
||||
* struct mlxreg_wdt - wd private data:
|
||||
@@ -44,16 +33,12 @@
|
||||
* @pdata: data received from platform driver;
|
||||
* @regmap: register map of parent device;
|
||||
* @timeout: defined timeout in sec.;
|
||||
- * @hw_timeout: real timeout set in hw;
|
||||
- * It will be roundup base of 2 in WD type 1,
|
||||
- * in WD type 2 it will be same number of sec as timeout;
|
||||
* @action_idx: index for direct access to action register;
|
||||
* @timeout_idx:index for direct access to TO register;
|
||||
+ * @tleft_idx: index for direct access to time left register;
|
||||
* @ping_idx: index for direct access to ping register;
|
||||
* @reset_idx: index for direct access to reset cause register;
|
||||
* @wd_type: watchdog HW type;
|
||||
- * @hw_timeout: actual HW timeout;
|
||||
- * @io_lock: spinlock for io access;
|
||||
*/
|
||||
struct mlxreg_wdt {
|
||||
struct watchdog_device wdd;
|
||||
@@ -61,138 +46,61 @@
|
||||
void *regmap;
|
||||
int action_idx;
|
||||
int timeout_idx;
|
||||
+ int tleft_idx;
|
||||
int ping_idx;
|
||||
int reset_idx;
|
||||
enum mlxreg_wdt_type wdt_type;
|
||||
- u8 hw_timeout;
|
||||
- spinlock_t io_lock; /* the lock for io operations */
|
||||
};
|
||||
|
||||
-static int mlxreg_wdt_roundup_to_base_2(struct mlxreg_wdt *wdt, int timeout)
|
||||
-{
|
||||
- timeout *= MLXREG_WDT_CLOCK_SCALE;
|
||||
-
|
||||
- wdt->hw_timeout = order_base_2(timeout);
|
||||
- dev_info(wdt->wdd.parent,
|
||||
- "watchdog %s timeout %d was rounded up to %lu (msec)\n",
|
||||
- wdt->wdd.info->identity, timeout, roundup_pow_of_two(timeout));
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static enum mlxreg_wdt_type
|
||||
-mlxreg_wdt_check_watchdog_type(struct mlxreg_wdt *wdt,
|
||||
- struct mlxreg_core_platform_data *pdata)
|
||||
-{
|
||||
- if ((pdata->data[wdt->action_idx].reg ==
|
||||
- pdata->data[wdt->ping_idx].reg) &&
|
||||
- (pdata->data[wdt->action_idx].mask ==
|
||||
- pdata->data[wdt->ping_idx].mask))
|
||||
- return MLX_WDT_TYPE2;
|
||||
- else
|
||||
- return MLX_WDT_TYPE1;
|
||||
-}
|
||||
-
|
||||
-static int mlxreg_wdt_check_card_reset(struct mlxreg_wdt *wdt)
|
||||
+static void mlxreg_wdt_check_card_reset(struct mlxreg_wdt *wdt)
|
||||
{
|
||||
struct mlxreg_core_data *reg_data;
|
||||
u32 regval;
|
||||
int rc;
|
||||
|
||||
if (wdt->reset_idx == -EINVAL)
|
||||
- return -EINVAL;
|
||||
+ return;
|
||||
|
||||
if (!(wdt->wdd.info->options & WDIOF_CARDRESET))
|
||||
- return 0;
|
||||
+ return;
|
||||
|
||||
- spin_lock(&wdt->io_lock);
|
||||
reg_data = &wdt->pdata->data[wdt->reset_idx];
|
||||
rc = regmap_read(wdt->regmap, reg_data->reg, ®val);
|
||||
- spin_unlock(&wdt->io_lock);
|
||||
- if (rc)
|
||||
- goto read_error;
|
||||
-
|
||||
- if (regval & ~reg_data->mask) {
|
||||
- wdt->wdd.bootstatus = WDIOF_CARDRESET;
|
||||
- dev_info(wdt->wdd.parent,
|
||||
- "watchdog previously reset the CPU\n");
|
||||
+ if (!rc) {
|
||||
+ if (regval & ~reg_data->mask) {
|
||||
+ wdt->wdd.bootstatus = WDIOF_CARDRESET;
|
||||
+ dev_info(wdt->wdd.parent,
|
||||
+ "watchdog previously reset the CPU\n");
|
||||
+ }
|
||||
}
|
||||
-
|
||||
-read_error:
|
||||
- return rc;
|
||||
}
|
||||
|
||||
static int mlxreg_wdt_start(struct watchdog_device *wdd)
|
||||
{
|
||||
struct mlxreg_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||
struct mlxreg_core_data *reg_data = &wdt->pdata->data[wdt->action_idx];
|
||||
- u32 regval;
|
||||
- int rc;
|
||||
-
|
||||
- spin_lock(&wdt->io_lock);
|
||||
- rc = regmap_read(wdt->regmap, reg_data->reg, ®val);
|
||||
- if (rc) {
|
||||
- spin_unlock(&wdt->io_lock);
|
||||
- goto read_error;
|
||||
- }
|
||||
-
|
||||
- regval = (regval & reg_data->mask) | BIT(reg_data->bit);
|
||||
- rc = regmap_write(wdt->regmap, reg_data->reg, regval);
|
||||
- spin_unlock(&wdt->io_lock);
|
||||
- if (!rc) {
|
||||
- set_bit(WDOG_HW_RUNNING, &wdt->wdd.status);
|
||||
- dev_info(wdt->wdd.parent, "watchdog %s started\n",
|
||||
- wdd->info->identity);
|
||||
- }
|
||||
|
||||
-read_error:
|
||||
- return rc;
|
||||
+ return regmap_update_bits(wdt->regmap, reg_data->reg, ~reg_data->mask,
|
||||
+ BIT(reg_data->bit));
|
||||
}
|
||||
|
||||
static int mlxreg_wdt_stop(struct watchdog_device *wdd)
|
||||
{
|
||||
struct mlxreg_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||
struct mlxreg_core_data *reg_data = &wdt->pdata->data[wdt->action_idx];
|
||||
- u32 regval;
|
||||
- int rc;
|
||||
-
|
||||
- spin_lock(&wdt->io_lock);
|
||||
- rc = regmap_read(wdt->regmap, reg_data->reg, ®val);
|
||||
- if (rc) {
|
||||
- spin_unlock(&wdt->io_lock);
|
||||
- goto read_error;
|
||||
- }
|
||||
|
||||
- regval = (regval & reg_data->mask) & ~BIT(reg_data->bit);
|
||||
- rc = regmap_write(wdt->regmap, reg_data->reg, regval);
|
||||
- spin_unlock(&wdt->io_lock);
|
||||
- if (!rc)
|
||||
- dev_info(wdt->wdd.parent, "watchdog %s stopped\n",
|
||||
- wdd->info->identity);
|
||||
-
|
||||
-read_error:
|
||||
- return rc;
|
||||
+ return regmap_update_bits(wdt->regmap, reg_data->reg, ~reg_data->mask,
|
||||
+ ~BIT(reg_data->bit));
|
||||
}
|
||||
|
||||
static int mlxreg_wdt_ping(struct watchdog_device *wdd)
|
||||
{
|
||||
struct mlxreg_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||
struct mlxreg_core_data *reg_data = &wdt->pdata->data[wdt->ping_idx];
|
||||
- u32 regval;
|
||||
- int rc;
|
||||
|
||||
- spin_lock(&wdt->io_lock);
|
||||
- rc = regmap_read(wdt->regmap, reg_data->reg, ®val);
|
||||
- if (rc)
|
||||
- goto read_error;
|
||||
-
|
||||
- regval = (regval & reg_data->mask) | BIT(reg_data->bit);
|
||||
- rc = regmap_write(wdt->regmap, reg_data->reg, regval);
|
||||
-
|
||||
-read_error:
|
||||
- spin_unlock(&wdt->io_lock);
|
||||
-
|
||||
- return rc;
|
||||
+ return regmap_update_bits_base(wdt->regmap, reg_data->reg,
|
||||
+ ~reg_data->mask, BIT(reg_data->bit),
|
||||
+ NULL, false, true);
|
||||
}
|
||||
|
||||
static int mlxreg_wdt_set_timeout(struct watchdog_device *wdd,
|
||||
@@ -200,25 +108,37 @@
|
||||
{
|
||||
struct mlxreg_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||
struct mlxreg_core_data *reg_data = &wdt->pdata->data[wdt->timeout_idx];
|
||||
- u32 regval;
|
||||
+ u32 regval, set_time, hw_timeout;
|
||||
int rc;
|
||||
|
||||
- spin_lock(&wdt->io_lock);
|
||||
-
|
||||
if (wdt->wdt_type == MLX_WDT_TYPE1) {
|
||||
rc = regmap_read(wdt->regmap, reg_data->reg, ®val);
|
||||
if (rc)
|
||||
- goto read_error;
|
||||
- regval = (regval & reg_data->mask) | wdt->hw_timeout;
|
||||
+ return rc;
|
||||
+
|
||||
+ hw_timeout = order_base_2(timeout * MLXREG_WDT_CLOCK_SCALE);
|
||||
+ regval = (regval & reg_data->mask) | hw_timeout;
|
||||
+ /* Rowndown to actual closest number of sec. */
|
||||
+ set_time = BIT(hw_timeout) / MLXREG_WDT_CLOCK_SCALE;
|
||||
} else {
|
||||
- wdt->hw_timeout = timeout;
|
||||
+ set_time = timeout;
|
||||
regval = timeout;
|
||||
}
|
||||
|
||||
+ wdd->timeout = set_time;
|
||||
rc = regmap_write(wdt->regmap, reg_data->reg, regval);
|
||||
|
||||
-read_error:
|
||||
- spin_unlock(&wdt->io_lock);
|
||||
+ if (!rc) {
|
||||
+ /*
|
||||
+ * Restart watchdog with new timeout period
|
||||
+ * if watchdog is already started.
|
||||
+ */
|
||||
+ if (watchdog_active(wdd)) {
|
||||
+ rc = mlxreg_wdt_stop(wdd);
|
||||
+ if (!rc)
|
||||
+ rc = mlxreg_wdt_start(wdd);
|
||||
+ }
|
||||
+ }
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -226,23 +146,13 @@
|
||||
static unsigned int mlxreg_wdt_get_timeleft(struct watchdog_device *wdd)
|
||||
{
|
||||
struct mlxreg_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||
- struct mlxreg_core_data *reg_data = &wdt->pdata->data[wdt->timeout_idx];
|
||||
+ struct mlxreg_core_data *reg_data = &wdt->pdata->data[wdt->tleft_idx];
|
||||
u32 regval;
|
||||
int rc;
|
||||
|
||||
- if (wdt->wdt_type == MLX_WDT_TYPE1)
|
||||
- return 0;
|
||||
-
|
||||
- spin_lock(&wdt->io_lock);
|
||||
rc = regmap_read(wdt->regmap, reg_data->reg, ®val);
|
||||
- if (rc)
|
||||
- rc = 0;
|
||||
- else
|
||||
- rc = regval;
|
||||
-
|
||||
- spin_unlock(&wdt->io_lock);
|
||||
-
|
||||
- return rc;
|
||||
+ /* Return 0 timeleft in case of failure register read. */
|
||||
+ return rc == 0 ? regval : 0;
|
||||
}
|
||||
|
||||
static const struct watchdog_ops mlxreg_wdt_ops_type1 = {
|
||||
@@ -263,26 +173,22 @@
|
||||
};
|
||||
|
||||
static const struct watchdog_info mlxreg_wdt_main_info = {
|
||||
- .options = WDIOF_KEEPALIVEPING
|
||||
- | WDIOF_MAGICCLOSE
|
||||
- | WDIOF_SETTIMEOUT
|
||||
+ .options = MLXREG_WDT_OPTIONS_BASE
|
||||
| WDIOF_CARDRESET,
|
||||
.identity = "mlx-wdt-main",
|
||||
};
|
||||
|
||||
static const struct watchdog_info mlxreg_wdt_aux_info = {
|
||||
- .options = WDIOF_KEEPALIVEPING
|
||||
- | WDIOF_MAGICCLOSE
|
||||
- | WDIOF_SETTIMEOUT
|
||||
+ .options = MLXREG_WDT_OPTIONS_BASE
|
||||
| WDIOF_ALARMONLY,
|
||||
.identity = "mlx-wdt-aux",
|
||||
};
|
||||
|
||||
-static int mlxreg_wdt_config(struct mlxreg_wdt *wdt,
|
||||
- struct mlxreg_core_platform_data *pdata)
|
||||
+static void mlxreg_wdt_config(struct mlxreg_wdt *wdt,
|
||||
+ struct mlxreg_core_platform_data *pdata)
|
||||
{
|
||||
struct mlxreg_core_data *data = pdata->data;
|
||||
- int i, timeout;
|
||||
+ int i;
|
||||
|
||||
wdt->reset_idx = -EINVAL;
|
||||
for (i = 0; i < pdata->counter; i++, data++) {
|
||||
@@ -290,6 +196,8 @@
|
||||
wdt->action_idx = i;
|
||||
else if (strnstr(data->label, "timeout", sizeof(data->label)))
|
||||
wdt->timeout_idx = i;
|
||||
+ else if (strnstr(data->label, "timeleft", sizeof(data->label)))
|
||||
+ wdt->tleft_idx = i;
|
||||
else if (strnstr(data->label, "ping", sizeof(data->label)))
|
||||
wdt->ping_idx = i;
|
||||
else if (strnstr(data->label, "reset", sizeof(data->label)))
|
||||
@@ -303,24 +211,24 @@
|
||||
else
|
||||
wdt->wdd.info = &mlxreg_wdt_aux_info;
|
||||
|
||||
- timeout = pdata->data[wdt->timeout_idx].health_cntr;
|
||||
- wdt->wdt_type = mlxreg_wdt_check_watchdog_type(wdt, pdata);
|
||||
+ wdt->wdt_type = pdata->version;
|
||||
if (wdt->wdt_type == MLX_WDT_TYPE2) {
|
||||
- wdt->hw_timeout = timeout;
|
||||
wdt->wdd.ops = &mlxreg_wdt_ops_type2;
|
||||
- wdt->wdd.timeout = wdt->hw_timeout;
|
||||
wdt->wdd.max_timeout = MLXREG_WDT_MAX_TIMEOUT_TYPE2;
|
||||
} else {
|
||||
- mlxreg_wdt_roundup_to_base_2(wdt, timeout);
|
||||
wdt->wdd.ops = &mlxreg_wdt_ops_type1;
|
||||
- /* Rowndown to actual closest number of sec. */
|
||||
- wdt->wdd.timeout =
|
||||
- MLXREG_WDT_HW_TIMEOUT_CONVERT(wdt->hw_timeout);
|
||||
wdt->wdd.max_timeout = MLXREG_WDT_MAX_TIMEOUT_TYPE1;
|
||||
}
|
||||
wdt->wdd.min_timeout = MLXREG_WDT_MIN_TIMEOUT;
|
||||
+}
|
||||
|
||||
- return -EINVAL;
|
||||
+static int mlxreg_wdt_init_timeout(struct mlxreg_wdt *wdt,
|
||||
+ struct mlxreg_core_platform_data *pdata)
|
||||
+{
|
||||
+ u32 timeout;
|
||||
+
|
||||
+ timeout = pdata->data[wdt->timeout_idx].health_cntr;
|
||||
+ return mlxreg_wdt_set_timeout(&wdt->wdd, timeout);
|
||||
}
|
||||
|
||||
static int mlxreg_wdt_probe(struct platform_device *pdev)
|
||||
@@ -338,48 +246,38 @@
|
||||
if (!wdt)
|
||||
return -ENOMEM;
|
||||
|
||||
- spin_lock_init(&wdt->io_lock);
|
||||
-
|
||||
wdt->wdd.parent = &pdev->dev;
|
||||
wdt->regmap = pdata->regmap;
|
||||
mlxreg_wdt_config(wdt, pdata);
|
||||
|
||||
- if ((pdata->features & MLXREG_CORE_WD_FEATURE_NOSTOP_AFTER_START))
|
||||
+ if ((pdata->features & MLXREG_CORE_WD_FEATURE_NOWAYOUT))
|
||||
watchdog_set_nowayout(&wdt->wdd, WATCHDOG_NOWAYOUT);
|
||||
watchdog_stop_on_reboot(&wdt->wdd);
|
||||
- watchdog_init_timeout(&wdt->wdd, 0, &pdev->dev);
|
||||
watchdog_set_drvdata(&wdt->wdd, wdt);
|
||||
+ rc = mlxreg_wdt_init_timeout(wdt, pdata);
|
||||
+ if (rc)
|
||||
+ goto register_error;
|
||||
|
||||
+ if ((pdata->features & MLXREG_CORE_WD_FEATURE_START_AT_BOOT)) {
|
||||
+ rc = mlxreg_wdt_start(&wdt->wdd);
|
||||
+ if (rc)
|
||||
+ goto register_error;
|
||||
+ set_bit(WDOG_HW_RUNNING, &wdt->wdd.status);
|
||||
+ }
|
||||
mlxreg_wdt_check_card_reset(wdt);
|
||||
rc = devm_watchdog_register_device(&pdev->dev, &wdt->wdd);
|
||||
- if (rc) {
|
||||
+
|
||||
+register_error:
|
||||
+ if (rc)
|
||||
dev_err(&pdev->dev,
|
||||
"Cannot register watchdog device (err=%d)\n", rc);
|
||||
- return rc;
|
||||
- }
|
||||
-
|
||||
- mlxreg_wdt_set_timeout(&wdt->wdd, wdt->wdd.timeout);
|
||||
- if ((pdata->features & MLXREG_CORE_WD_FEATURE_START_AT_BOOT))
|
||||
- mlxreg_wdt_start(&wdt->wdd);
|
||||
-
|
||||
return rc;
|
||||
}
|
||||
|
||||
-static int mlxreg_wdt_remove(struct platform_device *pdev)
|
||||
-{
|
||||
- struct mlxreg_wdt *wdt = dev_get_platdata(&pdev->dev);
|
||||
-
|
||||
- mlxreg_wdt_stop(&wdt->wdd);
|
||||
- watchdog_unregister_device(&wdt->wdd);
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
static struct platform_driver mlxreg_wdt_driver = {
|
||||
.probe = mlxreg_wdt_probe,
|
||||
- .remove = mlxreg_wdt_remove,
|
||||
.driver = {
|
||||
- .name = "mlx-wdt",
|
||||
+ .name = "mlx-wdt",
|
||||
},
|
||||
};
|
||||
|
||||
diff -Nur a/include/linux/platform_data/mlxreg.h b/include/linux/platform_data/mlxreg.h
|
||||
--- a/include/linux/platform_data/mlxreg.h 2019-02-21 13:58:39.410873888 +0000
|
||||
+++ b/include/linux/platform_data/mlxreg.h 2019-02-21 13:59:41.015345425 +0000
|
||||
@@ -35,8 +35,19 @@
|
||||
#define __LINUX_PLATFORM_DATA_MLXREG_H
|
||||
|
||||
#define MLXREG_CORE_LABEL_MAX_SIZE 32
|
||||
-#define MLXREG_CORE_WD_FEATURE_NOSTOP_AFTER_START BIT(0)
|
||||
-#define MLXREG_CORE_WD_FEATURE_START_AT_BOOT BIT(1)
|
||||
+#define MLXREG_CORE_WD_FEATURE_NOWAYOUT BIT(0)
|
||||
+#define MLXREG_CORE_WD_FEATURE_START_AT_BOOT BIT(1)
|
||||
+
|
||||
+/**
|
||||
+ * enum mlxreg_wdt_type - type of HW watchdog
|
||||
+ *
|
||||
+ * TYPE1 HW watchdog implementation exist in old systems.
|
||||
+ * All new systems have TYPE2 HW watchdog.
|
||||
+ */
|
||||
+enum mlxreg_wdt_type {
|
||||
+ MLX_WDT_TYPE1,
|
||||
+ MLX_WDT_TYPE2,
|
||||
+};
|
||||
|
||||
/**
|
||||
* struct mlxreg_hotplug_device - I2C device data:
|
||||
@@ -115,6 +126,7 @@
|
||||
* @regmap: register map of parent device;
|
||||
* @counter: number of instances;
|
||||
* @features: supported features of device;
|
||||
+ * @version: implementation version;
|
||||
* @identity: device identity name;
|
||||
*/
|
||||
struct mlxreg_core_platform_data {
|
||||
@@ -122,6 +134,7 @@
|
||||
void *regmap;
|
||||
int counter;
|
||||
u32 features;
|
||||
+ u32 version;
|
||||
char identity[MLXREG_CORE_LABEL_MAX_SIZE];
|
||||
};
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
From 7f31d9b833b0c31f5c8d75416758a9f30add6190 Mon Sep 17 00:00:00 2001
|
||||
From: Vadim Pasternak <vadimp@mellanox.com>
|
||||
Date: Wed, 15 May 2019 15:22:44 +0000
|
||||
Subject: [PATCH backport v5.2] mlxsw: core: Prevent reading unsupported slave
|
||||
address from SFP EEPROM
|
||||
|
||||
Prevent reading unsupported slave address from SFP EEPROM by testing
|
||||
Diagnostic Monitoring Type byte in EEPROM. Read only page zero of
|
||||
EEPROM, in case this byte is zero.
|
||||
|
||||
If some SFP transceiver don't support Digital Optical Monitoring (DOM),
|
||||
thus reading SFP EEPROM slave address 0x51 could return error.
|
||||
Availability of DOM support is verified by reading from zero page
|
||||
Diagnostic Monitoring Type byte describing how diagnostic monitoring is
|
||||
implemented by transceiver. If bit 6 of this byte is set, it indicates
|
||||
that digital diagnostic monitoring has been implemented. Otherwise it is
|
||||
not and transceiver could fail to reply to transaction for slave address
|
||||
0x51 [1010001X (A2h)], which is used to access measurements page.
|
||||
|
||||
Such issue has been observed when reading cable MCP2M00-xxxx,
|
||||
MCP7F00-xxxx, and few others.
|
||||
|
||||
Signed-off-by: Vadim Pasternak <vadimp@mellanox.com>
|
||||
---
|
||||
drivers/net/ethernet/mellanox/mlxsw/core_env.c | 18 ++++++++++++++++--
|
||||
1 file changed, 16 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c
|
||||
index 7a15e932ed2f..edcf1b656cbf 100644
|
||||
--- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c
|
||||
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/err.h>
|
||||
+#include <linux/sfp.h>
|
||||
|
||||
#include "core.h"
|
||||
#include "core_env.h"
|
||||
@@ -162,7 +163,7 @@ int mlxsw_env_get_module_info(struct mlxsw_core *mlxsw_core, int module,
|
||||
{
|
||||
u8 module_info[MLXSW_REG_MCIA_EEPROM_MODULE_INFO_SIZE];
|
||||
u16 offset = MLXSW_REG_MCIA_EEPROM_MODULE_INFO_SIZE;
|
||||
- u8 module_rev_id, module_id;
|
||||
+ u8 module_rev_id, module_id, diag_mon;
|
||||
unsigned int read_size;
|
||||
int err;
|
||||
|
||||
@@ -195,8 +196,21 @@ int mlxsw_env_get_module_info(struct mlxsw_core *mlxsw_core, int module,
|
||||
}
|
||||
break;
|
||||
case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_SFP:
|
||||
+ /* Verify if transceiver provides digital diagnostic monitoring page */
|
||||
+ err = mlxsw_env_query_module_eeprom(mlxsw_core, module,
|
||||
+ SFP_DIAGMON, 1, &diag_mon,
|
||||
+ &read_size);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ if (read_size < 1)
|
||||
+ return -EIO;
|
||||
+
|
||||
modinfo->type = ETH_MODULE_SFF_8472;
|
||||
- modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
|
||||
+ if (diag_mon)
|
||||
+ modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
|
||||
+ else
|
||||
+ modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN / 2;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
--
|
||||
2.11.0
|
||||
|
||||
@@ -0,0 +1,650 @@
|
||||
From 83d2cf92f7fef5df0de2cf19f4235dc6c50f92a5 Mon Sep 17 00:00:00 2001
|
||||
From: Vadim Pasternak <vadimp@mellanox.com>
|
||||
Date: Mon, 4 Mar 2019 14:50:48 +0000
|
||||
Subject: [PATCH backport 5.1] mlxsw: core: add support for Gear Box
|
||||
temperatures in hwmon
|
||||
|
||||
Add hwmon interface for inter-connects temperature reading.
|
||||
This information is a critical for the system equipped with such hardware.
|
||||
These new attributes are necessary for the system monitoring.
|
||||
|
||||
Such inter-connect devices are equipped on new Mellanox MSN3800
|
||||
Ethernet 2U systems with 64xQSFP28 100GbE full bidirectional bandwidth
|
||||
ports.
|
||||
The connectivity map is depicted below.
|
||||
|
||||
+------+D01
|
||||
| |+-->+--------+
|
||||
| | | Die0+--->P01
|
||||
| | |Gear +--->P02
|
||||
| | |Box |
|
||||
| S | |01 +--->P03
|
||||
| P | | Die1+--->P04
|
||||
| E |+-->+--------+
|
||||
| C |D02
|
||||
| T |...
|
||||
| R |D15
|
||||
| U |+-->+---------+
|
||||
| M | | Die0+--->P29
|
||||
| 2 | |Gear +--->P30
|
||||
| | |Box |
|
||||
| C | |08 +--->P31
|
||||
| H | | Die1+--->P32
|
||||
| I |+-->+---------+
|
||||
| P |D16
|
||||
| |...
|
||||
| |D31
|
||||
| |+-->+---------+
|
||||
| | | Die0+--->P61
|
||||
| | |Gear +--->P62
|
||||
| | |Box |
|
||||
| | |16 +--->P63
|
||||
| | | Die1+--->P64
|
||||
| |+-->+---------+
|
||||
+------+D32
|
||||
|
||||
Spectrum-2 chip provides 64 100GbE ports toward the front panel, in 64
|
||||
QSFP ports.
|
||||
|
||||
Each D(i) above is a pair of 2x50GBe lanes utilizing PAM4 (Pulse
|
||||
Amplitude Modulation) technology lanes.
|
||||
|
||||
Each P(k) above is 4x25GBe lanes utilizing NRZ (Non-Return to Zero)
|
||||
technology.
|
||||
|
||||
Each Gearbox(j) above is a low power 400GbE device supporting data
|
||||
streams in re-timer mode with PAM-4 modulation or 26.5625Gbps down to
|
||||
1.25Gbps streams with NRZ modulation.
|
||||
Each such device is equipped with two dies and each die is equipped
|
||||
with the temperature sensor for junction temperature measurement. The
|
||||
operating junction temperature is between 0C and 110C.
|
||||
These sensors are the subject of this patchset.
|
||||
|
||||
Signed-off-by: Vadim Pasternak <vadimp@mellanox.com>
|
||||
---
|
||||
drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c | 85 ++++++++++-
|
||||
drivers/net/ethernet/mellanox/mlxsw/core_thermal.c | 165 ++++++++++++++++-----
|
||||
drivers/net/ethernet/mellanox/mlxsw/qsfp_sysfs.c | 7 +
|
||||
drivers/net/ethernet/mellanox/mlxsw/reg.h | 56 ++++++-
|
||||
drivers/platform/mellanox/mlxreg-hotplug.c | 5 +-
|
||||
drivers/platform/x86/mlx-platform.c | 6 +-
|
||||
6 files changed, 276 insertions(+), 48 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c
|
||||
index 6956bbebe2f1..976f81a2bbba 100644
|
||||
--- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c
|
||||
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c
|
||||
@@ -15,6 +15,9 @@
|
||||
#define MLXSW_HWMON_TEMP_SENSOR_MAX_COUNT 127
|
||||
#define MLXSW_HWMON_ATTR_COUNT (MLXSW_HWMON_TEMP_SENSOR_MAX_COUNT * 4 + \
|
||||
MLXSW_MFCR_TACHOS_MAX + MLXSW_MFCR_PWMS_MAX)
|
||||
+#define MLXSW_HWMON_GET_ATTR_INDEX(ind, count) \
|
||||
+ (((ind) >= (count)) ? (ind) % (count) + \
|
||||
+ MLXSW_REG_MTMP_GBOX_INDEX_MIN : (ind))
|
||||
|
||||
struct mlxsw_hwmon_attr {
|
||||
struct device_attribute dev_attr;
|
||||
@@ -33,6 +36,7 @@ struct mlxsw_hwmon {
|
||||
struct mlxsw_hwmon_attr hwmon_attrs[MLXSW_HWMON_ATTR_COUNT];
|
||||
unsigned int attrs_count;
|
||||
u8 sensor_count;
|
||||
+ u8 module_sensor_count;
|
||||
};
|
||||
|
||||
static ssize_t mlxsw_hwmon_temp_show(struct device *dev,
|
||||
@@ -44,10 +48,12 @@ static ssize_t mlxsw_hwmon_temp_show(struct device *dev,
|
||||
struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
|
||||
char mtmp_pl[MLXSW_REG_MTMP_LEN];
|
||||
unsigned int temp;
|
||||
+ int index;
|
||||
int err;
|
||||
|
||||
- mlxsw_reg_mtmp_pack(mtmp_pl, mlwsw_hwmon_attr->type_index,
|
||||
- false, false);
|
||||
+ index = MLXSW_HWMON_GET_ATTR_INDEX(mlwsw_hwmon_attr->type_index,
|
||||
+ mlxsw_hwmon->module_sensor_count);
|
||||
+ mlxsw_reg_mtmp_pack(mtmp_pl, index, false, false);
|
||||
err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl);
|
||||
if (err) {
|
||||
dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query temp sensor\n");
|
||||
@@ -66,10 +72,12 @@ static ssize_t mlxsw_hwmon_temp_max_show(struct device *dev,
|
||||
struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
|
||||
char mtmp_pl[MLXSW_REG_MTMP_LEN];
|
||||
unsigned int temp_max;
|
||||
+ int index;
|
||||
int err;
|
||||
|
||||
- mlxsw_reg_mtmp_pack(mtmp_pl, mlwsw_hwmon_attr->type_index,
|
||||
- false, false);
|
||||
+ index = MLXSW_HWMON_GET_ATTR_INDEX(mlwsw_hwmon_attr->type_index,
|
||||
+ mlxsw_hwmon->module_sensor_count);
|
||||
+ mlxsw_reg_mtmp_pack(mtmp_pl, index, false, false);
|
||||
err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl);
|
||||
if (err) {
|
||||
dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query temp sensor\n");
|
||||
@@ -88,6 +96,7 @@ static ssize_t mlxsw_hwmon_temp_rst_store(struct device *dev,
|
||||
struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
|
||||
char mtmp_pl[MLXSW_REG_MTMP_LEN];
|
||||
unsigned long val;
|
||||
+ int index;
|
||||
int err;
|
||||
|
||||
err = kstrtoul(buf, 10, &val);
|
||||
@@ -96,7 +105,9 @@ static ssize_t mlxsw_hwmon_temp_rst_store(struct device *dev,
|
||||
if (val != 1)
|
||||
return -EINVAL;
|
||||
|
||||
- mlxsw_reg_mtmp_pack(mtmp_pl, mlwsw_hwmon_attr->type_index, true, true);
|
||||
+ index = MLXSW_HWMON_GET_ATTR_INDEX(mlwsw_hwmon_attr->type_index,
|
||||
+ mlxsw_hwmon->module_sensor_count);
|
||||
+ mlxsw_reg_mtmp_pack(mtmp_pl, index, true, true);
|
||||
err = mlxsw_reg_write(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl);
|
||||
if (err) {
|
||||
dev_err(mlxsw_hwmon->bus_info->dev, "Failed to reset temp sensor history\n");
|
||||
@@ -333,6 +344,20 @@ mlxsw_hwmon_module_temp_label_show(struct device *dev,
|
||||
mlwsw_hwmon_attr->type_index);
|
||||
}
|
||||
|
||||
+static ssize_t
|
||||
+mlxsw_hwmon_gbox_temp_label_show(struct device *dev,
|
||||
+ struct device_attribute *attr,
|
||||
+ char *buf)
|
||||
+{
|
||||
+ struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
|
||||
+ container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
|
||||
+ struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
|
||||
+ int index = mlwsw_hwmon_attr->type_index -
|
||||
+ mlxsw_hwmon->module_sensor_count + 1;
|
||||
+
|
||||
+ return sprintf(buf, "gearbox %03u\n", index);
|
||||
+}
|
||||
+
|
||||
enum mlxsw_hwmon_attr_type {
|
||||
MLXSW_HWMON_ATTR_TYPE_TEMP,
|
||||
MLXSW_HWMON_ATTR_TYPE_TEMP_MAX,
|
||||
@@ -345,6 +370,7 @@ enum mlxsw_hwmon_attr_type {
|
||||
MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_CRIT,
|
||||
MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG,
|
||||
MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_LABEL,
|
||||
+ MLXSW_HWMON_ATTR_TYPE_TEMP_GBOX_LABEL,
|
||||
};
|
||||
|
||||
static void mlxsw_hwmon_attr_add(struct mlxsw_hwmon *mlxsw_hwmon,
|
||||
@@ -428,6 +454,13 @@ static void mlxsw_hwmon_attr_add(struct mlxsw_hwmon *mlxsw_hwmon,
|
||||
snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
|
||||
"temp%u_label", num + 1);
|
||||
break;
|
||||
+ case MLXSW_HWMON_ATTR_TYPE_TEMP_GBOX_LABEL:
|
||||
+ mlxsw_hwmon_attr->dev_attr.show =
|
||||
+ mlxsw_hwmon_gbox_temp_label_show;
|
||||
+ mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
|
||||
+ snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
|
||||
+ "temp%u_label", num + 1);
|
||||
+ break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
}
|
||||
@@ -553,6 +586,43 @@ static int mlxsw_hwmon_module_init(struct mlxsw_hwmon *mlxsw_hwmon)
|
||||
index, index);
|
||||
index++;
|
||||
}
|
||||
+ mlxsw_hwmon->module_sensor_count = index;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mlxsw_hwmon_gearbox_init(struct mlxsw_hwmon *mlxsw_hwmon)
|
||||
+{
|
||||
+ char mgpir_pl[MLXSW_REG_MGPIR_LEN];
|
||||
+ int index, max_index;
|
||||
+ u8 gbox_num;
|
||||
+ int err;
|
||||
+
|
||||
+ mlxsw_reg_mgpir_pack(mgpir_pl);
|
||||
+ err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mgpir), mgpir_pl);
|
||||
+ if (err)
|
||||
+ return 0;
|
||||
+
|
||||
+ mlxsw_reg_mgpir_unpack(mgpir_pl, &gbox_num, NULL, NULL);
|
||||
+ if (!gbox_num)
|
||||
+ return 0;
|
||||
+
|
||||
+ index = mlxsw_hwmon->module_sensor_count;
|
||||
+ max_index = mlxsw_hwmon->module_sensor_count + gbox_num;
|
||||
+ while (index < max_index) {
|
||||
+ mlxsw_hwmon_attr_add(mlxsw_hwmon, MLXSW_HWMON_ATTR_TYPE_TEMP,
|
||||
+ index, index);
|
||||
+ mlxsw_hwmon_attr_add(mlxsw_hwmon,
|
||||
+ MLXSW_HWMON_ATTR_TYPE_TEMP_MAX, index,
|
||||
+ index);
|
||||
+ mlxsw_hwmon_attr_add(mlxsw_hwmon,
|
||||
+ MLXSW_HWMON_ATTR_TYPE_TEMP_RST, index,
|
||||
+ index);
|
||||
+ mlxsw_hwmon_attr_add(mlxsw_hwmon,
|
||||
+ MLXSW_HWMON_ATTR_TYPE_TEMP_GBOX_LABEL,
|
||||
+ index, index);
|
||||
+ index++;
|
||||
+ }
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -583,6 +653,10 @@ int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core,
|
||||
if (err)
|
||||
goto err_temp_module_init;
|
||||
|
||||
+ err = mlxsw_hwmon_gearbox_init(mlxsw_hwmon);
|
||||
+ if (err)
|
||||
+ goto err_temp_gearbox_init;
|
||||
+
|
||||
mlxsw_hwmon->groups[0] = &mlxsw_hwmon->group;
|
||||
mlxsw_hwmon->group.attrs = mlxsw_hwmon->attrs;
|
||||
|
||||
@@ -599,6 +673,7 @@ int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core,
|
||||
return 0;
|
||||
|
||||
err_hwmon_register:
|
||||
+err_temp_gearbox_init:
|
||||
err_temp_module_init:
|
||||
err_fans_init:
|
||||
err_temp_init:
|
||||
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
|
||||
index 1f7ef90b2270..5f970798ab6a 100644
|
||||
--- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
|
||||
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
|
||||
@@ -112,6 +112,8 @@ struct mlxsw_thermal {
|
||||
enum thermal_device_mode mode;
|
||||
struct mlxsw_thermal_module *tz_module_arr;
|
||||
unsigned int tz_module_num;
|
||||
+ struct mlxsw_thermal_module *tz_gearbox_arr;
|
||||
+ u8 tz_gearbox_num;
|
||||
};
|
||||
|
||||
static inline u8 mlxsw_state_to_duty(int state)
|
||||
@@ -546,62 +548,61 @@ mlxsw_thermal_module_trip_hyst_set(struct thermal_zone_device *tzdev, int trip,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int mlxsw_thermal_module_trend_get(struct thermal_zone_device *tzdev,
|
||||
- int trip, enum thermal_trend *trend)
|
||||
+static struct thermal_zone_params mlxsw_thermal_module_params = {
|
||||
+ .governor_name = "user_space",
|
||||
+};
|
||||
+
|
||||
+static struct thermal_zone_device_ops mlxsw_thermal_module_ops = {
|
||||
+ .bind = mlxsw_thermal_module_bind,
|
||||
+ .unbind = mlxsw_thermal_module_unbind,
|
||||
+ .get_mode = mlxsw_thermal_module_mode_get,
|
||||
+ .set_mode = mlxsw_thermal_module_mode_set,
|
||||
+ .get_temp = mlxsw_thermal_module_temp_get,
|
||||
+ .get_trip_type = mlxsw_thermal_module_trip_type_get,
|
||||
+ .get_trip_temp = mlxsw_thermal_module_trip_temp_get,
|
||||
+ .set_trip_temp = mlxsw_thermal_module_trip_temp_set,
|
||||
+ .get_trip_hyst = mlxsw_thermal_module_trip_hyst_get,
|
||||
+ .set_trip_hyst = mlxsw_thermal_module_trip_hyst_set,
|
||||
+};
|
||||
+
|
||||
+static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev,
|
||||
+ int *p_temp)
|
||||
{
|
||||
struct mlxsw_thermal_module *tz = tzdev->devdata;
|
||||
struct mlxsw_thermal *thermal = tz->parent;
|
||||
- struct device *dev = thermal->bus_info->dev;
|
||||
- char *envp[2] = { "TZ_DOWN=1", NULL };
|
||||
- int delta, window;
|
||||
+ char mtmp_pl[MLXSW_REG_MTMP_LEN];
|
||||
+ unsigned int temp;
|
||||
+ u16 index;
|
||||
int err;
|
||||
|
||||
- if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
|
||||
- return -EINVAL;
|
||||
+ index = MLXSW_REG_MTMP_GBOX_INDEX_MIN + tz->module;
|
||||
+ mlxsw_reg_mtmp_pack(mtmp_pl, index, false, false);
|
||||
|
||||
- delta = tzdev->last_temperature - tzdev->temperature;
|
||||
- window = tz->trips[MLXSW_THERMAL_TEMP_TRIP_HIGH].temp -
|
||||
- tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp;
|
||||
- if (delta > window && !window && !tzdev->last_temperature) {
|
||||
- /* Notify user about fast temperature decreasing by sending
|
||||
- * hwmon uevent. Fast decreasing could happen when some hot
|
||||
- * module is removed. In this situation temperature trend could
|
||||
- * go down once, and then stay in a stable state.
|
||||
- * Notification will allow user to handle such case, if user
|
||||
- * supposes to optimize PWM state.
|
||||
- */
|
||||
- err = kobject_uevent_env(&tzdev->device.kobj, KOBJ_CHANGE,
|
||||
- envp);
|
||||
- if (err)
|
||||
- dev_err(dev, "Error sending uevent %s\n", envp[0]);
|
||||
- }
|
||||
+ err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
|
||||
- if (tzdev->temperature > tzdev->last_temperature)
|
||||
- *trend = THERMAL_TREND_RAISING;
|
||||
- else if (tzdev->temperature < tzdev->last_temperature)
|
||||
- *trend = THERMAL_TREND_DROPPING;
|
||||
- else
|
||||
- *trend = THERMAL_TREND_STABLE;
|
||||
+ mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL);
|
||||
|
||||
+ *p_temp = (int) temp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static struct thermal_zone_params mlxsw_thermal_module_params = {
|
||||
- .governor_name = "user_space",
|
||||
-};
|
||||
-
|
||||
-static struct thermal_zone_device_ops mlxsw_thermal_module_ops = {
|
||||
+static struct thermal_zone_device_ops mlxsw_thermal_gearbox_ops = {
|
||||
.bind = mlxsw_thermal_module_bind,
|
||||
.unbind = mlxsw_thermal_module_unbind,
|
||||
.get_mode = mlxsw_thermal_module_mode_get,
|
||||
.set_mode = mlxsw_thermal_module_mode_set,
|
||||
- .get_temp = mlxsw_thermal_module_temp_get,
|
||||
+ .get_temp = mlxsw_thermal_gearbox_temp_get,
|
||||
.get_trip_type = mlxsw_thermal_module_trip_type_get,
|
||||
.get_trip_temp = mlxsw_thermal_module_trip_temp_get,
|
||||
.set_trip_temp = mlxsw_thermal_module_trip_temp_set,
|
||||
.get_trip_hyst = mlxsw_thermal_module_trip_hyst_get,
|
||||
.set_trip_hyst = mlxsw_thermal_module_trip_hyst_set,
|
||||
- .get_trend = mlxsw_thermal_module_trend_get,
|
||||
+};
|
||||
+
|
||||
+static struct thermal_zone_params mlxsw_thermal_gearbox_params = {
|
||||
+ .governor_name = "user_space",
|
||||
};
|
||||
|
||||
static int mlxsw_thermal_get_max_state(struct thermal_cooling_device *cdev,
|
||||
@@ -752,7 +753,7 @@ mlxsw_thermal_module_init(struct device *dev, struct mlxsw_core *core,
|
||||
|
||||
module = mlxsw_reg_pmlp_module_get(pmlp_pl, 0);
|
||||
module_tz = &thermal->tz_module_arr[module];
|
||||
- /* Skip if parent is already set - could in in case of port split. */
|
||||
+ /* Skip if parent is already set (case of port split). */
|
||||
if (module_tz->parent)
|
||||
return 0;
|
||||
module_tz->module = module;
|
||||
@@ -776,7 +777,7 @@ static void mlxsw_thermal_module_fini(struct mlxsw_thermal_module *module_tz)
|
||||
if (module_tz && module_tz->tzdev) {
|
||||
mlxsw_thermal_module_tz_fini(module_tz->tzdev);
|
||||
module_tz->tzdev = NULL;
|
||||
- module_tz->parent = 0;
|
||||
+ module_tz->parent = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -830,6 +831,89 @@ mlxsw_thermal_modules_fini(struct mlxsw_thermal *thermal)
|
||||
kfree(thermal->tz_module_arr);
|
||||
}
|
||||
|
||||
+static int
|
||||
+mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module *gearbox_tz)
|
||||
+{
|
||||
+ char tz_name[MLXSW_THERMAL_ZONE_MAX_NAME];
|
||||
+ int err;
|
||||
+
|
||||
+ snprintf(tz_name, sizeof(tz_name), "mlxsw-gearbox%d",
|
||||
+ gearbox_tz->module + 1);
|
||||
+ gearbox_tz->tzdev = thermal_zone_device_register(tz_name,
|
||||
+ MLXSW_THERMAL_NUM_TRIPS,
|
||||
+ MLXSW_THERMAL_TRIP_MASK,
|
||||
+ gearbox_tz,
|
||||
+ &mlxsw_thermal_gearbox_ops,
|
||||
+ &mlxsw_thermal_gearbox_params,
|
||||
+ 0, 0);
|
||||
+ if (IS_ERR(gearbox_tz->tzdev)) {
|
||||
+ err = PTR_ERR(gearbox_tz->tzdev);
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+mlxsw_thermal_gearbox_tz_fini(struct mlxsw_thermal_module *gearbox_tz)
|
||||
+{
|
||||
+ thermal_zone_device_unregister(gearbox_tz->tzdev);
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core,
|
||||
+ struct mlxsw_thermal *thermal)
|
||||
+{
|
||||
+ struct mlxsw_thermal_module *gearbox_tz;
|
||||
+ char mgpir_pl[MLXSW_REG_MGPIR_LEN];
|
||||
+ int i;
|
||||
+ int err;
|
||||
+
|
||||
+ mlxsw_reg_mgpir_pack(mgpir_pl);
|
||||
+ err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl);
|
||||
+ if (err)
|
||||
+ return 0;
|
||||
+
|
||||
+ mlxsw_reg_mgpir_unpack(mgpir_pl, &thermal->tz_gearbox_num, NULL, NULL);
|
||||
+ if (!thermal->tz_gearbox_num)
|
||||
+ return 0;
|
||||
+
|
||||
+ thermal->tz_gearbox_arr = kcalloc(thermal->tz_gearbox_num,
|
||||
+ sizeof(*thermal->tz_gearbox_arr),
|
||||
+ GFP_KERNEL);
|
||||
+ if (!thermal->tz_gearbox_arr)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ for (i = 0; i < thermal->tz_gearbox_num; i++) {
|
||||
+ gearbox_tz = &thermal->tz_gearbox_arr[i];
|
||||
+ memcpy(gearbox_tz->trips, default_thermal_trips,
|
||||
+ sizeof(thermal->trips));
|
||||
+ gearbox_tz->module = i;
|
||||
+ gearbox_tz->parent = thermal;
|
||||
+ err = mlxsw_thermal_gearbox_tz_init(gearbox_tz);
|
||||
+ if (err)
|
||||
+ goto err_unreg_tz_gearbox;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+err_unreg_tz_gearbox:
|
||||
+ for (i--; i >= 0; i--)
|
||||
+ mlxsw_thermal_gearbox_tz_fini(&thermal->tz_gearbox_arr[i]);
|
||||
+ kfree(thermal->tz_gearbox_arr);
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+mlxsw_thermal_gearboxes_fini(struct mlxsw_thermal *thermal)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = thermal->tz_gearbox_num - 1; i >= 0; i--)
|
||||
+ mlxsw_thermal_gearbox_tz_fini(&thermal->tz_gearbox_arr[i]);
|
||||
+ kfree(thermal->tz_gearbox_arr);
|
||||
+}
|
||||
+
|
||||
int mlxsw_thermal_init(struct mlxsw_core *core,
|
||||
const struct mlxsw_bus_info *bus_info,
|
||||
struct mlxsw_thermal **p_thermal)
|
||||
@@ -920,6 +1004,10 @@ int mlxsw_thermal_init(struct mlxsw_core *core,
|
||||
if (err)
|
||||
goto err_unreg_tzdev;
|
||||
|
||||
+ mlxsw_thermal_gearboxes_init(dev, core, thermal);
|
||||
+ if (err)
|
||||
+ goto err_unreg_modules_tzdev;
|
||||
+
|
||||
thermal->mode = THERMAL_DEVICE_ENABLED;
|
||||
*p_thermal = thermal;
|
||||
return 0;
|
||||
@@ -944,6 +1032,7 @@ void mlxsw_thermal_fini(struct mlxsw_thermal *thermal)
|
||||
{
|
||||
int i;
|
||||
|
||||
+ mlxsw_thermal_gearboxes_fini(thermal);
|
||||
mlxsw_thermal_modules_fini(thermal);
|
||||
if (thermal->tzdev) {
|
||||
thermal_zone_device_unregister(thermal->tzdev);
|
||||
diff --git a/drivers/net/ethernet/mellanox/mlxsw/qsfp_sysfs.c b/drivers/net/ethernet/mellanox/mlxsw/qsfp_sysfs.c
|
||||
index bee2a08d372b..347f9823e375 100644
|
||||
--- a/drivers/net/ethernet/mellanox/mlxsw/qsfp_sysfs.c
|
||||
+++ b/drivers/net/ethernet/mellanox/mlxsw/qsfp_sysfs.c
|
||||
@@ -268,6 +268,13 @@ static const struct dmi_system_id mlxsw_qsfp_dmi_table[] = {
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "MSN37"),
|
||||
},
|
||||
},
|
||||
+ {
|
||||
+ .callback = mlxsw_qsfp_dmi_set_qsfp_num,
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
|
||||
+ DMI_MATCH(DMI_PRODUCT_NAME, "MSN38"),
|
||||
+ },
|
||||
+ },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(dmi, mlxsw_qsfp_dmi_table);
|
||||
diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h
|
||||
index 94407dcfacdb..f16d27e115d2 100644
|
||||
--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h
|
||||
+++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h
|
||||
@@ -7589,6 +7589,7 @@ MLXSW_ITEM32(reg, mtcap, sensor_count, 0x00, 0, 7);
|
||||
*/
|
||||
#define MLXSW_REG_MTMP_ID 0x900A
|
||||
#define MLXSW_REG_MTMP_LEN 0x20
|
||||
+#define MLXSW_REG_MTMP_GBOX_INDEX_MIN 256
|
||||
|
||||
MLXSW_REG_DEFINE(mtmp, MLXSW_REG_MTMP_ID, MLXSW_REG_MTMP_LEN);
|
||||
|
||||
@@ -7598,7 +7599,7 @@ MLXSW_REG_DEFINE(mtmp, MLXSW_REG_MTMP_ID, MLXSW_REG_MTMP_LEN);
|
||||
* (module 0 is mapped to sensor_index 64).
|
||||
* Access: Index
|
||||
*/
|
||||
-MLXSW_ITEM32(reg, mtmp, sensor_index, 0x00, 0, 7);
|
||||
+MLXSW_ITEM32(reg, mtmp, sensor_index, 0x00, 0, 11);
|
||||
|
||||
/* Convert to milli degrees Celsius */
|
||||
#define MLXSW_REG_MTMP_TEMP_TO_MC(val) (val * 125)
|
||||
@@ -7660,7 +7661,7 @@ MLXSW_ITEM32(reg, mtmp, temperature_threshold_lo, 0x10, 0, 16);
|
||||
*/
|
||||
MLXSW_ITEM_BUF(reg, mtmp, sensor_name, 0x18, MLXSW_REG_MTMP_SENSOR_NAME_SIZE);
|
||||
|
||||
-static inline void mlxsw_reg_mtmp_pack(char *payload, u8 sensor_index,
|
||||
+static inline void mlxsw_reg_mtmp_pack(char *payload, u16 sensor_index,
|
||||
bool max_temp_enable,
|
||||
bool max_temp_reset)
|
||||
{
|
||||
@@ -8579,6 +8580,56 @@ static inline void mlxsw_reg_mprs_pack(char *payload, u16 parsing_depth,
|
||||
mlxsw_reg_mprs_vxlan_udp_dport_set(payload, vxlan_udp_dport);
|
||||
}
|
||||
|
||||
+/* MGPIR - Management General Peripheral Information Register
|
||||
+ * ----------------------------------------------------------
|
||||
+ * MGPIR register allows software to query the hardware and
|
||||
+ * firmware general information of peripheral entities.
|
||||
+ */
|
||||
+#define MLXSW_REG_MGPIR_ID 0x9100
|
||||
+#define MLXSW_REG_MGPIR_LEN 0xA0
|
||||
+
|
||||
+MLXSW_REG_DEFINE(mgpir, MLXSW_REG_MGPIR_ID, MLXSW_REG_MGPIR_LEN);
|
||||
+
|
||||
+/* device_type
|
||||
+ * Access: RO
|
||||
+ */
|
||||
+MLXSW_ITEM32(reg, mgpir, device_type, 0x00, 24, 4);
|
||||
+
|
||||
+/* devices_per_flash
|
||||
+ * Number of devices of device_type per flash (can be shared by few devices).
|
||||
+ * Access: RO
|
||||
+ */
|
||||
+MLXSW_ITEM32(reg, mgpir, devices_per_flash, 0x00, 16, 8);
|
||||
+
|
||||
+/* num_of_devices
|
||||
+ * Number of devices of device_type.
|
||||
+ * Access: RO
|
||||
+ */
|
||||
+MLXSW_ITEM32(reg, mgpir, num_of_devices, 0x00, 0, 8);
|
||||
+
|
||||
+enum mlxsw_reg_mgpir_device_type {
|
||||
+ MLXSW_REG_MGPIR_TYPE_NONE,
|
||||
+ MLXSW_REG_MGPIR_TYPE_GEARBOX_DIE,
|
||||
+};
|
||||
+
|
||||
+static inline void mlxsw_reg_mgpir_pack(char *payload)
|
||||
+{
|
||||
+ MLXSW_REG_ZERO(mgpir, payload);
|
||||
+}
|
||||
+
|
||||
+static inline void mlxsw_reg_mgpir_unpack(char *payload, u8 *num_of_devices,
|
||||
+ u8 *device_type,
|
||||
+ u8 *devices_per_flash)
|
||||
+{
|
||||
+ if (num_of_devices)
|
||||
+ *num_of_devices = mlxsw_reg_mgpir_num_of_devices_get(payload);
|
||||
+ if (device_type)
|
||||
+ *device_type = mlxsw_reg_mgpir_device_type_get(payload);
|
||||
+ if (devices_per_flash)
|
||||
+ *devices_per_flash =
|
||||
+ mlxsw_reg_mgpir_devices_per_flash_get(payload);
|
||||
+}
|
||||
+
|
||||
/* TNGCR - Tunneling NVE General Configuration Register
|
||||
* ----------------------------------------------------
|
||||
* The TNGCR register is used for setting up the NVE Tunneling configuration.
|
||||
@@ -9591,6 +9642,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = {
|
||||
MLXSW_REG(mcda),
|
||||
MLXSW_REG(mgpc),
|
||||
MLXSW_REG(mprs),
|
||||
+ MLXSW_REG(mgpir),
|
||||
MLXSW_REG(tngcr),
|
||||
MLXSW_REG(tnumt),
|
||||
MLXSW_REG(tnqcr),
|
||||
diff --git a/drivers/platform/mellanox/mlxreg-hotplug.c b/drivers/platform/mellanox/mlxreg-hotplug.c
|
||||
index 52314a1ffaaf..687ce6817d0d 100644
|
||||
--- a/drivers/platform/mellanox/mlxreg-hotplug.c
|
||||
+++ b/drivers/platform/mellanox/mlxreg-hotplug.c
|
||||
@@ -248,7 +248,8 @@ mlxreg_hotplug_work_helper(struct mlxreg_hotplug_priv_data *priv,
|
||||
struct mlxreg_core_item *item)
|
||||
{
|
||||
struct mlxreg_core_data *data;
|
||||
- u32 asserted, regval, bit;
|
||||
+ unsigned long asserted;
|
||||
+ u32 regval, bit;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
@@ -281,7 +282,7 @@ mlxreg_hotplug_work_helper(struct mlxreg_hotplug_priv_data *priv,
|
||||
asserted = item->cache ^ regval;
|
||||
item->cache = regval;
|
||||
|
||||
- for_each_set_bit(bit, (unsigned long *)&asserted, 8) {
|
||||
+ for_each_set_bit(bit, &asserted, 8) {
|
||||
data = item->data + bit;
|
||||
if (regval & BIT(bit)) {
|
||||
if (item->inversed)
|
||||
diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c
|
||||
index af033fb2e5d9..d5d2448dc7e4 100644
|
||||
--- a/drivers/platform/x86/mlx-platform.c
|
||||
+++ b/drivers/platform/x86/mlx-platform.c
|
||||
@@ -938,6 +938,11 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_led_data[] = {
|
||||
.capability = MLXPLAT_CPLD_LPC_REG_FAN_DRW_CAP_OFFSET,
|
||||
.bit = BIT(5),
|
||||
},
|
||||
+ {
|
||||
+ .label = "uid:blue",
|
||||
+ .reg = MLXPLAT_CPLD_LPC_REG_LED5_OFFSET,
|
||||
+ .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
|
||||
+ },
|
||||
};
|
||||
|
||||
static struct mlxreg_core_platform_data mlxplat_default_ng_led_data = {
|
||||
@@ -1361,7 +1366,6 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
|
||||
},
|
||||
{
|
||||
.label = "conf",
|
||||
- .reg = MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET,
|
||||
.capability = MLXPLAT_CPLD_LPC_REG_TACHO_SPEED_OFFSET,
|
||||
},
|
||||
};
|
||||
--
|
||||
2.11.0
|
||||
|
||||
@@ -0,0 +1,668 @@
|
||||
From 8c964a3e17bb41eef69c81d45864d72cbc1185f4 Mon Sep 17 00:00:00 2001
|
||||
From: Vadim Pasternak <vadimp@mellanox.com>
|
||||
Date: Fri, 17 May 2019 09:22:21 +0000
|
||||
Subject: [PATCH backport 5.2] mlxsw: minimal: Provide optimization for I2C bus
|
||||
access
|
||||
|
||||
Use register MTMP instead of MTBR.
|
||||
Use maximum buffer size allowed by I2C adapter.
|
||||
|
||||
Signed-off-by: Vadim Pasternak <vadimp@mellanox.com>
|
||||
---
|
||||
drivers/i2c/busses/i2c-mlxcpld.c | 2 +-
|
||||
drivers/net/ethernet/mellanox/mlxsw/core.c | 6 ++
|
||||
drivers/net/ethernet/mellanox/mlxsw/core.h | 2 +
|
||||
drivers/net/ethernet/mellanox/mlxsw/core_env.c | 29 ++-----
|
||||
drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c | 98 +++++++++-------------
|
||||
drivers/net/ethernet/mellanox/mlxsw/core_thermal.c | 60 +++++++------
|
||||
drivers/net/ethernet/mellanox/mlxsw/i2c.c | 56 +++++++++----
|
||||
drivers/net/ethernet/mellanox/mlxsw/minimal.c | 18 ++++
|
||||
drivers/net/ethernet/mellanox/mlxsw/reg.h | 7 +-
|
||||
9 files changed, 144 insertions(+), 134 deletions(-)
|
||||
|
||||
diff --git a/drivers/i2c/busses/i2c-mlxcpld.c b/drivers/i2c/busses/i2c-mlxcpld.c
|
||||
index 745ed43a22d6..2fd717d8dd30 100644
|
||||
--- a/drivers/i2c/busses/i2c-mlxcpld.c
|
||||
+++ b/drivers/i2c/busses/i2c-mlxcpld.c
|
||||
@@ -503,6 +503,7 @@ static int mlxcpld_i2c_probe(struct platform_device *pdev)
|
||||
platform_set_drvdata(pdev, priv);
|
||||
|
||||
priv->dev = &pdev->dev;
|
||||
+ priv->base_addr = MLXPLAT_CPLD_LPC_I2C_BASE_ADDR;
|
||||
|
||||
/* Register with i2c layer */
|
||||
mlxcpld_i2c_adapter.timeout = usecs_to_jiffies(MLXCPLD_I2C_XFER_TO);
|
||||
@@ -518,7 +519,6 @@ static int mlxcpld_i2c_probe(struct platform_device *pdev)
|
||||
mlxcpld_i2c_adapter.nr = pdev->id;
|
||||
priv->adap = mlxcpld_i2c_adapter;
|
||||
priv->adap.dev.parent = &pdev->dev;
|
||||
- priv->base_addr = MLXPLAT_CPLD_LPC_I2C_BASE_ADDR;
|
||||
i2c_set_adapdata(&priv->adap, priv);
|
||||
|
||||
err = i2c_add_numbered_adapter(&priv->adap);
|
||||
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c
|
||||
index e420451942e2..9a74ae8beb43 100644
|
||||
--- a/drivers/net/ethernet/mellanox/mlxsw/core.c
|
||||
+++ b/drivers/net/ethernet/mellanox/mlxsw/core.c
|
||||
@@ -122,6 +122,12 @@ void *mlxsw_core_driver_priv(struct mlxsw_core *mlxsw_core)
|
||||
}
|
||||
EXPORT_SYMBOL(mlxsw_core_driver_priv);
|
||||
|
||||
+bool mlxsw_core_res_query_enabled(const struct mlxsw_core *mlxsw_core)
|
||||
+{
|
||||
+ return mlxsw_core->driver->res_query_enabled;
|
||||
+}
|
||||
+EXPORT_SYMBOL(mlxsw_core_res_query_enabled);
|
||||
+
|
||||
struct mlxsw_rx_listener_item {
|
||||
struct list_head list;
|
||||
struct mlxsw_rx_listener rxl;
|
||||
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h
|
||||
index 76e8fd76ef36..1e1bcfd8d032 100644
|
||||
--- a/drivers/net/ethernet/mellanox/mlxsw/core.h
|
||||
+++ b/drivers/net/ethernet/mellanox/mlxsw/core.h
|
||||
@@ -28,6 +28,8 @@ unsigned int mlxsw_core_max_ports(const struct mlxsw_core *mlxsw_core);
|
||||
|
||||
void *mlxsw_core_driver_priv(struct mlxsw_core *mlxsw_core);
|
||||
|
||||
+bool mlxsw_core_res_query_enabled(const struct mlxsw_core *mlxsw_core);
|
||||
+
|
||||
int mlxsw_core_driver_register(struct mlxsw_driver *mlxsw_driver);
|
||||
void mlxsw_core_driver_unregister(struct mlxsw_driver *mlxsw_driver);
|
||||
|
||||
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c
|
||||
index edcf1b656cbf..d2c7ce67c300 100644
|
||||
--- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c
|
||||
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c
|
||||
@@ -92,33 +92,20 @@ int mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, int module,
|
||||
u16 temp;
|
||||
} temp_thresh;
|
||||
char mcia_pl[MLXSW_REG_MCIA_LEN] = {0};
|
||||
- char mtbr_pl[MLXSW_REG_MTBR_LEN] = {0};
|
||||
- u16 module_temp;
|
||||
+ char mtmp_pl[MLXSW_REG_MTMP_LEN];
|
||||
+ unsigned int module_temp;
|
||||
bool qsfp;
|
||||
int err;
|
||||
|
||||
- mlxsw_reg_mtbr_pack(mtbr_pl, MLXSW_REG_MTBR_BASE_MODULE_INDEX + module,
|
||||
- 1);
|
||||
- err = mlxsw_reg_query(core, MLXSW_REG(mtbr), mtbr_pl);
|
||||
+ mlxsw_reg_mtmp_pack(mtmp_pl, MLXSW_REG_MTMP_MODULE_INDEX_MIN + module,
|
||||
+ false, false);
|
||||
+ err = mlxsw_reg_query(core, MLXSW_REG(mtmp), mtmp_pl);
|
||||
if (err)
|
||||
return err;
|
||||
-
|
||||
- /* Don't read temperature thresholds for module with no valid info. */
|
||||
- mlxsw_reg_mtbr_temp_unpack(mtbr_pl, 0, &module_temp, NULL);
|
||||
- switch (module_temp) {
|
||||
- case MLXSW_REG_MTBR_BAD_SENS_INFO: /* fall-through */
|
||||
- case MLXSW_REG_MTBR_NO_CONN: /* fall-through */
|
||||
- case MLXSW_REG_MTBR_NO_TEMP_SENS: /* fall-through */
|
||||
- case MLXSW_REG_MTBR_INDEX_NA:
|
||||
+ mlxsw_reg_mtmp_unpack(mtmp_pl, &module_temp, NULL, NULL);
|
||||
+ if (!module_temp) {
|
||||
*temp = 0;
|
||||
return 0;
|
||||
- default:
|
||||
- /* Do not consider thresholds for zero temperature. */
|
||||
- if (!MLXSW_REG_MTMP_TEMP_TO_MC(module_temp)) {
|
||||
- *temp = 0;
|
||||
- return 0;
|
||||
- }
|
||||
- break;
|
||||
}
|
||||
|
||||
/* Read Free Side Device Temperature Thresholds from page 03h
|
||||
@@ -196,7 +183,7 @@ int mlxsw_env_get_module_info(struct mlxsw_core *mlxsw_core, int module,
|
||||
}
|
||||
break;
|
||||
case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_SFP:
|
||||
- /* Verify if transceiver provides digital diagnostic monitoring page */
|
||||
+ /* Verify if transceiver provides diagnostic monitoring page */
|
||||
err = mlxsw_env_query_module_eeprom(mlxsw_core, module,
|
||||
SFP_DIAGMON, 1, &diag_mon,
|
||||
&read_size);
|
||||
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c
|
||||
index 976f81a2bbba..a414a09efb5d 100644
|
||||
--- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c
|
||||
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c
|
||||
@@ -15,9 +15,6 @@
|
||||
#define MLXSW_HWMON_TEMP_SENSOR_MAX_COUNT 127
|
||||
#define MLXSW_HWMON_ATTR_COUNT (MLXSW_HWMON_TEMP_SENSOR_MAX_COUNT * 4 + \
|
||||
MLXSW_MFCR_TACHOS_MAX + MLXSW_MFCR_PWMS_MAX)
|
||||
-#define MLXSW_HWMON_GET_ATTR_INDEX(ind, count) \
|
||||
- (((ind) >= (count)) ? (ind) % (count) + \
|
||||
- MLXSW_REG_MTMP_GBOX_INDEX_MIN : (ind))
|
||||
|
||||
struct mlxsw_hwmon_attr {
|
||||
struct device_attribute dev_attr;
|
||||
@@ -26,6 +23,14 @@ struct mlxsw_hwmon_attr {
|
||||
char name[32];
|
||||
};
|
||||
|
||||
+static int mlxsw_hwmon_get_attr_index(int index, int count)
|
||||
+{
|
||||
+ if (index >= count)
|
||||
+ return index % count + MLXSW_REG_MTMP_GBOX_INDEX_MIN;
|
||||
+
|
||||
+ return index;
|
||||
+}
|
||||
+
|
||||
struct mlxsw_hwmon {
|
||||
struct mlxsw_core *core;
|
||||
const struct mlxsw_bus_info *bus_info;
|
||||
@@ -51,7 +56,7 @@ static ssize_t mlxsw_hwmon_temp_show(struct device *dev,
|
||||
int index;
|
||||
int err;
|
||||
|
||||
- index = MLXSW_HWMON_GET_ATTR_INDEX(mlwsw_hwmon_attr->type_index,
|
||||
+ index = mlxsw_hwmon_get_attr_index(mlwsw_hwmon_attr->type_index,
|
||||
mlxsw_hwmon->module_sensor_count);
|
||||
mlxsw_reg_mtmp_pack(mtmp_pl, index, false, false);
|
||||
err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl);
|
||||
@@ -75,7 +80,7 @@ static ssize_t mlxsw_hwmon_temp_max_show(struct device *dev,
|
||||
int index;
|
||||
int err;
|
||||
|
||||
- index = MLXSW_HWMON_GET_ATTR_INDEX(mlwsw_hwmon_attr->type_index,
|
||||
+ index = mlxsw_hwmon_get_attr_index(mlwsw_hwmon_attr->type_index,
|
||||
mlxsw_hwmon->module_sensor_count);
|
||||
mlxsw_reg_mtmp_pack(mtmp_pl, index, false, false);
|
||||
err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl);
|
||||
@@ -105,7 +110,7 @@ static ssize_t mlxsw_hwmon_temp_rst_store(struct device *dev,
|
||||
if (val != 1)
|
||||
return -EINVAL;
|
||||
|
||||
- index = MLXSW_HWMON_GET_ATTR_INDEX(mlwsw_hwmon_attr->type_index,
|
||||
+ index = mlxsw_hwmon_get_attr_index(mlwsw_hwmon_attr->type_index,
|
||||
mlxsw_hwmon->module_sensor_count);
|
||||
mlxsw_reg_mtmp_pack(mtmp_pl, index, true, true);
|
||||
err = mlxsw_reg_write(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl);
|
||||
@@ -209,38 +214,18 @@ static ssize_t mlxsw_hwmon_module_temp_show(struct device *dev,
|
||||
struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
|
||||
container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
|
||||
struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
|
||||
- char mtbr_pl[MLXSW_REG_MTBR_LEN] = {0};
|
||||
- u16 temp;
|
||||
+ char mtmp_pl[MLXSW_REG_MTMP_LEN];
|
||||
+ unsigned int temp;
|
||||
u8 module;
|
||||
int err;
|
||||
|
||||
module = mlwsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count;
|
||||
- mlxsw_reg_mtbr_pack(mtbr_pl, MLXSW_REG_MTBR_BASE_MODULE_INDEX + module,
|
||||
- 1);
|
||||
- err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtbr), mtbr_pl);
|
||||
- if (err) {
|
||||
- dev_err(dev, "Failed to query module temperature sensor\n");
|
||||
+ mlxsw_reg_mtmp_pack(mtmp_pl, MLXSW_REG_MTMP_MODULE_INDEX_MIN + module,
|
||||
+ false, false);
|
||||
+ err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl);
|
||||
+ if (err)
|
||||
return err;
|
||||
- }
|
||||
-
|
||||
- mlxsw_reg_mtbr_temp_unpack(mtbr_pl, 0, &temp, NULL);
|
||||
- /* Update status and temperature cache. */
|
||||
- switch (temp) {
|
||||
- case MLXSW_REG_MTBR_NO_CONN: /* fall-through */
|
||||
- case MLXSW_REG_MTBR_NO_TEMP_SENS: /* fall-through */
|
||||
- case MLXSW_REG_MTBR_INDEX_NA:
|
||||
- temp = 0;
|
||||
- break;
|
||||
- case MLXSW_REG_MTBR_BAD_SENS_INFO:
|
||||
- /* Untrusted cable is connected. Reading temperature from its
|
||||
- * sensor is faulty.
|
||||
- */
|
||||
- temp = 0;
|
||||
- break;
|
||||
- default:
|
||||
- temp = MLXSW_REG_MTMP_TEMP_TO_MC(temp);
|
||||
- break;
|
||||
- }
|
||||
+ mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL);
|
||||
|
||||
return sprintf(buf, "%u\n", temp);
|
||||
}
|
||||
@@ -252,37 +237,18 @@ static ssize_t mlxsw_hwmon_module_temp_fault_show(struct device *dev,
|
||||
struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
|
||||
container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
|
||||
struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
|
||||
- char mtbr_pl[MLXSW_REG_MTBR_LEN] = {0};
|
||||
+ char mtmp_pl[MLXSW_REG_MTMP_LEN];
|
||||
u8 module, fault;
|
||||
- u16 temp;
|
||||
int err;
|
||||
|
||||
module = mlwsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count;
|
||||
- mlxsw_reg_mtbr_pack(mtbr_pl, MLXSW_REG_MTBR_BASE_MODULE_INDEX + module,
|
||||
- 1);
|
||||
- err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtbr), mtbr_pl);
|
||||
- if (err) {
|
||||
- dev_err(dev, "Failed to query module temperature sensor\n");
|
||||
- return err;
|
||||
- }
|
||||
-
|
||||
- mlxsw_reg_mtbr_temp_unpack(mtbr_pl, 0, &temp, NULL);
|
||||
-
|
||||
- /* Update status and temperature cache. */
|
||||
- switch (temp) {
|
||||
- case MLXSW_REG_MTBR_BAD_SENS_INFO:
|
||||
- /* Untrusted cable is connected. Reading temperature from its
|
||||
- * sensor is faulty.
|
||||
- */
|
||||
+ mlxsw_reg_mtmp_pack(mtmp_pl, MLXSW_REG_MTBR_BASE_MODULE_INDEX + module,
|
||||
+ false, false);
|
||||
+ err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl);
|
||||
+ if (err)
|
||||
fault = 1;
|
||||
- break;
|
||||
- case MLXSW_REG_MTBR_NO_CONN: /* fall-through */
|
||||
- case MLXSW_REG_MTBR_NO_TEMP_SENS: /* fall-through */
|
||||
- case MLXSW_REG_MTBR_INDEX_NA:
|
||||
- default:
|
||||
+ else
|
||||
fault = 0;
|
||||
- break;
|
||||
- }
|
||||
|
||||
return sprintf(buf, "%u\n", fault);
|
||||
}
|
||||
@@ -551,6 +517,9 @@ static int mlxsw_hwmon_module_init(struct mlxsw_hwmon *mlxsw_hwmon)
|
||||
u8 width;
|
||||
int err;
|
||||
|
||||
+ if (!mlxsw_core_res_query_enabled(mlxsw_hwmon->core))
|
||||
+ return 0;
|
||||
+
|
||||
/* Add extra attributes for module temperature. Sensor index is
|
||||
* assigned to sensor_count value, while all indexed before
|
||||
* sensor_count are already utilized by the sensors connected through
|
||||
@@ -593,8 +562,9 @@ static int mlxsw_hwmon_module_init(struct mlxsw_hwmon *mlxsw_hwmon)
|
||||
|
||||
static int mlxsw_hwmon_gearbox_init(struct mlxsw_hwmon *mlxsw_hwmon)
|
||||
{
|
||||
+ int index, max_index, sensor_index;
|
||||
char mgpir_pl[MLXSW_REG_MGPIR_LEN];
|
||||
- int index, max_index;
|
||||
+ char mtmp_pl[MLXSW_REG_MTMP_LEN];
|
||||
u8 gbox_num;
|
||||
int err;
|
||||
|
||||
@@ -610,6 +580,16 @@ static int mlxsw_hwmon_gearbox_init(struct mlxsw_hwmon *mlxsw_hwmon)
|
||||
index = mlxsw_hwmon->module_sensor_count;
|
||||
max_index = mlxsw_hwmon->module_sensor_count + gbox_num;
|
||||
while (index < max_index) {
|
||||
+ sensor_index = index % mlxsw_hwmon->module_sensor_count +
|
||||
+ MLXSW_REG_MTMP_GBOX_INDEX_MIN;
|
||||
+ mlxsw_reg_mtmp_pack(mtmp_pl, sensor_index, true, true);
|
||||
+ err = mlxsw_reg_write(mlxsw_hwmon->core,
|
||||
+ MLXSW_REG(mtmp), mtmp_pl);
|
||||
+ if (err) {
|
||||
+ dev_err(mlxsw_hwmon->bus_info->dev, "Failed to setup temp sensor number %d\n",
|
||||
+ sensor_index);
|
||||
+ return err;
|
||||
+ }
|
||||
mlxsw_hwmon_attr_add(mlxsw_hwmon, MLXSW_HWMON_ATTR_TYPE_TEMP,
|
||||
index, index);
|
||||
mlxsw_hwmon_attr_add(mlxsw_hwmon,
|
||||
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
|
||||
index 5f970798ab6a..e9451e447bf0 100644
|
||||
--- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
|
||||
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
|
||||
@@ -452,36 +452,27 @@ static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev,
|
||||
struct mlxsw_thermal_module *tz = tzdev->devdata;
|
||||
struct mlxsw_thermal *thermal = tz->parent;
|
||||
struct device *dev = thermal->bus_info->dev;
|
||||
- char mtbr_pl[MLXSW_REG_MTBR_LEN];
|
||||
- u16 temp;
|
||||
+ char mtmp_pl[MLXSW_REG_MTMP_LEN];
|
||||
+ unsigned int temp;
|
||||
int err;
|
||||
|
||||
/* Read module temperature. */
|
||||
- mlxsw_reg_mtbr_pack(mtbr_pl, MLXSW_REG_MTBR_BASE_MODULE_INDEX +
|
||||
- tz->module, 1);
|
||||
- err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtbr), mtbr_pl);
|
||||
- if (err)
|
||||
- return err;
|
||||
-
|
||||
- mlxsw_reg_mtbr_temp_unpack(mtbr_pl, 0, &temp, NULL);
|
||||
- /* Update temperature. */
|
||||
- switch (temp) {
|
||||
- case MLXSW_REG_MTBR_NO_CONN: /* fall-through */
|
||||
- case MLXSW_REG_MTBR_NO_TEMP_SENS: /* fall-through */
|
||||
- case MLXSW_REG_MTBR_INDEX_NA: /* fall-through */
|
||||
- case MLXSW_REG_MTBR_BAD_SENS_INFO:
|
||||
+ mlxsw_reg_mtmp_pack(mtmp_pl, MLXSW_REG_MTMP_MODULE_INDEX_MIN +
|
||||
+ tz->module, false, false);
|
||||
+ err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl);
|
||||
+ if (err) {
|
||||
+ dev_err(dev, "Failed to query temp sensor\n");
|
||||
temp = 0;
|
||||
- break;
|
||||
- default:
|
||||
- temp = MLXSW_REG_MTMP_TEMP_TO_MC(temp);
|
||||
- /* Reset all trip point. */
|
||||
- mlxsw_thermal_module_trips_reset(tz);
|
||||
- /* Update trip points. */
|
||||
+ *p_temp = (int) temp;
|
||||
+ return 0;
|
||||
+ }
|
||||
+ mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL);
|
||||
+
|
||||
+ if (temp) {
|
||||
err = mlxsw_thermal_module_trips_update(dev, thermal->core,
|
||||
tz);
|
||||
if (err)
|
||||
return err;
|
||||
- break;
|
||||
}
|
||||
|
||||
*p_temp = (int) temp;
|
||||
@@ -714,12 +705,12 @@ mlxsw_thermal_module_tz_init(struct mlxsw_thermal_module *module_tz)
|
||||
snprintf(tz_name, sizeof(tz_name), "mlxsw-module%d",
|
||||
module_tz->module + 1);
|
||||
module_tz->tzdev = thermal_zone_device_register(tz_name,
|
||||
- MLXSW_THERMAL_NUM_TRIPS,
|
||||
- MLXSW_THERMAL_TRIP_MASK,
|
||||
- module_tz,
|
||||
- &mlxsw_thermal_module_ops,
|
||||
- &mlxsw_thermal_module_params,
|
||||
- 0, 0);
|
||||
+ MLXSW_THERMAL_NUM_TRIPS,
|
||||
+ MLXSW_THERMAL_TRIP_MASK,
|
||||
+ module_tz,
|
||||
+ &mlxsw_thermal_module_ops,
|
||||
+ &mlxsw_thermal_module_params,
|
||||
+ 0, 0);
|
||||
if (IS_ERR(module_tz->tzdev)) {
|
||||
err = PTR_ERR(module_tz->tzdev);
|
||||
return err;
|
||||
@@ -789,6 +780,9 @@ mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core,
|
||||
struct mlxsw_thermal_module *module_tz;
|
||||
int i, err;
|
||||
|
||||
+ if (!mlxsw_core_res_query_enabled(core))
|
||||
+ return 0;
|
||||
+
|
||||
thermal->tz_module_arr = kcalloc(module_count,
|
||||
sizeof(*thermal->tz_module_arr),
|
||||
GFP_KERNEL);
|
||||
@@ -801,8 +795,7 @@ mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core,
|
||||
goto err_unreg_tz_module_arr;
|
||||
}
|
||||
|
||||
- module_count -= 1;
|
||||
- for (i = 0; i < module_count; i++) {
|
||||
+ for (i = 0; i < module_count - 1; i++) {
|
||||
module_tz = &thermal->tz_module_arr[i];
|
||||
if (!module_tz->parent)
|
||||
continue;
|
||||
@@ -814,7 +807,7 @@ mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core,
|
||||
return 0;
|
||||
|
||||
err_unreg_tz_module_arr:
|
||||
- for (i = module_count; i >= 0; i--)
|
||||
+ for (i = module_count - 1; i >= 0; i--)
|
||||
mlxsw_thermal_module_fini(&thermal->tz_module_arr[i]);
|
||||
kfree(thermal->tz_module_arr);
|
||||
return err;
|
||||
@@ -826,6 +819,9 @@ mlxsw_thermal_modules_fini(struct mlxsw_thermal *thermal)
|
||||
unsigned int module_count = mlxsw_core_max_ports(thermal->core);
|
||||
int i;
|
||||
|
||||
+ if (!mlxsw_core_res_query_enabled(thermal->core))
|
||||
+ return;
|
||||
+
|
||||
for (i = module_count - 1; i >= 0; i--)
|
||||
mlxsw_thermal_module_fini(&thermal->tz_module_arr[i]);
|
||||
kfree(thermal->tz_module_arr);
|
||||
@@ -910,7 +906,7 @@ mlxsw_thermal_gearboxes_fini(struct mlxsw_thermal *thermal)
|
||||
int i;
|
||||
|
||||
for (i = thermal->tz_gearbox_num - 1; i >= 0; i--)
|
||||
- mlxsw_thermal_gearbox_tz_fini(&thermal->tz_gearbox_arr[i]);
|
||||
+ mlxsw_thermal_gearbox_tz_fini(&thermal->tz_gearbox_arr[i]); /*Remove*/
|
||||
kfree(thermal->tz_gearbox_arr);
|
||||
}
|
||||
|
||||
diff --git a/drivers/net/ethernet/mellanox/mlxsw/i2c.c b/drivers/net/ethernet/mellanox/mlxsw/i2c.c
|
||||
index 307fd5fcd302..08c774875d1e 100644
|
||||
--- a/drivers/net/ethernet/mellanox/mlxsw/i2c.c
|
||||
+++ b/drivers/net/ethernet/mellanox/mlxsw/i2c.c
|
||||
@@ -43,11 +43,10 @@
|
||||
#define MLXSW_I2C_PREP_SIZE (MLXSW_I2C_ADDR_WIDTH + 28)
|
||||
#define MLXSW_I2C_MBOX_SIZE 20
|
||||
#define MLXSW_I2C_MBOX_OUT_PARAM_OFF 12
|
||||
-#define MLXSW_I2C_MAX_BUFF_SIZE 32
|
||||
#define MLXSW_I2C_MBOX_OFFSET_BITS 20
|
||||
#define MLXSW_I2C_MBOX_SIZE_BITS 12
|
||||
#define MLXSW_I2C_ADDR_BUF_SIZE 4
|
||||
-#define MLXSW_I2C_BLK_MAX 32
|
||||
+#define MLXSW_I2C_BLK_DEF 32
|
||||
#define MLXSW_I2C_RETRY 5
|
||||
#define MLXSW_I2C_TIMEOUT_MSECS 5000
|
||||
#define MLXSW_I2C_MAX_DATA_SIZE 256
|
||||
@@ -62,6 +61,7 @@
|
||||
* @dev: I2C device;
|
||||
* @core: switch core pointer;
|
||||
* @bus_info: bus info block;
|
||||
+ * @block_size: maximum block size allowed to pass to under layer;
|
||||
*/
|
||||
struct mlxsw_i2c {
|
||||
struct {
|
||||
@@ -74,6 +74,7 @@ struct mlxsw_i2c {
|
||||
struct device *dev;
|
||||
struct mlxsw_core *core;
|
||||
struct mlxsw_bus_info bus_info;
|
||||
+ u16 block_size;
|
||||
};
|
||||
|
||||
#define MLXSW_I2C_READ_MSG(_client, _addr_buf, _buf, _len) { \
|
||||
@@ -315,20 +316,26 @@ mlxsw_i2c_write(struct device *dev, size_t in_mbox_size, u8 *in_mbox, int num,
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct mlxsw_i2c *mlxsw_i2c = i2c_get_clientdata(client);
|
||||
unsigned long timeout = msecs_to_jiffies(MLXSW_I2C_TIMEOUT_MSECS);
|
||||
- u8 tran_buf[MLXSW_I2C_MAX_BUFF_SIZE + MLXSW_I2C_ADDR_BUF_SIZE];
|
||||
int off = mlxsw_i2c->cmd.mb_off_in, chunk_size, i, j;
|
||||
unsigned long end;
|
||||
+ u8 *tran_buf;
|
||||
struct i2c_msg write_tran =
|
||||
- MLXSW_I2C_WRITE_MSG(client, tran_buf, MLXSW_I2C_PUSH_CMD_SIZE);
|
||||
+ MLXSW_I2C_WRITE_MSG(client, NULL, MLXSW_I2C_PUSH_CMD_SIZE);
|
||||
int err;
|
||||
|
||||
+ tran_buf = kmalloc(mlxsw_i2c->block_size + MLXSW_I2C_ADDR_BUF_SIZE,
|
||||
+ GFP_KERNEL);
|
||||
+ if (!tran_buf)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ write_tran.buf = tran_buf;
|
||||
for (i = 0; i < num; i++) {
|
||||
- chunk_size = (in_mbox_size > MLXSW_I2C_BLK_MAX) ?
|
||||
- MLXSW_I2C_BLK_MAX : in_mbox_size;
|
||||
+ chunk_size = (in_mbox_size > mlxsw_i2c->block_size) ?
|
||||
+ mlxsw_i2c->block_size : in_mbox_size;
|
||||
write_tran.len = MLXSW_I2C_ADDR_WIDTH + chunk_size;
|
||||
mlxsw_i2c_set_slave_addr(tran_buf, off);
|
||||
memcpy(&tran_buf[MLXSW_I2C_ADDR_BUF_SIZE], in_mbox +
|
||||
- MLXSW_I2C_BLK_MAX * i, chunk_size);
|
||||
+ mlxsw_i2c->block_size * i, chunk_size);
|
||||
|
||||
j = 0;
|
||||
end = jiffies + timeout;
|
||||
@@ -342,9 +349,10 @@ mlxsw_i2c_write(struct device *dev, size_t in_mbox_size, u8 *in_mbox, int num,
|
||||
(j++ < MLXSW_I2C_RETRY));
|
||||
|
||||
if (err != 1) {
|
||||
- if (!err)
|
||||
+ if (!err) {
|
||||
err = -EIO;
|
||||
- return err;
|
||||
+ goto mlxsw_i2c_write_exit;
|
||||
+ }
|
||||
}
|
||||
|
||||
off += chunk_size;
|
||||
@@ -355,24 +363,28 @@ mlxsw_i2c_write(struct device *dev, size_t in_mbox_size, u8 *in_mbox, int num,
|
||||
err = mlxsw_i2c_write_cmd(client, mlxsw_i2c, 0);
|
||||
if (err) {
|
||||
dev_err(&client->dev, "Could not start transaction");
|
||||
- return -EIO;
|
||||
+ err = -EIO;
|
||||
+ goto mlxsw_i2c_write_exit;
|
||||
}
|
||||
|
||||
/* Wait until go bit is cleared. */
|
||||
err = mlxsw_i2c_wait_go_bit(client, mlxsw_i2c, p_status);
|
||||
if (err) {
|
||||
dev_err(&client->dev, "HW semaphore is not released");
|
||||
- return err;
|
||||
+ goto mlxsw_i2c_write_exit;
|
||||
}
|
||||
|
||||
/* Validate transaction completion status. */
|
||||
if (*p_status) {
|
||||
dev_err(&client->dev, "Bad transaction completion status %x\n",
|
||||
*p_status);
|
||||
- return -EIO;
|
||||
+ err = -EIO;
|
||||
}
|
||||
|
||||
- return 0;
|
||||
+mlxsw_i2c_write_exit:
|
||||
+ kfree(tran_buf);
|
||||
+
|
||||
+ return err;
|
||||
}
|
||||
|
||||
/* Routine executes I2C command. */
|
||||
@@ -395,8 +407,8 @@ mlxsw_i2c_cmd(struct device *dev, u16 opcode, u32 in_mod, size_t in_mbox_size,
|
||||
|
||||
if (in_mbox) {
|
||||
reg_size = mlxsw_i2c_get_reg_size(in_mbox);
|
||||
- num = reg_size / MLXSW_I2C_BLK_MAX;
|
||||
- if (reg_size % MLXSW_I2C_BLK_MAX)
|
||||
+ num = reg_size / mlxsw_i2c->block_size;
|
||||
+ if (reg_size % mlxsw_i2c->block_size)
|
||||
num++;
|
||||
|
||||
if (mutex_lock_interruptible(&mlxsw_i2c->cmd.lock) < 0) {
|
||||
@@ -416,7 +428,7 @@ mlxsw_i2c_cmd(struct device *dev, u16 opcode, u32 in_mod, size_t in_mbox_size,
|
||||
} else {
|
||||
/* No input mailbox is case of initialization query command. */
|
||||
reg_size = MLXSW_I2C_MAX_DATA_SIZE;
|
||||
- num = reg_size / MLXSW_I2C_BLK_MAX;
|
||||
+ num = reg_size / mlxsw_i2c->block_size;
|
||||
|
||||
if (mutex_lock_interruptible(&mlxsw_i2c->cmd.lock) < 0) {
|
||||
dev_err(&client->dev, "Could not acquire lock");
|
||||
@@ -432,8 +444,8 @@ mlxsw_i2c_cmd(struct device *dev, u16 opcode, u32 in_mod, size_t in_mbox_size,
|
||||
/* Send read transaction to get output mailbox content. */
|
||||
read_tran[1].buf = out_mbox;
|
||||
for (i = 0; i < num; i++) {
|
||||
- chunk_size = (reg_size > MLXSW_I2C_BLK_MAX) ?
|
||||
- MLXSW_I2C_BLK_MAX : reg_size;
|
||||
+ chunk_size = (reg_size > mlxsw_i2c->block_size) ?
|
||||
+ mlxsw_i2c->block_size : reg_size;
|
||||
read_tran[1].len = chunk_size;
|
||||
mlxsw_i2c_set_slave_addr(tran_buf, off);
|
||||
|
||||
@@ -546,6 +558,7 @@ static const struct mlxsw_bus mlxsw_i2c_bus = {
|
||||
static int mlxsw_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
+ const struct i2c_adapter_quirks *quirks = client->adapter->quirks;
|
||||
struct mlxsw_i2c *mlxsw_i2c;
|
||||
u8 status;
|
||||
int err;
|
||||
@@ -554,6 +567,13 @@ static int mlxsw_i2c_probe(struct i2c_client *client,
|
||||
if (!mlxsw_i2c)
|
||||
return -ENOMEM;
|
||||
|
||||
+ if (quirks)
|
||||
+ mlxsw_i2c->block_size = max_t(u16, MLXSW_I2C_BLK_DEF,
|
||||
+ min_t(u16, quirks->max_read_len,
|
||||
+ quirks->max_write_len));
|
||||
+ else
|
||||
+ mlxsw_i2c->block_size = MLXSW_I2C_BLK_DEF;
|
||||
+
|
||||
i2c_set_clientdata(client, mlxsw_i2c);
|
||||
mutex_init(&mlxsw_i2c->cmd.lock);
|
||||
|
||||
diff --git a/drivers/net/ethernet/mellanox/mlxsw/minimal.c b/drivers/net/ethernet/mellanox/mlxsw/minimal.c
|
||||
index cac36c231864..5290993ff93f 100644
|
||||
--- a/drivers/net/ethernet/mellanox/mlxsw/minimal.c
|
||||
+++ b/drivers/net/ethernet/mellanox/mlxsw/minimal.c
|
||||
@@ -45,6 +45,23 @@ static const struct net_device_ops mlxsw_m_port_netdev_ops = {
|
||||
.ndo_stop = mlxsw_m_port_dummy_open_stop,
|
||||
};
|
||||
|
||||
+static void mlxsw_m_module_get_drvinfo(struct net_device *dev,
|
||||
+ struct ethtool_drvinfo *drvinfo)
|
||||
+{
|
||||
+ 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,
|
||||
+ 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,
|
||||
+ sizeof(drvinfo->bus_info));
|
||||
+}
|
||||
+
|
||||
static int mlxsw_m_get_module_info(struct net_device *netdev,
|
||||
struct ethtool_modinfo *modinfo)
|
||||
{
|
||||
@@ -66,6 +83,7 @@ mlxsw_m_get_module_eeprom(struct net_device *netdev, struct ethtool_eeprom *ee,
|
||||
}
|
||||
|
||||
static const struct ethtool_ops mlxsw_m_port_ethtool_ops = {
|
||||
+ .get_drvinfo = mlxsw_m_module_get_drvinfo,
|
||||
.get_module_info = mlxsw_m_get_module_info,
|
||||
.get_module_eeprom = mlxsw_m_get_module_eeprom,
|
||||
};
|
||||
diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h
|
||||
index f16d27e115d2..eb58940d2e9c 100644
|
||||
--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h
|
||||
+++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h
|
||||
@@ -7589,17 +7589,18 @@ MLXSW_ITEM32(reg, mtcap, sensor_count, 0x00, 0, 7);
|
||||
*/
|
||||
#define MLXSW_REG_MTMP_ID 0x900A
|
||||
#define MLXSW_REG_MTMP_LEN 0x20
|
||||
-#define MLXSW_REG_MTMP_GBOX_INDEX_MIN 256
|
||||
|
||||
MLXSW_REG_DEFINE(mtmp, MLXSW_REG_MTMP_ID, MLXSW_REG_MTMP_LEN);
|
||||
|
||||
+#define MLXSW_REG_MTMP_MODULE_INDEX_MIN 64
|
||||
+#define MLXSW_REG_MTMP_GBOX_INDEX_MIN 256
|
||||
/* reg_mtmp_sensor_index
|
||||
* Sensors index to access.
|
||||
* 64-127 of sensor_index are mapped to the SFP+/QSFP modules sequentially
|
||||
* (module 0 is mapped to sensor_index 64).
|
||||
* Access: Index
|
||||
*/
|
||||
-MLXSW_ITEM32(reg, mtmp, sensor_index, 0x00, 0, 11);
|
||||
+MLXSW_ITEM32(reg, mtmp, sensor_index, 0x00, 0, 12);
|
||||
|
||||
/* Convert to milli degrees Celsius */
|
||||
#define MLXSW_REG_MTMP_TEMP_TO_MC(val) (val * 125)
|
||||
@@ -7710,7 +7711,7 @@ MLXSW_REG_DEFINE(mtbr, MLXSW_REG_MTBR_ID, MLXSW_REG_MTBR_LEN);
|
||||
* 64-127 are mapped to the SFP+/QSFP modules sequentially).
|
||||
* Access: Index
|
||||
*/
|
||||
-MLXSW_ITEM32(reg, mtbr, base_sensor_index, 0x00, 0, 7);
|
||||
+MLXSW_ITEM32(reg, mtbr, base_sensor_index, 0x00, 0, 12);
|
||||
|
||||
/* reg_mtbr_num_rec
|
||||
* Request: Number of records to read
|
||||
--
|
||||
2.11.0
|
||||
|
||||
@@ -19,5 +19,15 @@ driver-add-the-support-max6620.patch
|
||||
0016-qsfp_sysfs-Fix-dmidecode-call.patch
|
||||
0017-mlxsw-qsfp_sysfs-Support-extended-port-numbers-for-S.patch
|
||||
0018-mlxsw-thermal-monitoring-amendments.patch
|
||||
0019-watchdog-mlx-wdt-introduce-watchdog-driver-for-Mella.patch
|
||||
0020-mlxsw-qsfp_sysfs-Support-port-numbers-initialization.patch
|
||||
0021-mlxsw-Align-code-with-kernel-v-5.0.patch
|
||||
0023-hwmon-pmbus-Fix-driver-info-initialization-in-probe-.patch
|
||||
0024-mlxsw-thermal-disable-highest-zone-calculation.patch
|
||||
0025-platform-x86-mlx-platform-Add-CPLD4-register.patch
|
||||
0026-mlxsw-Align-code-with-kernel-v-5.1.patch
|
||||
0027-mlxsw-core-Add-check-for-split-port-during-thermal-z.patch
|
||||
0028-watchdog-mlx-wdt-kernel-upstream-and-wd-type2-change.patch
|
||||
0029-mlxsw-core-Prevent-reading-unsupported-slave-address.patch
|
||||
0029-mlxsw-core-add-support-for-Gear-Box-temperatures-in-.patch
|
||||
0030-mlxsw-minimal-Provide-optimization-for-I2C-bus-acces.patch
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <mlnx_common/mlnx_common_config.h>
|
||||
#include <mlnx_common/mlnx_common.h>
|
||||
|
||||
#define MAX_NUM_OF_CPLD 3
|
||||
#define MAX_NUM_OF_CPLD 4
|
||||
#define PREFIX_PATH_ON_CPLD_DEV HW_MANAGEMENT_PATH"/system"
|
||||
|
||||
mlnx_platform_info_t* get_platform_info(void);
|
||||
|
||||
@@ -71,7 +71,9 @@ led_light_mode_map_t led_map[] = {
|
||||
{LED_SYSTEM, LED_MODE_OFF, ONLP_LED_MODE_OFF},
|
||||
{LED_SYSTEM, LED_MODE_GREEN, ONLP_LED_MODE_GREEN},
|
||||
{LED_SYSTEM, LED_MODE_RED, ONLP_LED_MODE_RED},
|
||||
{LED_SYSTEM, LED_MODE_ORANGE, ONLP_LED_MODE_ORANGE},
|
||||
{LED_SYSTEM, LED_MODE_RED_BLINK, ONLP_LED_MODE_RED_BLINKING},
|
||||
{LED_SYSTEM, LED_MODE_ORANGE_BLINK, ONLP_LED_MODE_ORANGE_BLINKING},
|
||||
{LED_SYSTEM, LED_MODE_GREEN_BLINK, ONLP_LED_MODE_GREEN_BLINKING},
|
||||
{LED_SYSTEM, LED_MODE_AUTO, ONLP_LED_MODE_AUTO},
|
||||
|
||||
@@ -305,7 +307,7 @@ onlp_ledi_info_get(onlp_oid_t id, onlp_led_info_t* info)
|
||||
|
||||
mlnx_platform_info_t* mlnx_platform_info = get_platform_info();
|
||||
/* Set the onlp_oid_hdr_t and capabilities */
|
||||
*info = mlnx_platform_info->linfo[ONLP_OID_ID_GET(id)];
|
||||
*info = mlnx_platform_info->linfo[local_id];
|
||||
|
||||
/* Get LED mode */
|
||||
if (mc_get_kernel_ver() >= KERNEL_VERSION(4,9,30)) {
|
||||
|
||||
@@ -42,7 +42,8 @@ static char arr_cplddev_name[MAX_NUM_OF_CPLD][30] =
|
||||
{
|
||||
"cpld_brd_version",
|
||||
"cpld_mgmt_version",
|
||||
"cpld_port_version"
|
||||
"cpld_port_version",
|
||||
"cpld_gearbox_version",
|
||||
};
|
||||
|
||||
mlnx_platform_info_t* get_platform_info()
|
||||
@@ -82,6 +83,9 @@ onlp_sysi_platform_info_get(onlp_platform_info_t* pi)
|
||||
case 3:
|
||||
pi->cpld_versions = aim_fstrdup("brd=%d, mgmt=%d, port=%d", v[0], v[1], v[2]);
|
||||
break;
|
||||
case 4:
|
||||
pi->cpld_versions = aim_fstrdup("brd=%d, mgmt=%d, port=%d", v[0], v[1], v[2]);
|
||||
break;
|
||||
case 0:
|
||||
default:
|
||||
AIM_LOG_ERROR("Incorrect CPLD Number %d\n", platform_info->cpld_num);
|
||||
@@ -382,15 +386,12 @@ onlp_sysi_platform_manage_leds_type2(void)
|
||||
int
|
||||
onlp_sysi_platform_manage_leds_type3(void)
|
||||
{
|
||||
int fan_number, psu_number;
|
||||
int fan_number, fan_sub, fan_idx, psu_number;
|
||||
onlp_led_mode_t mode, system_mode;
|
||||
int min_fan_speed;
|
||||
|
||||
int fan_led_id[6] = { LED_FAN1, LED_FAN2, LED_FAN3, LED_FAN4, LED_FAN5, LED_FAN6 };
|
||||
|
||||
int fan_problem = 0;
|
||||
int psu_problem = 0;
|
||||
|
||||
/*
|
||||
* FAN Indicators
|
||||
*
|
||||
@@ -399,59 +400,37 @@ onlp_sysi_platform_manage_leds_type3(void)
|
||||
* Off - No power
|
||||
*
|
||||
*/
|
||||
for (fan_number = 1; fan_number <= mlnx_platform_info.fan_num; fan_number += 2)
|
||||
fan_idx=0;
|
||||
for (fan_number = 1; fan_number <= mlnx_platform_info.fan_num; fan_idx++)
|
||||
{
|
||||
/* each 2 fans had same led_fan */
|
||||
onlp_fan_info_t fi;
|
||||
/* check fans */
|
||||
mode = ONLP_LED_MODE_GREEN;
|
||||
if (onlp_fani_info_get(ONLP_FAN_ID_CREATE(fan_number), &fi) < 0)
|
||||
{
|
||||
mode = ONLP_LED_MODE_ORANGE;
|
||||
fan_problem = 1;
|
||||
} else if ((fi.status & ONLP_FAN_STATUS_PRESENT) == 0) {
|
||||
if (mlnx_platform_info.fan_fixed == false)
|
||||
{
|
||||
/* Not present */
|
||||
mode = ONLP_LED_MODE_ORANGE;
|
||||
fan_problem = 1;
|
||||
}
|
||||
} else if (fi.status & ONLP_FAN_STATUS_FAILED) {
|
||||
mode = ONLP_LED_MODE_ORANGE;
|
||||
fan_problem = 1;
|
||||
} else {
|
||||
min_fan_speed = onlp_fani_get_min_rpm(fan_number);
|
||||
if (fi.rpm < min_fan_speed)
|
||||
{
|
||||
mode = ONLP_LED_MODE_ORANGE;
|
||||
fan_problem = 1;
|
||||
}
|
||||
}
|
||||
/* check fan i+1 */
|
||||
if (onlp_fani_info_get(ONLP_FAN_ID_CREATE(fan_number + 1), &fi) < 0)
|
||||
{
|
||||
mode = ONLP_LED_MODE_ORANGE;
|
||||
fan_problem = 1;
|
||||
} else if ((fi.status & 0x1) == 0) {
|
||||
if (mlnx_platform_info.fan_fixed == false)
|
||||
{
|
||||
/* Not present */
|
||||
mode = ONLP_LED_MODE_ORANGE;
|
||||
fan_problem = 1;
|
||||
}
|
||||
} else if (fi.status & ONLP_FAN_STATUS_FAILED)
|
||||
{
|
||||
mode = ONLP_LED_MODE_ORANGE;
|
||||
fan_problem = 1;
|
||||
} else {
|
||||
min_fan_speed = onlp_fani_get_min_rpm(fan_number + 1);
|
||||
if (fi.rpm < min_fan_speed)
|
||||
{
|
||||
mode = ONLP_LED_MODE_ORANGE;
|
||||
fan_problem = 1;
|
||||
}
|
||||
}
|
||||
onlp_ledi_mode_set( ONLP_OID_TYPE_CREATE(ONLP_OID_TYPE_LED, fan_led_id[fan_number / 2]), mode);
|
||||
for (fan_sub = 0; fan_sub < mlnx_platform_info.fan_per_module; fan_sub++, fan_number++) {
|
||||
/* check fans */
|
||||
if (onlp_fani_info_get(ONLP_FAN_ID_CREATE(fan_number), &fi) < 0)
|
||||
{
|
||||
mode = ONLP_LED_MODE_ORANGE;
|
||||
fan_problem = 1;
|
||||
} else if ((fi.status & ONLP_FAN_STATUS_PRESENT) == 0) {
|
||||
if (mlnx_platform_info.fan_fixed == false)
|
||||
{
|
||||
/* Not present */
|
||||
mode = ONLP_LED_MODE_ORANGE;
|
||||
fan_problem = 1;
|
||||
}
|
||||
} else if (fi.status & ONLP_FAN_STATUS_FAILED) {
|
||||
mode = ONLP_LED_MODE_ORANGE;
|
||||
fan_problem = 1;
|
||||
} else {
|
||||
min_fan_speed = onlp_fani_get_min_rpm(fan_number);
|
||||
if (fi.rpm < min_fan_speed)
|
||||
{
|
||||
mode = ONLP_LED_MODE_ORANGE;
|
||||
fan_problem = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
onlp_ledi_mode_set( ONLP_OID_TYPE_CREATE(ONLP_OID_TYPE_LED, fan_led_id[fan_idx]), mode);
|
||||
}
|
||||
|
||||
for (psu_number = 1; psu_number <= mlnx_platform_info.psu_num; psu_number++)
|
||||
|
||||
@@ -12,6 +12,5 @@ class OnlPlatform_x86_64_mlnx_mqm8700_r0(OnlPlatformMellanox,
|
||||
import os
|
||||
# necessary if there are issues with the install
|
||||
# os.system("/usr/bin/apt-get install")
|
||||
os.system("/etc/mlnx/mlnx-hw-management start")
|
||||
self.syseeprom_export();
|
||||
return True
|
||||
|
||||
@@ -12,6 +12,5 @@ class OnlPlatform_x86_64_mlnx_msn2010_r0(OnlPlatformMellanox,
|
||||
import os
|
||||
# necessary if there are issues with the install
|
||||
# os.system("/usr/bin/apt-get install")
|
||||
os.system("/etc/mlnx/mlnx-hw-management start")
|
||||
self.syseeprom_export();
|
||||
return True
|
||||
|
||||
@@ -12,6 +12,5 @@ class OnlPlatform_x86_64_mlnx_msn2100_r0(OnlPlatformMellanox,
|
||||
import os
|
||||
# necessary if there are issues with the install
|
||||
# os.system("/usr/bin/apt-get install")
|
||||
os.system("/etc/mlnx/mlnx-hw-management start")
|
||||
self.syseeprom_export();
|
||||
return True
|
||||
|
||||
@@ -12,6 +12,5 @@ class OnlPlatform_x86_64_mlnx_msn2100b_r0(OnlPlatformMellanox,
|
||||
import os
|
||||
# necessary if there are issues with the install
|
||||
# os.system("/usr/bin/apt-get install")
|
||||
os.system("/etc/mlnx/mlnx-hw-management start")
|
||||
self.syseeprom_export();
|
||||
return True
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from onl.platform.base import *
|
||||
from onl.platform.mellanox import *
|
||||
import os
|
||||
|
||||
class OnlPlatform_x86_64_mlnx_msn2410_r0(OnlPlatformMellanox,
|
||||
OnlPlatformPortConfig_32x100):
|
||||
@@ -8,18 +7,10 @@ class OnlPlatform_x86_64_mlnx_msn2410_r0(OnlPlatformMellanox,
|
||||
MODEL="SN2410"
|
||||
SYS_OBJECT_ID=".2410.1"
|
||||
|
||||
def hw_management_start(self):
|
||||
for tool in [ '/etc/mlnx/mlnx-hw-management', '/usr/bin/hw-management.sh' ]:
|
||||
if os.path.exists(tool):
|
||||
print "Starting Mellanox HW Management..."
|
||||
os.system("%s start" % tool)
|
||||
return True
|
||||
return False
|
||||
|
||||
def baseconfig(self):
|
||||
|
||||
if not self.hw_management_start():
|
||||
print "Mellanox HW Management Package Missing."
|
||||
|
||||
# load modules
|
||||
import os
|
||||
# necessary if there are issues with the install
|
||||
# os.system("/usr/bin/apt-get install")
|
||||
self.syseeprom_export();
|
||||
return True
|
||||
|
||||
@@ -12,6 +12,5 @@ class OnlPlatform_x86_64_mlnx_msn2410b_r0(OnlPlatformMellanox,
|
||||
import os
|
||||
# necessary if there are issues with the install
|
||||
# os.system("/usr/bin/apt-get install")
|
||||
os.system("/etc/mlnx/mlnx-hw-management start")
|
||||
self.syseeprom_export();
|
||||
return True
|
||||
|
||||
@@ -1,25 +1,16 @@
|
||||
from onl.platform.base import *
|
||||
from onl.platform.mellanox import *
|
||||
import os
|
||||
|
||||
class OnlPlatform_x86_64_mlnx_msn2700_r0(OnlPlatformMellanox,
|
||||
OnlPlatformPortConfig_48x25_8x100):
|
||||
OnlPlatformPortConfig_32x100):
|
||||
PLATFORM='x86-64-mlnx-msn2700-r0'
|
||||
MODEL="SN2700"
|
||||
SYS_OBJECT_ID=".2700.1"
|
||||
|
||||
def hw_management_start(self):
|
||||
for tool in [ '/etc/mlnx/mlnx-hw-management', '/usr/bin/hw-management.sh' ]:
|
||||
if os.path.exists(tool):
|
||||
print "Starting Mellanox HW Management..."
|
||||
os.system("%s start" % tool)
|
||||
return True
|
||||
return False
|
||||
|
||||
def baseconfig(self):
|
||||
|
||||
if not self.hw_management_start():
|
||||
print "Mellanox HW Management Package Missing."
|
||||
|
||||
# load modules
|
||||
import os
|
||||
# necessary if there are issues with the install
|
||||
# os.system("/usr/bin/apt-get install")
|
||||
self.syseeprom_export();
|
||||
return True
|
||||
|
||||
@@ -12,6 +12,5 @@ class OnlPlatform_x86_64_mlnx_msn2700b_r0(OnlPlatformMellanox,
|
||||
import os
|
||||
# necessary if there are issues with the install
|
||||
# os.system("/usr/bin/apt-get install")
|
||||
os.system("/etc/mlnx/mlnx-hw-management start")
|
||||
self.syseeprom_export();
|
||||
return True
|
||||
|
||||
@@ -12,6 +12,5 @@ class OnlPlatform_x86_64_mlnx_msn2740_r0(OnlPlatformMellanox,
|
||||
import os
|
||||
# necessary if there are issues with the install
|
||||
# os.system("/usr/bin/apt-get install")
|
||||
os.system("/etc/mlnx/mlnx-hw-management start")
|
||||
self.syseeprom_export();
|
||||
return True
|
||||
|
||||
@@ -12,6 +12,5 @@ class OnlPlatform_x86_64_mlnx_msn2740b_r0(OnlPlatformMellanox,
|
||||
import os
|
||||
# necessary if there are issues with the install
|
||||
# os.system("/usr/bin/apt-get install")
|
||||
os.system("/etc/mlnx/mlnx-hw-management start")
|
||||
self.syseeprom_export();
|
||||
return True
|
||||
|
||||
@@ -12,6 +12,5 @@ class OnlPlatform_x86_64_mlnx_msn3700_r0(OnlPlatformMellanox,
|
||||
import os
|
||||
# necessary if there are issues with the install
|
||||
# os.system("/usr/bin/apt-get install")
|
||||
os.system("/etc/mlnx/mlnx-hw-management start")
|
||||
self.syseeprom_export();
|
||||
return True
|
||||
|
||||
@@ -12,6 +12,5 @@ class OnlPlatform_x86_64_mlnx_msn3700c_r0(OnlPlatformMellanox,
|
||||
import os
|
||||
# necessary if there are issues with the install
|
||||
# os.system("/usr/bin/apt-get install")
|
||||
os.system("/etc/mlnx/mlnx-hw-management start")
|
||||
self.syseeprom_export();
|
||||
return True
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
include $(ONL)/make/pkg.mk
|
||||
@@ -0,0 +1 @@
|
||||
include $(ONL)/make/pkg.mk
|
||||
@@ -0,0 +1 @@
|
||||
!include $ONL_TEMPLATES/no-platform-modules.yml ARCH=amd64 VENDOR=mellanox BASENAME=x86-64-mlnx-msn3800
|
||||
@@ -0,0 +1 @@
|
||||
include $(ONL)/make/pkg.mk
|
||||
@@ -0,0 +1 @@
|
||||
!include $ONL_TEMPLATES/onlp-platform-any.yml PLATFORM=x86-64-mlnx-msn3800 ARCH=amd64 TOOLCHAIN=x86_64-linux-gnu
|
||||
@@ -0,0 +1,2 @@
|
||||
FILTER=src
|
||||
include $(ONL)/make/subdirs.mk
|
||||
@@ -0,0 +1,46 @@
|
||||
############################################################
|
||||
# <bsn.cl fy=2014 v=onl>
|
||||
#
|
||||
# Copyright 2014 BigSwitch Networks, Inc.
|
||||
#
|
||||
# Licensed under the Eclipse Public License, Version 1.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.eclipse.org/legal/epl-v10.html
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
# either express or implied. See the License for the specific
|
||||
# language governing permissions and limitations under the
|
||||
# License.
|
||||
#
|
||||
# </bsn.cl>
|
||||
############################################################
|
||||
#
|
||||
#
|
||||
############################################################
|
||||
include $(ONL)/make/config.amd64.mk
|
||||
|
||||
MODULE := libonlp-x86-64-mlnx-msn3800
|
||||
include $(BUILDER)/standardinit.mk
|
||||
|
||||
DEPENDMODULES := AIM IOF mlnx_common x86_64_mlnx_msn3800 onlplib
|
||||
DEPENDMODULE_HEADERS := sff
|
||||
|
||||
include $(BUILDER)/dependmodules.mk
|
||||
|
||||
SHAREDLIB := libonlp-x86-64-mlnx-msn3800.so
|
||||
$(SHAREDLIB)_TARGETS := $(ALL_TARGETS)
|
||||
include $(BUILDER)/so.mk
|
||||
.DEFAULT_GOAL := $(SHAREDLIB)
|
||||
|
||||
GLOBAL_CFLAGS += -I$(onlp_BASEDIR)/module/inc
|
||||
GLOBAL_CFLAGS += -I$(mlnx_common_BASEDIR)/module/inc
|
||||
GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1
|
||||
GLOBAL_CFLAGS += -fPIC
|
||||
GLOBAL_LINK_LIBS += -lpthread
|
||||
|
||||
include $(BUILDER)/targets.mk
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# Inclusive Makefile for the libonlp-x86-64-mlnx-msn3800-r0 module.
|
||||
#
|
||||
# Autogenerated 2015-12-23 23:45:22.249911
|
||||
#
|
||||
###############################################################################
|
||||
libonlp-x86-64-mlnx-msn3800-r0_BASEDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# Inclusive Makefile for the libonlp-x86-64-mlnx-msn3800 module.
|
||||
#
|
||||
# Autogenerated 2016-10-13 22:58:39.095824
|
||||
#
|
||||
###############################################################################
|
||||
libonlp-x86-64-mlnx-msn3800_BASEDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# Inclusive Makefile for the x86_64_mlnx_msn3800 module.
|
||||
#
|
||||
# Autogenerated 2015-12-23 23:45:22.262891
|
||||
#
|
||||
###############################################################################
|
||||
x86_64_mlnx_msn3800_BASEDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
############################################################
|
||||
# <bsn.cl fy=2014 v=onl>
|
||||
#
|
||||
# Copyright 2014 BigSwitch Networks, Inc.
|
||||
#
|
||||
# Licensed under the Eclipse Public License, Version 1.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.eclipse.org/legal/epl-v10.html
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
# either express or implied. See the License for the specific
|
||||
# language governing permissions and limitations under the
|
||||
# License.
|
||||
#
|
||||
# </bsn.cl>
|
||||
############################################################
|
||||
#
|
||||
#
|
||||
#
|
||||
############################################################
|
||||
include $(ONL)/make/config.amd64.mk
|
||||
|
||||
.DEFAULT_GOAL := onlpdump
|
||||
|
||||
MODULE := onlpdump
|
||||
include $(BUILDER)/standardinit.mk
|
||||
|
||||
DEPENDMODULES := AIM IOF onlp mlnx_common x86_64_mlnx_msn3800 onlplib onlp_platform_defaults sff cjson cjson_util timer_wheel OS
|
||||
|
||||
include $(BUILDER)/dependmodules.mk
|
||||
|
||||
BINARY := onlpdump
|
||||
$(BINARY)_LIBRARIES := $(LIBRARY_TARGETS)
|
||||
include $(BUILDER)/bin.mk
|
||||
|
||||
GLOBAL_CFLAGS += -DAIM_CONFIG_AIM_MAIN_FUNCTION=onlpdump_main
|
||||
GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1
|
||||
GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MAIN=1
|
||||
GLOBAL_LINK_LIBS += -lpthread -lm
|
||||
|
||||
include $(BUILDER)/targets.mk
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# Inclusive Makefile for the onlpdump module.
|
||||
#
|
||||
# Autogenerated 2016-10-13 22:58:37.393320
|
||||
#
|
||||
###############################################################################
|
||||
onlpdump_BASEDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
name: x86_64_mlnx_msn3800
|
||||
@@ -0,0 +1,9 @@
|
||||
###############################################################################
|
||||
#
|
||||
#
|
||||
#
|
||||
###############################################################################
|
||||
include ../../init.mk
|
||||
MODULE := x86_64_mlnx_msn3800
|
||||
AUTOMODULE := x86_64_mlnx_msn3800
|
||||
include $(BUILDER)/definemodule.mk
|
||||
@@ -0,0 +1,6 @@
|
||||
###############################################################################
|
||||
#
|
||||
# x86_64_mlnx_msn3800 README
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
###############################################################################
|
||||
#
|
||||
# x86_64_mlnx_msn3800 Autogeneration
|
||||
#
|
||||
###############################################################################
|
||||
x86_64_mlnx_msn3800_AUTO_DEFS := module/auto/x86_64_mlnx_msn3800.yml
|
||||
x86_64_mlnx_msn3800_AUTO_DIRS := module/inc/x86_64_mlnx_msn3800 module/src
|
||||
include $(BUILDER)/auto.mk
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
###############################################################################
|
||||
#
|
||||
# x86_64_mlnx_msn3800 Autogeneration Definitions.
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
cdefs: &cdefs
|
||||
- X86_64_MLNX_MSN3800_CONFIG_INCLUDE_LOGGING:
|
||||
doc: "Include or exclude logging."
|
||||
default: 1
|
||||
- X86_64_MLNX_MSN3800_CONFIG_LOG_OPTIONS_DEFAULT:
|
||||
doc: "Default enabled log options."
|
||||
default: AIM_LOG_OPTIONS_DEFAULT
|
||||
- X86_64_MLNX_MSN3800_CONFIG_LOG_BITS_DEFAULT:
|
||||
doc: "Default enabled log bits."
|
||||
default: AIM_LOG_BITS_DEFAULT
|
||||
- X86_64_MLNX_MSN3800_CONFIG_LOG_CUSTOM_BITS_DEFAULT:
|
||||
doc: "Default enabled custom log bits."
|
||||
default: 0
|
||||
- X86_64_MLNX_MSN3800_CONFIG_PORTING_STDLIB:
|
||||
doc: "Default all porting macros to use the C standard libraries."
|
||||
default: 1
|
||||
- X86_64_MLNX_MSN3800_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS:
|
||||
doc: "Include standard library headers for stdlib porting macros."
|
||||
default: x86_64_mlnx_msn3800_CONFIG_PORTING_STDLIB
|
||||
- X86_64_MLNX_MSN3800_CONFIG_INCLUDE_UCLI:
|
||||
doc: "Include generic uCli support."
|
||||
default: 0
|
||||
- X86_64_MLNX_MSN3800_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION:
|
||||
doc: "Assume chassis fan direction is the same as the PSU fan direction."
|
||||
default: 0
|
||||
|
||||
|
||||
definitions:
|
||||
cdefs:
|
||||
X86_64_MLNX_MSN3800_CONFIG_HEADER:
|
||||
defs: *cdefs
|
||||
basename: x86_64_mlnx_msn3800_config
|
||||
|
||||
portingmacro:
|
||||
x86_64_mlnx_msn3800:
|
||||
macros:
|
||||
- malloc
|
||||
- free
|
||||
- memset
|
||||
- memcpy
|
||||
- strncpy
|
||||
- vsnprintf
|
||||
- snprintf
|
||||
- strlen
|
||||
@@ -0,0 +1,14 @@
|
||||
/**************************************************************************//**
|
||||
*
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include <x86_64_mlnx_msn3800/x86_64_mlnx_msn3800_config.h>
|
||||
|
||||
/* <--auto.start.xmacro(ALL).define> */
|
||||
/* <auto.end.xmacro(ALL).define> */
|
||||
|
||||
/* <--auto.start.xenum(ALL).define> */
|
||||
/* <auto.end.xenum(ALL).define> */
|
||||
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
/**************************************************************************//**
|
||||
*
|
||||
* @file
|
||||
* @brief x86_64_mlnx_msn3800 Configuration Header
|
||||
*
|
||||
* @addtogroup x86_64_mlnx_msn3800-config
|
||||
* @{
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef __X86_64_MLNX_MSN3800_CONFIG_H__
|
||||
#define __X86_64_MLNX_MSN3800_CONFIG_H__
|
||||
|
||||
#ifdef GLOBAL_INCLUDE_CUSTOM_CONFIG
|
||||
#include <global_custom_config.h>
|
||||
#endif
|
||||
#ifdef X86_64_MLNX_MSN3800_INCLUDE_CUSTOM_CONFIG
|
||||
#include <x86_64_mlnx_msn3800_custom_config.h>
|
||||
#endif
|
||||
|
||||
/* <auto.start.cdefs(X86_64_MLNX_MSN3800_CONFIG_HEADER).header> */
|
||||
#include <AIM/aim.h>
|
||||
/**
|
||||
* X86_64_MLNX_MSN3800_CONFIG_INCLUDE_LOGGING
|
||||
*
|
||||
* Include or exclude logging. */
|
||||
|
||||
|
||||
#ifndef X86_64_MLNX_MSN3800_CONFIG_INCLUDE_LOGGING
|
||||
#define X86_64_MLNX_MSN3800_CONFIG_INCLUDE_LOGGING 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* X86_64_MLNX_MSN3800_CONFIG_LOG_OPTIONS_DEFAULT
|
||||
*
|
||||
* Default enabled log options. */
|
||||
|
||||
|
||||
#ifndef X86_64_MLNX_MSN3800_CONFIG_LOG_OPTIONS_DEFAULT
|
||||
#define X86_64_MLNX_MSN3800_CONFIG_LOG_OPTIONS_DEFAULT AIM_LOG_OPTIONS_DEFAULT
|
||||
#endif
|
||||
|
||||
/**
|
||||
* X86_64_MLNX_MSN3800_CONFIG_LOG_BITS_DEFAULT
|
||||
*
|
||||
* Default enabled log bits. */
|
||||
|
||||
|
||||
#ifndef X86_64_MLNX_MSN3800_CONFIG_LOG_BITS_DEFAULT
|
||||
#define X86_64_MLNX_MSN3800_CONFIG_LOG_BITS_DEFAULT AIM_LOG_BITS_DEFAULT
|
||||
#endif
|
||||
|
||||
/**
|
||||
* X86_64_MLNX_MSN3800_CONFIG_LOG_CUSTOM_BITS_DEFAULT
|
||||
*
|
||||
* Default enabled custom log bits. */
|
||||
|
||||
|
||||
#ifndef X86_64_MLNX_MSN3800_CONFIG_LOG_CUSTOM_BITS_DEFAULT
|
||||
#define X86_64_MLNX_MSN3800_CONFIG_LOG_CUSTOM_BITS_DEFAULT 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* X86_64_MLNX_MSN3800_CONFIG_PORTING_STDLIB
|
||||
*
|
||||
* Default all porting macros to use the C standard libraries. */
|
||||
|
||||
|
||||
#ifndef X86_64_MLNX_MSN3800_CONFIG_PORTING_STDLIB
|
||||
#define X86_64_MLNX_MSN3800_CONFIG_PORTING_STDLIB 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* X86_64_MLNX_MSN3800_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS
|
||||
*
|
||||
* Include standard library headers for stdlib porting macros. */
|
||||
|
||||
|
||||
#ifndef X86_64_MLNX_MSN3800_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS
|
||||
#define X86_64_MLNX_MSN3800_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS X86_64_MLNX_MSN3800_CONFIG_PORTING_STDLIB
|
||||
#endif
|
||||
|
||||
/**
|
||||
* X86_64_MLNX_MSN3800_CONFIG_INCLUDE_UCLI
|
||||
*
|
||||
* Include generic uCli support. */
|
||||
|
||||
|
||||
#ifndef X86_64_MLNX_MSN3800_CONFIG_INCLUDE_UCLI
|
||||
#define X86_64_MLNX_MSN3800_CONFIG_INCLUDE_UCLI 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* X86_64_MLNX_MSN3800_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION
|
||||
*
|
||||
* Assume chassis fan direction is the same as the PSU fan direction. */
|
||||
|
||||
|
||||
#ifndef X86_64_MLNX_MSN3800_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION
|
||||
#define X86_64_MLNX_MSN3800_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION 0
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* All compile time options can be queried or displayed
|
||||
*/
|
||||
|
||||
/** Configuration settings structure. */
|
||||
typedef struct x86_64_mlnx_msn3800_config_settings_s {
|
||||
/** name */
|
||||
const char* name;
|
||||
/** value */
|
||||
const char* value;
|
||||
} x86_64_mlnx_msn3800_config_settings_t;
|
||||
|
||||
/** Configuration settings table. */
|
||||
/** x86_64_mlnx_msn3800_config_settings table. */
|
||||
extern x86_64_mlnx_msn3800_config_settings_t x86_64_mlnx_msn3800_config_settings[];
|
||||
|
||||
/**
|
||||
* @brief Lookup a configuration setting.
|
||||
* @param setting The name of the configuration option to lookup.
|
||||
*/
|
||||
const char* x86_64_mlnx_msn3800_config_lookup(const char* setting);
|
||||
|
||||
/**
|
||||
* @brief Show the compile-time configuration.
|
||||
* @param pvs The output stream.
|
||||
*/
|
||||
int x86_64_mlnx_msn3800_config_show(struct aim_pvs_s* pvs);
|
||||
|
||||
/* <auto.end.cdefs(X86_64_MLNX_MSN3800_CONFIG_HEADER).header> */
|
||||
|
||||
#include "x86_64_mlnx_msn3800_porting.h"
|
||||
|
||||
#endif /* __X86_64_MLNX_MSN3800_CONFIG_H__ */
|
||||
/* @} */
|
||||
@@ -0,0 +1,26 @@
|
||||
/**************************************************************************//**
|
||||
*
|
||||
* x86_64_mlnx_msn3800 Doxygen Header
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef __X86_64_MLNX_MSN3800_DOX_H__
|
||||
#define __X86_64_MLNX_MSN3800_DOX_H__
|
||||
|
||||
/**
|
||||
* @defgroup x86_64_mlnx_msn3800 x86_64_mlnx_msn3800 - x86_64_mlnx_msn3800 Description
|
||||
*
|
||||
|
||||
The documentation overview for this module should go here.
|
||||
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* @defgroup x86_64_mlnx_msn3800-x86_64_mlnx_msn3800 Public Interface
|
||||
* @defgroup x86_64_mlnx_msn3800-config Compile Time Configuration
|
||||
* @defgroup x86_64_mlnx_msn3800-porting Porting Macros
|
||||
*
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
#endif /* __X86_64_MLNX_MSN3800_DOX_H__ */
|
||||
@@ -0,0 +1,107 @@
|
||||
/**************************************************************************//**
|
||||
*
|
||||
* @file
|
||||
* @brief x86_64_mlnx_msn3800 Porting Macros.
|
||||
*
|
||||
* @addtogroup x86_64_mlnx_msn3800-porting
|
||||
* @{
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef __X86_64_MLNX_MSN3800_PORTING_H__
|
||||
#define __X86_64_MLNX_MSN3800_PORTING_H__
|
||||
|
||||
|
||||
/* <auto.start.portingmacro(ALL).define> */
|
||||
#if X86_64_MLNX_MSN3800_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS == 1
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <memory.h>
|
||||
#endif
|
||||
|
||||
#ifndef X86_64_MLNX_MSN3800_MALLOC
|
||||
#if defined(GLOBAL_MALLOC)
|
||||
#define X86_64_MLNX_MSN3800_MALLOC GLOBAL_MALLOC
|
||||
#elif X86_64_MLNX_MSN3800_CONFIG_PORTING_STDLIB == 1
|
||||
#define X86_64_MLNX_MSN3800_MALLOC malloc
|
||||
#else
|
||||
#error The macro X86_64_MLNX_MSN3800_MALLOC is required but cannot be defined.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef X86_64_MLNX_MSN3800_FREE
|
||||
#if defined(GLOBAL_FREE)
|
||||
#define X86_64_MLNX_MSN3800_FREE GLOBAL_FREE
|
||||
#elif X86_64_MLNX_MSN3800_CONFIG_PORTING_STDLIB == 1
|
||||
#define X86_64_MLNX_MSN3800_FREE free
|
||||
#else
|
||||
#error The macro X86_64_MLNX_MSN3800_FREE is required but cannot be defined.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef X86_64_MLNX_MSN3800_MEMSET
|
||||
#if defined(GLOBAL_MEMSET)
|
||||
#define X86_64_MLNX_MSN3800_MEMSET GLOBAL_MEMSET
|
||||
#elif X86_64_MLNX_MSN3800_CONFIG_PORTING_STDLIB == 1
|
||||
#define X86_64_MLNX_MSN3800_MEMSET memset
|
||||
#else
|
||||
#error The macro X86_64_MLNX_MSN3800_MEMSET is required but cannot be defined.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef X86_64_MLNX_MSN3800_MEMCPY
|
||||
#if defined(GLOBAL_MEMCPY)
|
||||
#define X86_64_MLNX_MSN3800_MEMCPY GLOBAL_MEMCPY
|
||||
#elif X86_64_MLNX_MSN3800_CONFIG_PORTING_STDLIB == 1
|
||||
#define X86_64_MLNX_MSN3800_MEMCPY memcpy
|
||||
#else
|
||||
#error The macro X86_64_MLNX_MSN3800_MEMCPY is required but cannot be defined.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef X86_64_MLNX_MSN3800_STRNCPY
|
||||
#if defined(GLOBAL_STRNCPY)
|
||||
#define X86_64_MLNX_MSN3800_STRNCPY GLOBAL_STRNCPY
|
||||
#elif X86_64_MLNX_MSN3800_CONFIG_PORTING_STDLIB == 1
|
||||
#define X86_64_MLNX_MSN3800_STRNCPY strncpy
|
||||
#else
|
||||
#error The macro X86_64_MLNX_MSN3800_STRNCPY is required but cannot be defined.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef X86_64_MLNX_MSN3800_VSNPRINTF
|
||||
#if defined(GLOBAL_VSNPRINTF)
|
||||
#define X86_64_MLNX_MSN3800_VSNPRINTF GLOBAL_VSNPRINTF
|
||||
#elif X86_64_MLNX_MSN3800_CONFIG_PORTING_STDLIB == 1
|
||||
#define X86_64_MLNX_MSN3800_VSNPRINTF vsnprintf
|
||||
#else
|
||||
#error The macro X86_64_MLNX_MSN3800_VSNPRINTF is required but cannot be defined.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef X86_64_MLNX_MSN3800_SNPRINTF
|
||||
#if defined(GLOBAL_SNPRINTF)
|
||||
#define X86_64_MLNX_MSN3800_SNPRINTF GLOBAL_SNPRINTF
|
||||
#elif X86_64_MLNX_MSN3800_CONFIG_PORTING_STDLIB == 1
|
||||
#define X86_64_MLNX_MSN3800_SNPRINTF snprintf
|
||||
#else
|
||||
#error The macro X86_64_MLNX_MSN3800_SNPRINTF is required but cannot be defined.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef X86_64_MLNX_MSN3800_STRLEN
|
||||
#if defined(GLOBAL_STRLEN)
|
||||
#define X86_64_MLNX_MSN3800_STRLEN GLOBAL_STRLEN
|
||||
#elif X86_64_MLNX_MSN3800_CONFIG_PORTING_STDLIB == 1
|
||||
#define X86_64_MLNX_MSN3800_STRLEN strlen
|
||||
#else
|
||||
#error The macro X86_64_MLNX_MSN3800_STRLEN is required but cannot be defined.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* <auto.end.portingmacro(ALL).define> */
|
||||
|
||||
|
||||
#endif /* __X86_64_MLNX_MSN3800_PORTING_H__ */
|
||||
/* @} */
|
||||
@@ -0,0 +1,10 @@
|
||||
###############################################################################
|
||||
#
|
||||
#
|
||||
#
|
||||
###############################################################################
|
||||
THIS_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
|
||||
x86_64_mlnx_msn3800_INCLUDES := -I $(THIS_DIR)inc
|
||||
x86_64_mlnx_msn3800_INTERNAL_INCLUDES := -I $(THIS_DIR)src
|
||||
x86_64_mlnx_msn3800_DEPENDMODULE_ENTRIES := init:x86_64_mlnx_msn3800 ucli:x86_64_mlnx_msn3800
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
###############################################################################
|
||||
#
|
||||
# Local source generation targets.
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
ucli:
|
||||
@../../../../tools/uclihandlers.py x86_64_mlnx_msn3800_ucli.c
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
/************************************************************
|
||||
* <bsn.cl fy=2014 v=onl>
|
||||
*
|
||||
* Copyright 2014 Big Switch Networks, Inc.
|
||||
*
|
||||
* Licensed under the Eclipse Public License, Version 1.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*
|
||||
* </bsn.cl>
|
||||
************************************************************
|
||||
*
|
||||
* Fan Platform Implementation Defaults.
|
||||
*
|
||||
***********************************************************/
|
||||
#include <fcntl.h>
|
||||
#include <onlplib/file.h>
|
||||
#include <onlplib/mmap.h>
|
||||
#include <onlp/platformi/fani.h>
|
||||
#include "platform_lib.h"
|
||||
#include "mlnx_common/mlnx_common.h"
|
||||
|
||||
#define FAN_RESERVED 0
|
||||
#define FAN_1_ON_MAIN_BOARD 1
|
||||
#define FAN_2_ON_MAIN_BOARD 2
|
||||
#define FAN_3_ON_MAIN_BOARD 3
|
||||
#define FAN_1_ON_PSU1 4
|
||||
#define FAN_1_ON_PSU2 5
|
||||
|
||||
#define FIRST_PSU_FAN_ID 4
|
||||
|
||||
static int min_fan_speed[CHASSIS_FAN_COUNT+1] = {0};
|
||||
static int max_fan_speed[CHASSIS_FAN_COUNT+1] = {0};
|
||||
|
||||
static fan_path_T fan_path[] = /* must map with onlp_fan_id */
|
||||
{
|
||||
MAKE_FAN_PATH_ON_MAIN_BOARD(PROJECT_NAME, FAN_RESERVED),
|
||||
MAKE_FAN_PATH_ON_MAIN_BOARD(PROJECT_NAME, FAN_1_ON_MAIN_BOARD),
|
||||
MAKE_FAN_PATH_ON_MAIN_BOARD(PROJECT_NAME, FAN_2_ON_MAIN_BOARD),
|
||||
MAKE_FAN_PATH_ON_MAIN_BOARD(PROJECT_NAME, FAN_3_ON_MAIN_BOARD),
|
||||
MAKE_FAN_PATH_ON_PSU(1 ,1),
|
||||
MAKE_FAN_PATH_ON_PSU(2, 1)
|
||||
};
|
||||
|
||||
/* Static fan information */
|
||||
onlp_fan_info_t finfo[] = {
|
||||
{ }, /* Not used */
|
||||
MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(1),
|
||||
MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(2),
|
||||
MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(3),
|
||||
MAKE_FAN_INFO_NODE_ON_PSU(1,1),
|
||||
MAKE_FAN_INFO_NODE_ON_PSU(2,1)
|
||||
};
|
||||
|
||||
/*
|
||||
* This function will be called prior to all of onlp_fani_* functions.
|
||||
*/
|
||||
int
|
||||
onlp_fani_init(void)
|
||||
{
|
||||
mlnx_platform_info_t* mlnx_platform_info = get_platform_info();
|
||||
mlnx_platform_info->min_fan_speed = min_fan_speed;
|
||||
mlnx_platform_info->max_fan_speed = max_fan_speed;
|
||||
mlnx_platform_info->finfo = finfo;
|
||||
mlnx_platform_info->fan_fnames = fan_path;
|
||||
mlnx_platform_info->fan_type = FAN_TYPE_NO_EEPROM;
|
||||
mlnx_platform_info->fan_per_module = 1;
|
||||
mlnx_platform_info->first_psu_fan_id = FIRST_PSU_FAN_ID;
|
||||
return ONLP_STATUS_OK;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
/************************************************************
|
||||
* <bsn.cl fy=2014 v=onl>
|
||||
*
|
||||
* Copyright 2014 Big Switch Networks, Inc.
|
||||
*
|
||||
* Licensed under the Eclipse Public License, Version 1.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*
|
||||
* </bsn.cl>
|
||||
************************************************************
|
||||
*
|
||||
*
|
||||
*
|
||||
***********************************************************/
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <onlplib/mmap.h>
|
||||
#include <onlplib/file.h>
|
||||
#include <onlp/platformi/ledi.h>
|
||||
#include "platform_lib.h"
|
||||
#include <mlnx_common/mlnx_common.h>
|
||||
|
||||
static char* file_names[] = /* must map with onlp_led_id */
|
||||
{
|
||||
"reserved",
|
||||
"status",
|
||||
"fan1",
|
||||
"fan2",
|
||||
"fan3",
|
||||
"psu",
|
||||
"psu",
|
||||
};
|
||||
|
||||
/*
|
||||
* Get the information for the given LED OID.
|
||||
*/
|
||||
static onlp_led_info_t linfo[] =
|
||||
{
|
||||
{ }, /* Not used */
|
||||
{
|
||||
{ ONLP_LED_ID_CREATE(LED_SYSTEM), "Chassis LED 1 (SYSTEM LED)", 0 },
|
||||
ONLP_LED_STATUS_PRESENT,
|
||||
ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_GREEN_BLINKING |
|
||||
ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_ORANGE_BLINKING | ONLP_LED_CAPS_AUTO,
|
||||
},
|
||||
{
|
||||
{ ONLP_LED_ID_CREATE(LED_FAN1), "Chassis LED 2 (FAN1)", 0 },
|
||||
ONLP_LED_STATUS_PRESENT,
|
||||
ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_GREEN_BLINKING |
|
||||
ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_ORANGE_BLINKING | ONLP_LED_CAPS_AUTO,
|
||||
},
|
||||
{
|
||||
{ ONLP_LED_ID_CREATE(LED_FAN2), "Chassis LED 3 (FAN2)", 0 },
|
||||
ONLP_LED_STATUS_PRESENT,
|
||||
ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_GREEN_BLINKING |
|
||||
ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_ORANGE_BLINKING | ONLP_LED_CAPS_AUTO,
|
||||
},
|
||||
{
|
||||
{ ONLP_LED_ID_CREATE(LED_FAN3), "Chassis LED 4 (FAN3)", 0 },
|
||||
ONLP_LED_STATUS_PRESENT,
|
||||
ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_GREEN_BLINKING |
|
||||
ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_ORANGE_BLINKING | ONLP_LED_CAPS_AUTO,
|
||||
},
|
||||
{
|
||||
{ ONLP_LED_ID_CREATE(LED_PSU_T3), "Chassis LED 5 (PSU LED)", 0 },
|
||||
ONLP_LED_STATUS_PRESENT,
|
||||
ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_GREEN_BLINKING |
|
||||
ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_ORANGE_BLINKING | ONLP_LED_CAPS_AUTO,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* This function will be called prior to any other onlp_ledi_* functions.
|
||||
*/
|
||||
int
|
||||
onlp_ledi_init(void)
|
||||
{
|
||||
/*
|
||||
* ONLPD calls it too early before all BSP insfrastructure is set
|
||||
*/
|
||||
mlnx_platform_info_t* mlnx_platform_info = get_platform_info();
|
||||
mlnx_platform_info->linfo = linfo;
|
||||
mlnx_platform_info->led_fnames = file_names;
|
||||
return ONLP_STATUS_OK;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
###############################################################################
|
||||
#
|
||||
#
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
LIBRARY := x86_64_mlnx_msn3800
|
||||
$(LIBRARY)_SUBDIR := $(dir $(lastword $(MAKEFILE_LIST)))
|
||||
include $(BUILDER)/lib.mk
|
||||
@@ -0,0 +1,39 @@
|
||||
/************************************************************
|
||||
* <bsn.cl fy=2014 v=onl>
|
||||
*
|
||||
* Copyright 2014 Big Switch Networks, Inc.
|
||||
*
|
||||
* Licensed under the Eclipse Public License, Version 1.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*
|
||||
* </bsn.cl>
|
||||
************************************************************
|
||||
*
|
||||
*
|
||||
*
|
||||
***********************************************************/
|
||||
#ifndef __PLATFORM_LIB_H__
|
||||
#define __PLATFORM_LIB_H__
|
||||
|
||||
#include "x86_64_mlnx_msn3800_log.h"
|
||||
|
||||
#define CHASSIS_PSU_COUNT 2
|
||||
#define CHASSIS_TOTAL_FAN_COUNT 5
|
||||
#define CHASSIS_TOTAL_THERMAL_COUNT 10
|
||||
#define CHASSIS_FAN_COUNT (CHASSIS_TOTAL_FAN_COUNT - CHASSIS_PSU_COUNT)
|
||||
#define CHASSIS_THERMAL_COUNT (CHASSIS_TOTAL_THERMAL_COUNT - CHASSIS_PSU_COUNT)
|
||||
#define CPLD_COUNT 4
|
||||
#define SFP_PORT_COUNT 32
|
||||
#define CHASSIS_LED_COUNT 5
|
||||
|
||||
#endif /* __PLATFORM_LIB_H__ */
|
||||
@@ -0,0 +1,64 @@
|
||||
/************************************************************
|
||||
* <bsn.cl fy=2014 v=onl>
|
||||
*
|
||||
* Copyright 2014 Big Switch Networks, Inc.
|
||||
*
|
||||
* Licensed under the Eclipse Public License, Version 1.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*
|
||||
* </bsn.cl>
|
||||
************************************************************
|
||||
*
|
||||
*
|
||||
*
|
||||
***********************************************************/
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <onlplib/file.h>
|
||||
#include <onlp/platformi/fani.h>
|
||||
#include <onlp/platformi/ledi.h>
|
||||
#include <onlp/platformi/psui.h>
|
||||
#include <onlp/platformi/sysi.h>
|
||||
#include <onlp/platformi/thermali.h>
|
||||
#include "platform_lib.h"
|
||||
#include <mlnx_common/mlnx_common.h>
|
||||
#include "x86_64_mlnx_msn3800_int.h"
|
||||
#include "x86_64_mlnx_msn3800_log.h"
|
||||
|
||||
#define ONL_PLATFORM_NAME "x86-64-mlnx-msn3800-r0"
|
||||
|
||||
int mc_get_platform_info(mlnx_platform_info_t* mlnx_platform)
|
||||
{
|
||||
strncpy(mlnx_platform->onl_platform_name, ONL_PLATFORM_NAME, PLATFORM_NAME_MAX_LEN);
|
||||
mlnx_platform->sfp_num = SFP_PORT_COUNT;
|
||||
mlnx_platform->led_num = CHASSIS_LED_COUNT;
|
||||
mlnx_platform->psu_num = CHASSIS_PSU_COUNT;
|
||||
mlnx_platform->fan_num = CHASSIS_FAN_COUNT;
|
||||
mlnx_platform->thermal_num = CHASSIS_THERMAL_COUNT;
|
||||
mlnx_platform->cpld_num = CPLD_COUNT;
|
||||
mlnx_platform->psu_fixed = false;
|
||||
mlnx_platform->fan_fixed = false;
|
||||
mlnx_platform->psu_type = PSU_TYPE_3;
|
||||
mlnx_platform->led_type = LED_TYPE_3;
|
||||
|
||||
return ONLP_STATUS_OK;
|
||||
}
|
||||
|
||||
int
|
||||
onlp_sysi_init(void)
|
||||
{
|
||||
return ONLP_STATUS_OK;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
/************************************************************
|
||||
* <bsn.cl fy=2014 v=onl>
|
||||
*
|
||||
* Copyright 2014 Big Switch Networks, Inc.
|
||||
*
|
||||
* Licensed under the Eclipse Public License, Version 1.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*
|
||||
* </bsn.cl>
|
||||
************************************************************
|
||||
*
|
||||
* Thermal Sensor Platform Implementation.
|
||||
*
|
||||
***********************************************************/
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <AIM/aim_log.h>
|
||||
#include <onlplib/file.h>
|
||||
#include <onlplib/mmap.h>
|
||||
#include <onlp/platformi/thermali.h>
|
||||
#include "platform_lib.h"
|
||||
#include "mlnx_common/mlnx_common.h"
|
||||
|
||||
enum onlp_thermal_id
|
||||
{
|
||||
THERMAL_RESERVED = 0,
|
||||
THERMAL_CPU_CORE_0,
|
||||
THERMAL_CPU_CORE_1,
|
||||
THERMAL_CPU_CORE_2,
|
||||
THERMAL_CPU_CORE_3,
|
||||
THERMAL_CPU_PACK,
|
||||
THERMAL_ASIC,
|
||||
THERMAL_BOARD_AMB,
|
||||
THERMAL_PORT,
|
||||
THERMAL_ON_PSU1,
|
||||
THERMAL_ON_PSU2,
|
||||
};
|
||||
|
||||
static char* thermal_fnames[] = /* must map with onlp_thermal_id */
|
||||
{
|
||||
"reserved",
|
||||
"cpu_core0",
|
||||
"cpu_core1",
|
||||
"cpu_core2",
|
||||
"cpu_core3",
|
||||
"cpu_pack",
|
||||
"asic",
|
||||
"fan_amb",
|
||||
"port_amb",
|
||||
"psu1",
|
||||
"psu2"
|
||||
};
|
||||
|
||||
/* Static values */
|
||||
static onlp_thermal_info_t tinfo[] = {
|
||||
{ }, /* Not used */
|
||||
{ { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE_0), "CPU Core 0", 0},
|
||||
ONLP_THERMAL_STATUS_PRESENT,
|
||||
ONLP_THERMAL_CAPS_ALL, 0, CPU_THERMAL_THRESHOLD_INIT_DEFAULTS
|
||||
},
|
||||
{ { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE_1), "CPU Core 1", 0},
|
||||
ONLP_THERMAL_STATUS_PRESENT,
|
||||
ONLP_THERMAL_CAPS_ALL, 0, CPU_THERMAL_THRESHOLD_INIT_DEFAULTS
|
||||
},
|
||||
{ { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE_2), "CPU Core 2", 0},
|
||||
ONLP_THERMAL_STATUS_PRESENT,
|
||||
ONLP_THERMAL_CAPS_ALL, 0, CPU_THERMAL_THRESHOLD_INIT_DEFAULTS
|
||||
},
|
||||
{ { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE_3), "CPU Core 3", 0},
|
||||
ONLP_THERMAL_STATUS_PRESENT,
|
||||
ONLP_THERMAL_CAPS_ALL, 0, CPU_THERMAL_THRESHOLD_INIT_DEFAULTS
|
||||
},
|
||||
{ { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_PACK), "CPU pack", 0},
|
||||
ONLP_THERMAL_STATUS_PRESENT,
|
||||
ONLP_THERMAL_CAPS_ALL, 0, CPU_THERMAL_THRESHOLD_INIT_DEFAULTS
|
||||
},
|
||||
{ { ONLP_THERMAL_ID_CREATE(THERMAL_ASIC), "Asic Thermal Sensor", 0},
|
||||
ONLP_THERMAL_STATUS_PRESENT,
|
||||
ONLP_THERMAL_CAPS_ALL, 0, ASIC_THERMAL_THRESHOLD_INIT_DEFAULTS
|
||||
},
|
||||
{ { ONLP_THERMAL_ID_CREATE(THERMAL_BOARD_AMB), "Board AMB Thermal Sensor", 0},
|
||||
ONLP_THERMAL_STATUS_PRESENT,
|
||||
ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0, {0,0,0}
|
||||
},
|
||||
{ { ONLP_THERMAL_ID_CREATE(THERMAL_PORT), "Port AMB Thermal Sensor", 0},
|
||||
ONLP_THERMAL_STATUS_PRESENT,
|
||||
ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0, {0,0,0}
|
||||
},
|
||||
{ { ONLP_THERMAL_ID_CREATE(THERMAL_ON_PSU1), "PSU-1 Thermal Sensor 1", ONLP_PSU_ID_CREATE(PSU1_ID)},
|
||||
ONLP_THERMAL_STATUS_PRESENT,
|
||||
ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0, {0,0,0}
|
||||
},
|
||||
{ { ONLP_THERMAL_ID_CREATE(THERMAL_ON_PSU2), "PSU-2 Thermal Sensor 1", ONLP_PSU_ID_CREATE(PSU2_ID)},
|
||||
ONLP_THERMAL_STATUS_PRESENT,
|
||||
ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0, {0,0,0}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* This will be called to intiialize the thermali subsystem.
|
||||
*/
|
||||
int
|
||||
onlp_thermali_init(void)
|
||||
{
|
||||
mlnx_platform_info_t* mlnx_platform_info = get_platform_info();
|
||||
mlnx_platform_info->tinfo=tinfo;
|
||||
mlnx_platform_info->thermal_fnames=thermal_fnames;
|
||||
return ONLP_STATUS_OK;
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/**************************************************************************//**
|
||||
*
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include <x86_64_mlnx_msn3800/x86_64_mlnx_msn3800_config.h>
|
||||
|
||||
/* <auto.start.cdefs(X86_64_MLNX_MSN3800_CONFIG_HEADER).source> */
|
||||
#define __X86_64_MLNX_MSN3800_CONFIG_STRINGIFY_NAME(_x) #_x
|
||||
#define __X86_64_MLNX_MSN3800_CONFIG_STRINGIFY_VALUE(_x) __X86_64_MLNX_MSN3800_CONFIG_STRINGIFY_NAME(_x)
|
||||
x86_64_mlnx_msn3800_config_settings_t x86_64_mlnx_msn3800_config_settings[] =
|
||||
{
|
||||
#ifdef X86_64_MLNX_MSN3800_CONFIG_INCLUDE_LOGGING
|
||||
{ __X86_64_MLNX_MSN3800_CONFIG_STRINGIFY_NAME(X86_64_MLNX_MSN3800_CONFIG_INCLUDE_LOGGING), __X86_64_MLNX_MSN3800_CONFIG_STRINGIFY_VALUE(X86_64_MLNX_MSN3800_CONFIG_INCLUDE_LOGGING) },
|
||||
#else
|
||||
{ X86_64_MLNX_MSN3800_CONFIG_INCLUDE_LOGGING(__X86_64_MLNX_MSN3800_CONFIG_STRINGIFY_NAME), "__undefined__" },
|
||||
#endif
|
||||
#ifdef X86_64_MLNX_MSN3800_CONFIG_LOG_OPTIONS_DEFAULT
|
||||
{ __X86_64_MLNX_MSN3800_CONFIG_STRINGIFY_NAME(X86_64_MLNX_MSN3800_CONFIG_LOG_OPTIONS_DEFAULT), __X86_64_MLNX_MSN3800_CONFIG_STRINGIFY_VALUE(X86_64_MLNX_MSN3800_CONFIG_LOG_OPTIONS_DEFAULT) },
|
||||
#else
|
||||
{ X86_64_MLNX_MSN3800_CONFIG_LOG_OPTIONS_DEFAULT(__X86_64_MLNX_MSN3800_CONFIG_STRINGIFY_NAME), "__undefined__" },
|
||||
#endif
|
||||
#ifdef X86_64_MLNX_MSN3800_CONFIG_LOG_BITS_DEFAULT
|
||||
{ __X86_64_MLNX_MSN3800_CONFIG_STRINGIFY_NAME(X86_64_MLNX_MSN3800_CONFIG_LOG_BITS_DEFAULT), __X86_64_MLNX_MSN3800_CONFIG_STRINGIFY_VALUE(X86_64_MLNX_MSN3800_CONFIG_LOG_BITS_DEFAULT) },
|
||||
#else
|
||||
{ X86_64_MLNX_MSN3800_CONFIG_LOG_BITS_DEFAULT(__X86_64_MLNX_MSN3800_CONFIG_STRINGIFY_NAME), "__undefined__" },
|
||||
#endif
|
||||
#ifdef X86_64_MLNX_MSN3800_CONFIG_LOG_CUSTOM_BITS_DEFAULT
|
||||
{ __X86_64_MLNX_MSN3800_CONFIG_STRINGIFY_NAME(X86_64_MLNX_MSN3800_CONFIG_LOG_CUSTOM_BITS_DEFAULT), __X86_64_MLNX_MSN3800_CONFIG_STRINGIFY_VALUE(X86_64_MLNX_MSN3800_CONFIG_LOG_CUSTOM_BITS_DEFAULT) },
|
||||
#else
|
||||
{ X86_64_MLNX_MSN3800_CONFIG_LOG_CUSTOM_BITS_DEFAULT(__X86_64_MLNX_MSN3800_CONFIG_STRINGIFY_NAME), "__undefined__" },
|
||||
#endif
|
||||
#ifdef X86_64_MLNX_MSN3800_CONFIG_PORTING_STDLIB
|
||||
{ __X86_64_MLNX_MSN3800_CONFIG_STRINGIFY_NAME(X86_64_MLNX_MSN3800_CONFIG_PORTING_STDLIB), __X86_64_MLNX_MSN3800_CONFIG_STRINGIFY_VALUE(X86_64_MLNX_MSN3800_CONFIG_PORTING_STDLIB) },
|
||||
#else
|
||||
{ X86_64_MLNX_MSN3800_CONFIG_PORTING_STDLIB(__X86_64_MLNX_MSN3800_CONFIG_STRINGIFY_NAME), "__undefined__" },
|
||||
#endif
|
||||
#ifdef X86_64_MLNX_MSN3800_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS
|
||||
{ __X86_64_MLNX_MSN3800_CONFIG_STRINGIFY_NAME(X86_64_MLNX_MSN3800_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS), __X86_64_MLNX_MSN3800_CONFIG_STRINGIFY_VALUE(X86_64_MLNX_MSN3800_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS) },
|
||||
#else
|
||||
{ X86_64_MLNX_MSN3800_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS(__X86_64_MLNX_MSN3800_CONFIG_STRINGIFY_NAME), "__undefined__" },
|
||||
#endif
|
||||
#ifdef X86_64_MLNX_MSN3800_CONFIG_INCLUDE_UCLI
|
||||
{ __X86_64_MLNX_MSN3800_CONFIG_STRINGIFY_NAME(X86_64_MLNX_MSN3800_CONFIG_INCLUDE_UCLI), __X86_64_MLNX_MSN3800_CONFIG_STRINGIFY_VALUE(X86_64_MLNX_MSN3800_CONFIG_INCLUDE_UCLI) },
|
||||
#else
|
||||
{ X86_64_MLNX_MSN3800_CONFIG_INCLUDE_UCLI(__X86_64_MLNX_MSN3800_CONFIG_STRINGIFY_NAME), "__undefined__" },
|
||||
#endif
|
||||
#ifdef X86_64_MLNX_MSN3800_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION
|
||||
{ __X86_64_MLNX_MSN3800_CONFIG_STRINGIFY_NAME(X86_64_MLNX_MSN3800_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION), __X86_64_MLNX_MSN3800_CONFIG_STRINGIFY_VALUE(X86_64_MLNX_MSN3800_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION) },
|
||||
#else
|
||||
{ X86_64_MLNX_MSN3800_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION(__X86_64_MLNX_MSN3800_CONFIG_STRINGIFY_NAME), "__undefined__" },
|
||||
#endif
|
||||
{ NULL, NULL }
|
||||
};
|
||||
#undef __X86_64_MLNX_MSN3800_CONFIG_STRINGIFY_VALUE
|
||||
#undef __X86_64_MLNX_MSN3800_CONFIG_STRINGIFY_NAME
|
||||
|
||||
const char*
|
||||
x86_64_mlnx_msn3800_config_lookup(const char* setting)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; x86_64_mlnx_msn3800_config_settings[i].name; i++) {
|
||||
if(strcmp(x86_64_mlnx_msn3800_config_settings[i].name, setting)) {
|
||||
return x86_64_mlnx_msn3800_config_settings[i].value;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
x86_64_mlnx_msn3800_config_show(struct aim_pvs_s* pvs)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; x86_64_mlnx_msn3800_config_settings[i].name; i++) {
|
||||
aim_printf(pvs, "%s = %s\n", x86_64_mlnx_msn3800_config_settings[i].name, x86_64_mlnx_msn3800_config_settings[i].value);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/* <auto.end.cdefs(x86_64_mlnx_msn3800_CONFIG_HEADER).source> */
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
/**************************************************************************//**
|
||||
*
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include <x86_64_mlnx_msn3800/x86_64_mlnx_msn3800_config.h>
|
||||
|
||||
/* <--auto.start.enum(ALL).source> */
|
||||
/* <auto.end.enum(ALL).source> */
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
/**************************************************************************//**
|
||||
*
|
||||
* x86_64_mlnx_msn3800 Internal Header
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef __X86_64_MLNX_MSN3800_INT_H__
|
||||
#define __X86_64_MLNX_MSN3800_INT_H__
|
||||
|
||||
#include <x86_64_mlnx_msn3800/x86_64_mlnx_msn3800_config.h>
|
||||
|
||||
|
||||
#endif /* __X86_64_MLNX_MSN3800_INT_H__ */
|
||||
@@ -0,0 +1,18 @@
|
||||
/**************************************************************************//**
|
||||
*
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include <x86_64_mlnx_msn3800/x86_64_mlnx_msn3800_config.h>
|
||||
|
||||
#include "x86_64_mlnx_msn3800_log.h"
|
||||
/*
|
||||
* x86_64_mlnx_msn3800 log struct.
|
||||
*/
|
||||
AIM_LOG_STRUCT_DEFINE(
|
||||
X86_64_MLNX_MSN3800_CONFIG_LOG_OPTIONS_DEFAULT,
|
||||
X86_64_MLNX_MSN3800_CONFIG_LOG_BITS_DEFAULT,
|
||||
NULL, /* Custom log map */
|
||||
X86_64_MLNX_MSN3800_CONFIG_LOG_CUSTOM_BITS_DEFAULT
|
||||
);
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
/**************************************************************************//**
|
||||
*
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef __X86_64_MLNX_MSN3800_LOG_H__
|
||||
#define __X86_64_MLNX_MSN3800_LOG_H__
|
||||
|
||||
#define AIM_LOG_MODULE_NAME x86_64_mlnx_msn3800
|
||||
#include <AIM/aim_log.h>
|
||||
|
||||
#endif /* __X86_64_MLNX_MSN3800_LOG_H__ */
|
||||
@@ -0,0 +1,24 @@
|
||||
/**************************************************************************//**
|
||||
*
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include <x86_64_mlnx_msn3800/x86_64_mlnx_msn3800_config.h>
|
||||
|
||||
#include "x86_64_mlnx_msn3800_log.h"
|
||||
|
||||
static int
|
||||
datatypes_init__(void)
|
||||
{
|
||||
#define x86_64_mlnx_msn3800_ENUMERATION_ENTRY(_enum_name, _desc) AIM_DATATYPE_MAP_REGISTER(_enum_name, _enum_name##_map, _desc, AIM_LOG_INTERNAL);
|
||||
#include <x86_64_mlnx_msn3800/x86_64_mlnx_msn3800.x>
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __x86_64_mlnx_msn3800_module_init__(void)
|
||||
{
|
||||
AIM_LOG_STRUCT_REGISTER();
|
||||
datatypes_init__();
|
||||
}
|
||||
|
||||
int __onlp_platform_version__ = 1;
|
||||
@@ -0,0 +1,50 @@
|
||||
/**************************************************************************//**
|
||||
*
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include <x86_64_mlnx_msn3800/x86_64_mlnx_msn3800_config.h>
|
||||
|
||||
#if x86_64_mlnx_msn3800_CONFIG_INCLUDE_UCLI == 1
|
||||
|
||||
#include <uCli/ucli.h>
|
||||
#include <uCli/ucli_argparse.h>
|
||||
#include <uCli/ucli_handler_macros.h>
|
||||
|
||||
static ucli_status_t
|
||||
x86_64_mlnx_msn3800_ucli_ucli__config__(ucli_context_t* uc)
|
||||
{
|
||||
UCLI_HANDLER_MACRO_MODULE_CONFIG(x86_64_mlnx_msn3800)
|
||||
}
|
||||
|
||||
/* <auto.ucli.handlers.start> */
|
||||
/* <auto.ucli.handlers.end> */
|
||||
|
||||
static ucli_module_t
|
||||
x86_64_mlnx_msn3800_ucli_module__ =
|
||||
{
|
||||
"x86_64_mlnx_msn3800_ucli",
|
||||
NULL,
|
||||
x86_64_mlnx_msn3800_ucli_ucli_handlers__,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
ucli_node_t*
|
||||
x86_64_mlnx_msn3800_ucli_node_create(void)
|
||||
{
|
||||
ucli_node_t* n;
|
||||
ucli_module_init(&x86_64_mlnx_msn3800_ucli_module__);
|
||||
n = ucli_node_create("x86_64_mlnx_msn3800", NULL, &x86_64_mlnx_msn3800_ucli_module__);
|
||||
ucli_node_subnode_add(n, ucli_module_log_node_create("x86_64_mlnx_msn3800"));
|
||||
return n;
|
||||
}
|
||||
|
||||
#else
|
||||
void*
|
||||
x86_64_mlnx_msn3800_ucli_node_create(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# Inclusive Makefile for the x86_64_mlnx_msn3800 module.
|
||||
#
|
||||
# Autogenerated 2015-12-23 23:45:56.754200
|
||||
#
|
||||
###############################################################################
|
||||
x86_64_mlnx_msn3800_BASEDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||
include $(x86_64_mlnx_msn3800_BASEDIR)/module/make.mk
|
||||
include $(x86_64_mlnx_msn3800_BASEDIR)/module/auto/make.mk
|
||||
include $(x86_64_mlnx_msn3800_BASEDIR)/module/src/make.mk
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
include $(ONL)/make/pkg.mk
|
||||
@@ -0,0 +1 @@
|
||||
include $(ONL)/make/pkg.mk
|
||||
@@ -0,0 +1 @@
|
||||
!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=amd64 VENDOR=mellanox BASENAME=x86-64-mlnx-msn3800 REVISION=r0
|
||||
@@ -0,0 +1,33 @@
|
||||
---
|
||||
|
||||
######################################################################
|
||||
#
|
||||
# platform-config for Mellanox msn3800
|
||||
#
|
||||
######################################################################
|
||||
|
||||
x86-64-mlnx-msn3800-r0:
|
||||
|
||||
grub:
|
||||
|
||||
serial: >-
|
||||
--unit=0
|
||||
--speed=115200
|
||||
--word=8
|
||||
--parity=0
|
||||
--stop=1
|
||||
|
||||
kernel:
|
||||
<<: *kernel-4-9
|
||||
|
||||
args: >-
|
||||
nopat
|
||||
console=ttyS0,115200n8
|
||||
rd_NO_MD
|
||||
rd_NO_LUKS
|
||||
|
||||
##network
|
||||
## interfaces:
|
||||
## ma1:
|
||||
## name: ~
|
||||
## syspath: pci0000:00/0000:00:14.0
|
||||
@@ -0,0 +1,16 @@
|
||||
from onl.platform.base import *
|
||||
from onl.platform.mellanox import *
|
||||
|
||||
class OnlPlatform_x86_64_mlnx_msn3800_r0(OnlPlatformMellanox,
|
||||
OnlPlatformPortConfig_32x100):
|
||||
PLATFORM='x86-64-mlnx-msn3800-r0'
|
||||
MODEL="MSN3800"
|
||||
SYS_OBJECT_ID=".3800.1"
|
||||
|
||||
def baseconfig(self):
|
||||
# load modules
|
||||
import os
|
||||
# necessary if there are issues with the install
|
||||
# os.system("/usr/bin/apt-get install")
|
||||
self.syseeprom_export();
|
||||
return True
|
||||
Reference in New Issue
Block a user