From nobody Sat Jun 13 14:47:56 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 89F853EBF2F for ; Wed, 6 May 2026 15:38:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778081935; cv=none; b=ZBBh+1U2tlcnFyy/0nSjehfahL9S06ZDflyI6x+sSly0anBk1tLyXxZ29tWLf4x4zyuzOtUvueiBjBcvJ6m+YiTHT2BKmUDUDOD9ZdAGHR3bkfqjXlFQiNVqPdQVCauGhBqJJCXZgo0zpyZIX0gPqWvfhk50iBx7YLtLYFXaaS8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778081935; c=relaxed/simple; bh=FK2qd6k2lUSHvhXYucAV47L5SGF8mrfwsm9xSzuKOF8=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=tddSWtMEYGSaIHFvO0wHmNgN39/Rve81zor/lwUOx8ne93l9hebx+aKTx++56NYDtZsgJzdBds0LMnAsI8gqzswugXdBHbBfyTdUv6C5yoO33XheKNDcy7M+ny9BzEGDTOFzCy/gBP3IAUBfEKFCChK2/lC/6oZB71D/m7urLGo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5C92FC2BCF4; Wed, 6 May 2026 15:38:54 +0000 (UTC) From: Daniel Lezcano To: jstultz@google.com, tglx@kernel.org, sboyd@kernel.org Cc: linux-kernel@vger.kernel.org Subject: [PATCH] clocksource: add devm_clocksource_register_*() helpers Date: Wed, 6 May 2026 17:38:31 +0200 Message-ID: <20260506153831.605159-1-daniel.lezcano@oss.qualcomm.com> X-Mailer: git-send-email 2.43.0 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" Introduce device-managed helpers for clocksource registration. The clocksource framework currently provides __clocksource_register_scale() along with convenience wrappers for Hz and kHz registration. However, drivers must handle error paths and cleanup manually, typically by pairing registration with an explicit clocksource_unregister() call. Add a devm-based variant, __devm_clocksource_register_scale(), along with devm_clocksource_register_hz() and devm_clocksource_register_khz() helpers. These helpers register the clocksource and attach a devres action to automatically unregister it on driver detach or probe failure. This simplifies driver code by: * removing explicit cleanup paths * ensuring correct teardown ordering * aligning with the devm-based resource management model widely used across the kernel While drivers can open-code devm_add_action_or_reset(), providing a dedicated helper avoids duplication, reduces boilerplate, and ensures consistent usage across drivers, following patterns used in other subsystems. This is also particularly useful for drivers built as modules, where device-managed resource handling avoids manual cleanup in remove paths and ensures correct teardown on module unload. This helper is self-contained and can be adopted progressively by drivers. No functional change. Signed-off-by: Daniel Lezcano Signed-off-by: Daniel Lezcano --- include/linux/clocksource.h | 15 +++++++++++++++ kernel/time/clocksource.c | 20 ++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h index 7c38190b10bf..c5b34c16602e 100644 --- a/include/linux/clocksource.h +++ b/include/linux/clocksource.h @@ -236,6 +236,9 @@ clocks_calc_mult_shift(u32 *mult, u32 *shift, u32 from,= u32 to, u32 minsec); */ extern int __clocksource_register_scale(struct clocksource *cs, u32 scale, u32 freq); +extern int +__devm_clocksource_register_scale(struct device *dev, struct clocksource *= cs, + u32 scale, u32 freq); extern void __clocksource_update_freq_scale(struct clocksource *cs, u32 scale, u32 fre= q); =20 @@ -258,6 +261,18 @@ static inline int clocksource_register_khz(struct cloc= ksource *cs, u32 khz) return __clocksource_register_scale(cs, 1000, khz); } =20 +static inline int devm_clocksource_register_hz(struct device *dev, + struct clocksource *cs, u32 hz) +{ + return __devm_clocksource_register_scale(dev, cs, 1, hz); +} + +static inline int devm_clocksource_register_khz(struct device *dev, + struct clocksource *cs, u32 khz) +{ + return __devm_clocksource_register_scale(dev, cs, 1000, khz); +} + static inline void __clocksource_update_freq_hz(struct clocksource *cs, u3= 2 hz) { __clocksource_update_freq_scale(cs, 1, hz); diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index baee13a1f87f..313f6c88148e 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c @@ -1338,6 +1338,26 @@ int __clocksource_register_scale(struct clocksource = *cs, u32 scale, u32 freq) } EXPORT_SYMBOL_GPL(__clocksource_register_scale); =20 +static void __devm_clocksource_unregister(void *data) +{ + struct clocksource *cs =3D data; + + clocksource_unregister(cs); +} + +int __devm_clocksource_register_scale(struct device *dev, struct clocksour= ce *cs, + u32 scale, u32 freq) +{ + int ret; + + ret =3D __clocksource_register_scale(cs, scale, freq); + if (ret) + return ret; + + return devm_add_action_or_reset(dev, __devm_clocksource_unregister, cs); +} +EXPORT_SYMBOL_GPL(__devm_clocksource_register_scale); + /* * Unbind clocksource @cs. Called with clocksource_mutex held */ --=20 2.43.0