From f5e1cc9a284bff2510981643a5bca4bc4c21b81a Mon Sep 17 00:00:00 2001 From: Di Shen Date: Mon, 27 Apr 2026 20:00:47 +0800 Subject: [PATCH 1/3] OPP: Fix race between OPP addition and lookup A race exists between dev_pm_opp_add_dynamic() and dev_pm_opp_find_freq_exact(): CPU0 (add) CPU1 (lookup) ------------------------------- ------------------------------ _opp_add() mutex_lock() list_add(&new_opp->node, head) mutex_unlock() _opp_table_find_key() mutex_lock() dev_pm_opp_get(opp) kref_get() mutex_unlock() kref_init(&new_opp->kref) dev_pm_opp_put() kref_put_mutex() The newly added OPP is inserted into the list before its kref is initialized. A concurrent lookup can find this OPP and increment its reference count while it is still uninitialized, leading to refcount corruption and a potential premature free. Fix this by initializing ->kref and ->opp_table before making the OPP visible via list_add(). This ensures any concurrent lookup observes a fully initialized object. Fixes: 7034764a1e4a (PM / OPP: Add 'struct kref' to struct dev_pm_opp) Co-developed-by: Ling Xu Signed-off-by: Ling Xu Signed-off-by: Di Shen [ Viresh: Updated commit log ] Signed-off-by: Viresh Kumar --- drivers/opp/core.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/opp/core.c b/drivers/opp/core.c index da3f5eba4341..ab0b0a2f85a1 100644 --- a/drivers/opp/core.c +++ b/drivers/opp/core.c @@ -2088,11 +2088,10 @@ int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, return ret; list_add(&new_opp->node, head); + new_opp->opp_table = opp_table; + kref_init(&new_opp->kref); } - new_opp->opp_table = opp_table; - kref_init(&new_opp->kref); - opp_debug_create_one(new_opp, opp_table); if (!_opp_supported_by_regulators(new_opp, opp_table)) { From 69f888381d2ecbe18ed9f112c096f8fd3623db98 Mon Sep 17 00:00:00 2001 From: Abdun Nihaal Date: Mon, 11 May 2026 12:12:11 +0530 Subject: [PATCH 2/3] OPP: of: Fix potential memory leak in opp_parse_supplies() The memory allocated for microvolt, microamp and microwatt is not freed in one of the paths in opp_parse_supplies() which returns directly. Fix that by adding a goto to the error unwind ladder. Fixes: 2eedf62e66c2 ("OPP: decouple dt properties in opp_parse_supplies()") Cc: stable@vger.kernel.org Signed-off-by: Abdun Nihaal Signed-off-by: Viresh Kumar --- drivers/opp/of.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/opp/of.c b/drivers/opp/of.c index f96adfd5b219..c02e20632fa6 100644 --- a/drivers/opp/of.c +++ b/drivers/opp/of.c @@ -673,7 +673,7 @@ static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev, */ if (unlikely(opp_table->regulator_count == -1)) { opp_table->regulator_count = 0; - return 0; + goto free_microwatt; } for (i = 0, j = 0; i < opp_table->regulator_count; i++) { @@ -696,6 +696,7 @@ static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev, opp->supplies[i].u_watt = microwatt[i]; } +free_microwatt: kfree(microwatt); free_microamp: kfree(microamp); From b59020834b2d8718fe37a4e77367f554cbf95982 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Antinori?= Date: Sun, 24 May 2026 12:40:16 -0300 Subject: [PATCH 3/3] opp: rust: mark OPP methods as inline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When building the kernel using llvm-19.1.7-rust-1.85.0-x86_64, the following symbols are generated: $ nm vmlinux | grep ' _R'.*OPP | rustfilt ffffffff81801560 T ::freq ffffffff81801540 T ::dec_ref ffffffff81801520 T ::inc_ref However, these Rust symbols are trivial wrappers around the `dev_pm_opp_get`, `dev_pm_opp_put` and `dev_pm_opp_get_freq_indexed` functions. It doesn't make sense to go through a trivial wrapper for these functions. After applying this patch, the above command will produce no output. Link: https://github.com/Rust-for-Linux/linux/issues/1145 Suggested-by: Alice Ryhl Signed-off-by: Nicolás Antinori Signed-off-by: Viresh Kumar --- rust/kernel/opp.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rust/kernel/opp.rs b/rust/kernel/opp.rs index a760fac28765..62e44676125d 100644 --- a/rust/kernel/opp.rs +++ b/rust/kernel/opp.rs @@ -1042,11 +1042,13 @@ unsafe impl Sync for OPP {} /// SAFETY: The type invariants guarantee that [`OPP`] is always refcounted. unsafe impl AlwaysRefCounted for OPP { + #[inline] fn inc_ref(&self) { // SAFETY: The existence of a shared reference means that the refcount is nonzero. unsafe { bindings::dev_pm_opp_get(self.0.get()) }; } + #[inline] unsafe fn dec_ref(obj: ptr::NonNull) { // SAFETY: The safety requirements guarantee that the refcount is nonzero. unsafe { bindings::dev_pm_opp_put(obj.cast().as_ptr()) } @@ -1095,6 +1097,7 @@ fn as_raw(&self) -> *mut bindings::dev_pm_opp { } /// Returns the frequency of an [`OPP`]. + #[inline] pub fn freq(&self, index: Option) -> Hertz { let index = index.unwrap_or(0);