diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2012-10-22 19:07:27 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2012-10-22 19:07:27 -0400 |
commit | 5f986c590fcf4284924fcda991cf14ab32bff49f (patch) | |
tree | 07b31910af67192423c5bc7b7e6ee1134bc221c2 | |
parent | 6f0c0580b70c89094b3422ba81118c7b959c7556 (diff) |
PM / QoS: Prepare device structure for adding more constraint types
Currently struct dev_pm_info contains only one PM QoS constraints
pointer reserved for latency requirements. Since one more device
constraints type (i.e. flags) will be necessary, introduce a new
structure, struct dev_pm_qos, that eventually will contain all of
the available device PM QoS constraints and replace the "constraints"
pointer in struct dev_pm_info with a pointer to the new structure
called "qos".
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Reviewed-by: Jean Pihet <j-pihet@ti.com>
-rw-r--r-- | drivers/base/power/qos.c | 42 | ||||
-rw-r--r-- | include/linux/pm.h | 2 | ||||
-rw-r--r-- | include/linux/pm_qos.h | 4 |
3 files changed, 27 insertions, 21 deletions
diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c index 74a67e0019a2..40ff1b02a7c5 100644 --- a/drivers/base/power/qos.c +++ b/drivers/base/power/qos.c | |||
@@ -55,9 +55,7 @@ static BLOCKING_NOTIFIER_HEAD(dev_pm_notifiers); | |||
55 | */ | 55 | */ |
56 | s32 __dev_pm_qos_read_value(struct device *dev) | 56 | s32 __dev_pm_qos_read_value(struct device *dev) |
57 | { | 57 | { |
58 | struct pm_qos_constraints *c = dev->power.constraints; | 58 | return dev->power.qos ? pm_qos_read_value(&dev->power.qos->latency) : 0; |
59 | |||
60 | return c ? pm_qos_read_value(c) : 0; | ||
61 | } | 59 | } |
62 | 60 | ||
63 | /** | 61 | /** |
@@ -91,12 +89,12 @@ static int apply_constraint(struct dev_pm_qos_request *req, | |||
91 | { | 89 | { |
92 | int ret, curr_value; | 90 | int ret, curr_value; |
93 | 91 | ||
94 | ret = pm_qos_update_target(req->dev->power.constraints, | 92 | ret = pm_qos_update_target(&req->dev->power.qos->latency, |
95 | &req->node, action, value); | 93 | &req->node, action, value); |
96 | 94 | ||
97 | if (ret) { | 95 | if (ret) { |
98 | /* Call the global callbacks if needed */ | 96 | /* Call the global callbacks if needed */ |
99 | curr_value = pm_qos_read_value(req->dev->power.constraints); | 97 | curr_value = pm_qos_read_value(&req->dev->power.qos->latency); |
100 | blocking_notifier_call_chain(&dev_pm_notifiers, | 98 | blocking_notifier_call_chain(&dev_pm_notifiers, |
101 | (unsigned long)curr_value, | 99 | (unsigned long)curr_value, |
102 | req); | 100 | req); |
@@ -114,20 +112,22 @@ static int apply_constraint(struct dev_pm_qos_request *req, | |||
114 | */ | 112 | */ |
115 | static int dev_pm_qos_constraints_allocate(struct device *dev) | 113 | static int dev_pm_qos_constraints_allocate(struct device *dev) |
116 | { | 114 | { |
115 | struct dev_pm_qos *qos; | ||
117 | struct pm_qos_constraints *c; | 116 | struct pm_qos_constraints *c; |
118 | struct blocking_notifier_head *n; | 117 | struct blocking_notifier_head *n; |
119 | 118 | ||
120 | c = kzalloc(sizeof(*c), GFP_KERNEL); | 119 | qos = kzalloc(sizeof(*qos), GFP_KERNEL); |
121 | if (!c) | 120 | if (!qos) |
122 | return -ENOMEM; | 121 | return -ENOMEM; |
123 | 122 | ||
124 | n = kzalloc(sizeof(*n), GFP_KERNEL); | 123 | n = kzalloc(sizeof(*n), GFP_KERNEL); |
125 | if (!n) { | 124 | if (!n) { |
126 | kfree(c); | 125 | kfree(qos); |
127 | return -ENOMEM; | 126 | return -ENOMEM; |
128 | } | 127 | } |
129 | BLOCKING_INIT_NOTIFIER_HEAD(n); | 128 | BLOCKING_INIT_NOTIFIER_HEAD(n); |
130 | 129 | ||
130 | c = &qos->latency; | ||
131 | plist_head_init(&c->list); | 131 | plist_head_init(&c->list); |
132 | c->target_value = PM_QOS_DEV_LAT_DEFAULT_VALUE; | 132 | c->target_value = PM_QOS_DEV_LAT_DEFAULT_VALUE; |
133 | c->default_value = PM_QOS_DEV_LAT_DEFAULT_VALUE; | 133 | c->default_value = PM_QOS_DEV_LAT_DEFAULT_VALUE; |
@@ -135,7 +135,7 @@ static int dev_pm_qos_constraints_allocate(struct device *dev) | |||
135 | c->notifiers = n; | 135 | c->notifiers = n; |
136 | 136 | ||
137 | spin_lock_irq(&dev->power.lock); | 137 | spin_lock_irq(&dev->power.lock); |
138 | dev->power.constraints = c; | 138 | dev->power.qos = qos; |
139 | spin_unlock_irq(&dev->power.lock); | 139 | spin_unlock_irq(&dev->power.lock); |
140 | 140 | ||
141 | return 0; | 141 | return 0; |
@@ -151,7 +151,7 @@ static int dev_pm_qos_constraints_allocate(struct device *dev) | |||
151 | void dev_pm_qos_constraints_init(struct device *dev) | 151 | void dev_pm_qos_constraints_init(struct device *dev) |
152 | { | 152 | { |
153 | mutex_lock(&dev_pm_qos_mtx); | 153 | mutex_lock(&dev_pm_qos_mtx); |
154 | dev->power.constraints = NULL; | 154 | dev->power.qos = NULL; |
155 | dev->power.power_state = PMSG_ON; | 155 | dev->power.power_state = PMSG_ON; |
156 | mutex_unlock(&dev_pm_qos_mtx); | 156 | mutex_unlock(&dev_pm_qos_mtx); |
157 | } | 157 | } |
@@ -164,6 +164,7 @@ void dev_pm_qos_constraints_init(struct device *dev) | |||
164 | */ | 164 | */ |
165 | void dev_pm_qos_constraints_destroy(struct device *dev) | 165 | void dev_pm_qos_constraints_destroy(struct device *dev) |
166 | { | 166 | { |
167 | struct dev_pm_qos *qos; | ||
167 | struct dev_pm_qos_request *req, *tmp; | 168 | struct dev_pm_qos_request *req, *tmp; |
168 | struct pm_qos_constraints *c; | 169 | struct pm_qos_constraints *c; |
169 | 170 | ||
@@ -176,10 +177,11 @@ void dev_pm_qos_constraints_destroy(struct device *dev) | |||
176 | mutex_lock(&dev_pm_qos_mtx); | 177 | mutex_lock(&dev_pm_qos_mtx); |
177 | 178 | ||
178 | dev->power.power_state = PMSG_INVALID; | 179 | dev->power.power_state = PMSG_INVALID; |
179 | c = dev->power.constraints; | 180 | qos = dev->power.qos; |
180 | if (!c) | 181 | if (!qos) |
181 | goto out; | 182 | goto out; |
182 | 183 | ||
184 | c = &qos->latency; | ||
183 | /* Flush the constraints list for the device */ | 185 | /* Flush the constraints list for the device */ |
184 | plist_for_each_entry_safe(req, tmp, &c->list, node) { | 186 | plist_for_each_entry_safe(req, tmp, &c->list, node) { |
185 | /* | 187 | /* |
@@ -191,7 +193,7 @@ void dev_pm_qos_constraints_destroy(struct device *dev) | |||
191 | } | 193 | } |
192 | 194 | ||
193 | spin_lock_irq(&dev->power.lock); | 195 | spin_lock_irq(&dev->power.lock); |
194 | dev->power.constraints = NULL; | 196 | dev->power.qos = NULL; |
195 | spin_unlock_irq(&dev->power.lock); | 197 | spin_unlock_irq(&dev->power.lock); |
196 | 198 | ||
197 | kfree(c->notifiers); | 199 | kfree(c->notifiers); |
@@ -235,7 +237,7 @@ int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req, | |||
235 | 237 | ||
236 | mutex_lock(&dev_pm_qos_mtx); | 238 | mutex_lock(&dev_pm_qos_mtx); |
237 | 239 | ||
238 | if (!dev->power.constraints) { | 240 | if (!dev->power.qos) { |
239 | if (dev->power.power_state.event == PM_EVENT_INVALID) { | 241 | if (dev->power.power_state.event == PM_EVENT_INVALID) { |
240 | /* The device has been removed from the system. */ | 242 | /* The device has been removed from the system. */ |
241 | req->dev = NULL; | 243 | req->dev = NULL; |
@@ -290,7 +292,7 @@ int dev_pm_qos_update_request(struct dev_pm_qos_request *req, | |||
290 | 292 | ||
291 | mutex_lock(&dev_pm_qos_mtx); | 293 | mutex_lock(&dev_pm_qos_mtx); |
292 | 294 | ||
293 | if (req->dev->power.constraints) { | 295 | if (req->dev->power.qos) { |
294 | if (new_value != req->node.prio) | 296 | if (new_value != req->node.prio) |
295 | ret = apply_constraint(req, PM_QOS_UPDATE_REQ, | 297 | ret = apply_constraint(req, PM_QOS_UPDATE_REQ, |
296 | new_value); | 298 | new_value); |
@@ -329,7 +331,7 @@ int dev_pm_qos_remove_request(struct dev_pm_qos_request *req) | |||
329 | 331 | ||
330 | mutex_lock(&dev_pm_qos_mtx); | 332 | mutex_lock(&dev_pm_qos_mtx); |
331 | 333 | ||
332 | if (req->dev->power.constraints) { | 334 | if (req->dev->power.qos) { |
333 | ret = apply_constraint(req, PM_QOS_REMOVE_REQ, | 335 | ret = apply_constraint(req, PM_QOS_REMOVE_REQ, |
334 | PM_QOS_DEFAULT_VALUE); | 336 | PM_QOS_DEFAULT_VALUE); |
335 | memset(req, 0, sizeof(*req)); | 337 | memset(req, 0, sizeof(*req)); |
@@ -362,13 +364,13 @@ int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier) | |||
362 | 364 | ||
363 | mutex_lock(&dev_pm_qos_mtx); | 365 | mutex_lock(&dev_pm_qos_mtx); |
364 | 366 | ||
365 | if (!dev->power.constraints) | 367 | if (!dev->power.qos) |
366 | ret = dev->power.power_state.event != PM_EVENT_INVALID ? | 368 | ret = dev->power.power_state.event != PM_EVENT_INVALID ? |
367 | dev_pm_qos_constraints_allocate(dev) : -ENODEV; | 369 | dev_pm_qos_constraints_allocate(dev) : -ENODEV; |
368 | 370 | ||
369 | if (!ret) | 371 | if (!ret) |
370 | ret = blocking_notifier_chain_register( | 372 | ret = blocking_notifier_chain_register( |
371 | dev->power.constraints->notifiers, notifier); | 373 | dev->power.qos->latency.notifiers, notifier); |
372 | 374 | ||
373 | mutex_unlock(&dev_pm_qos_mtx); | 375 | mutex_unlock(&dev_pm_qos_mtx); |
374 | return ret; | 376 | return ret; |
@@ -393,9 +395,9 @@ int dev_pm_qos_remove_notifier(struct device *dev, | |||
393 | mutex_lock(&dev_pm_qos_mtx); | 395 | mutex_lock(&dev_pm_qos_mtx); |
394 | 396 | ||
395 | /* Silently return if the constraints object is not present. */ | 397 | /* Silently return if the constraints object is not present. */ |
396 | if (dev->power.constraints) | 398 | if (dev->power.qos) |
397 | retval = blocking_notifier_chain_unregister( | 399 | retval = blocking_notifier_chain_unregister( |
398 | dev->power.constraints->notifiers, | 400 | dev->power.qos->latency.notifiers, |
399 | notifier); | 401 | notifier); |
400 | 402 | ||
401 | mutex_unlock(&dev_pm_qos_mtx); | 403 | mutex_unlock(&dev_pm_qos_mtx); |
diff --git a/include/linux/pm.h b/include/linux/pm.h index 007e687c4f69..0ce6df94221a 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h | |||
@@ -549,7 +549,7 @@ struct dev_pm_info { | |||
549 | struct dev_pm_qos_request *pq_req; | 549 | struct dev_pm_qos_request *pq_req; |
550 | #endif | 550 | #endif |
551 | struct pm_subsys_data *subsys_data; /* Owned by the subsystem. */ | 551 | struct pm_subsys_data *subsys_data; /* Owned by the subsystem. */ |
552 | struct pm_qos_constraints *constraints; | 552 | struct dev_pm_qos *qos; |
553 | }; | 553 | }; |
554 | 554 | ||
555 | extern void update_pm_runtime_accounting(struct device *dev); | 555 | extern void update_pm_runtime_accounting(struct device *dev); |
diff --git a/include/linux/pm_qos.h b/include/linux/pm_qos.h index 9924ea1f22e0..30e9ad72e797 100644 --- a/include/linux/pm_qos.h +++ b/include/linux/pm_qos.h | |||
@@ -57,6 +57,10 @@ struct pm_qos_constraints { | |||
57 | struct blocking_notifier_head *notifiers; | 57 | struct blocking_notifier_head *notifiers; |
58 | }; | 58 | }; |
59 | 59 | ||
60 | struct dev_pm_qos { | ||
61 | struct pm_qos_constraints latency; | ||
62 | }; | ||
63 | |||
60 | /* Action requested to pm_qos_update_target */ | 64 | /* Action requested to pm_qos_update_target */ |
61 | enum pm_qos_req_action { | 65 | enum pm_qos_req_action { |
62 | PM_QOS_ADD_REQ, /* Add a new request */ | 66 | PM_QOS_ADD_REQ, /* Add a new request */ |