diff options
-rw-r--r-- | Documentation/power/pm_qos_interface.txt | 92 | ||||
-rw-r--r-- | arch/arm/mach-msm/clock.c | 2 | ||||
-rw-r--r-- | drivers/acpi/processor_idle.c | 2 | ||||
-rw-r--r-- | drivers/base/power/Makefile | 4 | ||||
-rw-r--r-- | drivers/base/power/main.c | 3 | ||||
-rw-r--r-- | drivers/base/power/power.h | 10 | ||||
-rw-r--r-- | drivers/base/power/qos.c | 419 | ||||
-rw-r--r-- | drivers/cpuidle/cpuidle.c | 2 | ||||
-rw-r--r-- | drivers/cpuidle/governors/ladder.c | 2 | ||||
-rw-r--r-- | drivers/cpuidle/governors/menu.c | 2 | ||||
-rw-r--r-- | drivers/media/video/via-camera.c | 4 | ||||
-rw-r--r-- | drivers/net/e1000e/netdev.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ipw2x00/ipw2100.c | 4 | ||||
-rw-r--r-- | include/linux/netdevice.h | 4 | ||||
-rw-r--r-- | include/linux/pm.h | 3 | ||||
-rw-r--r-- | include/linux/pm_qos.h | 155 | ||||
-rw-r--r-- | include/linux/pm_qos_params.h | 38 | ||||
-rw-r--r-- | include/sound/pcm.h | 4 | ||||
-rw-r--r-- | kernel/Makefile | 2 | ||||
-rw-r--r-- | kernel/power/Makefile | 2 | ||||
-rw-r--r-- | kernel/power/qos.c (renamed from kernel/pm_qos_params.c) | 273 | ||||
-rw-r--r-- | net/mac80211/main.c | 2 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 2 | ||||
-rw-r--r-- | net/mac80211/scan.c | 2 | ||||
-rw-r--r-- | sound/core/pcm_native.c | 2 |
25 files changed, 839 insertions, 198 deletions
diff --git a/Documentation/power/pm_qos_interface.txt b/Documentation/power/pm_qos_interface.txt index bfed898a03fc..17e130a80347 100644 --- a/Documentation/power/pm_qos_interface.txt +++ b/Documentation/power/pm_qos_interface.txt | |||
@@ -4,14 +4,19 @@ This interface provides a kernel and user mode interface for registering | |||
4 | performance expectations by drivers, subsystems and user space applications on | 4 | performance expectations by drivers, subsystems and user space applications on |
5 | one of the parameters. | 5 | one of the parameters. |
6 | 6 | ||
7 | Currently we have {cpu_dma_latency, network_latency, network_throughput} as the | 7 | Two different PM QoS frameworks are available: |
8 | initial set of pm_qos parameters. | 8 | 1. PM QoS classes for cpu_dma_latency, network_latency, network_throughput. |
9 | 2. the per-device PM QoS framework provides the API to manage the per-device latency | ||
10 | constraints. | ||
9 | 11 | ||
10 | Each parameters have defined units: | 12 | Each parameters have defined units: |
11 | * latency: usec | 13 | * latency: usec |
12 | * timeout: usec | 14 | * timeout: usec |
13 | * throughput: kbs (kilo bit / sec) | 15 | * throughput: kbs (kilo bit / sec) |
14 | 16 | ||
17 | |||
18 | 1. PM QoS framework | ||
19 | |||
15 | The infrastructure exposes multiple misc device nodes one per implemented | 20 | The infrastructure exposes multiple misc device nodes one per implemented |
16 | parameter. The set of parameters implement is defined by pm_qos_power_init() | 21 | parameter. The set of parameters implement is defined by pm_qos_power_init() |
17 | and pm_qos_params.h. This is done because having the available parameters | 22 | and pm_qos_params.h. This is done because having the available parameters |
@@ -23,14 +28,18 @@ an aggregated target value. The aggregated target value is updated with | |||
23 | changes to the request list or elements of the list. Typically the | 28 | changes to the request list or elements of the list. Typically the |
24 | aggregated target value is simply the max or min of the request values held | 29 | aggregated target value is simply the max or min of the request values held |
25 | in the parameter list elements. | 30 | in the parameter list elements. |
31 | Note: the aggregated target value is implemented as an atomic variable so that | ||
32 | reading the aggregated value does not require any locking mechanism. | ||
33 | |||
26 | 34 | ||
27 | From kernel mode the use of this interface is simple: | 35 | From kernel mode the use of this interface is simple: |
28 | 36 | ||
29 | handle = pm_qos_add_request(param_class, target_value): | 37 | void pm_qos_add_request(handle, param_class, target_value): |
30 | Will insert an element into the list for that identified PM_QOS class with the | 38 | Will insert an element into the list for that identified PM QoS class with the |
31 | target value. Upon change to this list the new target is recomputed and any | 39 | target value. Upon change to this list the new target is recomputed and any |
32 | registered notifiers are called only if the target value is now different. | 40 | registered notifiers are called only if the target value is now different. |
33 | Clients of pm_qos need to save the returned handle. | 41 | Clients of pm_qos need to save the returned handle for future use in other |
42 | pm_qos API functions. | ||
34 | 43 | ||
35 | void pm_qos_update_request(handle, new_target_value): | 44 | void pm_qos_update_request(handle, new_target_value): |
36 | Will update the list element pointed to by the handle with the new target value | 45 | Will update the list element pointed to by the handle with the new target value |
@@ -42,6 +51,20 @@ Will remove the element. After removal it will update the aggregate target and | |||
42 | call the notification tree if the target was changed as a result of removing | 51 | call the notification tree if the target was changed as a result of removing |
43 | the request. | 52 | the request. |
44 | 53 | ||
54 | int pm_qos_request(param_class): | ||
55 | Returns the aggregated value for a given PM QoS class. | ||
56 | |||
57 | int pm_qos_request_active(handle): | ||
58 | Returns if the request is still active, i.e. it has not been removed from a | ||
59 | PM QoS class constraints list. | ||
60 | |||
61 | int pm_qos_add_notifier(param_class, notifier): | ||
62 | Adds a notification callback function to the PM QoS class. The callback is | ||
63 | called when the aggregated value for the PM QoS class is changed. | ||
64 | |||
65 | int pm_qos_remove_notifier(int param_class, notifier): | ||
66 | Removes the notification callback function for the PM QoS class. | ||
67 | |||
45 | 68 | ||
46 | From user mode: | 69 | From user mode: |
47 | Only processes can register a pm_qos request. To provide for automatic | 70 | Only processes can register a pm_qos request. To provide for automatic |
@@ -63,4 +86,63 @@ To remove the user mode request for a target value simply close the device | |||
63 | node. | 86 | node. |
64 | 87 | ||
65 | 88 | ||
89 | 2. PM QoS per-device latency framework | ||
90 | |||
91 | For each device a list of performance requests is maintained along with | ||
92 | an aggregated target value. The aggregated target value is updated with | ||
93 | changes to the request list or elements of the list. Typically the | ||
94 | aggregated target value is simply the max or min of the request values held | ||
95 | in the parameter list elements. | ||
96 | Note: the aggregated target value is implemented as an atomic variable so that | ||
97 | reading the aggregated value does not require any locking mechanism. | ||
98 | |||
99 | |||
100 | From kernel mode the use of this interface is the following: | ||
101 | |||
102 | int dev_pm_qos_add_request(device, handle, value): | ||
103 | Will insert an element into the list for that identified device with the | ||
104 | target value. Upon change to this list the new target is recomputed and any | ||
105 | registered notifiers are called only if the target value is now different. | ||
106 | Clients of dev_pm_qos need to save the handle for future use in other | ||
107 | dev_pm_qos API functions. | ||
108 | |||
109 | int dev_pm_qos_update_request(handle, new_value): | ||
110 | Will update the list element pointed to by the handle with the new target value | ||
111 | and recompute the new aggregated target, calling the notification trees if the | ||
112 | target is changed. | ||
113 | |||
114 | int dev_pm_qos_remove_request(handle): | ||
115 | Will remove the element. After removal it will update the aggregate target and | ||
116 | call the notification trees if the target was changed as a result of removing | ||
117 | the request. | ||
118 | |||
119 | s32 dev_pm_qos_read_value(device): | ||
120 | Returns the aggregated value for a given device's constraints list. | ||
121 | |||
122 | |||
123 | Notification mechanisms: | ||
124 | The per-device PM QoS framework has 2 different and distinct notification trees: | ||
125 | a per-device notification tree and a global notification tree. | ||
126 | |||
127 | int dev_pm_qos_add_notifier(device, notifier): | ||
128 | Adds a notification callback function for the device. | ||
129 | The callback is called when the aggregated value of the device constraints list | ||
130 | is changed. | ||
131 | |||
132 | int dev_pm_qos_remove_notifier(device, notifier): | ||
133 | Removes the notification callback function for the device. | ||
134 | |||
135 | int dev_pm_qos_add_global_notifier(notifier): | ||
136 | Adds a notification callback function in the global notification tree of the | ||
137 | framework. | ||
138 | The callback is called when the aggregated value for any device is changed. | ||
139 | |||
140 | int dev_pm_qos_remove_global_notifier(notifier): | ||
141 | Removes the notification callback function from the global notification tree | ||
142 | of the framework. | ||
143 | |||
144 | |||
145 | From user mode: | ||
146 | No API for user space access to the per-device latency constraints is provided | ||
147 | yet - still under discussion. | ||
66 | 148 | ||
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c index 22a537669624..d9145dfc2a3b 100644 --- a/arch/arm/mach-msm/clock.c +++ b/arch/arm/mach-msm/clock.c | |||
@@ -18,7 +18,7 @@ | |||
18 | #include <linux/list.h> | 18 | #include <linux/list.h> |
19 | #include <linux/err.h> | 19 | #include <linux/err.h> |
20 | #include <linux/spinlock.h> | 20 | #include <linux/spinlock.h> |
21 | #include <linux/pm_qos_params.h> | 21 | #include <linux/pm_qos.h> |
22 | #include <linux/mutex.h> | 22 | #include <linux/mutex.h> |
23 | #include <linux/clk.h> | 23 | #include <linux/clk.h> |
24 | #include <linux/string.h> | 24 | #include <linux/string.h> |
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 431ab11c8c1b..2e69e09ff03e 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
@@ -37,7 +37,7 @@ | |||
37 | #include <linux/dmi.h> | 37 | #include <linux/dmi.h> |
38 | #include <linux/moduleparam.h> | 38 | #include <linux/moduleparam.h> |
39 | #include <linux/sched.h> /* need_resched() */ | 39 | #include <linux/sched.h> /* need_resched() */ |
40 | #include <linux/pm_qos_params.h> | 40 | #include <linux/pm_qos.h> |
41 | #include <linux/clockchips.h> | 41 | #include <linux/clockchips.h> |
42 | #include <linux/cpuidle.h> | 42 | #include <linux/cpuidle.h> |
43 | #include <linux/irqflags.h> | 43 | #include <linux/irqflags.h> |
diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile index 6488ce12f586..81676dd17900 100644 --- a/drivers/base/power/Makefile +++ b/drivers/base/power/Makefile | |||
@@ -1,4 +1,4 @@ | |||
1 | obj-$(CONFIG_PM) += sysfs.o generic_ops.o common.o | 1 | obj-$(CONFIG_PM) += sysfs.o generic_ops.o common.o qos.o |
2 | obj-$(CONFIG_PM_SLEEP) += main.o wakeup.o | 2 | obj-$(CONFIG_PM_SLEEP) += main.o wakeup.o |
3 | obj-$(CONFIG_PM_RUNTIME) += runtime.o | 3 | obj-$(CONFIG_PM_RUNTIME) += runtime.o |
4 | obj-$(CONFIG_PM_TRACE_RTC) += trace.o | 4 | obj-$(CONFIG_PM_TRACE_RTC) += trace.o |
@@ -6,4 +6,4 @@ obj-$(CONFIG_PM_OPP) += opp.o | |||
6 | obj-$(CONFIG_PM_GENERIC_DOMAINS) += domain.o | 6 | obj-$(CONFIG_PM_GENERIC_DOMAINS) += domain.o |
7 | obj-$(CONFIG_HAVE_CLK) += clock_ops.o | 7 | obj-$(CONFIG_HAVE_CLK) += clock_ops.o |
8 | 8 | ||
9 | ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG \ No newline at end of file | 9 | ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG |
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index a85459126bc6..c6291ab725a3 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
@@ -65,6 +65,7 @@ void device_pm_init(struct device *dev) | |||
65 | spin_lock_init(&dev->power.lock); | 65 | spin_lock_init(&dev->power.lock); |
66 | pm_runtime_init(dev); | 66 | pm_runtime_init(dev); |
67 | INIT_LIST_HEAD(&dev->power.entry); | 67 | INIT_LIST_HEAD(&dev->power.entry); |
68 | dev->power.power_state = PMSG_INVALID; | ||
68 | } | 69 | } |
69 | 70 | ||
70 | /** | 71 | /** |
@@ -96,6 +97,7 @@ void device_pm_add(struct device *dev) | |||
96 | dev_warn(dev, "parent %s should not be sleeping\n", | 97 | dev_warn(dev, "parent %s should not be sleeping\n", |
97 | dev_name(dev->parent)); | 98 | dev_name(dev->parent)); |
98 | list_add_tail(&dev->power.entry, &dpm_list); | 99 | list_add_tail(&dev->power.entry, &dpm_list); |
100 | dev_pm_qos_constraints_init(dev); | ||
99 | mutex_unlock(&dpm_list_mtx); | 101 | mutex_unlock(&dpm_list_mtx); |
100 | } | 102 | } |
101 | 103 | ||
@@ -109,6 +111,7 @@ void device_pm_remove(struct device *dev) | |||
109 | dev->bus ? dev->bus->name : "No Bus", dev_name(dev)); | 111 | dev->bus ? dev->bus->name : "No Bus", dev_name(dev)); |
110 | complete_all(&dev->power.completion); | 112 | complete_all(&dev->power.completion); |
111 | mutex_lock(&dpm_list_mtx); | 113 | mutex_lock(&dpm_list_mtx); |
114 | dev_pm_qos_constraints_destroy(dev); | ||
112 | list_del_init(&dev->power.entry); | 115 | list_del_init(&dev->power.entry); |
113 | mutex_unlock(&dpm_list_mtx); | 116 | mutex_unlock(&dpm_list_mtx); |
114 | device_wakeup_disable(dev); | 117 | device_wakeup_disable(dev); |
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h index f2a25f18fde7..9bf62323aaf3 100644 --- a/drivers/base/power/power.h +++ b/drivers/base/power/power.h | |||
@@ -1,3 +1,5 @@ | |||
1 | #include <linux/pm_qos.h> | ||
2 | |||
1 | #ifdef CONFIG_PM_RUNTIME | 3 | #ifdef CONFIG_PM_RUNTIME |
2 | 4 | ||
3 | extern void pm_runtime_init(struct device *dev); | 5 | extern void pm_runtime_init(struct device *dev); |
@@ -35,15 +37,21 @@ extern void device_pm_move_last(struct device *); | |||
35 | static inline void device_pm_init(struct device *dev) | 37 | static inline void device_pm_init(struct device *dev) |
36 | { | 38 | { |
37 | spin_lock_init(&dev->power.lock); | 39 | spin_lock_init(&dev->power.lock); |
40 | dev->power.power_state = PMSG_INVALID; | ||
38 | pm_runtime_init(dev); | 41 | pm_runtime_init(dev); |
39 | } | 42 | } |
40 | 43 | ||
44 | static inline void device_pm_add(struct device *dev) | ||
45 | { | ||
46 | dev_pm_qos_constraints_init(dev); | ||
47 | } | ||
48 | |||
41 | static inline void device_pm_remove(struct device *dev) | 49 | static inline void device_pm_remove(struct device *dev) |
42 | { | 50 | { |
51 | dev_pm_qos_constraints_destroy(dev); | ||
43 | pm_runtime_remove(dev); | 52 | pm_runtime_remove(dev); |
44 | } | 53 | } |
45 | 54 | ||
46 | static inline void device_pm_add(struct device *dev) {} | ||
47 | static inline void device_pm_move_before(struct device *deva, | 55 | static inline void device_pm_move_before(struct device *deva, |
48 | struct device *devb) {} | 56 | struct device *devb) {} |
49 | static inline void device_pm_move_after(struct device *deva, | 57 | static inline void device_pm_move_after(struct device *deva, |
diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c new file mode 100644 index 000000000000..91e061417382 --- /dev/null +++ b/drivers/base/power/qos.c | |||
@@ -0,0 +1,419 @@ | |||
1 | /* | ||
2 | * Devices PM QoS constraints management | ||
3 | * | ||
4 | * Copyright (C) 2011 Texas Instruments, Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * | ||
11 | * This module exposes the interface to kernel space for specifying | ||
12 | * per-device PM QoS dependencies. It provides infrastructure for registration | ||
13 | * of: | ||
14 | * | ||
15 | * Dependents on a QoS value : register requests | ||
16 | * Watchers of QoS value : get notified when target QoS value changes | ||
17 | * | ||
18 | * This QoS design is best effort based. Dependents register their QoS needs. | ||
19 | * Watchers register to keep track of the current QoS needs of the system. | ||
20 | * Watchers can register different types of notification callbacks: | ||
21 | * . a per-device notification callback using the dev_pm_qos_*_notifier API. | ||
22 | * The notification chain data is stored in the per-device constraint | ||
23 | * data struct. | ||
24 | * . a system-wide notification callback using the dev_pm_qos_*_global_notifier | ||
25 | * API. The notification chain data is stored in a static variable. | ||
26 | * | ||
27 | * Note about the per-device constraint data struct allocation: | ||
28 | * . The per-device constraints data struct ptr is tored into the device | ||
29 | * dev_pm_info. | ||
30 | * . To minimize the data usage by the per-device constraints, the data struct | ||
31 | * is only allocated at the first call to dev_pm_qos_add_request. | ||
32 | * . The data is later free'd when the device is removed from the system. | ||
33 | * . A global mutex protects the constraints users from the data being | ||
34 | * allocated and free'd. | ||
35 | */ | ||
36 | |||
37 | #include <linux/pm_qos.h> | ||
38 | #include <linux/spinlock.h> | ||
39 | #include <linux/slab.h> | ||
40 | #include <linux/device.h> | ||
41 | #include <linux/mutex.h> | ||
42 | |||
43 | |||
44 | static DEFINE_MUTEX(dev_pm_qos_mtx); | ||
45 | |||
46 | static BLOCKING_NOTIFIER_HEAD(dev_pm_notifiers); | ||
47 | |||
48 | /** | ||
49 | * dev_pm_qos_read_value - Get PM QoS constraint for a given device. | ||
50 | * @dev: Device to get the PM QoS constraint value for. | ||
51 | */ | ||
52 | s32 dev_pm_qos_read_value(struct device *dev) | ||
53 | { | ||
54 | struct pm_qos_constraints *c; | ||
55 | unsigned long flags; | ||
56 | s32 ret = 0; | ||
57 | |||
58 | spin_lock_irqsave(&dev->power.lock, flags); | ||
59 | |||
60 | c = dev->power.constraints; | ||
61 | if (c) | ||
62 | ret = pm_qos_read_value(c); | ||
63 | |||
64 | spin_unlock_irqrestore(&dev->power.lock, flags); | ||
65 | |||
66 | return ret; | ||
67 | } | ||
68 | |||
69 | /* | ||
70 | * apply_constraint | ||
71 | * @req: constraint request to apply | ||
72 | * @action: action to perform add/update/remove, of type enum pm_qos_req_action | ||
73 | * @value: defines the qos request | ||
74 | * | ||
75 | * Internal function to update the constraints list using the PM QoS core | ||
76 | * code and if needed call the per-device and the global notification | ||
77 | * callbacks | ||
78 | */ | ||
79 | static int apply_constraint(struct dev_pm_qos_request *req, | ||
80 | enum pm_qos_req_action action, int value) | ||
81 | { | ||
82 | int ret, curr_value; | ||
83 | |||
84 | ret = pm_qos_update_target(req->dev->power.constraints, | ||
85 | &req->node, action, value); | ||
86 | |||
87 | if (ret) { | ||
88 | /* Call the global callbacks if needed */ | ||
89 | curr_value = pm_qos_read_value(req->dev->power.constraints); | ||
90 | blocking_notifier_call_chain(&dev_pm_notifiers, | ||
91 | (unsigned long)curr_value, | ||
92 | req); | ||
93 | } | ||
94 | |||
95 | return ret; | ||
96 | } | ||
97 | |||
98 | /* | ||
99 | * dev_pm_qos_constraints_allocate | ||
100 | * @dev: device to allocate data for | ||
101 | * | ||
102 | * Called at the first call to add_request, for constraint data allocation | ||
103 | * Must be called with the dev_pm_qos_mtx mutex held | ||
104 | */ | ||
105 | static int dev_pm_qos_constraints_allocate(struct device *dev) | ||
106 | { | ||
107 | struct pm_qos_constraints *c; | ||
108 | struct blocking_notifier_head *n; | ||
109 | |||
110 | c = kzalloc(sizeof(*c), GFP_KERNEL); | ||
111 | if (!c) | ||
112 | return -ENOMEM; | ||
113 | |||
114 | n = kzalloc(sizeof(*n), GFP_KERNEL); | ||
115 | if (!n) { | ||
116 | kfree(c); | ||
117 | return -ENOMEM; | ||
118 | } | ||
119 | BLOCKING_INIT_NOTIFIER_HEAD(n); | ||
120 | |||
121 | plist_head_init(&c->list); | ||
122 | c->target_value = PM_QOS_DEV_LAT_DEFAULT_VALUE; | ||
123 | c->default_value = PM_QOS_DEV_LAT_DEFAULT_VALUE; | ||
124 | c->type = PM_QOS_MIN; | ||
125 | c->notifiers = n; | ||
126 | |||
127 | spin_lock_irq(&dev->power.lock); | ||
128 | dev->power.constraints = c; | ||
129 | spin_unlock_irq(&dev->power.lock); | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | /** | ||
135 | * dev_pm_qos_constraints_init - Initalize device's PM QoS constraints pointer. | ||
136 | * @dev: target device | ||
137 | * | ||
138 | * Called from the device PM subsystem during device insertion under | ||
139 | * device_pm_lock(). | ||
140 | */ | ||
141 | void dev_pm_qos_constraints_init(struct device *dev) | ||
142 | { | ||
143 | mutex_lock(&dev_pm_qos_mtx); | ||
144 | dev->power.constraints = NULL; | ||
145 | dev->power.power_state = PMSG_ON; | ||
146 | mutex_unlock(&dev_pm_qos_mtx); | ||
147 | } | ||
148 | |||
149 | /** | ||
150 | * dev_pm_qos_constraints_destroy | ||
151 | * @dev: target device | ||
152 | * | ||
153 | * Called from the device PM subsystem on device removal under device_pm_lock(). | ||
154 | */ | ||
155 | void dev_pm_qos_constraints_destroy(struct device *dev) | ||
156 | { | ||
157 | struct dev_pm_qos_request *req, *tmp; | ||
158 | struct pm_qos_constraints *c; | ||
159 | |||
160 | mutex_lock(&dev_pm_qos_mtx); | ||
161 | |||
162 | dev->power.power_state = PMSG_INVALID; | ||
163 | c = dev->power.constraints; | ||
164 | if (!c) | ||
165 | goto out; | ||
166 | |||
167 | /* Flush the constraints list for the device */ | ||
168 | plist_for_each_entry_safe(req, tmp, &c->list, node) { | ||
169 | /* | ||
170 | * Update constraints list and call the notification | ||
171 | * callbacks if needed | ||
172 | */ | ||
173 | apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE); | ||
174 | memset(req, 0, sizeof(*req)); | ||
175 | } | ||
176 | |||
177 | spin_lock_irq(&dev->power.lock); | ||
178 | dev->power.constraints = NULL; | ||
179 | spin_unlock_irq(&dev->power.lock); | ||
180 | |||
181 | kfree(c->notifiers); | ||
182 | kfree(c); | ||
183 | |||
184 | out: | ||
185 | mutex_unlock(&dev_pm_qos_mtx); | ||
186 | } | ||
187 | |||
188 | /** | ||
189 | * dev_pm_qos_add_request - inserts new qos request into the list | ||
190 | * @dev: target device for the constraint | ||
191 | * @req: pointer to a preallocated handle | ||
192 | * @value: defines the qos request | ||
193 | * | ||
194 | * This function inserts a new entry in the device constraints list of | ||
195 | * requested qos performance characteristics. It recomputes the aggregate | ||
196 | * QoS expectations of parameters and initializes the dev_pm_qos_request | ||
197 | * handle. Caller needs to save this handle for later use in updates and | ||
198 | * removal. | ||
199 | * | ||
200 | * Returns 1 if the aggregated constraint value has changed, | ||
201 | * 0 if the aggregated constraint value has not changed, | ||
202 | * -EINVAL in case of wrong parameters, -ENOMEM if there's not enough memory | ||
203 | * to allocate for data structures, -ENODEV if the device has just been removed | ||
204 | * from the system. | ||
205 | */ | ||
206 | int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req, | ||
207 | s32 value) | ||
208 | { | ||
209 | int ret = 0; | ||
210 | |||
211 | if (!dev || !req) /*guard against callers passing in null */ | ||
212 | return -EINVAL; | ||
213 | |||
214 | if (dev_pm_qos_request_active(req)) { | ||
215 | WARN(1, KERN_ERR "dev_pm_qos_add_request() called for already " | ||
216 | "added request\n"); | ||
217 | return -EINVAL; | ||
218 | } | ||
219 | |||
220 | req->dev = dev; | ||
221 | |||
222 | mutex_lock(&dev_pm_qos_mtx); | ||
223 | |||
224 | if (!dev->power.constraints) { | ||
225 | if (dev->power.power_state.event == PM_EVENT_INVALID) { | ||
226 | /* The device has been removed from the system. */ | ||
227 | req->dev = NULL; | ||
228 | ret = -ENODEV; | ||
229 | goto out; | ||
230 | } else { | ||
231 | /* | ||
232 | * Allocate the constraints data on the first call to | ||
233 | * add_request, i.e. only if the data is not already | ||
234 | * allocated and if the device has not been removed. | ||
235 | */ | ||
236 | ret = dev_pm_qos_constraints_allocate(dev); | ||
237 | } | ||
238 | } | ||
239 | |||
240 | if (!ret) | ||
241 | ret = apply_constraint(req, PM_QOS_ADD_REQ, value); | ||
242 | |||
243 | out: | ||
244 | mutex_unlock(&dev_pm_qos_mtx); | ||
245 | |||
246 | return ret; | ||
247 | } | ||
248 | EXPORT_SYMBOL_GPL(dev_pm_qos_add_request); | ||
249 | |||
250 | /** | ||
251 | * dev_pm_qos_update_request - modifies an existing qos request | ||
252 | * @req : handle to list element holding a dev_pm_qos request to use | ||
253 | * @new_value: defines the qos request | ||
254 | * | ||
255 | * Updates an existing dev PM qos request along with updating the | ||
256 | * target value. | ||
257 | * | ||
258 | * Attempts are made to make this code callable on hot code paths. | ||
259 | * | ||
260 | * Returns 1 if the aggregated constraint value has changed, | ||
261 | * 0 if the aggregated constraint value has not changed, | ||
262 | * -EINVAL in case of wrong parameters, -ENODEV if the device has been | ||
263 | * removed from the system | ||
264 | */ | ||
265 | int dev_pm_qos_update_request(struct dev_pm_qos_request *req, | ||
266 | s32 new_value) | ||
267 | { | ||
268 | int ret = 0; | ||
269 | |||
270 | if (!req) /*guard against callers passing in null */ | ||
271 | return -EINVAL; | ||
272 | |||
273 | if (!dev_pm_qos_request_active(req)) { | ||
274 | WARN(1, KERN_ERR "dev_pm_qos_update_request() called for " | ||
275 | "unknown object\n"); | ||
276 | return -EINVAL; | ||
277 | } | ||
278 | |||
279 | mutex_lock(&dev_pm_qos_mtx); | ||
280 | |||
281 | if (req->dev->power.constraints) { | ||
282 | if (new_value != req->node.prio) | ||
283 | ret = apply_constraint(req, PM_QOS_UPDATE_REQ, | ||
284 | new_value); | ||
285 | } else { | ||
286 | /* Return if the device has been removed */ | ||
287 | ret = -ENODEV; | ||
288 | } | ||
289 | |||
290 | mutex_unlock(&dev_pm_qos_mtx); | ||
291 | return ret; | ||
292 | } | ||
293 | EXPORT_SYMBOL_GPL(dev_pm_qos_update_request); | ||
294 | |||
295 | /** | ||
296 | * dev_pm_qos_remove_request - modifies an existing qos request | ||
297 | * @req: handle to request list element | ||
298 | * | ||
299 | * Will remove pm qos request from the list of constraints and | ||
300 | * recompute the current target value. Call this on slow code paths. | ||
301 | * | ||
302 | * Returns 1 if the aggregated constraint value has changed, | ||
303 | * 0 if the aggregated constraint value has not changed, | ||
304 | * -EINVAL in case of wrong parameters, -ENODEV if the device has been | ||
305 | * removed from the system | ||
306 | */ | ||
307 | int dev_pm_qos_remove_request(struct dev_pm_qos_request *req) | ||
308 | { | ||
309 | int ret = 0; | ||
310 | |||
311 | if (!req) /*guard against callers passing in null */ | ||
312 | return -EINVAL; | ||
313 | |||
314 | if (!dev_pm_qos_request_active(req)) { | ||
315 | WARN(1, KERN_ERR "dev_pm_qos_remove_request() called for " | ||
316 | "unknown object\n"); | ||
317 | return -EINVAL; | ||
318 | } | ||
319 | |||
320 | mutex_lock(&dev_pm_qos_mtx); | ||
321 | |||
322 | if (req->dev->power.constraints) { | ||
323 | ret = apply_constraint(req, PM_QOS_REMOVE_REQ, | ||
324 | PM_QOS_DEFAULT_VALUE); | ||
325 | memset(req, 0, sizeof(*req)); | ||
326 | } else { | ||
327 | /* Return if the device has been removed */ | ||
328 | ret = -ENODEV; | ||
329 | } | ||
330 | |||
331 | mutex_unlock(&dev_pm_qos_mtx); | ||
332 | return ret; | ||
333 | } | ||
334 | EXPORT_SYMBOL_GPL(dev_pm_qos_remove_request); | ||
335 | |||
336 | /** | ||
337 | * dev_pm_qos_add_notifier - sets notification entry for changes to target value | ||
338 | * of per-device PM QoS constraints | ||
339 | * | ||
340 | * @dev: target device for the constraint | ||
341 | * @notifier: notifier block managed by caller. | ||
342 | * | ||
343 | * Will register the notifier into a notification chain that gets called | ||
344 | * upon changes to the target value for the device. | ||
345 | */ | ||
346 | int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier) | ||
347 | { | ||
348 | int retval = 0; | ||
349 | |||
350 | mutex_lock(&dev_pm_qos_mtx); | ||
351 | |||
352 | /* Silently return if the constraints object is not present. */ | ||
353 | if (dev->power.constraints) | ||
354 | retval = blocking_notifier_chain_register( | ||
355 | dev->power.constraints->notifiers, | ||
356 | notifier); | ||
357 | |||
358 | mutex_unlock(&dev_pm_qos_mtx); | ||
359 | return retval; | ||
360 | } | ||
361 | EXPORT_SYMBOL_GPL(dev_pm_qos_add_notifier); | ||
362 | |||
363 | /** | ||
364 | * dev_pm_qos_remove_notifier - deletes notification for changes to target value | ||
365 | * of per-device PM QoS constraints | ||
366 | * | ||
367 | * @dev: target device for the constraint | ||
368 | * @notifier: notifier block to be removed. | ||
369 | * | ||
370 | * Will remove the notifier from the notification chain that gets called | ||
371 | * upon changes to the target value. | ||
372 | */ | ||
373 | int dev_pm_qos_remove_notifier(struct device *dev, | ||
374 | struct notifier_block *notifier) | ||
375 | { | ||
376 | int retval = 0; | ||
377 | |||
378 | mutex_lock(&dev_pm_qos_mtx); | ||
379 | |||
380 | /* Silently return if the constraints object is not present. */ | ||
381 | if (dev->power.constraints) | ||
382 | retval = blocking_notifier_chain_unregister( | ||
383 | dev->power.constraints->notifiers, | ||
384 | notifier); | ||
385 | |||
386 | mutex_unlock(&dev_pm_qos_mtx); | ||
387 | return retval; | ||
388 | } | ||
389 | EXPORT_SYMBOL_GPL(dev_pm_qos_remove_notifier); | ||
390 | |||
391 | /** | ||
392 | * dev_pm_qos_add_global_notifier - sets notification entry for changes to | ||
393 | * target value of the PM QoS constraints for any device | ||
394 | * | ||
395 | * @notifier: notifier block managed by caller. | ||
396 | * | ||
397 | * Will register the notifier into a notification chain that gets called | ||
398 | * upon changes to the target value for any device. | ||
399 | */ | ||
400 | int dev_pm_qos_add_global_notifier(struct notifier_block *notifier) | ||
401 | { | ||
402 | return blocking_notifier_chain_register(&dev_pm_notifiers, notifier); | ||
403 | } | ||
404 | EXPORT_SYMBOL_GPL(dev_pm_qos_add_global_notifier); | ||
405 | |||
406 | /** | ||
407 | * dev_pm_qos_remove_global_notifier - deletes notification for changes to | ||
408 | * target value of PM QoS constraints for any device | ||
409 | * | ||
410 | * @notifier: notifier block to be removed. | ||
411 | * | ||
412 | * Will remove the notifier from the notification chain that gets called | ||
413 | * upon changes to the target value for any device. | ||
414 | */ | ||
415 | int dev_pm_qos_remove_global_notifier(struct notifier_block *notifier) | ||
416 | { | ||
417 | return blocking_notifier_chain_unregister(&dev_pm_notifiers, notifier); | ||
418 | } | ||
419 | EXPORT_SYMBOL_GPL(dev_pm_qos_remove_global_notifier); | ||
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index d4c542372886..0df014110097 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c | |||
@@ -12,7 +12,7 @@ | |||
12 | #include <linux/mutex.h> | 12 | #include <linux/mutex.h> |
13 | #include <linux/sched.h> | 13 | #include <linux/sched.h> |
14 | #include <linux/notifier.h> | 14 | #include <linux/notifier.h> |
15 | #include <linux/pm_qos_params.h> | 15 | #include <linux/pm_qos.h> |
16 | #include <linux/cpu.h> | 16 | #include <linux/cpu.h> |
17 | #include <linux/cpuidle.h> | 17 | #include <linux/cpuidle.h> |
18 | #include <linux/ktime.h> | 18 | #include <linux/ktime.h> |
diff --git a/drivers/cpuidle/governors/ladder.c b/drivers/cpuidle/governors/ladder.c index 12c98900dcf8..f62fde21e962 100644 --- a/drivers/cpuidle/governors/ladder.c +++ b/drivers/cpuidle/governors/ladder.c | |||
@@ -14,7 +14,7 @@ | |||
14 | 14 | ||
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/cpuidle.h> | 16 | #include <linux/cpuidle.h> |
17 | #include <linux/pm_qos_params.h> | 17 | #include <linux/pm_qos.h> |
18 | #include <linux/moduleparam.h> | 18 | #include <linux/moduleparam.h> |
19 | #include <linux/jiffies.h> | 19 | #include <linux/jiffies.h> |
20 | 20 | ||
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index c47f3d09c1ee..3600f1955e48 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c | |||
@@ -12,7 +12,7 @@ | |||
12 | 12 | ||
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/cpuidle.h> | 14 | #include <linux/cpuidle.h> |
15 | #include <linux/pm_qos_params.h> | 15 | #include <linux/pm_qos.h> |
16 | #include <linux/time.h> | 16 | #include <linux/time.h> |
17 | #include <linux/ktime.h> | 17 | #include <linux/ktime.h> |
18 | #include <linux/hrtimer.h> | 18 | #include <linux/hrtimer.h> |
diff --git a/drivers/media/video/via-camera.c b/drivers/media/video/via-camera.c index bb7f17f2a33c..cbf13d09b4ac 100644 --- a/drivers/media/video/via-camera.c +++ b/drivers/media/video/via-camera.c | |||
@@ -21,7 +21,7 @@ | |||
21 | #include <media/videobuf-dma-sg.h> | 21 | #include <media/videobuf-dma-sg.h> |
22 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
23 | #include <linux/dma-mapping.h> | 23 | #include <linux/dma-mapping.h> |
24 | #include <linux/pm_qos_params.h> | 24 | #include <linux/pm_qos.h> |
25 | #include <linux/via-core.h> | 25 | #include <linux/via-core.h> |
26 | #include <linux/via-gpio.h> | 26 | #include <linux/via-gpio.h> |
27 | #include <linux/via_i2c.h> | 27 | #include <linux/via_i2c.h> |
@@ -69,7 +69,7 @@ struct via_camera { | |||
69 | struct mutex lock; | 69 | struct mutex lock; |
70 | enum viacam_opstate opstate; | 70 | enum viacam_opstate opstate; |
71 | unsigned long flags; | 71 | unsigned long flags; |
72 | struct pm_qos_request_list qos_request; | 72 | struct pm_qos_request qos_request; |
73 | /* | 73 | /* |
74 | * GPIO info for power/reset management | 74 | * GPIO info for power/reset management |
75 | */ | 75 | */ |
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 2198e615f241..07031af38964 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c | |||
@@ -47,7 +47,7 @@ | |||
47 | #include <linux/if_vlan.h> | 47 | #include <linux/if_vlan.h> |
48 | #include <linux/cpu.h> | 48 | #include <linux/cpu.h> |
49 | #include <linux/smp.h> | 49 | #include <linux/smp.h> |
50 | #include <linux/pm_qos_params.h> | 50 | #include <linux/pm_qos.h> |
51 | #include <linux/pm_runtime.h> | 51 | #include <linux/pm_runtime.h> |
52 | #include <linux/aer.h> | 52 | #include <linux/aer.h> |
53 | #include <linux/prefetch.h> | 53 | #include <linux/prefetch.h> |
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index ef9ad79d1bfd..127e9c63beaf 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c | |||
@@ -161,7 +161,7 @@ that only one external action is invoked at a time. | |||
161 | #include <linux/firmware.h> | 161 | #include <linux/firmware.h> |
162 | #include <linux/acpi.h> | 162 | #include <linux/acpi.h> |
163 | #include <linux/ctype.h> | 163 | #include <linux/ctype.h> |
164 | #include <linux/pm_qos_params.h> | 164 | #include <linux/pm_qos.h> |
165 | 165 | ||
166 | #include <net/lib80211.h> | 166 | #include <net/lib80211.h> |
167 | 167 | ||
@@ -174,7 +174,7 @@ that only one external action is invoked at a time. | |||
174 | #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2100 Network Driver" | 174 | #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2100 Network Driver" |
175 | #define DRV_COPYRIGHT "Copyright(c) 2003-2006 Intel Corporation" | 175 | #define DRV_COPYRIGHT "Copyright(c) 2003-2006 Intel Corporation" |
176 | 176 | ||
177 | static struct pm_qos_request_list ipw2100_pm_qos_req; | 177 | static struct pm_qos_request ipw2100_pm_qos_req; |
178 | 178 | ||
179 | /* Debugging stuff */ | 179 | /* Debugging stuff */ |
180 | #ifdef CONFIG_IPW2100_DEBUG | 180 | #ifdef CONFIG_IPW2100_DEBUG |
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index ddee79bb8f15..f38ab5b7e768 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -31,7 +31,7 @@ | |||
31 | #include <linux/if_link.h> | 31 | #include <linux/if_link.h> |
32 | 32 | ||
33 | #ifdef __KERNEL__ | 33 | #ifdef __KERNEL__ |
34 | #include <linux/pm_qos_params.h> | 34 | #include <linux/pm_qos.h> |
35 | #include <linux/timer.h> | 35 | #include <linux/timer.h> |
36 | #include <linux/delay.h> | 36 | #include <linux/delay.h> |
37 | #include <linux/atomic.h> | 37 | #include <linux/atomic.h> |
@@ -964,7 +964,7 @@ struct net_device { | |||
964 | */ | 964 | */ |
965 | char name[IFNAMSIZ]; | 965 | char name[IFNAMSIZ]; |
966 | 966 | ||
967 | struct pm_qos_request_list pm_qos_req; | 967 | struct pm_qos_request pm_qos_req; |
968 | 968 | ||
969 | /* device name hash chain */ | 969 | /* device name hash chain */ |
970 | struct hlist_node name_hlist; | 970 | struct hlist_node name_hlist; |
diff --git a/include/linux/pm.h b/include/linux/pm.h index f497ed06ee15..91f248bbe4fe 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h | |||
@@ -326,6 +326,7 @@ extern struct dev_pm_ops generic_subsys_pm_ops; | |||
326 | * requested by a driver. | 326 | * requested by a driver. |
327 | */ | 327 | */ |
328 | 328 | ||
329 | #define PM_EVENT_INVALID (-1) | ||
329 | #define PM_EVENT_ON 0x0000 | 330 | #define PM_EVENT_ON 0x0000 |
330 | #define PM_EVENT_FREEZE 0x0001 | 331 | #define PM_EVENT_FREEZE 0x0001 |
331 | #define PM_EVENT_SUSPEND 0x0002 | 332 | #define PM_EVENT_SUSPEND 0x0002 |
@@ -346,6 +347,7 @@ extern struct dev_pm_ops generic_subsys_pm_ops; | |||
346 | #define PM_EVENT_AUTO_SUSPEND (PM_EVENT_AUTO | PM_EVENT_SUSPEND) | 347 | #define PM_EVENT_AUTO_SUSPEND (PM_EVENT_AUTO | PM_EVENT_SUSPEND) |
347 | #define PM_EVENT_AUTO_RESUME (PM_EVENT_AUTO | PM_EVENT_RESUME) | 348 | #define PM_EVENT_AUTO_RESUME (PM_EVENT_AUTO | PM_EVENT_RESUME) |
348 | 349 | ||
350 | #define PMSG_INVALID ((struct pm_message){ .event = PM_EVENT_INVALID, }) | ||
349 | #define PMSG_ON ((struct pm_message){ .event = PM_EVENT_ON, }) | 351 | #define PMSG_ON ((struct pm_message){ .event = PM_EVENT_ON, }) |
350 | #define PMSG_FREEZE ((struct pm_message){ .event = PM_EVENT_FREEZE, }) | 352 | #define PMSG_FREEZE ((struct pm_message){ .event = PM_EVENT_FREEZE, }) |
351 | #define PMSG_QUIESCE ((struct pm_message){ .event = PM_EVENT_QUIESCE, }) | 353 | #define PMSG_QUIESCE ((struct pm_message){ .event = PM_EVENT_QUIESCE, }) |
@@ -481,6 +483,7 @@ struct dev_pm_info { | |||
481 | unsigned long accounting_timestamp; | 483 | unsigned long accounting_timestamp; |
482 | #endif | 484 | #endif |
483 | struct pm_subsys_data *subsys_data; /* Owned by the subsystem. */ | 485 | struct pm_subsys_data *subsys_data; /* Owned by the subsystem. */ |
486 | struct pm_qos_constraints *constraints; | ||
484 | }; | 487 | }; |
485 | 488 | ||
486 | extern void update_pm_runtime_accounting(struct device *dev); | 489 | extern void update_pm_runtime_accounting(struct device *dev); |
diff --git a/include/linux/pm_qos.h b/include/linux/pm_qos.h new file mode 100644 index 000000000000..83b0ea302a80 --- /dev/null +++ b/include/linux/pm_qos.h | |||
@@ -0,0 +1,155 @@ | |||
1 | #ifndef _LINUX_PM_QOS_H | ||
2 | #define _LINUX_PM_QOS_H | ||
3 | /* interface for the pm_qos_power infrastructure of the linux kernel. | ||
4 | * | ||
5 | * Mark Gross <mgross@linux.intel.com> | ||
6 | */ | ||
7 | #include <linux/plist.h> | ||
8 | #include <linux/notifier.h> | ||
9 | #include <linux/miscdevice.h> | ||
10 | #include <linux/device.h> | ||
11 | |||
12 | #define PM_QOS_RESERVED 0 | ||
13 | #define PM_QOS_CPU_DMA_LATENCY 1 | ||
14 | #define PM_QOS_NETWORK_LATENCY 2 | ||
15 | #define PM_QOS_NETWORK_THROUGHPUT 3 | ||
16 | |||
17 | #define PM_QOS_NUM_CLASSES 4 | ||
18 | #define PM_QOS_DEFAULT_VALUE -1 | ||
19 | |||
20 | #define PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE (2000 * USEC_PER_SEC) | ||
21 | #define PM_QOS_NETWORK_LAT_DEFAULT_VALUE (2000 * USEC_PER_SEC) | ||
22 | #define PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE 0 | ||
23 | #define PM_QOS_DEV_LAT_DEFAULT_VALUE 0 | ||
24 | |||
25 | struct pm_qos_request { | ||
26 | struct plist_node node; | ||
27 | int pm_qos_class; | ||
28 | }; | ||
29 | |||
30 | struct dev_pm_qos_request { | ||
31 | struct plist_node node; | ||
32 | struct device *dev; | ||
33 | }; | ||
34 | |||
35 | enum pm_qos_type { | ||
36 | PM_QOS_UNITIALIZED, | ||
37 | PM_QOS_MAX, /* return the largest value */ | ||
38 | PM_QOS_MIN /* return the smallest value */ | ||
39 | }; | ||
40 | |||
41 | /* | ||
42 | * Note: The lockless read path depends on the CPU accessing | ||
43 | * target_value atomically. Atomic access is only guaranteed on all CPU | ||
44 | * types linux supports for 32 bit quantites | ||
45 | */ | ||
46 | struct pm_qos_constraints { | ||
47 | struct plist_head list; | ||
48 | s32 target_value; /* Do not change to 64 bit */ | ||
49 | s32 default_value; | ||
50 | enum pm_qos_type type; | ||
51 | struct blocking_notifier_head *notifiers; | ||
52 | }; | ||
53 | |||
54 | /* Action requested to pm_qos_update_target */ | ||
55 | enum pm_qos_req_action { | ||
56 | PM_QOS_ADD_REQ, /* Add a new request */ | ||
57 | PM_QOS_UPDATE_REQ, /* Update an existing request */ | ||
58 | PM_QOS_REMOVE_REQ /* Remove an existing request */ | ||
59 | }; | ||
60 | |||
61 | static inline int dev_pm_qos_request_active(struct dev_pm_qos_request *req) | ||
62 | { | ||
63 | return req->dev != 0; | ||
64 | } | ||
65 | |||
66 | #ifdef CONFIG_PM | ||
67 | int pm_qos_update_target(struct pm_qos_constraints *c, struct plist_node *node, | ||
68 | enum pm_qos_req_action action, int value); | ||
69 | void pm_qos_add_request(struct pm_qos_request *req, int pm_qos_class, | ||
70 | s32 value); | ||
71 | void pm_qos_update_request(struct pm_qos_request *req, | ||
72 | s32 new_value); | ||
73 | void pm_qos_remove_request(struct pm_qos_request *req); | ||
74 | |||
75 | int pm_qos_request(int pm_qos_class); | ||
76 | int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier); | ||
77 | int pm_qos_remove_notifier(int pm_qos_class, struct notifier_block *notifier); | ||
78 | int pm_qos_request_active(struct pm_qos_request *req); | ||
79 | s32 pm_qos_read_value(struct pm_qos_constraints *c); | ||
80 | |||
81 | s32 dev_pm_qos_read_value(struct device *dev); | ||
82 | int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req, | ||
83 | s32 value); | ||
84 | int dev_pm_qos_update_request(struct dev_pm_qos_request *req, s32 new_value); | ||
85 | int dev_pm_qos_remove_request(struct dev_pm_qos_request *req); | ||
86 | int dev_pm_qos_add_notifier(struct device *dev, | ||
87 | struct notifier_block *notifier); | ||
88 | int dev_pm_qos_remove_notifier(struct device *dev, | ||
89 | struct notifier_block *notifier); | ||
90 | int dev_pm_qos_add_global_notifier(struct notifier_block *notifier); | ||
91 | int dev_pm_qos_remove_global_notifier(struct notifier_block *notifier); | ||
92 | void dev_pm_qos_constraints_init(struct device *dev); | ||
93 | void dev_pm_qos_constraints_destroy(struct device *dev); | ||
94 | #else | ||
95 | static inline int pm_qos_update_target(struct pm_qos_constraints *c, | ||
96 | struct plist_node *node, | ||
97 | enum pm_qos_req_action action, | ||
98 | int value) | ||
99 | { return 0; } | ||
100 | static inline void pm_qos_add_request(struct pm_qos_request *req, | ||
101 | int pm_qos_class, s32 value) | ||
102 | { return; } | ||
103 | static inline void pm_qos_update_request(struct pm_qos_request *req, | ||
104 | s32 new_value) | ||
105 | { return; } | ||
106 | static inline void pm_qos_remove_request(struct pm_qos_request *req) | ||
107 | { return; } | ||
108 | |||
109 | static inline int pm_qos_request(int pm_qos_class) | ||
110 | { return 0; } | ||
111 | static inline int pm_qos_add_notifier(int pm_qos_class, | ||
112 | struct notifier_block *notifier) | ||
113 | { return 0; } | ||
114 | static inline int pm_qos_remove_notifier(int pm_qos_class, | ||
115 | struct notifier_block *notifier) | ||
116 | { return 0; } | ||
117 | static inline int pm_qos_request_active(struct pm_qos_request *req) | ||
118 | { return 0; } | ||
119 | static inline s32 pm_qos_read_value(struct pm_qos_constraints *c) | ||
120 | { return 0; } | ||
121 | |||
122 | static inline s32 dev_pm_qos_read_value(struct device *dev) | ||
123 | { return 0; } | ||
124 | static inline int dev_pm_qos_add_request(struct device *dev, | ||
125 | struct dev_pm_qos_request *req, | ||
126 | s32 value) | ||
127 | { return 0; } | ||
128 | static inline int dev_pm_qos_update_request(struct dev_pm_qos_request *req, | ||
129 | s32 new_value) | ||
130 | { return 0; } | ||
131 | static inline int dev_pm_qos_remove_request(struct dev_pm_qos_request *req) | ||
132 | { return 0; } | ||
133 | static inline int dev_pm_qos_add_notifier(struct device *dev, | ||
134 | struct notifier_block *notifier) | ||
135 | { return 0; } | ||
136 | static inline int dev_pm_qos_remove_notifier(struct device *dev, | ||
137 | struct notifier_block *notifier) | ||
138 | { return 0; } | ||
139 | static inline int dev_pm_qos_add_global_notifier( | ||
140 | struct notifier_block *notifier) | ||
141 | { return 0; } | ||
142 | static inline int dev_pm_qos_remove_global_notifier( | ||
143 | struct notifier_block *notifier) | ||
144 | { return 0; } | ||
145 | static inline void dev_pm_qos_constraints_init(struct device *dev) | ||
146 | { | ||
147 | dev->power.power_state = PMSG_ON; | ||
148 | } | ||
149 | static inline void dev_pm_qos_constraints_destroy(struct device *dev) | ||
150 | { | ||
151 | dev->power.power_state = PMSG_INVALID; | ||
152 | } | ||
153 | #endif | ||
154 | |||
155 | #endif | ||
diff --git a/include/linux/pm_qos_params.h b/include/linux/pm_qos_params.h deleted file mode 100644 index a7d87f911cab..000000000000 --- a/include/linux/pm_qos_params.h +++ /dev/null | |||
@@ -1,38 +0,0 @@ | |||
1 | #ifndef _LINUX_PM_QOS_PARAMS_H | ||
2 | #define _LINUX_PM_QOS_PARAMS_H | ||
3 | /* interface for the pm_qos_power infrastructure of the linux kernel. | ||
4 | * | ||
5 | * Mark Gross <mgross@linux.intel.com> | ||
6 | */ | ||
7 | #include <linux/plist.h> | ||
8 | #include <linux/notifier.h> | ||
9 | #include <linux/miscdevice.h> | ||
10 | |||
11 | #define PM_QOS_RESERVED 0 | ||
12 | #define PM_QOS_CPU_DMA_LATENCY 1 | ||
13 | #define PM_QOS_NETWORK_LATENCY 2 | ||
14 | #define PM_QOS_NETWORK_THROUGHPUT 3 | ||
15 | |||
16 | #define PM_QOS_NUM_CLASSES 4 | ||
17 | #define PM_QOS_DEFAULT_VALUE -1 | ||
18 | |||
19 | #define PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE (2000 * USEC_PER_SEC) | ||
20 | #define PM_QOS_NETWORK_LAT_DEFAULT_VALUE (2000 * USEC_PER_SEC) | ||
21 | #define PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE 0 | ||
22 | |||
23 | struct pm_qos_request_list { | ||
24 | struct plist_node list; | ||
25 | int pm_qos_class; | ||
26 | }; | ||
27 | |||
28 | void pm_qos_add_request(struct pm_qos_request_list *l, int pm_qos_class, s32 value); | ||
29 | void pm_qos_update_request(struct pm_qos_request_list *pm_qos_req, | ||
30 | s32 new_value); | ||
31 | void pm_qos_remove_request(struct pm_qos_request_list *pm_qos_req); | ||
32 | |||
33 | int pm_qos_request(int pm_qos_class); | ||
34 | int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier); | ||
35 | int pm_qos_remove_notifier(int pm_qos_class, struct notifier_block *notifier); | ||
36 | int pm_qos_request_active(struct pm_qos_request_list *req); | ||
37 | |||
38 | #endif | ||
diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 57e71fa33f7c..54cb079b7bf1 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h | |||
@@ -29,7 +29,7 @@ | |||
29 | #include <linux/poll.h> | 29 | #include <linux/poll.h> |
30 | #include <linux/mm.h> | 30 | #include <linux/mm.h> |
31 | #include <linux/bitops.h> | 31 | #include <linux/bitops.h> |
32 | #include <linux/pm_qos_params.h> | 32 | #include <linux/pm_qos.h> |
33 | 33 | ||
34 | #define snd_pcm_substream_chip(substream) ((substream)->private_data) | 34 | #define snd_pcm_substream_chip(substream) ((substream)->private_data) |
35 | #define snd_pcm_chip(pcm) ((pcm)->private_data) | 35 | #define snd_pcm_chip(pcm) ((pcm)->private_data) |
@@ -373,7 +373,7 @@ struct snd_pcm_substream { | |||
373 | int number; | 373 | int number; |
374 | char name[32]; /* substream name */ | 374 | char name[32]; /* substream name */ |
375 | int stream; /* stream (direction) */ | 375 | int stream; /* stream (direction) */ |
376 | struct pm_qos_request_list latency_pm_qos_req; /* pm_qos request */ | 376 | struct pm_qos_request latency_pm_qos_req; /* pm_qos request */ |
377 | size_t buffer_bytes_max; /* limit ring buffer size */ | 377 | size_t buffer_bytes_max; /* limit ring buffer size */ |
378 | struct snd_dma_buffer dma_buffer; | 378 | struct snd_dma_buffer dma_buffer; |
379 | unsigned int dma_buf_id; | 379 | unsigned int dma_buf_id; |
diff --git a/kernel/Makefile b/kernel/Makefile index eca595e2fd52..2da48d3515eb 100644 --- a/kernel/Makefile +++ b/kernel/Makefile | |||
@@ -9,7 +9,7 @@ obj-y = sched.o fork.o exec_domain.o panic.o printk.o \ | |||
9 | rcupdate.o extable.o params.o posix-timers.o \ | 9 | rcupdate.o extable.o params.o posix-timers.o \ |
10 | kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \ | 10 | kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \ |
11 | hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \ | 11 | hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \ |
12 | notifier.o ksysfs.o pm_qos_params.o sched_clock.o cred.o \ | 12 | notifier.o ksysfs.o sched_clock.o cred.o \ |
13 | async.o range.o | 13 | async.o range.o |
14 | obj-y += groups.o | 14 | obj-y += groups.o |
15 | 15 | ||
diff --git a/kernel/power/Makefile b/kernel/power/Makefile index c5ebc6a90643..ad6bdd8b401a 100644 --- a/kernel/power/Makefile +++ b/kernel/power/Makefile | |||
@@ -1,7 +1,7 @@ | |||
1 | 1 | ||
2 | ccflags-$(CONFIG_PM_DEBUG) := -DDEBUG | 2 | ccflags-$(CONFIG_PM_DEBUG) := -DDEBUG |
3 | 3 | ||
4 | obj-$(CONFIG_PM) += main.o | 4 | obj-$(CONFIG_PM) += main.o qos.o |
5 | obj-$(CONFIG_PM_SLEEP) += console.o | 5 | obj-$(CONFIG_PM_SLEEP) += console.o |
6 | obj-$(CONFIG_FREEZER) += process.o | 6 | obj-$(CONFIG_FREEZER) += process.o |
7 | obj-$(CONFIG_SUSPEND) += suspend.o | 7 | obj-$(CONFIG_SUSPEND) += suspend.o |
diff --git a/kernel/pm_qos_params.c b/kernel/power/qos.c index 37f05d0f0793..1c1797dd1d1d 100644 --- a/kernel/pm_qos_params.c +++ b/kernel/power/qos.c | |||
@@ -29,7 +29,7 @@ | |||
29 | 29 | ||
30 | /*#define DEBUG*/ | 30 | /*#define DEBUG*/ |
31 | 31 | ||
32 | #include <linux/pm_qos_params.h> | 32 | #include <linux/pm_qos.h> |
33 | #include <linux/sched.h> | 33 | #include <linux/sched.h> |
34 | #include <linux/spinlock.h> | 34 | #include <linux/spinlock.h> |
35 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
@@ -45,62 +45,57 @@ | |||
45 | #include <linux/uaccess.h> | 45 | #include <linux/uaccess.h> |
46 | 46 | ||
47 | /* | 47 | /* |
48 | * locking rule: all changes to requests or notifiers lists | 48 | * locking rule: all changes to constraints or notifiers lists |
49 | * or pm_qos_object list and pm_qos_objects need to happen with pm_qos_lock | 49 | * or pm_qos_object list and pm_qos_objects need to happen with pm_qos_lock |
50 | * held, taken with _irqsave. One lock to rule them all | 50 | * held, taken with _irqsave. One lock to rule them all |
51 | */ | 51 | */ |
52 | enum pm_qos_type { | ||
53 | PM_QOS_MAX, /* return the largest value */ | ||
54 | PM_QOS_MIN /* return the smallest value */ | ||
55 | }; | ||
56 | |||
57 | /* | ||
58 | * Note: The lockless read path depends on the CPU accessing | ||
59 | * target_value atomically. Atomic access is only guaranteed on all CPU | ||
60 | * types linux supports for 32 bit quantites | ||
61 | */ | ||
62 | struct pm_qos_object { | 52 | struct pm_qos_object { |
63 | struct plist_head requests; | 53 | struct pm_qos_constraints *constraints; |
64 | struct blocking_notifier_head *notifiers; | ||
65 | struct miscdevice pm_qos_power_miscdev; | 54 | struct miscdevice pm_qos_power_miscdev; |
66 | char *name; | 55 | char *name; |
67 | s32 target_value; /* Do not change to 64 bit */ | ||
68 | s32 default_value; | ||
69 | enum pm_qos_type type; | ||
70 | }; | 56 | }; |
71 | 57 | ||
72 | static DEFINE_SPINLOCK(pm_qos_lock); | 58 | static DEFINE_SPINLOCK(pm_qos_lock); |
73 | 59 | ||
74 | static struct pm_qos_object null_pm_qos; | 60 | static struct pm_qos_object null_pm_qos; |
61 | |||
75 | static BLOCKING_NOTIFIER_HEAD(cpu_dma_lat_notifier); | 62 | static BLOCKING_NOTIFIER_HEAD(cpu_dma_lat_notifier); |
76 | static struct pm_qos_object cpu_dma_pm_qos = { | 63 | static struct pm_qos_constraints cpu_dma_constraints = { |
77 | .requests = PLIST_HEAD_INIT(cpu_dma_pm_qos.requests), | 64 | .list = PLIST_HEAD_INIT(cpu_dma_constraints.list), |
78 | .notifiers = &cpu_dma_lat_notifier, | ||
79 | .name = "cpu_dma_latency", | ||
80 | .target_value = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE, | 65 | .target_value = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE, |
81 | .default_value = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE, | 66 | .default_value = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE, |
82 | .type = PM_QOS_MIN, | 67 | .type = PM_QOS_MIN, |
68 | .notifiers = &cpu_dma_lat_notifier, | ||
69 | }; | ||
70 | static struct pm_qos_object cpu_dma_pm_qos = { | ||
71 | .constraints = &cpu_dma_constraints, | ||
83 | }; | 72 | }; |
84 | 73 | ||
85 | static BLOCKING_NOTIFIER_HEAD(network_lat_notifier); | 74 | static BLOCKING_NOTIFIER_HEAD(network_lat_notifier); |
86 | static struct pm_qos_object network_lat_pm_qos = { | 75 | static struct pm_qos_constraints network_lat_constraints = { |
87 | .requests = PLIST_HEAD_INIT(network_lat_pm_qos.requests), | 76 | .list = PLIST_HEAD_INIT(network_lat_constraints.list), |
88 | .notifiers = &network_lat_notifier, | ||
89 | .name = "network_latency", | ||
90 | .target_value = PM_QOS_NETWORK_LAT_DEFAULT_VALUE, | 77 | .target_value = PM_QOS_NETWORK_LAT_DEFAULT_VALUE, |
91 | .default_value = PM_QOS_NETWORK_LAT_DEFAULT_VALUE, | 78 | .default_value = PM_QOS_NETWORK_LAT_DEFAULT_VALUE, |
92 | .type = PM_QOS_MIN | 79 | .type = PM_QOS_MIN, |
80 | .notifiers = &network_lat_notifier, | ||
81 | }; | ||
82 | static struct pm_qos_object network_lat_pm_qos = { | ||
83 | .constraints = &network_lat_constraints, | ||
84 | .name = "network_latency", | ||
93 | }; | 85 | }; |
94 | 86 | ||
95 | 87 | ||
96 | static BLOCKING_NOTIFIER_HEAD(network_throughput_notifier); | 88 | static BLOCKING_NOTIFIER_HEAD(network_throughput_notifier); |
97 | static struct pm_qos_object network_throughput_pm_qos = { | 89 | static struct pm_qos_constraints network_tput_constraints = { |
98 | .requests = PLIST_HEAD_INIT(network_throughput_pm_qos.requests), | 90 | .list = PLIST_HEAD_INIT(network_tput_constraints.list), |
99 | .notifiers = &network_throughput_notifier, | ||
100 | .name = "network_throughput", | ||
101 | .target_value = PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE, | 91 | .target_value = PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE, |
102 | .default_value = PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE, | 92 | .default_value = PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE, |
103 | .type = PM_QOS_MAX, | 93 | .type = PM_QOS_MAX, |
94 | .notifiers = &network_throughput_notifier, | ||
95 | }; | ||
96 | static struct pm_qos_object network_throughput_pm_qos = { | ||
97 | .constraints = &network_tput_constraints, | ||
98 | .name = "network_throughput", | ||
104 | }; | 99 | }; |
105 | 100 | ||
106 | 101 | ||
@@ -127,17 +122,17 @@ static const struct file_operations pm_qos_power_fops = { | |||
127 | }; | 122 | }; |
128 | 123 | ||
129 | /* unlocked internal variant */ | 124 | /* unlocked internal variant */ |
130 | static inline int pm_qos_get_value(struct pm_qos_object *o) | 125 | static inline int pm_qos_get_value(struct pm_qos_constraints *c) |
131 | { | 126 | { |
132 | if (plist_head_empty(&o->requests)) | 127 | if (plist_head_empty(&c->list)) |
133 | return o->default_value; | 128 | return c->default_value; |
134 | 129 | ||
135 | switch (o->type) { | 130 | switch (c->type) { |
136 | case PM_QOS_MIN: | 131 | case PM_QOS_MIN: |
137 | return plist_first(&o->requests)->prio; | 132 | return plist_first(&c->list)->prio; |
138 | 133 | ||
139 | case PM_QOS_MAX: | 134 | case PM_QOS_MAX: |
140 | return plist_last(&o->requests)->prio; | 135 | return plist_last(&c->list)->prio; |
141 | 136 | ||
142 | default: | 137 | default: |
143 | /* runtime check for not using enum */ | 138 | /* runtime check for not using enum */ |
@@ -145,69 +140,73 @@ static inline int pm_qos_get_value(struct pm_qos_object *o) | |||
145 | } | 140 | } |
146 | } | 141 | } |
147 | 142 | ||
148 | static inline s32 pm_qos_read_value(struct pm_qos_object *o) | 143 | s32 pm_qos_read_value(struct pm_qos_constraints *c) |
149 | { | 144 | { |
150 | return o->target_value; | 145 | return c->target_value; |
151 | } | 146 | } |
152 | 147 | ||
153 | static inline void pm_qos_set_value(struct pm_qos_object *o, s32 value) | 148 | static inline void pm_qos_set_value(struct pm_qos_constraints *c, s32 value) |
154 | { | 149 | { |
155 | o->target_value = value; | 150 | c->target_value = value; |
156 | } | 151 | } |
157 | 152 | ||
158 | static void update_target(struct pm_qos_object *o, struct plist_node *node, | 153 | /** |
159 | int del, int value) | 154 | * pm_qos_update_target - manages the constraints list and calls the notifiers |
155 | * if needed | ||
156 | * @c: constraints data struct | ||
157 | * @node: request to add to the list, to update or to remove | ||
158 | * @action: action to take on the constraints list | ||
159 | * @value: value of the request to add or update | ||
160 | * | ||
161 | * This function returns 1 if the aggregated constraint value has changed, 0 | ||
162 | * otherwise. | ||
163 | */ | ||
164 | int pm_qos_update_target(struct pm_qos_constraints *c, struct plist_node *node, | ||
165 | enum pm_qos_req_action action, int value) | ||
160 | { | 166 | { |
161 | unsigned long flags; | 167 | unsigned long flags; |
162 | int prev_value, curr_value; | 168 | int prev_value, curr_value, new_value; |
163 | 169 | ||
164 | spin_lock_irqsave(&pm_qos_lock, flags); | 170 | spin_lock_irqsave(&pm_qos_lock, flags); |
165 | prev_value = pm_qos_get_value(o); | 171 | prev_value = pm_qos_get_value(c); |
166 | /* PM_QOS_DEFAULT_VALUE is a signal that the value is unchanged */ | 172 | if (value == PM_QOS_DEFAULT_VALUE) |
167 | if (value != PM_QOS_DEFAULT_VALUE) { | 173 | new_value = c->default_value; |
174 | else | ||
175 | new_value = value; | ||
176 | |||
177 | switch (action) { | ||
178 | case PM_QOS_REMOVE_REQ: | ||
179 | plist_del(node, &c->list); | ||
180 | break; | ||
181 | case PM_QOS_UPDATE_REQ: | ||
168 | /* | 182 | /* |
169 | * to change the list, we atomically remove, reinit | 183 | * to change the list, we atomically remove, reinit |
170 | * with new value and add, then see if the extremal | 184 | * with new value and add, then see if the extremal |
171 | * changed | 185 | * changed |
172 | */ | 186 | */ |
173 | plist_del(node, &o->requests); | 187 | plist_del(node, &c->list); |
174 | plist_node_init(node, value); | 188 | case PM_QOS_ADD_REQ: |
175 | plist_add(node, &o->requests); | 189 | plist_node_init(node, new_value); |
176 | } else if (del) { | 190 | plist_add(node, &c->list); |
177 | plist_del(node, &o->requests); | 191 | break; |
178 | } else { | 192 | default: |
179 | plist_add(node, &o->requests); | 193 | /* no action */ |
194 | ; | ||
180 | } | 195 | } |
181 | curr_value = pm_qos_get_value(o); | 196 | |
182 | pm_qos_set_value(o, curr_value); | 197 | curr_value = pm_qos_get_value(c); |
198 | pm_qos_set_value(c, curr_value); | ||
199 | |||
183 | spin_unlock_irqrestore(&pm_qos_lock, flags); | 200 | spin_unlock_irqrestore(&pm_qos_lock, flags); |
184 | 201 | ||
185 | if (prev_value != curr_value) | 202 | if (prev_value != curr_value) { |
186 | blocking_notifier_call_chain(o->notifiers, | 203 | blocking_notifier_call_chain(c->notifiers, |
187 | (unsigned long)curr_value, | 204 | (unsigned long)curr_value, |
188 | NULL); | 205 | NULL); |
189 | } | 206 | return 1; |
190 | 207 | } else { | |
191 | static int register_pm_qos_misc(struct pm_qos_object *qos) | 208 | return 0; |
192 | { | ||
193 | qos->pm_qos_power_miscdev.minor = MISC_DYNAMIC_MINOR; | ||
194 | qos->pm_qos_power_miscdev.name = qos->name; | ||
195 | qos->pm_qos_power_miscdev.fops = &pm_qos_power_fops; | ||
196 | |||
197 | return misc_register(&qos->pm_qos_power_miscdev); | ||
198 | } | ||
199 | |||
200 | static int find_pm_qos_object_by_minor(int minor) | ||
201 | { | ||
202 | int pm_qos_class; | ||
203 | |||
204 | for (pm_qos_class = 0; | ||
205 | pm_qos_class < PM_QOS_NUM_CLASSES; pm_qos_class++) { | ||
206 | if (minor == | ||
207 | pm_qos_array[pm_qos_class]->pm_qos_power_miscdev.minor) | ||
208 | return pm_qos_class; | ||
209 | } | 209 | } |
210 | return -1; | ||
211 | } | 210 | } |
212 | 211 | ||
213 | /** | 212 | /** |
@@ -218,11 +217,11 @@ static int find_pm_qos_object_by_minor(int minor) | |||
218 | */ | 217 | */ |
219 | int pm_qos_request(int pm_qos_class) | 218 | int pm_qos_request(int pm_qos_class) |
220 | { | 219 | { |
221 | return pm_qos_read_value(pm_qos_array[pm_qos_class]); | 220 | return pm_qos_read_value(pm_qos_array[pm_qos_class]->constraints); |
222 | } | 221 | } |
223 | EXPORT_SYMBOL_GPL(pm_qos_request); | 222 | EXPORT_SYMBOL_GPL(pm_qos_request); |
224 | 223 | ||
225 | int pm_qos_request_active(struct pm_qos_request_list *req) | 224 | int pm_qos_request_active(struct pm_qos_request *req) |
226 | { | 225 | { |
227 | return req->pm_qos_class != 0; | 226 | return req->pm_qos_class != 0; |
228 | } | 227 | } |
@@ -230,40 +229,36 @@ EXPORT_SYMBOL_GPL(pm_qos_request_active); | |||
230 | 229 | ||
231 | /** | 230 | /** |
232 | * pm_qos_add_request - inserts new qos request into the list | 231 | * pm_qos_add_request - inserts new qos request into the list |
233 | * @dep: pointer to a preallocated handle | 232 | * @req: pointer to a preallocated handle |
234 | * @pm_qos_class: identifies which list of qos request to use | 233 | * @pm_qos_class: identifies which list of qos request to use |
235 | * @value: defines the qos request | 234 | * @value: defines the qos request |
236 | * | 235 | * |
237 | * This function inserts a new entry in the pm_qos_class list of requested qos | 236 | * This function inserts a new entry in the pm_qos_class list of requested qos |
238 | * performance characteristics. It recomputes the aggregate QoS expectations | 237 | * performance characteristics. It recomputes the aggregate QoS expectations |
239 | * for the pm_qos_class of parameters and initializes the pm_qos_request_list | 238 | * for the pm_qos_class of parameters and initializes the pm_qos_request |
240 | * handle. Caller needs to save this handle for later use in updates and | 239 | * handle. Caller needs to save this handle for later use in updates and |
241 | * removal. | 240 | * removal. |
242 | */ | 241 | */ |
243 | 242 | ||
244 | void pm_qos_add_request(struct pm_qos_request_list *dep, | 243 | void pm_qos_add_request(struct pm_qos_request *req, |
245 | int pm_qos_class, s32 value) | 244 | int pm_qos_class, s32 value) |
246 | { | 245 | { |
247 | struct pm_qos_object *o = pm_qos_array[pm_qos_class]; | 246 | if (!req) /*guard against callers passing in null */ |
248 | int new_value; | 247 | return; |
249 | 248 | ||
250 | if (pm_qos_request_active(dep)) { | 249 | if (pm_qos_request_active(req)) { |
251 | WARN(1, KERN_ERR "pm_qos_add_request() called for already added request\n"); | 250 | WARN(1, KERN_ERR "pm_qos_add_request() called for already added request\n"); |
252 | return; | 251 | return; |
253 | } | 252 | } |
254 | if (value == PM_QOS_DEFAULT_VALUE) | 253 | req->pm_qos_class = pm_qos_class; |
255 | new_value = o->default_value; | 254 | pm_qos_update_target(pm_qos_array[pm_qos_class]->constraints, |
256 | else | 255 | &req->node, PM_QOS_ADD_REQ, value); |
257 | new_value = value; | ||
258 | plist_node_init(&dep->list, new_value); | ||
259 | dep->pm_qos_class = pm_qos_class; | ||
260 | update_target(o, &dep->list, 0, PM_QOS_DEFAULT_VALUE); | ||
261 | } | 256 | } |
262 | EXPORT_SYMBOL_GPL(pm_qos_add_request); | 257 | EXPORT_SYMBOL_GPL(pm_qos_add_request); |
263 | 258 | ||
264 | /** | 259 | /** |
265 | * pm_qos_update_request - modifies an existing qos request | 260 | * pm_qos_update_request - modifies an existing qos request |
266 | * @pm_qos_req : handle to list element holding a pm_qos request to use | 261 | * @req : handle to list element holding a pm_qos request to use |
267 | * @value: defines the qos request | 262 | * @value: defines the qos request |
268 | * | 263 | * |
269 | * Updates an existing qos request for the pm_qos_class of parameters along | 264 | * Updates an existing qos request for the pm_qos_class of parameters along |
@@ -271,56 +266,47 @@ EXPORT_SYMBOL_GPL(pm_qos_add_request); | |||
271 | * | 266 | * |
272 | * Attempts are made to make this code callable on hot code paths. | 267 | * Attempts are made to make this code callable on hot code paths. |
273 | */ | 268 | */ |
274 | void pm_qos_update_request(struct pm_qos_request_list *pm_qos_req, | 269 | void pm_qos_update_request(struct pm_qos_request *req, |
275 | s32 new_value) | 270 | s32 new_value) |
276 | { | 271 | { |
277 | s32 temp; | 272 | if (!req) /*guard against callers passing in null */ |
278 | struct pm_qos_object *o; | ||
279 | |||
280 | if (!pm_qos_req) /*guard against callers passing in null */ | ||
281 | return; | 273 | return; |
282 | 274 | ||
283 | if (!pm_qos_request_active(pm_qos_req)) { | 275 | if (!pm_qos_request_active(req)) { |
284 | WARN(1, KERN_ERR "pm_qos_update_request() called for unknown object\n"); | 276 | WARN(1, KERN_ERR "pm_qos_update_request() called for unknown object\n"); |
285 | return; | 277 | return; |
286 | } | 278 | } |
287 | 279 | ||
288 | o = pm_qos_array[pm_qos_req->pm_qos_class]; | 280 | if (new_value != req->node.prio) |
289 | 281 | pm_qos_update_target( | |
290 | if (new_value == PM_QOS_DEFAULT_VALUE) | 282 | pm_qos_array[req->pm_qos_class]->constraints, |
291 | temp = o->default_value; | 283 | &req->node, PM_QOS_UPDATE_REQ, new_value); |
292 | else | ||
293 | temp = new_value; | ||
294 | |||
295 | if (temp != pm_qos_req->list.prio) | ||
296 | update_target(o, &pm_qos_req->list, 0, temp); | ||
297 | } | 284 | } |
298 | EXPORT_SYMBOL_GPL(pm_qos_update_request); | 285 | EXPORT_SYMBOL_GPL(pm_qos_update_request); |
299 | 286 | ||
300 | /** | 287 | /** |
301 | * pm_qos_remove_request - modifies an existing qos request | 288 | * pm_qos_remove_request - modifies an existing qos request |
302 | * @pm_qos_req: handle to request list element | 289 | * @req: handle to request list element |
303 | * | 290 | * |
304 | * Will remove pm qos request from the list of requests and | 291 | * Will remove pm qos request from the list of constraints and |
305 | * recompute the current target value for the pm_qos_class. Call this | 292 | * recompute the current target value for the pm_qos_class. Call this |
306 | * on slow code paths. | 293 | * on slow code paths. |
307 | */ | 294 | */ |
308 | void pm_qos_remove_request(struct pm_qos_request_list *pm_qos_req) | 295 | void pm_qos_remove_request(struct pm_qos_request *req) |
309 | { | 296 | { |
310 | struct pm_qos_object *o; | 297 | if (!req) /*guard against callers passing in null */ |
311 | |||
312 | if (pm_qos_req == NULL) | ||
313 | return; | 298 | return; |
314 | /* silent return to keep pcm code cleaner */ | 299 | /* silent return to keep pcm code cleaner */ |
315 | 300 | ||
316 | if (!pm_qos_request_active(pm_qos_req)) { | 301 | if (!pm_qos_request_active(req)) { |
317 | WARN(1, KERN_ERR "pm_qos_remove_request() called for unknown object\n"); | 302 | WARN(1, KERN_ERR "pm_qos_remove_request() called for unknown object\n"); |
318 | return; | 303 | return; |
319 | } | 304 | } |
320 | 305 | ||
321 | o = pm_qos_array[pm_qos_req->pm_qos_class]; | 306 | pm_qos_update_target(pm_qos_array[req->pm_qos_class]->constraints, |
322 | update_target(o, &pm_qos_req->list, 1, PM_QOS_DEFAULT_VALUE); | 307 | &req->node, PM_QOS_REMOVE_REQ, |
323 | memset(pm_qos_req, 0, sizeof(*pm_qos_req)); | 308 | PM_QOS_DEFAULT_VALUE); |
309 | memset(req, 0, sizeof(*req)); | ||
324 | } | 310 | } |
325 | EXPORT_SYMBOL_GPL(pm_qos_remove_request); | 311 | EXPORT_SYMBOL_GPL(pm_qos_remove_request); |
326 | 312 | ||
@@ -337,7 +323,8 @@ int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier) | |||
337 | int retval; | 323 | int retval; |
338 | 324 | ||
339 | retval = blocking_notifier_chain_register( | 325 | retval = blocking_notifier_chain_register( |
340 | pm_qos_array[pm_qos_class]->notifiers, notifier); | 326 | pm_qos_array[pm_qos_class]->constraints->notifiers, |
327 | notifier); | ||
341 | 328 | ||
342 | return retval; | 329 | return retval; |
343 | } | 330 | } |
@@ -356,19 +343,43 @@ int pm_qos_remove_notifier(int pm_qos_class, struct notifier_block *notifier) | |||
356 | int retval; | 343 | int retval; |
357 | 344 | ||
358 | retval = blocking_notifier_chain_unregister( | 345 | retval = blocking_notifier_chain_unregister( |
359 | pm_qos_array[pm_qos_class]->notifiers, notifier); | 346 | pm_qos_array[pm_qos_class]->constraints->notifiers, |
347 | notifier); | ||
360 | 348 | ||
361 | return retval; | 349 | return retval; |
362 | } | 350 | } |
363 | EXPORT_SYMBOL_GPL(pm_qos_remove_notifier); | 351 | EXPORT_SYMBOL_GPL(pm_qos_remove_notifier); |
364 | 352 | ||
353 | /* User space interface to PM QoS classes via misc devices */ | ||
354 | static int register_pm_qos_misc(struct pm_qos_object *qos) | ||
355 | { | ||
356 | qos->pm_qos_power_miscdev.minor = MISC_DYNAMIC_MINOR; | ||
357 | qos->pm_qos_power_miscdev.name = qos->name; | ||
358 | qos->pm_qos_power_miscdev.fops = &pm_qos_power_fops; | ||
359 | |||
360 | return misc_register(&qos->pm_qos_power_miscdev); | ||
361 | } | ||
362 | |||
363 | static int find_pm_qos_object_by_minor(int minor) | ||
364 | { | ||
365 | int pm_qos_class; | ||
366 | |||
367 | for (pm_qos_class = 0; | ||
368 | pm_qos_class < PM_QOS_NUM_CLASSES; pm_qos_class++) { | ||
369 | if (minor == | ||
370 | pm_qos_array[pm_qos_class]->pm_qos_power_miscdev.minor) | ||
371 | return pm_qos_class; | ||
372 | } | ||
373 | return -1; | ||
374 | } | ||
375 | |||
365 | static int pm_qos_power_open(struct inode *inode, struct file *filp) | 376 | static int pm_qos_power_open(struct inode *inode, struct file *filp) |
366 | { | 377 | { |
367 | long pm_qos_class; | 378 | long pm_qos_class; |
368 | 379 | ||
369 | pm_qos_class = find_pm_qos_object_by_minor(iminor(inode)); | 380 | pm_qos_class = find_pm_qos_object_by_minor(iminor(inode)); |
370 | if (pm_qos_class >= 0) { | 381 | if (pm_qos_class >= 0) { |
371 | struct pm_qos_request_list *req = kzalloc(sizeof(*req), GFP_KERNEL); | 382 | struct pm_qos_request *req = kzalloc(sizeof(*req), GFP_KERNEL); |
372 | if (!req) | 383 | if (!req) |
373 | return -ENOMEM; | 384 | return -ENOMEM; |
374 | 385 | ||
@@ -383,7 +394,7 @@ static int pm_qos_power_open(struct inode *inode, struct file *filp) | |||
383 | 394 | ||
384 | static int pm_qos_power_release(struct inode *inode, struct file *filp) | 395 | static int pm_qos_power_release(struct inode *inode, struct file *filp) |
385 | { | 396 | { |
386 | struct pm_qos_request_list *req; | 397 | struct pm_qos_request *req; |
387 | 398 | ||
388 | req = filp->private_data; | 399 | req = filp->private_data; |
389 | pm_qos_remove_request(req); | 400 | pm_qos_remove_request(req); |
@@ -398,17 +409,15 @@ static ssize_t pm_qos_power_read(struct file *filp, char __user *buf, | |||
398 | { | 409 | { |
399 | s32 value; | 410 | s32 value; |
400 | unsigned long flags; | 411 | unsigned long flags; |
401 | struct pm_qos_object *o; | 412 | struct pm_qos_request *req = filp->private_data; |
402 | struct pm_qos_request_list *pm_qos_req = filp->private_data; | ||
403 | 413 | ||
404 | if (!pm_qos_req) | 414 | if (!req) |
405 | return -EINVAL; | 415 | return -EINVAL; |
406 | if (!pm_qos_request_active(pm_qos_req)) | 416 | if (!pm_qos_request_active(req)) |
407 | return -EINVAL; | 417 | return -EINVAL; |
408 | 418 | ||
409 | o = pm_qos_array[pm_qos_req->pm_qos_class]; | ||
410 | spin_lock_irqsave(&pm_qos_lock, flags); | 419 | spin_lock_irqsave(&pm_qos_lock, flags); |
411 | value = pm_qos_get_value(o); | 420 | value = pm_qos_get_value(pm_qos_array[req->pm_qos_class]->constraints); |
412 | spin_unlock_irqrestore(&pm_qos_lock, flags); | 421 | spin_unlock_irqrestore(&pm_qos_lock, flags); |
413 | 422 | ||
414 | return simple_read_from_buffer(buf, count, f_pos, &value, sizeof(s32)); | 423 | return simple_read_from_buffer(buf, count, f_pos, &value, sizeof(s32)); |
@@ -418,7 +427,7 @@ static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf, | |||
418 | size_t count, loff_t *f_pos) | 427 | size_t count, loff_t *f_pos) |
419 | { | 428 | { |
420 | s32 value; | 429 | s32 value; |
421 | struct pm_qos_request_list *pm_qos_req; | 430 | struct pm_qos_request *req; |
422 | 431 | ||
423 | if (count == sizeof(s32)) { | 432 | if (count == sizeof(s32)) { |
424 | if (copy_from_user(&value, buf, sizeof(s32))) | 433 | if (copy_from_user(&value, buf, sizeof(s32))) |
@@ -449,8 +458,8 @@ static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf, | |||
449 | return -EINVAL; | 458 | return -EINVAL; |
450 | } | 459 | } |
451 | 460 | ||
452 | pm_qos_req = filp->private_data; | 461 | req = filp->private_data; |
453 | pm_qos_update_request(pm_qos_req, value); | 462 | pm_qos_update_request(req, value); |
454 | 463 | ||
455 | return count; | 464 | return count; |
456 | } | 465 | } |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index acb44230b251..b1c23c0408f6 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -19,7 +19,7 @@ | |||
19 | #include <linux/if_arp.h> | 19 | #include <linux/if_arp.h> |
20 | #include <linux/rtnetlink.h> | 20 | #include <linux/rtnetlink.h> |
21 | #include <linux/bitmap.h> | 21 | #include <linux/bitmap.h> |
22 | #include <linux/pm_qos_params.h> | 22 | #include <linux/pm_qos.h> |
23 | #include <linux/inetdevice.h> | 23 | #include <linux/inetdevice.h> |
24 | #include <net/net_namespace.h> | 24 | #include <net/net_namespace.h> |
25 | #include <net/cfg80211.h> | 25 | #include <net/cfg80211.h> |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index d6470c7fd6ce..9604abc61a59 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -17,7 +17,7 @@ | |||
17 | #include <linux/if_arp.h> | 17 | #include <linux/if_arp.h> |
18 | #include <linux/etherdevice.h> | 18 | #include <linux/etherdevice.h> |
19 | #include <linux/rtnetlink.h> | 19 | #include <linux/rtnetlink.h> |
20 | #include <linux/pm_qos_params.h> | 20 | #include <linux/pm_qos.h> |
21 | #include <linux/crc32.h> | 21 | #include <linux/crc32.h> |
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include <net/mac80211.h> | 23 | #include <net/mac80211.h> |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 6f09eca01112..beefb0afefa1 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -14,7 +14,7 @@ | |||
14 | 14 | ||
15 | #include <linux/if_arp.h> | 15 | #include <linux/if_arp.h> |
16 | #include <linux/rtnetlink.h> | 16 | #include <linux/rtnetlink.h> |
17 | #include <linux/pm_qos_params.h> | 17 | #include <linux/pm_qos.h> |
18 | #include <net/sch_generic.h> | 18 | #include <net/sch_generic.h> |
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include <net/mac80211.h> | 20 | #include <net/mac80211.h> |
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 1c6be91dfb98..c74e228731ed 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c | |||
@@ -23,7 +23,7 @@ | |||
23 | #include <linux/file.h> | 23 | #include <linux/file.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/time.h> | 25 | #include <linux/time.h> |
26 | #include <linux/pm_qos_params.h> | 26 | #include <linux/pm_qos.h> |
27 | #include <linux/uio.h> | 27 | #include <linux/uio.h> |
28 | #include <linux/dma-mapping.h> | 28 | #include <linux/dma-mapping.h> |
29 | #include <sound/core.h> | 29 | #include <sound/core.h> |