Skip to content

Commit e8ad8d5

Browse files
committed
Merge tag 'devfreq-fixes-for-5.5-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/linux
Pull devfreq updates for 5.5-rc1 from Chanwoo Choi: "Update devfreq core: - Add PM QoS support for devfreq device with following QoS type. External user of devfreq device can request the minimum and maximum frequency according to their multiple requirements. : DEV_PM_QOS_MIN_FREQUENCY is used for requesting the minimum device frequency. : DEV_PM_QOS_MAX_FREQUENCY is used for requesting the maximum device frequency. - Use PM QoS interface when entering the min/max_freq via sysfs interface. - Add get_freq_range() helper function in order to get the final min/max frequency among the multiple requirements of min/max frequency. - Fix a function return value and modify code for more correct exception handling if errors happen." * tag 'devfreq-fixes-for-5.5-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/linux: PM / devfreq: Use PM QoS for sysfs min/max_freq PM / devfreq: Add PM QoS support PM / devfreq: Don't fail devfreq_dev_release if not in list PM / devfreq: Introduce get_freq_range helper PM / devfreq: Set scaling_max_freq to max on OPP notifier error PM / devfreq: Fix devfreq_notifier_call returning errno
2 parents e42617b + 27dbc54 commit e8ad8d5

File tree

2 files changed

+212
-75
lines changed

2 files changed

+212
-75
lines changed

drivers/devfreq/devfreq.c

Lines changed: 202 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,14 @@
2424
#include <linux/printk.h>
2525
#include <linux/hrtimer.h>
2626
#include <linux/of.h>
27+
#include <linux/pm_qos.h>
2728
#include "governor.h"
2829

2930
#define CREATE_TRACE_POINTS
3031
#include <trace/events/devfreq.h>
3132

33+
#define HZ_PER_KHZ 1000
34+
3235
static struct class *devfreq_class;
3336

3437
/*
@@ -98,6 +101,54 @@ static unsigned long find_available_max_freq(struct devfreq *devfreq)
98101
return max_freq;
99102
}
100103

104+
/**
105+
* get_freq_range() - Get the current freq range
106+
* @devfreq: the devfreq instance
107+
* @min_freq: the min frequency
108+
* @max_freq: the max frequency
109+
*
110+
* This takes into consideration all constraints.
111+
*/
112+
static void get_freq_range(struct devfreq *devfreq,
113+
unsigned long *min_freq,
114+
unsigned long *max_freq)
115+
{
116+
unsigned long *freq_table = devfreq->profile->freq_table;
117+
s32 qos_min_freq, qos_max_freq;
118+
119+
lockdep_assert_held(&devfreq->lock);
120+
121+
/*
122+
* Initialize minimum/maximum frequency from freq table.
123+
* The devfreq drivers can initialize this in either ascending or
124+
* descending order and devfreq core supports both.
125+
*/
126+
if (freq_table[0] < freq_table[devfreq->profile->max_state - 1]) {
127+
*min_freq = freq_table[0];
128+
*max_freq = freq_table[devfreq->profile->max_state - 1];
129+
} else {
130+
*min_freq = freq_table[devfreq->profile->max_state - 1];
131+
*max_freq = freq_table[0];
132+
}
133+
134+
/* Apply constraints from PM QoS */
135+
qos_min_freq = dev_pm_qos_read_value(devfreq->dev.parent,
136+
DEV_PM_QOS_MIN_FREQUENCY);
137+
qos_max_freq = dev_pm_qos_read_value(devfreq->dev.parent,
138+
DEV_PM_QOS_MAX_FREQUENCY);
139+
*min_freq = max(*min_freq, (unsigned long)HZ_PER_KHZ * qos_min_freq);
140+
if (qos_max_freq != PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE)
141+
*max_freq = min(*max_freq,
142+
(unsigned long)HZ_PER_KHZ * qos_max_freq);
143+
144+
/* Apply constraints from OPP interface */
145+
*min_freq = max(*min_freq, devfreq->scaling_min_freq);
146+
*max_freq = min(*max_freq, devfreq->scaling_max_freq);
147+
148+
if (*min_freq > *max_freq)
149+
*min_freq = *max_freq;
150+
}
151+
101152
/**
102153
* devfreq_get_freq_level() - Lookup freq_table for the frequency
103154
* @devfreq: the devfreq instance
@@ -351,16 +402,7 @@ int update_devfreq(struct devfreq *devfreq)
351402
err = devfreq->governor->get_target_freq(devfreq, &freq);
352403
if (err)
353404
return err;
354-
355-
/*
356-
* Adjust the frequency with user freq, QoS and available freq.
357-
*
358-
* List from the highest priority
359-
* max_freq
360-
* min_freq
361-
*/
362-
max_freq = min(devfreq->scaling_max_freq, devfreq->max_freq);
363-
min_freq = max(devfreq->scaling_min_freq, devfreq->min_freq);
405+
get_freq_range(devfreq, &min_freq, &max_freq);
364406

