Blame view

kernel/pm_qos_params.c 13.1 KB
d82b35186   Mark Gross   pm qos infrastruc...
1
2
3
4
  /*
   * This module exposes the interface to kernel space for specifying
   * QoS dependencies.  It provides infrastructure for registration of:
   *
ed77134bf   Mark Gross   PM QOS update
5
   * Dependents on a QoS value : register requests
d82b35186   Mark Gross   pm qos infrastruc...
6
7
8
9
10
11
12
13
14
15
16
   * Watchers of QoS value : get notified when target QoS value changes
   *
   * This QoS design is best effort based.  Dependents register their QoS needs.
   * Watchers register to keep track of the current QoS needs of the system.
   *
   * There are 3 basic classes of QoS parameter: latency, timeout, throughput
   * each have defined units:
   * latency: usec
   * timeout: usec <-- currently not used.
   * throughput: kbs (kilo byte / sec)
   *
ed77134bf   Mark Gross   PM QOS update
17
   * There are lists of pm_qos_objects each one wrapping requests, notifiers
d82b35186   Mark Gross   pm qos infrastruc...
18
   *
ed77134bf   Mark Gross   PM QOS update
19
   * User mode requests on a QOS parameter register themselves to the
d82b35186   Mark Gross   pm qos infrastruc...
20
21
22
   * subsystem by opening the device node /dev/... and writing there request to
   * the node.  As long as the process holds a file handle open to the node the
   * client continues to be accounted for.  Upon file release the usermode
ed77134bf   Mark Gross   PM QOS update
23
24
   * request is removed and a new qos target is computed.  This way when the
   * request that the application has is cleaned up when closes the file
d82b35186   Mark Gross   pm qos infrastruc...
25
26
   * pointer or exits the pm_qos_object will get an opportunity to clean up.
   *
bf1db69fb   Richard Hughes   pm_qos: spelling ...
27
   * Mark Gross <mgross@linux.intel.com>
d82b35186   Mark Gross   pm qos infrastruc...
28
   */
ed77134bf   Mark Gross   PM QOS update
29
  /*#define DEBUG*/
d82b35186   Mark Gross   pm qos infrastruc...
30
31
32
33
34
35
36
37
38
39
40
  #include <linux/pm_qos_params.h>
  #include <linux/sched.h>
  #include <linux/spinlock.h>
  #include <linux/slab.h>
  #include <linux/time.h>
  #include <linux/fs.h>
  #include <linux/device.h>
  #include <linux/miscdevice.h>
  #include <linux/string.h>
  #include <linux/platform_device.h>
  #include <linux/init.h>
0775a60ac   Rafael J. Wysocki   PM: Fix PM QOS's ...
41
  #include <linux/kernel.h>
d82b35186   Mark Gross   pm qos infrastruc...
42
43
44
45
  
  #include <linux/uaccess.h>
  
  /*
ed77134bf   Mark Gross   PM QOS update
46
   * locking rule: all changes to requests or notifiers lists
d82b35186   Mark Gross   pm qos infrastruc...
47
48
49
   * or pm_qos_object list and pm_qos_objects need to happen with pm_qos_lock
   * held, taken with _irqsave.  One lock to rule them all
   */
5f279845f   James Bottomley   pm_qos: Reimpleme...
50
51
52
53
  enum pm_qos_type {
  	PM_QOS_MAX,		/* return the largest value */
  	PM_QOS_MIN		/* return the smallest value */
  };
d82b35186   Mark Gross   pm qos infrastruc...
54

333c5ae99   Tim Chen   idle governor: Av...
55
56
57
58
59
  /*
   * Note: The lockless read path depends on the CPU accessing
   * target_value atomically.  Atomic access is only guaranteed on all CPU
   * types linux supports for 32 bit quantites
   */
d82b35186   Mark Gross   pm qos infrastruc...
60
  struct pm_qos_object {
5f279845f   James Bottomley   pm_qos: Reimpleme...
61
  	struct plist_head requests;
d82b35186   Mark Gross   pm qos infrastruc...
62
63
64
  	struct blocking_notifier_head *notifiers;
  	struct miscdevice pm_qos_power_miscdev;
  	char *name;
333c5ae99   Tim Chen   idle governor: Av...
65
  	s32 target_value;	/* Do not change to 64 bit */
d82b35186   Mark Gross   pm qos infrastruc...
66
  	s32 default_value;
5f279845f   James Bottomley   pm_qos: Reimpleme...
67
  	enum pm_qos_type type;
d82b35186   Mark Gross   pm qos infrastruc...
68
  };
