diff options
| author | Viresh Kumar <viresh.kumar@linaro.org> | 2017-01-22 23:41:46 -0500 |
|---|---|---|
| committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2017-01-30 03:22:21 -0500 |
| commit | 7034764a1e4a6edbb60914e89aad8384e3fe5d17 (patch) | |
| tree | b12ca30409bb79882cc25cae16beeeed236d4b9c /drivers/base | |
| parent | b83c1899a0e98cabd0997531434e1fb3b6574db8 (diff) | |
PM / OPP: Add 'struct kref' to struct dev_pm_opp
Add kref to struct dev_pm_opp for easier accounting of the OPPs.
Note that the OPPs are freed under the opp_table->lock mutex only.
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')
| -rw-r--r-- | drivers/base/power/opp/core.c | 27 | ||||
| -rw-r--r-- | drivers/base/power/opp/opp.h | 3 |
2 files changed, 15 insertions, 15 deletions
diff --git a/drivers/base/power/opp/core.c b/drivers/base/power/opp/core.c index ab9499e3ba02..9870ee54d708 100644 --- a/drivers/base/power/opp/core.c +++ b/drivers/base/power/opp/core.c | |||
| @@ -949,20 +949,10 @@ static void _kfree_opp_rcu(struct rcu_head *head) | |||
| 949 | kfree_rcu(opp, rcu_head); | 949 | kfree_rcu(opp, rcu_head); |
| 950 | } | 950 | } |
| 951 | 951 | ||
| 952 | /** | 952 | static void _opp_kref_release(struct kref *kref) |
| 953 | * _opp_remove() - Remove an OPP from a table definition | ||
| 954 | * @opp_table: points back to the opp_table struct this opp belongs to | ||
| 955 | * @opp: pointer to the OPP to remove | ||
| 956 | * | ||
| 957 | * This function removes an opp definition from the opp table. | ||
| 958 | * | ||
| 959 | * Locking: The internal opp_table and opp structures are RCU protected. | ||
| 960 | * It is assumed that the caller holds required mutex for an RCU updater | ||
| 961 | * strategy. | ||
| 962 | */ | ||
| 963 | static void _opp_remove(struct opp_table *opp_table, struct dev_pm_opp *opp) | ||
| 964 | { | 953 | { |
| 965 | mutex_lock(&opp_table->lock); | 954 | struct dev_pm_opp *opp = container_of(kref, struct dev_pm_opp, kref); |
| 955 | struct opp_table *opp_table = opp->opp_table; | ||
| 966 | 956 | ||
| 967 | /* | 957 | /* |
| 968 | * Notify the changes in the availability of the operable | 958 | * Notify the changes in the availability of the operable |
| @@ -977,6 +967,12 @@ static void _opp_remove(struct opp_table *opp_table, struct dev_pm_opp *opp) | |||
| 977 | dev_pm_opp_put_opp_table(opp_table); | 967 | dev_pm_opp_put_opp_table(opp_table); |
| 978 | } | 968 | } |
| 979 | 969 | ||
| 970 | void dev_pm_opp_put(struct dev_pm_opp *opp) | ||
| 971 | { | ||
| 972 | kref_put_mutex(&opp->kref, _opp_kref_release, &opp->opp_table->lock); | ||
| 973 | } | ||
| 974 | EXPORT_SYMBOL_GPL(dev_pm_opp_put); | ||
| 975 | |||
| 980 | /** | 976 | /** |
| 981 | * dev_pm_opp_remove() - Remove an OPP from OPP table | 977 | * dev_pm_opp_remove() - Remove an OPP from OPP table |
| 982 | * @dev: device for which we do this operation | 978 | * @dev: device for which we do this operation |
| @@ -1020,7 +1016,7 @@ void dev_pm_opp_remove(struct device *dev, unsigned long freq) | |||
| 1020 | goto unlock; | 1016 | goto unlock; |
| 1021 | } | 1017 | } |
| 1022 | 1018 | ||
| 1023 | _opp_remove(opp_table, opp); | 1019 | dev_pm_opp_put(opp); |
| 1024 | unlock: | 1020 | unlock: |
| 1025 | mutex_unlock(&opp_table_lock); | 1021 | mutex_unlock(&opp_table_lock); |
| 1026 | } | 1022 | } |
| @@ -1124,6 +1120,7 @@ int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, | |||
| 1124 | mutex_unlock(&opp_table->lock); | 1120 | mutex_unlock(&opp_table->lock); |
| 1125 | 1121 | ||
| 1126 | new_opp->opp_table = opp_table; | 1122 | new_opp->opp_table = opp_table; |
| 1123 | kref_init(&new_opp->kref); | ||
| 1127 | 1124 | ||
| 1128 | /* Get a reference to the OPP table */ | 1125 | /* Get a reference to the OPP table */ |
| 1129 | _get_opp_table_kref(opp_table); | 1126 | _get_opp_table_kref(opp_table); |
| @@ -1819,7 +1816,7 @@ void _dev_pm_opp_remove_table(struct opp_table *opp_table, struct device *dev, | |||
| 1819 | /* Free static OPPs */ | 1816 | /* Free static OPPs */ |
| 1820 | list_for_each_entry_safe(opp, tmp, &opp_table->opp_list, node) { | 1817 | list_for_each_entry_safe(opp, tmp, &opp_table->opp_list, node) { |
| 1821 | if (remove_all || !opp->dynamic) | 1818 | if (remove_all || !opp->dynamic) |
| 1822 | _opp_remove(opp_table, opp); | 1819 | dev_pm_opp_put(opp); |
| 1823 | } | 1820 | } |
| 1824 | } else { | 1821 | } else { |
| 1825 | _remove_opp_dev(_find_opp_dev(dev, opp_table), opp_table); | 1822 | _remove_opp_dev(_find_opp_dev(dev, opp_table), opp_table); |
diff --git a/drivers/base/power/opp/opp.h b/drivers/base/power/opp/opp.h index a01724363347..586f36f94e28 100644 --- a/drivers/base/power/opp/opp.h +++ b/drivers/base/power/opp/opp.h | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | 16 | ||
| 17 | #include <linux/device.h> | 17 | #include <linux/device.h> |
| 18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
| 19 | #include <linux/kref.h> | ||
| 19 | #include <linux/list.h> | 20 | #include <linux/list.h> |
| 20 | #include <linux/limits.h> | 21 | #include <linux/limits.h> |
| 21 | #include <linux/pm_opp.h> | 22 | #include <linux/pm_opp.h> |
| @@ -56,6 +57,7 @@ extern struct list_head opp_tables; | |||
| 56 | * are protected by the opp_table_lock for integrity. | 57 | * are protected by the opp_table_lock for integrity. |
| 57 | * IMPORTANT: the opp nodes should be maintained in increasing | 58 | * IMPORTANT: the opp nodes should be maintained in increasing |
| 58 | * order. | 59 | * order. |
| 60 | * @kref: for reference count of the OPP. | ||
| 59 | * @available: true/false - marks if this OPP as available or not | 61 | * @available: true/false - marks if this OPP as available or not |
| 60 | * @dynamic: not-created from static DT entries. | 62 | * @dynamic: not-created from static DT entries. |
| 61 | * @turbo: true if turbo (boost) OPP | 63 | * @turbo: true if turbo (boost) OPP |
| @@ -73,6 +75,7 @@ extern struct list_head opp_tables; | |||
| 73 | */ | 75 | */ |
| 74 | struct dev_pm_opp { | 76 | struct dev_pm_opp { |
| 75 | struct list_head node; | 77 | struct list_head node; |
| 78 | struct kref kref; | ||
| 76 | 79 | ||
| 77 | bool available; | 80 | bool available; |
| 78 | bool dynamic; | 81 | bool dynamic; |
