diff options
author | Jean Pihet <j-pihet@ti.com> | 2011-08-25 09:35:27 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rjw@sisk.pl> | 2011-08-25 09:35:27 -0400 |
commit | 4e1779baaa542c83b459b0a56585e0c1a04c7782 (patch) | |
tree | 0708390d5e00c000d97b89e846a94a7006249521 /kernel/power/qos.c | |
parent | 4a31a33425a1eb92f6a0b9846f081842268361c8 (diff) |
PM QoS: Reorganize data structs
In preparation for the per-device constratins support, re-organize
the data strctures:
- add a struct pm_qos_constraints which contains the constraints
related data
- update struct pm_qos_object contents to the PM QoS internal object
data. Add a pointer to struct pm_qos_constraints
- update the internal code to use the new data structs.
Signed-off-by: Jean Pihet <j-pihet@ti.com>
Reviewed-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Diffstat (limited to 'kernel/power/qos.c')
-rw-r--r-- | kernel/power/qos.c | 85 |
1 files changed, 41 insertions, 44 deletions
diff --git a/kernel/power/qos.c b/kernel/power/qos.c index 788c4cfe0cdb..4a35fe50b777 100644 --- a/kernel/power/qos.c +++ b/kernel/power/qos.c | |||
@@ -49,58 +49,53 @@ | |||
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 constraints; | 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 | .constraints = PLIST_HEAD_INIT(cpu_dma_pm_qos.constraints), | 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 | .constraints = PLIST_HEAD_INIT(network_lat_pm_qos.constraints), | 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 | .constraints = PLIST_HEAD_INIT(network_throughput_pm_qos.constraints), | 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 | ||
@@ -129,15 +124,15 @@ static const struct file_operations pm_qos_power_fops = { | |||
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_object *o) |
131 | { | 126 | { |
132 | if (plist_head_empty(&o->constraints)) | 127 | if (plist_head_empty(&o->constraints->list)) |
133 | return o->default_value; | 128 | return o->constraints->default_value; |
134 | 129 | ||
135 | switch (o->type) { | 130 | switch (o->constraints->type) { |
136 | case PM_QOS_MIN: | 131 | case PM_QOS_MIN: |
137 | return plist_first(&o->constraints)->prio; | 132 | return plist_first(&o->constraints->list)->prio; |
138 | 133 | ||
139 | case PM_QOS_MAX: | 134 | case PM_QOS_MAX: |
140 | return plist_last(&o->constraints)->prio; | 135 | return plist_last(&o->constraints->list)->prio; |
141 | 136 | ||
142 | default: | 137 | default: |
143 | /* runtime check for not using enum */ | 138 | /* runtime check for not using enum */ |
@@ -147,12 +142,12 @@ static inline int pm_qos_get_value(struct pm_qos_object *o) | |||
147 | 142 | ||
148 | static inline s32 pm_qos_read_value(struct pm_qos_object *o) | 143 | static inline s32 pm_qos_read_value(struct pm_qos_object *o) |
149 | { | 144 | { |
150 | return o->target_value; | 145 | return o->constraints->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_object *o, s32 value) |
154 | { | 149 | { |
155 | o->target_value = value; | 150 | o->constraints->target_value = value; |
156 | } | 151 | } |
157 | 152 | ||
158 | static void update_target(struct pm_qos_object *o, struct plist_node *node, | 153 | static void update_target(struct pm_qos_object *o, struct plist_node *node, |
@@ -170,20 +165,20 @@ static void update_target(struct pm_qos_object *o, struct plist_node *node, | |||
170 | * with new value and add, then see if the extremal | 165 | * with new value and add, then see if the extremal |
171 | * changed | 166 | * changed |
172 | */ | 167 | */ |
173 | plist_del(node, &o->constraints); | 168 | plist_del(node, &o->constraints->list); |
174 | plist_node_init(node, value); | 169 | plist_node_init(node, value); |
175 | plist_add(node, &o->constraints); | 170 | plist_add(node, &o->constraints->list); |
176 | } else if (del) { | 171 | } else if (del) { |
177 | plist_del(node, &o->constraints); | 172 | plist_del(node, &o->constraints->list); |
178 | } else { | 173 | } else { |
179 | plist_add(node, &o->constraints); | 174 | plist_add(node, &o->constraints->list); |
180 | } | 175 | } |
181 | curr_value = pm_qos_get_value(o); | 176 | curr_value = pm_qos_get_value(o); |
182 | pm_qos_set_value(o, curr_value); | 177 | pm_qos_set_value(o, curr_value); |
183 | spin_unlock_irqrestore(&pm_qos_lock, flags); | 178 | spin_unlock_irqrestore(&pm_qos_lock, flags); |
184 | 179 | ||
185 | if (prev_value != curr_value) | 180 | if (prev_value != curr_value) |
186 | blocking_notifier_call_chain(o->notifiers, | 181 | blocking_notifier_call_chain(o->constraints->notifiers, |
187 | (unsigned long)curr_value, | 182 | (unsigned long)curr_value, |
188 | NULL); | 183 | NULL); |
189 | } | 184 | } |
@@ -230,7 +225,7 @@ void pm_qos_add_request(struct pm_qos_request *req, | |||
230 | return; | 225 | return; |
231 | } | 226 | } |
232 | if (value == PM_QOS_DEFAULT_VALUE) | 227 | if (value == PM_QOS_DEFAULT_VALUE) |
233 | new_value = o->default_value; | 228 | new_value = o->constraints->default_value; |
234 | else | 229 | else |
235 | new_value = value; | 230 | new_value = value; |
236 | plist_node_init(&req->node, new_value); | 231 | plist_node_init(&req->node, new_value); |
@@ -266,7 +261,7 @@ void pm_qos_update_request(struct pm_qos_request *req, | |||
266 | o = pm_qos_array[req->pm_qos_class]; | 261 | o = pm_qos_array[req->pm_qos_class]; |
267 | 262 | ||
268 | if (new_value == PM_QOS_DEFAULT_VALUE) | 263 | if (new_value == PM_QOS_DEFAULT_VALUE) |
269 | temp = o->default_value; | 264 | temp = o->constraints->default_value; |
270 | else | 265 | else |
271 | temp = new_value; | 266 | temp = new_value; |
272 | 267 | ||
@@ -315,7 +310,8 @@ int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier) | |||
315 | int retval; | 310 | int retval; |
316 | 311 | ||
317 | retval = blocking_notifier_chain_register( | 312 | retval = blocking_notifier_chain_register( |
318 | pm_qos_array[pm_qos_class]->notifiers, notifier); | 313 | pm_qos_array[pm_qos_class]->constraints->notifiers, |
314 | notifier); | ||
319 | 315 | ||
320 | return retval; | 316 | return retval; |
321 | } | 317 | } |
@@ -334,7 +330,8 @@ int pm_qos_remove_notifier(int pm_qos_class, struct notifier_block *notifier) | |||
334 | int retval; | 330 | int retval; |
335 | 331 | ||
336 | retval = blocking_notifier_chain_unregister( | 332 | retval = blocking_notifier_chain_unregister( |
337 | pm_qos_array[pm_qos_class]->notifiers, notifier); | 333 | pm_qos_array[pm_qos_class]->constraints->notifiers, |
334 | notifier); | ||
338 | 335 | ||
339 | return retval; | 336 | return retval; |
340 | } | 337 | } |