From patchwork Sat Jun 20 17:48:58 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Corey Minyard X-Patchwork-Id: 215009 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 13449C433E1 for ; Sat, 20 Jun 2020 17:50:17 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E17E820748 for ; Sat, 20 Jun 2020 17:50:16 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="BJ9R24HY" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728367AbgFTRuQ (ORCPT ); Sat, 20 Jun 2020 13:50:16 -0400 Received: from mail-ot1-f68.google.com ([209.85.210.68]:44499 "EHLO mail-ot1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728369AbgFTRuP (ORCPT ); Sat, 20 Jun 2020 13:50:15 -0400 Received: by mail-ot1-f68.google.com with SMTP id e5so9799418ote.11 for ; Sat, 20 Jun 2020 10:50:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=EZ87HAZTDdt3n3C9oeFellNh4inXOqJx8U+6lc7QfOQ=; b=BJ9R24HYViAnp9paCk61vLoCVDVB8wq0MhANRXPpjyagKgMeyOyq+kOqbgnhnGPLfF IFGHEOUfCDi5T01Jd/7XBrryrvLDR/DpoGZDGQFracj325e0pR430X1rGk+ZhBrldL4Z b/dc3JxPntgtg3/XScTCOCsvEE6vtyH7O6f3QbB/Lf2MNNcFopteSvXmOI9+JTh1LbAi 8CVw0ufqVx97lrrR13PMcEW1Z4Tbw1W0C+KfnDn0IU1kNCKAi3lw0PBDEiyxyLeIfdlv gzh+yQscCs9H0JNeqDTOogCvewIuOTtE32J4GLpOQxKgl5xsgHuG6ROZ2NJR5MK2fu0h gNTw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=EZ87HAZTDdt3n3C9oeFellNh4inXOqJx8U+6lc7QfOQ=; b=IIj2ZrH3lHvEwXtvxHuXT6mcC/jJOnHHxC8WCv05TokEjj+ZiP5BnCfP4fdmVoWn3N ztmJZnFUMT+B3vNTY6eU6HYRRBQnjTv59kTfzj33fUYSMpjkFIVkyfBZs3/LweyFRux1 BdHDWdbPTIFeYT1F1lPav3JVehJIQvfDYEOC5/y5dweE/mXeKpWoVBtjHa5FprpJWxVt HMEqphReWPSSRxvKBdspy3ICEkysW0mMiwDVv1AwzlDUMJBLXFVc9WBddAFuBpXbMX8f Oow8mHIu0yCa/0dG94Y9ruWakxKngnO3RLpK4dzITl0mgHVk4QbqBxM88HuriXoLfr2U FAUw== X-Gm-Message-State: AOAM5325bJHIZGgwGoshXemQfeC0wIQs/4L/ur4pMvCmaBhpNG3oiLea xIPK3OhRPfHlY2tlbNmsTQ== X-Google-Smtp-Source: ABdhPJw0CbCwMoZvhYI7R6/GLLKwFKpofJQjrF6y4vveqT5NWORBZU3VlHElFB2pRSsN9CvcQOQYUA== X-Received: by 2002:a9d:f07:: with SMTP id 7mr7610999ott.46.1592675353682; Sat, 20 Jun 2020 10:49:13 -0700 (PDT) Received: from serve.minyard.net (serve.minyard.net. [2001:470:b8f6:1b::1]) by smtp.gmail.com with ESMTPSA id u80sm2003711oia.5.2020.06.20.10.49.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 20 Jun 2020 10:49:12 -0700 (PDT) Received: from t560.minyard.net (unknown [IPv6:2001:470:b8f6:1b:98f8:1e34:b5b7:82f7]) by serve.minyard.net (Postfix) with ESMTPA id 7329B180171; Sat, 20 Jun 2020 17:49:11 +0000 (UTC) From: minyard@acm.org To: Guenter Roeck , Wim Van Sebroeck Cc: linux-watchdog@vger.kernel.org, Corey Minyard Subject: [PATCH 01/10] watchdog: Ignore stop_on_reboot if no stop function Date: Sat, 20 Jun 2020 12:48:58 -0500 Message-Id: <20200620174907.20229-2-minyard@acm.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200620174907.20229-1-minyard@acm.org> References: <20200620174907.20229-1-minyard@acm.org> Sender: linux-watchdog-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-watchdog@vger.kernel.org From: Corey Minyard The reboot notifier unconditionally calls the stop function on the watchdog, which would result in a crash if the watchdog didn't have a stop function. So check at register time to see if there is a stop function, and don't do stop_on_reboot if it is NULL. Signed-off-by: Corey Minyard --- drivers/watchdog/watchdog_core.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c index 423844757812..03943a34e9fb 100644 --- a/drivers/watchdog/watchdog_core.c +++ b/drivers/watchdog/watchdog_core.c @@ -260,10 +260,16 @@ static int __watchdog_register_device(struct watchdog_device *wdd) /* Module parameter to force watchdog policy on reboot. */ if (stop_on_reboot != -1) { - if (stop_on_reboot) - set_bit(WDOG_STOP_ON_REBOOT, &wdd->status); - else + if (stop_on_reboot) { + if (!wdd->ops->stop) { + pr_err("watchdog%d: stop_on_reboot set, but no stop function. Ignoring stop_on_reboot.\n", wdd->id); + clear_bit(WDOG_STOP_ON_REBOOT, &wdd->status); + } else { + set_bit(WDOG_STOP_ON_REBOOT, &wdd->status); + } + } else { clear_bit(WDOG_STOP_ON_REBOOT, &wdd->status); + } } if (test_bit(WDOG_STOP_ON_REBOOT, &wdd->status)) { From patchwork Sat Jun 20 17:48:59 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Corey Minyard X-Patchwork-Id: 215011 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D275DC433E0 for ; Sat, 20 Jun 2020 17:50:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A18E82067B for ; Sat, 20 Jun 2020 17:50:14 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="UekCF6s7" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728306AbgFTRuO (ORCPT ); Sat, 20 Jun 2020 13:50:14 -0400 Received: from mail-oo1-f66.google.com ([209.85.161.66]:45114 "EHLO mail-oo1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726838AbgFTRuN (ORCPT ); Sat, 20 Jun 2020 13:50:13 -0400 Received: by mail-oo1-f66.google.com with SMTP id k7so2536859ooo.12 for ; Sat, 20 Jun 2020 10:50:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=9UxhjSoE82TmEXppeCDn14Vvto0FXpWKoJEeMHzGlYo=; b=UekCF6s7D3qzXwRvg84H2d03EQWIOEb6dc3Lu1zHaxHJeqxWiExJrBIVtSoDmf5QQl GDwscbKXnH8Wcoqjx1RT11BsIk643BJTD4vsxgKV47iMh+yw4k0bzNrhJnals2gUE5vZ 6Bgh6iS9o7viXmuSaEhZykiDtNUs/LHKZCjH1WaR7U7AWALq/rmSv2pXW3QvcwYojt+B Cb8VnFZcsUAglzAXXBMkCj/87ZbyTRLw7wgi60ZZlmiaI+Dquqw9J1A0FllwF5OeIcVR ddyC5NrDSFLRVL79vpdYdL9UTKklPaIkCXTnKpWk4r9yFs+UOvJLoU2/bPZX7iEkOyGE vJVQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=9UxhjSoE82TmEXppeCDn14Vvto0FXpWKoJEeMHzGlYo=; b=JsnOfHaeRTC6iYqOeAHH68S05Wrx2gRrAzCRwAYYazBRAU6BN3gcKPwiwqN/8c0yPT VwldKyjC7WdFY3P3rbxXgbF7Hf6HToagnl9V0Zwbyy5PwFuIFs0Gz4DdjbMHdIsP1agY k4exCuA5KbrmFfbuOQmtWDAxGJ8rTuRw0tzUGDZjN2D70SPEcvN4fSZsir9XX+lfno/S bgin5DREEjoso0fmTal9absa2zvbP3wiKmYrwQ9JMoHfaOqFYoOebN0McnNSHenCBJEd 1mCi3DSKxS1j8LbnpvHWTnVP1UgTVPqSdnANx4xWscgSRwvZkgZis+a4oVaWvmi+1M4V ksBw== X-Gm-Message-State: AOAM532fZMK/hNTfHt5z+Tinx3xb3cNOyLuQW8OOoJ+LXqvZaNOen4Go 1AQzotdkCdtJ+BDE+vH6VJblE8M= X-Google-Smtp-Source: ABdhPJzhyC/dF1sfvjhicBX2eMfArY8Ag0C+jhIh52nMNtfIUPR0JkPhRKWCAD87Z269iK+sY7m+4w== X-Received: by 2002:a4a:e496:: with SMTP id s22mr8167459oov.67.1592675352862; Sat, 20 Jun 2020 10:49:12 -0700 (PDT) Received: from serve.minyard.net ([47.184.146.204]) by smtp.gmail.com with ESMTPSA id w19sm298243otj.10.2020.06.20.10.49.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 20 Jun 2020 10:49:12 -0700 (PDT) Received: from t560.minyard.net (unknown [IPv6:2001:470:b8f6:1b:98f8:1e34:b5b7:82f7]) by serve.minyard.net (Postfix) with ESMTPA id 89471180545; Sat, 20 Jun 2020 17:49:11 +0000 (UTC) From: minyard@acm.org To: Guenter Roeck , Wim Van Sebroeck Cc: linux-watchdog@vger.kernel.org, Corey Minyard Subject: [PATCH 02/10] watchdog: Add read capability Date: Sat, 20 Jun 2020 12:48:59 -0500 Message-Id: <20200620174907.20229-3-minyard@acm.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200620174907.20229-1-minyard@acm.org> References: <20200620174907.20229-1-minyard@acm.org> Sender: linux-watchdog-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-watchdog@vger.kernel.org From: Corey Minyard Allow read, poll, and fasync calls on the watchdog device to be passed to the driver. This is so the IPMI driver can be moved over to the watchdog framework, as it has the ability to have a read return when data comes in on the watchdog. Signed-off-by: Corey Minyard --- drivers/watchdog/watchdog_dev.c | 45 +++++++++++++++++++++++++++++++++ include/linux/watchdog.h | 8 ++++++ 2 files changed, 53 insertions(+) diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c index 7e4cd34a8c20..45a0a4fe731d 100644 --- a/drivers/watchdog/watchdog_dev.c +++ b/drivers/watchdog/watchdog_dev.c @@ -698,6 +698,48 @@ static ssize_t watchdog_write(struct file *file, const char __user *data, return len; } +/* + * watchdog_read: Pass a read on to the device if it accepts it + * @file: file handle to the device + * @buf: the buffer to read into + * @count: the size of buf in bytes + * @ppos: pointer to the file offset + * + * The watchdog API defines a common set of functions for all watchdogs + * according to their available features. + */ + +static ssize_t watchdog_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct watchdog_core_data *wd_data = file->private_data; + struct watchdog_device *wdd = wd_data->wdd; + + if (!wdd->ops->read) + return -EINVAL; + return wdd->ops->read(wdd, file, buf, count, ppos); +} + +static __poll_t watchdog_poll(struct file *file, poll_table *wait) +{ + struct watchdog_core_data *wd_data = file->private_data; + struct watchdog_device *wdd = wd_data->wdd; + + if (!wdd->ops->poll) + return DEFAULT_POLLMASK; + return wdd->ops->poll(wdd, file, wait); +} + +static int watchdog_fasync(int fd, struct file *file, int on) +{ + struct watchdog_core_data *wd_data = file->private_data; + struct watchdog_device *wdd = wd_data->wdd; + + if (!wdd->ops->fasync) + return 0; + return wdd->ops->fasync(wdd, fd, file, on); +} + /* * watchdog_ioctl: handle the different ioctl's for the watchdog device. * @file: file handle to the device @@ -951,6 +993,9 @@ static int watchdog_release(struct inode *inode, struct file *file) static const struct file_operations watchdog_fops = { .owner = THIS_MODULE, .write = watchdog_write, + .read = watchdog_read, + .poll = watchdog_poll, + .fasync = watchdog_fasync, .unlocked_ioctl = watchdog_ioctl, .compat_ioctl = compat_ptr_ioctl, .open = watchdog_open, diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h index 1464ce6ffa31..36f99c8c973e 100644 --- a/include/linux/watchdog.h +++ b/include/linux/watchdog.h @@ -15,6 +15,7 @@ #include #include #include +#include #include struct watchdog_ops; @@ -34,6 +35,9 @@ struct watchdog_governor; * @get_timeleft:The routine that gets the time left before a reset (in seconds). * @restart: The routine for restarting the machine. * @ioctl: The routines that handles extra ioctl calls. + * @read: Call this is not NULL and a read comes in on the watchdog dev. + * @poll: Call this is not NULL and a poll comes in on the watchdog dev. + * @fasync: Call this is not NULL and a fasync comes in on the watchdog dev. * * The watchdog_ops structure contains a list of low-level operations * that control a watchdog device. It also contains the module that owns @@ -53,6 +57,10 @@ struct watchdog_ops { unsigned int (*get_timeleft)(struct watchdog_device *); int (*restart)(struct watchdog_device *, unsigned long, void *); long (*ioctl)(struct watchdog_device *, unsigned int, unsigned long); + ssize_t (*read)(struct watchdog_device *, struct file *, char __user *, + size_t, loff_t *); + __poll_t (*poll)(struct watchdog_device *, struct file *, poll_table *); + int (*fasync)(struct watchdog_device *, int, struct file *, int); }; /** struct watchdog_device - The structure that defines a watchdog device From patchwork Sat Jun 20 17:49:01 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Corey Minyard X-Patchwork-Id: 215008 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8B9E6C433E0 for ; Sat, 20 Jun 2020 17:50:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6AF7920748 for ; Sat, 20 Jun 2020 17:50:18 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Lz1G/TGO" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728374AbgFTRuS (ORCPT ); Sat, 20 Jun 2020 13:50:18 -0400 Received: from mail-ot1-f67.google.com ([209.85.210.67]:42965 "EHLO mail-ot1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728376AbgFTRuR (ORCPT ); Sat, 20 Jun 2020 13:50:17 -0400 Received: by mail-ot1-f67.google.com with SMTP id t6so9804988otk.9 for ; Sat, 20 Jun 2020 10:50:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=461CLOKGmiU5CofZzL7eUc/s5fevWfSccRK543s1Eo0=; b=Lz1G/TGOcix74igMNs2i3BCOsB6VwLSOHtuyEaCgWPqM3rbCVeXjvrXh30IcHjZX/b SvANV4xrNaamC+J37mxaqtoo+Iq9tBAgnVW0iGZ6tfwdjgEVDpjXjcPSa8Paaat2/JLw 0WFeYAJ8t8+XIWv1J597hcGF7RCX7faLYgzejHLxuxGK3bmqo4i8un656kXFs+7v0NgZ N2acGEkah0KSwOvLGDfLLfH204b5EGZsL4AdfC8Ojbf8hAUOMQb4sfOA4nllGDTG7lx9 z6C3cMqF4BShG2GSXfEpxyDSb2WJ1+HuWhcWDpmHa369VfVyMLuhIsGopaeY2fO0luS9 GWzw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=461CLOKGmiU5CofZzL7eUc/s5fevWfSccRK543s1Eo0=; b=ZNyG/FU6YrF3NMr89+8TSS/NuWUB0rcVot+cZyCqqsV6OZuln49AxKD+aWJ13cOSeC qRZAZ8pwkCMfC6qWX9TPuGtfp+/xSzVURd7hfItCKtF/ssfnWOtBONAfZFISBe84Q0I6 /bZAe3gDyqdqJlviNqbQOvlAPs0bf2jxGSjBTCgh9UCsQ1dxG2wbWQ6hy+yK4Myy3DjT sc1CuUk2yvB7Ug9bJbQOdCiWF8YIJW+VHDR/qIaxMw/TTRFScNwJy7avh6iArqKWAtl6 LfWiVOnhwysDtlYOMsq1TWmMCYgQ5LSHXi1uvxyIX5x4XVXKyuojjl0AS/DSgq7g/1WM IK5g== X-Gm-Message-State: AOAM530y3z19KSiQyg+wkIw9sDICUxVoMkeScMf8XqBbUFg/9mEgRpoD /E1eDxhOOKJ9DxS7DTqoFg== X-Google-Smtp-Source: ABdhPJyjCBUY145ExsorOuUiTMW4lgD2SALtS8QiuaOGerzcHQQ91jos9UTs1x02WVH+UlOiYXYfzg== X-Received: by 2002:a9d:629a:: with SMTP id x26mr8090339otk.116.1592675354828; Sat, 20 Jun 2020 10:49:14 -0700 (PDT) Received: from serve.minyard.net (serve.minyard.net. [2001:470:b8f6:1b::1]) by smtp.gmail.com with ESMTPSA id m8sm2083210otc.1.2020.06.20.10.49.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 20 Jun 2020 10:49:13 -0700 (PDT) Received: from t560.minyard.net (unknown [IPv6:2001:470:b8f6:1b:98f8:1e34:b5b7:82f7]) by serve.minyard.net (Postfix) with ESMTPA id 9CFBE18054F; Sat, 20 Jun 2020 17:49:11 +0000 (UTC) From: minyard@acm.org To: Guenter Roeck , Wim Van Sebroeck Cc: linux-watchdog@vger.kernel.org, Corey Minyard Subject: [PATCH 04/10] watchdog: Add functions to set the timeout and pretimeout Date: Sat, 20 Jun 2020 12:49:01 -0500 Message-Id: <20200620174907.20229-5-minyard@acm.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200620174907.20229-1-minyard@acm.org> References: <20200620174907.20229-1-minyard@acm.org> Sender: linux-watchdog-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-watchdog@vger.kernel.org From: Corey Minyard If the watchdog device wants to set it's pretimeout (say from module parameters), this lets them do that. Signed-off-by: Corey Minyard --- drivers/watchdog/watchdog_dev.c | 54 +++++++++++++++++++++++++++++---- include/linux/watchdog.h | 4 +++ 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c index 45a0a4fe731d..6c423aed3f3c 100644 --- a/drivers/watchdog/watchdog_dev.c +++ b/drivers/watchdog/watchdog_dev.c @@ -364,14 +364,14 @@ static unsigned int watchdog_get_status(struct watchdog_device *wdd) } /* - * watchdog_set_timeout: set the watchdog timer timeout + * _watchdog_set_timeout: set the watchdog timer timeout * @wdd: the watchdog device to set the timeout for * @timeout: timeout to set in seconds * * The caller must hold wd_data->lock. */ -static int watchdog_set_timeout(struct watchdog_device *wdd, +static int _watchdog_set_timeout(struct watchdog_device *wdd, unsigned int timeout) { int err = 0; @@ -396,14 +396,35 @@ static int watchdog_set_timeout(struct watchdog_device *wdd, return err; } +/* + * watchdog_set_timeout: set the watchdog timer timeout + * @wdd: the watchdog device to set the timeout for + * @timeout: timeout to set in seconds + */ + +int watchdog_set_timeout(struct watchdog_device *wdd, unsigned int timeout) +{ + int err = 0; + + if (!wdd->wd_data) + return -ENODEV; + + mutex_lock(&wdd->wd_data->lock); + err = _watchdog_set_timeout(wdd, timeout); + mutex_unlock(&wdd->wd_data->lock); + + return err; +} +EXPORT_SYMBOL_GPL(watchdog_set_timeout); + /* * watchdog_set_pretimeout: set the watchdog timer pretimeout * @wdd: the watchdog device to set the timeout for * @timeout: pretimeout to set in seconds */ -static int watchdog_set_pretimeout(struct watchdog_device *wdd, - unsigned int timeout) +static int _watchdog_set_pretimeout(struct watchdog_device *wdd, + unsigned int timeout) { int err = 0; @@ -421,6 +442,27 @@ static int watchdog_set_pretimeout(struct watchdog_device *wdd, return err; } +/* + * watchdog_set_pretimeout: set the watchdog timer pretimeout + * @wdd: the watchdog device to set the timeout for + * @timeout: pretimeout to set in seconds + */ + +int watchdog_set_pretimeout(struct watchdog_device *wdd, unsigned int timeout) +{ + int err = 0; + + if (!wdd->wd_data) + return -ENODEV; + + mutex_lock(&wdd->wd_data->lock); + err = _watchdog_set_pretimeout(wdd, timeout); + mutex_unlock(&wdd->wd_data->lock); + + return err; +} +EXPORT_SYMBOL_GPL(watchdog_set_pretimeout); + /* * watchdog_get_timeleft: wrapper to get the time left before a reboot * @wdd: the watchdog device to get the remaining time from @@ -809,7 +851,7 @@ static long watchdog_ioctl(struct file *file, unsigned int cmd, err = -EFAULT; break; } - err = watchdog_set_timeout(wdd, val); + err = _watchdog_set_timeout(wdd, val); if (err < 0) break; /* If the watchdog is active then we send a keepalive ping @@ -838,7 +880,7 @@ static long watchdog_ioctl(struct file *file, unsigned int cmd, err = -EFAULT; break; } - err = watchdog_set_pretimeout(wdd, val); + err = _watchdog_set_pretimeout(wdd, val); break; case WDIOC_GETPRETIMEOUT: err = put_user(wdd->pretimeout, p); diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h index 36f99c8c973e..95396b644a9b 100644 --- a/include/linux/watchdog.h +++ b/include/linux/watchdog.h @@ -201,6 +201,10 @@ static inline void *watchdog_get_drvdata(struct watchdog_device *wdd) return wdd->driver_data; } +/* Allow the driver to set the timeout and pretimeout. */ +int watchdog_set_timeout(struct watchdog_device *wdd, unsigned int timeout); +int watchdog_set_pretimeout(struct watchdog_device *wdd, unsigned int timeout); + /* Use the following functions to report watchdog pretimeout event */ #if IS_ENABLED(CONFIG_WATCHDOG_PRETIMEOUT_GOV) void watchdog_notify_pretimeout(struct watchdog_device *wdd); From patchwork Sat Jun 20 17:49:03 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Corey Minyard X-Patchwork-Id: 215006 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6A523C433DF for ; Sat, 20 Jun 2020 17:50:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 3B32F20FC3 for ; Sat, 20 Jun 2020 17:50:20 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="dPlK26Ms" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728385AbgFTRuU (ORCPT ); Sat, 20 Jun 2020 13:50:20 -0400 Received: from mail-ot1-f68.google.com ([209.85.210.68]:45905 "EHLO mail-ot1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728381AbgFTRuT (ORCPT ); Sat, 20 Jun 2020 13:50:19 -0400 Received: by mail-ot1-f68.google.com with SMTP id m2so9801625otr.12 for ; Sat, 20 Jun 2020 10:50:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=nK+mVF9ZQV0dr81AyPeFSL6mPMdD5C2OQ3fEkI0R0m0=; b=dPlK26Ms53JnKa5FcI5IFSPZ9eyYhE36FQjOY+UzsUKdBpykpaqF/EhvQLoq3i2qX5 VVyCpRmNZhPoWr5xGGMufLF33KiT9tqtNwzIH9yWML5Hey0XeRgN6qgpVcOEDrUnovUR H/nI4smtT7E2fi+iM2n9iD9Pqv/6xI5NQEQ3Fzas8ZdBWJGiEjcTGpJ4GDmg7sVzmJwD D+svfjm+di5yrm58Ei5Fbi6cXj7BjYH55HWs3j2cnOhlpk/o29WJAsAuFXesb3Utw/qG SmibIKvzq7FUi9cJSgJ0T45k7EyL93cLKZ0X8T3nsX11rJiBUU9lkWLK5RTn3/vVzY4l 7t8w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=nK+mVF9ZQV0dr81AyPeFSL6mPMdD5C2OQ3fEkI0R0m0=; b=Jtg6EpO1H0NX1BvykTXzO6toVd16Du+Cvxun1LuaAXwOhUj5T6zokZTIdELjvTdsxg 5iARByybXAMybUzwTxzvq7xQmSTe9TkP+t203iFjmlXgvkaFfPnk6GfqpWJ5DVPsdvrp f4q+n7RSTLC9XyTJFb3spZI9X01Oagka/y6E9KCAt+VifGzYpyywJMCesmex02ehZRGe t6OLBdF8VTsMhUm1+2FUt1m6kfpyy4XACIjjRCp5LUJL/bggrQijZaz7/Vkutks41RWa LoUmO0/hWQyD4TkBBmISHAviNvgtEhW4CgtS3ZRPzjTZELmaDuSFMKmRrs9a+iflrPDg 7sVg== X-Gm-Message-State: AOAM530Ku60F1UB4+Od2NqOR7ehclM+ZQJheBYXdM1UtUrxy1v93pdRy hLzam+h1wEI4YZPX/ytD7w== X-Google-Smtp-Source: ABdhPJyjegTKtwpTOY4XHo/rhDg0aIxxQBW2s0yA69ynK8Yu0w/cy3uEiK/r9liQVirElBqnJaSdHg== X-Received: by 2002:a9d:6c03:: with SMTP id f3mr7697909otq.291.1592675357150; Sat, 20 Jun 2020 10:49:17 -0700 (PDT) Received: from serve.minyard.net ([47.184.146.204]) by smtp.gmail.com with ESMTPSA id o2sm2057599ota.14.2020.06.20.10.49.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 20 Jun 2020 10:49:14 -0700 (PDT) Received: from t560.minyard.net (unknown [IPv6:2001:470:b8f6:1b:98f8:1e34:b5b7:82f7]) by serve.minyard.net (Postfix) with ESMTPA id CA4B7180561; Sat, 20 Jun 2020 17:49:11 +0000 (UTC) From: minyard@acm.org To: Guenter Roeck , Wim Van Sebroeck Cc: linux-watchdog@vger.kernel.org, Corey Minyard Subject: [PATCH 06/10] ipmi:watchdog: Convert over to the watchdog framework Date: Sat, 20 Jun 2020 12:49:03 -0500 Message-Id: <20200620174907.20229-7-minyard@acm.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200620174907.20229-1-minyard@acm.org> References: <20200620174907.20229-1-minyard@acm.org> Sender: linux-watchdog-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-watchdog@vger.kernel.org From: Corey Minyard Use the standard watchdog framework for the IPMI watchdog. This reduces complexity and should avoid issues with interactions between the IPMI watchdog and other watchdogs. Signed-off-by: Corey Minyard --- drivers/char/ipmi/ipmi_watchdog.c | 381 ++++++++++++------------------ 1 file changed, 153 insertions(+), 228 deletions(-) diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 55986e10a124..9265a5145691 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -122,7 +121,11 @@ #define IPMI_WDOG_TIMER_NOT_INIT_RESP 0x80 +/* Forward declaration. */ +static struct watchdog_device ipmi_wdd; + static DEFINE_MUTEX(ipmi_watchdog_mutex); + static bool nowayout = WATCHDOG_NOWAYOUT; static struct ipmi_user *watchdog_user; @@ -154,7 +157,6 @@ static char data_to_read; static DECLARE_WAIT_QUEUE_HEAD(read_q); static struct fasync_struct *fasync_q; static atomic_t pretimeout_since_last_heartbeat; -static char expect_close; static int ifnum_to_use = -1; @@ -163,7 +165,6 @@ static int ifnum_to_use = -1; #define IPMI_SET_TIMEOUT_HB_IF_NECESSARY 1 #define IPMI_SET_TIMEOUT_FORCE_HB 2 -static int ipmi_set_timeout(int do_heartbeat); static void ipmi_register_watchdog(int ipmi_intf); static void ipmi_unregister_watchdog(int ipmi_intf); @@ -175,19 +176,24 @@ static int start_now; static int set_param_timeout(const char *val, const struct kernel_param *kp) { - char *endp; - int l; + unsigned long l; int rv = 0; + int *ptr; if (!val) return -EINVAL; - l = simple_strtoul(val, &endp, 0); - if (endp == val) - return -EINVAL; + rv = kstrtoul(val, 0, &l); + if (rv) + return rv; - *((int *)kp->arg) = l; - if (watchdog_user) - rv = ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY); + ptr = (int *) kp->arg; + *ptr = l; + if (watchdog_user) { + if (ptr == &pretimeout) + rv = watchdog_set_pretimeout(&ipmi_wdd, l); + else if (ptr == &timeout) + rv = watchdog_set_timeout(&ipmi_wdd, l); + } return rv; } @@ -223,7 +229,7 @@ static int set_param_str(const char *val, const struct kernel_param *kp) check_parms(); if (watchdog_user) - rv = ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY); + rv = watchdog_set_timeout(&ipmi_wdd, ipmi_wdd.timeout); out: return rv; @@ -266,6 +272,38 @@ static const struct kernel_param_ops param_ops_str = { .get = get_param_str, }; +static int set_param_nowayout(const char *val, const struct kernel_param *kp) +{ + unsigned long l; + int rv; + + if (!val) + return -EINVAL; + if (val[0] == 'Y' || val[0] == 'y') + l = true; + else if (val[0] == 'N' || val[0] == 'n') + l = false; + else { + rv = kstrtoul(val, 0, &l); + if (rv) + return rv; + } + + nowayout = l; + if (nowayout) + set_bit(WDOG_NO_WAY_OUT, &ipmi_wdd.status); + else + clear_bit(WDOG_NO_WAY_OUT, &ipmi_wdd.status); + + return 0; +} + +static const struct kernel_param_ops param_ops_nowayout = { + .set = set_param_nowayout, + .get = param_get_bool, +}; +#define param_check_nowayout param_check_bool + module_param(ifnum_to_use, wdog_ifnum, 0644); MODULE_PARM_DESC(ifnum_to_use, "The interface number to use for the watchdog " "timer. Setting to -1 defaults to the first registered " @@ -296,24 +334,13 @@ module_param(start_now, int, 0444); MODULE_PARM_DESC(start_now, "Set to 1 to start the watchdog as" "soon as the driver is loaded."); -module_param(nowayout, bool, 0644); +module_param(nowayout, nowayout, 0644); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " "(default=CONFIG_WATCHDOG_NOWAYOUT)"); /* Default state of the timer. */ static unsigned char ipmi_watchdog_state = WDOG_TIMEOUT_NONE; -/* Is someone using the watchdog? Only one user is allowed. */ -static unsigned long ipmi_wdog_open; - -/* - * If set to 1, the heartbeat command will set the state to reset and - * start the timer. The timer doesn't normally run when the driver is - * first opened until the heartbeat is set the first time, this - * variable is used to accomplish this. - */ -static int ipmi_start_timer_on_heartbeat; - /* IPMI version of the BMC. */ static unsigned char ipmi_version_major; static unsigned char ipmi_version_minor; @@ -326,7 +353,7 @@ static int testing_nmi; static int nmi_handler_registered; #endif -static int __ipmi_heartbeat(void); +static int __ipmi_heartbeat(struct watchdog_device *wdd); /* * We use a mutex to make sure that only one thing can send a set a @@ -352,7 +379,8 @@ static struct ipmi_recv_msg recv_msg = { .done = msg_free_recv }; -static int __ipmi_set_timeout(struct ipmi_smi_msg *smi_msg, +static int __ipmi_set_timeout(struct watchdog_device *wdd, + struct ipmi_smi_msg *smi_msg, struct ipmi_recv_msg *recv_msg, int *send_heartbeat_now) { @@ -380,15 +408,16 @@ static int __ipmi_set_timeout(struct ipmi_smi_msg *smi_msg, data[1] = 0; WDOG_SET_TIMEOUT_ACT(data[1], ipmi_watchdog_state); - if ((pretimeout > 0) && (ipmi_watchdog_state != WDOG_TIMEOUT_NONE)) { - WDOG_SET_PRETIMEOUT_ACT(data[1], preaction_val); - data[2] = pretimeout; + if ((wdd->pretimeout > 0) && + (ipmi_watchdog_state != WDOG_TIMEOUT_NONE)) { + WDOG_SET_PRETIMEOUT_ACT(data[1], preaction_val); + data[2] = wdd->pretimeout; } else { WDOG_SET_PRETIMEOUT_ACT(data[1], WDOG_PRETIMEOUT_NONE); data[2] = 0; /* No pretimeout. */ } data[3] = 0; - WDOG_SET_TIMEOUT(data[4], data[5], timeout); + WDOG_SET_TIMEOUT(data[4], data[5], wdd->timeout); addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; addr.channel = IPMI_BMC_CHANNEL; @@ -414,7 +443,7 @@ static int __ipmi_set_timeout(struct ipmi_smi_msg *smi_msg, return rv; } -static int _ipmi_set_timeout(int do_heartbeat) +static int _ipmi_set_timeout(struct watchdog_device *wdd, int do_heartbeat) { int send_heartbeat_now; int rv; @@ -424,8 +453,7 @@ static int _ipmi_set_timeout(int do_heartbeat) atomic_set(&msg_tofree, 2); - rv = __ipmi_set_timeout(&smi_msg, - &recv_msg, + rv = __ipmi_set_timeout(wdd, &smi_msg, &recv_msg, &send_heartbeat_now); if (rv) return rv; @@ -435,17 +463,17 @@ static int _ipmi_set_timeout(int do_heartbeat) if ((do_heartbeat == IPMI_SET_TIMEOUT_FORCE_HB) || ((send_heartbeat_now) && (do_heartbeat == IPMI_SET_TIMEOUT_HB_IF_NECESSARY))) - rv = __ipmi_heartbeat(); + rv = __ipmi_heartbeat(wdd); return rv; } -static int ipmi_set_timeout(int do_heartbeat) +static int ipmi_set_timeout(struct watchdog_device *wdd, int do_heartbeat) { int rv; mutex_lock(&ipmi_watchdog_mutex); - rv = _ipmi_set_timeout(do_heartbeat); + rv = _ipmi_set_timeout(wdd, do_heartbeat); mutex_unlock(&ipmi_watchdog_mutex); return rv; @@ -525,9 +553,8 @@ static void panic_halt_ipmi_set_timeout(void) while (atomic_read(&panic_done_count) != 0) ipmi_poll_interface(watchdog_user); atomic_add(1, &panic_done_count); - rv = __ipmi_set_timeout(&panic_halt_smi_msg, - &panic_halt_recv_msg, - &send_heartbeat_now); + rv = __ipmi_set_timeout(&ipmi_wdd, &panic_halt_smi_msg, + &panic_halt_recv_msg, &send_heartbeat_now); if (rv) { atomic_sub(1, &panic_done_count); pr_warn("Unable to extend the watchdog timeout\n"); @@ -539,7 +566,7 @@ static void panic_halt_ipmi_set_timeout(void) ipmi_poll_interface(watchdog_user); } -static int __ipmi_heartbeat(void) +static int __ipmi_heartbeat(struct watchdog_device *wdd) { struct kernel_ipmi_msg msg; int rv; @@ -596,7 +623,7 @@ static int __ipmi_heartbeat(void) * in this process, so must say no heartbeat to avoid a * deadlock on this mutex */ - rv = _ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB); + rv = _ipmi_set_timeout(wdd, IPMI_SET_TIMEOUT_NO_HB); if (rv) { pr_err("Unable to send the command to set the watchdog's settings, giving up\n"); goto out; @@ -617,165 +644,87 @@ static int __ipmi_heartbeat(void) return rv; } -static int _ipmi_heartbeat(void) +static int _ipmi_heartbeat(struct watchdog_device *wdd) { int rv; if (!watchdog_user) return -ENODEV; - if (ipmi_start_timer_on_heartbeat) { - ipmi_start_timer_on_heartbeat = 0; - ipmi_watchdog_state = action_val; - rv = _ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB); - } else if (atomic_cmpxchg(&pretimeout_since_last_heartbeat, 1, 0)) { - /* - * A pretimeout occurred, make sure we set the timeout. - * We don't want to set the action, though, we want to - * leave that alone (thus it can't be combined with the - * above operation. - */ - rv = _ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY); + if (atomic_cmpxchg(&pretimeout_since_last_heartbeat, 1, 0)) { + /* A pretimeout occurred, make sure we set the timeout. */ + rv = _ipmi_set_timeout(wdd, IPMI_SET_TIMEOUT_HB_IF_NECESSARY); } else { - rv = __ipmi_heartbeat(); + rv = __ipmi_heartbeat(wdd); } return rv; } -static int ipmi_heartbeat(void) +static int ipmi_wdog_set_timeout(struct watchdog_device *wdd, + unsigned int timeout) { int rv; mutex_lock(&ipmi_watchdog_mutex); - rv = _ipmi_heartbeat(); + wdd->timeout = timeout; + rv = _ipmi_set_timeout(wdd, IPMI_SET_TIMEOUT_HB_IF_NECESSARY); mutex_unlock(&ipmi_watchdog_mutex); return rv; } -static struct watchdog_info ident = { - .options = 0, /* WDIOF_SETTIMEOUT, */ - .firmware_version = 1, - .identity = "IPMI" -}; - -static int ipmi_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) +static int ipmi_wdog_set_pretimeout(struct watchdog_device *wdd, + unsigned int pretimeout) { - void __user *argp = (void __user *)arg; - int i; - int val; - - switch (cmd) { - case WDIOC_GETSUPPORT: - i = copy_to_user(argp, &ident, sizeof(ident)); - return i ? -EFAULT : 0; - - case WDIOC_SETTIMEOUT: - i = copy_from_user(&val, argp, sizeof(int)); - if (i) - return -EFAULT; - timeout = val; - return _ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY); - - case WDIOC_GETTIMEOUT: - i = copy_to_user(argp, &timeout, sizeof(timeout)); - if (i) - return -EFAULT; - return 0; - - case WDIOC_SETPRETIMEOUT: - i = copy_from_user(&val, argp, sizeof(int)); - if (i) - return -EFAULT; - pretimeout = val; - return _ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY); - - case WDIOC_GETPRETIMEOUT: - i = copy_to_user(argp, &pretimeout, sizeof(pretimeout)); - if (i) - return -EFAULT; - return 0; - - case WDIOC_KEEPALIVE: - return _ipmi_heartbeat(); - - case WDIOC_SETOPTIONS: - i = copy_from_user(&val, argp, sizeof(int)); - if (i) - return -EFAULT; - if (val & WDIOS_DISABLECARD) { - ipmi_watchdog_state = WDOG_TIMEOUT_NONE; - _ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB); - ipmi_start_timer_on_heartbeat = 0; - } - - if (val & WDIOS_ENABLECARD) { - ipmi_watchdog_state = action_val; - _ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB); - } - return 0; + int rv; - case WDIOC_GETSTATUS: - val = 0; - i = copy_to_user(argp, &val, sizeof(val)); - if (i) - return -EFAULT; - return 0; + mutex_lock(&ipmi_watchdog_mutex); + wdd->pretimeout = pretimeout; + rv = _ipmi_set_timeout(wdd, IPMI_SET_TIMEOUT_HB_IF_NECESSARY); + mutex_unlock(&ipmi_watchdog_mutex); - default: - return -ENOIOCTLCMD; - } + return rv; } -static long ipmi_unlocked_ioctl(struct file *file, - unsigned int cmd, - unsigned long arg) +static int ipmi_wdog_start(struct watchdog_device *wdd) { - int ret; + int rv; mutex_lock(&ipmi_watchdog_mutex); - ret = ipmi_ioctl(file, cmd, arg); + ipmi_watchdog_state = action_val; + rv = _ipmi_set_timeout(wdd, IPMI_SET_TIMEOUT_FORCE_HB); mutex_unlock(&ipmi_watchdog_mutex); - return ret; + return rv; } -static ssize_t ipmi_write(struct file *file, - const char __user *buf, - size_t len, - loff_t *ppos) +static int ipmi_wdog_ping(struct watchdog_device *wdd) { int rv; - if (len) { - if (!nowayout) { - size_t i; + mutex_lock(&ipmi_watchdog_mutex); + rv = _ipmi_heartbeat(wdd); + mutex_unlock(&ipmi_watchdog_mutex); - /* In case it was set long ago */ - expect_close = 0; + return rv; +} - for (i = 0; i != len; i++) { - char c; +static int ipmi_wdog_stop(struct watchdog_device *wdd) +{ + mutex_lock(&ipmi_watchdog_mutex); + ipmi_watchdog_state = WDOG_TIMEOUT_NONE; + _ipmi_set_timeout(wdd, IPMI_SET_TIMEOUT_NO_HB); + mutex_unlock(&ipmi_watchdog_mutex); - if (get_user(c, buf + i)) - return -EFAULT; - if (c == 'V') - expect_close = 42; - } - } - rv = ipmi_heartbeat(); - if (rv) - return rv; - } - return len; + return 0; } -static ssize_t ipmi_read(struct file *file, - char __user *buf, - size_t count, - loff_t *ppos) +static ssize_t ipmi_wdog_read(struct watchdog_device *wdd, + struct file *file, + char __user *buf, + size_t count, + loff_t *ppos) { int rv = 0; wait_queue_entry_t wait; @@ -824,27 +773,8 @@ static ssize_t ipmi_read(struct file *file, return rv; } -static int ipmi_open(struct inode *ino, struct file *filep) -{ - switch (iminor(ino)) { - case WATCHDOG_MINOR: - if (test_and_set_bit(0, &ipmi_wdog_open)) - return -EBUSY; - - - /* - * Don't start the timer now, let it start on the - * first heartbeat. - */ - ipmi_start_timer_on_heartbeat = 1; - return stream_open(ino, filep); - - default: - return (-ENODEV); - } -} - -static __poll_t ipmi_poll(struct file *file, poll_table *wait) +static __poll_t ipmi_wdog_poll(struct watchdog_device *wdd, + struct file *file, poll_table *wait) { __poll_t mask = 0; @@ -858,7 +788,8 @@ static __poll_t ipmi_poll(struct file *file, poll_table *wait) return mask; } -static int ipmi_fasync(int fd, struct file *file, int on) +static int ipmi_wdog_fasync(struct watchdog_device *wdd, + int fd, struct file *file, int on) { int result; @@ -867,43 +798,31 @@ static int ipmi_fasync(int fd, struct file *file, int on) return (result); } -static int ipmi_close(struct inode *ino, struct file *filep) -{ - if (iminor(ino) == WATCHDOG_MINOR) { - if (expect_close == 42) { - mutex_lock(&ipmi_watchdog_mutex); - ipmi_watchdog_state = WDOG_TIMEOUT_NONE; - _ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB); - mutex_unlock(&ipmi_watchdog_mutex); - } else { - pr_crit("Unexpected close, not stopping watchdog!\n"); - ipmi_heartbeat(); - } - clear_bit(0, &ipmi_wdog_open); - } - - expect_close = 0; - - return 0; -} +static const struct watchdog_ops ipmi_wdog_ops = { + .start = ipmi_wdog_start, + .stop = ipmi_wdog_stop, + .set_timeout = ipmi_wdog_set_timeout, + .set_pretimeout = ipmi_wdog_set_pretimeout, + .ping = ipmi_wdog_ping, + .read = ipmi_wdog_read, + .poll = ipmi_wdog_poll, + .fasync = ipmi_wdog_fasync, +}; -static const struct file_operations ipmi_wdog_fops = { - .owner = THIS_MODULE, - .read = ipmi_read, - .poll = ipmi_poll, - .write = ipmi_write, - .unlocked_ioctl = ipmi_unlocked_ioctl, - .compat_ioctl = compat_ptr_ioctl, - .open = ipmi_open, - .release = ipmi_close, - .fasync = ipmi_fasync, - .llseek = no_llseek, +static struct watchdog_info ipmi_wdog_info = { + .options = (WDIOF_SETTIMEOUT | WDIOF_PRETIMEOUT | + WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE), + .firmware_version = 1, + .identity = "IPMI" }; -static struct miscdevice ipmi_wdog_miscdev = { - .minor = WATCHDOG_MINOR, - .name = "watchdog", - .fops = &ipmi_wdog_fops +static struct watchdog_device ipmi_wdd = { + .ops = &ipmi_wdog_ops, + .info = &ipmi_wdog_info, + .min_timeout = 1, + .max_timeout = 6553, + .min_hw_heartbeat_ms = 1, + .max_hw_heartbeat_ms = 65535, }; static void ipmi_wdog_msg_handler(struct ipmi_recv_msg *msg, @@ -944,7 +863,7 @@ static void ipmi_wdog_pretimeout_handler(void *handler_data) atomic_set(&pretimeout_since_last_heartbeat, 1); } -static void ipmi_wdog_panic_handler(void *user_data) +static void ipmi_wdog_panic_handler(void *handler_data) { static int panic_event_handled; @@ -998,11 +917,21 @@ static void ipmi_register_watchdog(int ipmi_intf) ipmi_version_minor = 0; } - rv = misc_register(&ipmi_wdog_miscdev); + ipmi_wdd.pretimeout = pretimeout; + + rv = watchdog_init_timeout(&ipmi_wdd, timeout, NULL); if (rv < 0) { ipmi_destroy_user(watchdog_user); watchdog_user = NULL; - pr_crit("Unable to register misc device\n"); + pr_crit("Unable to initialize the IPMI watchdog device\n"); + } + watchdog_set_nowayout(&ipmi_wdd, nowayout); + + rv = watchdog_register_device(&ipmi_wdd); + if (rv) { + ipmi_destroy_user(watchdog_user); + watchdog_user = NULL; + pr_crit("Unable to register the IPMI watchdog device\n"); } #ifdef HAVE_DIE_NMI @@ -1022,7 +951,7 @@ static void ipmi_register_watchdog(int ipmi_intf) testing_nmi = 1; - rv = ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB); + rv = ipmi_set_timeout(&ipmi_wdd, IPMI_SET_TIMEOUT_FORCE_HB); if (rv) { pr_warn("Error starting timer to test NMI: 0x%x. The NMI pretimeout will likely not work\n", rv); @@ -1047,13 +976,12 @@ static void ipmi_register_watchdog(int ipmi_intf) if ((start_now) && (rv == 0)) { /* Run from startup, so start the timer now. */ start_now = 0; /* Disable this function after first startup. */ - ipmi_watchdog_state = action_val; - ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB); + watchdog_start(&ipmi_wdd); pr_info("Starting now!\n"); } else { /* Stop the timer now. */ ipmi_watchdog_state = WDOG_TIMEOUT_NONE; - ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB); + _ipmi_set_timeout(&ipmi_wdd, IPMI_SET_TIMEOUT_NO_HB); } } @@ -1069,7 +997,7 @@ static void ipmi_unregister_watchdog(int ipmi_intf) return; /* Make sure no one can call us any more. */ - misc_deregister(&ipmi_wdog_miscdev); + watchdog_unregister_device(&ipmi_wdd); watchdog_user = NULL; @@ -1088,9 +1016,6 @@ static void ipmi_unregister_watchdog(int ipmi_intf) if (rv) pr_warn("error unlinking from IPMI: %d\n", rv); - /* If it comes back, restart it properly. */ - ipmi_start_timer_on_heartbeat = 1; - mutex_unlock(&ipmi_watchdog_mutex); } @@ -1147,7 +1072,7 @@ static int wdog_reboot_handler(struct notifier_block *this, if (code == SYS_POWER_OFF || code == SYS_HALT) { /* Disable the WDT if we are shutting down. */ ipmi_watchdog_state = WDOG_TIMEOUT_NONE; - ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB); + ipmi_set_timeout(&ipmi_wdd, IPMI_SET_TIMEOUT_NO_HB); } else if (ipmi_watchdog_state != WDOG_TIMEOUT_NONE) { /* Set a long timer to let the reboot happen or reset if it hangs, but only if the watchdog @@ -1156,7 +1081,7 @@ static int wdog_reboot_handler(struct notifier_block *this, timeout = 120; pretimeout = 0; ipmi_watchdog_state = WDOG_TIMEOUT_RESET; - ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB); + ipmi_set_timeout(&ipmi_wdd, IPMI_SET_TIMEOUT_NO_HB); } } return NOTIFY_OK; From patchwork Sat Jun 20 17:49:06 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Corey Minyard X-Patchwork-Id: 215007 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 27803C433E3 for ; Sat, 20 Jun 2020 17:50:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 05ECA20748 for ; Sat, 20 Jun 2020 17:50:19 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="lAJGLN5g" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728369AbgFTRuS (ORCPT ); Sat, 20 Jun 2020 13:50:18 -0400 Received: from mail-ot1-f68.google.com ([209.85.210.68]:36122 "EHLO mail-ot1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728372AbgFTRuR (ORCPT ); Sat, 20 Jun 2020 13:50:17 -0400 Received: by mail-ot1-f68.google.com with SMTP id 97so9835424otg.3 for ; Sat, 20 Jun 2020 10:50:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=a+OmAdNBC/pnfo+gFZebqjumwX7Z8038L6u6RJcEe9c=; b=lAJGLN5gT9xfg/ycOJjQh94VamGGwglaZUg0QuTdyep5Npp9UGwn4uPwit/g29k5UX FL6aaTnuGXK1jw/5B8HkNBBqT3Km52XXj4fwYD5PPFA/m50sTxuR5NgHSgEPFIHcDbTp BxT0kAOewGb3UuDJ5gCbCMKkz6zxDDZepwKm6qN8CzCf9hvbn4uTcyXsuXW4eKS/msGm MuR1vteuj+5Fe57TfiSnpYMFsYEhWlb6Gpn9uicihPR8f0pvxTavkMzjTTitg9TBSF1c y1vfixjKV3xp1iqVH8ZHZ2klEVW6yslfKlha6q1WDUWYEcXIpxEnatIR6UzbesyTA2se GXjw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=a+OmAdNBC/pnfo+gFZebqjumwX7Z8038L6u6RJcEe9c=; b=olbb7NLX4wBIKLHgBkMBOAdpHJFqE9tHC031pGaZ1nq8ah6r6vwGo6GhCs+p8RpeKS PTM7WO3YcoJWMpIafV3Mu1CA/4oBWABG7zoem+r5pporhlBOnvrBY9+nZzACzh+LvA7+ bVQdXiJkB0nc/Hr8VLPIt+EbmTCP2jSGwGzLDerETM8A5Gyq6vSE+SZPY4I+QZ306DFg EG9hgAzMJy59sbcg03tlExX18cXpA7r5znLZucIQF+XoONKAYOq55VH0vmH5nfjOnqKF +Yd6MFzUKTH8ooAUN594RLUWugc+NaTi9jLcYoG/fzCI0B7/36Wx7IyTmCG6HJR0XGud oYgQ== X-Gm-Message-State: AOAM530Mv5oEKbcWXlpKeKtMcadbkKcYf2fnT4ehrTg3VUKiIdQ2HN2b GbcdnOBXT5Q63MraWjqjMg== X-Google-Smtp-Source: ABdhPJwLZuWMDioce1b/rAFs7pW4uaQJnUt6xZcWPsg1yD/lMrlTNlVeaBOD2W1BiiCWL7eCQC3wXA== X-Received: by 2002:a9d:6c50:: with SMTP id g16mr6973095otq.73.1592675356729; Sat, 20 Jun 2020 10:49:16 -0700 (PDT) Received: from serve.minyard.net (serve.minyard.net. [2001:470:b8f6:1b::1]) by smtp.gmail.com with ESMTPSA id i2sm2065728ota.66.2020.06.20.10.49.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 20 Jun 2020 10:49:14 -0700 (PDT) Received: from t560.minyard.net (unknown [IPv6:2001:470:b8f6:1b:98f8:1e34:b5b7:82f7]) by serve.minyard.net (Postfix) with ESMTPA id 09DCA180565; Sat, 20 Jun 2020 17:49:12 +0000 (UTC) From: minyard@acm.org To: Guenter Roeck , Wim Van Sebroeck Cc: linux-watchdog@vger.kernel.org, Corey Minyard Subject: [PATCH 09/10] ipmi:watchdog: Convert over to watchdog framework reboot handling Date: Sat, 20 Jun 2020 12:49:06 -0500 Message-Id: <20200620174907.20229-10-minyard@acm.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200620174907.20229-1-minyard@acm.org> References: <20200620174907.20229-1-minyard@acm.org> Sender: linux-watchdog-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-watchdog@vger.kernel.org From: Corey Minyard With the watchdog framework supporting a reboot timeout, we can switch the IPMI driver over to use that and get rid of some redundance code. Signed-off-by: Corey Minyard --- drivers/char/ipmi/ipmi_watchdog.c | 47 ++----------------------------- 1 file changed, 3 insertions(+), 44 deletions(-) diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 6e0c9faa6e6a..1ee884e6dcac 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -140,9 +139,6 @@ static int pretimeout; /* Default timeout to set on panic */ static int panic_wdt_timeout = 255; -/* Default timeout to set on reboot */ -static int reboot_wdt_timeout = 120; - /* Default action is to reset the board on a timeout. */ static unsigned char action_val = WDOG_TIMEOUT_RESET; @@ -321,7 +317,7 @@ MODULE_PARM_DESC(pretimeout, "Pretimeout value in seconds."); module_param(panic_wdt_timeout, timeout, 0644); MODULE_PARM_DESC(panic_wdt_timeout, "Timeout value on kernel panic in seconds."); -module_param(reboot_wdt_timeout, timeout, 0644); +module_param_named(reboot_wdt_timeout, ipmi_wdd.reboot_timeout, timeout, 0644); MODULE_PARM_DESC(reboot_wdt_timeout, "Timeout value on a reboot in seconds."); module_param_cb(action, ¶m_ops_str, action_op, 0644); @@ -825,10 +821,12 @@ static struct watchdog_info ipmi_wdog_info = { static struct watchdog_device ipmi_wdd = { .ops = &ipmi_wdog_ops, .info = &ipmi_wdog_info, + .status = 1 << WDOG_STOP_ON_REBOOT, .min_timeout = 1, .max_timeout = 6553, .min_hw_heartbeat_ms = 1, .max_hw_heartbeat_ms = 65535, + .reboot_timeout = 120, }; static void ipmi_wdog_msg_handler(struct ipmi_recv_msg *msg, @@ -1065,40 +1063,6 @@ ipmi_nmi(unsigned int val, struct pt_regs *regs) } #endif -static int wdog_reboot_handler(struct notifier_block *this, - unsigned long code, - void *unused) -{ - static int reboot_event_handled; - - if ((watchdog_user) && (!reboot_event_handled)) { - /* Make sure we only do this once. */ - reboot_event_handled = 1; - - if (code == SYS_POWER_OFF || code == SYS_HALT) { - /* Disable the WDT if we are shutting down. */ - ipmi_watchdog_state = WDOG_TIMEOUT_NONE; - ipmi_set_timeout(&ipmi_wdd, IPMI_SET_TIMEOUT_NO_HB); - } else if (ipmi_watchdog_state != WDOG_TIMEOUT_NONE) { - /* Set a long timer to let the reboot happen or - reset if it hangs, but only if the watchdog - timer was already running. */ - if (timeout < reboot_wdt_timeout) - timeout = reboot_wdt_timeout; - pretimeout = 0; - ipmi_watchdog_state = WDOG_TIMEOUT_RESET; - ipmi_set_timeout(&ipmi_wdd, IPMI_SET_TIMEOUT_NO_HB); - } - } - return NOTIFY_OK; -} - -static struct notifier_block wdog_reboot_notifier = { - .notifier_call = wdog_reboot_handler, - .next = NULL, - .priority = 0 -}; - static void ipmi_new_smi(int if_num, struct device *device) { ipmi_register_watchdog(if_num); @@ -1232,15 +1196,12 @@ static int __init ipmi_wdog_init(void) check_parms(); - register_reboot_notifier(&wdog_reboot_notifier); - rv = ipmi_smi_watcher_register(&smi_watcher); if (rv) { #ifdef HAVE_DIE_NMI if (nmi_handler_registered) unregister_nmi_handler(NMI_UNKNOWN, "ipmi"); #endif - unregister_reboot_notifier(&wdog_reboot_notifier); pr_warn("can't register smi watcher\n"); return rv; } @@ -1259,8 +1220,6 @@ static void __exit ipmi_wdog_exit(void) if (nmi_handler_registered) unregister_nmi_handler(NMI_UNKNOWN, "ipmi"); #endif - - unregister_reboot_notifier(&wdog_reboot_notifier); } module_exit(ipmi_wdog_exit); module_init(ipmi_wdog_init);