Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934191AbdCJLYS (ORCPT ); Fri, 10 Mar 2017 06:24:18 -0500 Received: from mail.linuxfoundation.org ([140.211.169.12]:37470 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S934041AbdCJJTa (ORCPT ); Fri, 10 Mar 2017 04:19:30 -0500 From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Chanwoo Choi , MyungJoo Ham Subject: [PATCH 4.9 052/153] PM / devfreq: Fix available_governor sysfs Date: Fri, 10 Mar 2017 10:08:05 +0100 Message-Id: <20170310083950.187045919@linuxfoundation.org> X-Mailer: git-send-email 2.12.0 In-Reply-To: <20170310083947.108106897@linuxfoundation.org> References: <20170310083947.108106897@linuxfoundation.org> User-Agent: quilt/0.65 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3523 Lines: 104 4.9-stable review patch. If anyone has any objections, please let me know. ------------------ From: Chanwoo Choi commit bcf23c79c4e46130701370af4383b61a3cba755c upstream. The devfreq using passive governor is not able to change the governor. So, the user can not change the governor through 'available_governor' sysfs entry. Also, the devfreq which don't use the passive governor is not able to change to 'passive' governor on the fly. Fixes: 996133119f57 ("PM / devfreq: Add new passive governor") Signed-off-by: Chanwoo Choi Signed-off-by: MyungJoo Ham Signed-off-by: Greg Kroah-Hartman --- drivers/devfreq/devfreq.c | 31 +++++++++++++++++++++++++++---- drivers/devfreq/governor_passive.c | 1 + include/linux/devfreq.h | 3 +++ 3 files changed, 31 insertions(+), 4 deletions(-) --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -939,6 +939,9 @@ static ssize_t governor_store(struct dev if (df->governor == governor) { ret = 0; goto out; + } else if (df->governor->immutable || governor->immutable) { + ret = -EINVAL; + goto out; } if (df->governor) { @@ -968,13 +971,33 @@ static ssize_t available_governors_show( struct device_attribute *attr, char *buf) { - struct devfreq_governor *tmp_governor; + struct devfreq *df = to_devfreq(d); ssize_t count = 0; mutex_lock(&devfreq_list_lock); - list_for_each_entry(tmp_governor, &devfreq_governor_list, node) - count += scnprintf(&buf[count], (PAGE_SIZE - count - 2), - "%s ", tmp_governor->name); + + /* + * The devfreq with immutable governor (e.g., passive) shows + * only own governor. + */ + if (df->governor->immutable) { + count = scnprintf(&buf[count], DEVFREQ_NAME_LEN, + "%s ", df->governor_name); + /* + * The devfreq device shows the registered governor except for + * immutable governors such as passive governor . + */ + } else { + struct devfreq_governor *governor; + + list_for_each_entry(governor, &devfreq_governor_list, node) { + if (governor->immutable) + continue; + count += scnprintf(&buf[count], (PAGE_SIZE - count - 2), + "%s ", governor->name); + } + } + mutex_unlock(&devfreq_list_lock); /* Truncate the trailing space */ --- a/drivers/devfreq/governor_passive.c +++ b/drivers/devfreq/governor_passive.c @@ -179,6 +179,7 @@ static int devfreq_passive_event_handler static struct devfreq_governor devfreq_passive = { .name = "passive", + .immutable = 1, .get_target_freq = devfreq_passive_get_target_freq, .event_handler = devfreq_passive_event_handler, }; --- a/include/linux/devfreq.h +++ b/include/linux/devfreq.h @@ -104,6 +104,8 @@ struct devfreq_dev_profile { * struct devfreq_governor - Devfreq policy governor * @node: list node - contains registered devfreq governors * @name: Governor's name + * @immutable: Immutable flag for governor. If the value is 1, + * this govenror is never changeable to other governor. * @get_target_freq: Returns desired operating frequency for the device. * Basically, get_target_freq will run * devfreq_dev_profile.get_dev_status() to get the @@ -121,6 +123,7 @@ struct devfreq_governor { struct list_head node; const char name[DEVFREQ_NAME_LEN]; + const unsigned int immutable; int (*get_target_freq)(struct devfreq *this, unsigned long *freq); int (*event_handler)(struct devfreq *devfreq, unsigned int event, void *data);