From patchwork Mon Jan 2 09:10:55 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 89461 Delivered-To: patch@linaro.org Received: by 10.140.20.101 with SMTP id 92csp7497711qgi; Mon, 2 Jan 2017 01:11:26 -0800 (PST) X-Received: by 10.84.140.133 with SMTP id 5mr88840885plt.162.1483348286188; Mon, 02 Jan 2017 01:11:26 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 79si65202907pfr.34.2017.01.02.01.11.25; Mon, 02 Jan 2017 01:11:26 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932227AbdABJLV (ORCPT + 25 others); Mon, 2 Jan 2017 04:11:21 -0500 Received: from mail-pg0-f44.google.com ([74.125.83.44]:33315 "EHLO mail-pg0-f44.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755440AbdABJLS (ORCPT ); Mon, 2 Jan 2017 04:11:18 -0500 Received: by mail-pg0-f44.google.com with SMTP id g1so162962235pgn.0 for ; Mon, 02 Jan 2017 01:11:18 -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=Xo1GtKtrdvkZTGtobSb3qajz0S6hJDa4DBKqsQxMqiw=; b=agBnQQCiEAAZOc/rtSYHgYDAgcLEXSy5WDwPFJkjK8EmggrytbQJbBQSTQ//EcxfjY dkr6pnvfOzECJUqrMx5YFhPiGkF9zu0qoxQ6NMax6uIfSPXs3VEelMU7od1DnVHG4v00 8ZjXvZVhGwm83VOyJECDrk+zyo8nrguzMphzA= 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=Xo1GtKtrdvkZTGtobSb3qajz0S6hJDa4DBKqsQxMqiw=; b=BNIWwwJ4FmFC3t7daWCkC0YqX9/Snp+f3DwJs/2/nCch5FGLsmyr0EfLKAsYBs7Nxa apuasVPFtXkbnWtvLn/D+NIO5jlI3a7dYwOvRMNYh04OI4dpFYoAPgO/0J+zwydLZTzI HYoqxb0EkF8M6f8LJXzPMKb/94oGMpLzy4Y5toRMTuE8EX8cUs4KN5gDK+vkDedFbnDW KBnFep5Ha6EJ6M9cjyfL+xbb5ujZ9Tl45+bPd2a0WhH2Gez9GenbgxS9uTCjZE/SedWL yHDhPVqKkWmq/xQkS96dh56gJhqu97q5usRaerDKjU9lJh1Kv328qozBoHHyOQvonIA6 FcTw== X-Gm-Message-State: AIkVDXIZjtNND2uTR5MdT51l2gLcyAcLEGrQbH5PD2PDqdNGxwIFfhrN+m08V8tXfvaKRYPh X-Received: by 10.84.128.67 with SMTP id 61mr51164021pla.153.1483348277556; Mon, 02 Jan 2017 01:11:17 -0800 (PST) Received: from localhost ([122.172.43.83]) by smtp.gmail.com with ESMTPSA id w5sm130474958pfl.31.2017.01.02.01.11.16 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 02 Jan 2017 01:11:16 -0800 (PST) From: Viresh Kumar To: Rafael Wysocki , Viresh Kumar , Nishanth Menon , Stephen Boyd Cc: linaro-kernel@lists.linaro.org, linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org, Vincent Guittot , Viresh Kumar Subject: [PATCH V3 01/10] PM / OPP: Fix memory leak while adding duplicate OPPs Date: Mon, 2 Jan 2017 14:40:55 +0530 Message-Id: <83cb1a5f9d4b8e957a6e875e2391d6349b158dae.1483348138.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-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org There are two types of duplicate OPPs that get different behavior from the core: A) An earlier OPP is marked 'available' and has same freq/voltages as the new one. B) An earlier OPP with same frequency, but is marked 'unavailable' OR doesn't have same voltages as the new one. The OPP core returns 0 for the first one, but -EEXIST for the second. While the OPP core returns 0 for the first case, its callers don't free the newly allocated OPP structure which isn't used anymore. Fix that by returning -EBUSY instead of 0, but make the callers return 0 eventually. As this isn't a critical fix, its not getting marked for stable kernel. Signed-off-by: Viresh Kumar Reviewed-by: Stephen Boyd --- drivers/base/power/opp/core.c | 18 ++++++++++++++++-- drivers/base/power/opp/of.c | 6 +++++- 2 files changed, 21 insertions(+), 3 deletions(-) -- 2.7.1.410.g6faf27b diff --git a/drivers/base/power/opp/core.c b/drivers/base/power/opp/core.c index 35ff06283738..a8a5e01b7756 100644 --- a/drivers/base/power/opp/core.c +++ b/drivers/base/power/opp/core.c @@ -1067,6 +1067,16 @@ static bool _opp_supported_by_regulators(struct dev_pm_opp *opp, return true; } +/* + * Returns: + * 0: On success. And appropriate error message for duplicate OPPs. + * -EBUSY: For OPP with same freq/volt and is available. The callers of + * _opp_add() must return 0 if they receive -EBUSY from it. This is to make + * sure we don't print error messages unnecessarily if different parts of + * kernel try to initialize the OPP table. + * -EEXIST: For OPP with same freq but different volt or is unavailable. This + * should be considered an error by the callers of _opp_add(). + */ int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, struct opp_table *opp_table) { @@ -1099,7 +1109,7 @@ int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, /* Should we compare voltages for all regulators here ? */ return opp->available && - new_opp->supplies[0].u_volt == opp->supplies[0].u_volt ? 0 : -EEXIST; + new_opp->supplies[0].u_volt == opp->supplies[0].u_volt ? -EBUSY : -EEXIST; } new_opp->opp_table = opp_table; @@ -1173,8 +1183,12 @@ int _opp_add_v1(struct device *dev, unsigned long freq, long u_volt, new_opp->dynamic = dynamic; ret = _opp_add(dev, new_opp, opp_table); - if (ret) + if (ret) { + /* Don't return error for duplicate OPPs */ + if (ret == -EBUSY) + ret = 0; goto free_opp; + } mutex_unlock(&opp_table_lock); diff --git a/drivers/base/power/opp/of.c b/drivers/base/power/opp/of.c index 3f7d2591b173..356c75edd656 100644 --- a/drivers/base/power/opp/of.c +++ b/drivers/base/power/opp/of.c @@ -327,8 +327,12 @@ static int _opp_add_static_v2(struct device *dev, struct device_node *np) goto free_opp; ret = _opp_add(dev, new_opp, opp_table); - if (ret) + if (ret) { + /* Don't return error for duplicate OPPs */ + if (ret == -EBUSY) + ret = 0; goto free_opp; + } /* OPP to select on device suspend */ if (of_property_read_bool(np, "opp-suspend")) {