From nobody Mon Jun 8 05:24:51 2026 Received: from mail-106112.protonmail.ch (mail-106112.protonmail.ch [79.135.106.112]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 769092EEE65 for ; Fri, 5 Jun 2026 13:12:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=79.135.106.112 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780665128; cv=none; b=HgGDQjXuBZKWv4JU3jh//qkOSDzioxzMaJadxqbcdIn9g8OS6mrTIZPjJW5WjSr4AwGqwdM1OfXRkq2b5/MiyfWEcSt48vDnwn7zZh2BgyrlK+rOajWWVTnB0GE/UNEoMEpw+rN4/FsmPBwjux8orX6e0qlPQtv+UZFmI/rNPmU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780665128; c=relaxed/simple; bh=okmxrgBCvufTcX32FIBoSLwcDGUzqtcDdCzFnkaOA7U=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=OxySWmoSABHYNnfI4Mi+IIJxDhO/w+Op7DR9y/mU1cIVkydwJjubiIa5ryUNJPfKuFUzkQ2wkWoCnk7rQXAS4wYQeg9cJIkD/VmDEMi5T0JerPh0oHZ/jiTQFnXpXUUbsIW3bixf5Kh6iKuoANC6Oc+WmyJUmulUiZL4fSgQdlI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=theesfeld.net; spf=fail smtp.mailfrom=theesfeld.net; dkim=fail (0-bit key) header.d=theesfeld.net header.i=@theesfeld.net header.b=bYCRFG/H reason="key not found in DNS"; arc=none smtp.client-ip=79.135.106.112 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=theesfeld.net Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=theesfeld.net Authentication-Results: smtp.subspace.kernel.org; dkim=fail reason="key not found in DNS" (0-bit key) header.d=theesfeld.net header.i=@theesfeld.net header.b="bYCRFG/H" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=theesfeld.net; s=protonmail2; t=1780665122; x=1780924322; bh=s2Tq9L+mxJV1LF+CSfNq0nEeRrlDQozObfED+HQhBNU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:From:To: Cc:Date:Subject:Reply-To:Feedback-ID:Message-ID:BIMI-Selector; b=bYCRFG/HZfWvoIZNfUQTJoOV+UW28LEywD5mDdFTERrW811mG8Wq2eYo6+4R9dlvf wvASNzsqKfPOvYu0jdPKnHJ2LQ9b5bJ/gZwThwzDM3DEX4ZeOYqulhpTuF9fcEfGMD kk/eWaha1MgRiekGsZsMmtUXKDiK1Oq7T+1gl/3kjJWfnhQeUpEi7t/SOpfEs9Ks+7 NQqIZyR/ABA/72zQDUEVNrnXUhthISu55rsF4laFpQSHn97ERjjrwoN4jWaHyLnuNB IGvtsbulZUvBSDmlBnhlCNrUB1IekgZ3J6oBc5ew0xczZUW40Sail1yjKYvGJ3dxzR zdBcPzkb4F9dA== X-Pm-Submission-Id: 4gX1zz1Gq6z1DFSh From: William Theesfeld To: Xingyu Wu Cc: Ziv Xu , Wim Van Sebroeck , Guenter Roeck , linux-watchdog@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 1/6] watchdog: starfive: balance PM refcount when start operation fails Date: Fri, 5 Jun 2026 09:11:50 -0400 Message-ID: X-Mailer: git-send-email 2.54.0 In-Reply-To: References: <20260605122336.159546-1-william@theesfeld.net> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" After pm_runtime_resume_and_get() succeeds in starfive_wdt_pm_start(), the runtime PM usage counter is incremented. If starfive_wdt_start() subsequently fails, the function returns the error without releasing that reference, leaking the usage counter. Call pm_runtime_put_sync() on the start failure path so the counter is balanced. This also folds in the v1 conversion of pm_runtime_get_sync() to pm_runtime_resume_and_get(), which was the original purpose of this patch; both fixes together close the refcount-leak window in this function as flagged by the maintainer on the v1 thread. Signed-off-by: William Theesfeld --- drivers/watchdog/starfive-wdt.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/starfive-wdt.c b/drivers/watchdog/starfive-wd= t.c index af55adc4a..ed8c5711a 100644 --- a/drivers/watchdog/starfive-wdt.c +++ b/drivers/watchdog/starfive-wdt.c @@ -371,12 +371,16 @@ static void starfive_wdt_stop(struct starfive_wdt *wd= t) static int starfive_wdt_pm_start(struct watchdog_device *wdd) { struct starfive_wdt *wdt =3D watchdog_get_drvdata(wdd); - int ret =3D pm_runtime_get_sync(wdd->parent); + int ret =3D pm_runtime_resume_and_get(wdd->parent); =20 if (ret < 0) return ret; =20 - return starfive_wdt_start(wdt); + ret =3D starfive_wdt_start(wdt); + if (ret) + pm_runtime_put_sync(wdd->parent); + + return ret; } =20 static int starfive_wdt_pm_stop(struct watchdog_device *wdd) --=20 2.54.0 From nobody Mon Jun 8 05:24:51 2026 Received: from mail-43171.protonmail.ch (mail-43171.protonmail.ch [185.70.43.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2781F3B14C8 for ; Fri, 5 Jun 2026 13:12:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.70.43.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780665132; cv=none; b=qrR+ZTWjnEA2ankosxQzOQIO+XNQS3JYaZQds8IpDiQG3Pcag5kjORUH7bN3sFUj8bCBAlVdQgda23lFkNNYHkwve45kMCTKyAgGhSkQk/gHmvSNqxaSpLr4YnjdDR7emOavNuM/WCEQ6FO3vkp62Qbh4F0IPrfmd0ZFMt4IV/U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780665132; c=relaxed/simple; bh=PR0LqjuezAQWrOubsNhn8MiAWagy5o3pKfuOGpAVcRY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=IqI+e8OIh2XIzo1diC6cmjTuUImxytLiGYjoMVNwSvM1Cp5aN0nKaHbRdlfCpGghdTwLyyia3nySbFNOdkjUzeccEa3RZG4j75DIWNQSVon+n1RfSBD5rUE5AH6cF15wSi/gh2NbGGd+tIcA4Z/66mmuz3vbSpLMTYsMVWtg//E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=theesfeld.net; spf=fail smtp.mailfrom=theesfeld.net; dkim=fail (0-bit key) header.d=theesfeld.net header.i=@theesfeld.net header.b=HxrSfdpv reason="key not found in DNS"; arc=none smtp.client-ip=185.70.43.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=theesfeld.net Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=theesfeld.net Authentication-Results: smtp.subspace.kernel.org; dkim=fail reason="key not found in DNS" (0-bit key) header.d=theesfeld.net header.i=@theesfeld.net header.b="HxrSfdpv" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=theesfeld.net; s=protonmail2; t=1780665123; x=1780924323; bh=v7CBWfDdEsACDlG8ioC8xdoQIRvy+Z9zowW0MU+qJvs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:From:To: Cc:Date:Subject:Reply-To:Feedback-ID:Message-ID:BIMI-Selector; b=HxrSfdpvqBlkD/X9wMDU1mDKEq+jurwUkxBJ3m05iLYs18L8nIAzEcQGycuGVyXv1 2KIq6sUXmD4DGoMgGJZvO1etPNkxoaF6ikQKi8L7Ta+Q25ybfVoxCoHEYycrYjArFW bPWccXx/6qYeMmtXJgAO8ol9+u9b1Mm5VWyLcBES2ZgDJEzvWavcz5YfcQ26+g48p9 LU+eK9oSxosRj2/g3hw3WqyvsgfacbJjND/YFleGP7DSTjOP7LJVasuwZ3DJu0WH29 yYe+mqYRkm1O1ZN/W81oyaMSPSmt07bj+q22q7mfsy00oshceFGDNTohgoINAcTdP6 AHwRTt5ZG3EjQ== X-Pm-Submission-Id: 4gX2014h4Qz1DFSq From: William Theesfeld To: Xingyu Wu Cc: Ziv Xu , Wim Van Sebroeck , Guenter Roeck , linux-watchdog@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 2/6] watchdog: starfive: treat pm_runtime_put_sync() positive return as success Date: Fri, 5 Jun 2026 09:11:51 -0400 Message-ID: X-Mailer: git-send-email 2.54.0 In-Reply-To: References: <20260605122336.159546-1-william@theesfeld.net> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" pm_runtime_put_sync() returns 1 when the device cannot be suspended because it is still in use (typically due to other runtime PM users holding references); only negative return values are real errors. Both starfive_wdt_pm_stop() and starfive_wdt_probe() currently treat any non-zero return as failure: pm_stop returns the value verbatim, which the watchdog framework propagates as an error, and probe takes the err_unregister_wdt path even on a successful but non-zero return. Mask off the positive return value in pm_stop and tighten the probe check to "< 0" so the legitimate non-suspended case is no longer mishandled. Signed-off-by: William Theesfeld --- drivers/watchdog/starfive-wdt.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/starfive-wdt.c b/drivers/watchdog/starfive-wd= t.c index ed8c5711a..c821b38d2 100644 --- a/drivers/watchdog/starfive-wdt.c +++ b/drivers/watchdog/starfive-wdt.c @@ -386,9 +386,17 @@ static int starfive_wdt_pm_start(struct watchdog_devic= e *wdd) static int starfive_wdt_pm_stop(struct watchdog_device *wdd) { struct starfive_wdt *wdt =3D watchdog_get_drvdata(wdd); + int ret; =20 starfive_wdt_stop(wdt); - return pm_runtime_put_sync(wdd->parent); + ret =3D pm_runtime_put_sync(wdd->parent); + /* + * pm_runtime_put_sync() can return 1 when the device is still in + * use (and therefore did not actually suspend). That is not an + * error from the caller's point of view; only propagate negative + * return values. + */ + return ret < 0 ? ret : 0; } =20 static int starfive_wdt_set_timeout(struct watchdog_device *wdd, @@ -503,7 +511,7 @@ static int starfive_wdt_probe(struct platform_device *p= dev) if (!early_enable) { if (pm_runtime_enabled(&pdev->dev)) { ret =3D pm_runtime_put_sync(&pdev->dev); - if (ret) + if (ret < 0) goto err_unregister_wdt; } } --=20 2.54.0 From nobody Mon Jun 8 05:24:51 2026 Received: from mail-244106.protonmail.ch (mail-244106.protonmail.ch [109.224.244.106]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B2A2F3382CB for ; Fri, 5 Jun 2026 13:12:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=109.224.244.106 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780665130; cv=none; b=FySi+yQ17nBK+F4QiqC0mhrqM/llFVHXqY06jETPgkoHPlC5xOc2cHiWW35OlWD/cEd4GUT+N8x/61ifZaf4xkvDqAPV3sjfIhI7TwyauLMGGIG78T7lF1A5rr6WHGUByX99ICNZZgADYG2QSq0AfAYwPcP+hZIx+SLJSy+pzLU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780665130; c=relaxed/simple; bh=5Ou2UWIsXRf5J1leh8L9HfwC/eZC+QTqHG4JBfxHCX4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RSKu2VI/fWnu7g2BLOkDzJ7TaBjt1jNSqRmLtk8Nm942JmXmbaoNNBLeutuExkeP+yuDxR3l5QikWKuhub4WPHs5qfGqqUfvGx4BiPDR7VJQf8bLXatm95mfi993adaFj+YvIAVEShtvARF4oNJM9DSz4jwn82z5F9Sy3vm4lKs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=theesfeld.net; spf=fail smtp.mailfrom=theesfeld.net; dkim=fail (0-bit key) header.d=theesfeld.net header.i=@theesfeld.net header.b=etW/9ZF1 reason="key not found in DNS"; arc=none smtp.client-ip=109.224.244.106 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=theesfeld.net Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=theesfeld.net Authentication-Results: smtp.subspace.kernel.org; dkim=fail reason="key not found in DNS" (0-bit key) header.d=theesfeld.net header.i=@theesfeld.net header.b="etW/9ZF1" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=theesfeld.net; s=protonmail2; t=1780665126; x=1780924326; bh=Oyj4FE/DQKQtHKcOpW57XDJVXp6PwZIsXvfERmGaalM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:From:To: Cc:Date:Subject:Reply-To:Feedback-ID:Message-ID:BIMI-Selector; b=etW/9ZF1M1h3SPuph049Irk9qZhsOb23HnJPVFx2QTsuE1KtgzHMpMc3oDba96aQm R+pmU0oEZgn/ySXcaAMHuBnEt+Qqyo3yuiwOYCP/hKZITqeV2lW9of/Z7H2I+me/Y6 snwIDtsPE9NsWdx/42XjYWzRa9XOaVWDGdKBmMPT+Ct1GmJN3RcRn4Y0BmoOgkv9VQ 9n3oZCyjsfZsK38LomTlKh8rmXi42ah7WgFK7ZVulC6CNHrx5y7pwBPqEfo+qxDLcO Au+AYqukh3DwE8a0oPdj3kB4jnEoewWc66mcvPDC3mL+AzO+F0AezgW8ZtrW6aVYl2 bz1HzH+8SP3qw== X-Pm-Submission-Id: 4gX2040WMNz1DFSn From: William Theesfeld To: Xingyu Wu Cc: Ziv Xu , Wim Van Sebroeck , Guenter Roeck , linux-watchdog@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 3/6] watchdog: starfive: balance PM refcount and disable in probe error paths Date: Fri, 5 Jun 2026 09:11:52 -0400 Message-ID: <21de4987785fbde29d23f5fde53dc1012e0ae768.1780664848.git.william@theesfeld.net> X-Mailer: git-send-email 2.54.0 In-Reply-To: References: <20260605122336.159546-1-william@theesfeld.net> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The probe path takes a runtime PM reference via pm_runtime_resume_and_get() (or enables the clocks directly when runtime PM is unavailable), but several error paths after that point do not release that reference before returning, and the two earliest error paths return without calling pm_runtime_disable() at all even though pm_runtime_enable() has already run. Restructure the error handling into three labels so every failure path balances exactly the resources it has acquired: err_pm_disable: pm_runtime_enable() ran but no clock/refcount was taken yet (resume_and_get / enable_clock failed). err_put_pm: clock or PM refcount is held; release it, then fall through to disable runtime PM. err_unregister_wdt: watchdog_register_device() succeeded; unregister before releasing the refcount. Update the in-function goto targets to use these labels and remove the early "return ret;" paths so pm_runtime_disable() is always run once pm_runtime_enable() has been called. Signed-off-by: William Theesfeld --- drivers/watchdog/starfive-wdt.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/watchdog/starfive-wdt.c b/drivers/watchdog/starfive-wd= t.c index c821b38d2..6539bf089 100644 --- a/drivers/watchdog/starfive-wdt.c +++ b/drivers/watchdog/starfive-wdt.c @@ -460,17 +460,17 @@ static int starfive_wdt_probe(struct platform_device = *pdev) if (pm_runtime_enabled(&pdev->dev)) { ret =3D pm_runtime_resume_and_get(&pdev->dev); if (ret < 0) - return ret; + goto err_pm_disable; } else { /* runtime PM is disabled but clocks need to be enabled */ ret =3D starfive_wdt_enable_clock(wdt); if (ret) - return ret; + goto err_pm_disable; } =20 ret =3D starfive_wdt_reset_init(&pdev->dev); if (ret) - goto err_exit; + goto err_put_pm; =20 watchdog_set_drvdata(&wdt->wdd, wdt); wdt->wdd.info =3D &starfive_wdt_info; @@ -482,7 +482,7 @@ static int starfive_wdt_probe(struct platform_device *p= dev) if (!wdt->freq) { dev_err(&pdev->dev, "get clock rate failed.\n"); ret =3D -EINVAL; - goto err_exit; + goto err_put_pm; } =20 wdt->wdd.min_timeout =3D 1; @@ -498,7 +498,7 @@ static int starfive_wdt_probe(struct platform_device *p= dev) if (early_enable) { ret =3D starfive_wdt_start(wdt); if (ret) - goto err_exit; + goto err_put_pm; set_bit(WDOG_HW_RUNNING, &wdt->wdd.status); } else { starfive_wdt_stop(wdt); @@ -506,7 +506,7 @@ static int starfive_wdt_probe(struct platform_device *p= dev) =20 ret =3D watchdog_register_device(&wdt->wdd); if (ret) - goto err_exit; + goto err_put_pm; =20 if (!early_enable) { if (pm_runtime_enabled(&pdev->dev)) { @@ -520,8 +520,12 @@ static int starfive_wdt_probe(struct platform_device *= pdev) =20 err_unregister_wdt: watchdog_unregister_device(&wdt->wdd); -err_exit: - starfive_wdt_disable_clock(wdt); +err_put_pm: + if (pm_runtime_enabled(&pdev->dev)) + pm_runtime_put_sync(&pdev->dev); + else + starfive_wdt_disable_clock(wdt); +err_pm_disable: pm_runtime_disable(&pdev->dev); =20 return ret; --=20 2.54.0 From nobody Mon Jun 8 05:24:51 2026 Received: from mail-43172.protonmail.ch (mail-43172.protonmail.ch [185.70.43.172]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DE28A336ECF; Fri, 5 Jun 2026 13:12:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.70.43.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780665131; cv=none; b=P6+T9HyE5XU4mlzdTRk3U4y2THEYdkipmdjlJG96vyza57PdDM7bIeAQQ2ysv+iW2HGNG5kA+GOUGs7o3kNtMaHvA+vsB/fo7m5Gr2ocu9QcqAZ7NX4zkA5El7QhBJVfulDtYE2a//1qHeJYmh69qhJlGystH7cBfDCzbeIuQn0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780665131; c=relaxed/simple; bh=sarV9ZnJceZxz4q6gqxxsk1ZLAhzHDUNx3scqu+cfko=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=BU0yGMkqw9guUA/NUHcpT843JXWDVsOlr83j1CqTE2+7iG8BorOrc90tBhG1Iwq2zDo+jHxccXZQlO5w3ash6EtKuXiFuNMN4oFuXLy1CZ3a8VUdWQNVfGNfsNg2Brgeo6QmOb318pCGxYeA5dATtz/x6EhCHjKE9rdfxUPfg6M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=theesfeld.net; spf=fail smtp.mailfrom=theesfeld.net; dkim=fail (0-bit key) header.d=theesfeld.net header.i=@theesfeld.net header.b=cYZ5nrr8 reason="key not found in DNS"; arc=none smtp.client-ip=185.70.43.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=theesfeld.net Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=theesfeld.net Authentication-Results: smtp.subspace.kernel.org; dkim=fail reason="key not found in DNS" (0-bit key) header.d=theesfeld.net header.i=@theesfeld.net header.b="cYZ5nrr8" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=theesfeld.net; s=protonmail2; t=1780665128; x=1780924328; bh=5qNukEK/rBUeJ+sg8uGW3tFF+vu84wXy1cVEbIckFns=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:From:To: Cc:Date:Subject:Reply-To:Feedback-ID:Message-ID:BIMI-Selector; b=cYZ5nrr8G6nWCjqbtvXGZXHfWBTZGfBKcLLQr0zZJdsX7M3DRyilO0/p+CyxeQejp y8r/8+pOa75OpcNM5/h3JLrnACQMyA2IQpTmATdcWYgm/IRo70TDV0pDBbGhRycJ96 BmcU87g0Vk6Gd+grg7T10CqvVY04LZKptbVVHC/sqr83QqPWfCWDB9IS1ey/nvqz+A Or5fVJpC/PSdVyW02CBPScxhjMFrj6E3ps8NyL4zeVKw8ZyosNDQKecJ9Nln8KMETh 818/X2e5ROMWPbrv73SBdGmrYkaOEDtvaPoTK4SsZhIZ0kI9xIM5YdTPeyHujn+JE3 ZSzC82v/D6SAw== X-Pm-Submission-Id: 4gX2055Gprz1DFSh From: William Theesfeld To: Xingyu Wu Cc: Ziv Xu , Wim Van Sebroeck , Guenter Roeck , linux-watchdog@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 4/6] watchdog: starfive: guard system suspend/resume hardware access Date: Fri, 5 Jun 2026 09:11:53 -0400 Message-ID: X-Mailer: git-send-email 2.54.0 In-Reply-To: References: <20260605122336.159546-1-william@theesfeld.net> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" starfive_wdt_suspend() reads from STARFIVE_WDT_VALUE and writes to WDOGCONTROL via starfive_wdt_get_count() and starfive_wdt_stop() before calling pm_runtime_force_suspend(). If the device was already runtime-suspended when system suspend began, the apb and core clocks are gated and those register accesses produce a synchronous external abort. starfive_wdt_resume() has the mirror problem: it unconditionally restores the WDOGLOAD value after pm_runtime_force_resume() returns, but pm_runtime_force_resume() leaves the device in whichever runtime PM state it was in pre-suspend. If the device stays suspended, the restore writes race with gated clocks. Gate both halves with pm_runtime_status_suspended() so the hardware is only touched when it is actually active. When the watchdog was suspended at runtime PM level there is no state to save or restore. Signed-off-by: William Theesfeld --- drivers/watchdog/starfive-wdt.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/drivers/watchdog/starfive-wdt.c b/drivers/watchdog/starfive-wd= t.c index 6539bf089..4926984bf 100644 --- a/drivers/watchdog/starfive-wdt.c +++ b/drivers/watchdog/starfive-wdt.c @@ -556,11 +556,16 @@ static int starfive_wdt_suspend(struct device *dev) { struct starfive_wdt *wdt =3D dev_get_drvdata(dev); =20 - /* Save watchdog state, and turn it off. */ - wdt->reload =3D starfive_wdt_get_count(wdt); - - /* Note that WTCNT doesn't need to be saved. */ - starfive_wdt_stop(wdt); + /* + * Only access the hardware while the device is runtime-resumed; if + * runtime PM has already suspended the device, its clocks are gated + * and a register read/write would trigger a synchronous external + * abort. WTCNT does not need to be saved. + */ + if (!pm_runtime_status_suspended(dev)) { + wdt->reload =3D starfive_wdt_get_count(wdt); + starfive_wdt_stop(wdt); + } =20 return pm_runtime_force_suspend(dev); } @@ -574,8 +579,16 @@ static int starfive_wdt_resume(struct device *dev) if (ret) return ret; =20 + /* + * pm_runtime_force_resume() leaves the device in whichever runtime + * PM state it was in before system suspend. Only restore hardware + * state when the device is actually resumed; otherwise the register + * writes below would race with gated clocks. + */ + if (pm_runtime_status_suspended(dev)) + return 0; + starfive_wdt_unlock(wdt); - /* Restore watchdog state. */ starfive_wdt_set_reload_count(wdt, wdt->reload); starfive_wdt_lock(wdt); =20 --=20 2.54.0 From nobody Mon Jun 8 05:24:51 2026 Received: from mail-106113.protonmail.ch (mail-106113.protonmail.ch [79.135.106.113]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D53F83DB300; Fri, 5 Jun 2026 13:12:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=79.135.106.113 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780665134; cv=none; b=JYnLLxR+57Az4hAnMSRWuJaoxizMXwrxyzRxZoQcV/bdnN1wvDz05KWphIO1EB61KCgDv1HOgG6FHc256z4t8R3nGMG/Mthb2zW44yOrdUMZKWBJZ6Pvlc3Rh2PmMo1/9kPcrCfwHMg2hw8yH4Z1VKt3yQ3wnOFkmfvTnEklebU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780665134; c=relaxed/simple; bh=SndQsFKzfUAF6PDEXcFmKRk0KRajgFY+eCK6F1ndD90=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Uc+8nBT6kDWUDsgCnNnGgXNYR2+cjI/BDh6TPNIEFil31zqSq9cxUBJAf9L77CU+WusqcGEI3bWnb0O1hIiMCZVnJBEaIoF4syRAm8pGvbnYNajxhSJuhUqrRHs9s9xOJXGrcx7xow6BPxhz5UN7MRfJkE5XJsXSB3bVeJrfN6o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=theesfeld.net; spf=fail smtp.mailfrom=theesfeld.net; dkim=fail (0-bit key) header.d=theesfeld.net header.i=@theesfeld.net header.b=1ayrrRhP reason="key not found in DNS"; arc=none smtp.client-ip=79.135.106.113 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=theesfeld.net Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=theesfeld.net Authentication-Results: smtp.subspace.kernel.org; dkim=fail reason="key not found in DNS" (0-bit key) header.d=theesfeld.net header.i=@theesfeld.net header.b="1ayrrRhP" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=theesfeld.net; s=protonmail2; t=1780665130; x=1780924330; bh=ZmWBEBsS6wSxsZ3LY4CY6OHjojI2S0R+xj1CQoxBMNk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:From:To: Cc:Date:Subject:Reply-To:Feedback-ID:Message-ID:BIMI-Selector; b=1ayrrRhP790LLqs55VwPJOOrck1KxXRbDGXX/NqThsz3FLHkoogkreqX0CxEnecGZ Qz+2EPQRtKCGUh5QhWA+00Tt4sjiFlpEwuK2A3vsyfkVq3K/bQ8KPEICId2d/utQfp lD4BoZT25CnYtAH+1IWh4VOpVcH+oY16CccI3r/Pct9DyhcO9SRHflz3joypImtxIZ HP65DWtVmMPZQgwOoUEhUUdysoKBYdRniBXS9Ij3WwP3aBfh00Sd2Q9x8rw4YdTPk3 QGp74Gp6pffV69YlaIp9qak94dSdicjjAnngpKYPeONQR27+ddtwh9OW5sYvnoV128 8CPbI8hmB61CA== X-Pm-Submission-Id: 4gX20820Ywz1DFSm From: William Theesfeld To: Xingyu Wu Cc: Ziv Xu , Wim Van Sebroeck , Guenter Roeck , linux-watchdog@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 5/6] watchdog: starfive: avoid PM refcount underflow in shutdown Date: Fri, 5 Jun 2026 09:11:54 -0400 Message-ID: X-Mailer: git-send-email 2.54.0 In-Reply-To: References: <20260605122336.159546-1-william@theesfeld.net> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" starfive_wdt_shutdown() unconditionally calls starfive_wdt_pm_stop(), which drops a runtime PM reference via pm_runtime_put_sync(). If the device was never opened (so there was no matching pm_start()), and early_enable is also off (so probe already balanced its own get/put), the counter is at zero and put_sync() drives it negative. Only call pm_stop() when WDOG_ACTIVE is set (meaning a paired pm_start() happened on open). For the early_enable-and-never-opened case, the framework state is WDOG_HW_RUNNING without WDOG_ACTIVE; in that case stop just the hardware so the watchdog does not keep ticking through shutdown, while leaving the PM refcount for the remove path to release. Signed-off-by: William Theesfeld --- drivers/watchdog/starfive-wdt.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/watchdog/starfive-wdt.c b/drivers/watchdog/starfive-wd= t.c index 4926984bf..848935dc6 100644 --- a/drivers/watchdog/starfive-wdt.c +++ b/drivers/watchdog/starfive-wdt.c @@ -549,7 +549,19 @@ static void starfive_wdt_shutdown(struct platform_devi= ce *pdev) { struct starfive_wdt *wdt =3D platform_get_drvdata(pdev); =20 - starfive_wdt_pm_stop(&wdt->wdd); + /* + * Only drop a runtime PM reference when we actually hold one. The + * watchdog framework increments it via pm_start() on open; when + * early_enable started the hardware without an open, the reference + * was taken at probe time and the framework state reads as + * WDOG_HW_RUNNING without WDOG_ACTIVE. In the inactive-and-not- + * running case there is nothing for us to do and dropping the + * counter unconditionally would underflow it. + */ + if (watchdog_active(&wdt->wdd)) + starfive_wdt_pm_stop(&wdt->wdd); + else if (test_bit(WDOG_HW_RUNNING, &wdt->wdd.status)) + starfive_wdt_stop(wdt); } =20 static int starfive_wdt_suspend(struct device *dev) --=20 2.54.0 From nobody Mon Jun 8 05:24:51 2026 Received: from mail-43170.protonmail.ch (mail-43170.protonmail.ch [185.70.43.170]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6A8854F798A; Fri, 5 Jun 2026 13:12:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.70.43.170 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780665138; cv=none; b=ZJB8ZoJEkoa3T/PNqs6RPDixc9iCJo6rsxv3emllf1IojzMvGmHXqCbuR8KzbXBip/kL+QT8HBLHTs/qQNJmT7VzqUNuQcc7Zuwf32AtsH/UAPbtnO6aaDB9uuJm54UGydMAqdhw2Crp5fZ/WWUhyVc3ZqD4onfFi54W2KX2db4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780665138; c=relaxed/simple; bh=NAFUSSgnlQ4pMbtcP9tBqMKeCzvjYGIetfdKT6rzPes=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rBAYnSuPw5xP2pTl6Iy/hbyEJuJIW2wWjUoR9WWxEbT9TvxybCdUDLYs8ApOys9nwUahv7Mep8twPM5GIKGHz0pf1zZHhbHkqh57M4S26HCMQow3I0ND1d9xfdrqVt3mG8cJ6OWR8cfnoXuV7uP3pqsksGncMJdwU5pXTvjZrxk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=theesfeld.net; spf=fail smtp.mailfrom=theesfeld.net; dkim=fail (0-bit key) header.d=theesfeld.net header.i=@theesfeld.net header.b=ugD5mCCZ reason="key not found in DNS"; arc=none smtp.client-ip=185.70.43.170 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=theesfeld.net Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=theesfeld.net Authentication-Results: smtp.subspace.kernel.org; dkim=fail reason="key not found in DNS" (0-bit key) header.d=theesfeld.net header.i=@theesfeld.net header.b="ugD5mCCZ" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=theesfeld.net; s=protonmail2; t=1780665132; x=1780924332; bh=UB1CHAWwfhnxd5b6vqbN6UybwRRnHYPv9ADzmVFG8Us=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:From:To: Cc:Date:Subject:Reply-To:Feedback-ID:Message-ID:BIMI-Selector; b=ugD5mCCZZGwng5KKAH71wIgmeEBR7Xn2j8qQYyh8G1KUPezsFXeqT4orGw59cQWQR mPmjuHCrUoSAw882bwrx8ZcJD3ex37v5mbcxGfJQoCTmMK3+WrfHGbx3U6MJQdlLkI y5Vz01N8UBP7XR69tzEGq2oDCj/nwZaPT57gOm/bJnir+CA4ByFpE2F+c7hiwMqr9i AbbkPGAQjiLX/hxy2Lbr3XDJR4D3lZigquIN6thdMvllq70Prr4PPaFtWeVnL/nfkl I0WIHWTxhcaPLDVPtKIMI45+L3k+mZtTBH5P1HbAWARBHVQoVvj0ctaEfWBQqBcpOX fTt6/gTvqEfLw== X-Pm-Submission-Id: 4gX20B54Xxz1DFSh From: William Theesfeld To: Xingyu Wu Cc: Ziv Xu , Wim Van Sebroeck , Guenter Roeck , linux-watchdog@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 6/6] watchdog: starfive: release early_enable PM refcount on remove Date: Fri, 5 Jun 2026 09:11:55 -0400 Message-ID: <57fe44ec9b838cdde9245b706f42053472efcade.1780664848.git.william@theesfeld.net> X-Mailer: git-send-email 2.54.0 In-Reply-To: References: <20260605122336.159546-1-william@theesfeld.net> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" When early_enable starts the hardware at probe time, the runtime PM reference taken by pm_runtime_resume_and_get() is intentionally kept to hold the device runtime-resumed. In the normal (userspace-opened) case the watchdog framework unwinds that reference via pm_stop() on close, and again via stop_on_unregister() during watchdog_unregister_device(). But watchdog_unregister_device() only runs the stop path when WDOG_ACTIVE is set (see drivers/watchdog/watchdog_dev.c). If early_enable started the hardware and userspace never opened it, WDOG_HW_RUNNING is set without WDOG_ACTIVE: unregister returns without touching pm_stop, and the probe-time PM reference is leaked. Drop that reference in starfive_wdt_remove() before pm_runtime_disable() runs, when WDOG_HW_RUNNING is still asserted. Signed-off-by: William Theesfeld --- drivers/watchdog/starfive-wdt.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/watchdog/starfive-wdt.c b/drivers/watchdog/starfive-wd= t.c index 848935dc6..d9175b045 100644 --- a/drivers/watchdog/starfive-wdt.c +++ b/drivers/watchdog/starfive-wdt.c @@ -538,6 +538,19 @@ static void starfive_wdt_remove(struct platform_device= *pdev) starfive_wdt_stop(wdt); watchdog_unregister_device(&wdt->wdd); =20 + /* + * watchdog_unregister_device() only calls our pm_stop op when + * WDOG_ACTIVE is set. When early_enable started the hardware at + * probe time and userspace never opened the watchdog, the framework + * state is WDOG_HW_RUNNING without WDOG_ACTIVE: the unregister path + * leaves the runtime PM reference taken at probe outstanding. Drop + * it here before disabling runtime PM so the usage counter does not + * leak. + */ + if (test_bit(WDOG_HW_RUNNING, &wdt->wdd.status) && + pm_runtime_enabled(&pdev->dev)) + pm_runtime_put_sync(&pdev->dev); + if (pm_runtime_enabled(&pdev->dev)) pm_runtime_disable(&pdev->dev); else --=20 2.54.0