5f279845f   James Bottomley   pm_qos: Reimpleme...
69
  static DEFINE_SPINLOCK(pm_qos_lock);
d82b35186   Mark Gross   pm qos infrastruc...
70
71
72
  static struct pm_qos_object null_pm_qos;
  static BLOCKING_NOTIFIER_HEAD(cpu_dma_lat_notifier);
  static struct pm_qos_object cpu_dma_pm_qos = {
732375c6a   Dima Zavin   plist: Remove the...
73
  	.requests = PLIST_HEAD_INIT(cpu_dma_pm_qos.requests),
d82b35186   Mark Gross   pm qos infrastruc...
74
75
  	.notifiers = &cpu_dma_lat_notifier,
  	.name = "cpu_dma_latency",
333c5ae99   Tim Chen   idle governor: Av...
76
77
  	.target_value = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE,
  	.default_value = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE,
5f279845f   James Bottomley   pm_qos: Reimpleme...
78
  	.type = PM_QOS_MIN,
d82b35186   Mark Gross   pm qos infrastruc...
79
80
81
82
  };
  
  static BLOCKING_NOTIFIER_HEAD(network_lat_notifier);
  static struct pm_qos_object network_lat_pm_qos = {
732375c6a   Dima Zavin   plist: Remove the...
83
  	.requests = PLIST_HEAD_INIT(network_lat_pm_qos.requests),
d82b35186   Mark Gross   pm qos infrastruc...
84
85
  	.notifiers = &network_lat_notifier,
  	.name = "network_latency",
333c5ae99   Tim Chen   idle governor: Av...
86
87
  	.target_value = PM_QOS_NETWORK_LAT_DEFAULT_VALUE,
  	.default_value = PM_QOS_NETWORK_LAT_DEFAULT_VALUE,
5f279845f   James Bottomley   pm_qos: Reimpleme...
88
  	.type = PM_QOS_MIN
d82b35186   Mark Gross   pm qos infrastruc...
89
90
91
92
93
  };
  
  
  static BLOCKING_NOTIFIER_HEAD(network_throughput_notifier);
  static struct pm_qos_object network_throughput_pm_qos = {
732375c6a   Dima Zavin   plist: Remove the...
94
  	.requests = PLIST_HEAD_INIT(network_throughput_pm_qos.requests),
d82b35186   Mark Gross   pm qos infrastruc...
95
96
  	.notifiers = &network_throughput_notifier,
  	.name = "network_throughput",
333c5ae99   Tim Chen   idle governor: Av...
97
98
  	.target_value = PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE,
  	.default_value = PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE,
5f279845f   James Bottomley   pm_qos: Reimpleme...
99
  	.type = PM_QOS_MAX,
d82b35186   Mark Gross   pm qos infrastruc...
100
101
102
103
104
105
106
107
108
  };
  
  
  static struct pm_qos_object *pm_qos_array[] = {
  	&null_pm_qos,
  	&cpu_dma_pm_qos,
  	&network_lat_pm_qos,
  	&network_throughput_pm_qos
  };
d82b35186   Mark Gross   pm qos infrastruc...
109
110
  static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf,
  		size_t count, loff_t *f_pos);
f9b9e806a   Thomas Renninger   PM QoS: Make pm_q...
111
112
  static ssize_t pm_qos_power_read(struct file *filp, char __user *buf,
  		size_t count, loff_t *f_pos);
d82b35186   Mark Gross   pm qos infrastruc...
113
114
115
116
117
  static int pm_qos_power_open(struct inode *inode, struct file *filp);
  static int pm_qos_power_release(struct inode *inode, struct file *filp);
  
  static const struct file_operations pm_qos_power_fops = {
  	.write = pm_qos_power_write,
f9b9e806a   Thomas Renninger   PM QoS: Make pm_q...
118
  	.read = pm_qos_power_read,
d82b35186   Mark Gross   pm qos infrastruc...
119
120
  	.open = pm_qos_power_open,
  	.release = pm_qos_power_release,
6038f373a   Arnd Bergmann   llseek: automatic...
121
  	.llseek = noop_llseek,
d82b35186   Mark Gross   pm qos infrastruc...
122
  };
