lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <2285210.ohmJzh2omj@vostro.rjw.lan>
Date:	Fri, 05 Dec 2014 23:47:19 +0100
From:	"Rafael J. Wysocki" <rjw@...ysocki.net>
To:	Dave Gerlach <d-gerlach@...com>
Cc:	linux-kernel@...r.kernel.org, linux-pm@...r.kernel.org,
	Pavel Machek <pavel@....cz>, Len Brown <len.brown@...el.com>,
	Nishanth Menon <nm@...com>
Subject: Re: [PATCH] PM QoS: Add debugfs support to view the list of constraints

On Friday, December 05, 2014 11:19:08 AM Dave Gerlach wrote:
> From: Nishanth Menon <nm@...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@...com>
> Signed-off-by: Dave Gerlach <d-gerlach@...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.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