diff options
| author | Viresh Kumar <viresh.kumar@linaro.org> | 2017-01-02 04:11:03 -0500 |
|---|---|---|
| committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2017-01-27 05:49:09 -0500 |
| commit | dc2c9ad52af45ebecf9743aacb1916ebb2f1e848 (patch) | |
| tree | 41001b1691bdad8d1b52a63561ffa9659d5412bd /drivers | |
| parent | 3aa26a3b2ea63c4d09420e74421370655aa1cf8f (diff) | |
PM / OPP: Don't expose srcu_head to register notifiers
Let the OPP core provide helpers to register notifiers for any device,
instead of exposing srcu_head outside of the core.
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Acked-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/base/power/opp/core.c | 66 | ||||
| -rw-r--r-- | drivers/devfreq/devfreq.c | 26 |
2 files changed, 52 insertions, 40 deletions
diff --git a/drivers/base/power/opp/core.c b/drivers/base/power/opp/core.c index 614d779ab6a2..f35effad60d1 100644 --- a/drivers/base/power/opp/core.c +++ b/drivers/base/power/opp/core.c | |||
| @@ -1860,29 +1860,63 @@ int dev_pm_opp_disable(struct device *dev, unsigned long freq) | |||
| 1860 | EXPORT_SYMBOL_GPL(dev_pm_opp_disable); | 1860 | EXPORT_SYMBOL_GPL(dev_pm_opp_disable); |
| 1861 | 1861 | ||
| 1862 | /** | 1862 | /** |
| 1863 | * dev_pm_opp_get_notifier() - find notifier_head of the device with opp | 1863 | * dev_pm_opp_register_notifier() - Register OPP notifier for the device |
| 1864 | * @dev: device pointer used to lookup OPP table. | 1864 | * @dev: Device for which notifier needs to be registered |
| 1865 | * @nb: Notifier block to be registered | ||
| 1865 | * | 1866 | * |
| 1866 | * Return: pointer to notifier head if found, otherwise -ENODEV or | 1867 | * Return: 0 on success or a negative error value. |
| 1867 | * -EINVAL based on type of error casted as pointer. value must be checked | 1868 | */ |
| 1868 | * with IS_ERR to determine valid pointer or error result. | 1869 | int dev_pm_opp_register_notifier(struct device *dev, struct notifier_block *nb) |
| 1870 | { | ||
| 1871 | struct opp_table *opp_table; | ||
| 1872 | int ret; | ||
| 1873 | |||
| 1874 | rcu_read_lock(); | ||
| 1875 | |||
| 1876 | opp_table = _find_opp_table(dev); | ||
| 1877 | if (IS_ERR(opp_table)) { | ||
| 1878 | ret = PTR_ERR(opp_table); | ||
| 1879 | goto unlock; | ||
| 1880 | } | ||
| 1881 | |||
| 1882 | ret = srcu_notifier_chain_register(&opp_table->srcu_head, nb); | ||
| 1883 | |||
| 1884 | unlock: | ||
| 1885 | rcu_read_unlock(); | ||
| 1886 | |||
| 1887 | return ret; | ||
| 1888 | } | ||
| 1889 | EXPORT_SYMBOL(dev_pm_opp_register_notifier); | ||
| 1890 | |||
| 1891 | /** | ||
| 1892 | * dev_pm_opp_unregister_notifier() - Unregister OPP notifier for the device | ||
| 1893 | * @dev: Device for which notifier needs to be unregistered | ||
| 1894 | * @nb: Notifier block to be unregistered | ||
| 1869 | * | 1895 | * |
| 1870 | * Locking: This function must be called under rcu_read_lock(). opp_table is a | 1896 | * Return: 0 on success or a negative error value. |
| 1871 | * RCU protected pointer. The reason for the same is that the opp pointer which | ||
| 1872 | * is returned will remain valid for use with opp_get_{voltage, freq} only while | ||
| 1873 | * under the locked area. The pointer returned must be used prior to unlocking | ||
| 1874 | * with rcu_read_unlock() to maintain the integrity of the pointer. | ||
| 1875 | */ | 1897 | */ |
| 1876 | struct srcu_notifier_head *dev_pm_opp_get_notifier(struct device *dev) | 1898 | int dev_pm_opp_unregister_notifier(struct device *dev, |
| 1899 | struct notifier_block *nb) | ||
| 1877 | { | 1900 | { |
| 1878 | struct opp_table *opp_table = _find_opp_table(dev); | 1901 | struct opp_table *opp_table; |
| 1902 | int ret; | ||
| 1879 | 1903 | ||
| 1880 | if (IS_ERR(opp_table)) | 1904 | rcu_read_lock(); |
| 1881 | return ERR_CAST(opp_table); /* matching type */ | 1905 | |
| 1906 | opp_table = _find_opp_table(dev); | ||
| 1907 | if (IS_ERR(opp_table)) { | ||
| 1908 | ret = PTR_ERR(opp_table); | ||
| 1909 | goto unlock; | ||
| 1910 | } | ||
| 1911 | |||
| 1912 | ret = srcu_notifier_chain_unregister(&opp_table->srcu_head, nb); | ||
| 1882 | 1913 | ||
| 1883 | return &opp_table->srcu_head; | 1914 | unlock: |
| 1915 | rcu_read_unlock(); | ||
| 1916 | |||
| 1917 | return ret; | ||
| 1884 | } | 1918 | } |
| 1885 | EXPORT_SYMBOL_GPL(dev_pm_opp_get_notifier); | 1919 | EXPORT_SYMBOL(dev_pm_opp_unregister_notifier); |
| 1886 | 1920 | ||
| 1887 | /* | 1921 | /* |
| 1888 | * Free OPPs either created using static entries present in DT or even the | 1922 | * Free OPPs either created using static entries present in DT or even the |
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 47206a21bb90..a545c0fee6e1 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c | |||
| @@ -1265,18 +1265,7 @@ EXPORT_SYMBOL(devfreq_recommended_opp); | |||
| 1265 | */ | 1265 | */ |
| 1266 | int devfreq_register_opp_notifier(struct device *dev, struct devfreq *devfreq) | 1266 | int devfreq_register_opp_notifier(struct device *dev, struct devfreq *devfreq) |
| 1267 | { | 1267 | { |
| 1268 | struct srcu_notifier_head *nh; | 1268 | return dev_pm_opp_register_notifier(dev, &devfreq->nb); |
| 1269 | int ret = 0; | ||
| 1270 | |||
| 1271 | rcu_read_lock(); | ||
| 1272 | nh = dev_pm_opp_get_notifier(dev); | ||
| 1273 | if (IS_ERR(nh)) | ||
| 1274 | ret = PTR_ERR(nh); | ||
| 1275 | rcu_read_unlock(); | ||
| 1276 | if (!ret) | ||
| 1277 | ret = srcu_notifier_chain_register(nh, &devfreq->nb); | ||
| 1278 | |||
| 1279 | return ret; | ||
| 1280 | } | 1269 | } |
| 1281 | EXPORT_SYMBOL(devfreq_register_opp_notifier); | 1270 | EXPORT_SYMBOL(devfreq_register_opp_notifier); |
| 1282 | 1271 | ||
| @@ -1292,18 +1281,7 @@ EXPORT_SYMBOL(devfreq_register_opp_notifier); | |||
| 1292 | */ | 1281 | */ |
| 1293 | int devfreq_unregister_opp_notifier(struct device *dev, struct devfreq *devfreq) | 1282 | int devfreq_unregister_opp_notifier(struct device *dev, struct devfreq *devfreq) |
| 1294 | { | 1283 | { |
| 1295 | struct srcu_notifier_head *nh; | 1284 | return dev_pm_opp_unregister_notifier(dev, &devfreq->nb); |
| 1296 | int ret = 0; | ||
| 1297 | |||
| 1298 | rcu_read_lock(); | ||
| 1299 | nh = dev_pm_opp_get_notifier(dev); | ||
| 1300 | if (IS_ERR(nh)) | ||
| 1301 | ret = PTR_ERR(nh); | ||
| 1302 | rcu_read_unlock(); | ||
| 1303 | if (!ret) | ||
| 1304 | ret = srcu_notifier_chain_unregister(nh, &devfreq->nb); | ||
| 1305 | |||
| 1306 | return ret; | ||
| 1307 | } | 1285 | } |
| 1308 | EXPORT_SYMBOL(devfreq_unregister_opp_notifier); | 1286 | EXPORT_SYMBOL(devfreq_unregister_opp_notifier); |
| 1309 | 1287 | ||
