summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorGregor Herburger <gregor.herburger@linutronix.de>2026-07-15 09:35:36 +0200
committerViresh Kumar <viresh.kumar@linaro.org>2026-07-15 13:57:34 +0530
commitce46fede7792cedd247e34b48bc8a02eb90c7848 (patch)
treef28058fde80c498a2c5cd214844e072ff9501bdd /drivers
parentdc59e4fea9d83f03bad6bddf3fa2e52491777482 (diff)
downloadlinux-next-ce46fede7792cedd247e34b48bc8a02eb90c7848.tar.gz
linux-next-ce46fede7792cedd247e34b48bc8a02eb90c7848.zip
OPP: Fix cleanup ordering
Commit 173e02d67494 ("OPP: Initialize scope-based pointers inline") added initialization for all pointers. In some cases, the ordering was changed so that *opp_table was initialized after *opp. This also changes the order of the registered cleanup functions. When the cleanup happens, this can cause use-after-free errors when the last reference is released and the release function _opp_kref_release tries to access the already freed opp->opp_table. Initialize *opp_table before *opp again to fix this and ensure the correct cleanup order. Fixes: 173e02d67494 ("OPP: Initialize scope-based pointers inline") Signed-off-by: Gregor Herburger <gregor.herburger@linutronix.de> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/opp/core.c13
1 files changed, 5 insertions, 8 deletions
diff --git a/drivers/opp/core.c b/drivers/opp/core.c
index ab0b0a2f85a1..b6966e509f7d 100644
--- a/drivers/opp/core.c
+++ b/drivers/opp/core.c
@@ -1412,13 +1412,12 @@ static int _set_opp(struct device *dev, struct opp_table *opp_table,
*/
int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)
{
+ struct opp_table *opp_table __free(put_opp_table) =
+ _find_opp_table(dev);
struct dev_pm_opp *opp __free(put_opp) = NULL;
unsigned long freq = 0, temp_freq;
bool forced = false;
- struct opp_table *opp_table __free(put_opp_table) =
- _find_opp_table(dev);
-
if (IS_ERR(opp_table)) {
dev_err(dev, "%s: device's opp table doesn't exist\n", __func__);
return PTR_ERR(opp_table);
@@ -2870,11 +2869,10 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_add_dynamic);
static int _opp_set_availability(struct device *dev, unsigned long freq,
bool availability_req)
{
- struct dev_pm_opp *opp __free(put_opp) = ERR_PTR(-ENODEV), *tmp_opp;
-
/* Find the opp_table */
struct opp_table *opp_table __free(put_opp_table) =
_find_opp_table(dev);
+ struct dev_pm_opp *opp __free(put_opp) = ERR_PTR(-ENODEV), *tmp_opp;
if (IS_ERR(opp_table)) {
dev_warn(dev, "%s: Device OPP not found (%ld)\n", __func__,
@@ -2932,12 +2930,11 @@ int dev_pm_opp_adjust_voltage(struct device *dev, unsigned long freq,
unsigned long u_volt_max)
{
- struct dev_pm_opp *opp __free(put_opp) = ERR_PTR(-ENODEV), *tmp_opp;
- int r;
-
/* Find the opp_table */
struct opp_table *opp_table __free(put_opp_table) =
_find_opp_table(dev);
+ struct dev_pm_opp *opp __free(put_opp) = ERR_PTR(-ENODEV), *tmp_opp;
+ int r;
if (IS_ERR(opp_table)) {
r = PTR_ERR(opp_table);