diff options
| -rw-r--r-- | Documentation/power/opp.txt | 25 | ||||
| -rw-r--r-- | drivers/acpi/glue.c | 55 | ||||
| -rw-r--r-- | drivers/acpi/processor_core.c | 3 | ||||
| -rw-r--r-- | drivers/acpi/processor_driver.c | 2 | ||||
| -rw-r--r-- | drivers/acpi/sleep.c | 16 | ||||
| -rw-r--r-- | drivers/ata/libata-acpi.c | 7 | ||||
| -rw-r--r-- | drivers/base/power/main.c | 2 | ||||
| -rw-r--r-- | drivers/base/power/power.h | 8 | ||||
| -rw-r--r-- | drivers/base/power/qos.c | 217 | ||||
| -rw-r--r-- | drivers/base/power/sysfs.c | 1 | ||||
| -rw-r--r-- | drivers/cpufreq/cpufreq_governor.h | 2 | ||||
| -rw-r--r-- | drivers/cpufreq/highbank-cpufreq.c | 8 | ||||
| -rw-r--r-- | drivers/cpufreq/intel_pstate.c | 42 | ||||
| -rw-r--r-- | drivers/mailbox/pl320-ipc.c | 3 | ||||
| -rw-r--r-- | drivers/pci/pci-acpi.c | 8 | ||||
| -rw-r--r-- | drivers/pnp/pnpacpi/core.c | 8 | ||||
| -rw-r--r-- | drivers/scsi/scsi_lib.c | 7 | ||||
| -rw-r--r-- | drivers/usb/core/usb-acpi.c | 9 | ||||
| -rw-r--r-- | include/acpi/acpi_bus.h | 6 |
19 files changed, 215 insertions, 214 deletions
diff --git a/Documentation/power/opp.txt b/Documentation/power/opp.txt index 3035d00757ad..425c51d56aef 100644 --- a/Documentation/power/opp.txt +++ b/Documentation/power/opp.txt | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | *=============* | 1 | Operating Performance Points (OPP) Library |
| 2 | * OPP Library * | 2 | ========================================== |
| 3 | *=============* | ||
| 4 | 3 | ||
| 5 | (C) 2009-2010 Nishanth Menon <nm@ti.com>, Texas Instruments Incorporated | 4 | (C) 2009-2010 Nishanth Menon <nm@ti.com>, Texas Instruments Incorporated |
| 6 | 5 | ||
| @@ -16,15 +15,31 @@ Contents | |||
| 16 | 15 | ||
| 17 | 1. Introduction | 16 | 1. Introduction |
| 18 | =============== | 17 | =============== |
| 18 | 1.1 What is an Operating Performance Point (OPP)? | ||
| 19 | |||
| 19 | Complex SoCs of today consists of a multiple sub-modules working in conjunction. | 20 | Complex SoCs of today consists of a multiple sub-modules working in conjunction. |
| 20 | In an operational system executing varied use cases, not all modules in the SoC | 21 | In an operational system executing varied use cases, not all modules in the SoC |
| 21 | need to function at their highest performing frequency all the time. To | 22 | need to function at their highest performing frequency all the time. To |
| 22 | facilitate this, sub-modules in a SoC are grouped into domains, allowing some | 23 | facilitate this, sub-modules in a SoC are grouped into domains, allowing some |
| 23 | domains to run at lower voltage and frequency while other domains are loaded | 24 | domains to run at lower voltage and frequency while other domains run at |
| 24 | more. The set of discrete tuples consisting of frequency and voltage pairs that | 25 | voltage/frequency pairs that are higher. |
| 26 | |||
| 27 | The set of discrete tuples consisting of frequency and voltage pairs that | ||
| 25 | the device will support per domain are called Operating Performance Points or | 28 | the device will support per domain are called Operating Performance Points or |
| 26 | OPPs. | 29 | OPPs. |
| 27 | 30 | ||
| 31 | As an example: | ||
| 32 | Let us consider an MPU device which supports the following: | ||
| 33 | {300MHz at minimum voltage of 1V}, {800MHz at minimum voltage of 1.2V}, | ||
| 34 | {1GHz at minimum voltage of 1.3V} | ||
| 35 | |||
| 36 | We can represent these as three OPPs as the following {Hz, uV} tuples: | ||
| 37 | {300000000, 1000000} | ||
| 38 | {800000000, 1200000} | ||
| 39 | {1000000000, 1300000} | ||
| 40 | |||
| 41 | 1.2 Operating Performance Points Library | ||
| 42 | |||
| 28 | OPP library provides a set of helper functions to organize and query the OPP | 43 | OPP library provides a set of helper functions to organize and query the OPP |
| 29 | information. The library is located in drivers/base/power/opp.c and the header | 44 | information. The library is located in drivers/base/power/opp.c and the header |
| 30 | is located in include/linux/opp.h. OPP library can be enabled by enabling | 45 | is located in include/linux/opp.h. OPP library can be enabled by enabling |
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index ef6f155469b5..40a84cc6740c 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c | |||
| @@ -36,12 +36,11 @@ int register_acpi_bus_type(struct acpi_bus_type *type) | |||
| 36 | { | 36 | { |
| 37 | if (acpi_disabled) | 37 | if (acpi_disabled) |
| 38 | return -ENODEV; | 38 | return -ENODEV; |
| 39 | if (type && type->bus && type->find_device) { | 39 | if (type && type->match && type->find_device) { |
| 40 | down_write(&bus_type_sem); | 40 | down_write(&bus_type_sem); |
| 41 | list_add_tail(&type->list, &bus_type_list); | 41 | list_add_tail(&type->list, &bus_type_list); |
| 42 | up_write(&bus_type_sem); | 42 | up_write(&bus_type_sem); |
| 43 | printk(KERN_INFO PREFIX "bus type %s registered\n", | 43 | printk(KERN_INFO PREFIX "bus type %s registered\n", type->name); |
| 44 | type->bus->name); | ||
| 45 | return 0; | 44 | return 0; |
| 46 | } | 45 | } |
| 47 | return -ENODEV; | 46 | return -ENODEV; |
| @@ -56,24 +55,21 @@ int unregister_acpi_bus_type(struct acpi_bus_type *type) | |||
| 56 | down_write(&bus_type_sem); | 55 | down_write(&bus_type_sem); |
| 57 | list_del_init(&type->list); | 56 | list_del_init(&type->list); |
| 58 | up_write(&bus_type_sem); | 57 | up_write(&bus_type_sem); |
| 59 | printk(KERN_INFO PREFIX "ACPI bus type %s unregistered\n", | 58 | printk(KERN_INFO PREFIX "bus type %s unregistered\n", |
| 60 | type->bus->name); | 59 | type->name); |
| 61 | return 0; | 60 | return 0; |
| 62 | } | 61 | } |
| 63 | return -ENODEV; | 62 | return -ENODEV; |
| 64 | } | 63 | } |
| 65 | EXPORT_SYMBOL_GPL(unregister_acpi_bus_type); | 64 | EXPORT_SYMBOL_GPL(unregister_acpi_bus_type); |
| 66 | 65 | ||
| 67 | static struct acpi_bus_type *acpi_get_bus_type(struct bus_type *type) | 66 | static struct acpi_bus_type *acpi_get_bus_type(struct device *dev) |
| 68 | { | 67 | { |
| 69 | struct acpi_bus_type *tmp, *ret = NULL; | 68 | struct acpi_bus_type *tmp, *ret = NULL; |
| 70 | 69 | ||
| 71 | if (!type) | ||
| 72 | return NULL; | ||
| 73 | |||
| 74 | down_read(&bus_type_sem); | 70 | down_read(&bus_type_sem); |
| 75 | list_for_each_entry(tmp, &bus_type_list, list) { | 71 | list_for_each_entry(tmp, &bus_type_list, list) { |
| 76 | if (tmp->bus == type) { | 72 | if (tmp->match(dev)) { |
| 77 | ret = tmp; | 73 | ret = tmp; |
| 78 | break; | 74 | break; |
| 79 | } | 75 | } |
| @@ -82,22 +78,6 @@ static struct acpi_bus_type *acpi_get_bus_type(struct bus_type *type) | |||
| 82 | return ret; | 78 | return ret; |
| 83 | } | 79 | } |
| 84 | 80 | ||
| 85 | static int acpi_find_bridge_device(struct device *dev, acpi_handle * handle) | ||
| 86 | { | ||
| 87 | struct acpi_bus_type *tmp; | ||
| 88 | int ret = -ENODEV; | ||
| 89 | |||
| 90 | down_read(&bus_type_sem); | ||
| 91 | list_for_each_entry(tmp, &bus_type_list, list) { | ||
| 92 | if (tmp->find_bridge && !tmp->find_bridge(dev, handle)) { | ||
| 93 | ret = 0; | ||
| 94 | break; | ||
| 95 | } | ||
| 96 | } | ||
| 97 | up_read(&bus_type_sem); | ||
| 98 | return ret; | ||
| 99 | } | ||
| 100 | |||
| 101 | static acpi_status do_acpi_find_child(acpi_handle handle, u32 lvl_not_used, | 81 | static acpi_status do_acpi_find_child(acpi_handle handle, u32 lvl_not_used, |
| 102 | void *addr_p, void **ret_p) | 82 | void *addr_p, void **ret_p) |
| 103 | { | 83 | { |
| @@ -261,29 +241,12 @@ err: | |||
| 261 | 241 | ||
| 262 | static int acpi_platform_notify(struct device *dev) | 242 | static int acpi_platform_notify(struct device *dev) |
| 263 | { | 243 | { |
| 264 | struct acpi_bus_type *type; | 244 | struct acpi_bus_type *type = acpi_get_bus_type(dev); |
| 265 | acpi_handle handle; | 245 | acpi_handle handle; |
| 266 | int ret; | 246 | int ret; |
| 267 | 247 | ||
| 268 | ret = acpi_bind_one(dev, NULL); | 248 | ret = acpi_bind_one(dev, NULL); |
| 269 | if (ret && (!dev->bus || !dev->parent)) { | 249 | if (ret && type) { |
| 270 | /* bridge devices genernally haven't bus or parent */ | ||
| 271 | ret = acpi_find_bridge_device(dev, &handle); | ||
| 272 | if (!ret) { | ||
| 273 | ret = acpi_bind_one(dev, handle); | ||
| 274 | if (ret) | ||
| 275 | goto out; | ||
| 276 | } | ||
| 277 | } | ||
| 278 | |||
| 279 | type = acpi_get_bus_type(dev->bus); | ||
| 280 | if (ret) { | ||
| 281 | if (!type || !type->find_device) { | ||
| 282 | DBG("No ACPI bus support for %s\n", dev_name(dev)); | ||
| 283 | ret = -EINVAL; | ||
| 284 | goto out; | ||
| 285 | } | ||
| 286 | |||
| 287 | ret = type->find_device(dev, &handle); | 250 | ret = type->find_device(dev, &handle); |
| 288 | if (ret) { | 251 | if (ret) { |
| 289 | DBG("Unable to get handle for %s\n", dev_name(dev)); | 252 | DBG("Unable to get handle for %s\n", dev_name(dev)); |
| @@ -316,7 +279,7 @@ static int acpi_platform_notify_remove(struct device *dev) | |||
| 316 | { | 279 | { |
| 317 | struct acpi_bus_type *type; | 280 | struct acpi_bus_type *type; |
| 318 | 281 | ||
| 319 | type = acpi_get_bus_type(dev->bus); | 282 | type = acpi_get_bus_type(dev); |
| 320 | if (type && type->cleanup) | 283 | if (type && type->cleanup) |
| 321 | type->cleanup(dev); | 284 | type->cleanup(dev); |
| 322 | 285 | ||
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index eff722278ff5..164d49569aeb 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c | |||
| @@ -158,8 +158,7 @@ static int map_mat_entry(acpi_handle handle, int type, u32 acpi_id) | |||
| 158 | } | 158 | } |
| 159 | 159 | ||
| 160 | exit: | 160 | exit: |
| 161 | if (buffer.pointer) | 161 | kfree(buffer.pointer); |
| 162 | kfree(buffer.pointer); | ||
| 163 | return apic_id; | 162 | return apic_id; |
| 164 | } | 163 | } |
| 165 | 164 | ||
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index df34bd04ae62..bec717ffd25f 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c | |||
| @@ -559,7 +559,7 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device) | |||
| 559 | return 0; | 559 | return 0; |
| 560 | #endif | 560 | #endif |
| 561 | 561 | ||
| 562 | BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0)); | 562 | BUG_ON(pr->id >= nr_cpu_ids); |
| 563 | 563 | ||
| 564 | /* | 564 | /* |
| 565 | * Buggy BIOS check | 565 | * Buggy BIOS check |
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 6d3a06a629a1..24213033fbae 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c | |||
| @@ -599,7 +599,6 @@ static void acpi_sleep_suspend_setup(void) | |||
| 599 | status = acpi_get_sleep_type_data(i, &type_a, &type_b); | 599 | status = acpi_get_sleep_type_data(i, &type_a, &type_b); |
| 600 | if (ACPI_SUCCESS(status)) { | 600 | if (ACPI_SUCCESS(status)) { |
| 601 | sleep_states[i] = 1; | 601 | sleep_states[i] = 1; |
| 602 | pr_cont(" S%d", i); | ||
| 603 | } | 602 | } |
| 604 | } | 603 | } |
| 605 | 604 | ||
| @@ -742,7 +741,6 @@ static void acpi_sleep_hibernate_setup(void) | |||
| 742 | hibernation_set_ops(old_suspend_ordering ? | 741 | hibernation_set_ops(old_suspend_ordering ? |
| 743 | &acpi_hibernation_ops_old : &acpi_hibernation_ops); | 742 | &acpi_hibernation_ops_old : &acpi_hibernation_ops); |
| 744 | sleep_states[ACPI_STATE_S4] = 1; | 743 | sleep_states[ACPI_STATE_S4] = 1; |
| 745 | pr_cont(KERN_CONT " S4"); | ||
| 746 | if (nosigcheck) | 744 | if (nosigcheck) |
| 747 | return; | 745 | return; |
| 748 | 746 | ||
| @@ -788,6 +786,9 @@ int __init acpi_sleep_init(void) | |||
| 788 | { | 786 | { |
| 789 | acpi_status status; | 787 | acpi_status status; |
| 790 | u8 type_a, type_b; | 788 | u8 type_a, type_b; |
| 789 | char supported[ACPI_S_STATE_COUNT * 3 + 1]; | ||
| 790 | char *pos = supported; | ||
| 791 | int i; | ||
| 791 | 792 | ||
| 792 | if (acpi_disabled) | 793 | if (acpi_disabled) |
| 793 | return 0; | 794 | return 0; |
| @@ -795,7 +796,6 @@ int __init acpi_sleep_init(void) | |||
| 795 | acpi_sleep_dmi_check(); | 796 | acpi_sleep_dmi_check(); |
| 796 | 797 | ||
| 797 | sleep_states[ACPI_STATE_S0] = 1; | 798 | sleep_states[ACPI_STATE_S0] = 1; |
| 798 | pr_info(PREFIX "(supports S0"); | ||
| 799 | 799 | ||
| 800 | acpi_sleep_suspend_setup(); | 800 | acpi_sleep_suspend_setup(); |
| 801 | acpi_sleep_hibernate_setup(); | 801 | acpi_sleep_hibernate_setup(); |
| @@ -803,11 +803,17 @@ int __init acpi_sleep_init(void) | |||
| 803 | status = acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b); | 803 | status = acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b); |
| 804 | if (ACPI_SUCCESS(status)) { | 804 | if (ACPI_SUCCESS(status)) { |
| 805 | sleep_states[ACPI_STATE_S5] = 1; | 805 | sleep_states[ACPI_STATE_S5] = 1; |
| 806 | pr_cont(" S5"); | ||
| 807 | pm_power_off_prepare = acpi_power_off_prepare; | 806 | pm_power_off_prepare = acpi_power_off_prepare; |
| 808 | pm_power_off = acpi_power_off; | 807 | pm_power_off = acpi_power_off; |
| 809 | } | 808 | } |
| 810 | pr_cont(")\n"); | 809 | |
| 810 | supported[0] = 0; | ||
| 811 | for (i = 0; i < ACPI_S_STATE_COUNT; i++) { | ||
| 812 | if (sleep_states[i]) | ||
| 813 | pos += sprintf(pos, " S%d", i); | ||
| 814 | } | ||
| 815 | pr_info(PREFIX "(supports%s)\n", supported); | ||
| 816 | |||
| 811 | /* | 817 | /* |
| 812 | * Register the tts_notifier to reboot notifier list so that the _TTS | 818 | * Register the tts_notifier to reboot notifier list so that the _TTS |
| 813 | * object can also be evaluated when the system enters S5. | 819 | * object can also be evaluated when the system enters S5. |
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index 0ea1018280bd..beea3115577e 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c | |||
| @@ -1144,13 +1144,8 @@ static int ata_acpi_find_device(struct device *dev, acpi_handle *handle) | |||
| 1144 | return -ENODEV; | 1144 | return -ENODEV; |
| 1145 | } | 1145 | } |
| 1146 | 1146 | ||
| 1147 | static int ata_acpi_find_dummy(struct device *dev, acpi_handle *handle) | ||
| 1148 | { | ||
| 1149 | return -ENODEV; | ||
| 1150 | } | ||
| 1151 | |||
| 1152 | static struct acpi_bus_type ata_acpi_bus = { | 1147 | static struct acpi_bus_type ata_acpi_bus = { |
| 1153 | .find_bridge = ata_acpi_find_dummy, | 1148 | .name = "ATA", |
| 1154 | .find_device = ata_acpi_find_device, | 1149 | .find_device = ata_acpi_find_device, |
| 1155 | }; | 1150 | }; |
| 1156 | 1151 | ||
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 2b7f77d3fcb0..15beb500a4e4 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
| @@ -99,7 +99,6 @@ void device_pm_add(struct device *dev) | |||
| 99 | dev_warn(dev, "parent %s should not be sleeping\n", | 99 | dev_warn(dev, "parent %s should not be sleeping\n", |
| 100 | dev_name(dev->parent)); | 100 | dev_name(dev->parent)); |
| 101 | list_add_tail(&dev->power.entry, &dpm_list); | 101 | list_add_tail(&dev->power.entry, &dpm_list); |
| 102 | dev_pm_qos_constraints_init(dev); | ||
| 103 | mutex_unlock(&dpm_list_mtx); | 102 | mutex_unlock(&dpm_list_mtx); |
| 104 | } | 103 | } |
| 105 | 104 | ||
| @@ -113,7 +112,6 @@ void device_pm_remove(struct device *dev) | |||
| 113 | dev->bus ? dev->bus->name : "No Bus", dev_name(dev)); | 112 | dev->bus ? dev->bus->name : "No Bus", dev_name(dev)); |
| 114 | complete_all(&dev->power.completion); | 113 | complete_all(&dev->power.completion); |
| 115 | mutex_lock(&dpm_list_mtx); | 114 | mutex_lock(&dpm_list_mtx); |
| 116 | dev_pm_qos_constraints_destroy(dev); | ||
| 117 | list_del_init(&dev->power.entry); | 115 | list_del_init(&dev->power.entry); |
| 118 | mutex_unlock(&dpm_list_mtx); | 116 | mutex_unlock(&dpm_list_mtx); |
| 119 | device_wakeup_disable(dev); | 117 | device_wakeup_disable(dev); |
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h index b16686a0a5a2..cfc3226ec492 100644 --- a/drivers/base/power/power.h +++ b/drivers/base/power/power.h | |||
| @@ -4,7 +4,7 @@ static inline void device_pm_init_common(struct device *dev) | |||
| 4 | { | 4 | { |
| 5 | if (!dev->power.early_init) { | 5 | if (!dev->power.early_init) { |
| 6 | spin_lock_init(&dev->power.lock); | 6 | spin_lock_init(&dev->power.lock); |
| 7 | dev->power.power_state = PMSG_INVALID; | 7 | dev->power.qos = NULL; |
| 8 | dev->power.early_init = true; | 8 | dev->power.early_init = true; |
| 9 | } | 9 | } |
| 10 | } | 10 | } |
| @@ -56,14 +56,10 @@ extern void device_pm_move_last(struct device *); | |||
| 56 | 56 | ||
| 57 | static inline void device_pm_sleep_init(struct device *dev) {} | 57 | static inline void device_pm_sleep_init(struct device *dev) {} |
| 58 | 58 | ||
| 59 | static inline void device_pm_add(struct device *dev) | 59 | static inline void device_pm_add(struct device *dev) {} |
| 60 | { | ||
| 61 | dev_pm_qos_constraints_init(dev); | ||
| 62 | } | ||
| 63 | 60 | ||
| 64 | static inline void device_pm_remove(struct device *dev) | 61 | static inline void device_pm_remove(struct device *dev) |
| 65 | { | 62 | { |
| 66 | dev_pm_qos_constraints_destroy(dev); | ||
| 67 | pm_runtime_remove(dev); | 63 | pm_runtime_remove(dev); |
| 68 | } | 64 | } |
| 69 | 65 | ||
diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c index 3d4d1f8aac5c..5f74587ef258 100644 --- a/drivers/base/power/qos.c +++ b/drivers/base/power/qos.c | |||
| @@ -41,6 +41,7 @@ | |||
| 41 | #include <linux/mutex.h> | 41 | #include <linux/mutex.h> |
| 42 | #include <linux/export.h> | 42 | #include <linux/export.h> |
| 43 | #include <linux/pm_runtime.h> | 43 | #include <linux/pm_runtime.h> |
| 44 | #include <linux/err.h> | ||
| 44 | 45 | ||
| 45 | #include "power.h" | 46 | #include "power.h" |
| 46 | 47 | ||
| @@ -61,7 +62,7 @@ enum pm_qos_flags_status __dev_pm_qos_flags(struct device *dev, s32 mask) | |||
| 61 | struct pm_qos_flags *pqf; | 62 | struct pm_qos_flags *pqf; |
| 62 | s32 val; | 63 | s32 val; |
| 63 | 64 | ||
| 64 | if (!qos) | 65 | if (IS_ERR_OR_NULL(qos)) |
| 65 | return PM_QOS_FLAGS_UNDEFINED; | 66 | return PM_QOS_FLAGS_UNDEFINED; |
| 66 | 67 | ||
| 67 | pqf = &qos->flags; | 68 | pqf = &qos->flags; |
| @@ -101,7 +102,8 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_flags); | |||
| 101 | */ | 102 | */ |
| 102 | s32 __dev_pm_qos_read_value(struct device *dev) | 103 | s32 __dev_pm_qos_read_value(struct device *dev) |
| 103 | { | 104 | { |
| 104 | return dev->power.qos ? pm_qos_read_value(&dev->power.qos->latency) : 0; | 105 | return IS_ERR_OR_NULL(dev->power.qos) ? |
| 106 | 0 : pm_qos_read_value(&dev->power.qos->latency); | ||
| 105 | } | 107 | } |
| 106 | 108 | ||
| 107 | /** | 109 | /** |
| @@ -198,20 +200,8 @@ static int dev_pm_qos_constraints_allocate(struct device *dev) | |||
| 198 | return 0; | 200 | return 0; |
| 199 | } | 201 | } |
| 200 | 202 | ||
| 201 | /** | 203 | static void __dev_pm_qos_hide_latency_limit(struct device *dev); |
| 202 | * dev_pm_qos_constraints_init - Initalize device's PM QoS constraints pointer. | 204 | static void __dev_pm_qos_hide_flags(struct device *dev); |
| 203 | * @dev: target device | ||
| 204 | * | ||
| 205 | * Called from the device PM subsystem during device insertion under | ||
| 206 | * device_pm_lock(). | ||
| 207 | */ | ||
| 208 | void dev_pm_qos_constraints_init(struct device *dev) | ||
| 209 | { | ||
| 210 | mutex_lock(&dev_pm_qos_mtx); | ||
| 211 | dev->power.qos = NULL; | ||
| 212 | dev->power.power_state = PMSG_ON; | ||
| 213 | mutex_unlock(&dev_pm_qos_mtx); | ||
| 214 | } | ||
| 215 | 205 | ||
| 216 | /** | 206 | /** |
| 217 | * dev_pm_qos_constraints_destroy | 207 | * dev_pm_qos_constraints_destroy |
| @@ -226,16 +216,15 @@ void dev_pm_qos_constraints_destroy(struct device *dev) | |||
| 226 | struct pm_qos_constraints *c; | 216 | struct pm_qos_constraints *c; |
| 227 | struct pm_qos_flags *f; | 217 | struct pm_qos_flags *f; |
| 228 | 218 | ||
| 219 | mutex_lock(&dev_pm_qos_mtx); | ||
| 220 | |||
| 229 | /* | 221 | /* |
| 230 | * If the device's PM QoS resume latency limit or PM QoS flags have been | 222 | * If the device's PM QoS resume latency limit or PM QoS flags have been |
| 231 | * exposed to user space, they have to be hidden at this point. | 223 | * exposed to user space, they have to be hidden at this point. |
| 232 | */ | 224 | */ |
| 233 | dev_pm_qos_hide_latency_limit(dev); | 225 | __dev_pm_qos_hide_latency_limit(dev); |
| 234 | dev_pm_qos_hide_flags(dev); | 226 | __dev_pm_qos_hide_flags(dev); |
| 235 | 227 | ||
| 236 | mutex_lock(&dev_pm_qos_mtx); | ||
| 237 | |||
| 238 | dev->power.power_state = PMSG_INVALID; | ||
| 239 | qos = dev->power.qos; | 228 | qos = dev->power.qos; |
| 240 | if (!qos) | 229 | if (!qos) |
| 241 | goto out; | 230 | goto out; |
| @@ -257,7 +246,7 @@ void dev_pm_qos_constraints_destroy(struct device *dev) | |||
| 257 | } | 246 | } |
| 258 | 247 | ||
| 259 | spin_lock_irq(&dev->power.lock); | 248 | spin_lock_irq(&dev->power.lock); |
| 260 | dev->power.qos = NULL; | 249 | dev->power.qos = ERR_PTR(-ENODEV); |
| 261 | spin_unlock_irq(&dev->power.lock); | 250 | spin_unlock_irq(&dev->power.lock); |
| 262 | 251 | ||
| 263 | kfree(c->notifiers); | 252 | kfree(c->notifiers); |
| @@ -301,32 +290,19 @@ int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req, | |||
| 301 | "%s() called for already added request\n", __func__)) | 290 | "%s() called for already added request\n", __func__)) |
| 302 | return -EINVAL; | 291 | return -EINVAL; |
| 303 | 292 | ||
| 304 | req->dev = dev; | ||
| 305 | |||
| 306 | mutex_lock(&dev_pm_qos_mtx); | 293 | mutex_lock(&dev_pm_qos_mtx); |
| 307 | 294 | ||
| 308 | if (!dev->power.qos) { | 295 | if (IS_ERR(dev->power.qos)) |
| 309 | if (dev->power.power_state.event == PM_EVENT_INVALID) { | 296 | ret = -ENODEV; |
| 310 | /* The device has been removed from the system. */ | 297 | else if (!dev->power.qos) |
| 311 | req->dev = NULL; | 298 | ret = dev_pm_qos_constraints_allocate(dev); |
| 312 | ret = -ENODEV; | ||
| 313 | goto out; | ||
| 314 | } else { | ||
| 315 | /* | ||
| 316 | * Allocate the constraints data on the first call to | ||
| 317 | * add_request, i.e. only if the data is not already | ||
| 318 | * allocated and if the device has not been removed. | ||
| 319 | */ | ||
| 320 | ret = dev_pm_qos_constraints_allocate(dev); | ||
| 321 | } | ||
| 322 | } | ||
| 323 | 299 | ||
| 324 | if (!ret) { | 300 | if (!ret) { |
| 301 | req->dev = dev; | ||
| 325 | req->type = type; | 302 | req->type = type; |
| 326 | ret = apply_constraint(req, PM_QOS_ADD_REQ, value); | 303 | ret = apply_constraint(req, PM_QOS_ADD_REQ, value); |
| 327 | } | 304 | } |
| 328 | 305 | ||
| 329 | out: | ||
| 330 | mutex_unlock(&dev_pm_qos_mtx); | 306 | mutex_unlock(&dev_pm_qos_mtx); |
| 331 | 307 | ||
| 332 | return ret; | 308 | return ret; |
| @@ -344,7 +320,14 @@ static int __dev_pm_qos_update_request(struct dev_pm_qos_request *req, | |||
| 344 | s32 curr_value; | 320 | s32 curr_value; |
| 345 | int ret = 0; | 321 | int ret = 0; |
| 346 | 322 | ||
| 347 | if (!req->dev->power.qos) | 323 | if (!req) /*guard against callers passing in null */ |
| 324 | return -EINVAL; | ||
| 325 | |||
| 326 | if (WARN(!dev_pm_qos_request_active(req), | ||
| 327 | "%s() called for unknown object\n", __func__)) | ||
| 328 | return -EINVAL; | ||
| 329 | |||
| 330 | if (IS_ERR_OR_NULL(req->dev->power.qos)) | ||
| 348 | return -ENODEV; | 331 | return -ENODEV; |
| 349 | 332 | ||
| 350 | switch(req->type) { | 333 | switch(req->type) { |
| @@ -386,6 +369,17 @@ int dev_pm_qos_update_request(struct dev_pm_qos_request *req, s32 new_value) | |||
| 386 | { | 369 | { |
| 387 | int ret; | 370 | int ret; |
| 388 | 371 | ||
| 372 | mutex_lock(&dev_pm_qos_mtx); | ||
| 373 | ret = __dev_pm_qos_update_request(req, new_value); | ||
| 374 | mutex_unlock(&dev_pm_qos_mtx); | ||
| 375 | return ret; | ||
| 376 | } | ||
| 377 | EXPORT_SYMBOL_GPL(dev_pm_qos_update_request); | ||
| 378 | |||
| 379 | static int __dev_pm_qos_remove_request(struct dev_pm_qos_request *req) | ||
| 380 | { | ||
| 381 | int ret; | ||
| 382 | |||
| 389 | if (!req) /*guard against callers passing in null */ | 383 | if (!req) /*guard against callers passing in null */ |
| 390 | return -EINVAL; | 384 | return -EINVAL; |
| 391 | 385 | ||
| @@ -393,13 +387,13 @@ int dev_pm_qos_update_request(struct dev_pm_qos_request *req, s32 new_value) | |||
| 393 | "%s() called for unknown object\n", __func__)) | 387 | "%s() called for unknown object\n", __func__)) |
| 394 | return -EINVAL; | 388 | return -EINVAL; |
| 395 | 389 | ||
| 396 | mutex_lock(&dev_pm_qos_mtx); | 390 | if (IS_ERR_OR_NULL(req->dev->power.qos)) |
| 397 | ret = __dev_pm_qos_update_request(req, new_value); | 391 | return -ENODEV; |
| 398 | mutex_unlock(&dev_pm_qos_mtx); | ||
| 399 | 392 | ||
| 393 | ret = apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE); | ||
| 394 | memset(req, 0, sizeof(*req)); | ||
| 400 | return ret; | 395 | return ret; |
| 401 | } | 396 | } |
| 402 | EXPORT_SYMBOL_GPL(dev_pm_qos_update_request); | ||
| 403 | 397 | ||
| 404 | /** | 398 | /** |
| 405 | * dev_pm_qos_remove_request - modifies an existing qos request | 399 | * dev_pm_qos_remove_request - modifies an existing qos request |
| @@ -418,26 +412,10 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_update_request); | |||
| 418 | */ | 412 | */ |
| 419 | int dev_pm_qos_remove_request(struct dev_pm_qos_request *req) | 413 | int dev_pm_qos_remove_request(struct dev_pm_qos_request *req) |
| 420 | { | 414 | { |
| 421 | int ret = 0; | 415 | int ret; |
| 422 | |||
| 423 | if (!req) /*guard against callers passing in null */ | ||
| 424 | return -EINVAL; | ||
| 425 | |||
| 426 | if (WARN(!dev_pm_qos_request_active(req), | ||
| 427 | "%s() called for unknown object\n", __func__)) | ||
| 428 | return -EINVAL; | ||
| 429 | 416 | ||
| 430 | mutex_lock(&dev_pm_qos_mtx); | 417 | mutex_lock(&dev_pm_qos_mtx); |
| 431 | 418 | ret = __dev_pm_qos_remove_request(req); | |
| 432 | if (req->dev->power.qos) { | ||
| 433 | ret = apply_constraint(req, PM_QOS_REMOVE_REQ, | ||
| 434 | PM_QOS_DEFAULT_VALUE); | ||
| 435 | memset(req, 0, sizeof(*req)); | ||
| 436 | } else { | ||
| 437 | /* Return if the device has been removed */ | ||
| 438 | ret = -ENODEV; | ||
| 439 | } | ||
| 440 | |||
| 441 | mutex_unlock(&dev_pm_qos_mtx); | 419 | mutex_unlock(&dev_pm_qos_mtx); |
| 442 | return ret; | 420 | return ret; |
| 443 | } | 421 | } |
| @@ -462,9 +440,10 @@ int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier) | |||
| 462 | 440 | ||
| 463 | mutex_lock(&dev_pm_qos_mtx); | 441 | mutex_lock(&dev_pm_qos_mtx); |
| 464 | 442 | ||
| 465 | if (!dev->power.qos) | 443 | if (IS_ERR(dev->power.qos)) |
| 466 | ret = dev->power.power_state.event != PM_EVENT_INVALID ? | 444 | ret = -ENODEV; |
| 467 | dev_pm_qos_constraints_allocate(dev) : -ENODEV; | 445 | else if (!dev->power.qos) |
| 446 | ret = dev_pm_qos_constraints_allocate(dev); | ||
| 468 | 447 | ||
| 469 | if (!ret) | 448 | if (!ret) |
| 470 | ret = blocking_notifier_chain_register( | 449 | ret = blocking_notifier_chain_register( |
| @@ -493,7 +472,7 @@ int dev_pm_qos_remove_notifier(struct device *dev, | |||
| 493 | mutex_lock(&dev_pm_qos_mtx); | 472 | mutex_lock(&dev_pm_qos_mtx); |
| 494 | 473 | ||
| 495 | /* Silently return if the constraints object is not present. */ | 474 | /* Silently return if the constraints object is not present. */ |
| 496 | if (dev->power.qos) | 475 | if (!IS_ERR_OR_NULL(dev->power.qos)) |
| 497 | retval = blocking_notifier_chain_unregister( | 476 | retval = blocking_notifier_chain_unregister( |
| 498 | dev->power.qos->latency.notifiers, | 477 | dev->power.qos->latency.notifiers, |
| 499 | notifier); | 478 | notifier); |
| @@ -563,16 +542,20 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_add_ancestor_request); | |||
| 563 | static void __dev_pm_qos_drop_user_request(struct device *dev, | 542 | static void __dev_pm_qos_drop_user_request(struct device *dev, |
| 564 | enum dev_pm_qos_req_type type) | 543 | enum dev_pm_qos_req_type type) |
| 565 | { | 544 | { |
| 545 | struct dev_pm_qos_request *req = NULL; | ||
| 546 | |||
| 566 | switch(type) { | 547 | switch(type) { |
| 567 | case DEV_PM_QOS_LATENCY: | 548 | case DEV_PM_QOS_LATENCY: |
| 568 | dev_pm_qos_remove_request(dev->power.qos->latency_req); | 549 | req = dev->power.qos->latency_req; |
| 569 | dev->power.qos->latency_req = NULL; | 550 | dev->power.qos->latency_req = NULL; |
| 570 | break; | 551 | break; |
| 571 | case DEV_PM_QOS_FLAGS: | 552 | case DEV_PM_QOS_FLAGS: |
| 572 | dev_pm_qos_remove_request(dev->power.qos->flags_req); | 553 | req = dev->power.qos->flags_req; |
| 573 | dev->power.qos->flags_req = NULL; | 554 | dev->power.qos->flags_req = NULL; |
| 574 | break; | 555 | break; |
| 575 | } | 556 | } |
| 557 | __dev_pm_qos_remove_request(req); | ||
| 558 | kfree(req); | ||
| 576 | } | 559 | } |
| 577 | 560 | ||
| 578 | /** | 561 | /** |
| @@ -588,36 +571,57 @@ int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value) | |||
| 588 | if (!device_is_registered(dev) || value < 0) | 571 | if (!device_is_registered(dev) || value < 0) |
| 589 | return -EINVAL; | 572 | return -EINVAL; |
| 590 | 573 | ||
| 591 | if (dev->power.qos && dev->power.qos->latency_req) | ||
| 592 | return -EEXIST; | ||
| 593 | |||
| 594 | req = kzalloc(sizeof(*req), GFP_KERNEL); | 574 | req = kzalloc(sizeof(*req), GFP_KERNEL); |
| 595 | if (!req) | 575 | if (!req) |
| 596 | return -ENOMEM; | 576 | return -ENOMEM; |
| 597 | 577 | ||
| 598 | ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_LATENCY, value); | 578 | ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_LATENCY, value); |
| 599 | if (ret < 0) | 579 | if (ret < 0) { |
| 580 | kfree(req); | ||
| 600 | return ret; | 581 | return ret; |
| 582 | } | ||
| 583 | |||
| 584 | mutex_lock(&dev_pm_qos_mtx); | ||
| 585 | |||
| 586 | if (IS_ERR_OR_NULL(dev->power.qos)) | ||
| 587 | ret = -ENODEV; | ||
| 588 | else if (dev->power.qos->latency_req) | ||
| 589 | ret = -EEXIST; | ||
| 590 | |||
| 591 | if (ret < 0) { | ||
| 592 | __dev_pm_qos_remove_request(req); | ||
| 593 | kfree(req); | ||
| 594 | goto out; | ||
| 595 | } | ||
| 601 | 596 | ||
| 602 | dev->power.qos->latency_req = req; | 597 | dev->power.qos->latency_req = req; |
| 603 | ret = pm_qos_sysfs_add_latency(dev); | 598 | ret = pm_qos_sysfs_add_latency(dev); |
| 604 | if (ret) | 599 | if (ret) |
| 605 | __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY); | 600 | __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY); |
| 606 | 601 | ||
| 602 | out: | ||
| 603 | mutex_unlock(&dev_pm_qos_mtx); | ||
| 607 | return ret; | 604 | return ret; |
| 608 | } | 605 | } |
| 609 | EXPORT_SYMBOL_GPL(dev_pm_qos_expose_latency_limit); | 606 | EXPORT_SYMBOL_GPL(dev_pm_qos_expose_latency_limit); |
| 610 | 607 | ||
| 608 | static void __dev_pm_qos_hide_latency_limit(struct device *dev) | ||
| 609 | { | ||
| 610 | 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); | ||
| 613 | } | ||
| 614 | } | ||
| 615 | |||
| 611 | /** | 616 | /** |
| 612 | * dev_pm_qos_hide_latency_limit - Hide PM QoS latency limit from user space. | 617 | * dev_pm_qos_hide_latency_limit - Hide PM QoS latency limit from user space. |
| 613 | * @dev: Device whose PM QoS latency limit is to be hidden from user space. | 618 | * @dev: Device whose PM QoS latency limit is to be hidden from user space. |
| 614 | */ | 619 | */ |
| 615 | void dev_pm_qos_hide_latency_limit(struct device *dev) | 620 | void dev_pm_qos_hide_latency_limit(struct device *dev) |
| 616 | { | 621 | { |
| 617 | if (dev->power.qos && dev->power.qos->latency_req) { | 622 | mutex_lock(&dev_pm_qos_mtx); |
| 618 | pm_qos_sysfs_remove_latency(dev); | 623 | __dev_pm_qos_hide_latency_limit(dev); |
| 619 | __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY); | 624 | mutex_unlock(&dev_pm_qos_mtx); |
| 620 | } | ||
| 621 | } | 625 | } |
| 622 | EXPORT_SYMBOL_GPL(dev_pm_qos_hide_latency_limit); | 626 | EXPORT_SYMBOL_GPL(dev_pm_qos_hide_latency_limit); |
| 623 | 627 | ||
| @@ -634,41 +638,61 @@ int dev_pm_qos_expose_flags(struct device *dev, s32 val) | |||
| 634 | if (!device_is_registered(dev)) | 638 | if (!device_is_registered(dev)) |
| 635 | return -EINVAL; | 639 | return -EINVAL; |
| 636 | 640 | ||
| 637 | if (dev->power.qos && dev->power.qos->flags_req) | ||
| 638 | return -EEXIST; | ||
| 639 | |||
| 640 | req = kzalloc(sizeof(*req), GFP_KERNEL); | 641 | req = kzalloc(sizeof(*req), GFP_KERNEL); |
| 641 | if (!req) | 642 | if (!req) |
| 642 | return -ENOMEM; | 643 | return -ENOMEM; |
| 643 | 644 | ||
| 644 | pm_runtime_get_sync(dev); | ||
| 645 | ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_FLAGS, val); | 645 | ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_FLAGS, val); |
| 646 | if (ret < 0) | 646 | if (ret < 0) { |
| 647 | goto fail; | 647 | kfree(req); |
| 648 | return ret; | ||
| 649 | } | ||
| 650 | |||
| 651 | pm_runtime_get_sync(dev); | ||
| 652 | mutex_lock(&dev_pm_qos_mtx); | ||
| 653 | |||
| 654 | if (IS_ERR_OR_NULL(dev->power.qos)) | ||
| 655 | ret = -ENODEV; | ||
| 656 | else if (dev->power.qos->flags_req) | ||
| 657 | ret = -EEXIST; | ||
| 658 | |||
| 659 | if (ret < 0) { | ||
| 660 | __dev_pm_qos_remove_request(req); | ||
| 661 | kfree(req); | ||
| 662 | goto out; | ||
| 663 | } | ||
| 648 | 664 | ||
| 649 | dev->power.qos->flags_req = req; | 665 | dev->power.qos->flags_req = req; |
| 650 | ret = pm_qos_sysfs_add_flags(dev); | 666 | ret = pm_qos_sysfs_add_flags(dev); |
| 651 | if (ret) | 667 | if (ret) |
| 652 | __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS); | 668 | __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS); |
| 653 | 669 | ||
| 654 | fail: | 670 | out: |
| 671 | mutex_unlock(&dev_pm_qos_mtx); | ||
| 655 | pm_runtime_put(dev); | 672 | pm_runtime_put(dev); |
| 656 | return ret; | 673 | return ret; |
| 657 | } | 674 | } |
| 658 | EXPORT_SYMBOL_GPL(dev_pm_qos_expose_flags); | 675 | EXPORT_SYMBOL_GPL(dev_pm_qos_expose_flags); |
| 659 | 676 | ||
| 677 | static void __dev_pm_qos_hide_flags(struct device *dev) | ||
| 678 | { | ||
| 679 | 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); | ||
| 682 | } | ||
| 683 | } | ||
| 684 | |||
| 660 | /** | 685 | /** |
| 661 | * dev_pm_qos_hide_flags - Hide PM QoS flags of a device from user space. | 686 | * dev_pm_qos_hide_flags - Hide PM QoS flags of a device from user space. |
| 662 | * @dev: Device whose PM QoS flags are to be hidden from user space. | 687 | * @dev: Device whose PM QoS flags are to be hidden from user space. |
| 663 | */ | 688 | */ |
| 664 | void dev_pm_qos_hide_flags(struct device *dev) | 689 | void dev_pm_qos_hide_flags(struct device *dev) |
| 665 | { | 690 | { |
| 666 | if (dev->power.qos && dev->power.qos->flags_req) { | 691 | pm_runtime_get_sync(dev); |
| 667 | pm_qos_sysfs_remove_flags(dev); | 692 | mutex_lock(&dev_pm_qos_mtx); |
| 668 | pm_runtime_get_sync(dev); | 693 | __dev_pm_qos_hide_flags(dev); |
| 669 | __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS); | 694 | mutex_unlock(&dev_pm_qos_mtx); |
| 670 | pm_runtime_put(dev); | 695 | pm_runtime_put(dev); |
| 671 | } | ||
| 672 | } | 696 | } |
| 673 | EXPORT_SYMBOL_GPL(dev_pm_qos_hide_flags); | 697 | EXPORT_SYMBOL_GPL(dev_pm_qos_hide_flags); |
| 674 | 698 | ||
| @@ -683,12 +707,14 @@ int dev_pm_qos_update_flags(struct device *dev, s32 mask, bool set) | |||
| 683 | s32 value; | 707 | s32 value; |
| 684 | int ret; | 708 | int ret; |
| 685 | 709 | ||
| 686 | if (!dev->power.qos || !dev->power.qos->flags_req) | ||
| 687 | return -EINVAL; | ||
| 688 | |||
| 689 | pm_runtime_get_sync(dev); | 710 | pm_runtime_get_sync(dev); |
| 690 | mutex_lock(&dev_pm_qos_mtx); | 711 | mutex_lock(&dev_pm_qos_mtx); |
| 691 | 712 | ||
| 713 | if (IS_ERR_OR_NULL(dev->power.qos) || !dev->power.qos->flags_req) { | ||
| 714 | ret = -EINVAL; | ||
| 715 | goto out; | ||
| 716 | } | ||
| 717 | |||
| 692 | value = dev_pm_qos_requested_flags(dev); | 718 | value = dev_pm_qos_requested_flags(dev); |
| 693 | if (set) | 719 | if (set) |
| 694 | value |= mask; | 720 | value |= mask; |
| @@ -697,9 +723,12 @@ int dev_pm_qos_update_flags(struct device *dev, s32 mask, bool set) | |||
| 697 | 723 | ||
| 698 | ret = __dev_pm_qos_update_request(dev->power.qos->flags_req, value); | 724 | ret = __dev_pm_qos_update_request(dev->power.qos->flags_req, value); |
| 699 | 725 | ||
| 726 | out: | ||
| 700 | mutex_unlock(&dev_pm_qos_mtx); | 727 | mutex_unlock(&dev_pm_qos_mtx); |
| 701 | pm_runtime_put(dev); | 728 | pm_runtime_put(dev); |
| 702 | |||
| 703 | return ret; | 729 | return ret; |
| 704 | } | 730 | } |
| 731 | #else /* !CONFIG_PM_RUNTIME */ | ||
| 732 | static void __dev_pm_qos_hide_latency_limit(struct device *dev) {} | ||
| 733 | static void __dev_pm_qos_hide_flags(struct device *dev) {} | ||
| 705 | #endif /* CONFIG_PM_RUNTIME */ | 734 | #endif /* CONFIG_PM_RUNTIME */ |
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c index 50d16e3cb0a9..a53ebd265701 100644 --- a/drivers/base/power/sysfs.c +++ b/drivers/base/power/sysfs.c | |||
| @@ -708,6 +708,7 @@ void rpm_sysfs_remove(struct device *dev) | |||
| 708 | 708 | ||
| 709 | void dpm_sysfs_remove(struct device *dev) | 709 | void dpm_sysfs_remove(struct device *dev) |
| 710 | { | 710 | { |
| 711 | dev_pm_qos_constraints_destroy(dev); | ||
| 711 | rpm_sysfs_remove(dev); | 712 | rpm_sysfs_remove(dev); |
| 712 | sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group); | 713 | sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group); |
| 713 | sysfs_remove_group(&dev->kobj, &pm_attr_group); | 714 | sysfs_remove_group(&dev->kobj, &pm_attr_group); |
diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h index d2ac91150600..46bde01eee62 100644 --- a/drivers/cpufreq/cpufreq_governor.h +++ b/drivers/cpufreq/cpufreq_governor.h | |||
| @@ -64,7 +64,7 @@ static void *get_cpu_dbs_info_s(int cpu) \ | |||
| 64 | * dbs: used as a shortform for demand based switching It helps to keep variable | 64 | * dbs: used as a shortform for demand based switching It helps to keep variable |
| 65 | * names smaller, simpler | 65 | * names smaller, simpler |
| 66 | * cdbs: common dbs | 66 | * cdbs: common dbs |
| 67 | * on_*: On-demand governor | 67 | * od_*: On-demand governor |
| 68 | * cs_*: Conservative governor | 68 | * cs_*: Conservative governor |
| 69 | */ | 69 | */ |
| 70 | 70 | ||
diff --git a/drivers/cpufreq/highbank-cpufreq.c b/drivers/cpufreq/highbank-cpufreq.c index 66e3a71b81a3..b61b5a3fad64 100644 --- a/drivers/cpufreq/highbank-cpufreq.c +++ b/drivers/cpufreq/highbank-cpufreq.c | |||
| @@ -28,13 +28,7 @@ | |||
| 28 | 28 | ||
| 29 | static int hb_voltage_change(unsigned int freq) | 29 | static int hb_voltage_change(unsigned int freq) |
| 30 | { | 30 | { |
| 31 | int i; | 31 | u32 msg[HB_CPUFREQ_IPC_LEN] = {HB_CPUFREQ_CHANGE_NOTE, freq / 1000000}; |
| 32 | u32 msg[HB_CPUFREQ_IPC_LEN]; | ||
| 33 | |||
| 34 | msg[0] = HB_CPUFREQ_CHANGE_NOTE; | ||
| 35 | msg[1] = freq / 1000000; | ||
| 36 | for (i = 2; i < HB_CPUFREQ_IPC_LEN; i++) | ||
| 37 | msg[i] = 0; | ||
| 38 | 32 | ||
| 39 | return pl320_ipc_transmit(msg); | 33 | return pl320_ipc_transmit(msg); |
| 40 | } | 34 | } |
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 096fde0ebcb5..f6dd1e761129 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c | |||
| @@ -662,6 +662,9 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy) | |||
| 662 | 662 | ||
| 663 | cpu = all_cpu_data[policy->cpu]; | 663 | cpu = all_cpu_data[policy->cpu]; |
| 664 | 664 | ||
| 665 | if (!policy->cpuinfo.max_freq) | ||
| 666 | return -ENODEV; | ||
| 667 | |||
| 665 | intel_pstate_get_min_max(cpu, &min, &max); | 668 | intel_pstate_get_min_max(cpu, &min, &max); |
| 666 | 669 | ||
| 667 | limits.min_perf_pct = (policy->min * 100) / policy->cpuinfo.max_freq; | 670 | limits.min_perf_pct = (policy->min * 100) / policy->cpuinfo.max_freq; |
| @@ -747,37 +750,11 @@ static struct cpufreq_driver intel_pstate_driver = { | |||
| 747 | .owner = THIS_MODULE, | 750 | .owner = THIS_MODULE, |
| 748 | }; | 751 | }; |
| 749 | 752 | ||
| 750 | static void intel_pstate_exit(void) | ||
| 751 | { | ||
| 752 | int cpu; | ||
| 753 | |||
| 754 | sysfs_remove_group(intel_pstate_kobject, | ||
| 755 | &intel_pstate_attr_group); | ||
| 756 | debugfs_remove_recursive(debugfs_parent); | ||
| 757 | |||
| 758 | cpufreq_unregister_driver(&intel_pstate_driver); | ||
| 759 | |||
| 760 | if (!all_cpu_data) | ||
| 761 | return; | ||
| 762 | |||
| 763 | get_online_cpus(); | ||
| 764 | for_each_online_cpu(cpu) { | ||
| 765 | if (all_cpu_data[cpu]) { | ||
| 766 | del_timer_sync(&all_cpu_data[cpu]->timer); | ||
| 767 | kfree(all_cpu_data[cpu]); | ||
| 768 | } | ||
| 769 | } | ||
| 770 | |||
| 771 | put_online_cpus(); | ||
| 772 | vfree(all_cpu_data); | ||
| 773 | } | ||
| 774 | module_exit(intel_pstate_exit); | ||
| 775 | |||
| 776 | static int __initdata no_load; | 753 | static int __initdata no_load; |
| 777 | 754 | ||
| 778 | static int __init intel_pstate_init(void) | 755 | static int __init intel_pstate_init(void) |
| 779 | { | 756 | { |
| 780 | int rc = 0; | 757 | int cpu, rc = 0; |
| 781 | const struct x86_cpu_id *id; | 758 | const struct x86_cpu_id *id; |
| 782 | 759 | ||
| 783 | if (no_load) | 760 | if (no_load) |
| @@ -802,7 +779,16 @@ static int __init intel_pstate_init(void) | |||
| 802 | intel_pstate_sysfs_expose_params(); | 779 | intel_pstate_sysfs_expose_params(); |
| 803 | return rc; | 780 | return rc; |
| 804 | out: | 781 | out: |
| 805 | intel_pstate_exit(); | 782 | get_online_cpus(); |
| 783 | for_each_online_cpu(cpu) { | ||
| 784 | if (all_cpu_data[cpu]) { | ||
| 785 | del_timer_sync(&all_cpu_data[cpu]->timer); | ||
| 786 | kfree(all_cpu_data[cpu]); | ||
| 787 | } | ||
| 788 | } | ||
| 789 | |||
| 790 | put_online_cpus(); | ||
| 791 | vfree(all_cpu_data); | ||
| 806 | return -ENODEV; | 792 | return -ENODEV; |
| 807 | } | 793 | } |
| 808 | device_initcall(intel_pstate_init); | 794 | device_initcall(intel_pstate_init); |
diff --git a/drivers/mailbox/pl320-ipc.c b/drivers/mailbox/pl320-ipc.c index c45b3aedafba..d873cbae2fbb 100644 --- a/drivers/mailbox/pl320-ipc.c +++ b/drivers/mailbox/pl320-ipc.c | |||
| @@ -138,8 +138,7 @@ int pl320_ipc_unregister_notifier(struct notifier_block *nb) | |||
| 138 | } | 138 | } |
| 139 | EXPORT_SYMBOL_GPL(pl320_ipc_unregister_notifier); | 139 | EXPORT_SYMBOL_GPL(pl320_ipc_unregister_notifier); |
| 140 | 140 | ||
| 141 | static int __init pl320_probe(struct amba_device *adev, | 141 | static int pl320_probe(struct amba_device *adev, const struct amba_id *id) |
| 142 | const struct amba_id *id) | ||
| 143 | { | 142 | { |
| 144 | int ret; | 143 | int ret; |
| 145 | 144 | ||
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 39c937f9b426..dee5dddaa292 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c | |||
| @@ -331,8 +331,14 @@ static void pci_acpi_cleanup(struct device *dev) | |||
| 331 | } | 331 | } |
| 332 | } | 332 | } |
| 333 | 333 | ||
| 334 | static bool pci_acpi_bus_match(struct device *dev) | ||
| 335 | { | ||
| 336 | return dev->bus == &pci_bus_type; | ||
| 337 | } | ||
| 338 | |||
| 334 | static struct acpi_bus_type acpi_pci_bus = { | 339 | static struct acpi_bus_type acpi_pci_bus = { |
| 335 | .bus = &pci_bus_type, | 340 | .name = "PCI", |
| 341 | .match = pci_acpi_bus_match, | ||
| 336 | .find_device = acpi_pci_find_device, | 342 | .find_device = acpi_pci_find_device, |
| 337 | .setup = pci_acpi_setup, | 343 | .setup = pci_acpi_setup, |
| 338 | .cleanup = pci_acpi_cleanup, | 344 | .cleanup = pci_acpi_cleanup, |
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index 8813fc03aa09..55cd459a3908 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c | |||
| @@ -353,8 +353,14 @@ static int __init acpi_pnp_find_device(struct device *dev, acpi_handle * handle) | |||
| 353 | /* complete initialization of a PNPACPI device includes having | 353 | /* complete initialization of a PNPACPI device includes having |
| 354 | * pnpdev->dev.archdata.acpi_handle point to its ACPI sibling. | 354 | * pnpdev->dev.archdata.acpi_handle point to its ACPI sibling. |
| 355 | */ | 355 | */ |
| 356 | static bool acpi_pnp_bus_match(struct device *dev) | ||
| 357 | { | ||
| 358 | return dev->bus == &pnp_bus_type; | ||
| 359 | } | ||
| 360 | |||
| 356 | static struct acpi_bus_type __initdata acpi_pnp_bus = { | 361 | static struct acpi_bus_type __initdata acpi_pnp_bus = { |
| 357 | .bus = &pnp_bus_type, | 362 | .name = "PNP", |
| 363 | .match = acpi_pnp_bus_match, | ||
| 358 | .find_device = acpi_pnp_find_device, | 364 | .find_device = acpi_pnp_find_device, |
| 359 | }; | 365 | }; |
| 360 | 366 | ||
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 765398c063c7..c31187d79343 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
| @@ -71,9 +71,14 @@ struct kmem_cache *scsi_sdb_cache; | |||
| 71 | #ifdef CONFIG_ACPI | 71 | #ifdef CONFIG_ACPI |
| 72 | #include <acpi/acpi_bus.h> | 72 | #include <acpi/acpi_bus.h> |
| 73 | 73 | ||
| 74 | static bool acpi_scsi_bus_match(struct device *dev) | ||
| 75 | { | ||
| 76 | return dev->bus == &scsi_bus_type; | ||
| 77 | } | ||
| 78 | |||
| 74 | int scsi_register_acpi_bus_type(struct acpi_bus_type *bus) | 79 | int scsi_register_acpi_bus_type(struct acpi_bus_type *bus) |
| 75 | { | 80 | { |
| 76 | bus->bus = &scsi_bus_type; | 81 | bus->match = acpi_scsi_bus_match; |
| 77 | return register_acpi_bus_type(bus); | 82 | return register_acpi_bus_type(bus); |
| 78 | } | 83 | } |
| 79 | EXPORT_SYMBOL_GPL(scsi_register_acpi_bus_type); | 84 | EXPORT_SYMBOL_GPL(scsi_register_acpi_bus_type); |
diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c index cef4252bb31a..b6f4bad3f756 100644 --- a/drivers/usb/core/usb-acpi.c +++ b/drivers/usb/core/usb-acpi.c | |||
| @@ -210,9 +210,14 @@ static int usb_acpi_find_device(struct device *dev, acpi_handle *handle) | |||
| 210 | return 0; | 210 | return 0; |
| 211 | } | 211 | } |
| 212 | 212 | ||
| 213 | static bool usb_acpi_bus_match(struct device *dev) | ||
| 214 | { | ||
| 215 | return is_usb_device(dev) || is_usb_port(dev); | ||
| 216 | } | ||
| 217 | |||
| 213 | static struct acpi_bus_type usb_acpi_bus = { | 218 | static struct acpi_bus_type usb_acpi_bus = { |
| 214 | .bus = &usb_bus_type, | 219 | .name = "USB", |
| 215 | .find_bridge = usb_acpi_find_device, | 220 | .match = usb_acpi_bus_match, |
| 216 | .find_device = usb_acpi_find_device, | 221 | .find_device = usb_acpi_find_device, |
| 217 | }; | 222 | }; |
| 218 | 223 | ||
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index e65278f560c4..22ba56e834e2 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h | |||
| @@ -437,11 +437,9 @@ void acpi_remove_dir(struct acpi_device *); | |||
| 437 | */ | 437 | */ |
| 438 | struct acpi_bus_type { | 438 | struct acpi_bus_type { |
| 439 | struct list_head list; | 439 | struct list_head list; |
| 440 | struct bus_type *bus; | 440 | const char *name; |
| 441 | /* For general devices under the bus */ | 441 | bool (*match)(struct device *dev); |
| 442 | int (*find_device) (struct device *, acpi_handle *); | 442 | int (*find_device) (struct device *, acpi_handle *); |
| 443 | /* For bridges, such as PCI root bridge, IDE controller */ | ||
| 444 | int (*find_bridge) (struct device *, acpi_handle *); | ||
| 445 | void (*setup)(struct device *); | 443 | void (*setup)(struct device *); |
| 446 | void (*cleanup)(struct device *); | 444 | void (*cleanup)(struct device *); |
| 447 | }; | 445 | }; |
