From patchwork Thu Feb 22 05:59:44 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 10234685 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 18BD560224 for ; Thu, 22 Feb 2018 06:00:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 125FC288BC for ; Thu, 22 Feb 2018 06:00:18 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 06B30288C4; Thu, 22 Feb 2018 06:00:18 +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=-7.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, RCVD_IN_DNSWL_HI autolearn=unavailable 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 74F24288BC for ; Thu, 22 Feb 2018 06:00:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752453AbeBVGAD (ORCPT ); Thu, 22 Feb 2018 01:00:03 -0500 Received: from mail-pl0-f67.google.com ([209.85.160.67]:33051 "EHLO mail-pl0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752460AbeBVGAA (ORCPT ); Thu, 22 Feb 2018 01:00:00 -0500 Received: by mail-pl0-f67.google.com with SMTP id x18so2363276pln.0 for ; Wed, 21 Feb 2018 22:00:00 -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=ICxF2yRTvWAPYGtY+eFFxrFkiw7ewW7Go8F1UDvV3s4=; b=kkhP55bq/udTOzQoPx6hKzESc1wYQbiepKQ3qtPwDbMYRyxYxMhWW81soz/fVFg7uF rX+KFk5L39X9Lob/eAhYoYELQxv+WsHnZFO/m7Yd2kDvbo0K2wioesYMrtRWN3hvBg7e 25ycwLFmYUvdaorjd72xwLAkTEf/9OiZiw3Fc= 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=ICxF2yRTvWAPYGtY+eFFxrFkiw7ewW7Go8F1UDvV3s4=; b=C+sCo1dnyGW1a90NysmYVb7ytT5ZSQcfUevyol1AZDacVA9JSfmCqbV5844cZ1ea7F PY3OtmsDbmqOUrx5OxBhvqTUVBWwgNcXGKjyueL6dFyujtYdiAfdWUhDvgNKXskOBsB1 ttn/2i4LIeo5YHxM1xAYdnEtqQiXN2RwjU0wa5JWCt7/lfgeGB/XCtGEo2bE7fEK0oKz tbwhN3UcY7rhA0sgQyDVGS+5mVciZM5U+WfXutyUlLdan7w1qoa5CnoZNS0vI/XjZZOY Tn5L+00SXIy7aIPijvsmbcNxLmwJMoYyHnOnje0Ob5Du2WmM/RwwGilzTHGryCebDTo/ 8Kxw== X-Gm-Message-State: APf1xPCUX9wvN3V+yOGGep3f+/rKQaAgunoYWMzHbqSxE//ne+IdjJrU yLdsuR/AkowpyQQkTqRADtlObA== X-Google-Smtp-Source: AH8x224ZgdIp9nl9GKboLD3/Ljf40+v3OOK9lxkqIZl857ZbvSMjmjjFOQLttzcHI6XzRX74uUFNxg== X-Received: by 2002:a17:902:14b:: with SMTP id 69-v6mr5573619plb.209.1519279200385; Wed, 21 Feb 2018 22:00:00 -0800 (PST) Received: from localhost ([122.167.232.138]) by smtp.gmail.com with ESMTPSA id y4sm49421942pfm.16.2018.02.21.21.59.59 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 21 Feb 2018 21:59:59 -0800 (PST) From: Viresh Kumar To: Rafael Wysocki Cc: Viresh Kumar , linux-pm@vger.kernel.org, Vincent Guittot , Michael Ellerman , linux-kernel@vger.kernel.org Subject: [PATCH 2/2] cpufreq: Validate cpufreq table from core Date: Thu, 22 Feb 2018 11:29:44 +0530 Message-Id: X-Mailer: git-send-email 2.15.0.194.g9af6a3dea062 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 By design, it is responsibility of the cpufreq drivers to call cpufreq_frequency_table_cpuinfo() from their ->init() callback to validate the cpufreq table. But what if the cpufreq driver is buggy and fails to do so properly? It may then result in unexpected behavior from the driver or the cpufreq core at a later point of time. It would be better if the core can validate the cpufreq table at the initial stage. This commit adds another routine cpufreq_table_validate_and_sort() and calls it right after calling the ->init() callback of the driver and destroys the cpufreq policy if the table is invalid. For the moment the validation of the table happens twice, once from the driver and then from the core. The individual drivers would be updated separately to drop table validation if they don't need it for other purposes. The cpufreq table is marked "sorted" or "unsorted" from the new helper now instead of cpufreq_table_validate_and_show(), as we should be doing that only after validating the table (which the drivers wouldn't do going forward). Signed-off-by: Viresh Kumar --- drivers/cpufreq/cpufreq.c | 13 +++++++++---- drivers/cpufreq/freq_table.c | 16 +++++++++++++++- include/linux/cpufreq.h | 1 + 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 8814c572e263..239063fb6afc 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1219,6 +1219,10 @@ static int cpufreq_online(unsigned int cpu) goto out_free_policy; } + ret = cpufreq_table_validate_and_sort(policy); + if (ret) + goto out_exit_policy; + down_write(&policy->rwsem); if (new_policy) { @@ -1249,7 +1253,7 @@ static int cpufreq_online(unsigned int cpu) policy->cur = cpufreq_driver->get(policy->cpu); if (!policy->cur) { pr_err("%s: ->get() failed\n", __func__); - goto out_exit_policy; + goto out_destroy_policy; } } @@ -1296,7 +1300,7 @@ static int cpufreq_online(unsigned int cpu) if (new_policy) { ret = cpufreq_add_dev_interface(policy); if (ret) - goto out_exit_policy; + goto out_destroy_policy; cpufreq_stats_create_table(policy); @@ -1311,7 +1315,7 @@ static int cpufreq_online(unsigned int cpu) __func__, cpu, ret); /* cpufreq_policy_free() will notify based on this */ new_policy = false; - goto out_exit_policy; + goto out_destroy_policy; } up_write(&policy->rwsem); @@ -1326,12 +1330,13 @@ static int cpufreq_online(unsigned int cpu) return 0; -out_exit_policy: +out_destroy_policy: for_each_cpu(j, policy->real_cpus) remove_cpu_dev_symlink(policy, get_cpu_device(j)); up_write(&policy->rwsem); +out_exit_policy: if (cpufreq_driver->exit) cpufreq_driver->exit(policy); diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c index 6d007f824ca7..10e119ae66dd 100644 --- a/drivers/cpufreq/freq_table.c +++ b/drivers/cpufreq/freq_table.c @@ -362,10 +362,24 @@ int cpufreq_table_validate_and_show(struct cpufreq_policy *policy, return ret; policy->freq_table = table; - return set_freq_table_sorted(policy); + return 0; } EXPORT_SYMBOL_GPL(cpufreq_table_validate_and_show); +int cpufreq_table_validate_and_sort(struct cpufreq_policy *policy) +{ + int ret; + + if (!policy->freq_table) + return 0; + + ret = cpufreq_frequency_table_cpuinfo(policy, policy->freq_table); + if (ret) + return ret; + + return set_freq_table_sorted(policy); +} + MODULE_AUTHOR("Dominik Brodowski "); MODULE_DESCRIPTION("CPUfreq frequency table helpers"); MODULE_LICENSE("GPL"); diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 21e8d248d956..1fe49724da9e 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -962,6 +962,7 @@ extern struct freq_attr cpufreq_freq_attr_scaling_boost_freqs; extern struct freq_attr *cpufreq_generic_attr[]; int cpufreq_table_validate_and_show(struct cpufreq_policy *policy, struct cpufreq_frequency_table *table); +int cpufreq_table_validate_and_sort(struct cpufreq_policy *policy); unsigned int cpufreq_generic_get(unsigned int cpu); int cpufreq_generic_init(struct cpufreq_policy *policy,