From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-10.1 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 87EB5C17440 for ; Wed, 13 Nov 2019 01:51:16 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 6114D222D4 for ; Wed, 13 Nov 2019 01:51:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1573609876; bh=/h7+WxnT0pQCjhRylNYlpEwLKKiUKIyEzlcqA3+++JY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=dgumQ2hRj1VIWX8fs5UKJWmbMKm5elX0UohkahpT6ABea6gcG/kpiLXurppuTVF9d 0iQ/ViV3Q1eQD84kcTmeBc8qvuQinI2AWsYw9k/vcD66UYq0q82/G3zvttbElSinsK oG+RZgfkw6WOc+mmC+gxBbkwEOsAqr8kZy6S6OSY= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727746AbfKMBvP (ORCPT ); Tue, 12 Nov 2019 20:51:15 -0500 Received: from mail.kernel.org ([198.145.29.99]:38360 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727656AbfKMBvG (ORCPT ); Tue, 12 Nov 2019 20:51:06 -0500 Received: from sasha-vm.mshome.net (c-73-47-72-35.hsd1.nh.comcast.net [73.47.72.35]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 0A453222CA; Wed, 13 Nov 2019 01:51:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1573609864; bh=/h7+WxnT0pQCjhRylNYlpEwLKKiUKIyEzlcqA3+++JY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=xJF0xJB8N7CIABKRJ1RF/rwnjqLS/390yyjrGIWi7xYNNeMgPnfnKMDWFycUcS5UW k5I2+3pR6oQtEwC++duKf8V3ho+BMipzqBuxZpZAJJ1Sg0Yqywe66gcvlMNcJUDzxc 7NMhKSILvHZbrvqLrCNjO67C7qTtVecaqm6qxpKk= From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Matthias Kaehlcke , Brian Norris , Chanwoo Choi , MyungJoo Ham , Sasha Levin , linux-pm@vger.kernel.org Subject: [PATCH AUTOSEL 4.19 030/209] PM / devfreq: Fix handling of min/max_freq == 0 Date: Tue, 12 Nov 2019 20:47:26 -0500 Message-Id: <20191113015025.9685-30-sashal@kernel.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191113015025.9685-1-sashal@kernel.org> References: <20191113015025.9685-1-sashal@kernel.org> MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Matthias Kaehlcke [ Upstream commit df5cf4a36178c5d4f2b8b9469cb2f722e64cd102 ] Commit ab8f58ad72c4 ("PM / devfreq: Set min/max_freq when adding the devfreq device") initializes df->min/max_freq with the min/max OPP when the device is added. Later commit f1d981eaecf8 ("PM / devfreq: Use the available min/max frequency") adds df->scaling_min/max_freq and the following to the frequency adjustment code: max_freq = MIN(devfreq->scaling_max_freq, devfreq->max_freq); With the current handling of min/max_freq this is incorrect: Even though df->max_freq is now initialized to a value != 0 user space can still set it to 0, in this case max_freq would be 0 instead of df->scaling_max_freq as intended. In consequence the frequency adjustment is not performed: if (max_freq && freq > max_freq) { freq = max_freq; To fix this set df->min/max freq to the min/max OPP in max/max_freq_store, when the user passes a value of 0. This also prevents df->max_freq from being set below the min OPP when df->min_freq is 0, and similar for min_freq. Since it is now guaranteed that df->min/max_freq can't be 0 the checks for this case can be removed. Fixes: f1d981eaecf8 ("PM / devfreq: Use the available min/max frequency") Signed-off-by: Matthias Kaehlcke Reviewed-by: Brian Norris Reviewed-by: Chanwoo Choi Signed-off-by: MyungJoo Ham Signed-off-by: Sasha Levin --- drivers/devfreq/devfreq.c | 42 ++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 62ead442a8721..8e21bedc74c38 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -327,11 +327,11 @@ int update_devfreq(struct devfreq *devfreq) max_freq = MIN(devfreq->scaling_max_freq, devfreq->max_freq); min_freq = MAX(devfreq->scaling_min_freq, devfreq->min_freq); - if (min_freq && freq < min_freq) { + if (freq < min_freq) { freq = min_freq; flags &= ~DEVFREQ_FLAG_LEAST_UPPER_BOUND; /* Use GLB */ } - if (max_freq && freq > max_freq) { + if (freq > max_freq) { freq = max_freq; flags |= DEVFREQ_FLAG_LEAST_UPPER_BOUND; /* Use LUB */ } @@ -1171,17 +1171,26 @@ static ssize_t min_freq_store(struct device *dev, struct device_attribute *attr, struct devfreq *df = to_devfreq(dev); unsigned long value; int ret; - unsigned long max; ret = sscanf(buf, "%lu", &value); if (ret != 1) return -EINVAL; mutex_lock(&df->lock); - max = df->max_freq; - if (value && max && value > max) { - ret = -EINVAL; - goto unlock; + + if (value) { + if (value > df->max_freq) { + ret = -EINVAL; + goto unlock; + } + } else { + unsigned long *freq_table = df->profile->freq_table; + + /* Get minimum frequency according to sorting order */ + if (freq_table[0] < freq_table[df->profile->max_state - 1]) + value = freq_table[0]; + else + value = freq_table[df->profile->max_state - 1]; } df->min_freq = value; @@ -1206,17 +1215,26 @@ static ssize_t max_freq_store(struct device *dev, struct device_attribute *attr, struct devfreq *df = to_devfreq(dev); unsigned long value; int ret; - unsigned long min; ret = sscanf(buf, "%lu", &value); if (ret != 1) return -EINVAL; mutex_lock(&df->lock); - min = df->min_freq; - if (value && min && value < min) { - ret = -EINVAL; - goto unlock; + + if (value) { + if (value < df->min_freq) { + ret = -EINVAL; + goto unlock; + } + } else { + unsigned long *freq_table = df->profile->freq_table; + + /* Get maximum frequency according to sorting order */ + if (freq_table[0] < freq_table[df->profile->max_state - 1]) + value = freq_table[df->profile->max_state - 1]; + else + value = freq_table[0]; } df->max_freq = value; -- 2.20.1