From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932827AbeBLFXY (ORCPT ); Mon, 12 Feb 2018 00:23:24 -0500 Received: from g2t1383g.austin.hpe.com ([15.233.16.89]:56869 "EHLO g2t1383g.austin.hpe.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751259AbeBLFW1 (ORCPT ); Mon, 12 Feb 2018 00:22:27 -0500 From: Jerry Hoemann To: wim@linux-watchdog.org, linux@roeck-us.net Cc: linux-watchdog@vger.kernel.org, linux-kernel@vger.kernel.org, rwright@hpe.com, maurice.a.saldivar@hpe.com, Jerry Hoemann Subject: [PATCH v2 06/11] watchdog/hpwdt: Modify to use watchdog core. Date: Sun, 11 Feb 2018 22:21:06 -0700 Message-Id: <20180212052111.12010-7-jerry.hoemann@hpe.com> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180212052111.12010-1-jerry.hoemann@hpe.com> References: <20180212052111.12010-1-jerry.hoemann@hpe.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Follow Documentation/watchdog/convert_drivers_to_kernel_api.txt to convert hpwdt from legacy watchdog driver to use the watchdog core. Removed functions: hpwdt_open, hpwdt_release, hpwdt_write, hpwdt_ioctl Removed data structures: hpwdt_fops, hpwdt_miscdev, watchdog_device Modified functions: hpwdt_start, hpwdt_stop, hpwdt_ping, hpwdt_gettimeleft Added functions: hpwdt_settimeout Added structures: watchdog_device Signed-off-by: Jerry Hoemann --- drivers/watchdog/hpwdt.c | 251 ++++++++++++----------------------------------- 1 file changed, 63 insertions(+), 188 deletions(-) diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index dead59f9ca80..740d0c633204 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c @@ -14,18 +14,13 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -#include -#include -#include #include -#include #include #include #include -#include #include -#include #include + #include #define HPWDT_VERSION "1.4.0" @@ -40,8 +35,6 @@ static bool nowayout = WATCHDOG_NOWAYOUT; #ifdef CONFIG_HPWDT_NMI_DECODING static unsigned int allow_kdump = 1; #endif -static char expect_release; -static unsigned long hpwdt_is_open; static void __iomem *pci_mem_addr; /* the PCI-memory address */ static unsigned long __iomem *hpwdt_nmistat; @@ -55,53 +48,58 @@ static const struct pci_device_id hpwdt_devices[] = { }; MODULE_DEVICE_TABLE(pci, hpwdt_devices); +static struct watchdog_device hpwdt_dev; /* * Watchdog operations */ -static void hpwdt_start(void) +static int hpwdt_start(struct watchdog_device *dev) { - reload = SECS_TO_TICKS(soft_margin); + reload = SECS_TO_TICKS(dev->timeout); + iowrite16(reload, hpwdt_timer_reg); iowrite8(0x85, hpwdt_timer_con); + + return 0; } -static void hpwdt_stop(void) +static int hpwdt_stop(struct watchdog_device *dev) { unsigned long data; data = ioread8(hpwdt_timer_con); data &= 0xFE; iowrite8(data, hpwdt_timer_con); + return 0; } -static void hpwdt_ping(void) -{ - iowrite16(reload, hpwdt_timer_reg); -} - -static int hpwdt_change_timer(int new_margin) +static int hpwdt_ping(struct watchdog_device *dev) { - if (new_margin < 1 || new_margin > HPWDT_MAX_TIMER) { - pr_warn("New value passed in is invalid: %d seconds\n", - new_margin); - return -EINVAL; - } + reload = SECS_TO_TICKS(dev->timeout); - soft_margin = new_margin; - pr_debug("New timer passed in is %d seconds\n", new_margin); - reload = SECS_TO_TICKS(soft_margin); + iowrite16(reload, hpwdt_timer_reg); return 0; } -static int hpwdt_time_left(void) +static unsigned int hpwdt_gettimeleft(struct watchdog_device *dev) { return TICKS_TO_SECS(ioread16(hpwdt_timer_reg)); } +static int hpwdt_settimeout(struct watchdog_device *dev, unsigned int val) +{ + pr_debug("settimeout = %d\n", val); + + soft_margin = dev->timeout = val; + hpwdt_ping(dev); + + return 0; +} + #ifdef CONFIG_HPWDT_NMI_DECODING /* { */ -static int hpwdt_my_nmi(void) + +static unsigned int hpwdt_my_nmi(void) { return ioread8(hpwdt_nmistat) & 0x6; } @@ -128,8 +126,10 @@ static int hpwdt_pretimeout(unsigned int ulReason, struct pt_regs *regs) if ((ulReason == NMI_UNKNOWN) && !mynmi) return NMI_DONE; + pr_debug("nmi: ulReason=%d, mynmi=0x%0x\n", ulReason, mynmi); + if (allow_kdump) - hpwdt_stop(); + hpwdt_stop(&hpwdt_dev); panic_msg[0] = hexdigit((mynmi>>4)&0xf); panic_msg[1] = hexdigit(mynmi&0xf); @@ -140,68 +140,6 @@ static int hpwdt_pretimeout(unsigned int ulReason, struct pt_regs *regs) } #endif /* } */ -/* - * /dev/watchdog handling - */ -static int hpwdt_open(struct inode *inode, struct file *file) -{ - /* /dev/watchdog can only be opened once */ - if (test_and_set_bit(0, &hpwdt_is_open)) - return -EBUSY; - - /* Start the watchdog */ - hpwdt_start(); - hpwdt_ping(); - - return nonseekable_open(inode, file); -} - -static int hpwdt_release(struct inode *inode, struct file *file) -{ - /* Stop the watchdog */ - if (expect_release == 42) { - hpwdt_stop(); - } else { - pr_crit("Unexpected close, not stopping watchdog!\n"); - hpwdt_ping(); - } - - expect_release = 0; - - /* /dev/watchdog is being closed, make sure it can be re-opened */ - clear_bit(0, &hpwdt_is_open); - - return 0; -} - -static ssize_t hpwdt_write(struct file *file, const char __user *data, - size_t len, loff_t *ppos) -{ - /* See if we got the magic character 'V' and reload the timer */ - if (len) { - if (!nowayout) { - size_t i; - - /* note: just in case someone wrote the magic character - * five months ago... */ - expect_release = 0; - - /* scan to see whether or not we got the magic char. */ - for (i = 0; i != len; i++) { - char c; - if (get_user(c, data + i)) - return -EFAULT; - if (c == 'V') - expect_release = 42; - } - } - - /* someone wrote to us, we should reload the timer */ - hpwdt_ping(); - } - - return len; -} static const struct watchdog_info hpwdt_info = { .options = WDIOF_SETTIMEOUT | @@ -210,90 +148,10 @@ static const struct watchdog_info hpwdt_info = { .identity = "HPE iLO2+ HW Watchdog Timer", }; -static long hpwdt_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - void __user *argp = (void __user *)arg; - int __user *p = argp; - int new_margin, options; - int ret = -ENOTTY; - - switch (cmd) { - case WDIOC_GETSUPPORT: - ret = 0; - if (copy_to_user(argp, &hpwdt_info, sizeof(hpwdt_info))) - ret = -EFAULT; - break; - - case WDIOC_GETSTATUS: - case WDIOC_GETBOOTSTATUS: - ret = put_user(0, p); - break; - - case WDIOC_KEEPALIVE: - hpwdt_ping(); - ret = 0; - break; - - case WDIOC_SETOPTIONS: - ret = get_user(options, p); - if (ret) - break; - - if (options & WDIOS_DISABLECARD) - hpwdt_stop(); - - if (options & WDIOS_ENABLECARD) { - hpwdt_start(); - hpwdt_ping(); - } - break; - - case WDIOC_SETTIMEOUT: - ret = get_user(new_margin, p); - if (ret) - break; - - ret = hpwdt_change_timer(new_margin); - if (ret) - break; - - hpwdt_ping(); - /* Fall */ - case WDIOC_GETTIMEOUT: - ret = put_user(soft_margin, p); - break; - - case WDIOC_GETTIMELEFT: - ret = put_user(hpwdt_time_left(), p); - break; - } - return ret; -} - -/* - * Kernel interfaces - */ -static const struct file_operations hpwdt_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .write = hpwdt_write, - .unlocked_ioctl = hpwdt_ioctl, - .open = hpwdt_open, - .release = hpwdt_release, -}; - -static struct miscdevice hpwdt_miscdev = { - .minor = WATCHDOG_MINOR, - .name = "watchdog", - .fops = &hpwdt_fops, -}; - /* * Init & Exit */ - static int hpwdt_init_nmi_decoding(struct pci_dev *dev) { #ifdef CONFIG_HPWDT_NMI_DECODING /* { */ @@ -311,10 +169,7 @@ static int hpwdt_init_nmi_decoding(struct pci_dev *dev) if (retval) goto error2; - dev_info(&dev->dev, - "HPE Watchdog Timer Driver: NMI decoding initialized" - ", allow kernel dump: %s (default = 1/ON)\n", - (allow_kdump == 0) ? "OFF" : "ON"); + dev_info(&dev->dev, "HPE Watchdog Timer Driver: NMI decoding initialized"); return 0; error2: @@ -381,31 +236,32 @@ static int hpwdt_probe(struct pci_dev *dev, const struct pci_device_id *ent) hpwdt_timer_con = pci_mem_addr + 0x72; /* Make sure that timer is disabled until /dev/watchdog is opened */ - hpwdt_stop(); - - /* Make sure that we have a valid soft_margin */ - if (hpwdt_change_timer(soft_margin)) - hpwdt_change_timer(DEFAULT_MARGIN); + hpwdt_stop(&hpwdt_dev); /* Initialize NMI Decoding functionality */ retval = hpwdt_init_nmi_decoding(dev); if (retval != 0) goto error_init_nmi_decoding; - retval = misc_register(&hpwdt_miscdev); + retval = watchdog_register_device(&hpwdt_dev); if (retval < 0) { - dev_warn(&dev->dev, - "Unable to register miscdev on minor=%d (err=%d).\n", - WATCHDOG_MINOR, retval); - goto error_misc_register; + dev_warn(&dev->dev, "Unable to register hpe watchdog (err=%d).\n", retval); + goto error_wd_register; + } + + watchdog_set_nowayout(&hpwdt_dev, nowayout); + if (watchdog_init_timeout(&hpwdt_dev, soft_margin, NULL)) { + dev_warn(&dev->dev, "Invalid soft_margin: %d. Using default\n", soft_margin); + soft_margin = DEFAULT_MARGIN; } dev_info(&dev->dev, "HPE Watchdog Timer Driver: %s" ", timer margin: %d seconds (nowayout=%d).\n", - HPWDT_VERSION, soft_margin, nowayout); + HPWDT_VERSION, hpwdt_dev.timeout, nowayout); + return 0; -error_misc_register: +error_wd_register: hpwdt_exit_nmi_decoding(); error_init_nmi_decoding: pci_iounmap(dev, pci_mem_addr); @@ -417,9 +273,9 @@ static int hpwdt_probe(struct pci_dev *dev, const struct pci_device_id *ent) static void hpwdt_exit(struct pci_dev *dev) { if (!nowayout) - hpwdt_stop(); + hpwdt_stop(&hpwdt_dev); - misc_deregister(&hpwdt_miscdev); + watchdog_unregister_device(&hpwdt_dev); hpwdt_exit_nmi_decoding(); pci_iounmap(dev, pci_mem_addr); pci_disable_device(dev); @@ -432,6 +288,25 @@ static struct pci_driver hpwdt_driver = { .remove = hpwdt_exit, }; + +static const struct watchdog_ops hpwdt_ops = { + .owner = THIS_MODULE, + .start = hpwdt_start, + .stop = hpwdt_stop, + .ping = hpwdt_ping, + .set_timeout = hpwdt_settimeout, + .get_timeleft = hpwdt_gettimeleft, +}; + +static struct watchdog_device hpwdt_dev = { + .info = &hpwdt_info, + .ops = &hpwdt_ops, + .min_timeout = 1, + .max_timeout = HPWDT_MAX_TIMER, + .timeout = DEFAULT_MARGIN, +}; + + MODULE_AUTHOR("Jerry Hoemann"); MODULE_DESCRIPTION("hpe watchdog driver"); MODULE_LICENSE("GPL"); -- 2.13.6