You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge git://www.linux-watchdog.org/linux-watchdog
Pull watchdog updates from Wim Van Sebroeck: - a new watchdog pretimeout governor framework - support to upload the firmware on the ziirave_wdt - several fixes and cleanups * git://www.linux-watchdog.org/linux-watchdog: (26 commits) watchdog: imx2_wdt: add pretimeout function support watchdog: softdog: implement pretimeout support watchdog: pretimeout: add pretimeout_available_governors attribute watchdog: pretimeout: add option to select a pretimeout governor in runtime watchdog: pretimeout: add panic pretimeout governor watchdog: pretimeout: add noop pretimeout governor watchdog: add watchdog pretimeout governor framework watchdog: hpwdt: add support for iLO5 fs: compat_ioctl: add pretimeout functions for watchdogs watchdog: add pretimeout support to the core watchdog: imx2_wdt: use preferred BIT macro instead of open coded values watchdog: st_wdt: Remove support for obsolete platforms watchdog: bindings: Remove obsolete platforms from dt doc. watchdog: mt7621_wdt: Remove assignment of dev pointer watchdog: rt2880_wdt: Remove assignment of dev pointer watchdog: constify watchdog_ops structures watchdog: tegra: constify watchdog_ops structures watchdog: iTCO_wdt: constify iTCO_wdt_pm structure watchdog: cadence_wdt: Fix the suspend resume watchdog: txx9wdt: Add missing clock (un)prepare calls for CCF ...
This commit is contained in:
@@ -7,6 +7,8 @@ Required properties:
|
||||
- reg : Physical base address and size
|
||||
|
||||
Optional properties:
|
||||
- clocks : Input clock specifier. Refer to common clock
|
||||
bindings.
|
||||
- clock-frequency : Frequency of clock in Hz
|
||||
- xlnx,wdt-enable-once : 0 - Watchdog can be restarted
|
||||
1 - Watchdog can be enabled just once
|
||||
@@ -17,6 +19,7 @@ Example:
|
||||
axi-timebase-wdt@40100000 {
|
||||
clock-frequency = <50000000>;
|
||||
compatible = "xlnx,xps-timebase-wdt-1.00.a";
|
||||
clocks = <&clkc 15>;
|
||||
reg = <0x40100000 0x10000>;
|
||||
xlnx,wdt-enable-once = <0x0>;
|
||||
xlnx,wdt-interval = <0x1b>;
|
||||
|
||||
@@ -9,8 +9,7 @@ functionality.
|
||||
|
||||
Required properties
|
||||
|
||||
- compatible : Must be one of: "st,stih407-lpc" "st,stih416-lpc"
|
||||
"st,stih415-lpc" "st,stid127-lpc"
|
||||
- compatible : Should be: "st,stih407-lpc"
|
||||
- reg : LPC registers base address + size
|
||||
- interrupts : LPC interrupt line number and associated flags
|
||||
- clocks : Clock used by LPC device (See: ../clock/clock-bindings.txt)
|
||||
|
||||
@@ -48,8 +48,10 @@ struct watchdog_device {
|
||||
const struct attribute_group **groups;
|
||||
const struct watchdog_info *info;
|
||||
const struct watchdog_ops *ops;
|
||||
const struct watchdog_governor *gov;
|
||||
unsigned int bootstatus;
|
||||
unsigned int timeout;
|
||||
unsigned int pretimeout;
|
||||
unsigned int min_timeout;
|
||||
unsigned int max_timeout;
|
||||
unsigned int min_hw_heartbeat_ms;
|
||||
@@ -74,9 +76,11 @@ It contains following fields:
|
||||
* info: a pointer to a watchdog_info structure. This structure gives some
|
||||
additional information about the watchdog timer itself. (Like it's unique name)
|
||||
* ops: a pointer to the list of watchdog operations that the watchdog supports.
|
||||
* gov: a pointer to the assigned watchdog device pretimeout governor or NULL.
|
||||
* timeout: the watchdog timer's timeout value (in seconds).
|
||||
This is the time after which the system will reboot if user space does
|
||||
not send a heartbeat request if WDOG_ACTIVE is set.
|
||||
* pretimeout: the watchdog timer's pretimeout value (in seconds).
|
||||
* min_timeout: the watchdog timer's minimum timeout value (in seconds).
|
||||
If set, the minimum configurable value for 'timeout'.
|
||||
* max_timeout: the watchdog timer's maximum timeout value (in seconds),
|
||||
@@ -121,6 +125,7 @@ struct watchdog_ops {
|
||||
int (*ping)(struct watchdog_device *);
|
||||
unsigned int (*status)(struct watchdog_device *);
|
||||
int (*set_timeout)(struct watchdog_device *, unsigned int);
|
||||
int (*set_pretimeout)(struct watchdog_device *, unsigned int);
|
||||
unsigned int (*get_timeleft)(struct watchdog_device *);
|
||||
int (*restart)(struct watchdog_device *);
|
||||
void (*ref)(struct watchdog_device *) __deprecated;
|
||||
@@ -188,6 +193,23 @@ they are supported. These optional routines/operations are:
|
||||
If set_timeout is not provided but, WDIOF_SETTIMEOUT is set, the watchdog
|
||||
infrastructure updates the timeout value of the watchdog_device internally
|
||||
to the requested value.
|
||||
If the pretimeout feature is used (WDIOF_PRETIMEOUT), then set_timeout must
|
||||
also take care of checking if pretimeout is still valid and set up the timer
|
||||
accordingly. This can't be done in the core without races, so it is the
|
||||
duty of the driver.
|
||||
* set_pretimeout: this routine checks and changes the pretimeout value of
|
||||
the watchdog. It is optional because not all watchdogs support pretimeout
|
||||
notification. The timeout value is not an absolute time, but the number of
|
||||
seconds before the actual timeout would happen. It returns 0 on success,
|
||||
-EINVAL for "parameter out of range" and -EIO for "could not write value to
|
||||
the watchdog". A value of 0 disables pretimeout notification.
|
||||
(Note: the WDIOF_PRETIMEOUT needs to be set in the options field of the
|
||||
watchdog's info structure).
|
||||
If the watchdog driver does not have to perform any action but setting the
|
||||
watchdog_device.pretimeout, this callback can be omitted. That means if
|
||||
set_pretimeout is not provided but WDIOF_PRETIMEOUT is set, the watchdog
|
||||
infrastructure updates the pretimeout value of the watchdog_device internally
|
||||
to the requested value.
|
||||
* get_timeleft: this routines returns the time that's left before a reset.
|
||||
* restart: this routine restarts the machine. It returns 0 on success or a
|
||||
negative errno code for failure.
|
||||
@@ -268,3 +290,14 @@ User should follow the following guidelines for setting the priority:
|
||||
* 128: default restart handler, use if no other handler is expected to be
|
||||
available, and/or if restart is sufficient to restart the entire system
|
||||
* 255: highest priority, will preempt all other restart handlers
|
||||
|
||||
To raise a pretimeout notification, the following function should be used:
|
||||
|
||||
void watchdog_notify_pretimeout(struct watchdog_device *wdd)
|
||||
|
||||
The function can be called in the interrupt context. If watchdog pretimeout
|
||||
governor framework (kbuild CONFIG_WATCHDOG_PRETIMEOUT_GOV symbol) is enabled,
|
||||
an action is taken by a preconfigured pretimeout governor preassigned to
|
||||
the watchdog device. If watchdog pretimeout governor framework is not
|
||||
enabled, watchdog_notify_pretimeout() prints a notification message to
|
||||
the kernel log buffer.
|
||||
|
||||
@@ -1844,4 +1844,53 @@ config USBPCWATCHDOG
|
||||
|
||||
Most people will say N.
|
||||
|
||||
comment "Watchdog Pretimeout Governors"
|
||||
|
||||
config WATCHDOG_PRETIMEOUT_GOV
|
||||
bool "Enable watchdog pretimeout governors"
|
||||
help
|
||||
The option allows to select watchdog pretimeout governors.
|
||||
|
||||
if WATCHDOG_PRETIMEOUT_GOV
|
||||
|
||||
choice
|
||||
prompt "Default Watchdog Pretimeout Governor"
|
||||
default WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC
|
||||
help
|
||||
This option selects a default watchdog pretimeout governor.
|
||||
The governor takes its action, if a watchdog is capable
|
||||
to report a pretimeout event.
|
||||
|
||||
config WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP
|
||||
bool "noop"
|
||||
select WATCHDOG_PRETIMEOUT_GOV_NOOP
|
||||
help
|
||||
Use noop watchdog pretimeout governor by default. If noop
|
||||
governor is selected by a user, write a short message to
|
||||
the kernel log buffer and don't do any system changes.
|
||||
|
||||
config WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC
|
||||
bool "panic"
|
||||
select WATCHDOG_PRETIMEOUT_GOV_PANIC
|
||||
help
|
||||
Use panic watchdog pretimeout governor by default, if
|
||||
a watchdog pretimeout event happens, consider that
|
||||
a watchdog feeder is dead and reboot is unavoidable.
|
||||
|
||||
endchoice
|
||||
|
||||
config WATCHDOG_PRETIMEOUT_GOV_NOOP
|
||||
tristate "Noop watchdog pretimeout governor"
|
||||
help
|
||||
Noop watchdog pretimeout governor, only an informational
|
||||
message is added to kernel log buffer.
|
||||
|
||||
config WATCHDOG_PRETIMEOUT_GOV_PANIC
|
||||
tristate "Panic watchdog pretimeout governor"
|
||||
help
|
||||
Panic watchdog pretimeout governor, on watchdog pretimeout
|
||||
event put the kernel into panic.
|
||||
|
||||
endif # WATCHDOG_PRETIMEOUT_GOV
|
||||
|
||||
endif # WATCHDOG
|
||||
|
||||
@@ -3,9 +3,15 @@
|
||||
#
|
||||
|
||||
# The WatchDog Timer Driver Core.
|
||||
watchdog-objs += watchdog_core.o watchdog_dev.o
|
||||
obj-$(CONFIG_WATCHDOG_CORE) += watchdog.o
|
||||
|
||||
watchdog-objs += watchdog_core.o watchdog_dev.o
|
||||
|
||||
watchdog-$(CONFIG_WATCHDOG_PRETIMEOUT_GOV) += watchdog_pretimeout.o
|
||||
|
||||
obj-$(CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP) += pretimeout_noop.o
|
||||
obj-$(CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC) += pretimeout_panic.o
|
||||
|
||||
# Only one watchdog can succeed. We probe the ISA/PCI/USB based
|
||||
# watchdog-cards first, then the architecture specific watchdog
|
||||
# drivers and then the architecture independent "softdog" driver.
|
||||
|
||||
@@ -389,7 +389,6 @@ MODULE_DEVICE_TABLE(of, asm9260_wdt_of_match);
|
||||
static struct platform_driver asm9260_wdt_driver = {
|
||||
.driver = {
|
||||
.name = "asm9260-wdt",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = asm9260_wdt_of_match,
|
||||
},
|
||||
.probe = asm9260_wdt_probe,
|
||||
|
||||
@@ -107,7 +107,7 @@ static struct watchdog_info bcm7038_wdt_info = {
|
||||
WDIOF_MAGICCLOSE
|
||||
};
|
||||
|
||||
static struct watchdog_ops bcm7038_wdt_ops = {
|
||||
static const struct watchdog_ops bcm7038_wdt_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.start = bcm7038_wdt_start,
|
||||
.stop = bcm7038_wdt_stop,
|
||||
|
||||
@@ -269,7 +269,7 @@ static struct watchdog_info cdns_wdt_info = {
|
||||
};
|
||||
|
||||
/* Watchdog Core Ops */
|
||||
static struct watchdog_ops cdns_wdt_ops = {
|
||||
static const struct watchdog_ops cdns_wdt_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.start = cdns_wdt_start,
|
||||
.stop = cdns_wdt_stop,
|
||||
@@ -424,8 +424,10 @@ static int __maybe_unused cdns_wdt_suspend(struct device *dev)
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct cdns_wdt *wdt = platform_get_drvdata(pdev);
|
||||
|
||||
cdns_wdt_stop(&wdt->cdns_wdt_device);
|
||||
clk_disable_unprepare(wdt->clk);
|
||||
if (watchdog_active(&wdt->cdns_wdt_device)) {
|
||||
cdns_wdt_stop(&wdt->cdns_wdt_device);
|
||||
clk_disable_unprepare(wdt->clk);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -442,12 +444,14 @@ static int __maybe_unused cdns_wdt_resume(struct device *dev)
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct cdns_wdt *wdt = platform_get_drvdata(pdev);
|
||||
|
||||
ret = clk_prepare_enable(wdt->clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "unable to enable clock\n");
|
||||
return ret;
|
||||
if (watchdog_active(&wdt->cdns_wdt_device)) {
|
||||
ret = clk_prepare_enable(wdt->clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "unable to enable clock\n");
|
||||
return ret;
|
||||
}
|
||||
cdns_wdt_start(&wdt->cdns_wdt_device);
|
||||
}
|
||||
cdns_wdt_start(&wdt->cdns_wdt_device);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
|
||||
struct dw_wdt {
|
||||
void __iomem *regs;
|
||||
struct clk *clk;
|
||||
unsigned long rate;
|
||||
struct notifier_block restart_handler;
|
||||
struct watchdog_device wdd;
|
||||
};
|
||||
@@ -72,7 +73,7 @@ static inline int dw_wdt_top_in_seconds(struct dw_wdt *dw_wdt, unsigned top)
|
||||
* There are 16 possible timeout values in 0..15 where the number of
|
||||
* cycles is 2 ^ (16 + i) and the watchdog counts down.
|
||||
*/
|
||||
return (1U << (16 + top)) / clk_get_rate(dw_wdt->clk);
|
||||
return (1U << (16 + top)) / dw_wdt->rate;
|
||||
}
|
||||
|
||||
static int dw_wdt_get_top(struct dw_wdt *dw_wdt)
|
||||
@@ -163,7 +164,7 @@ static unsigned int dw_wdt_get_timeleft(struct watchdog_device *wdd)
|
||||
struct dw_wdt *dw_wdt = to_dw_wdt(wdd);
|
||||
|
||||
return readl(dw_wdt->regs + WDOG_CURRENT_COUNT_REG_OFFSET) /
|
||||
clk_get_rate(dw_wdt->clk);
|
||||
dw_wdt->rate;
|
||||
}
|
||||
|
||||
static const struct watchdog_info dw_wdt_ident = {
|
||||
@@ -231,6 +232,12 @@ static int dw_wdt_drv_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dw_wdt->rate = clk_get_rate(dw_wdt->clk);
|
||||
if (dw_wdt->rate == 0) {
|
||||
ret = -EINVAL;
|
||||
goto out_disable_clk;
|
||||
}
|
||||
|
||||
wdd = &dw_wdt->wdd;
|
||||
wdd->info = &dw_wdt_ident;
|
||||
wdd->ops = &dw_wdt_ops;
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
#include <asm/nmi.h>
|
||||
#include <asm/frame.h>
|
||||
|
||||
#define HPWDT_VERSION "1.3.3"
|
||||
#define HPWDT_VERSION "1.4.0"
|
||||
#define SECS_TO_TICKS(secs) ((secs) * 1000 / 128)
|
||||
#define TICKS_TO_SECS(ticks) ((ticks) * 128 / 1000)
|
||||
#define HPWDT_MAX_TIMER TICKS_TO_SECS(65535)
|
||||
@@ -814,7 +814,8 @@ static int hpwdt_init_one(struct pci_dev *dev,
|
||||
* not run on a legacy ASM box.
|
||||
* So we only support the G5 ProLiant servers and higher.
|
||||
*/
|
||||
if (dev->subsystem_vendor != PCI_VENDOR_ID_HP) {
|
||||
if (dev->subsystem_vendor != PCI_VENDOR_ID_HP &&
|
||||
dev->subsystem_vendor != PCI_VENDOR_ID_HP_3PAR) {
|
||||
dev_warn(&dev->dev,
|
||||
"This server does not have an iLO2+ ASIC.\n");
|
||||
return -ENODEV;
|
||||
@@ -823,7 +824,8 @@ static int hpwdt_init_one(struct pci_dev *dev,
|
||||
/*
|
||||
* Ignore all auxilary iLO devices with the following PCI ID
|
||||
*/
|
||||
if (dev->subsystem_device == 0x1979)
|
||||
if (dev->subsystem_vendor == PCI_VENDOR_ID_HP &&
|
||||
dev->subsystem_device == 0x1979)
|
||||
return -ENODEV;
|
||||
|
||||
if (pci_enable_device(dev)) {
|
||||
|
||||
@@ -629,7 +629,7 @@ static int iTCO_wdt_resume_noirq(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dev_pm_ops iTCO_wdt_pm = {
|
||||
static const struct dev_pm_ops iTCO_wdt_pm = {
|
||||
.suspend_noirq = iTCO_wdt_suspend_noirq,
|
||||
.resume_noirq = iTCO_wdt_resume_noirq,
|
||||
};
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
@@ -37,18 +38,23 @@
|
||||
|
||||
#define IMX2_WDT_WCR 0x00 /* Control Register */
|
||||
#define IMX2_WDT_WCR_WT (0xFF << 8) /* -> Watchdog Timeout Field */
|
||||
#define IMX2_WDT_WCR_WDA (1 << 5) /* -> External Reset WDOG_B */
|
||||
#define IMX2_WDT_WCR_SRS (1 << 4) /* -> Software Reset Signal */
|
||||
#define IMX2_WDT_WCR_WRE (1 << 3) /* -> WDOG Reset Enable */
|
||||
#define IMX2_WDT_WCR_WDE (1 << 2) /* -> Watchdog Enable */
|
||||
#define IMX2_WDT_WCR_WDZST (1 << 0) /* -> Watchdog timer Suspend */
|
||||
#define IMX2_WDT_WCR_WDA BIT(5) /* -> External Reset WDOG_B */
|
||||
#define IMX2_WDT_WCR_SRS BIT(4) /* -> Software Reset Signal */
|
||||
#define IMX2_WDT_WCR_WRE BIT(3) /* -> WDOG Reset Enable */
|
||||
#define IMX2_WDT_WCR_WDE BIT(2) /* -> Watchdog Enable */
|
||||
#define IMX2_WDT_WCR_WDZST BIT(0) /* -> Watchdog timer Suspend */
|
||||
|
||||
#define IMX2_WDT_WSR 0x02 /* Service Register */
|
||||
#define IMX2_WDT_SEQ1 0x5555 /* -> service sequence 1 */
|
||||
#define IMX2_WDT_SEQ2 0xAAAA /* -> service sequence 2 */
|
||||
|
||||
#define IMX2_WDT_WRSR 0x04 /* Reset Status Register */
|
||||
#define IMX2_WDT_WRSR_TOUT (1 << 1) /* -> Reset due to Timeout */
|
||||
#define IMX2_WDT_WRSR_TOUT BIT(1) /* -> Reset due to Timeout */
|
||||
|
||||
#define IMX2_WDT_WICR 0x06 /* Interrupt Control Register */
|
||||
#define IMX2_WDT_WICR_WIE BIT(15) /* -> Interrupt Enable */
|
||||
#define IMX2_WDT_WICR_WTIS BIT(14) /* -> Interrupt Status */
|
||||
#define IMX2_WDT_WICR_WICT 0xFF /* -> Interrupt Count Timeout */
|
||||
|
||||
#define IMX2_WDT_WMCR 0x08 /* Misc Register */
|
||||
|
||||
@@ -80,6 +86,12 @@ static const struct watchdog_info imx2_wdt_info = {
|
||||
.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
|
||||
};
|
||||
|
||||
static const struct watchdog_info imx2_wdt_pretimeout_info = {
|
||||
.identity = "imx2+ watchdog",
|
||||
.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE |
|
||||
WDIOF_PRETIMEOUT,
|
||||
};
|
||||
|
||||
static int imx2_wdt_restart(struct watchdog_device *wdog, unsigned long action,
|
||||
void *data)
|
||||
{
|
||||
@@ -169,6 +181,35 @@ static int imx2_wdt_set_timeout(struct watchdog_device *wdog,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx2_wdt_set_pretimeout(struct watchdog_device *wdog,
|
||||
unsigned int new_pretimeout)
|
||||
{
|
||||
struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog);
|
||||
|
||||
if (new_pretimeout >= IMX2_WDT_MAX_TIME)
|
||||
return -EINVAL;
|
||||
|
||||
wdog->pretimeout = new_pretimeout;
|
||||
|
||||
regmap_update_bits(wdev->regmap, IMX2_WDT_WICR,
|
||||
IMX2_WDT_WICR_WIE | IMX2_WDT_WICR_WICT,
|
||||
IMX2_WDT_WICR_WIE | (new_pretimeout << 1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t imx2_wdt_isr(int irq, void *wdog_arg)
|
||||
{
|
||||
struct watchdog_device *wdog = wdog_arg;
|
||||
struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog);
|
||||
|
||||
regmap_write_bits(wdev->regmap, IMX2_WDT_WICR,
|
||||
IMX2_WDT_WICR_WTIS, IMX2_WDT_WICR_WTIS);
|
||||
|
||||
watchdog_notify_pretimeout(wdog);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int imx2_wdt_start(struct watchdog_device *wdog)
|
||||
{
|
||||
struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog);
|
||||
@@ -188,6 +229,7 @@ static const struct watchdog_ops imx2_wdt_ops = {
|
||||
.start = imx2_wdt_start,
|
||||
.ping = imx2_wdt_ping,
|
||||
.set_timeout = imx2_wdt_set_timeout,
|
||||
.set_pretimeout = imx2_wdt_set_pretimeout,
|
||||
.restart = imx2_wdt_restart,
|
||||
};
|
||||
|
||||
@@ -236,6 +278,12 @@ static int __init imx2_wdt_probe(struct platform_device *pdev)
|
||||
wdog->max_hw_heartbeat_ms = IMX2_WDT_MAX_TIME * 1000;
|
||||
wdog->parent = &pdev->dev;
|
||||
|
||||
ret = platform_get_irq(pdev, 0);
|
||||
if (ret > 0)
|
||||
if (!devm_request_irq(&pdev->dev, ret, imx2_wdt_isr, 0,
|
||||
dev_name(&pdev->dev), wdog))
|
||||
wdog->info = &imx2_wdt_pretimeout_info;
|
||||
|
||||
ret = clk_prepare_enable(wdev->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -430,7 +430,7 @@ static struct watchdog_info kempld_wdt_info = {
|
||||
WDIOF_PRETIMEOUT
|
||||
};
|
||||
|
||||
static struct watchdog_ops kempld_wdt_ops = {
|
||||
static const struct watchdog_ops kempld_wdt_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.start = kempld_wdt_start,
|
||||
.stop = kempld_wdt_stop,
|
||||
|
||||
@@ -139,7 +139,6 @@ static int mt7621_wdt_probe(struct platform_device *pdev)
|
||||
if (!IS_ERR(mt7621_wdt_reset))
|
||||
reset_control_deassert(mt7621_wdt_reset);
|
||||
|
||||
mt7621_wdt_dev.dev = &pdev->dev;
|
||||
mt7621_wdt_dev.bootstatus = mt7621_wdt_bootcause();
|
||||
|
||||
watchdog_init_timeout(&mt7621_wdt_dev, mt7621_wdt_dev.max_timeout,
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
@@ -45,6 +46,7 @@ struct xwdt_device {
|
||||
u32 wdt_interval;
|
||||
spinlock_t spinlock;
|
||||
struct watchdog_device xilinx_wdt_wdd;
|
||||
struct clk *clk;
|
||||
};
|
||||
|
||||
static int xilinx_wdt_start(struct watchdog_device *wdd)
|
||||
@@ -195,16 +197,30 @@ static int xwdt_probe(struct platform_device *pdev)
|
||||
spin_lock_init(&xdev->spinlock);
|
||||
watchdog_set_drvdata(xilinx_wdt_wdd, xdev);
|
||||
|
||||
xdev->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(xdev->clk)) {
|
||||
if (PTR_ERR(xdev->clk) == -ENOENT)
|
||||
xdev->clk = NULL;
|
||||
else
|
||||
return PTR_ERR(xdev->clk);
|
||||
}
|
||||
|
||||
rc = clk_prepare_enable(xdev->clk);
|
||||
if (rc) {
|
||||
dev_err(&pdev->dev, "unable to enable clock\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = xwdt_selftest(xdev);
|
||||
if (rc == XWT_TIMER_FAILED) {
|
||||
dev_err(&pdev->dev, "SelfTest routine error\n");
|
||||
return rc;
|
||||
goto err_clk_disable;
|
||||
}
|
||||
|
||||
rc = watchdog_register_device(xilinx_wdt_wdd);
|
||||
if (rc) {
|
||||
dev_err(&pdev->dev, "Cannot register watchdog (err=%d)\n", rc);
|
||||
return rc;
|
||||
goto err_clk_disable;
|
||||
}
|
||||
|
||||
dev_info(&pdev->dev, "Xilinx Watchdog Timer at %p with timeout %ds\n",
|
||||
@@ -213,6 +229,10 @@ static int xwdt_probe(struct platform_device *pdev)
|
||||
platform_set_drvdata(pdev, xdev);
|
||||
|
||||
return 0;
|
||||
err_clk_disable:
|
||||
clk_disable_unprepare(xdev->clk);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int xwdt_remove(struct platform_device *pdev)
|
||||
@@ -220,6 +240,7 @@ static int xwdt_remove(struct platform_device *pdev)
|
||||
struct xwdt_device *xdev = platform_get_drvdata(pdev);
|
||||
|
||||
watchdog_unregister_device(&xdev->xilinx_wdt_wdd);
|
||||
clk_disable_unprepare(xdev->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2016 Mentor Graphics
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/watchdog.h>
|
||||
|
||||
#include "watchdog_pretimeout.h"
|
||||
|
||||
/**
|
||||
* pretimeout_noop - No operation on watchdog pretimeout event
|
||||
* @wdd - watchdog_device
|
||||
*
|
||||
* This function prints a message about pretimeout to kernel log.
|
||||
*/
|
||||
static void pretimeout_noop(struct watchdog_device *wdd)
|
||||
{
|
||||
pr_alert("watchdog%d: pretimeout event\n", wdd->id);
|
||||
}
|
||||
|
||||
static struct watchdog_governor watchdog_gov_noop = {
|
||||
.name = "noop",
|
||||
.pretimeout = pretimeout_noop,
|
||||
};
|
||||
|
||||
static int __init watchdog_gov_noop_register(void)
|
||||
{
|
||||
return watchdog_register_governor(&watchdog_gov_noop);
|
||||
}
|
||||
|
||||
static void __exit watchdog_gov_noop_unregister(void)
|
||||
{
|
||||
watchdog_unregister_governor(&watchdog_gov_noop);
|
||||
}
|
||||
module_init(watchdog_gov_noop_register);
|
||||
module_exit(watchdog_gov_noop_unregister);
|
||||
|
||||
MODULE_AUTHOR("Vladimir Zapolskiy <vladimir_zapolskiy@mentor.com>");
|
||||
MODULE_DESCRIPTION("Panic watchdog pretimeout governor");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2016 Mentor Graphics
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/watchdog.h>
|
||||
|
||||
#include "watchdog_pretimeout.h"
|
||||
|
||||
/**
|
||||
* pretimeout_panic - Panic on watchdog pretimeout event
|
||||
* @wdd - watchdog_device
|
||||
*
|
||||
* Panic, watchdog has not been fed till pretimeout event.
|
||||
*/
|
||||
static void pretimeout_panic(struct watchdog_device *wdd)
|
||||
{
|
||||
panic("watchdog pretimeout event\n");
|
||||
}
|
||||
|
||||
static struct watchdog_governor watchdog_gov_panic = {
|
||||
.name = "panic",
|
||||
.pretimeout = pretimeout_panic,
|
||||
};
|
||||
|
||||
static int __init watchdog_gov_panic_register(void)
|
||||
{
|
||||
return watchdog_register_governor(&watchdog_gov_panic);
|
||||
}
|
||||
|
||||
static void __exit watchdog_gov_panic_unregister(void)
|
||||
{
|
||||
watchdog_unregister_governor(&watchdog_gov_panic);
|
||||
}
|
||||
module_init(watchdog_gov_panic_register);
|
||||
module_exit(watchdog_gov_panic_unregister);
|
||||
|
||||
MODULE_AUTHOR("Vladimir Zapolskiy <vladimir_zapolskiy@mentor.com>");
|
||||
MODULE_DESCRIPTION("Panic watchdog pretimeout governor");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -136,7 +136,7 @@ static struct watchdog_info rn5t618_wdt_info = {
|
||||
.identity = DRIVER_NAME,
|
||||
};
|
||||
|
||||
static struct watchdog_ops rn5t618_wdt_ops = {
|
||||
static const struct watchdog_ops rn5t618_wdt_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.start = rn5t618_wdt_start,
|
||||
.stop = rn5t618_wdt_stop,
|
||||
|
||||
@@ -158,7 +158,6 @@ static int rt288x_wdt_probe(struct platform_device *pdev)
|
||||
|
||||
rt288x_wdt_freq = clk_get_rate(rt288x_wdt_clk) / RALINK_WDT_PRESCALE;
|
||||
|
||||
rt288x_wdt_dev.dev = &pdev->dev;
|
||||
rt288x_wdt_dev.bootstatus = rt288x_wdt_bootcause();
|
||||
rt288x_wdt_dev.max_timeout = (0xfffful / rt288x_wdt_freq);
|
||||
rt288x_wdt_dev.parent = &pdev->dev;
|
||||
|
||||
@@ -72,10 +72,27 @@ static void softdog_fire(unsigned long data)
|
||||
static struct timer_list softdog_ticktock =
|
||||
TIMER_INITIALIZER(softdog_fire, 0, 0);
|
||||
|
||||
static struct watchdog_device softdog_dev;
|
||||
|
||||
static void softdog_pretimeout(unsigned long data)
|
||||
{
|
||||
watchdog_notify_pretimeout(&softdog_dev);
|
||||
}
|
||||
|
||||
static struct timer_list softdog_preticktock =
|
||||
TIMER_INITIALIZER(softdog_pretimeout, 0, 0);
|
||||
|
||||
static int softdog_ping(struct watchdog_device *w)
|
||||
{
|
||||
if (!mod_timer(&softdog_ticktock, jiffies + (w->timeout * HZ)))
|
||||
__module_get(THIS_MODULE);
|
||||
|
||||
if (w->pretimeout)
|
||||
mod_timer(&softdog_preticktock, jiffies +
|
||||
(w->timeout - w->pretimeout) * HZ);
|
||||
else
|
||||
del_timer(&softdog_preticktock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -84,15 +101,18 @@ static int softdog_stop(struct watchdog_device *w)
|
||||
if (del_timer(&softdog_ticktock))
|
||||
module_put(THIS_MODULE);
|
||||
|
||||
del_timer(&softdog_preticktock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct watchdog_info softdog_info = {
|
||||
.identity = "Software Watchdog",
|
||||
.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
|
||||
.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE |
|
||||
WDIOF_PRETIMEOUT,
|
||||
};
|
||||
|
||||
static struct watchdog_ops softdog_ops = {
|
||||
static const struct watchdog_ops softdog_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.start = softdog_ping,
|
||||
.stop = softdog_stop,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user