365407
if (freq < min_freq) {
366408
freq = min_freq;
@@ -568,26 +610,69 @@ static int devfreq_notifier_call(struct notifier_block *nb, unsigned long type,
568610
void *devp)
569611
{
570612
struct devfreq *devfreq = container_of(nb, struct devfreq, nb);
571-
int ret;
613+
int err = -EINVAL;
572614

573615
mutex_lock(&devfreq->lock);
574616

575617
devfreq->scaling_min_freq = find_available_min_freq(devfreq);
576-
if (!devfreq->scaling_min_freq) {
577-
mutex_unlock(&devfreq->lock);
578-
return -EINVAL;
579-
}
618+
if (!devfreq->scaling_min_freq)
619+
goto out;
580620

581621
devfreq->scaling_max_freq = find_available_max_freq(devfreq);
582622
if (!devfreq->scaling_max_freq) {
583-
mutex_unlock(&devfreq->lock);
584-
return -EINVAL;
623+
devfreq->scaling_max_freq = ULONG_MAX;
624+
goto out;
585625
}
586626

587-
ret = update_devfreq(devfreq);
627+
err = update_devfreq(devfreq);
628+
629+
out:
588630
mutex_unlock(&devfreq->lock);
631+
if (err)
632+
dev_err(devfreq->dev.parent,
633+
"failed to update frequency from OPP notifier (%d)\n",
634+
err);
589635

590-
return ret;
636+
return NOTIFY_OK;
637+
}
638+
639+
/**
640+
* qos_notifier_call() - Common handler for QoS constraints.
641+
* @devfreq: the devfreq instance.
642+
*/
643+
static int qos_notifier_call(struct devfreq *devfreq)
644+
{
645+
int err;
646+
647+
mutex_lock(&devfreq->lock);
648+
err = update_devfreq(devfreq);
649+
mutex_unlock(&devfreq->lock);
650+
if (err)
651+
dev_err(devfreq->dev.parent,
652+
"failed to update frequency from PM QoS (%d)\n",
653+
err);
654+
655+
return NOTIFY_OK;
656+
}
657+
658+
/**
659+
* qos_min_notifier_call() - Callback for QoS min_freq changes.
660+
* @nb: Should be devfreq->nb_min
661+
*/
662+
static int qos_min_notifier_call(struct notifier_block *nb,
663+
unsigned long val, void *ptr)
664+
{
665+
return qos_notifier_call(container_of(nb, struct devfreq, nb_min));
666+
}
667+
668+
/**
669+
* qos_max_notifier_call() - Callback for QoS max_freq changes.
670+
* @nb: Should be devfreq->nb_max
671+
*/
672+
static int qos_max_notifier_call(struct notifier_block *nb,
673+
unsigned long val, void *ptr)
674+
{
675+
return qos_notifier_call(container_of(nb, struct devfreq, nb_max));
591676
}
592677

593678
/**
@@ -599,16 +684,36 @@ static int devfreq_notifier_call(struct notifier_block *nb, unsigned long type,
599684
static void devfreq_dev_release(struct device *dev)
600685
{
601686
struct devfreq *devfreq = to_devfreq(dev);
687+
int err;
602688

603689
mutex_lock(&devfreq_list_lock);
604-
if (IS_ERR(find_device_devfreq(devfreq->dev.parent))) {
605-
mutex_unlock(&devfreq_list_lock);
606-
dev_warn(&devfreq->dev, "releasing devfreq which doesn't exist\n");
607-
return;
608-
}
609690
list_del(&devfreq->node);
610691
mutex_unlock(&devfreq_list_lock);
611692

693+
err = dev_pm_qos_remove_notifier(devfreq->dev.parent, &devfreq->nb_max,
694+
DEV_PM_QOS_MAX_FREQUENCY);
695+
if (err && err != -ENOENT)
696+
dev_warn(dev->parent,
697+
"Failed to remove max_freq notifier: %d\n", err);
698+
err = dev_pm_qos_remove_notifier(devfreq->dev.parent, &devfreq->nb_min,
699+
DEV_PM_QOS_MIN_FREQUENCY);
700+
if (err && err != -ENOENT)
701+
dev_warn(dev->parent,
702+
"Failed to remove min_freq notifier: %d\n", err);
703+
704+
if (dev_pm_qos_request_active(&devfreq->user_max_freq_req)) {
705+
err = dev_pm_qos_remove_request(&devfreq->user_max_freq_req);
706+
if (err)
707+
dev_warn(dev->parent,
708+
"Failed to remove max_freq request: %d\n", err);
709+
}
710+
if (dev_pm_qos_request_active(&devfreq->user_min_freq_req)) {
711+
err = dev_pm_qos_remove_request(&devfreq->user_min_freq_req);
712+
if (err)
713+
dev_warn(dev->parent,
714+
"Failed to remove min_freq request: %d\n", err);
715+
}
716+
612717
if (devfreq->profile->exit)
613718
devfreq->profile->exit(devfreq->dev.parent);
614719

@@ -660,6 +765,7 @@ struct devfreq *devfreq_add_device(struct device *dev,
660765
devfreq->dev.parent = dev;
661766
devfreq->dev.class = devfreq_class;
662767
devfreq->dev.release = devfreq_dev_release;
768+
INIT_LIST_HEAD(&devfreq->node);
663769
devfreq->profile = profile;
664770
strncpy(devfreq->governor_name, governor_name, DEVFREQ_NAME_LEN);
665771
devfreq->previous_freq = profile->initial_freq;
@@ -681,15 +787,13 @@ struct devfreq *devfreq_add_device(struct device *dev,
681787
err = -EINVAL;
682788
goto err_dev;
683789
}
684-
devfreq->min_freq = devfreq->scaling_min_freq;
685790

686791
devfreq->scaling_max_freq = find_available_max_freq(devfreq);
687792
if (!devfreq->scaling_max_freq) {
688793
mutex_unlock(&devfreq->lock);
689794
err = -EINVAL;
690795
goto err_dev;
691796
}
692-
devfreq->max_freq = devfreq->scaling_max_freq;
693797

694798
devfreq->suspend_freq = dev_pm_opp_get_suspend_opp_freq(dev);
695799
atomic_set(&devfreq->suspend_count, 0);
@@ -730,6 +834,28 @@ struct devfreq *devfreq_add_device(struct device *dev,
730834

731835
mutex_unlock(&devfreq->lock);
732836

837+
err = dev_pm_qos_add_request(dev, &devfreq->user_min_freq_req,
838+
DEV_PM_QOS_MIN_FREQUENCY, 0);
839+
if (err < 0)
840+
goto err_devfreq;
841+
err = dev_pm_qos_add_request(dev, &devfreq->user_max_freq_req,
842+
DEV_PM_QOS_MAX_FREQUENCY,
843+
PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE);
844+
if (err < 0)
845+
goto err_devfreq;
846+
847+
devfreq->nb_min.notifier_call = qos_min_notifier_call;
848+
err = dev_pm_qos_add_notifier(devfreq->dev.parent, &devfreq->nb_min,
849+
DEV_PM_QOS_MIN_FREQUENCY);
850+
if (err)
851+
goto err_devfreq;
852+
853+
devfreq->nb_max.notifier_call = qos_max_notifier_call;
854+
err = dev_pm_qos_add_notifier(devfreq->dev.parent, &devfreq->nb_max,
855+
DEV_PM_QOS_MAX_FREQUENCY);
856+
if (err)
857+
goto err_devfreq;
858+
733859
mutex_lock(&devfreq_list_lock);
734860

735861
governor = try_then_request_governor(devfreq->governor_name);
@@ -1303,41 +1429,37 @@ static ssize_t min_freq_store(struct device *dev, struct device_attribute *attr,
13031429
unsigned long value;
13041430
int ret;
13051431

1432+
/*
1433+
* Protect against theoretical sysfs writes between
1434+
* device_add and dev_pm_qos_add_request
1435+
*/
1436+
if (!dev_pm_qos_request_active(&df->user_min_freq_req))
1437+
return -EAGAIN;
1438+
13061439
ret = sscanf(buf, "%lu", &value);
13071440
if (ret != 1)
13081441
return -EINVAL;
13091442

1310-
mutex_lock(&df->lock);
1311-
1312-
if (value) {
1313-
if (value > df->max_freq) {
1314-
ret = -EINVAL;
1315-
goto unlock;
1316-
}
1317-
} else {
1318-
unsigned long *freq_table = df->profile->freq_table;
1319-
1320-
/* Get minimum frequency according to sorting order */
1321-
if (freq_table[0] < freq_table[df->profile->max_state - 1])
1322-
value = freq_table[0];
1323-
else
1324-
value = freq_table[df->profile->max_state - 1];
1325-
}
1443+
/* Round down to kHz for PM QoS */
1444+
ret = dev_pm_qos_update_request(&df->user_min_freq_req,
1445+
value / HZ_PER_KHZ);
1446+
if (ret < 0)
1447+
return ret;
13261448

1327-
df->min_freq = value;
1328-
update_devfreq(df);
1329-
ret = count;
1330-
unlock:
1331-
mutex_unlock(&df->lock);
1332-
return ret;
1449+
return count;
13331450
}
13341451

