From patchwork Mon Jan 23 04:41:52 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 9531733 X-Patchwork-Delegate: rjw@sisk.pl Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id DC4EE6020B for ; Mon, 23 Jan 2017 04:42:57 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CEB50279E0 for ; Mon, 23 Jan 2017 04:42:57 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C395B27D76; Mon, 23 Jan 2017 04:42:57 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 385EA279E0 for ; Mon, 23 Jan 2017 04:42:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751241AbdAWEmv (ORCPT ); Sun, 22 Jan 2017 23:42:51 -0500 Received: from mail-pf0-f172.google.com ([209.85.192.172]:35729 "EHLO mail-pf0-f172.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751234AbdAWEmt (ORCPT ); Sun, 22 Jan 2017 23:42:49 -0500 Received: by mail-pf0-f172.google.com with SMTP id f144so37890017pfa.2 for ; Sun, 22 Jan 2017 20:42:43 -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:in-reply-to:references :in-reply-to:references; bh=meO9LJVJida1h3ED3NyON6qDluj9n22qERf/EUiYDpw=; b=b59ATkD82fgd3XKrVIBQ99TpsZs2BJjE/kldAefd4qCg5nlFplmY9KHv3fnFuVuj2F nRFQDPTi8SFBSgu5aCjpSlmW73Wl3LMjtJ6jXOY7/iq/ffiVPx/YEqOZS5SVCBJmaMxI N508e0/75Qc4PfpeegpnmcJLCthgiCrkkpdgY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=meO9LJVJida1h3ED3NyON6qDluj9n22qERf/EUiYDpw=; b=gX8XG9LQnWUKVoaZ8L+0/ef8FFW1PtdC8wVb/fIkOG7yevRHQPFsHO07YNIjf+uMS9 INr8MS8nVBvJbsTR0BtWBmUDQq+d6mCrrb687ILQzntsURPYJV14jrtod0ooIw4llMP+ pxCKKhaos3CuaPGQBi4sfZATuGMqYpyTU+fR+CrLDD9q+CLD4rNO5uqsjqHJX+ni5uR/ kEdis0q2gY4elMlkCPcATu031h2D3C+7Zm4DtK5j+sxSN3Vt1HsyBaNvMq4fJUIzRGXg 5URjFjZ4OSziex+41xeDj8PRBoLwRU1bycZWWt9qlFwhDT761oCKnzZ/DAoNP4F1EFSZ NRFQ== X-Gm-Message-State: AIkVDXKgyr/3u23R4xR9NAKg3IBYLJw5cE4BMC1Of7lc7Y15rWH/qaqkw5bsEUdFkETtZkAt X-Received: by 10.84.198.3 with SMTP id o3mr40260558pld.170.1485146563393; Sun, 22 Jan 2017 20:42:43 -0800 (PST) Received: from localhost ([122.171.65.82]) by smtp.gmail.com with ESMTPSA id q19sm32746123pfl.21.2017.01.22.20.42.42 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 22 Jan 2017 20:42:42 -0800 (PST) From: Viresh Kumar To: Rafael Wysocki , Viresh Kumar , Nishanth Menon , Stephen Boyd , Len Brown , Pavel Machek Cc: linaro-kernel@lists.linaro.org, linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org, Vincent Guittot , Viresh Kumar Subject: [PATCH V2 12/12] PM / OPP: Update Documentation to remove RCU specific bits Date: Mon, 23 Jan 2017 10:11:52 +0530 Message-Id: <7dbda15ca13e5343c3dce2c624a57b389e3e5e77.1485146406.git.viresh.kumar@linaro.org> X-Mailer: git-send-email 2.7.1.410.g6faf27b In-Reply-To: References: In-Reply-To: References: Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Update OPP documentation to remove the RCU specific bits. Signed-off-by: Viresh Kumar Reviewed-by: Stephen Boyd --- Documentation/power/opp.txt | 52 ++++++++++++++------------------------------- 1 file changed, 16 insertions(+), 36 deletions(-) diff --git a/Documentation/power/opp.txt b/Documentation/power/opp.txt index c6279c2be47c..0c007e250cd1 100644 --- a/Documentation/power/opp.txt +++ b/Documentation/power/opp.txt @@ -79,22 +79,6 @@ dependent subsystems such as cpufreq are left to the discretion of the SoC specific framework which uses the OPP library. Similar care needs to be taken care to refresh the cpufreq table in cases of these operations. -WARNING on OPP List locking mechanism: -------------------------------------------------- -OPP library uses RCU for exclusivity. RCU allows the query functions to operate -in multiple contexts and this synchronization mechanism is optimal for a read -intensive operations on data structure as the OPP library caters to. - -To ensure that the data retrieved are sane, the users such as SoC framework -should ensure that the section of code operating on OPP queries are locked -using RCU read locks. The opp_find_freq_{exact,ceil,floor}, -opp_get_{voltage, freq, opp_count} fall into this category. - -opp_{add,enable,disable} are updaters which use mutex and implement it's own -RCU locking mechanisms. These functions should *NOT* be called under RCU locks -and other contexts that prevent blocking functions in RCU or mutex operations -from working. - 2. Initial OPP List Registration ================================ The SoC implementation calls dev_pm_opp_add function iteratively to add OPPs per @@ -137,15 +121,18 @@ functions return the matching pointer representing the opp if a match is found, else returns error. These errors are expected to be handled by standard error checks such as IS_ERR() and appropriate actions taken by the caller. +Callers of these functions shall call dev_pm_opp_put() after they have used the +OPP. Otherwise the memory for the OPP will never get freed and result in +memleak. + dev_pm_opp_find_freq_exact - Search for an OPP based on an *exact* frequency and availability. This function is especially useful to enable an OPP which is not available by default. Example: In a case when SoC framework detects a situation where a higher frequency could be made available, it can use this function to find the OPP prior to call the dev_pm_opp_enable to actually make it available. - rcu_read_lock(); opp = dev_pm_opp_find_freq_exact(dev, 1000000000, false); - rcu_read_unlock(); + dev_pm_opp_put(opp); /* dont operate on the pointer.. just do a sanity check.. */ if (IS_ERR(opp)) { pr_err("frequency not disabled!\n"); @@ -163,9 +150,8 @@ dev_pm_opp_find_freq_floor - Search for an available OPP which is *at most* the frequency. Example: To find the highest opp for a device: freq = ULONG_MAX; - rcu_read_lock(); - dev_pm_opp_find_freq_floor(dev, &freq); - rcu_read_unlock(); + opp = dev_pm_opp_find_freq_floor(dev, &freq); + dev_pm_opp_put(opp); dev_pm_opp_find_freq_ceil - Search for an available OPP which is *at least* the provided frequency. This function is useful while searching for a @@ -173,17 +159,15 @@ dev_pm_opp_find_freq_ceil - Search for an available OPP which is *at least* the frequency. Example 1: To find the lowest opp for a device: freq = 0; - rcu_read_lock(); - dev_pm_opp_find_freq_ceil(dev, &freq); - rcu_read_unlock(); + opp = dev_pm_opp_find_freq_ceil(dev, &freq); + dev_pm_opp_put(opp); Example 2: A simplified implementation of a SoC cpufreq_driver->target: soc_cpufreq_target(..) { /* Do stuff like policy checks etc. */ /* Find the best frequency match for the req */ - rcu_read_lock(); opp = dev_pm_opp_find_freq_ceil(dev, &freq); - rcu_read_unlock(); + dev_pm_opp_put(opp); if (!IS_ERR(opp)) soc_switch_to_freq_voltage(freq); else @@ -208,9 +192,8 @@ dev_pm_opp_enable - Make a OPP available for operation. implementation might choose to do something as follows: if (cur_temp < temp_low_thresh) { /* Enable 1GHz if it was disabled */ - rcu_read_lock(); opp = dev_pm_opp_find_freq_exact(dev, 1000000000, false); - rcu_read_unlock(); + dev_pm_opp_put(opp); /* just error check */ if (!IS_ERR(opp)) ret = dev_pm_opp_enable(dev, 1000000000); @@ -224,9 +207,8 @@ dev_pm_opp_disable - Make an OPP to be not available for operation choose to do something as follows: if (cur_temp > temp_high_thresh) { /* Disable 1GHz if it was enabled */ - rcu_read_lock(); opp = dev_pm_opp_find_freq_exact(dev, 1000000000, true); - rcu_read_unlock(); + dev_pm_opp_put(opp); /* just error check */ if (!IS_ERR(opp)) ret = dev_pm_opp_disable(dev, 1000000000); @@ -249,10 +231,9 @@ dev_pm_opp_get_voltage - Retrieve the voltage represented by the opp pointer. soc_switch_to_freq_voltage(freq) { /* do things */ - rcu_read_lock(); opp = dev_pm_opp_find_freq_ceil(dev, &freq); v = dev_pm_opp_get_voltage(opp); - rcu_read_unlock(); + dev_pm_opp_put(opp); if (v) regulator_set_voltage(.., v); /* do other things */ @@ -266,12 +247,12 @@ dev_pm_opp_get_freq - Retrieve the freq represented by the opp pointer. { /* do things.. */ max_freq = ULONG_MAX; - rcu_read_lock(); max_opp = dev_pm_opp_find_freq_floor(dev,&max_freq); requested_opp = dev_pm_opp_find_freq_ceil(dev,&freq); if (!IS_ERR(max_opp) && !IS_ERR(requested_opp)) r = soc_test_validity(max_opp, requested_opp); - rcu_read_unlock(); + dev_pm_opp_put(max_opp); + dev_pm_opp_put(requested_opp); /* do other things */ } soc_test_validity(..) @@ -289,7 +270,6 @@ dev_pm_opp_get_opp_count - Retrieve the number of available opps for a device soc_notify_coproc_available_frequencies() { /* Do things */ - rcu_read_lock(); num_available = dev_pm_opp_get_opp_count(dev); speeds = kzalloc(sizeof(u32) * num_available, GFP_KERNEL); /* populate the table in increasing order */ @@ -298,8 +278,8 @@ dev_pm_opp_get_opp_count - Retrieve the number of available opps for a device speeds[i] = freq; freq++; i++; + dev_pm_opp_put(opp); } - rcu_read_unlock(); soc_notify_coproc(AVAILABLE_FREQs, speeds, num_available); /* Do other things */