From patchwork Thu Mar 24 14:14:04 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lecopzer Chen X-Patchwork-Id: 12790742 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 42EFBC433F5 for ; Thu, 24 Mar 2022 14:19:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=8fQxf2aUzA4QCPBoQ4pZi0eCwr8Rblt3umx6JbqgDXQ=; b=1xKvRTEE7bBntE O3eCwz5mcKWmlEtbFYjwtx4hF4mrICpMr/aFwT15xthx9buKtKsNn3m4lETnGksX1L0pbbxYDQbpJ 4oJBxv4zsyV9i+a1c2gZSdUwWM0Q4J8A5qE5P6MDZQhjWC4kkj14yo9XaeZexVWTtrOeXW0ZcjAD7 vFipUWWLlR5aHtuWYJnChK+rYbkWko9OZQ9QMmfCp6Yyh5jJ2t3y6YII2xZqlP/e2esMDopnfqv0z yMnySl/C+Q8e+62DJEJsIMyxtchhmIwC/t0A8YhF3Xwdv8GFi/GKMeTEZrHN9M0H3pkonHEGPao3D PiSR7HyfJ4NGrP/rK2Gg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1nXOIK-00GpQU-1E; Thu, 24 Mar 2022 14:18:32 +0000 Received: from mailgw01.mediatek.com ([216.200.240.184]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1nXOHt-00GpGC-BH; Thu, 24 Mar 2022 14:18:07 +0000 X-UUID: 40c991c2c46c45aeaf840f334e351b24-20220324 X-UUID: 40c991c2c46c45aeaf840f334e351b24-20220324 Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by mailgw01.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 551735683; Thu, 24 Mar 2022 07:18:02 -0700 Received: from mtkexhb01.mediatek.inc (172.21.101.102) by MTKMBS62DR.mediatek.inc (172.29.94.18) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Thu, 24 Mar 2022 07:14:26 -0700 Received: from mtkcas11.mediatek.inc (172.21.101.40) by mtkexhb01.mediatek.inc (172.21.101.102) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Thu, 24 Mar 2022 22:14:12 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by mtkcas11.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Thu, 24 Mar 2022 22:14:12 +0800 From: Lecopzer Chen To: CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , Subject: [PATCH v3 4/5] kernel/watchdog: Adapt the watchdog_hld interface for async model Date: Thu, 24 Mar 2022 22:14:04 +0800 Message-ID: <20220324141405.10835-5-lecopzer.chen@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20220324141405.10835-1-lecopzer.chen@mediatek.com> References: <20220324141405.10835-1-lecopzer.chen@mediatek.com> MIME-Version: 1.0 X-MTK: N X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220324_071805_427676_1E569CE4 X-CRM114-Status: GOOD ( 21.64 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org When lockup_detector_init()->watchdog_nmi_probe(), PMU may be not ready yet. E.g. on arm64, PMU is not ready until device_initcall(armv8_pmu_driver_init). And it is deeply integrated with the driver model and cpuhp. Hence it is hard to push this initialization before smp_init(). But it is easy to take an opposite approach and try to initialize the watchdog once again later. The delayed probe is called using workqueues. It need to allocate memory and must be proceed in a normal context. The delayed probe is queued only when the early one returns -EBUSY. It is the return code returned when PMU is not ready yet. Provide an API - retry_lockup_detector_init() for anyone who needs to delayed init lockup detector. The original assumption is: nobody should use delayed probe after lockup_detector_check() which has __init attribute. That is, anyone uses this API must call between lockup_detector_init() and lockup_detector_check(), and the caller must have __init attribute Co-developed-by: Pingfan Liu Signed-off-by: Pingfan Liu Signed-off-by: Lecopzer Chen Suggested-by: Petr Mladek --- include/linux/nmi.h | 3 ++ kernel/watchdog.c | 69 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/include/linux/nmi.h b/include/linux/nmi.h index b7bcd63c36b4..1d84c9a8b460 100644 --- a/include/linux/nmi.h +++ b/include/linux/nmi.h @@ -118,6 +118,9 @@ static inline int hardlockup_detector_perf_init(void) { return 0; } void watchdog_nmi_stop(void); void watchdog_nmi_start(void); + +extern bool allow_lockup_detector_init_retry; +void retry_lockup_detector_init(void); int watchdog_nmi_probe(void); void watchdog_nmi_enable(unsigned int cpu); void watchdog_nmi_disable(unsigned int cpu); diff --git a/kernel/watchdog.c b/kernel/watchdog.c index b71d434cf648..308ba29f8f0f 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c @@ -103,7 +103,13 @@ void __weak watchdog_nmi_disable(unsigned int cpu) hardlockup_detector_perf_disable(); } -/* Return 0, if a NMI watchdog is available. Error code otherwise */ +/* + * Arch specific API. + * + * Return 0 when NMI watchdog is available, negative value otherwise. + * The error code -EBUSY is special. It means that a deferred probe + * might succeed later. + */ int __weak __init watchdog_nmi_probe(void) { return hardlockup_detector_perf_init(); @@ -839,16 +845,75 @@ static void __init watchdog_sysctl_init(void) #define watchdog_sysctl_init() do { } while (0) #endif /* CONFIG_SYSCTL */ +static void lockup_detector_delay_init(struct work_struct *work); +bool allow_lockup_detector_init_retry __initdata; + +static struct work_struct detector_work __initdata = + __WORK_INITIALIZER(detector_work, lockup_detector_delay_init); + +static void __init lockup_detector_delay_init(struct work_struct *work) +{ + int ret; + + ret = watchdog_nmi_probe(); + if (ret) { + pr_info("Delayed init of the lockup detector failed: %d\n", ret); + pr_info("Perf NMI watchdog permanently disabled\n"); + return; + } + + nmi_watchdog_available = true; + lockup_detector_setup(); + allow_lockup_detector_init_retry = false; +} + +/* + * retry_lockup_detector_init - retry init lockup detector if possible. + * + * Only take effect when allow_lockup_detector_init_retry is true, which + * means it must call between lockup_detector_init() and lockup_detector_check(). + * Be aware that caller must have __init attribute, relative functions + * will be freed after kernel initialization. + */ +void __init retry_lockup_detector_init(void) +{ + if (!allow_lockup_detector_init_retry) + return; + + queue_work_on(__smp_processor_id(), system_wq, &detector_work); +} + +/* Ensure the check is called after the initialization of driver */ +static int __init lockup_detector_check(void) +{ + /* Make sure no work is pending. */ + flush_work(&detector_work); + + if (!allow_lockup_detector_init_retry) + return 0; + + allow_lockup_detector_init_retry = false; + pr_info("Delayed init checking failed, please check your driver.\n"); + return 0; +} +late_initcall_sync(lockup_detector_check); + void __init lockup_detector_init(void) { + int ret; + if (tick_nohz_full_enabled()) pr_info("Disabling watchdog on nohz_full cores by default\n"); cpumask_copy(&watchdog_cpumask, housekeeping_cpumask(HK_FLAG_TIMER)); - if (!watchdog_nmi_probe()) + ret = watchdog_nmi_probe(); + if (!ret) nmi_watchdog_available = true; + else if (ret == -EBUSY) + allow_lockup_detector_init_retry = true; + lockup_detector_setup(); watchdog_sysctl_init(); }