All of lore.kernel.org
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: Maciej Matraszek <m.matraszek@samsung.com>
Cc: linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org,
	"Rafael J. Wysocki" <rjw@rjwysocki.net>,
	Len Brown <len.brown@intel.com>, Pavel Machek <pavel@ucw.cz>,
	Krzysztof Kozlowski <k.kozlowski@samsung.com>,
	Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Subject: Re: [PATCH] PM / Domains: add debugfs listing of struct generic_pm_domain-s
Date: Wed, 10 Sep 2014 07:43:40 -0700	[thread overview]
Message-ID: <20140910144340.GA17967@kroah.com> (raw)
In-Reply-To: <1410348536-15201-1-git-send-email-m.matraszek@samsung.com>

On Wed, Sep 10, 2014 at 01:28:56PM +0200, Maciej Matraszek wrote:
> Add /sys/kernel/debug/pm_genpd/pm_genpd_summary file, which
> lists power domains in the system, their statuses and attached devices,
> resembling /sys/kernel/debug/clk/clk_summary.
> 
> Currently it is impossible to inspect (from userland) whether
> a power domain is on or off. And, if it is on, which device blocks it
> from powering down. This change allows developers working on
> embedded devices power efficiency to list all necessary information
> about generic power domains in one place.
> 
> The content of pm_genpd/pm_genpd_summary file is generated by iterating
> over all generic power domain in the system, and, for each,
> over registered devices.
> 
> Example output:
> $ cat  /sys/kernel/debug/pm_genpd/pm_genpd_summary
>     domain                      status         slaves
>            /device                                      runtime status
> ----------------------------------------------------------------------
> isp-power-domain                off
>     /devices/soc/12180000.fimc-is                       suspended
>     /devices/soc/12180000.fimc-is/120a0000.fimc-lite    suspended
> lcd0-power-domain               on
>     /devices/soc/11c80000.dsi                           active
>     /devices/soc/11c00000.fimd                          active
>     /devices/soc/11e20000.sysmmu                        suspended
> g3d-power-domain                off
>     /devices/soc/13001000.gpu                           suspended
> mfc-power-domain                off
>     /devices/soc/13400000.mfc-codec                     suspended
>     /devices/soc/13620000.sysmmu                        suspended
> cam-power-domain                off
>     /devices/soc/11830000.jpeg-codec                    suspended
>     /devices/soc/11a60000.sysmmu                        suspended
>     /devices/soc/12180000.fimc-is/120c0000.csis         suspended
> 
> To enable this feature, compile the kernel with debugfs
> and CONFIG_PM_ADVANCED_DEBUG enabled.
> 
> Signed-off-by: Maciej Matraszek <m.matraszek@samsung.com>
> ---
>  drivers/base/power/domain.c | 153 ++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 153 insertions(+)
> 
> diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
> index eee55c1e5fde..d1aa731ba0db 100644
> --- a/drivers/base/power/domain.c
> +++ b/drivers/base/power/domain.c
> @@ -2189,3 +2189,156 @@ void pm_genpd_init(struct generic_pm_domain *genpd,
>  	list_add(&genpd->gpd_list_node, &gpd_list);
>  	mutex_unlock(&gpd_list_lock);
>  }
> +
> +
> +/***        debugfs support        ***/
> +
> +#ifdef CONFIG_PM_ADVANCED_DEBUG
> +#include <linux/pm.h>
> +#include <linux/device.h>
> +#include <linux/debugfs.h>
> +#include <linux/kobject.h>
> +static struct dentry *pm_genpd_debugfs_dir;
> +
> +/*
> + * TODO: This function is a slightly modified version of rtpm_status_show
> + * from sysfs.c, but dependencies between PM_GENERIC_DOMAINS and PM_RUNTIME
> + * are too loose to generalize it.
> + */
> +#ifdef CONFIG_PM_RUNTIME
> +static void rtpm_status_str(struct seq_file *s, struct device *dev)
> +{
> +	static const char * const status_lookup[] = {
> +		[RPM_ACTIVE] = "active",
> +		[RPM_RESUMING] = "resuming",
> +		[RPM_SUSPENDED] = "suspended",
> +		[RPM_SUSPENDING] = "suspending"
> +	};
> +	const char *p = "";
> +
> +	if (dev->power.runtime_error)
> +		p = "error";
> +	else if (dev->power.disable_depth)
> +		p = "unsupported";
> +	else if (dev->power.runtime_status < ARRAY_SIZE(status_lookup))
> +		p = status_lookup[dev->power.runtime_status];
> +	else
> +		WARN_ON(1);
> +
> +	seq_puts(s, p);
> +}
> +#else
> +static void rtpm_status_str(struct seq_file *s, struct device *dev)
> +{
> +	seq_puts(s, "active");
> +}
> +#endif
> +
> +static int pm_genpd_summary_one(struct seq_file *s,
> +		struct generic_pm_domain *gpd)
> +{
> +	static const char * const status_lookup[] = {
> +		[GPD_STATE_ACTIVE] = "on",
> +		[GPD_STATE_WAIT_MASTER] = "wait-master",
> +		[GPD_STATE_BUSY] = "busy",
> +		[GPD_STATE_REPEAT] = "off-in-progress",
> +		[GPD_STATE_POWER_OFF] = "off"
> +	};
> +	struct pm_domain_data *pm_data;
> +	const char *kobj_path;
> +	struct gpd_link *link;
> +	int ret;
> +
> +	ret = mutex_lock_interruptible(&gpd->lock);
> +	if (ret)
> +		return -ERESTARTSYS;
> +
> +	if (WARN_ON(gpd->status >= ARRAY_SIZE(status_lookup)))
> +		goto exit;
> +	seq_printf(s, "%-30s  %-15s  ", gpd->name, status_lookup[gpd->status]);
> +
> +	/*
> +	 * Modifications on the list require holding locks on both
> +	 * master and slave, so we are safe.
> +	 * Also gpd->name is immutable.
> +	 */
> +	list_for_each_entry(link, &gpd->master_links, master_node) {
> +		seq_printf(s, "%s", link->slave->name);
> +		if (!list_is_last(&link->master_node, &gpd->master_links))
> +			seq_puts(s, ", ");
> +	}
> +
> +	list_for_each_entry(pm_data, &gpd->dev_list, list_node) {
> +		kobj_path = kobject_get_path(&pm_data->dev->kobj, GFP_KERNEL);
> +		if (kobj_path == NULL)
> +			continue;
> +
> +		seq_printf(s, "\n    %-50s  ", kobj_path);
> +		rtpm_status_str(s, pm_data->dev);
> +		kfree(kobj_path);
> +	}
> +
> +	seq_puts(s, "\n");
> +exit:
> +	mutex_unlock(&gpd->lock);
> +
> +	return 0;
> +}
> +
> +static int pm_genpd_summary_show(struct seq_file *s, void *data)
> +{
> +	struct generic_pm_domain *gpd;
> +	int ret = 0;
> +
> +	seq_puts(s, "    domain                      status         slaves\n");
> +	seq_puts(s, "           /device                                      runtime status\n");
> +	seq_puts(s, "----------------------------------------------------------------------\n");
> +
> +	ret = mutex_lock_interruptible(&gpd_list_lock);
> +	if (ret)
> +		return -ERESTARTSYS;
> +
> +	list_for_each_entry(gpd, &gpd_list, gpd_list_node) {
> +		ret = pm_genpd_summary_one(s, gpd);
> +		if (ret)
> +			break;
> +	}
> +	mutex_unlock(&gpd_list_lock);
> +
> +	return ret;
> +}
> +
> +static int pm_genpd_summary_open(struct inode *inode, struct file *file)
> +{
> +	return single_open(file, pm_genpd_summary_show, inode->i_private);
> +}
> +
> +static const struct file_operations pm_genpd_summary_fops = {
> +	.open = pm_genpd_summary_open,
> +	.read = seq_read,
> +	.llseek = seq_lseek,
> +	.release = single_release,
> +};
> +
> +static int __init pm_genpd_debug_init(void)
> +{
> +	struct dentry *d;
> +
> +	pm_genpd_debugfs_dir = debugfs_create_dir("pm_genpd", NULL);
> +
> +	/* No debugfs */
> +	if (IS_ERR(pm_genpd_debugfs_dir))
> +		return PTR_ERR(pm_genpd_debugfs_dir);

You shouldn't care at all, just do this check:

> +	if (!pm_genpd_debugfs_dir)
> +		return -ENOMEM;

And all will be fine, because:

> +	d = debugfs_create_file("pm_genpd_summary", S_IRUGO,
> +			pm_genpd_debugfs_dir, NULL, &pm_genpd_summary_fops);

That call will resolve away to nothing if debugfs is not enabled, and it
doesn't make much sense to do anything with an "error" of no debugfs.

> +	if (!d)
> +		return -ENOMEM;
> +
> +	return 0;
> +}
> +late_initcall(pm_genpd_debug_init);
> +#endif /* CONFIG_PM_ADVANCED_DEBUG */