13351452
static ssize_t min_freq_show(struct device *dev, struct device_attribute *attr,
13361453
char *buf)
13371454
{
13381455
struct devfreq *df = to_devfreq(dev);
1456+
unsigned long min_freq, max_freq;
13391457

1340-
return sprintf(buf, "%lu\n", max(df->scaling_min_freq, df->min_freq));
1458+
mutex_lock(&df->lock);
1459+
get_freq_range(df, &min_freq, &max_freq);
1460+
mutex_unlock(&df->lock);
1461+
1462+
return sprintf(buf, "%lu\n", min_freq);
13411463
}
13421464

13431465
static ssize_t max_freq_store(struct device *dev, struct device_attribute *attr,
@@ -1347,42 +1469,51 @@ static ssize_t max_freq_store(struct device *dev, struct device_attribute *attr,
13471469
unsigned long value;
13481470
int ret;
13491471

1472+
/*
1473+
* Protect against theoretical sysfs writes between
1474+
* device_add and dev_pm_qos_add_request
1475+
*/
1476+
if (!dev_pm_qos_request_active(&df->user_max_freq_req))
1477+
return -EINVAL;
1478+
13501479
ret = sscanf(buf, "%lu", &value);
13511480
if (ret != 1)
13521481
return -EINVAL;
13531482

1354-
mutex_lock(&df->lock);
1355-
1356-
if (value) {
1357-
if (value < df->min_freq) {
1358-
ret = -EINVAL;
1359-
goto unlock;
1360-
}
1361-
} else {
1362-
unsigned long *freq_table = df->profile->freq_table;
1483+
/*
1484+
* PM QoS frequencies are in kHz so we need to convert. Convert by
1485+
* rounding upwards so that the acceptable interval never shrinks.
1486+
*
1487+
* For example if the user writes "666666666" to sysfs this value will
1488+
* be converted to 666667 kHz and back to 666667000 Hz before an OPP
1489+
* lookup, this ensures that an OPP of 666666666Hz is still accepted.
1490+
*
1491+
* A value of zero means "no limit".
1492+
*/
1493+
if (value)
1494+
value = DIV_ROUND_UP(value, HZ_PER_KHZ);
1495+
else
1496+
value = PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE;
13631497

1364-
/* Get maximum frequency according to sorting order */
1365-
if (freq_table[0] < freq_table[df->profile->max_state - 1])
1366-
value = freq_table[df->profile->max_state - 1];
1367-
else
1368-
value = freq_table[0];
1369-
}
1498+
ret = dev_pm_qos_update_request(&df->user_max_freq_req, value);
1499+
if (ret < 0)
1500+
return ret;
13701501

1371-
df->max_freq = value;
1372-
update_devfreq(df);
1373-
ret = count;
1374-
unlock:
1375-
mutex_unlock(&df->lock);
1376-
return ret;
1502+
return count;
13771503
}
13781504
static DEVICE_ATTR_RW(min_freq);
13791505

13801506
static ssize_t max_freq_show(struct device *dev, struct device_attribute *attr,
13811507
char *buf)
13821508
{
13831509
struct devfreq *df = to_devfreq(dev);
1510+
unsigned long min_freq, max_freq;
1511+
1512+
mutex_lock(&df->lock);
1513+
get_freq_range(df, &min_freq, &max_freq);
1514+
mutex_unlock(&df->lock);
13841515

1385-
return sprintf(buf, "%lu\n", min(df->scaling_max_freq, df->max_freq));
1516+
return sprintf(buf, "%lu\n", max_freq);
13861517
}
13871518
static DEVICE_ATTR_RW(max_freq);
13881519

0 commit comments

Comments
 (0)