From 85ceb284c2e8fb6b6ebcf437b2d9d9ea2512bf6c Mon Sep 17 00:00:00 2001 From: Oleksandr Shamray Date: Mon, 4 Feb 2019 13:18:16 +0000 Subject: [PATCH] Removed: mallanox wdt driver patch Signed-off-by: Oleksandr Shamray --- .../configs/x86_64-all/x86_64-all.config | 5 +- ...-introduce-watchdog-driver-for-Mella.patch | 839 ------------------ .../base/any/kernels/4.9-lts/patches/series | 1 - 3 files changed, 2 insertions(+), 843 deletions(-) delete mode 100644 packages/base/any/kernels/4.9-lts/patches/0019-watchdog-mlx-wdt-introduce-watchdog-driver-for-Mella.patch diff --git a/packages/base/any/kernels/4.9-lts/configs/x86_64-all/x86_64-all.config b/packages/base/any/kernels/4.9-lts/configs/x86_64-all/x86_64-all.config index 2a376cc8..46985dd6 100644 --- a/packages/base/any/kernels/4.9-lts/configs/x86_64-all/x86_64-all.config +++ b/packages/base/any/kernels/4.9-lts/configs/x86_64-all/x86_64-all.config @@ -2549,9 +2549,9 @@ CONFIG_X86_PKG_TEMP_THERMAL=m # CONFIG_INTEL_PCH_THERMAL is not set # CONFIG_GENERIC_ADC_THERMAL is not set CONFIG_WATCHDOG=y -CONFIG_WATCHDOG_CORE=y +# CONFIG_WATCHDOG_CORE is not set # CONFIG_WATCHDOG_NOWAYOUT is not set -CONFIG_WATCHDOG_SYSFS=y +# CONFIG_WATCHDOG_SYSFS is not set # # Watchdog Device Drivers @@ -2595,7 +2595,6 @@ CONFIG_WATCHDOG_SYSFS=y # CONFIG_SBC_EPX_C3_WATCHDOG is not set # CONFIG_NI903X_WDT is not set # CONFIG_MEN_A21_WDT is not set -CONFIG_MLX_WDT=m # # PCI-based Watchdog Cards diff --git a/packages/base/any/kernels/4.9-lts/patches/0019-watchdog-mlx-wdt-introduce-watchdog-driver-for-Mella.patch b/packages/base/any/kernels/4.9-lts/patches/0019-watchdog-mlx-wdt-introduce-watchdog-driver-for-Mella.patch deleted file mode 100644 index d29b5c5c..00000000 --- a/packages/base/any/kernels/4.9-lts/patches/0019-watchdog-mlx-wdt-introduce-watchdog-driver-for-Mella.patch +++ /dev/null @@ -1,839 +0,0 @@ -From a648f2856518f8884a7798469faf755d0f5dcd50 Mon Sep 17 00:00:00 2001 -From: Michael Shych -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 ---- - 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 -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#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 "); -+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 - diff --git a/packages/base/any/kernels/4.9-lts/patches/series b/packages/base/any/kernels/4.9-lts/patches/series index 6599e9c5..22527ddb 100644 --- a/packages/base/any/kernels/4.9-lts/patches/series +++ b/packages/base/any/kernels/4.9-lts/patches/series @@ -19,6 +19,5 @@ 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