linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] PM QoS: Add debugfs support to view the list of constraints
@ 2014-12-05 17:19 Dave Gerlach
  2014-12-05 22:47 ` Rafael J. Wysocki
  2014-12-15 22:34 ` Kevin Hilman
  0 siblings, 2 replies; 4+ messages in thread
From: Dave Gerlach @ 2014-12-05 17:19 UTC (permalink / raw)
  To: linux-kernel, linux-pm
  Cc: Rafael J. Wysocki, Pavel Machek, Len Brown, Nishanth Menon, Dave Gerlach

From: Nishanth Menon <nm@ti.com>

PM QoS requests are notoriously hard to debug and made even
more so due to their highly dynamic nature. Having visibility
into the internal data representation per constraint allows
us to have much better appreciation of potential issues or
bad usage by drivers in the system.

So introduce for all classes of PM QoS, an entry in
/sys/kernel/debug/pm_qos that shall show all the current
requests as well as the snapshot of the value these requests
boil down to. For example:
==> /sys/kernel/debug/pm_qos/cpu_dma_latency <==
1: 4444: Active
2: 2000000000: Default
3: 2000000000: Default
4: 2000000000: Default
Type=Minimum, Value=4444, Requests: active=1 / total=4

==> /sys/kernel/debug/pm_qos/memory_bandwidth <==
Empty!

...

The actual value listed will have their meaning based
on the QoS it is on, the 'Type' indicates what logic
it would use to collate the information - Minimum,
Maximum, or Sum. Value is the collation of all requests.
This interface also compares the values with the defaults
for the QoS class and marks the ones that are
currently active.

Signed-off-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
---
 kernel/power/qos.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 89 insertions(+), 2 deletions(-)

diff --git a/kernel/power/qos.c b/kernel/power/qos.c
index 5f4c006..97b0df7 100644
--- a/kernel/power/qos.c
+++ b/kernel/power/qos.c
@@ -41,6 +41,8 @@
 #include <linux/platform_device.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
 
 #include <linux/uaccess.h>
 #include <linux/export.h>
@@ -182,6 +184,81 @@ static inline void pm_qos_set_value(struct pm_qos_constraints *c, s32 value)
 	c->target_value = value;
 }
 
+static inline int pm_qos_get_value(struct pm_qos_constraints *c);
+static int pm_qos_dbg_show_requests(struct seq_file *s, void *unused)
+{
+	struct pm_qos_object *qos = (struct pm_qos_object *)s->private;
+	struct pm_qos_constraints *c;
+	struct pm_qos_request *req;
+	char *type;
+	unsigned long flags;
+	int tot_reqs = 0;
+	int active_reqs = 0;
+
+	if (IS_ERR_OR_NULL(qos)) {
+		pr_err("%s: bad qos param!\n", __func__);
+		return -EINVAL;
+	}
+	c = qos->constraints;
+	if (IS_ERR_OR_NULL(c)) {
+		pr_err("%s: Bad constraints on qos?\n", __func__);
+		return -EINVAL;
+	}
+
+	/* Lock to ensure we have a snapshot */
+	spin_lock_irqsave(&pm_qos_lock, flags);
+	if (plist_head_empty(&c->list)) {
+		seq_puts(s, "Empty!\n");
+		goto out;
+	}
+
+	switch (c->type) {
+	case PM_QOS_MIN:
+		type = "Minimum";
+		break;
+	case PM_QOS_MAX:
+		type = "Maximum";
+		break;
+	case PM_QOS_SUM:
+		type = "Sum";
+		break;
+	default:
+		type = "Unknown";
+	}
+
+	plist_for_each_entry(req, &c->list, node) {
+		char *state = "Default";
+
+		if ((req->node).prio != c->default_value) {
+			active_reqs++;
+			state = "Active";
+		}
+		tot_reqs++;
+		seq_printf(s, "%d: %d: %s\n", tot_reqs,
+			   (req->node).prio, state);
+	}
+
+	seq_printf(s, "Type=%s, Value=%d, Requests: active=%d / total=%d\n",
+		   type, pm_qos_get_value(c), active_reqs, tot_reqs);
+
+out:
+	spin_unlock_irqrestore(&pm_qos_lock, flags);
+	return 0;
+}
+
+static int pm_qos_dbg_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, pm_qos_dbg_show_requests,
+			   inode->i_private);
+}
+
+static const struct file_operations pm_qos_debug_fops = {
+	.open           = pm_qos_dbg_open,
+	.read           = seq_read,
+	.llseek         = seq_lseek,
+	.release        = single_release,
+};
+
 /**
  * pm_qos_update_target - manages the constraints list and calls the notifiers
  *  if needed
@@ -509,12 +586,17 @@ int pm_qos_remove_notifier(int pm_qos_class, struct notifier_block *notifier)
 EXPORT_SYMBOL_GPL(pm_qos_remove_notifier);
 
 /* User space interface to PM QoS classes via misc devices */
