This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-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  * when registering a cpufreq driver with this ACPI processor driver, the
170  * _PCT and _PSS structures are read out and written into struct
171  * acpi_processor_performance.
172  */
173 static int acpi_processor_set_pdc (struct acpi_processor *pr)
174 {
175         acpi_status             status = AE_OK;
176         u32                     arg0_buf[3];
177         union acpi_object       arg0 = {ACPI_TYPE_BUFFER};
178         struct acpi_object_list no_object = {1, &arg0};
179         struct acpi_object_list *pdc;
180
181         ACPI_FUNCTION_TRACE("acpi_processor_set_pdc");
182
183         arg0.buffer.length = 12;
184         arg0.buffer.pointer = (u8 *) arg0_buf;
185         arg0_buf[0] = ACPI_PDC_REVISION_ID;
186         arg0_buf[1] = 0;
187         arg0_buf[2] = 0;
188
189         pdc = (pr->performance->pdc) ? pr->performance->pdc : &no_object;
190
191         status = acpi_evaluate_object(pr->handle, "_PDC", pdc, NULL);
192
193         if ((ACPI_FAILURE(status)) && (pr->performance->pdc))
194                 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Error evaluating _PDC, using legacy perf. control...\n"));
195
196         return_VALUE(status);
197 }
198
199
200 static int
201 acpi_processor_get_performance_control (
202         struct acpi_processor *pr)
203 {
204         int                     result = 0;
205         acpi_status             status = 0;
206         struct acpi_buffer      buffer = {ACPI_ALLOCATE_BUFFER, NULL};
207         union acpi_object       *pct = NULL;
208         union acpi_object       obj = {0};
209
210         ACPI_FUNCTION_TRACE("acpi_processor_get_performance_control");
211
212         status = acpi_evaluate_object(pr->handle, "_PCT", NULL, &buffer);
213         if(ACPI_FAILURE(status)) {
214                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PCT\n"));
215                 return_VALUE(-ENODEV);
216         }
217
218         pct = (union acpi_object *) buffer.pointer;
219         if (!pct || (pct->type != ACPI_TYPE_PACKAGE)
220                 || (pct->package.count != 2)) {
221                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PCT data\n"));
222                 result = -EFAULT;
223                 goto end;
224         }
225
226         /*
227          * control_register
228          */
229
230         obj = pct->package.elements[0];
231
232         if ((obj.type != ACPI_TYPE_BUFFER)
233                 || (obj.buffer.length < sizeof(struct acpi_pct_register))
234                 || (obj.buffer.pointer == NULL)) {
235                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
236                         "Invalid _PCT data (control_register)\n"));
237                 result = -EFAULT;
238                 goto end;
239         }
240         memcpy(&pr->performance->control_register, obj.buffer.pointer, sizeof(struct acpi_pct_register));
241
242
243         /*
244          * status_register
245          */
246
247         obj = pct->package.elements[1];
248
249         if ((obj.type != ACPI_TYPE_BUFFER)
250                 || (obj.buffer.length < sizeof(struct acpi_pct_register))
251                 || (obj.buffer.pointer == NULL)) {
252                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
253                         "Invalid _PCT data (status_register)\n"));
254                 result = -EFAULT;
255                 goto end;
256         }
257
258         memcpy(&pr->performance->status_register, obj.buffer.pointer, sizeof(struct acpi_pct_register));
259
260 end:
261         acpi_os_free(buffer.pointer);
262
263         return_VALUE(result);
264 }
265
266
267 static int
268 acpi_processor_get_performance_states (
269         struct acpi_processor   *pr)
270 {
271         int                     result = 0;
272         acpi_status             status = AE_OK;
273         struct acpi_buffer      buffer = {ACPI_ALLOCATE_BUFFER, NULL};
274         struct acpi_buffer      format = {sizeof("NNNNNN"), "NNNNNN"};
275         struct acpi_buffer      state = {0, NULL};
276         union acpi_object       *pss = NULL;
277         int                     i;
278
279         ACPI_FUNCTION_TRACE("acpi_processor_get_performance_states");
280
281         status = acpi_evaluate_object(pr->handle, "_PSS", NULL, &buffer);
282         if(ACPI_FAILURE(status)) {
283                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PSS\n"));
284                 return_VALUE(-ENODEV);
285         }
286
287         pss = (union acpi_object *) buffer.pointer;
288         if (!pss || (pss->type != ACPI_TYPE_PACKAGE)) {
289                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSS data\n"));
290                 result = -EFAULT;
291                 goto end;
292         }
293
294         ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d performance states\n",
295                 pss->package.count));
296
297         pr->performance->state_count = pss->package.count;
298         pr->performance->states = kmalloc(sizeof(struct acpi_processor_px) * pss->package.count, GFP_KERNEL);
299         if (!pr->performance->states) {
300                 result = -ENOMEM;
301                 goto end;
302         }
303
304         for (i = 0; i < pr->performance->state_count; i++) {
305
306                 struct acpi_processor_px *px = &(pr->performance->states[i]);
307
308                 state.length = sizeof(struct acpi_processor_px);
309                 state.pointer = px;
310
311                 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Extracting state %d\n", i));
312
313                 status = acpi_extract_package(&(pss->package.elements[i]),
314                         &format, &state);
315                 if (ACPI_FAILURE(status)) {
316                         ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSS data\n"));
317                         result = -EFAULT;
318                         kfree(pr->performance->states);
319                         goto end;
320                 }
321
322                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
323                         "State [%d]: core_frequency[%d] power[%d] transition_latency[%d] bus_master_latency[%d] control[0x%x] status[0x%x]\n",
324                         i,
325                         (u32) px->core_frequency,
326                         (u32) px->power,
327                         (u32) px->transition_latency,
328                         (u32) px->bus_master_latency,
329                         (u32) px->control,
330                         (u32) px->status));
331
332                 if (!px->core_frequency) {
333                         ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSS data: freq is zero\n"));
334                         result = -EFAULT;
335                         kfree(pr->performance->states);
336                         goto end;
337                 }
338         }
339
340 end:
341         acpi_os_free(buffer.pointer);
342
343         return_VALUE(result);
344 }
345
346
347 static int
348 acpi_processor_get_performance_info (
349         struct acpi_processor   *pr)
350 {
351         int                     result = 0;
352         acpi_status             status = AE_OK;
353         acpi_handle             handle = NULL;
354
355         ACPI_FUNCTION_TRACE("acpi_processor_get_performance_info");
356
357         if (!pr || !pr->performance || !pr->handle)
358                 return_VALUE(-EINVAL);
359
360         acpi_processor_set_pdc(pr);
361
362         status = acpi_get_handle(pr->handle, "_PCT", &handle);
363         if (ACPI_FAILURE(status)) {
364                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
365                         "ACPI-based processor performance control unavailable\n"));
366                 return_VALUE(-ENODEV);
367         }
368
369         result = acpi_processor_get_performance_control(pr);
370         if (result)
371                 return_VALUE(result);
372
373         result = acpi_processor_get_performance_states(pr);
374         if (result)
375                 return_VALUE(result);
376
377         result = acpi_processor_get_platform_limit(pr);
378         if (result)
379                 return_VALUE(result);
380
381         return_VALUE(0);
382 }
383
384
385 int acpi_processor_notify_smm(struct module *calling_module) {
386         acpi_status             status;
387         static int              is_done = 0;
388
389         ACPI_FUNCTION_TRACE("acpi_processor_notify_smm");
390
391         if (!(acpi_processor_ppc_status & PPC_REGISTERED))
392                 return_VALUE(-EBUSY);
393
394         if (!try_module_get(calling_module))
395                 return_VALUE(-EINVAL);
396
397         /* is_done is set to negative if an error occured,
398          * and to postitive if _no_ error occured, but SMM
399          * was already notified. This avoids double notification
400          * which might lead to unexpected results...
401          */
402         if (is_done > 0) {
403                 module_put(calling_module);
404                 return_VALUE(0);
405         }
406         else if (is_done < 0) {
407                 module_put(calling_module);
408                 return_VALUE(is_done);
409         }
410
411         is_done = -EIO;
412
413         /* Can't write pstate_cnt to smi_cmd if either value is zero */
414         if ((!acpi_fadt.smi_cmd) ||
415             (!acpi_fadt.pstate_cnt)) {
416                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
417                         "No SMI port or pstate_cnt\n"));
418                 module_put(calling_module);
419                 return_VALUE(0);
420         }
421
422         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));
423
424         /* FADT v1 doesn't support pstate_cnt, many BIOS vendors use
425          * it anyway, so we need to support it... */
426         if (acpi_fadt_is_v1) {
427                 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Using v1.0 FADT reserved value for pstate_cnt\n"));
428         }
429
430         status = acpi_os_write_port (acpi_fadt.smi_cmd,
431                                      (u32) acpi_fadt.pstate_cnt, 8);
432         if (ACPI_FAILURE (status)) {
433                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
434                                   "Failed to write pstate_cnt [0x%x] to "
435                                   "smi_cmd [0x%x]\n", acpi_fadt.pstate_cnt, acpi_fadt.smi_cmd));
436                 module_put(calling_module);
437                 return_VALUE(status);
438         }
439
440         /* Success. If there's no _PPC, we need to fear nothing, so
441          * we can allow the cpufreq driver to be rmmod'ed. */
442         is_done = 1;
443
444         if (!(acpi_processor_ppc_status & PPC_IN_USE))
445                 module_put(calling_module);
446
447         return_VALUE(0);
448 }
449 EXPORT_SYMBOL(acpi_processor_notify_smm);
450
451
452 #ifdef CONFIG_X86_ACPI_CPUFREQ_PROC_INTF
453 /* /proc/acpi/processor/../performance interface (DEPRECATED) */
454
455 static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file);
456 static struct file_operations acpi_processor_perf_fops = {
457         .open           = acpi_processor_perf_open_fs,
458         .read           = seq_read,
459         .llseek         = seq_lseek,
460         .release        = single_release,
461 };
462
463 static int acpi_processor_perf_seq_show(struct seq_file *seq, void *offset)
464 {
465         struct acpi_processor   *pr = (struct acpi_processor *)seq->private;
466         int                     i;
467
468         ACPI_FUNCTION_TRACE("acpi_processor_perf_seq_show");
469
470         if (!pr)
471                 goto end;
472
473         if (!pr->performance) {
474                 seq_puts(seq, "<not supported>\n");
475                 goto end;
476         }
477
478         seq_printf(seq, "state count:             %d\n"
479                         "active state:            P%d\n",
480                         pr->performance->state_count,
481                         pr->performance->state);
482
483         seq_puts(seq, "states:\n");
484         for (i = 0; i < pr->performance->state_count; i++)
485                 seq_printf(seq, "   %cP%d:                  %d MHz, %d mW, %d uS\n",
486                         (i == pr->performance->state?'*':' '), i,
487                         (u32) pr->performance->states[i].core_frequency,
488                         (u32) pr->performance->states[i].power,
489                         (u32) pr->performance->states[i].transition_latency);
490
491 end:
492         return_VALUE(0);
493 }
494
495 static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file)
496 {
497         return single_open(file, acpi_processor_perf_seq_show,
498                                                 PDE(inode)->data);
499 }
500
501 static ssize_t
502 acpi_processor_write_performance (
503         struct file             *file,
504         const char              __user *buffer,
505         size_t                  count,
506         loff_t                  *data)
507 {
508         int                     result = 0;
509         struct seq_file         *m = (struct seq_file *) file->private_data;
510         struct acpi_processor   *pr = (struct acpi_processor *) m->private;
511         struct acpi_processor_performance *perf;
512         char                    state_string[12] = {'\0'};
513         unsigned int            new_state = 0;
514         struct cpufreq_policy   policy;
515
516         ACPI_FUNCTION_TRACE("acpi_processor_write_performance");
517
518         if (!pr || (count > sizeof(state_string) - 1))
519                 return_VALUE(-EINVAL);
520
521         perf = pr->performance;
522         if (!perf)
523                 return_VALUE(-EINVAL);
524
525         if (copy_from_user(state_string, buffer, count))
526                 return_VALUE(-EFAULT);
527
528         state_string[count] = '\0';
529         new_state = simple_strtoul(state_string, NULL, 0);
530
531         if (new_state >= perf->state_count)
532                 return_VALUE(-EINVAL);
533
534         cpufreq_get_policy(&policy, pr->id);
535
536         policy.cpu = pr->id;
537         policy.min = perf->states[new_state].core_frequency * 1000;
538         policy.max = perf->states[new_state].core_frequency * 1000;
539
540         result = cpufreq_set_policy(&policy);
541         if (result)
542                 return_VALUE(result);
543
544         return_VALUE(count);
545 }
546
547 static void
548 acpi_cpufreq_add_file (
549         struct acpi_processor *pr)
550 {
551         struct proc_dir_entry   *entry = NULL;
552         struct acpi_device      *device = NULL;
553
554         ACPI_FUNCTION_TRACE("acpi_cpufreq_addfile");
555
556         if (acpi_bus_get_device(pr->handle, &device))
557                 return_VOID;
558
559         /* add file 'performance' [R/W] */
560         entry = create_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE,
561                   S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
562         if (!entry)
563                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
564                         "Unable to create '%s' fs entry\n",
565                         ACPI_PROCESSOR_FILE_PERFORMANCE));
566         else {
567                 entry->proc_fops = &acpi_processor_perf_fops;
568                 entry->proc_fops->write = acpi_processor_write_performance;
569                 entry->data = acpi_driver_data(device);
570                 entry->owner = THIS_MODULE;
571         }
572         return_VOID;
573 }
574
575 static void
576 acpi_cpufreq_remove_file (
577         struct acpi_processor *pr)
578 {
579         struct acpi_device      *device = NULL;
580
581         ACPI_FUNCTION_TRACE("acpi_cpufreq_addfile");
582
583         if (acpi_bus_get_device(pr->handle, &device))
584                 return_VOID;
585
586         /* remove file 'performance' */
587         remove_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE,
588                   acpi_device_dir(device));
589
590         return_VOID;
591 }
592
593 #else
594 static void acpi_cpufreq_add_file (struct acpi_processor *pr) { return; }
595 static void acpi_cpufreq_remove_file (struct acpi_processor *pr) { return; }
596 #endif /* CONFIG_X86_ACPI_CPUFREQ_PROC_INTF */
597
598
599 int
600 acpi_processor_register_performance (
601         struct acpi_processor_performance * performance,
602         unsigned int cpu)
603 {
604         struct acpi_processor *pr;
605
606         ACPI_FUNCTION_TRACE("acpi_processor_register_performance");
607
608         if (!(acpi_processor_ppc_status & PPC_REGISTERED))
609                 return_VALUE(-EINVAL);
610
611         down(&performance_sem);
612
613         pr = processors[cpu];
614         if (!pr) {
615                 up(&performance_sem);
616                 return_VALUE(-ENODEV);
617         }
618
619         if (pr->performance) {
620                 up(&performance_sem);
621                 return_VALUE(-EBUSY);
622         }
623
624         pr->performance = performance;
625
626         if (acpi_processor_get_performance_info(pr)) {
627                 pr->performance = NULL;
628                 up(&performance_sem);
629                 return_VALUE(-EIO);
630         }
631
632         acpi_cpufreq_add_file(pr);
633
634         up(&performance_sem);
635         return_VALUE(0);
636 }
637 EXPORT_SYMBOL(acpi_processor_register_performance);
638
639
640 void
641 acpi_processor_unregister_performance (
642         struct acpi_processor_performance * performance,
643         unsigned int cpu)
644 {
645         struct acpi_processor *pr;
646
647         ACPI_FUNCTION_TRACE("acpi_processor_unregister_performance");
648
649         down(&performance_sem);
650
651         pr = processors[cpu];
652         if (!pr) {
653                 up(&performance_sem);
654                 return_VOID;
655         }
656
657         kfree(pr->performance->states);
658         pr->performance = NULL;
659
660         acpi_cpufreq_remove_file(pr);
661
662         up(&performance_sem);
663
664         return_VOID;
665 }
666 EXPORT_SYMBOL(acpi_processor_unregister_performance);