From patchwork Wed Feb 13 15:19:55 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: Enhanced support for MPC8xx/8xxx watchdog Date: Wed, 13 Feb 2013 05:19:55 -0000 From: LEROY Christophe X-Patchwork-Id: 220195 Message-Id: <201302131519.r1DFJtGm032487@localhost.localdomain> To: Wim Van Sebroeck Cc: linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org, linux-watchdog@vger.kernel.org This patch modifies the behaviour of the MPC8xx/8xxx watchdog. On the MPC8xx, at 133Mhz, the maximum timeout of the watchdog timer is 1s, which means it must be pinged twice a second. This is not in line with the Linux watchdog concept which is based on a default watchdog timeout around 60s. This patch introduces an intermediate layer between the CPU and the userspace. The kernel pings the watchdog at the required frequency at the condition that userspace tools refresh it regularly. The new parameter 'heartbeat' allows to set up the userspace timeout. The driver also implements the WDIOC_SETTIMEOUT ioctl. Signed-off-by: Christophe Leroy diff -ur linux-3.7.7/drivers/watchdog/mpc8xxx_wdt.c linux/drivers/watchdog/mpc8xxx_wdt.c --- linux-3.7.7/drivers/watchdog/mpc8xxx_wdt.c 2013-02-11 18:05:09.000000000 +0100 +++ linux/drivers/watchdog/mpc8xxx_wdt.c 2013-02-13 15:55:22.000000000 +0100 @@ -52,10 +52,17 @@ static struct mpc8xxx_wdt __iomem *wd_base; static int mpc8xxx_wdt_init_late(void); +#define WD_TIMO 10 /* Default heartbeat = 10 seconds */ + +static int heartbeat = WD_TIMO; +module_param(heartbeat, int, 0); +MODULE_PARM_DESC(heartbeat, + "Watchdog SW heartbeat in seconds. (0 < heartbeat < 65536s, default=" + __MODULE_STRING(WD_TIMO) "s)"); static u16 timeout = 0xffff; module_param(timeout, ushort, 0); MODULE_PARM_DESC(timeout, - "Watchdog timeout in ticks. (0swcrr, tmp); - del_timer_sync(&wdt_timer); + wdt_auto = 0; return nonseekable_open(inode, file); } @@ -138,7 +158,8 @@ static int mpc8xxx_wdt_release(struct inode *inode, struct file *file) { if (!nowayout) - mpc8xxx_wdt_timer_ping(0); + wdt_auto = 1; + else mpc8xxx_wdt_pr_warn("watchdog closed"); clear_bit(0, &wdt_is_open); @@ -163,10 +184,12 @@ case WDIOC_GETBOOTSTATUS: return put_user(0, p); case WDIOC_KEEPALIVE: - mpc8xxx_wdt_keepalive(); + mpc8xxx_wdt_sw_keepalive(); return 0; case WDIOC_GETTIMEOUT: - return put_user(timeout_sec, p); + return put_user(heartbeat, p); + case WDIOC_SETTIMEOUT: + return get_user(heartbeat, p); default: return -ENOTTY; } @@ -215,6 +238,8 @@ ret = -ENOSYS; goto err_unmap; } + if (enabled) + timeout = in_be32(&wd_base->swcrr) >> 16; /* Calculate the timeout in seconds */ if (prescale) @@ -273,6 +298,7 @@ .compatible = "fsl,mpc823-wdt", .data = &(struct mpc8xxx_wdt_type) { .prescaler = 0x800, + .hw_enabled = true, }, }, {},