From patchwork Thu Dec 1 10:25:40 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 86001 Delivered-To: patch@linaro.org Received: by 10.140.20.101 with SMTP id 92csp622695qgi; Thu, 1 Dec 2016 02:25:55 -0800 (PST) X-Received: by 10.99.36.65 with SMTP id k62mr66979284pgk.13.1480587955607; Thu, 01 Dec 2016 02:25:55 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id o33si40154963plb.86.2016.12.01.02.25.55; Thu, 01 Dec 2016 02:25:55 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-pm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org; spf=pass (google.com: best guess record for domain of linux-pm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-pm-owner@vger.kernel.org; dmarc=fail (p=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756141AbcLAKZy (ORCPT + 13 others); Thu, 1 Dec 2016 05:25:54 -0500 Received: from mail-pg0-f53.google.com ([74.125.83.53]:35489 "EHLO mail-pg0-f53.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755413AbcLAKZx (ORCPT ); Thu, 1 Dec 2016 05:25:53 -0500 Received: by mail-pg0-f53.google.com with SMTP id p66so93761362pga.2 for ; Thu, 01 Dec 2016 02:25:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=Y6Y7jurI7XUKeaP0ps3J9ihILkRAFHKW9jqSYe9vlX4=; b=HH8d5QHyXBu1eBjoOrGPRuSZL9DAOY9mOEzp96LXdWCkYvDt3GNWXIhKmmUFA35PFO 3Igvhjs7NAleckZN/CBHoVt/ZwijcFxHiKdUvMAkf7gZEcWWueWMYwxqxcnDWp+fnfhZ aO0lv4SITxCwkcP0wT5iHy3JDKlHSiTWXiOmY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=Y6Y7jurI7XUKeaP0ps3J9ihILkRAFHKW9jqSYe9vlX4=; b=ARm2JuToN60Tn+dNKCmE7HkvS7XHMm+4eL1MkL2ZEhf3257QmnsSwDi+bBYBruGNQe DDTJgINjqm5CrslW8aU1YTHwq3FHro9ilWgk5Cbx283mwnML5ZSrMOQjyBD94zRQUsaU cpFXm2rQtYFAmqzi9ePeHA247DgbaxSx4CTFxnXhxIhBEVJEmr/C9++57hW4PYZpnisY oItMSyFkjkop6VVeNRl49xff1srEJtt5U8efmACLg6NZxyEoeoKjNeCnht9CBEZWbSeE 8FSniM6nOlL4kvvkSx8VI2bZZRVX8UomTXO0h13s6+A/e3KLjLbwuLMgm9g+lvZtpNhA MnEQ== X-Gm-Message-State: AKaTC02stVTU1hN4RR3P9pqo9IcSsMq0/xQOskZ+XtUAWrkgSkGIL+idw5kp21ye5Vp6UaOM X-Received: by 10.84.216.24 with SMTP id m24mr11279191pli.26.1480587952677; Thu, 01 Dec 2016 02:25:52 -0800 (PST) Received: from localhost ([122.172.143.30]) by smtp.gmail.com with ESMTPSA id q145sm109462636pfq.22.2016.12.01.02.25.51 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 01 Dec 2016 02:25:52 -0800 (PST) From: Viresh Kumar To: Rafael Wysocki , Chanwoo Choi , MyungJoo Ham , Kyungmin Park , Kukjin Kim , Krzysztof Kozlowski , Javier Martinez Canillas Cc: linaro-kernel@lists.linaro.org, linux-pm@vger.kernel.org, Stephen Boyd , nm@ti.com, Vincent Guittot , Viresh Kumar Subject: [PATCH] devfreq: exynos: Don't use OPP structures outside of RCU locks Date: Thu, 1 Dec 2016 15:55:40 +0530 Message-Id: <9cb02ef0037c8d161f7b57ff3e99c2831661da03.1480587838.git.viresh.kumar@linaro.org> X-Mailer: git-send-email 2.7.1.410.g6faf27b Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org The OPP structures are abused to the best here, without understanding how the OPP core and RCU locks work. In short, the OPP pointer saved 'struct exynos_bus' can become invalid under your nose, as the OPP core may free it. Fix various abuses around OPP structures and calls. Compile tested only. Signed-off-by: Viresh Kumar --- I would like it to go via the PM tree. Perhaps that's already the default tree for this. drivers/devfreq/exynos-bus.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) -- 2.7.1.410.g6faf27b -- To unsubscribe from this list: send the line "unsubscribe linux-pm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Acked-by: Chanwoo Choi Tested-by: Chanwoo Choi diff --git a/drivers/devfreq/exynos-bus.c b/drivers/devfreq/exynos-bus.c index 29866f7e6d7e..a8ed7792ece2 100644 --- a/drivers/devfreq/exynos-bus.c +++ b/drivers/devfreq/exynos-bus.c @@ -35,7 +35,7 @@ struct exynos_bus { unsigned int edev_count; struct mutex lock; - struct dev_pm_opp *curr_opp; + unsigned long curr_freq; struct regulator *regulator; struct clk *clk; @@ -99,7 +99,7 @@ static int exynos_bus_target(struct device *dev, unsigned long *freq, u32 flags) { struct exynos_bus *bus = dev_get_drvdata(dev); struct dev_pm_opp *new_opp; - unsigned long old_freq, new_freq, old_volt, new_volt, tol; + unsigned long old_freq, new_freq, new_volt, tol; int ret = 0; /* Get new opp-bus instance according to new bus clock */ @@ -113,8 +113,7 @@ static int exynos_bus_target(struct device *dev, unsigned long *freq, u32 flags) new_freq = dev_pm_opp_get_freq(new_opp); new_volt = dev_pm_opp_get_voltage(new_opp); - old_freq = dev_pm_opp_get_freq(bus->curr_opp); - old_volt = dev_pm_opp_get_voltage(bus->curr_opp); + old_freq = bus->curr_freq; rcu_read_unlock(); if (old_freq == new_freq) @@ -146,7 +145,7 @@ static int exynos_bus_target(struct device *dev, unsigned long *freq, u32 flags) goto out; } } - bus->curr_opp = new_opp; + bus->curr_freq = new_freq; dev_dbg(dev, "Set the frequency of bus (%lukHz -> %lukHz)\n", old_freq/1000, new_freq/1000); @@ -163,9 +162,7 @@ static int exynos_bus_get_dev_status(struct device *dev, struct devfreq_event_data edata; int ret; - rcu_read_lock(); - stat->current_frequency = dev_pm_opp_get_freq(bus->curr_opp); - rcu_read_unlock(); + stat->current_frequency = bus->curr_freq; ret = exynos_bus_get_event(bus, &edata); if (ret < 0) { @@ -226,7 +223,7 @@ static int exynos_bus_passive_target(struct device *dev, unsigned long *freq, } new_freq = dev_pm_opp_get_freq(new_opp); - old_freq = dev_pm_opp_get_freq(bus->curr_opp); + old_freq = bus->curr_freq; rcu_read_unlock(); if (old_freq == new_freq) @@ -242,7 +239,7 @@ static int exynos_bus_passive_target(struct device *dev, unsigned long *freq, } *freq = new_freq; - bus->curr_opp = new_opp; + bus->curr_freq = new_freq; dev_dbg(dev, "Set the frequency of bus (%lukHz -> %lukHz)\n", old_freq/1000, new_freq/1000); @@ -335,6 +332,7 @@ static int exynos_bus_parse_of(struct device_node *np, struct exynos_bus *bus) { struct device *dev = bus->dev; + struct dev_pm_opp *opp; unsigned long rate; int ret; @@ -352,22 +350,23 @@ static int exynos_bus_parse_of(struct device_node *np, } /* Get the freq and voltage from OPP table to scale the bus freq */ - rcu_read_lock(); ret = dev_pm_opp_of_add_table(dev); if (ret < 0) { dev_err(dev, "failed to get OPP table\n"); - rcu_read_unlock(); goto err_clk; } rate = clk_get_rate(bus->clk); - bus->curr_opp = devfreq_recommended_opp(dev, &rate, 0); - if (IS_ERR(bus->curr_opp)) { + + rcu_read_lock(); + opp = devfreq_recommended_opp(dev, &rate, 0); + if (IS_ERR(opp)) { dev_err(dev, "failed to find dev_pm_opp\n"); rcu_read_unlock(); - ret = PTR_ERR(bus->curr_opp); + ret = PTR_ERR(opp); goto err_opp; } + bus->curr_freq = dev_pm_opp_get_freq(opp); rcu_read_unlock(); return 0;