aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2012-10-22 19:07:27 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2012-10-22 19:07:27 -0400
commit5f986c590fcf4284924fcda991cf14ab32bff49f (patch)
tree07b31910af67192423c5bc7b7e6ee1134bc221c2
parent6f0c0580b70c89094b3422ba81118c7b959c7556 (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.c42
-rw-r--r--include/linux/pm.h2
-rw-r--r--include/linux/pm_qos.h4
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 */
56s32 __dev_pm_qos_read_value(struct device *dev) 56s32 __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 */
115static int dev_pm_qos_constraints_allocate(struct device *dev) 113static 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)
151void dev_pm_qos_constraints_init(struct device *dev) 151void 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 */
165void dev_pm_qos_constraints_destroy(struct device *dev) 165void 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
555extern void update_pm_runtime_accounting(struct device *dev); 555extern 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
60struct 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 */
61enum pm_qos_req_action { 65enum pm_qos_req_action {
62 PM_QOS_ADD_REQ, /* Add a new request */ 66 PM_QOS_ADD_REQ, /* Add a new request */