aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/power/opp/core.c
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2015-11-10 21:29:01 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-11-23 17:38:23 -0500
commitdeaa51465105a7eda19a627b10372f4f7c51a4df (patch)
tree1ebf1d9d36eaa0d9061bcae5e7704e92681a9268 /drivers/base/power/opp/core.c
parent1ec218373b8ebda821aec00bb156a9c94fad9cd4 (diff)
PM / OPP: Add debugfs support
This patch adds debugfs support to OPP layer to export OPPs and their properties for all the devices. This creates a top level directory: /sys/kernel/debug/opp and then device specific directories (based on device names) inside it. For example: 'cpu0', 'cpu1', etc.. If multiple devices share the OPP table, then the real directory is created only for the first device. For all others, links are created to the real directory. Inside the device specific directory, a separate directory is created for each OPP. And within that files per opp property. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Stephen Boyd <sboyd@codeaurora.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/base/power/opp/core.c')
-rw-r--r--drivers/base/power/opp/core.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/drivers/base/power/opp/core.c b/drivers/base/power/opp/core.c
index b8e76f75073b..6aa172be6e8e 100644
--- a/drivers/base/power/opp/core.c
+++ b/drivers/base/power/opp/core.c
@@ -463,6 +463,7 @@ static void _kfree_list_dev_rcu(struct rcu_head *head)
463static void _remove_list_dev(struct device_list_opp *list_dev, 463static void _remove_list_dev(struct device_list_opp *list_dev,
464 struct device_opp *dev_opp) 464 struct device_opp *dev_opp)
465{ 465{
466 opp_debug_unregister(list_dev, dev_opp);
466 list_del(&list_dev->node); 467 list_del(&list_dev->node);
467 call_srcu(&dev_opp->srcu_head.srcu, &list_dev->rcu_head, 468 call_srcu(&dev_opp->srcu_head.srcu, &list_dev->rcu_head,
468 _kfree_list_dev_rcu); 469 _kfree_list_dev_rcu);
@@ -472,6 +473,7 @@ struct device_list_opp *_add_list_dev(const struct device *dev,
472 struct device_opp *dev_opp) 473 struct device_opp *dev_opp)
473{ 474{
474 struct device_list_opp *list_dev; 475 struct device_list_opp *list_dev;
476 int ret;
475 477
476 list_dev = kzalloc(sizeof(*list_dev), GFP_KERNEL); 478 list_dev = kzalloc(sizeof(*list_dev), GFP_KERNEL);
477 if (!list_dev) 479 if (!list_dev)
@@ -481,6 +483,12 @@ struct device_list_opp *_add_list_dev(const struct device *dev,
481 list_dev->dev = dev; 483 list_dev->dev = dev;
482 list_add_rcu(&list_dev->node, &dev_opp->dev_list); 484 list_add_rcu(&list_dev->node, &dev_opp->dev_list);
483 485
486 /* Create debugfs entries for the dev_opp */
487 ret = opp_debug_register(list_dev, dev_opp);
488 if (ret)
489 dev_err(dev, "%s: Failed to register opp debugfs (%d)\n",
490 __func__, ret);
491
484 return list_dev; 492 return list_dev;
485} 493}
486 494
@@ -596,6 +604,7 @@ static void _opp_remove(struct device_opp *dev_opp,
596 */ 604 */
597 if (notify) 605 if (notify)
598 srcu_notifier_call_chain(&dev_opp->srcu_head, OPP_EVENT_REMOVE, opp); 606 srcu_notifier_call_chain(&dev_opp->srcu_head, OPP_EVENT_REMOVE, opp);
607 opp_debug_remove_one(opp);
599 list_del_rcu(&opp->node); 608 list_del_rcu(&opp->node);
600 call_srcu(&dev_opp->srcu_head.srcu, &opp->rcu_head, _kfree_opp_rcu); 609 call_srcu(&dev_opp->srcu_head.srcu, &opp->rcu_head, _kfree_opp_rcu);
601 610
@@ -673,6 +682,7 @@ static int _opp_add(struct device *dev, struct dev_pm_opp *new_opp,
673{ 682{
674 struct dev_pm_opp *opp; 683 struct dev_pm_opp *opp;
675 struct list_head *head = &dev_opp->opp_list; 684 struct list_head *head = &dev_opp->opp_list;
685 int ret;
676 686
677 /* 687 /*
678 * Insert new OPP in order of increasing frequency and discard if 688 * Insert new OPP in order of increasing frequency and discard if
@@ -703,6 +713,11 @@ static int _opp_add(struct device *dev, struct dev_pm_opp *new_opp,
703 new_opp->dev_opp = dev_opp; 713 new_opp->dev_opp = dev_opp;
704 list_add_rcu(&new_opp->node, head); 714 list_add_rcu(&new_opp->node, head);
705 715
716 ret = opp_debug_create_one(new_opp, dev_opp);
717 if (ret)
718 dev_err(dev, "%s: Failed to register opp to debugfs (%d)\n",
719 __func__, ret);
720
706 return 0; 721 return 0;
707} 722}
708 723
@@ -889,12 +904,14 @@ static int _opp_add_static_v2(struct device *dev, struct device_node *np)
889 904
890 /* OPP to select on device suspend */ 905 /* OPP to select on device suspend */
891 if (of_property_read_bool(np, "opp-suspend")) { 906 if (of_property_read_bool(np, "opp-suspend")) {
892 if (dev_opp->suspend_opp) 907 if (dev_opp->suspend_opp) {
893 dev_warn(dev, "%s: Multiple suspend OPPs found (%lu %lu)\n", 908 dev_warn(dev, "%s: Multiple suspend OPPs found (%lu %lu)\n",
894 __func__, dev_opp->suspend_opp->rate, 909 __func__, dev_opp->suspend_opp->rate,
895 new_opp->rate); 910 new_opp->rate);
896 else 911 } else {
912 new_opp->suspend = true;
897 dev_opp->suspend_opp = new_opp; 913 dev_opp->suspend_opp = new_opp;
914 }
898 } 915 }
899 916
900 if (new_opp->clock_latency_ns > dev_opp->clock_latency_ns_max) 917 if (new_opp->clock_latency_ns > dev_opp->clock_latency_ns_max)