diff options
author | Viresh Kumar <viresh.kumar@linaro.org> | 2015-11-10 21:29:01 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2015-11-23 17:38:23 -0500 |
commit | deaa51465105a7eda19a627b10372f4f7c51a4df (patch) | |
tree | 1ebf1d9d36eaa0d9061bcae5e7704e92681a9268 /drivers/base/power/opp/core.c | |
parent | 1ec218373b8ebda821aec00bb156a9c94fad9cd4 (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.c | 21 |
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) | |||
463 | static void _remove_list_dev(struct device_list_opp *list_dev, | 463 | static 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) |