diff options
| -rw-r--r-- | drivers/base/power/qos.c | 60 |
1 files changed, 47 insertions, 13 deletions
diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c index 5f74587ef258..71671c42ef45 100644 --- a/drivers/base/power/qos.c +++ b/drivers/base/power/qos.c | |||
| @@ -46,6 +46,7 @@ | |||
| 46 | #include "power.h" | 46 | #include "power.h" |
| 47 | 47 | ||
| 48 | static DEFINE_MUTEX(dev_pm_qos_mtx); | 48 | static DEFINE_MUTEX(dev_pm_qos_mtx); |
| 49 | static DEFINE_MUTEX(dev_pm_qos_sysfs_mtx); | ||
| 49 | 50 | ||
| 50 | static BLOCKING_NOTIFIER_HEAD(dev_pm_notifiers); | 51 | static BLOCKING_NOTIFIER_HEAD(dev_pm_notifiers); |
| 51 | 52 | ||
| @@ -216,12 +217,17 @@ void dev_pm_qos_constraints_destroy(struct device *dev) | |||
| 216 | struct pm_qos_constraints *c; | 217 | struct pm_qos_constraints *c; |
| 217 | struct pm_qos_flags *f; | 218 | struct pm_qos_flags *f; |
| 218 | 219 | ||
| 219 | mutex_lock(&dev_pm_qos_mtx); | 220 | mutex_lock(&dev_pm_qos_sysfs_mtx); |
| 220 | 221 | ||
| 221 | /* | 222 | /* |
| 222 | * If the device's PM QoS resume latency limit or PM QoS flags have been | 223 | * If the device's PM QoS resume latency limit or PM QoS flags have been |
| 223 | * exposed to user space, they have to be hidden at this point. | 224 | * exposed to user space, they have to be hidden at this point. |
| 224 | */ | 225 | */ |
| 226 | pm_qos_sysfs_remove_latency(dev); | ||
| 227 | pm_qos_sysfs_remove_flags(dev); | ||
| 228 | |||
| 229 | mutex_lock(&dev_pm_qos_mtx); | ||
| 230 | |||
| 225 | __dev_pm_qos_hide_latency_limit(dev); | 231 | __dev_pm_qos_hide_latency_limit(dev); |
| 226 | __dev_pm_qos_hide_flags(dev); | 232 | __dev_pm_qos_hide_flags(dev); |
| 227 | 233 | ||
| @@ -254,6 +260,8 @@ void dev_pm_qos_constraints_destroy(struct device *dev) | |||
| 254 | 260 | ||
| 255 | out: | 261 | out: |
| 256 | mutex_unlock(&dev_pm_qos_mtx); | 262 | mutex_unlock(&dev_pm_qos_mtx); |
| 263 | |||
| 264 | mutex_unlock(&dev_pm_qos_sysfs_mtx); | ||
| 257 | } | 265 | } |
| 258 | 266 | ||
| 259 | /** | 267 | /** |
| @@ -558,6 +566,14 @@ static void __dev_pm_qos_drop_user_request(struct device *dev, | |||
| 558 | kfree(req); | 566 | kfree(req); |
| 559 | } | 567 | } |
| 560 | 568 | ||
| 569 | static void dev_pm_qos_drop_user_request(struct device *dev, | ||
| 570 | enum dev_pm_qos_req_type type) | ||
| 571 | { | ||
| 572 | mutex_lock(&dev_pm_qos_mtx); | ||
| 573 | __dev_pm_qos_drop_user_request(dev, type); | ||
| 574 | mutex_unlock(&dev_pm_qos_mtx); | ||
| 575 | } | ||
| 576 | |||
| 561 | /** | 577 | /** |
| 562 | * dev_pm_qos_expose_latency_limit - Expose PM QoS latency limit to user space. | 578 | * dev_pm_qos_expose_latency_limit - Expose PM QoS latency limit to user space. |
| 563 | * @dev: Device whose PM QoS latency limit is to be exposed to user space. | 579 | * @dev: Device whose PM QoS latency limit is to be exposed to user space. |
| @@ -581,6 +597,8 @@ int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value) | |||
| 581 | return ret; | 597 | return ret; |
| 582 | } | 598 | } |
| 583 | 599 | ||
| 600 | mutex_lock(&dev_pm_qos_sysfs_mtx); | ||
| 601 | |||
| 584 | mutex_lock(&dev_pm_qos_mtx); | 602 | mutex_lock(&dev_pm_qos_mtx); |
| 585 | 603 | ||
| 586 | if (IS_ERR_OR_NULL(dev->power.qos)) | 604 | if (IS_ERR_OR_NULL(dev->power.qos)) |
| @@ -591,26 +609,27 @@ int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value) | |||
| 591 | if (ret < 0) { | 609 | if (ret < 0) { |
| 592 | __dev_pm_qos_remove_request(req); | 610 | __dev_pm_qos_remove_request(req); |
| 593 | kfree(req); | 611 | kfree(req); |
| 612 | mutex_unlock(&dev_pm_qos_mtx); | ||
| 594 | goto out; | 613 | goto out; |
| 595 | } | 614 | } |
| 596 | |||
| 597 | dev->power.qos->latency_req = req; | 615 | dev->power.qos->latency_req = req; |
| 616 | |||
| 617 | mutex_unlock(&dev_pm_qos_mtx); | ||
| 618 | |||
| 598 | ret = pm_qos_sysfs_add_latency(dev); | 619 | ret = pm_qos_sysfs_add_latency(dev); |
| 599 | if (ret) | 620 | if (ret) |
| 600 | __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY); | 621 | dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY); |
| 601 | 622 | ||
| 602 | out: | 623 | out: |
| 603 | mutex_unlock(&dev_pm_qos_mtx); | 624 | mutex_unlock(&dev_pm_qos_sysfs_mtx); |
| 604 | return ret; | 625 | return ret; |
| 605 | } | 626 | } |
| 606 | EXPORT_SYMBOL_GPL(dev_pm_qos_expose_latency_limit); | 627 | EXPORT_SYMBOL_GPL(dev_pm_qos_expose_latency_limit); |
| 607 | 628 | ||
| 608 | static void __dev_pm_qos_hide_latency_limit(struct device *dev) | 629 | static void __dev_pm_qos_hide_latency_limit(struct device *dev) |
| 609 | { | 630 | { |
| 610 | if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->latency_req) { | 631 | if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->latency_req) |
| 611 | pm_qos_sysfs_remove_latency(dev); | ||
| 612 | __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY); | 632 | __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY); |
| 613 | } | ||
| 614 | } | 633 | } |
| 615 | 634 | ||
| 616 | /** | 635 | /** |
| @@ -619,9 +638,15 @@ static void __dev_pm_qos_hide_latency_limit(struct device *dev) | |||
| 619 | */ | 638 | */ |
| 620 | void dev_pm_qos_hide_latency_limit(struct device *dev) | 639 | void dev_pm_qos_hide_latency_limit(struct device *dev) |
| 621 | { | 640 | { |
| 641 | mutex_lock(&dev_pm_qos_sysfs_mtx); | ||
| 642 | |||
| 643 | pm_qos_sysfs_remove_latency(dev); | ||
| 644 | |||
| 622 | mutex_lock(&dev_pm_qos_mtx); | 645 | mutex_lock(&dev_pm_qos_mtx); |
| 623 | __dev_pm_qos_hide_latency_limit(dev); | 646 | __dev_pm_qos_hide_latency_limit(dev); |
| 624 | mutex_unlock(&dev_pm_qos_mtx); | 647 | mutex_unlock(&dev_pm_qos_mtx); |
| 648 | |||
| 649 | mutex_unlock(&dev_pm_qos_sysfs_mtx); | ||
| 625 | } | 650 | } |
| 626 | EXPORT_SYMBOL_GPL(dev_pm_qos_hide_latency_limit); | 651 | EXPORT_SYMBOL_GPL(dev_pm_qos_hide_latency_limit); |
| 627 | 652 | ||
| @@ -649,6 +674,8 @@ int dev_pm_qos_expose_flags(struct device *dev, s32 val) | |||
| 649 | } | 674 | } |
| 650 | 675 | ||
| 651 | pm_runtime_get_sync(dev); | 676 | pm_runtime_get_sync(dev); |
| 677 | mutex_lock(&dev_pm_qos_sysfs_mtx); | ||
| 678 | |||
| 652 | mutex_lock(&dev_pm_qos_mtx); | 679 | mutex_lock(&dev_pm_qos_mtx); |
| 653 | 680 | ||
| 654 | if (IS_ERR_OR_NULL(dev->power.qos)) | 681 | if (IS_ERR_OR_NULL(dev->power.qos)) |
| @@ -659,16 +686,19 @@ int dev_pm_qos_expose_flags(struct device *dev, s32 val) | |||
| 659 | if (ret < 0) { | 686 | if (ret < 0) { |
| 660 | __dev_pm_qos_remove_request(req); | 687 | __dev_pm_qos_remove_request(req); |
| 661 | kfree(req); | 688 | kfree(req); |
| 689 | mutex_unlock(&dev_pm_qos_mtx); | ||
| 662 | goto out; | 690 | goto out; |
| 663 | } | 691 | } |
| 664 | |||
| 665 | dev->power.qos->flags_req = req; | 692 | dev->power.qos->flags_req = req; |
| 693 | |||
| 694 | mutex_unlock(&dev_pm_qos_mtx); | ||
| 695 | |||
| 666 | ret = pm_qos_sysfs_add_flags(dev); | 696 | ret = pm_qos_sysfs_add_flags(dev); |
| 667 | if (ret) | 697 | if (ret) |
| 668 | __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS); | 698 | dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS); |
| 669 | 699 | ||
| 670 | out: | 700 | out: |
| 671 | mutex_unlock(&dev_pm_qos_mtx); | 701 | mutex_unlock(&dev_pm_qos_sysfs_mtx); |
| 672 | pm_runtime_put(dev); | 702 | pm_runtime_put(dev); |
| 673 | return ret; | 703 | return ret; |
| 674 | } | 704 | } |
| @@ -676,10 +706,8 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_expose_flags); | |||
| 676 | 706 | ||
| 677 | static void __dev_pm_qos_hide_flags(struct device *dev) | 707 | static void __dev_pm_qos_hide_flags(struct device *dev) |
| 678 | { | 708 | { |
| 679 | if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->flags_req) { | 709 | if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->flags_req) |
| 680 | pm_qos_sysfs_remove_flags(dev); | ||
| 681 | __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS); | 710 | __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS); |
| 682 | } | ||
| 683 | } | 711 | } |
| 684 | 712 | ||
| 685 | /** | 713 | /** |
| @@ -689,9 +717,15 @@ static void __dev_pm_qos_hide_flags(struct device *dev) | |||
| 689 | void dev_pm_qos_hide_flags(struct device *dev) | 717 | void dev_pm_qos_hide_flags(struct device *dev) |
| 690 | { | 718 | { |
| 691 | pm_runtime_get_sync(dev); | 719 | pm_runtime_get_sync(dev); |
| 720 | mutex_lock(&dev_pm_qos_sysfs_mtx); | ||
| 721 | |||
| 722 | pm_qos_sysfs_remove_flags(dev); | ||
| 723 | |||
| 692 | mutex_lock(&dev_pm_qos_mtx); | 724 | mutex_lock(&dev_pm_qos_mtx); |
| 693 | __dev_pm_qos_hide_flags(dev); | 725 | __dev_pm_qos_hide_flags(dev); |
| 694 | mutex_unlock(&dev_pm_qos_mtx); | 726 | mutex_unlock(&dev_pm_qos_mtx); |
| 727 | |||
| 728 | mutex_unlock(&dev_pm_qos_sysfs_mtx); | ||
| 695 | pm_runtime_put(dev); | 729 | pm_runtime_put(dev); |
| 696 | } | 730 | } |
| 697 | EXPORT_SYMBOL_GPL(dev_pm_qos_hide_flags); | 731 | EXPORT_SYMBOL_GPL(dev_pm_qos_hide_flags); |
