From df678ff7531990ba11cc0b921609a7e229d1323c Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Tue, 17 Nov 2015 14:25:06 +0900 Subject: [PATCH 1/8] PM / devfreq: event: Remove the error log of devfreq_event_get_edev_by_phandle() This patch just removes the error log when devfreq_event_get_edev_by_phandle() fail to get the instance of devfreq-event device. It is related to sequence of the probe() of each driver. So, this error log might show the always during kernel booting. Each driver using this function can show the appropriate error log. Signed-off-by: Chanwoo Choi Signed-off-by: MyungJoo Ham --- drivers/devfreq/devfreq-event.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/drivers/devfreq/devfreq-event.c b/drivers/devfreq/devfreq-event.c index f304a0289eda..f51de879b2be 100644 --- a/drivers/devfreq/devfreq-event.c +++ b/drivers/devfreq/devfreq-event.c @@ -226,17 +226,12 @@ struct devfreq_event_dev *devfreq_event_get_edev_by_phandle(struct device *dev, struct device_node *node; struct devfreq_event_dev *edev; - if (!dev->of_node) { - dev_err(dev, "device does not have a device node entry\n"); + if (!dev->of_node) return ERR_PTR(-EINVAL); - } node = of_parse_phandle(dev->of_node, "devfreq-events", index); - if (!node) { - dev_err(dev, "failed to get phandle in %s node\n", - dev->of_node->full_name); + if (!node) return ERR_PTR(-ENODEV); - } mutex_lock(&devfreq_event_list_lock); list_for_each_entry(edev, &devfreq_event_list, node) { @@ -248,8 +243,6 @@ struct devfreq_event_dev *devfreq_event_get_edev_by_phandle(struct device *dev, mutex_unlock(&devfreq_event_list_lock); if (!edev) { - dev_err(dev, "unable to get devfreq-event device : %s\n", - node->name); of_node_put(node); return ERR_PTR(-ENODEV); } From e54916c6e1d0b939999eb38011202dd9064d5788 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Thu, 19 Nov 2015 17:03:44 +0900 Subject: [PATCH 2/8] PM / devfreq: event: Fix the error and warning from script/checkpatch.pl This patch just fixes following error and warning by using scripts/checkpatch.pl. - Follwoing issue from checkpatch.pl: ERROR: space prohibited before that close parenthesis ')' + if (count < 0 ) { WARNING: line over 80 characters + ptr = devres_alloc(devm_devfreq_event_release, sizeof(*ptr), GFP_KERNEL); Signed-off-by: Chanwoo Choi Signed-off-by: MyungJoo Ham --- drivers/devfreq/devfreq-event.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/devfreq/devfreq-event.c b/drivers/devfreq/devfreq-event.c index f51de879b2be..38bf144ca147 100644 --- a/drivers/devfreq/devfreq-event.c +++ b/drivers/devfreq/devfreq-event.c @@ -270,7 +270,7 @@ int devfreq_event_get_edev_count(struct device *dev) count = of_property_count_elems_of_size(dev->of_node, "devfreq-events", sizeof(u32)); - if (count < 0 ) { + if (count < 0) { dev_err(dev, "failed to get the count of devfreq-event in %s node\n", dev->of_node->full_name); @@ -395,7 +395,8 @@ struct devfreq_event_dev *devm_devfreq_event_add_edev(struct device *dev, { struct devfreq_event_dev **ptr, *edev; - ptr = devres_alloc(devm_devfreq_event_release, sizeof(*ptr), GFP_KERNEL); + ptr = devres_alloc(devm_devfreq_event_release, sizeof(*ptr), + GFP_KERNEL); if (!ptr) return ERR_PTR(-ENOMEM); From 3104fa3081126c9bda35793af5f335d0ee0d5818 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Fri, 13 Nov 2015 19:25:28 +0900 Subject: [PATCH 3/8] PM / devfreq: Add show_one macro to delete the duplicate code This patch adds the 'show_one' macro to simplify the duplicate code of both max_freq_show() and min_freq_show(). Signed-off-by: Chanwoo Choi Signed-off-by: MyungJoo Ham --- drivers/devfreq/devfreq.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index ca848cc6a8fd..49fc7dcf664c 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -921,12 +921,6 @@ static ssize_t min_freq_store(struct device *dev, struct device_attribute *attr, return ret; } -static ssize_t min_freq_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - return sprintf(buf, "%lu\n", to_devfreq(dev)->min_freq); -} - static ssize_t max_freq_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { @@ -953,13 +947,17 @@ static ssize_t max_freq_store(struct device *dev, struct device_attribute *attr, mutex_unlock(&df->lock); return ret; } -static DEVICE_ATTR_RW(min_freq); -static ssize_t max_freq_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - return sprintf(buf, "%lu\n", to_devfreq(dev)->max_freq); +#define show_one(name) \ +static ssize_t name##_show \ +(struct device *dev, struct device_attribute *attr, char *buf) \ +{ \ + return sprintf(buf, "%lu\n", to_devfreq(dev)->name); \ } +show_one(min_freq); +show_one(max_freq); + +static DEVICE_ATTR_RW(min_freq); static DEVICE_ATTR_RW(max_freq); static ssize_t available_frequencies_show(struct device *d, From 0ec09ac2cebe9769491a470c33edff0f873ff79d Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Wed, 18 Nov 2015 14:49:02 +0900 Subject: [PATCH 4/8] PM / devfreq: Set the freq_table of devfreq device This patch initialize the freq_table array of each devfreq device by using the devfreq_set_freq_table(). If freq_table is NULL, the devfreq framework is not able to support the frequency transtion information through sysfs. The OPP core uses the integer type for the number of opps in the opp list and uses the 'unsigned long' type for each frequency. So, this patch modifies the type of some variable as following: - the type of freq_table : unsigned int -> unsigned long - the type of max_state : unsigned int -> int - Corrected types, format strings, mutex usages by MyungJoo Signed-off-by: Chanwoo Choi Signed-off-by: MyungJoo Ham --- drivers/devfreq/devfreq.c | 50 +++++++++++++++++++++++++++++++++++++-- include/linux/devfreq.h | 2 +- 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 49fc7dcf664c..f3ee2388bf6e 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -84,6 +84,46 @@ static int devfreq_get_freq_level(struct devfreq *devfreq, unsigned long freq) return -EINVAL; } +/** + * devfreq_set_freq_table() - Initialize freq_table for the frequency + * @devfreq: the devfreq instance + */ +static void devfreq_set_freq_table(struct devfreq *devfreq) +{ + struct devfreq_dev_profile *profile = devfreq->profile; + struct dev_pm_opp *opp; + unsigned long freq; + int i, count; + + /* Initialize the freq_table from OPP table */ + count = dev_pm_opp_get_opp_count(devfreq->dev.parent); + if (count <= 0) + return; + + profile->max_state = count; + profile->freq_table = devm_kcalloc(devfreq->dev.parent, + profile->max_state, + sizeof(*profile->freq_table), + GFP_KERNEL); + if (!profile->freq_table) { + profile->max_state = 0; + return; + } + + rcu_read_lock(); + for (i = 0, freq = 0; i < profile->max_state; i++, freq++) { + opp = dev_pm_opp_find_freq_ceil(devfreq->dev.parent, &freq); + if (IS_ERR(opp)) { + devm_kfree(devfreq->dev.parent, profile->freq_table); + profile->max_state = 0; + rcu_read_unlock(); + return; + } + profile->freq_table[i] = freq; + } + rcu_read_unlock(); +} + /** * devfreq_update_status() - Update statistics of devfreq behavior * @devfreq: the devfreq instance @@ -478,6 +518,12 @@ 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) { + mutex_unlock(&devfreq->lock); + devfreq_set_freq_table(devfreq); + mutex_lock(&devfreq->lock); + } + devfreq->trans_table = devm_kzalloc(dev, sizeof(unsigned int) * devfreq->profile->max_state * devfreq->profile->max_state, @@ -1007,7 +1053,7 @@ static ssize_t trans_stat_show(struct device *dev, len = sprintf(buf, " From : To\n"); len += sprintf(buf + len, " :"); for (i = 0; i < max_state; i++) - len += sprintf(buf + len, "%8u", + len += sprintf(buf + len, "%8lu", devfreq->profile->freq_table[i]); len += sprintf(buf + len, " time(ms)\n"); @@ -1019,7 +1065,7 @@ static ssize_t trans_stat_show(struct device *dev, } else { len += sprintf(buf + len, " "); } - len += sprintf(buf + len, "%8u:", + len += sprintf(buf + len, "%8lu:", devfreq->profile->freq_table[i]); for (j = 0; j < max_state; j++) len += sprintf(buf + len, "%8u", diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h index 68030e22af35..6fa02a20eb63 100644 --- a/include/linux/devfreq.h +++ b/include/linux/devfreq.h @@ -89,7 +89,7 @@ struct devfreq_dev_profile { int (*get_cur_freq)(struct device *dev, unsigned long *freq); void (*exit)(struct device *dev); - unsigned int *freq_table; + unsigned long *freq_table; unsigned int max_state; }; From d7df1e464749650056f511e75b3d4e53cfac5d53 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Thu, 19 Nov 2015 16:28:46 +0900 Subject: [PATCH 5/8] PM / devfreq: Modify the indentation of trans_stat sysfs for readability This patch modifies the indentation of 'trans_stat' sysfs to improve readability. The 1GHz is 1000,000,000. So it needs the least 10 position to show the GHz unit. - Before apply this patch, -sh-3.2# cat trans_stat From : To :50000000100000000133000000200000000400000000 time(ms) *50000000: 0 0 0 0 7 1817635 100000000: 4 0 0 0 4 1590 133000000: 1 4 0 0 7 975 200000000: 2 2 7 0 1 2655 400000000: 0 2 5 12 0 1860 Total transition : 58 - After apply this patch, -sh-3.2# cat trans_stat From : To : 50000000 100000000 133000000 200000000 400000000 time(ms) * 50000000: 0 0 0 0 7 14405 100000000: 4 0 0 0 3 2015 133000000: 2 3 0 0 7 1020 200000000: 1 2 7 0 0 2970 400000000: 0 2 5 10 0 1575 Total transition : 53 Signed-off-by: Chanwoo Choi Signed-off-by: MyungJoo Ham --- drivers/devfreq/devfreq.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index f3ee2388bf6e..d36fa2db4d29 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -1050,10 +1050,10 @@ static ssize_t trans_stat_show(struct device *dev, devfreq_update_status(devfreq, devfreq->previous_freq)) return 0; - len = sprintf(buf, " From : To\n"); - len += sprintf(buf + len, " :"); + len = sprintf(buf, " From : To\n"); + len += sprintf(buf + len, " :"); for (i = 0; i < max_state; i++) - len += sprintf(buf + len, "%8lu", + len += sprintf(buf + len, "%10lu", devfreq->profile->freq_table[i]); len += sprintf(buf + len, " time(ms)\n"); @@ -1065,10 +1065,10 @@ static ssize_t trans_stat_show(struct device *dev, } else { len += sprintf(buf + len, " "); } - len += sprintf(buf + len, "%8lu:", + len += sprintf(buf + len, "%10lu:", devfreq->profile->freq_table[i]); for (j = 0; j < max_state; j++) - len += sprintf(buf + len, "%8u", + len += sprintf(buf + len, "%10u", devfreq->trans_table[(i * max_state) + j]); len += sprintf(buf + len, "%10u\n", jiffies_to_msecs(devfreq->time_in_state[i])); From 34bd322070a41898b032f59a0dfd345627fc1e7e Mon Sep 17 00:00:00 2001 From: MyungJoo Ham Date: Mon, 23 Nov 2015 15:45:36 +0900 Subject: [PATCH 6/8] PM / devfreq: Do not show statistics if it's not ready. Before this patch for a device without statistics support, $ cat trans_stat From : To : time(ms) Total transitions : 0 $ After this patch applied for such a device, $ cat trans_stat Not Supported. $ Signed-off-by: MyungJoo Ham --- drivers/devfreq/devfreq.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index d36fa2db4d29..984c5e9e7bdd 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -1049,6 +1049,8 @@ static ssize_t trans_stat_show(struct device *dev, if (!devfreq->stop_polling && devfreq_update_status(devfreq, devfreq->previous_freq)) return 0; + if (max_state == 0) + return sprintf(buf, "Not Supported.\n"); len = sprintf(buf, " From : To\n"); len += sprintf(buf + len, " :"); From 6a3cd7220364ad9e92c926600500f225c02ae3ac Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Thu, 5 Nov 2015 13:30:17 +0900 Subject: [PATCH 7/8] MAINTAINERS: Add missing git repository and directory for devfreq This patch adds the missing git repository infomation and directory for devfreq. When using get_maintainer.pl, the result should include the correct maintainer information. Suggested-by: Joe Perches [cw00.chio: Add missing directory for devfreq] Signed-off-by: Chanwoo Choi Signed-off-by: Myungjoo Ham --- MAINTAINERS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 233f83464814..033abfcdf818 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3403,8 +3403,11 @@ DEVICE FREQUENCY (DEVFREQ) M: MyungJoo Ham M: Kyungmin Park L: linux-pm@vger.kernel.org +T: git git://git.kernel.org/pub/scm/linux/kernel/git/mzx/devfreq.git S: Maintained F: drivers/devfreq/ +F: include/linux/devfreq.h +F: Documentation/devicetree/bindings/devfreq/ DEVICE NUMBER REGISTRY M: Torben Mathiasen From 7dbded06efe41367163e903331ef45bd765a62a4 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Thu, 5 Nov 2015 13:30:18 +0900 Subject: [PATCH 8/8] MAINTAINERS: Add devfreq-event entry This patch adds the devfreq-event[1] entry to review the patches as just supporter. Patches will be picked up by Myungjoo Ham on devfreq git repository. [1] https://lkml.org/lkml/2015/1/25/573 Signed-off-by: Chanwoo Choi Signed-off-by: Myungjoo Ham --- MAINTAINERS | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 033abfcdf818..7cb4f8c6d41d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3409,6 +3409,16 @@ F: drivers/devfreq/ F: include/linux/devfreq.h F: Documentation/devicetree/bindings/devfreq/ +DEVICE FREQUENCY EVENT (DEVFREQ-EVENT) +M: Chanwoo Choi +L: linux-pm@vger.kernel.org +T: git git://git.kernel.org/pub/scm/linux/kernel/git/mzx/devfreq.git +S: Supported +F: drivers/devfreq/event/ +F: drivers/devfreq/devfreq-event.c +F: include/linux/devfreq-event.h +F: Documentation/devicetree/bindings/devfreq/event/ + DEVICE NUMBER REGISTRY M: Torben Mathiasen W: http://lanana.org/docs/device-list/index.html