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

Reply via email to