[PATCH 5/7] devfreq: move transition statistics to devfreq profile structure

From: Kamil Konieczny
Date: Wed Nov 13 2019 - 04:14:04 EST


Move transition statistics to devfreq profile structure. This is for
preparation for moving transition statistics into separate struct.
It is safe to do as frequency table and maximum state information are
already present in devfreq profile structure and there are no devfreq
drivers using more than one instance of devfreq structure per devfreq
profile one.

It also makes devfreq code more similar to cpufreq one.

Signed-off-by: Kamil Konieczny <k.konieczny@xxxxxxxxxxx>
---
drivers/devfreq/devfreq.c | 115 +++++++++++++++++++-------------------
include/linux/devfreq.h | 25 ++++-----
2 files changed, 70 insertions(+), 70 deletions(-)

diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 6e5a17f4c92c..70533b787744 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -128,7 +128,7 @@ static int set_freq_table(struct devfreq *devfreq)

profile->max_state = count;
profile->freq_table = devm_kcalloc(devfreq->dev.parent,
- profile->max_state,
+ count,
sizeof(*profile->freq_table),
GFP_KERNEL);
if (!profile->freq_table) {
@@ -157,29 +157,30 @@ static int set_freq_table(struct devfreq *devfreq)
*/
int devfreq_update_status(struct devfreq *devfreq, unsigned long freq)
{
- int lev, prev_lev, ret = 0;
+ struct devfreq_dev_profile *profile = devfreq->profile;
unsigned long long cur_time;
+ int lev, prev_lev, ret = 0;

cur_time = get_jiffies_64();

/* Immediately exit if previous_freq is not initialized yet. */
if (!devfreq->previous_freq) {
- spin_lock(&devfreq->stats_lock);
- devfreq->last_time = cur_time;
- spin_unlock(&devfreq->stats_lock);
+ spin_lock(&profile->stats_lock);
+ profile->last_time = cur_time;
+ spin_unlock(&profile->stats_lock);
return 0;
}

prev_lev = devfreq_get_freq_level(devfreq, devfreq->previous_freq);

- spin_lock(&devfreq->stats_lock);
+ spin_lock(&profile->stats_lock);
if (prev_lev < 0) {
ret = prev_lev;
goto out;
}

- devfreq->time_in_state[prev_lev] +=
- cur_time - devfreq->last_time;
+ profile->time_in_state[prev_lev] +=
+ cur_time - profile->last_time;
lev = devfreq_get_freq_level(devfreq, freq);
if (lev < 0) {
ret = lev;
@@ -187,14 +188,14 @@ int devfreq_update_status(struct devfreq *devfreq, unsigned long freq)
}

if (lev != prev_lev) {
- devfreq->trans_table[(prev_lev *
- devfreq->profile->max_state) + lev]++;
- devfreq->total_trans++;
+ profile->trans_table[(prev_lev *
+ profile->max_state) + lev]++;
+ profile->total_trans++;
}

out:
- devfreq->last_time = cur_time;
- spin_unlock(&devfreq->stats_lock);
+ profile->last_time = cur_time;
+ spin_unlock(&profile->stats_lock);
return ret;
}
EXPORT_SYMBOL(devfreq_update_status);
@@ -474,23 +475,23 @@ EXPORT_SYMBOL(devfreq_monitor_suspend);
void devfreq_monitor_resume(struct devfreq *devfreq)
{
unsigned long freq;
+ struct devfreq_dev_profile *profile = devfreq->profile;

mutex_lock(&devfreq->lock);
if (!devfreq->stop_polling)
goto out;

- if (!delayed_work_pending(&devfreq->work) &&
- devfreq->profile->polling_ms)
+ if (!delayed_work_pending(&devfreq->work) && profile->polling_ms)
queue_delayed_work(devfreq_wq, &devfreq->work,
- msecs_to_jiffies(devfreq->profile->polling_ms));
+ msecs_to_jiffies(profile->polling_ms));

- spin_lock(&devfreq->stats_lock);
- devfreq->last_time = get_jiffies_64();
- spin_unlock(&devfreq->stats_lock);
+ spin_lock(&profile->stats_lock);
+ profile->last_time = get_jiffies_64();
+ spin_unlock(&profile->stats_lock);
devfreq->stop_polling = false;

- if (devfreq->profile->get_cur_freq &&
- !devfreq->profile->get_cur_freq(devfreq->dev.parent, &freq))
+ if (profile->get_cur_freq &&
+ !profile->get_cur_freq(devfreq->dev.parent, &freq))
devfreq->previous_freq = freq;

out:
@@ -657,7 +658,7 @@ struct devfreq *devfreq_add_device(struct device *dev,
devfreq->data = data;
devfreq->nb.notifier_call = devfreq_notifier_call;

- if (!devfreq->profile->max_state && !devfreq->profile->freq_table) {
+ if (!profile->max_state && !profile->freq_table) {
mutex_unlock(&devfreq->lock);
err = set_freq_table(devfreq);
if (err < 0)
@@ -693,29 +694,29 @@ struct devfreq *devfreq_add_device(struct device *dev,
goto err_out;
}

- devfreq->trans_table = devm_kzalloc(&devfreq->dev,
- array3_size(sizeof(unsigned int),
- devfreq->profile->max_state,
- devfreq->profile->max_state),
- GFP_KERNEL);
- if (!devfreq->trans_table) {
+ profile->trans_table = devm_kzalloc(&devfreq->dev,
+ array3_size(sizeof(unsigned int),
+ profile->max_state,
+ profile->max_state),
+ GFP_KERNEL);
+ if (!profile->trans_table) {
mutex_unlock(&devfreq->lock);
err = -ENOMEM;
goto err_devfreq;
}

- devfreq->time_in_state = devm_kcalloc(&devfreq->dev,
- devfreq->profile->max_state,
- sizeof(*devfreq->time_in_state),
- GFP_KERNEL);
- if (!devfreq->time_in_state) {
+ profile->time_in_state = devm_kcalloc(&devfreq->dev,
+ profile->max_state,
+ sizeof(*profile->time_in_state),
+ GFP_KERNEL);
+ if (!profile->time_in_state) {
mutex_unlock(&devfreq->lock);
err = -ENOMEM;
goto err_devfreq;
}

- devfreq->last_time = get_jiffies_64();
- spin_lock_init(&devfreq->stats_lock);
+ profile->last_time = get_jiffies_64();
+ spin_lock_init(&profile->stats_lock);

srcu_init_notifier_head(&devfreq->transition_notifier_list);

@@ -1402,9 +1403,10 @@ static ssize_t trans_stat_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct devfreq *devfreq = to_devfreq(dev);
+ struct devfreq_dev_profile *profile = devfreq->profile;
ssize_t len;
int i, j;
- unsigned int max_state = devfreq->profile->max_state;
+ unsigned int max_state = profile->max_state;

if (!devfreq->stop_polling &&
devfreq_update_status(devfreq, devfreq->previous_freq))
@@ -1415,46 +1417,45 @@ static ssize_t trans_stat_show(struct device *dev,
len = sprintf(buf, " From : To\n");
len += sprintf(buf + len, " :");

- spin_lock(&devfreq->stats_lock);
+ spin_lock(&profile->stats_lock);
for (i = 0; i < max_state; i++)
len += sprintf(buf + len, "%10lu",
- devfreq->profile->freq_table[i]);
+ profile->freq_table[i]);

len += sprintf(buf + len, " time(ms)\n");

for (i = 0; i < max_state; i++) {
- if (devfreq->profile->freq_table[i]
- == devfreq->previous_freq) {
+ if (profile->freq_table[i] == devfreq->previous_freq)
len += sprintf(buf + len, "*");
- } else {
+ else
len += sprintf(buf + len, " ");
- }
+
len += sprintf(buf + len, "%10lu:",
- devfreq->profile->freq_table[i]);
+ profile->freq_table[i]);
for (j = 0; j < max_state; j++)
len += sprintf(buf + len, "%10u",
- devfreq->trans_table[(i * max_state) + j]);
+ profile->trans_table[(i * max_state) + j]);
len += sprintf(buf + len, "%10llu\n", (u64)
- jiffies64_to_msecs(devfreq->time_in_state[i]));
+ jiffies64_to_msecs(profile->time_in_state[i]));
}

len += sprintf(buf + len, "Total transition : %u\n",
- devfreq->total_trans);
- spin_unlock(&devfreq->stats_lock);
+ profile->total_trans);
+ spin_unlock(&profile->stats_lock);
return len;
}
static DEVICE_ATTR_RO(trans_stat);

-static void defvreq_stats_clear_table(struct devfreq *devfreq)
+static void defvreq_stats_clear_table(struct devfreq_dev_profile *profile)
{
- unsigned int count = devfreq->profile->max_state;
-
- spin_lock(&devfreq->stats_lock);
- memset(devfreq->time_in_state, 0, count * sizeof(u64));
- memset(devfreq->trans_table, 0, count * count * sizeof(int));
- devfreq->last_time = get_jiffies_64();
- devfreq->total_trans = 0;
- spin_unlock(&devfreq->stats_lock);
+ unsigned int count = profile->max_state;
+
+ spin_lock(&profile->stats_lock);
+ memset(profile->time_in_state, 0, count * sizeof(u64));
+ memset(profile->trans_table, 0, count * count * sizeof(int));
+ profile->last_time = get_jiffies_64();
+ profile->total_trans = 0;
+ spin_unlock(&profile->stats_lock);
}

static ssize_t trans_reset_store(struct device *dev,
@@ -1464,7 +1465,7 @@ static ssize_t trans_reset_store(struct device *dev,
{
struct devfreq *devfreq = to_devfreq(dev);

- defvreq_stats_clear_table(devfreq);
+ defvreq_stats_clear_table(devfreq->profile);

return count;
}
diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h
index 2ddf25993f7d..4ceb2a517a9c 100644
--- a/include/linux/devfreq.h
+++ b/include/linux/devfreq.h
@@ -91,6 +91,12 @@ struct devfreq_dev_status {
* @freq_table: Optional list of frequencies to support statistics
* and freq_table must be generated in ascending order.
* @max_state: The size of freq_table.
+ * @total_trans: Number of devfreq transitions
+ * @trans_table: Statistics of devfreq transitions
+ * @time_in_state: Statistics of devfreq states
+ * @last_time: The last time stats were updated
+ * @stats_lock: Lock protecting trans_table, time_in_state,
+ * last_time and total_trans used for statistics
*/
struct devfreq_dev_profile {
unsigned long initial_freq;
@@ -104,6 +110,12 @@ struct devfreq_dev_profile {

unsigned long *freq_table;
unsigned int max_state;
+ /* information for device frequency transition */
+ unsigned int total_trans;
+ unsigned int *trans_table;
+ u64 *time_in_state;
+ unsigned long long last_time;
+ spinlock_t stats_lock;
};

/**
@@ -131,12 +143,6 @@ struct devfreq_dev_profile {
* @suspend_freq: frequency of a device set during suspend phase.
* @resume_freq: frequency of a device set in resume phase.
* @suspend_count: suspend requests counter for a device.
- * @total_trans: Number of devfreq transitions
- * @trans_table: Statistics of devfreq transitions
- * @time_in_state: Statistics of devfreq states
- * @last_time: The last time stats were updated
- * @stats_lock: Lock protecting trans_table, time_in_state, last_time
- * and total_trans used for statistics
* @transition_notifier_list: list head of DEVFREQ_TRANSITION_NOTIFIER notifier
*
* This structure stores the devfreq information for a give device.
@@ -173,13 +179,6 @@ struct devfreq {
unsigned long resume_freq;
atomic_t suspend_count;

- /* information for device frequency transition */
- unsigned int total_trans;
- unsigned int *trans_table;
- u64 *time_in_state;
- unsigned long long last_time;
- spinlock_t stats_lock;
-
struct srcu_notifier_head transition_notifier_list;
};

--
2.24.0