5f279845f   James Bottomley   pm_qos: Reimpleme...
123
124
  /* unlocked internal variant */
  static inline int pm_qos_get_value(struct pm_qos_object *o)
d82b35186   Mark Gross   pm qos infrastruc...
125
  {
5f279845f   James Bottomley   pm_qos: Reimpleme...
126
127
  	if (plist_head_empty(&o->requests))
  		return o->default_value;
d82b35186   Mark Gross   pm qos infrastruc...
128

5f279845f   James Bottomley   pm_qos: Reimpleme...
129
130
  	switch (o->type) {
  	case PM_QOS_MIN:
00fafcda1   Colin Cross   PM / PM QoS: Fix ...
131
  		return plist_first(&o->requests)->prio;
d82b35186   Mark Gross   pm qos infrastruc...
132

5f279845f   James Bottomley   pm_qos: Reimpleme...
133
  	case PM_QOS_MAX:
00fafcda1   Colin Cross   PM / PM QoS: Fix ...
134
  		return plist_last(&o->requests)->prio;
d82b35186   Mark Gross   pm qos infrastruc...
135

5f279845f   James Bottomley   pm_qos: Reimpleme...
136
137
138
139
140
  	default:
  		/* runtime check for not using enum */
  		BUG();
  	}
  }
333c5ae99   Tim Chen   idle governor: Av...
141
142
143
144
145
146
147
148
149
  static inline s32 pm_qos_read_value(struct pm_qos_object *o)
  {
  	return o->target_value;
  }
  
  static inline void pm_qos_set_value(struct pm_qos_object *o, s32 value)
  {
  	o->target_value = value;
  }
5f279845f   James Bottomley   pm_qos: Reimpleme...
150
151
  static void update_target(struct pm_qos_object *o, struct plist_node *node,
  			  int del, int value)
d82b35186   Mark Gross   pm qos infrastruc...
152
  {
d82b35186   Mark Gross   pm qos infrastruc...
153
  	unsigned long flags;
5f279845f   James Bottomley   pm_qos: Reimpleme...
154
  	int prev_value, curr_value;
d82b35186   Mark Gross   pm qos infrastruc...
155
156
  
  	spin_lock_irqsave(&pm_qos_lock, flags);
5f279845f   James Bottomley   pm_qos: Reimpleme...
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
  	prev_value = pm_qos_get_value(o);
  	/* PM_QOS_DEFAULT_VALUE is a signal that the value is unchanged */
  	if (value != PM_QOS_DEFAULT_VALUE) {
  		/*
  		 * to change the list, we atomically remove, reinit
  		 * with new value and add, then see if the extremal
  		 * changed
  		 */
  		plist_del(node, &o->requests);
  		plist_node_init(node, value);
  		plist_add(node, &o->requests);
  	} else if (del) {
  		plist_del(node, &o->requests);
  	} else {
  		plist_add(node, &o->requests);
d82b35186   Mark Gross   pm qos infrastruc...
172
  	}
5f279845f   James Bottomley   pm_qos: Reimpleme...
173
  	curr_value = pm_qos_get_value(o);
333c5ae99   Tim Chen   idle governor: Av...
174
  	pm_qos_set_value(o, curr_value);
d82b35186   Mark Gross   pm qos infrastruc...
175
  	spin_unlock_irqrestore(&pm_qos_lock, flags);
5f279845f   James Bottomley   pm_qos: Reimpleme...
176
177
178
179
  	if (prev_value != curr_value)
  		blocking_notifier_call_chain(o->notifiers,
  					     (unsigned long)curr_value,
  					     NULL);
d82b35186   Mark Gross   pm qos infrastruc...
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
  }
  
  static int register_pm_qos_misc(struct pm_qos_object *qos)
  {
  	qos->pm_qos_power_miscdev.minor = MISC_DYNAMIC_MINOR;
  	qos->pm_qos_power_miscdev.name = qos->name;
  	qos->pm_qos_power_miscdev.fops = &pm_qos_power_fops;
  
  	return misc_register(&qos->pm_qos_power_miscdev);
  }
  
  static int find_pm_qos_object_by_minor(int minor)
  {
  	int pm_qos_class;
  
  	for (pm_qos_class = 0;
  		pm_qos_class < PM_QOS_NUM_CLASSES; pm_qos_class++) {
  		if (minor ==
  			pm_qos_array[pm_qos_class]->pm_qos_power_miscdev.minor)
  			return pm_qos_class;
  	}
  	return -1;
  }
  
  /**
ed77134bf   Mark Gross   PM QOS update
205
   * pm_qos_request - returns current system wide qos expectation
d82b35186   Mark Gross   pm qos infrastruc...
206
207
   * @pm_qos_class: identification of which qos value is requested
   *
333c5ae99   Tim Chen   idle governor: Av...
208
   * This function returns the current target value.
d82b35186   Mark Gross   pm qos infrastruc...
209
   */
