From 671cdde36e26feb509e5cc25c0ca273907eaf914 Mon Sep 17 00:00:00 2001 From: Sai Prakash Ranjan Date: Thu, 17 Jan 2019 20:49:42 +0530 Subject: [PATCH 01/15] watchdog: qcom: Add suspend/resume support This adds the support for qcom watchdog suspend and resume when entering and exiting deep sleep states. Otherwise having watchdog active after suspend would result in unwanted crashes/resets if resume happens after a long time. Signed-off-by: Sai Prakash Ranjan Reviewed-by: Guenter Roeck Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/qcom-wdt.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/watchdog/qcom-wdt.c b/drivers/watchdog/qcom-wdt.c index 780971318810..5dfd604477a4 100644 --- a/drivers/watchdog/qcom-wdt.c +++ b/drivers/watchdog/qcom-wdt.c @@ -245,6 +245,28 @@ static int qcom_wdt_remove(struct platform_device *pdev) return 0; } +static int __maybe_unused qcom_wdt_suspend(struct device *dev) +{ + struct qcom_wdt *wdt = dev_get_drvdata(dev); + + if (watchdog_active(&wdt->wdd)) + qcom_wdt_stop(&wdt->wdd); + + return 0; +} + +static int __maybe_unused qcom_wdt_resume(struct device *dev) +{ + struct qcom_wdt *wdt = dev_get_drvdata(dev); + + if (watchdog_active(&wdt->wdd)) + qcom_wdt_start(&wdt->wdd); + + return 0; +} + +static SIMPLE_DEV_PM_OPS(qcom_wdt_pm_ops, qcom_wdt_suspend, qcom_wdt_resume); + static const struct of_device_id qcom_wdt_of_table[] = { { .compatible = "qcom,kpss-timer", .data = reg_offset_data_apcs_tmr }, { .compatible = "qcom,scss-timer", .data = reg_offset_data_apcs_tmr }, @@ -259,6 +281,7 @@ static struct platform_driver qcom_watchdog_driver = { .driver = { .name = KBUILD_MODNAME, .of_match_table = qcom_wdt_of_table, + .pm = &qcom_wdt_pm_ops, }, }; module_platform_driver(qcom_watchdog_driver); From 59600d045ff411da193a8b5a2999681801ecd430 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Fri, 26 Oct 2018 09:55:53 +0100 Subject: [PATCH 02/15] dt-bindings: watchdog: renesas-wdt: Document r8a77470 support RZ/G1C (R8A77470) watchdog implementation is compatible with R-Car Gen2, therefore add relevant documentation. Signed-off-by: Biju Das Reviewed-by: Fabrizio Castro Reviewed-by: Simon Horman Reviewed-by: Rob Herring Reviewed-by: Geert Uytterhoeven Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- Documentation/devicetree/bindings/watchdog/renesas-wdt.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/watchdog/renesas-wdt.txt b/Documentation/devicetree/bindings/watchdog/renesas-wdt.txt index ef2b97b72e08..9f365c1a3399 100644 --- a/Documentation/devicetree/bindings/watchdog/renesas-wdt.txt +++ b/Documentation/devicetree/bindings/watchdog/renesas-wdt.txt @@ -8,6 +8,7 @@ Required properties: - "renesas,r8a7743-wdt" (RZ/G1M) - "renesas,r8a7744-wdt" (RZ/G1N) - "renesas,r8a7745-wdt" (RZ/G1E) + - "renesas,r8a77470-wdt" (RZ/G1C) - "renesas,r8a774a1-wdt" (RZ/G2M) - "renesas,r8a774c0-wdt" (RZ/G2E) - "renesas,r8a7790-wdt" (R-Car H2) From 00fd20b4d94ef4200993eab13a108d7c68b0202b Mon Sep 17 00:00:00 2001 From: Jerry Hoemann Date: Fri, 8 Feb 2019 10:48:03 -0700 Subject: [PATCH 03/15] watchdog/hpwdt: Update Kconfig documentation Update documentation relating to HPWDT_NMI_DECODING to reflect its current usage. Signed-off-by: Jerry Hoemann Reviewed-by: Guenter Roeck Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 57f017d74a97..846dd07e9a8a 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -1145,7 +1145,7 @@ config HP_WATCHDOG select WATCHDOG_CORE depends on X86 && PCI help - A software monitoring watchdog and NMI sourcing driver. This driver + A software monitoring watchdog and NMI handling driver. This driver will detect lockups and provide a stack trace. This is a driver that will only load on an HP ProLiant system with a minimum of iLO2 support. To compile this driver as a module, choose M here: the module will be @@ -1163,12 +1163,13 @@ config KEMPLD_WDT called kempld_wdt. config HPWDT_NMI_DECODING - bool "NMI decoding support for the HP ProLiant iLO2+ Hardware Watchdog Timer" + bool "NMI support for the HP ProLiant iLO2+ Hardware Watchdog Timer" depends on HP_WATCHDOG default y help - When an NMI occurs this feature will make the necessary BIOS calls to - log the cause of the NMI. + Enables the NMI handler for the watchdog pretimeout NMI and the iLO + "Generate NMI to System" virtual button. When an NMI is claimed + by the driver, panic is called. config SC1200_WDT tristate "National Semiconductor PC87307/PC97307 (ala SC1200) Watchdog" From da39013e8e6aecc7afe0654ad87cf2f0fad993af Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Wed, 23 Jan 2019 17:05:24 +0800 Subject: [PATCH 04/15] watchdog: pika_wdt: drop pointless static qualifier in pikawdt_init There is no need to have the 'post1' variable static since new value always be assigned before use it. Signed-off-by: YueHaibing Reviewed-by: Guenter Roeck Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/pika_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/watchdog/pika_wdt.c b/drivers/watchdog/pika_wdt.c index e0a6f8c0f03c..bb97f5b2f7eb 100644 --- a/drivers/watchdog/pika_wdt.c +++ b/drivers/watchdog/pika_wdt.c @@ -225,7 +225,7 @@ static int __init pikawdt_init(void) { struct device_node *np; void __iomem *fpga; - static u32 post1; + u32 post1; int ret; np = of_find_compatible_node(NULL, NULL, "pika,fpga"); From b6ce9c73941abd3e9791bf60f466ae7f7e090c30 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Fri, 25 Jan 2019 07:57:52 +0000 Subject: [PATCH 05/15] watchdog: dw: remove useless pr_fmt When switch to watchdog infrastructure, pr_* usage is removed, so there's no any users of the pr_fmt, remove it. Signed-off-by: Jisheng Zhang Reviewed-by: Guenter Roeck Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/dw_wdt.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c index 501aebb5b81f..aa95f57cc1c3 100644 --- a/drivers/watchdog/dw_wdt.c +++ b/drivers/watchdog/dw_wdt.c @@ -16,8 +16,6 @@ * heartbeat requests after the watchdog device has been closed. */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include #include #include From d02d104ea0cefc6ed33e49832c7d70ffa5ab3a67 Mon Sep 17 00:00:00 2001 From: Jerry Hoemann Date: Mon, 4 Feb 2019 16:57:36 -0700 Subject: [PATCH 06/15] watchdog: Update sysfs documentation. Document the sysfs attributes: pretimeout pretimeout_available_governors pretimeout_governor Signed-off-by: Jerry Hoemann Reviewed-by: Guenter Roeck Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- .../ABI/testing/sysfs-class-watchdog | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-class-watchdog b/Documentation/ABI/testing/sysfs-class-watchdog index 736046b33040..6317ade5ad19 100644 --- a/Documentation/ABI/testing/sysfs-class-watchdog +++ b/Documentation/ABI/testing/sysfs-class-watchdog @@ -49,3 +49,26 @@ Contact: Wim Van Sebroeck Description: It is a read only file. It is read to know about current value of timeout programmed. + +What: /sys/class/watchdog/watchdogn/pretimeout +Date: December 2016 +Contact: Wim Van Sebroeck +Description: + It is a read only file. It specifies the time in seconds before + timeout when the pretimeout interrupt is delivered. Pretimeout + is an optional feature. + +What: /sys/class/watchdog/watchdogn/pretimeout_avaialable_governors +Date: February 2017 +Contact: Wim Van Sebroeck +Description: + It is a read only file. It shows the pretimeout governors + available for this watchdog. + +What: /sys/class/watchdog/watchdogn/pretimeout_governor +Date: February 2017 +Contact: Wim Van Sebroeck +Description: + It is a read/write file. When read, the currently assigned + pretimeout governor is returned. When written, it sets + the pretimeout governor. From 9f03161a1bd8cd9ccf11533e52326718c656036e Mon Sep 17 00:00:00 2001 From: Michael Shych Date: Wed, 20 Feb 2019 09:34:22 +0000 Subject: [PATCH 07/15] platform_data/mlxreg: additions for Mellanox watchdog driver. There are two new fields added to mlxreg core structure: features - supported features of device and identity - device identity name. Add new defines for watchdog features. Signed-off-by: Michael Shych Reviewed-by: Guenter Roeck Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- include/linux/platform_data/mlxreg.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/include/linux/platform_data/mlxreg.h b/include/linux/platform_data/mlxreg.h index 19f5cb618c55..31f7c25a44da 100644 --- a/include/linux/platform_data/mlxreg.h +++ b/include/linux/platform_data/mlxreg.h @@ -35,6 +35,19 @@ #define __LINUX_PLATFORM_DATA_MLXREG_H #define MLXREG_CORE_LABEL_MAX_SIZE 32 +#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: @@ -110,11 +123,17 @@ struct mlxreg_core_item { * @led_data: led private data; * @regmap: register map of parent device; * @counter: number of led instances; + * @features: supported features of device; + * @version: implementation version; + * @identity: device identity name; */ struct mlxreg_core_platform_data { struct mlxreg_core_data *data; void *regmap; int counter; + u32 features; + u32 version; + char identity[MLXREG_CORE_LABEL_MAX_SIZE]; }; /** From c60923dd5feedc337b1450e3f4c6e19ffa305439 Mon Sep 17 00:00:00 2001 From: Michael Shych Date: Wed, 20 Feb 2019 09:34:23 +0000 Subject: [PATCH 08/15] watchdog: mlx-wdt: introduce a watchdog driver for Mellanox systems. Introduce watchdog driver for a various range of Mellanox Ethernet and Infiniband switch 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 a counter. The last 2 actions are performed without a system reset. Actions without reset are provided for auxiliary watchdog devices, which is optional. Access to HW registers is performed through generic regmap interface. There are 2 types of HW 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 the same as user-defined timeout; maximum timeout is 255 sec; get time-left is supported; Watchdog driver is probed from the common mlx_platform driver. Signed-off-by: Michael Shych Reviewed-by: Guenter Roeck Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 16 ++ drivers/watchdog/Makefile | 1 + drivers/watchdog/mlx_wdt.c | 290 +++++++++++++++++++++++++++++++++++++ 3 files changed, 307 insertions(+) create mode 100644 drivers/watchdog/mlx_wdt.c diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 846dd07e9a8a..a3fe5e988fb0 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -241,6 +241,22 @@ config RAVE_SP_WATCHDOG help Support for the watchdog on RAVE SP device. +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 --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index a0917ef28e07..941b74185c9c 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -142,6 +142,7 @@ 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_NIC7018_WDT) += nic7018_wdt.o +obj-$(CONFIG_MLX_WDT) += mlx_wdt.o # M68K Architecture obj-$(CONFIG_M54xx_WATCHDOG) += m54xx_wdt.o diff --git a/drivers/watchdog/mlx_wdt.c b/drivers/watchdog/mlx_wdt.c new file mode 100644 index 000000000000..70c2cbf9c993 --- /dev/null +++ b/drivers/watchdog/mlx_wdt.c @@ -0,0 +1,290 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Mellanox watchdog driver + * + * Copyright (C) 2019 Mellanox Technologies + * Copyright (C) 2019 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_OPTIONS_BASE (WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE | \ + WDIOF_SETTIMEOUT) + +/** + * 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.; + * @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; + */ +struct mlxreg_wdt { + struct watchdog_device wdd; + struct mlxreg_core_platform_data *pdata; + void *regmap; + int action_idx; + int timeout_idx; + int tleft_idx; + int ping_idx; + int reset_idx; + enum mlxreg_wdt_type wdt_type; +}; + +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; + + if (!(wdt->wdd.info->options & WDIOF_CARDRESET)) + return; + + reg_data = &wdt->pdata->data[wdt->reset_idx]; + rc = regmap_read(wdt->regmap, reg_data->reg, ®val); + if (!rc) { + if (regval & ~reg_data->mask) { + wdt->wdd.bootstatus = WDIOF_CARDRESET; + dev_info(wdt->wdd.parent, + "watchdog previously reset the CPU\n"); + } + } +} + +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]; + + 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]; + + 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]; + + 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, + 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, set_time, hw_timeout; + int rc; + + if (wdt->wdt_type == MLX_WDT_TYPE1) { + rc = regmap_read(wdt->regmap, reg_data->reg, ®val); + if (rc) + 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 { + set_time = timeout; + regval = timeout; + } + + wdd->timeout = set_time; + rc = regmap_write(wdt->regmap, reg_data->reg, regval); + + 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; +} + +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->tleft_idx]; + u32 regval; + int rc; + + rc = regmap_read(wdt->regmap, reg_data->reg, ®val); + /* Return 0 timeleft in case of failure register read. */ + return rc == 0 ? regval : 0; +} + +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 = MLXREG_WDT_OPTIONS_BASE + | WDIOF_CARDRESET, + .identity = "mlx-wdt-main", +}; + +static const struct watchdog_info mlxreg_wdt_aux_info = { + .options = MLXREG_WDT_OPTIONS_BASE + | WDIOF_ALARMONLY, + .identity = "mlx-wdt-aux", +}; + +static void mlxreg_wdt_config(struct mlxreg_wdt *wdt, + struct mlxreg_core_platform_data *pdata) +{ + struct mlxreg_core_data *data = pdata->data; + int i; + + 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, "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))) + 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; + + wdt->wdt_type = pdata->version; + if (wdt->wdt_type == MLX_WDT_TYPE2) { + wdt->wdd.ops = &mlxreg_wdt_ops_type2; + wdt->wdd.max_timeout = MLXREG_WDT_MAX_TIMEOUT_TYPE2; + } else { + wdt->wdd.ops = &mlxreg_wdt_ops_type1; + wdt->wdd.max_timeout = MLXREG_WDT_MAX_TIMEOUT_TYPE1; + } + wdt->wdd.min_timeout = MLXREG_WDT_MIN_TIMEOUT; +} + +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) +{ + 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; + + wdt->wdd.parent = &pdev->dev; + wdt->regmap = pdata->regmap; + mlxreg_wdt_config(wdt, pdata); + + if ((pdata->features & MLXREG_CORE_WD_FEATURE_NOWAYOUT)) + watchdog_set_nowayout(&wdt->wdd, WATCHDOG_NOWAYOUT); + watchdog_stop_on_reboot(&wdt->wdd); + watchdog_stop_on_unregister(&wdt->wdd); + 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); + +register_error: + if (rc) + dev_err(&pdev->dev, + "Cannot register watchdog device (err=%d)\n", rc); + return rc; +} + +static struct platform_driver mlxreg_wdt_driver = { + .probe = mlxreg_wdt_probe, + .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"); From 9d489ad121927609d6e51df1a755707966945a53 Mon Sep 17 00:00:00 2001 From: Michael Shych Date: Sun, 24 Feb 2019 17:26:31 +0000 Subject: [PATCH 09/15] Documentation/watchdog: Add documentation mlx-wdt driver Add documentation with details of Mellanox watchdog driver. Signed-off-by: Michael Shych Reviewed-by: Guenter Roeck Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- Documentation/watchdog/mlx-wdt.txt | 52 ++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 Documentation/watchdog/mlx-wdt.txt diff --git a/Documentation/watchdog/mlx-wdt.txt b/Documentation/watchdog/mlx-wdt.txt new file mode 100644 index 000000000000..66eeb78505c3 --- /dev/null +++ b/Documentation/watchdog/mlx-wdt.txt @@ -0,0 +1,52 @@ + Mellanox watchdog drivers + for x86 based system switches + +This driver provides watchdog functionality for various Mellanox +Ethernet and Infiniband switch systems. + +Mellanox watchdog device is implemented in a programmable logic device. + +There are 2 types of HW watchdog implementations. + +Type 1: +Actual HW timeout can be defined as a power of 2 msec. +e.g. timeout 20 sec will be rounded up to 32768 msec. +The 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 the same as +a user-defined timeout. +Maximum timeout is 255 sec. +Get time-left is supported. + +Type 1 HW watchdog implementation exist in old systems and +all new systems have type 2 HW watchdog. +Two types of HW implementation have also different register map. + +Mellanox system can have 2 watchdogs: main and auxiliary. +Main and auxiliary watchdog devices can be enabled together +on the same system. +There are several actions that can be defined in the watchdog: +system reset, start fans on full speed and increase register counter. +The last 2 actions are performed without a system reset. +Actions without reset are provided for auxiliary watchdog device, +which is optional. +Watchdog can be started during a probe, in this case it will be +pinged by watchdog core before watchdog device will be opened by +user space application. +Watchdog can be initialised in nowayout way, i.e. oncse started +it can't be stopped. + +This mlx-wdt driver supports both HW watchdog implementations. + +Watchdog driver is probed from the common mlx_platform driver. +Mlx_platform driver provides an appropriate set of registers for +Mellanox watchdog device, identity name (mlx-wdt-main or mlx-wdt-aux), +initial timeout, performed action in expiration and configuration flags. +watchdog configuration flags: nowayout and start_at_boot, hw watchdog +version - type1 or type2. +The driver checks during initialization if the previous system reset +was done by the watchdog. If yes, it makes a notification about this event. + +Access to HW registers is performed through a generic regmap interface. From 8baee57218f6dcd976bb5cb13d8262fbbd153282 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 14 Feb 2019 14:26:18 -0600 Subject: [PATCH 10/15] watchdog: pc87413: Mark expected switch fall-through MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. This patch fixes the following warning: drivers/watchdog/pc87413_wdt.c: In function ‘pc87413_ioctl’: drivers/watchdog/pc87413_wdt.c:439:3: warning: this statement may fall through [-Wimplicit-fallthrough=] pc87413_refresh(); ^~~~~~~~~~~~~~~~~ drivers/watchdog/pc87413_wdt.c:441:2: note: here case WDIOC_GETTIMEOUT: ^~~~ Warning level 3 was used: -Wimplicit-fallthrough=3 Notice that, in this particular case, the code comment is modified in accordance with what GCC is expecting to find. This patch is part of the ongoing efforts to enable -Wimplicit-fallthrough. Signed-off-by: Gustavo A. R. Silva Reviewed-by: Guenter Roeck Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/pc87413_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/watchdog/pc87413_wdt.c b/drivers/watchdog/pc87413_wdt.c index 06a892e36a8d..2ffa39b46970 100644 --- a/drivers/watchdog/pc87413_wdt.c +++ b/drivers/watchdog/pc87413_wdt.c @@ -437,7 +437,7 @@ static long pc87413_ioctl(struct file *file, unsigned int cmd, return -EINVAL; timeout = new_timeout; pc87413_refresh(); - /* fall through and return the new timeout... */ + /* fall through - and return the new timeout... */ case WDIOC_GETTIMEOUT: new_timeout = timeout * 60; return put_user(new_timeout, uarg.i); From 51c802f57a0c4ce17f472d8fb718ecd94e23c5d3 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 14 Feb 2019 14:20:08 -0600 Subject: [PATCH 11/15] watchdog: sc1200: Mark expected switch fall-through MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. This patch fixes the following warning: drivers/watchdog/sc1200wdt.c: In function ‘sc1200wdt_ioctl’: drivers/watchdog/sc1200wdt.c:241:3: warning: this statement may fall through [-Wimplicit-fallthrough=] sc1200wdt_write_data(WDTO, timeout); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/watchdog/sc1200wdt.c:244:2: note: here case WDIOC_GETTIMEOUT: ^~~~ Warning level 3 was used: -Wimplicit-fallthrough=3 Notice that, in this particular case, the code comment is modified in accordance with what GCC is expecting to find. This patch is part of the ongoing efforts to enable -Wimplicit-fallthrough. Signed-off-by: Gustavo A. R. Silva Reviewed-by: Guenter Roeck Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/sc1200wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/watchdog/sc1200wdt.c b/drivers/watchdog/sc1200wdt.c index 8e4e2fc13f87..e035a4d4b299 100644 --- a/drivers/watchdog/sc1200wdt.c +++ b/drivers/watchdog/sc1200wdt.c @@ -239,7 +239,7 @@ static long sc1200wdt_ioctl(struct file *file, unsigned int cmd, return -EINVAL; timeout = new_timeout; sc1200wdt_write_data(WDTO, timeout); - /* fall through and return the new timeout */ + /* fall through - and return the new timeout */ case WDIOC_GETTIMEOUT: return put_user(timeout * 60, p); From 4a1b1161561ed573a324d7a708b66df5e0f30114 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 14 Feb 2019 14:16:01 -0600 Subject: [PATCH 12/15] watchdog: smsc37b787_wdt: Mark expected switch fall-through MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. This patch fixes the following warning: drivers/watchdog/smsc37b787_wdt.c: In function ‘wb_smsc_wdt_ioctl’: drivers/watchdog/smsc37b787_wdt.c:480:3: warning: this statement may fall through [-Wimplicit-fallthrough=] wb_smsc_wdt_set_timeout(timeout); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/watchdog/smsc37b787_wdt.c:482:2: note: here case WDIOC_GETTIMEOUT: ^~~~ Warning level 3 was used: -Wimplicit-fallthrough=3 Notice that, in this particular case, the code comment is modified in accordance with what GCC is expecting to find. This patch is part of the ongoing efforts to enable -Wimplicit-fallthrough. Signed-off-by: Gustavo A. R. Silva Reviewed-by: Guenter Roeck Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/smsc37b787_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/watchdog/smsc37b787_wdt.c b/drivers/watchdog/smsc37b787_wdt.c index 445ea1ad1fa9..c768dcd53034 100644 --- a/drivers/watchdog/smsc37b787_wdt.c +++ b/drivers/watchdog/smsc37b787_wdt.c @@ -478,7 +478,7 @@ static long wb_smsc_wdt_ioctl(struct file *file, return -EINVAL; timeout = new_timeout; wb_smsc_wdt_set_timeout(timeout); - /* fall through and return the new timeout... */ + /* fall through - and return the new timeout... */ case WDIOC_GETTIMEOUT: new_timeout = timeout; if (unit == UNIT_MINUTE) From 3612b87d181beffe2ad7ff21c46f5a5bb2c58c65 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 26 Feb 2019 11:58:35 -0600 Subject: [PATCH 13/15] watchdog: sbc60xxwdt: Mark expected switch fall-through MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. This patch fixes the following warning: drivers/watchdog/sbc60xxwdt.c: In function ‘fop_ioctl’: drivers/watchdog/sbc60xxwdt.c:272:3: warning: this statement may fall through [-Wimplicit-fallthrough=] wdt_keepalive(); ^~~~~~~~~~~~~~~ drivers/watchdog/sbc60xxwdt.c:275:2: note: here case WDIOC_GETTIMEOUT: ^~~~ Notice that, in this particular case, the code comment is modified in accordance with what GCC is expecting to find. This patch is part of the ongoing efforts to enable -Wimplicit-fallthrough. Signed-off-by: Gustavo A. R. Silva Reviewed-by: Guenter Roeck Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/sbc60xxwdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/watchdog/sbc60xxwdt.c b/drivers/watchdog/sbc60xxwdt.c index 87333a41f753..72d15fd1f183 100644 --- a/drivers/watchdog/sbc60xxwdt.c +++ b/drivers/watchdog/sbc60xxwdt.c @@ -270,8 +270,8 @@ static long fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) timeout = new_timeout; wdt_keepalive(); - /* Fall through */ } + /* Fall through */ case WDIOC_GETTIMEOUT: return put_user(timeout, p); default: From e70d3547fc44892d12543b039c40dbadc0ffaaee Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 26 Feb 2019 12:01:14 -0600 Subject: [PATCH 14/15] watchdog: sc520_wdt: Mark expected switch fall-through MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. This patch fixes the following warning: drivers/watchdog/sc520_wdt.c: In function ‘fop_ioctl’: drivers/watchdog/sc520_wdt.c:326:3: warning: this statement may fall through [-Wimplicit-fallthrough=] wdt_keepalive(); ^~~~~~~~~~~~~~~ drivers/watchdog/sc520_wdt.c:329:2: note: here case WDIOC_GETTIMEOUT: ^~~~ Warning level 3 was used: -Wimplicit-fallthrough=3 Notice that, in this particular case, the code comment is modified in accordance with what GCC is expecting to find. This patch is part of the ongoing efforts to enable -Wimplicit-fallthrough. Signed-off-by: Gustavo A. R. Silva Reviewed-by: Guenter Roeck Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/sc520_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/watchdog/sc520_wdt.c b/drivers/watchdog/sc520_wdt.c index 6aadb56e7faa..403542f9ed8d 100644 --- a/drivers/watchdog/sc520_wdt.c +++ b/drivers/watchdog/sc520_wdt.c @@ -324,8 +324,8 @@ static long fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return -EINVAL; wdt_keepalive(); - /* Fall through */ } + /* Fall through */ case WDIOC_GETTIMEOUT: return put_user(timeout, p); default: From 458c8961c194f2d2cb6ffed3dd9b6692d74ad65e Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 26 Feb 2019 13:07:43 -0600 Subject: [PATCH 15/15] watchdog: w83877f_wdt: Mark expected switch fall-through MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. This patch fixes the following warning: drivers/watchdog/w83877f_wdt.c: In function ‘fop_ioctl’: drivers/watchdog/w83877f_wdt.c:294:3: warning: this statement may fall through [-Wimplicit-fallthrough=] wdt_keepalive(); ^~~~~~~~~~~~~~~ drivers/watchdog/w83877f_wdt.c:297:2: note: here case WDIOC_GETTIMEOUT: ^~~~ Warning level 3 was used: -Wimplicit-fallthrough=3 Notice that, in this particular case, the code comment is modified in accordance with what GCC is expecting to find. This patch is part of the ongoing efforts to enable -Wimplicit-fallthrough. Signed-off-by: Gustavo A. R. Silva Reviewed-by: Guenter Roeck Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/w83877f_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/watchdog/w83877f_wdt.c b/drivers/watchdog/w83877f_wdt.c index 05658ecc0aa4..db9b6488e388 100644 --- a/drivers/watchdog/w83877f_wdt.c +++ b/drivers/watchdog/w83877f_wdt.c @@ -292,8 +292,8 @@ static long fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) timeout = new_timeout; wdt_keepalive(); - /* Fall through */ } + /* Fall through */ case WDIOC_GETTIMEOUT: return put_user(timeout, p); default: