[ACPI] Fix "ec_burst=1" mode latency issue
[sfrench/cifs-2.6.git] / drivers / acpi / processor_perflib.c
1 /*
2  * processor_perflib.c - ACPI Processor P-States Library ($Revision: 71 $)
3  *
4  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6  *  Copyright (C) 2004       Dominik Brodowski <linux@brodo.de>
7  *  Copyright (C) 2004  Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
8  *                      - Added processor hotplug support
9  *
10  *
11  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12  *
13  *  This program is free software; you can redistribute it and/or modify
14  *  it under the terms of the GNU General Public License as published by
15  *  the Free Software Foundation; either version 2 of the License, or (at
16  *  your option) any later version.
17  *
18  *  This program is distributed in the hope that it will be useful, but
19  *  WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21  *  General Public License for more details.
22  *
23  *  You should have received a copy of the GNU General Public License along
24  *  with this program; if not, write to the Free Software Foundation, Inc.,
25  *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26  *
27  */
28
29
30 #include <linux/kernel.h>
31 #include <linux/module.h>
32 #include <linux/init.h>
33 #include <linux/cpufreq.h>
34
35 #ifdef CONFIG_X86_ACPI_CPUFREQ_PROC_INTF
36 #include <linux/proc_fs.h>
37 #include <linux/seq_file.h>
38
39 #include <asm/uaccess.h>
40 #endif
41
42 #include <acpi/acpi_bus.h>
43 #include <acpi/processor.h>
44
45
46 #define ACPI_PROCESSOR_COMPONENT        0x01000000
47 #define ACPI_PROCESSOR_CLASS            "processor"
48 #define ACPI_PROCESSOR_DRIVER_NAME      "ACPI Processor Driver"
49 #define ACPI_PROCESSOR_FILE_PERFORMANCE "performance"
50 #define _COMPONENT              ACPI_PROCESSOR_COMPONENT
51 ACPI_MODULE_NAME                ("acpi_processor")
52
53
54 static DECLARE_MUTEX(performance_sem);
55
56 /*
57  * _PPC support is implemented as a CPUfreq policy notifier:
58  * This means each time a CPUfreq driver registered also with
59  * the ACPI core is asked to change the speed policy, the maximum
60  * value is adjusted so that it is within the platform limit.
61  *
62  * Also, when a new platform limit value is detected, the CPUfreq
63  * policy is adjusted accordingly.
64  */
65
66 #define PPC_REGISTERED   1
67 #define PPC_IN_USE       2
68
69 static int acpi_processor_ppc_status = 0;
70
71 static int acpi_processor_ppc_notifier(struct notifier_block *nb,
72         unsigned long event,
73         void *data)
74 {
75         struct cpufreq_policy *policy = data;
76         struct acpi_processor *pr;
77         unsigned int ppc = 0;
78
79         down(&performance_sem);
80
81         if (event != CPUFREQ_INCOMPATIBLE)
82                 goto out;
83
84         pr = processors[policy->cpu];
85         if (!pr || !pr->performance)
86                 goto out;
87
88         ppc = (unsigned int) pr->performance_platform_limit;
89         if (!ppc)
90                 goto out;
91
92         if (ppc > pr->performance->state_count)
93                 goto out;
94
95         cpufreq_verify_within_limits(policy, 0,
96                 pr->performance->states[ppc].core_frequency * 1000);
97
98  out:
99         up(&performance_sem);
100
101         return 0;
102 }
103
104
105 static struct notifier_block acpi_ppc_notifier_block = {
106         .notifier_call = acpi_processor_ppc_notifier,
107 };
108
109
110 static int
111 acpi_processor_get_platform_limit (
112         struct acpi_processor*  pr)
113 {
114         acpi_status             status = 0;
115         unsigned long           ppc = 0;
116
117         ACPI_FUNCTION_TRACE("acpi_processor_get_platform_limit");
118
119         if (!pr)
120                 return_VALUE(-EINVAL);
121
122         /*
123          * _PPC indicates the maximum state currently supported by the platform
124          * (e.g. 0 = states 0..n; 1 = states 1..n; etc.
125          */
126         status = acpi_evaluate_integer(pr->handle, "_PPC", NULL, &ppc);
127
128         if (status != AE_NOT_FOUND)
129                 acpi_processor_ppc_status |= PPC_IN_USE;
130
131         if(ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
132                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PPC\n"));
133                 return_VALUE(-ENODEV);
134         }
135
136         pr->performance_platform_limit = (int) ppc;
137
138         return_VALUE(0);
139 }
140
141
142 int acpi_processor_ppc_has_changed(
143         struct acpi_processor *pr)
144 {
145         int ret = acpi_processor_get_platform_limit(pr);
146         if (ret < 0)
147                 return (ret);
148         else
149                 return cpufreq_update_policy(pr->id);
150 }
151
152
153 void acpi_processor_ppc_init(void) {
154         if (!cpufreq_register_notifier(&acpi_ppc_notifier_block, CPUFREQ_POLICY_NOTIFIER))
155                 acpi_processor_ppc_status |= PPC_REGISTERED;
156         else
157                 printk(KERN_DEBUG "Warning: Processor Platform Limit not supported.\n");
158 }
159
160
161 void acpi_processor_ppc_exit(void) {
162         if (acpi_processor_ppc_status & PPC_REGISTERED)
163                 cpufreq_unregister_notifier(&acpi_ppc_notifier_block, CPUFREQ_POLICY_NOTIFIER);
164
165         acpi_processor_ppc_status &= ~PPC_REGISTERED;
166 }
167
168
169 static int
170 acpi_processor_get_performance_control (
171         struct acpi_processor *pr)
172 {
173         int                     result = 0;
174         acpi_status             status = 0;
175         struct acpi_buffer      buffer = {ACPI_ALLOCATE_BUFFER, NULL};
176         union acpi_object       *pct = NULL;
177         union acpi_object       obj = {0};
178
179         ACPI_FUNCTION_TRACE("acpi_processor_get_performance_control");
180
181         status = acpi_evaluate_object(pr->handle, "_PCT", NULL, &buffer);
182         if(ACPI_FAILURE(status)) {
183                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PCT\n"));
184                 return_VALUE(-ENODEV);
185         }
186
187         pct = (union acpi_object *) buffer.pointer;
188         if (!pct || (pct->type != ACPI_TYPE_PACKAGE)
189                 || (pct->package.count != 2)) {
190                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PCT data\n"));
191                 result = -EFAULT;
192                 goto end;
193         }
194
195         /*
196          * control_register
197          */
198
199         obj = pct->package.elements[0];
200
201         if ((obj.type != ACPI_TYPE_BUFFER)
202                 || (obj.buffer.length < sizeof(struct acpi_pct_register))
203                 || (obj.buffer.pointer == NULL)) {
204                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
205                         "Invalid _PCT data (control_register)\n"));
206                 result = -EFAULT;
207                 goto end;
208         }
209         memcpy(&pr->performance->control_register, obj.buffer.pointer, sizeof(struct acpi_pct_register));
210
211
212         /*
213          * status_register
214          */
215
216         obj = pct->package.elements[1];
217
218         if ((obj.type != ACPI_TYPE_BUFFER)
219                 || (obj.buffer.length < sizeof(struct acpi_pct_register))
220                 || (obj.buffer.pointer == NULL)) {
221                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
222                         "Invalid _PCT data (status_register)\n"));
223                 result = -EFAULT;
224                 goto end;
225         }
226
227         memcpy(&pr->performance->status_register, obj.buffer.pointer, sizeof(struct acpi_pct_register));
228
229 end:
230         acpi_os_free(buffer.pointer);
231
232         return_VALUE(result);
233 }
234
235
236 static int
237 acpi_processor_get_performance_states (
238         struct acpi_processor   *pr)
239 {
240         int                     result = 0;
241         acpi_status             status = AE_OK;
242         struct acpi_buffer      buffer = {ACPI_ALLOCATE_BUFFER, NULL};
243         struct acpi_buffer      format = {sizeof("NNNNNN"), "NNNNNN"};
244         struct acpi_buffer      state = {0, NULL};
245         union acpi_object       *pss = NULL;
246         int                     i;
247
248         ACPI_FUNCTION_TRACE("acpi_processor_get_performance_states");
249
250         status = acpi_evaluate_object(pr->handle, "_PSS", NULL, &buffer);
251         if(ACPI_FAILURE(status)) {
252                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PSS\n"));
253                 return_VALUE(-ENODEV);
254         }
255
256         pss = (union acpi_object *) buffer.pointer;
257         if (!pss || (pss->type != ACPI_TYPE_PACKAGE)) {
258                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSS data\n"));
259                 result = -EFAULT;
260                 goto end;
261         }
262
263         ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d performance states\n",
264                 pss->package.count));
265
266         pr->performance->state_count = pss->package.count;
267         pr->performance->states = kmalloc(sizeof(struct acpi_processor_px) * pss->package.count, GFP_KERNEL);
268         if (!pr->performance->states) {
269                 result = -ENOMEM;
270                 goto end;
271         }
272
273         for (i = 0; i < pr->performance->state_count; i++) {
274
275                 struct acpi_processor_px *px = &(pr->performance->states[i]);
276
277                 state.length = sizeof(struct acpi_processor_px);
278                 state.pointer = px;
279
280                 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Extracting state %d\n", i));
281
282                 status = acpi_extract_package(&(pss->package.elements[i]),
283                         &format, &state);
284                 if (ACPI_FAILURE(status)) {
285                         ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSS data\n"));
286                         result = -EFAULT;
287                         kfree(pr->performance->states);
288                         goto end;
289                 }
290
291                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
292                         "State [%d]: core_frequency[%d] power[%d] transition_latency[%d] bus_master_latency[%d] control[0x%x] status[0x%x]\n",
293                         i,
294                         (u32) px->core_frequency,
295                         (u32) px->power,
296                         (u32) px->transition_latency,
297                         (u32) px->bus_master_latency,
298                         (u32) px->control,
299                         (u32) px->status));
300
301                 if (!px->core_frequency) {
302                         ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSS data: freq is zero\n"));
303                         result = -EFAULT;
304                         kfree(pr->performance->states);
305                         goto end;
306                 }
307         }
308
309 end:
310         acpi_os_free(buffer.pointer);
311
312         return_VALUE(result);
313 }
314
315
316 static int
317 acpi_processor_get_performance_info (
318         struct acpi_processor   *pr)
319 {
320         int                     result = 0;
321         acpi_status             status = AE_OK;
322         acpi_handle             handle = NULL;
323
324         ACPI_FUNCTION_TRACE("acpi_processor_get_performance_info");
325
326         if (!pr || !pr->performance || !pr->handle)
327                 return_VALUE(-EINVAL);
328
329         acpi_processor_set_pdc(pr, pr->performance->pdc);
330
331         status = acpi_get_handle(pr->handle, "_PCT", &handle);
332         if (ACPI_FAILURE(status)) {
333                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
334                         "ACPI-based processor performance control unavailable\n"));
335                 return_VALUE(-ENODEV);
336         }
337
338         result = acpi_processor_get_performance_control(pr);
339         if (result)
340                 return_VALUE(result);
341
342         result = acpi_processor_get_performance_states(pr);
343         if (result)
344                 return_VALUE(result);
345
346         result = acpi_processor_get_platform_limit(pr);
347         if (result)
348                 return_VALUE(result);
349
350         return_VALUE(0);
351 }
352
353
354 int acpi_processor_notify_smm(struct module *calling_module) {
355         acpi_status             status;
356         static int              is_done = 0;
357
358         ACPI_FUNCTION_TRACE("acpi_processor_notify_smm");
359
360         if (!(acpi_processor_ppc_status & PPC_REGISTERED))
361                 return_VALUE(-EBUSY);
362
363         if (!try_module_get(calling_module))
364                 return_VALUE(-EINVAL);
365
366         /* is_done is set to negative if an error occured,
367          * and to postitive if _no_ error occured, but SMM
368          * was already notified. This avoids double notification
369          * which might lead to unexpected results...
370          */
371         if (is_done > 0) {
372                 module_put(calling_module);
373                 return_VALUE(0);
374         }
375         else if (is_done < 0) {
376                 module_put(calling_module);
377                 return_VALUE(is_done);
378         }
379
380         is_done = -EIO;
381
382         /* Can't write pstate_cnt to smi_cmd if either value is zero */
383         if ((!acpi_fadt.smi_cmd) ||
384             (!acpi_fadt.pstate_cnt)) {
385                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
386                         "No SMI port or pstate_cnt\n"));
387                 module_put(calling_module);
388                 return_VALUE(0);
389         }
390
391         ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Writing pstate_cnt [0x%x] to smi_cmd [0x%x]\n", acpi_fadt.pstate_cnt, acpi_fadt.smi_cmd));
392
393         /* FADT v1 doesn't support pstate_cnt, many BIOS vendors use
394          * it anyway, so we need to support it... */
395         if (acpi_fadt_is_v1) {
396                 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Using v1.0 FADT reserved value for pstate_cnt\n"));
397         }
398
399         status = acpi_os_write_port (acpi_fadt.smi_cmd,
400                                      (u32) acpi_fadt.pstate_cnt, 8);
401         if (ACPI_FAILURE (status)) {
402                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
403                                   "Failed to write pstate_cnt [0x%x] to "
404                                   "smi_cmd [0x%x]\n", acpi_fadt.pstate_cnt, acpi_fadt.smi_cmd));
405                 module_put(calling_module);
406                 return_VALUE(status);
407         }
408
409         /* Success. If there's no _PPC, we need to fear nothing, so
410          * we can allow the cpufreq driver to be rmmod'ed. */
411         is_done = 1;
412
413         if (!(acpi_processor_ppc_status & PPC_IN_USE))
414                 module_put(calling_module);
415
416         return_VALUE(0);
417 }
418 EXPORT_SYMBOL(acpi_processor_notify_smm);
419
420
421 #ifdef CONFIG_X86_ACPI_CPUFREQ_PROC_INTF
422 /* /proc/acpi/processor/../performance interface (DEPRECATED) */
423
424 static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file);
425 static struct file_operations acpi_processor_perf_fops = {
426         .open           = acpi_processor_perf_open_fs,
427         .read           = seq_read,
428         .llseek         = seq_lseek,
429         .release        = single_release,
430 };
431
432 static int acpi_processor_perf_seq_show(struct seq_file *seq, void *offset)
433 {
434         struct acpi_processor   *pr = (struct acpi_processor *)seq->private;
435         int                     i;
436
437         ACPI_FUNCTION_TRACE("acpi_processor_perf_seq_show");
438
439         if (!pr)
440                 goto end;
441
442         if (!pr->performance) {
443                 seq_puts(seq, "<not supported>\n");
444                 goto end;
445         }
446
447         seq_printf(seq, "state count:             %d\n"
448                         "active state:            P%d\n",
449                         pr->performance->state_count,
450                         pr->performance->state);
451
452         seq_puts(seq, "states:\n");
453         for (i = 0; i < pr->performance->state_count; i++)
454                 seq_printf(seq, "   %cP%d:                  %d MHz, %d mW, %d uS\n",
455                         (i == pr->performance->state?'*':' '), i,
456                         (u32) pr->performance->states[i].core_frequency,
457                         (u32) pr->performance->states[i].power,
458                         (u32) pr->performance->states[i].transition_latency);
459
460 end:
461         return_VALUE(0);
462 }
463
464 static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file)
465 {
466         return single_open(file, acpi_processor_perf_seq_show,
467                                                 PDE(inode)->data);
468 }
469
470 static ssize_t
471 acpi_processor_write_performance (
472         struct file             *file,
473         const char              __user *buffer,
474         size_t                  count,
475         loff_t                  *data)
476 {
477         int                     result = 0;
478         struct seq_file         *m = (struct seq_file *) file->private_data;
479         struct acpi_processor   *pr = (struct acpi_processor *) m->private;
480         struct acpi_processor_performance *perf;
481         char                    state_string[12] = {'\0'};
482         unsigned int            new_state = 0;
483         struct cpufreq_policy   policy;
484
485         ACPI_FUNCTION_TRACE("acpi_processor_write_performance");
486
487         if (!pr || (count > sizeof(state_string) - 1))
488                 return_VALUE(-EINVAL);
489
490         perf = pr->performance;
491         if (!perf)
492                 return_VALUE(-EINVAL);
493
494         if (copy_from_user(state_string, buffer, count))
495                 return_VALUE(-EFAULT);
496
497         state_string[count] = '\0';
498         new_state = simple_strtoul(state_string, NULL, 0);
499
500         if (new_state >= perf->state_count)
501                 return_VALUE(-EINVAL);
502
503         cpufreq_get_policy(&policy, pr->id);
504
505         policy.cpu = pr->id;
506         policy.min = perf->states[new_state].core_frequency * 1000;
507         policy.max = perf->states[new_state].core_frequency * 1000;
508
509         result = cpufreq_set_policy(&policy);
510         if (result)
511                 return_VALUE(result);
512
513         return_VALUE(count);
514 }
515
516 static void
517 acpi_cpufreq_add_file (
518         struct acpi_processor *pr)
519 {
520         struct proc_dir_entry   *entry = NULL;
521         struct acpi_device      *device = NULL;
522
523         ACPI_FUNCTION_TRACE("acpi_cpufreq_addfile");
524
525         if (acpi_bus_get_device(pr->handle, &device))
526                 return_VOID;
527
528         /* add file 'performance' [R/W] */
529         entry = create_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE,
530                   S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
531         if (!entry)
532                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
533                         "Unable to create '%s' fs entry\n",
534                         ACPI_PROCESSOR_FILE_PERFORMANCE));
535         else {
536                 entry->proc_fops = &acpi_processor_perf_fops;
537                 entry->proc_fops->write = acpi_processor_write_performance;
538                 entry->data = acpi_driver_data(device);
539                 entry->owner = THIS_MODULE;
540         }
541         return_VOID;
542 }
543
544 static void
545 acpi_cpufreq_remove_file (
546         struct acpi_processor *pr)
547 {
548         struct acpi_device      *device = NULL;
549
550         ACPI_FUNCTION_TRACE("acpi_cpufreq_addfile");
551
552         if (acpi_bus_get_device(pr->handle, &device))
553                 return_VOID;
554
555         /* remove file 'performance' */
556         remove_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE,
557                   acpi_device_dir(device));
558
559         return_VOID;
560 }
561
562 #else
563 static void acpi_cpufreq_add_file (struct acpi_processor *pr) { return; }
564 static void acpi_cpufreq_remove_file (struct acpi_processor *pr) { return; }
565 #endif /* CONFIG_X86_ACPI_CPUFREQ_PROC_INTF */
566
567
568 int
569 acpi_processor_register_performance (
570         struct acpi_processor_performance * performance,
571         unsigned int cpu)
572 {
573         struct acpi_processor *pr;
574
575         ACPI_FUNCTION_TRACE("acpi_processor_register_performance");
576
577         if (!(acpi_processor_ppc_status & PPC_REGISTERED))
578                 return_VALUE(-EINVAL);
579
580         down(&performance_sem);
581
582         pr = processors[cpu];
583         if (!pr) {
584                 up(&performance_sem);
585                 return_VALUE(-ENODEV);
586         }
587
588         if (pr->performance) {
589                 up(&performance_sem);
590                 return_VALUE(-EBUSY);
591         }
592
593         pr->performance = performance;
594
595         if (acpi_processor_get_performance_info(pr)) {
596                 pr->performance = NULL;
597                 up(&performance_sem);
598                 return_VALUE(-EIO);
599         }
600
601         acpi_cpufreq_add_file(pr);
602
603         up(&performance_sem);
604         return_VALUE(0);
605 }
606 EXPORT_SYMBOL(acpi_processor_register_performance);
607
608
609 void
610 acpi_processor_unregister_performance (
611         struct acpi_processor_performance * performance,
612         unsigned int cpu)
613 {
614         struct acpi_processor *pr;
615
616         ACPI_FUNCTION_TRACE("acpi_processor_unregister_performance");
617
618         down(&performance_sem);
619
620         pr = processors[cpu];
621         if (!pr) {
622                 up(&performance_sem);
623                 return_VOID;
624         }
625
626         kfree(pr->performance->states);
627         pr->performance = NULL;
628
629         acpi_cpufreq_remove_file(pr);
630
631         up(&performance_sem);
632
633         return_VOID;
634 }
635 EXPORT_SYMBOL(acpi_processor_unregister_performance);