ed77134bf   Mark Gross   PM QOS update
210
  int pm_qos_request(int pm_qos_class)
d82b35186   Mark Gross   pm qos infrastruc...
211
  {
333c5ae99   Tim Chen   idle governor: Av...
212
  	return pm_qos_read_value(pm_qos_array[pm_qos_class]);
d82b35186   Mark Gross   pm qos infrastruc...
213
  }
ed77134bf   Mark Gross   PM QOS update
214
  EXPORT_SYMBOL_GPL(pm_qos_request);
d82b35186   Mark Gross   pm qos infrastruc...
215

82f682514   James Bottomley   pm_qos: Get rid o...
216
217
218
219
220
  int pm_qos_request_active(struct pm_qos_request_list *req)
  {
  	return req->pm_qos_class != 0;
  }
  EXPORT_SYMBOL_GPL(pm_qos_request_active);
d82b35186   Mark Gross   pm qos infrastruc...
221
  /**
ed77134bf   Mark Gross   PM QOS update
222
   * pm_qos_add_request - inserts new qos request into the list
25cc69ec3   Saravana Kannan   PM QoS: Fix inlin...
223
224
   * @dep: pointer to a preallocated handle
   * @pm_qos_class: identifies which list of qos request to use
d82b35186   Mark Gross   pm qos infrastruc...
225
226
227
   * @value: defines the qos request
   *
   * This function inserts a new entry in the pm_qos_class list of requested qos
bf1db69fb   Richard Hughes   pm_qos: spelling ...
228
   * performance characteristics.  It recomputes the aggregate QoS expectations
25cc69ec3   Saravana Kannan   PM QoS: Fix inlin...
229
230
231
   * for the pm_qos_class of parameters and initializes the pm_qos_request_list
   * handle.  Caller needs to save this handle for later use in updates and
   * removal.
d82b35186   Mark Gross   pm qos infrastruc...
232
   */
25cc69ec3   Saravana Kannan   PM QoS: Fix inlin...
233

82f682514   James Bottomley   pm_qos: Get rid o...
234
235
  void pm_qos_add_request(struct pm_qos_request_list *dep,
  			int pm_qos_class, s32 value)