No tear-down of the debugfs files on shutdown?

thanks,

greg k-h

  reply	other threads:[~2014-09-10 14:44 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-09-10 11:28 [PATCH] PM / Domains: add debugfs listing of struct generic_pm_domain-s Maciej Matraszek
2014-09-10 14:43 ` Greg Kroah-Hartman [this message]
2014-09-10 15:38   ` Maciej Matraszek
2014-09-10 18:27     ` Greg Kroah-Hartman
2014-09-11 17:02       ` Maciej Matraszek
2014-09-10 19:18 ` Al Viro
2014-09-11 16:52   ` Maciej Matraszek
2014-09-11  8:51 ` Geert Uytterhoeven
2014-09-11  8:51   ` Geert Uytterhoeven
2014-09-11 16:45   ` Maciej Matraszek
2014-09-11 16:45     ` Maciej Matraszek
2014-09-11 17:27     ` Geert Uytterhoeven
2014-09-11 17:27       ` Geert Uytterhoeven
2014-09-12 16:19       ` Maciej Matraszek
2014-09-12 16:19         ` Maciej Matraszek
2014-09-17 11:09         ` Geert Uytterhoeven
2014-09-17 11:09           ` Geert Uytterhoeven

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20140910144340.GA17967@kroah.com \
    --to=gregkh@linuxfoundation.org \
    --cc=b.zolnierkie@samsung.com \
    --cc=k.kozlowski@samsung.com \
    --cc=len.brown@intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=m.matraszek@samsung.com \
    --cc=pavel@ucw.cz \
    --cc=rjw@rjwysocki.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.