-static int register_pm_qos_misc(struct pm_qos_object *qos)
+static int register_pm_qos_misc(struct pm_qos_object *qos, struct dentry *d)
 {
 	qos->pm_qos_power_miscdev.minor = MISC_DYNAMIC_MINOR;
 	qos->pm_qos_power_miscdev.name = qos->name;
 	qos->pm_qos_power_miscdev.fops = &pm_qos_power_fops;
 
+	if (d) {
+		(void)debugfs_create_file(qos->name, S_IRUGO, d,
+					  (void *)qos, &pm_qos_debug_fops);
+	}
+
 	return misc_register(&qos->pm_qos_power_miscdev);
 }
 
@@ -608,11 +690,16 @@ static int __init pm_qos_power_init(void)
 {
 	int ret = 0;
 	int i;
+	struct dentry *d;
 
 	BUILD_BUG_ON(ARRAY_SIZE(pm_qos_array) != PM_QOS_NUM_CLASSES);
 
+	d = debugfs_create_dir("pm_qos", NULL);
+	if (IS_ERR_OR_NULL(d))
+		d = NULL;
+
 	for (i = PM_QOS_CPU_DMA_LATENCY; i < PM_QOS_NUM_CLASSES; i++) {
-		ret = register_pm_qos_misc(pm_qos_array[i]);
+		ret = register_pm_qos_misc(pm_qos_array[i], d);
 		if (ret < 0) {
 			printk(KERN_ERR "pm_qos_param: %s setup failed\n",
 			       pm_qos_array[i]->name);
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] PM QoS: Add debugfs support to view the list of constraints
  2014-12-05 17:19 [PATCH] PM QoS: Add debugfs support to view the list of constraints Dave Gerlach
@ 2014-12-05 22:47 ` Rafael J. Wysocki
  2014-12-15 22:34 ` Kevin Hilman
  1 sibling, 0 replies; 4+ messages in thread
From: Rafael J. Wysocki @ 2014-12-05 22:47 UTC (permalink / raw)
  To: Dave Gerlach
  Cc: linux-kernel, linux-pm, Pavel Machek, Len Brown, Nishanth Menon

On Friday, December 05, 2014 11:19:08 AM Dave Gerlach wrote:
> From: Nishanth Menon <nm@ti.com>
> 
> PM QoS requests are notoriously hard to debug and made even
> more so due to their highly dynamic nature. Having visibility
> into the internal data representation per constraint allows
> us to have much better appreciation of potential issues or
> bad usage by drivers in the system.
> 
> So introduce for all classes of PM QoS, an entry in
> /sys/kernel/debug/pm_qos that shall show all the current
> requests as well as the snapshot of the value these requests
> boil down to. For example:
> ==> /sys/kernel/debug/pm_qos/cpu_dma_latency <==
> 1: 4444: Active
> 2: 2000000000: Default
> 3: 2000000000: Default
> 4: 2000000000: Default
> Type=Minimum, Value=4444, Requests: active=1 / total=4
> 
> ==> /sys/kernel/debug/pm_qos/memory_bandwidth <==
> Empty!
> 
> ...
> 
> The actual value listed will have their meaning based
> on the QoS it is on, the 'Type' indicates what logic
> it would use to collate the information - Minimum,
> Maximum, or Sum. Value is the collation of all requests.
> This interface also compares the values with the defaults
> for the QoS class and marks the ones that are
> currently active.
> 
> Signed-off-by: Nishanth Menon <nm@ti.com>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>

This is fine by me, but let's wait and see if there are any comments.

> ---
>  kernel/power/qos.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 89 insertions(+), 2 deletions(-)
> 
> diff --git a/kernel/power/qos.c b/kernel/power/qos.c
> index 5f4c006..97b0df7 100644
> --- a/kernel/power/qos.c
> +++ b/kernel/power/qos.c
> @@ -41,6 +41,8 @@
>  #include <linux/platform_device.h>
>  #include <linux/init.h>
>  #include <linux/kernel.h>
> +#include <linux/debugfs.h>
> +#include <linux/seq_file.h>
>  
>  #include <linux/uaccess.h>
>  #include <linux/export.h>
> @@ -182,6 +184,81 @@ static inline void pm_qos_set_value(struct pm_qos_constraints *c, s32 value)
>  	c->target_value = value;
>  }
>  
> +static inline int pm_qos_get_value(struct pm_qos_constraints *c);
> +static int pm_qos_dbg_show_requests(struct seq_file *s, void *unused)
> +{
> +	struct pm_qos_object *qos = (struct pm_qos_object *)s->private;
> +	struct pm_qos_constraints *c;
> +	struct pm_qos_request *req;
> +	char *type;
> +	unsigned long flags;
> +	int tot_reqs = 0;
> +	int active_reqs = 0;
> +
> +	if (IS_ERR_OR_NULL(qos)) {
> +		pr_err("%s: bad qos param!\n", __func__);
> +		return -EINVAL;
> +	}
> +	c = qos->constraints;
> +	if (IS_ERR_OR_NULL(c)) {
> +		pr_err("%s: Bad constraints on qos?\n", __func__);
> +		return -EINVAL;
> +	}
> +
> +	/* Lock to ensure we have a snapshot */
> +	spin_lock_irqsave(&pm_qos_lock, flags);
> +	if (plist_head_empty(&c->list)) {
> +		seq_puts(s, "Empty!\n");
> +		goto out;
> +	}
> +
> +	switch (c->type) {
> +	case PM_QOS_MIN:
> +		type = "Minimum";
> +		break;
> +	case PM_QOS_MAX:
> +		type = "Maximum";
> +		break;
> +	case PM_QOS_SUM:
> +		type = "Sum";
> +		break;
> +	default:
> +		type = "Unknown";
> +	}
> +
> +	plist_for_each_entry(req, &c->list, node) {
> +		char *state = "Default";
> +
> +		if ((req->node).prio != c->default_value) {
> +			active_reqs++;
> +			state = "Active";
> +		}
> +		tot_reqs++;
> +		seq_printf(s, "%d: %d: %s\n", tot_reqs,
> +			   (req->node).prio, state);
> +	}
> +
> +	seq_printf(s, "Type=%s, Value=%d, Requests: active=%d / total=%d\n",
> +		   type, pm_qos_get_value(c), active_reqs, tot_reqs);
> +
> +out:
> +	spin_unlock_irqrestore(&pm_qos_lock, flags);
> +	return 0;
> +}
> +
> +static int pm_qos_dbg_open(struct inode *inode, struct file *file)
> +{
> +	return single_open(file, pm_qos_dbg_show_requests,
> +			   inode->i_private);
> +}
> +
> +static const struct file_operations pm_qos_debug_fops = {
> +	.open           = pm_qos_dbg_open,
> +	.read           = seq_read,
> +	.llseek         = seq_lseek,
> +	.release        = single_release,
> +};
> +
>  /**
>   * pm_qos_update_target - manages the constraints list and calls the notifiers
>   *  if needed
> @@ -509,12 +586,17 @@ int pm_qos_remove_notifier(int pm_qos_class, struct notifier_block *notifier)
>  EXPORT_SYMBOL_GPL(pm_qos_remove_notifier);
>  
>  /* User space interface to PM QoS classes via misc devices */
> -static int register_pm_qos_misc(struct pm_qos_object *qos)
> +static int register_pm_qos_misc(struct pm_qos_object *qos, struct dentry *d)
>  {
>  	qos->pm_qos_power_miscdev.minor = MISC_DYNAMIC_MINOR;
>  	qos->pm_qos_power_miscdev.name = qos->name;
>  	qos->pm_qos_power_miscdev.fops = &pm_qos_power_fops;
>  
> +	if (d) {
> +		(void)debugfs_create_file(qos->name, S_IRUGO, d,
> +					  (void *)qos, &pm_qos_debug_fops);
> +	}
> +
>  	return misc_register(&qos->pm_qos_power_miscdev);
>  }
>  
> @@ -608,11 +690,16 @@ static int __init pm_qos_power_init(void)
>  {
>  	int ret = 0;
>  	int i;
> +	struct dentry *d;
>  
>  	BUILD_BUG_ON(ARRAY_SIZE(pm_qos_array) != PM_QOS_NUM_CLASSES);
>  
> +	d = debugfs_create_dir("pm_qos", NULL);
> +	if (IS_ERR_OR_NULL(d))
> +		d = NULL;
> +
>  	for (i = PM_QOS_CPU_DMA_LATENCY; i < PM_QOS_NUM_CLASSES; i++) {
> -		ret = register_pm_qos_misc(pm_qos_array[i]);
> +		ret = register_pm_qos_misc(pm_qos_array[i], d);
>  		if (ret < 0) {
>  			printk(KERN_ERR "pm_qos_param: %s setup failed\n",
>  			       pm_qos_array[i]->name);
> 

-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] PM QoS: Add debugfs support to view the list of constraints
  2014-12-05 17:19 [PATCH] PM QoS: Add debugfs support to view the list of constraints Dave Gerlach
  2014-12-05 22:47 ` Rafael J. Wysocki
@ 2014-12-15 22:34 ` Kevin Hilman
  2015-01-30  0:10   ` Rafael J. Wysocki
  1 sibling, 1 reply; 4+ messages in thread
From: Kevin Hilman @ 2014-12-15 22:34 UTC (permalink / raw)
  To: Dave Gerlach
  Cc: linux-kernel, linux-pm, Rafael J. Wysocki, Pavel Machek,
	Len Brown, Nishanth Menon

Dave Gerlach <d-gerlach@ti.com> writes:

> From: Nishanth Menon <nm@ti.com>
>
> PM QoS requests are notoriously hard to debug and made even
> more so due to their highly dynamic nature. Having visibility
> into the internal data representation per constraint allows
> us to have much better appreciation of potential issues or
> bad usage by drivers in the system.
>
> So introduce for all classes of PM QoS, an entry in
> /sys/kernel/debug/pm_qos that shall show all the current
> requests as well as the snapshot of the value these requests
> boil down to. For example:
> ==> /sys/kernel/debug/pm_qos/cpu_dma_latency <==
> 1: 4444: Active
> 2: 2000000000: Default
> 3: 2000000000: Default
> 4: 2000000000: Default
> Type=Minimum, Value=4444, Requests: active=1 / total=4
>
> ==> /sys/kernel/debug/pm_qos/memory_bandwidth <==
> Empty!
>
> ...
>
> The actual value listed will have their meaning based
> on the QoS it is on, the 'Type' indicates what logic
> it would use to collate the information - Minimum,
> Maximum, or Sum. Value is the collation of all requests.
> This interface also compares the values with the defaults
> for the QoS class and marks the ones that are
> currently active.
>
> Signed-off-by: Nishanth Menon <nm@ti.com>
> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>

A very useful feature indeed,

Acked-by: Kevin Hilman <khilman@linaro.org>

Kevin

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] PM QoS: Add debugfs support to view the list of constraints
  2014-12-15 22:34 ` Kevin Hilman
@ 2015-01-30  0:10   ` Rafael J. Wysocki
  0 siblings, 0 replies; 4+ messages in thread
From: Rafael J. Wysocki @ 2015-01-30  0:10 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: Dave Gerlach, linux-kernel, linux-pm, Pavel Machek, Len Brown,
	Nishanth Menon

On Monday, December 15, 2014 02:34:15 PM Kevin Hilman wrote:
> Dave Gerlach <d-gerlach@ti.com> writes:
> 
> > From: Nishanth Menon <nm@ti.com>
> >
> > PM QoS requests are notoriously hard to debug and made even
> > more so due to their highly dynamic nature. Having visibility
> > into the internal data representation per constraint allows
> > us to have much better appreciation of potential issues or
> > bad usage by drivers in the system.
> >
> > So introduce for all classes of PM QoS, an entry in
> > /sys/kernel/debug/pm_qos that shall show all the current
> > requests as well as the snapshot of the value these requests
> > boil down to. For example:
> > ==> /sys/kernel/debug/pm_qos/cpu_dma_latency <==
> > 1: 4444: Active
> > 2: 2000000000: Default
> > 3: 2000000000: Default
> > 4: 2000000000: Default
> > Type=Minimum, Value=4444, Requests: active=1 / total=4
> >
> > ==> /sys/kernel/debug/pm_qos/memory_bandwidth <==
> > Empty!
> >
> > ...
> >
> > The actual value listed will have their meaning based
> > on the QoS it is on, the 'Type' indicates what logic
> > it would use to collate the information - Minimum,
> > Maximum, or Sum. Value is the collation of all requests.
> > This interface also compares the values with the defaults
> > for the QoS class and marks the ones that are
> > currently active.
> >
> > Signed-off-by: Nishanth Menon <nm@ti.com>
> > Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
> 
> A very useful feature indeed,
> 
> Acked-by: Kevin Hilman <khilman@linaro.org>

Queued up for 3.20, thanks!


-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2015-01-29 23:48 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-12-05 17:19 [PATCH] PM QoS: Add debugfs support to view the list of constraints Dave Gerlach
2014-12-05 22:47 ` Rafael J. Wysocki
2014-12-15 22:34 ` Kevin Hilman
2015-01-30  0:10   ` Rafael J. Wysocki

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).