d82b35186   Mark Gross   pm qos infrastruc...
236
  {
82f682514   James Bottomley   pm_qos: Get rid o...
237
238
  	struct pm_qos_object *o =  pm_qos_array[pm_qos_class];
  	int new_value;
d82b35186   Mark Gross   pm qos infrastruc...
239

82f682514   James Bottomley   pm_qos: Get rid o...
240
241
242
243
244
245
246
247
248
249
250
251
  	if (pm_qos_request_active(dep)) {
  		WARN(1, KERN_ERR "pm_qos_add_request() called for already added request
  ");
  		return;
  	}
  	if (value == PM_QOS_DEFAULT_VALUE)
  		new_value = o->default_value;
  	else
  		new_value = value;
  	plist_node_init(&dep->list, new_value);
  	dep->pm_qos_class = pm_qos_class;
  	update_target(o, &dep->list, 0, PM_QOS_DEFAULT_VALUE);
d82b35186   Mark Gross   pm qos infrastruc...
252
  }
ed77134bf   Mark Gross   PM QOS update
253
  EXPORT_SYMBOL_GPL(pm_qos_add_request);
d82b35186   Mark Gross   pm qos infrastruc...
254
255
  
  /**
ed77134bf   Mark Gross   PM QOS update
256
257
   * pm_qos_update_request - modifies an existing qos request
   * @pm_qos_req : handle to list element holding a pm_qos request to use
d82b35186   Mark Gross   pm qos infrastruc...
258
259
   * @value: defines the qos request
   *
ed77134bf   Mark Gross   PM QOS update
260
   * Updates an existing qos request for the pm_qos_class of parameters along
d82b35186   Mark Gross   pm qos infrastruc...
261
262
   * with updating the target pm_qos_class value.
   *
ed77134bf   Mark Gross   PM QOS update
263
   * Attempts are made to make this code callable on hot code paths.
d82b35186   Mark Gross   pm qos infrastruc...
264
   */
ed77134bf   Mark Gross   PM QOS update
265
  void pm_qos_update_request(struct pm_qos_request_list *pm_qos_req,
5f279845f   James Bottomley   pm_qos: Reimpleme...
266
  			   s32 new_value)
d82b35186   Mark Gross   pm qos infrastruc...
267
  {
ed77134bf   Mark Gross   PM QOS update
268
  	s32 temp;
5f279845f   James Bottomley   pm_qos: Reimpleme...
269
  	struct pm_qos_object *o;
d82b35186   Mark Gross   pm qos infrastruc...
270

5f279845f   James Bottomley   pm_qos: Reimpleme...
271
272
  	if (!pm_qos_req) /*guard against callers passing in null */
  		return;
82f682514   James Bottomley   pm_qos: Get rid o...
273
274
275
276
277
  	if (!pm_qos_request_active(pm_qos_req)) {
  		WARN(1, KERN_ERR "pm_qos_update_request() called for unknown object
  ");
  		return;
  	}
5f279845f   James Bottomley   pm_qos: Reimpleme...
278
279
280
281
282
283
284
285
286
  	o = pm_qos_array[pm_qos_req->pm_qos_class];
  
  	if (new_value == PM_QOS_DEFAULT_VALUE)
  		temp = o->default_value;
  	else
  		temp = new_value;
  
  	if (temp != pm_qos_req->list.prio)
  		update_target(o, &pm_qos_req->list, 0, temp);
d82b35186   Mark Gross   pm qos infrastruc...
287
  }
ed77134bf   Mark Gross   PM QOS update
288
  EXPORT_SYMBOL_GPL(pm_qos_update_request);
d82b35186   Mark Gross   pm qos infrastruc...
289
290
  
  /**
ed77134bf   Mark Gross   PM QOS update
291
292
   * pm_qos_remove_request - modifies an existing qos request
   * @pm_qos_req: handle to request list element
d82b35186   Mark Gross   pm qos infrastruc...
293
   *
ed77134bf   Mark Gross   PM QOS update
294
295
296
   * Will remove pm qos request from the list of requests and
   * recompute the current target value for the pm_qos_class.  Call this
   * on slow code paths.
d82b35186   Mark Gross   pm qos infrastruc...
297
   */
ed77134bf   Mark Gross   PM QOS update
298
  void pm_qos_remove_request(struct pm_qos_request_list *pm_qos_req)
d82b35186   Mark Gross   pm qos infrastruc...
299
  {
5f279845f   James Bottomley   pm_qos: Reimpleme...
300
  	struct pm_qos_object *o;
ed77134bf   Mark Gross   PM QOS update
301
302
303
304
  
  	if (pm_qos_req == NULL)
  		return;
  		/* silent return to keep pcm code cleaner */
d82b35186   Mark Gross   pm qos infrastruc...
305

82f682514   James Bottomley   pm_qos: Get rid o...
306
307
308
309
310
  	if (!pm_qos_request_active(pm_qos_req)) {
  		WARN(1, KERN_ERR "pm_qos_remove_request() called for unknown object
  ");
  		return;
  	}
5f279845f   James Bottomley   pm_qos: Reimpleme...
311
312
  	o = pm_qos_array[pm_qos_req->pm_qos_class];
  	update_target(o, &pm_qos_req->list, 1, PM_QOS_DEFAULT_VALUE);
82f682514   James Bottomley   pm_qos: Get rid o...
313
  	memset(pm_qos_req, 0, sizeof(*pm_qos_req));
d82b35186   Mark Gross   pm qos infrastruc...
314
  }
ed77134bf   Mark Gross   PM QOS update
315
  EXPORT_SYMBOL_GPL(pm_qos_remove_request);
d82b35186   Mark Gross   pm qos infrastruc...
316
317
318
319
320
321
322
  
  /**
   * pm_qos_add_notifier - sets notification entry for changes to target value
   * @pm_qos_class: identifies which qos target changes should be notified.
   * @notifier: notifier block managed by caller.
   *
   * will register the notifier into a notification chain that gets called
bf1db69fb   Richard Hughes   pm_qos: spelling ...
323
   * upon changes to the pm_qos_class target value.
d82b35186   Mark Gross   pm qos infrastruc...
324
   */
ed77134bf   Mark Gross   PM QOS update
325
  int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier)
d82b35186   Mark Gross   pm qos infrastruc...
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
  {
  	int retval;
  
  	retval = blocking_notifier_chain_register(
  			pm_qos_array[pm_qos_class]->notifiers, notifier);
  
  	return retval;
  }
  EXPORT_SYMBOL_GPL(pm_qos_add_notifier);
  
  /**
   * pm_qos_remove_notifier - deletes notification entry from chain.
   * @pm_qos_class: identifies which qos target changes are notified.
   * @notifier: notifier block to be removed.
   *
   * will remove the notifier from the notification chain that gets called
bf1db69fb   Richard Hughes   pm_qos: spelling ...
342
   * upon changes to the pm_qos_class target value.
d82b35186   Mark Gross   pm qos infrastruc...
343
344
345
346
347
348
349
350
351
352
353
   */
  int pm_qos_remove_notifier(int pm_qos_class, struct notifier_block *notifier)
  {
  	int retval;
  
  	retval = blocking_notifier_chain_unregister(
  			pm_qos_array[pm_qos_class]->notifiers, notifier);
  
  	return retval;
  }
  EXPORT_SYMBOL_GPL(pm_qos_remove_notifier);
d82b35186   Mark Gross   pm qos infrastruc...
354
355
  static int pm_qos_power_open(struct inode *inode, struct file *filp)
  {
d82b35186   Mark Gross   pm qos infrastruc...
356
357
358
359
  	long pm_qos_class;
  
  	pm_qos_class = find_pm_qos_object_by_minor(iminor(inode));
  	if (pm_qos_class >= 0) {
bac1e74db   David Alan Gilbert   PM QoS: Fix kzall...
360
                 struct pm_qos_request_list *req = kzalloc(sizeof(*req), GFP_KERNEL);
82f682514   James Bottomley   pm_qos: Get rid o...
361
362
363
364
365
  		if (!req)
  			return -ENOMEM;
  
  		pm_qos_add_request(req, pm_qos_class, PM_QOS_DEFAULT_VALUE);
  		filp->private_data = req;
ed77134bf   Mark Gross   PM QOS update
366
367
  
  		if (filp->private_data)
d82b35186   Mark Gross   pm qos infrastruc...
368
369
  			return 0;
  	}
d82b35186   Mark Gross   pm qos infrastruc...
370
371
372
373
374
  	return -EPERM;
  }
  
  static int pm_qos_power_release(struct inode *inode, struct file *filp)
  {
ed77134bf   Mark Gross   PM QOS update
375
  	struct pm_qos_request_list *req;
d82b35186   Mark Gross   pm qos infrastruc...
376

82f682514   James Bottomley   pm_qos: Get rid o...
377
  	req = filp->private_data;
ed77134bf   Mark Gross   PM QOS update
378
  	pm_qos_remove_request(req);
82f682514   James Bottomley   pm_qos: Get rid o...
379
  	kfree(req);
d82b35186   Mark Gross   pm qos infrastruc...
380
381
382
  
  	return 0;
  }
ed77134bf   Mark Gross   PM QOS update
383

f9b9e806a   Thomas Renninger   PM QoS: Make pm_q...
384
385
386
387
388
389
  static ssize_t pm_qos_power_read(struct file *filp, char __user *buf,
  		size_t count, loff_t *f_pos)
  {
  	s32 value;
  	unsigned long flags;
  	struct pm_qos_object *o;
6eab04a87   Justin P. Mattock   treewide: remove ...
390
  	struct pm_qos_request_list *pm_qos_req = filp->private_data;
f9b9e806a   Thomas Renninger   PM QoS: Make pm_q...
391
392
393
394
395
396
397
398
399
400
401
402
403
  
  	if (!pm_qos_req)
  		return -EINVAL;
  	if (!pm_qos_request_active(pm_qos_req))
  		return -EINVAL;
  
  	o = pm_qos_array[pm_qos_req->pm_qos_class];
  	spin_lock_irqsave(&pm_qos_lock, flags);
  	value = pm_qos_get_value(o);
  	spin_unlock_irqrestore(&pm_qos_lock, flags);
  
  	return simple_read_from_buffer(buf, count, f_pos, &value, sizeof(s32));
  }
d82b35186   Mark Gross   pm qos infrastruc...
404
405
406
407
  static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf,
  		size_t count, loff_t *f_pos)
  {
  	s32 value;
ed77134bf   Mark Gross   PM QOS update
408
409
410
411
412
  	struct pm_qos_request_list *pm_qos_req;
  
  	if (count == sizeof(s32)) {
  		if (copy_from_user(&value, buf, sizeof(s32)))
  			return -EFAULT;
0775a60ac   Rafael J. Wysocki   PM: Fix PM QOS's ...
413
414
415
416
417
418
  	} else if (count <= 11) { /* ASCII perhaps? */
  		char ascii_value[11];
  		unsigned long int ulval;
  		int ret;
  
  		if (copy_from_user(ascii_value, buf, count))
ed77134bf   Mark Gross   PM QOS update
419
  			return -EFAULT;
0775a60ac   Rafael J. Wysocki   PM: Fix PM QOS's ...
420
421
422
423
424
425
426
427
428
429
430
431
432
433
  
  		if (count > 10) {
  			if (ascii_value[10] == '
  ')
  				ascii_value[10] = '\0';
  			else
  				return -EINVAL;
  		} else {
  			ascii_value[count] = '\0';
  		}
  		ret = strict_strtoul(ascii_value, 16, &ulval);
  		if (ret) {
  			pr_debug("%s, 0x%lx, 0x%x
  ", ascii_value, ulval, ret);
ed77134bf   Mark Gross   PM QOS update
434
  			return -EINVAL;
0775a60ac   Rafael J. Wysocki   PM: Fix PM QOS's ...
435
436
437
  		}
  		value = (s32)lower_32_bits(ulval);
  	} else {
d82b35186   Mark Gross   pm qos infrastruc...
438
  		return -EINVAL;
0775a60ac   Rafael J. Wysocki   PM: Fix PM QOS's ...
439
  	}
d82b35186   Mark Gross   pm qos infrastruc...
440

99a51792d   Joe Perches   kernel/pm_qos_par...
441
  	pm_qos_req = filp->private_data;
ed77134bf   Mark Gross   PM QOS update
442
443
444
  	pm_qos_update_request(pm_qos_req, value);
  
  	return count;
d82b35186   Mark Gross   pm qos infrastruc...
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
  }
  
  
  static int __init pm_qos_power_init(void)
  {
  	int ret = 0;
  
  	ret = register_pm_qos_misc(&cpu_dma_pm_qos);
  	if (ret < 0) {
  		printk(KERN_ERR "pm_qos_param: cpu_dma_latency setup failed
  ");
  		return ret;
  	}
  	ret = register_pm_qos_misc(&network_lat_pm_qos);
  	if (ret < 0) {
  		printk(KERN_ERR "pm_qos_param: network_latency setup failed
  ");
  		return ret;
  	}
  	ret = register_pm_qos_misc(&network_throughput_pm_qos);
  	if (ret < 0)
  		printk(KERN_ERR
  			"pm_qos_param: network_throughput setup failed
  ");
  
  	return ret;
  }
  
  late_initcall(pm_qos_power_init);