devfreq: memlat: Add suspend/resume for mem_latency

Add suspend/resume support for the mem_latency governor. Uses hwmon driver-
defined suspend/resume calls in addition to monitor start/stop calls within
the devfreq framework.

Change-Id: I900b322a05cd0312f082d70640e21851879cb18c
Signed-off-by: Jonathan Avila <avilaj@codeaurora.org>
[avajid@codeaurora.org: made minor styling changes]
Signed-off-by: Amir Vajid <avajid@codeaurora.org>
This commit is contained in:
Jonathan Avila 2019-01-16 20:32:20 -08:00 • committed by Amir Vajid
commit 10e4379923

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2015-2017, 2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2015-2018, 2019, The Linux Foundation. All rights reserved.
*/
#define pr_fmt(fmt) "mem_lat: " fmt
@ -35,6 +35,7 @@ struct memlat_node {
struct memlat_hwmon *hw;
struct devfreq_governor *gov;
struct attribute_group *attr_grp;
unsigned long resume_freq;
};
static LIST_HEAD(memlat_list);
@ -199,6 +200,39 @@ err_start:
return ret;
}
static int gov_suspend(struct devfreq *df)
{
struct memlat_node *node = df->data;
unsigned long prev_freq = df->previous_freq;
node->mon_started = false;
devfreq_monitor_suspend(df);
mutex_lock(&df->lock);
update_devfreq(df);
mutex_unlock(&df->lock);
node->resume_freq = max(prev_freq, 1UL);
return 0;
}
static int gov_resume(struct devfreq *df)
{
struct memlat_node *node = df->data;
mutex_lock(&df->lock);
update_devfreq(df);
mutex_unlock(&df->lock);
node->resume_freq = 0;
devfreq_monitor_resume(df);
node->mon_started = true;
return 0;
}
static void gov_stop(struct devfreq *df)
{
struct memlat_node *node = df->data;
@ -220,6 +254,18 @@ static int devfreq_memlat_get_freq(struct devfreq *df,
unsigned long max_freq = 0;
unsigned int ratio;
/*
* node->resume_freq is set to 0 at the end of resume (after the update)
* and is set to df->prev_freq at the end of suspend (after the update).
* This function will be called as part of the update_devfreq call in
* both scenarios. As a result, this block will cause a 0 vote during
* suspend and a vote for df->prev_freq during resume.
*/
if (!node->mon_started) {
*freq = node->resume_freq;
return 0;
}
hw->get_cnt(hw);
for (i = 0; i < hw->num_cores; i++) {
@ -322,6 +368,30 @@ static int devfreq_memlat_ev_handler(struct devfreq *df,
"Disabled Memory Latency governor\n");
break;
case DEVFREQ_GOV_SUSPEND:
ret = gov_suspend(df);
if (ret < 0) {
dev_err(df->dev.parent,
"Unable to suspend memlat governor (%d)\n",
ret);
return ret;
}
dev_dbg(df->dev.parent, "Suspended memlat governor\n");
break;
case DEVFREQ_GOV_RESUME:
ret = gov_resume(df);
if (ret < 0) {
dev_err(df->dev.parent,
"Unable to resume memlat governor (%d)\n",
ret);
return ret;
}
dev_dbg(df->dev.parent, "Resumed memlat governor\n");
break;
case DEVFREQ_GOV_INTERVAL:
sample_ms = *(unsigned int *)data;
sample_ms = max(MIN_MS, sample_ms);