diff options
| author | Jisheng Zhang <jszhang@marvell.com> | 2016-07-25 02:11:16 -0400 |
|---|---|---|
| committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2016-07-28 17:54:16 -0400 |
| commit | 067b7ce083df6c69e67345bdba658ab59274cc01 (patch) | |
| tree | 868c5698b001c902fbad61e4afb9b8c2b1581536 /drivers/base/power | |
| parent | 523d939ef98fd712632d93a5a2b588e477a7565e (diff) | |
PM / OPP: optimize dev_pm_opp_set_rate() performance a bit
In dev_pm_opp_set_rate(), _find_opp_table() is called 4 times: once by
_get_opp_clk(), once by dev_pm_opp_set_rate() itself, and twice by
dev_pm_opp_find_freq_ceil(). If there are several opp_tables in the
system, three times of opp table finding is a big waste. This patch
reduced the call of _find_opp_table() to twice.
Signed-off-by: Jisheng Zhang <jszhang@marvell.com>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/base/power')
| -rw-r--r-- | drivers/base/power/opp/core.c | 31 |
1 files changed, 19 insertions, 12 deletions
diff --git a/drivers/base/power/opp/core.c b/drivers/base/power/opp/core.c index 7c04c87738a6..df0c70963d9e 100644 --- a/drivers/base/power/opp/core.c +++ b/drivers/base/power/opp/core.c | |||
| @@ -402,6 +402,22 @@ struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev, | |||
| 402 | } | 402 | } |
| 403 | EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_exact); | 403 | EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_exact); |
| 404 | 404 | ||
| 405 | static noinline struct dev_pm_opp *_find_freq_ceil(struct opp_table *opp_table, | ||
| 406 | unsigned long *freq) | ||
| 407 | { | ||
| 408 | struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE); | ||
| 409 | |||
| 410 | list_for_each_entry_rcu(temp_opp, &opp_table->opp_list, node) { | ||
| 411 | if (temp_opp->available && temp_opp->rate >= *freq) { | ||
| 412 | opp = temp_opp; | ||
| 413 | *freq = opp->rate; | ||
| 414 | break; | ||
| 415 | } | ||
| 416 | } | ||
| 417 | |||
| 418 | return opp; | ||
| 419 | } | ||
| 420 | |||
| 405 | /** | 421 | /** |
| 406 | * dev_pm_opp_find_freq_ceil() - Search for an rounded ceil freq | 422 | * dev_pm_opp_find_freq_ceil() - Search for an rounded ceil freq |
| 407 | * @dev: device for which we do this operation | 423 | * @dev: device for which we do this operation |
| @@ -427,7 +443,6 @@ struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev, | |||
| 427 | unsigned long *freq) | 443 | unsigned long *freq) |
| 428 | { | 444 | { |
| 429 | struct opp_table *opp_table; | 445 | struct opp_table *opp_table; |
| 430 | struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE); | ||
| 431 | 446 | ||
| 432 | opp_rcu_lockdep_assert(); | 447 | opp_rcu_lockdep_assert(); |
| 433 | 448 | ||
| @@ -440,15 +455,7 @@ struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev, | |||
| 440 | if (IS_ERR(opp_table)) | 455 | if (IS_ERR(opp_table)) |
| 441 | return ERR_CAST(opp_table); | 456 | return ERR_CAST(opp_table); |
| 442 | 457 | ||
| 443 | list_for_each_entry_rcu(temp_opp, &opp_table->opp_list, node) { | 458 | return _find_freq_ceil(opp_table, freq); |
| 444 | if (temp_opp->available && temp_opp->rate >= *freq) { | ||
| 445 | opp = temp_opp; | ||
| 446 | *freq = opp->rate; | ||
| 447 | break; | ||
| 448 | } | ||
| 449 | } | ||
| 450 | |||
| 451 | return opp; | ||
| 452 | } | 459 | } |
| 453 | EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_ceil); | 460 | EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_ceil); |
| 454 | 461 | ||
| @@ -612,7 +619,7 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq) | |||
| 612 | return PTR_ERR(opp_table); | 619 | return PTR_ERR(opp_table); |
| 613 | } | 620 | } |
| 614 | 621 | ||
| 615 | old_opp = dev_pm_opp_find_freq_ceil(dev, &old_freq); | 622 | old_opp = _find_freq_ceil(opp_table, &old_freq); |
| 616 | if (!IS_ERR(old_opp)) { | 623 | if (!IS_ERR(old_opp)) { |
| 617 | ou_volt = old_opp->u_volt; | 624 | ou_volt = old_opp->u_volt; |
| 618 | ou_volt_min = old_opp->u_volt_min; | 625 | ou_volt_min = old_opp->u_volt_min; |
| @@ -622,7 +629,7 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq) | |||
| 622 | __func__, old_freq, PTR_ERR(old_opp)); | 629 | __func__, old_freq, PTR_ERR(old_opp)); |
| 623 | } | 630 | } |
| 624 | 631 | ||
| 625 | opp = dev_pm_opp_find_freq_ceil(dev, &freq); | 632 | opp = _find_freq_ceil(opp_table, &freq); |
| 626 | if (IS_ERR(opp)) { | 633 | if (IS_ERR(opp)) { |
| 627 | ret = PTR_ERR(opp); | 634 | ret = PTR_ERR(opp); |
| 628 | dev_err(dev, "%s: failed to find OPP for freq %lu (%d)\n", | 635 | dev_err(dev, "%s: failed to find OPP for freq %lu (%d)\n", |
