OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [acpi/] [processor_perflib.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
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
#include <linux/kernel.h>
30
#include <linux/module.h>
31
#include <linux/init.h>
32
#include <linux/cpufreq.h>
33
 
34
#ifdef CONFIG_X86_ACPI_CPUFREQ_PROC_INTF
35
#include <linux/proc_fs.h>
36
#include <linux/seq_file.h>
37
#include <linux/mutex.h>
38
 
39
#include <asm/uaccess.h>
40
#endif
41
 
42
#include <acpi/acpi_bus.h>
43
#include <acpi/processor.h>
44
 
45
#define ACPI_PROCESSOR_COMPONENT        0x01000000
46
#define ACPI_PROCESSOR_CLASS            "processor"
47
#define ACPI_PROCESSOR_FILE_PERFORMANCE "performance"
48
#define _COMPONENT              ACPI_PROCESSOR_COMPONENT
49
ACPI_MODULE_NAME("processor_perflib");
50
 
51
static DEFINE_MUTEX(performance_mutex);
52
 
53
/*
54
 * _PPC support is implemented as a CPUfreq policy notifier:
55
 * This means each time a CPUfreq driver registered also with
56
 * the ACPI core is asked to change the speed policy, the maximum
57
 * value is adjusted so that it is within the platform limit.
58
 *
59
 * Also, when a new platform limit value is detected, the CPUfreq
60
 * policy is adjusted accordingly.
61
 */
62
 
63
#define PPC_REGISTERED   1
64
#define PPC_IN_USE       2
65
 
66
static int acpi_processor_ppc_status = 0;
67
 
68
static int acpi_processor_ppc_notifier(struct notifier_block *nb,
69
                                       unsigned long event, void *data)
70
{
71
        struct cpufreq_policy *policy = data;
72
        struct acpi_processor *pr;
73
        unsigned int ppc = 0;
74
 
75
        mutex_lock(&performance_mutex);
76
 
77
        if (event != CPUFREQ_INCOMPATIBLE)
78
                goto out;
79
 
80
        pr = processors[policy->cpu];
81
        if (!pr || !pr->performance)
82
                goto out;
83
 
84
        ppc = (unsigned int)pr->performance_platform_limit;
85
 
86
        if (ppc >= pr->performance->state_count)
87
                goto out;
88
 
89
        cpufreq_verify_within_limits(policy, 0,
90
                                     pr->performance->states[ppc].
91
                                     core_frequency * 1000);
92
 
93
      out:
94
        mutex_unlock(&performance_mutex);
95
 
96
        return 0;
97
}
98
 
99
static struct notifier_block acpi_ppc_notifier_block = {
100
        .notifier_call = acpi_processor_ppc_notifier,
101
};
102
 
103
static int acpi_processor_get_platform_limit(struct acpi_processor *pr)
104
{
105
        acpi_status status = 0;
106
        unsigned long ppc = 0;
107
 
108
 
109
        if (!pr)
110
                return -EINVAL;
111
 
112
        /*
113
         * _PPC indicates the maximum state currently supported by the platform
114
         * (e.g. 0 = states 0..n; 1 = states 1..n; etc.
115
         */
116
        status = acpi_evaluate_integer(pr->handle, "_PPC", NULL, &ppc);
117
 
118
        if (status != AE_NOT_FOUND)
119
                acpi_processor_ppc_status |= PPC_IN_USE;
120
 
121
        if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
122
                ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PPC"));
123
                return -ENODEV;
124
        }
125
 
126
        pr->performance_platform_limit = (int)ppc;
127
 
128
        return 0;
129
}
130
 
131
int acpi_processor_ppc_has_changed(struct acpi_processor *pr)
132
{
133
        int ret = acpi_processor_get_platform_limit(pr);
134
        if (ret < 0)
135
                return (ret);
136
        else
137
                return cpufreq_update_policy(pr->id);
138
}
139
 
140
void acpi_processor_ppc_init(void)
141
{
142
        if (!cpufreq_register_notifier
143
            (&acpi_ppc_notifier_block, CPUFREQ_POLICY_NOTIFIER))
144
                acpi_processor_ppc_status |= PPC_REGISTERED;
145
        else
146
                printk(KERN_DEBUG
147
                       "Warning: Processor Platform Limit not supported.\n");
148
}
149
 
150
void acpi_processor_ppc_exit(void)
151
{
152
        if (acpi_processor_ppc_status & PPC_REGISTERED)
153
                cpufreq_unregister_notifier(&acpi_ppc_notifier_block,
154
                                            CPUFREQ_POLICY_NOTIFIER);
155
 
156
        acpi_processor_ppc_status &= ~PPC_REGISTERED;
157
}
158
 
159
static int acpi_processor_get_performance_control(struct acpi_processor *pr)
160
{
161
        int result = 0;
162
        acpi_status status = 0;
163
        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
164
        union acpi_object *pct = NULL;
165
        union acpi_object obj = { 0 };
166
 
167
 
168
        status = acpi_evaluate_object(pr->handle, "_PCT", NULL, &buffer);
169
        if (ACPI_FAILURE(status)) {
170
                ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PCT"));
171
                return -ENODEV;
172
        }
173
 
174
        pct = (union acpi_object *)buffer.pointer;
175
        if (!pct || (pct->type != ACPI_TYPE_PACKAGE)
176
            || (pct->package.count != 2)) {
177
                printk(KERN_ERR PREFIX "Invalid _PCT data\n");
178
                result = -EFAULT;
179
                goto end;
180
        }
181
 
182
        /*
183
         * control_register
184
         */
185
 
186
        obj = pct->package.elements[0];
187
 
188
        if ((obj.type != ACPI_TYPE_BUFFER)
189
            || (obj.buffer.length < sizeof(struct acpi_pct_register))
190
            || (obj.buffer.pointer == NULL)) {
191
                printk(KERN_ERR PREFIX "Invalid _PCT data (control_register)\n");
192
                result = -EFAULT;
193
                goto end;
194
        }
195
        memcpy(&pr->performance->control_register, obj.buffer.pointer,
196
               sizeof(struct acpi_pct_register));
197
 
198
        /*
199
         * status_register
200
         */
201
 
202
        obj = pct->package.elements[1];
203
 
204
        if ((obj.type != ACPI_TYPE_BUFFER)
205
            || (obj.buffer.length < sizeof(struct acpi_pct_register))
206
            || (obj.buffer.pointer == NULL)) {
207
                printk(KERN_ERR PREFIX "Invalid _PCT data (status_register)\n");
208
                result = -EFAULT;
209
                goto end;
210
        }
211
 
212
        memcpy(&pr->performance->status_register, obj.buffer.pointer,
213
               sizeof(struct acpi_pct_register));
214
 
215
      end:
216
        kfree(buffer.pointer);
217
 
218
        return result;
219
}
220
 
221
static int acpi_processor_get_performance_states(struct acpi_processor *pr)
222
{
223
        int result = 0;
224
        acpi_status status = AE_OK;
225
        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
226
        struct acpi_buffer format = { sizeof("NNNNNN"), "NNNNNN" };
227
        struct acpi_buffer state = { 0, NULL };
228
        union acpi_object *pss = NULL;
229
        int i;
230
 
231
 
232
        status = acpi_evaluate_object(pr->handle, "_PSS", NULL, &buffer);
233
        if (ACPI_FAILURE(status)) {
234
                ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PSS"));
235
                return -ENODEV;
236
        }
237
 
238
        pss = buffer.pointer;
239
        if (!pss || (pss->type != ACPI_TYPE_PACKAGE)) {
240
                printk(KERN_ERR PREFIX "Invalid _PSS data\n");
241
                result = -EFAULT;
242
                goto end;
243
        }
244
 
245
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d performance states\n",
246
                          pss->package.count));
247
 
248
        pr->performance->state_count = pss->package.count;
249
        pr->performance->states =
250
            kmalloc(sizeof(struct acpi_processor_px) * pss->package.count,
251
                    GFP_KERNEL);
252
        if (!pr->performance->states) {
253
                result = -ENOMEM;
254
                goto end;
255
        }
256
 
257
        for (i = 0; i < pr->performance->state_count; i++) {
258
 
259
                struct acpi_processor_px *px = &(pr->performance->states[i]);
260
 
261
                state.length = sizeof(struct acpi_processor_px);
262
                state.pointer = px;
263
 
264
                ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Extracting state %d\n", i));
265
 
266
                status = acpi_extract_package(&(pss->package.elements[i]),
267
                                              &format, &state);
268
                if (ACPI_FAILURE(status)) {
269
                        ACPI_EXCEPTION((AE_INFO, status, "Invalid _PSS data"));
270
                        result = -EFAULT;
271
                        kfree(pr->performance->states);
272
                        goto end;
273
                }
274
 
275
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
276
                                  "State [%d]: core_frequency[%d] power[%d] transition_latency[%d] bus_master_latency[%d] control[0x%x] status[0x%x]\n",
277
                                  i,
278
                                  (u32) px->core_frequency,
279
                                  (u32) px->power,
280
                                  (u32) px->transition_latency,
281
                                  (u32) px->bus_master_latency,
282
                                  (u32) px->control, (u32) px->status));
283
 
284
                if (!px->core_frequency) {
285
                        printk(KERN_ERR PREFIX
286
                                    "Invalid _PSS data: freq is zero\n");
287
                        result = -EFAULT;
288
                        kfree(pr->performance->states);
289
                        goto end;
290
                }
291
        }
292
 
293
      end:
294
        kfree(buffer.pointer);
295
 
296
        return result;
297
}
298
 
299
static int acpi_processor_get_performance_info(struct acpi_processor *pr)
300
{
301
        int result = 0;
302
        acpi_status status = AE_OK;
303
        acpi_handle handle = NULL;
304
 
305
 
306
        if (!pr || !pr->performance || !pr->handle)
307
                return -EINVAL;
308
 
309
        status = acpi_get_handle(pr->handle, "_PCT", &handle);
310
        if (ACPI_FAILURE(status)) {
311
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
312
                                  "ACPI-based processor performance control unavailable\n"));
313
                return -ENODEV;
314
        }
315
 
316
        result = acpi_processor_get_performance_control(pr);
317
        if (result)
318
                return result;
319
 
320
        result = acpi_processor_get_performance_states(pr);
321
        if (result)
322
                return result;
323
 
324
        return 0;
325
}
326
 
327
int acpi_processor_notify_smm(struct module *calling_module)
328
{
329
        acpi_status status;
330
        static int is_done = 0;
331
 
332
 
333
        if (!(acpi_processor_ppc_status & PPC_REGISTERED))
334
                return -EBUSY;
335
 
336
        if (!try_module_get(calling_module))
337
                return -EINVAL;
338
 
339
        /* is_done is set to negative if an error occured,
340
         * and to postitive if _no_ error occured, but SMM
341
         * was already notified. This avoids double notification
342
         * which might lead to unexpected results...
343
         */
344
        if (is_done > 0) {
345
                module_put(calling_module);
346
                return 0;
347
        } else if (is_done < 0) {
348
                module_put(calling_module);
349
                return is_done;
350
        }
351
 
352
        is_done = -EIO;
353
 
354
        /* Can't write pstate_control to smi_command if either value is zero */
355
        if ((!acpi_gbl_FADT.smi_command) || (!acpi_gbl_FADT.pstate_control)) {
356
                ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No SMI port or pstate_control\n"));
357
                module_put(calling_module);
358
                return 0;
359
        }
360
 
361
        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
362
                          "Writing pstate_control [0x%x] to smi_command [0x%x]\n",
363
                          acpi_gbl_FADT.pstate_control, acpi_gbl_FADT.smi_command));
364
 
365
        status = acpi_os_write_port(acpi_gbl_FADT.smi_command,
366
                                    (u32) acpi_gbl_FADT.pstate_control, 8);
367
        if (ACPI_FAILURE(status)) {
368
                ACPI_EXCEPTION((AE_INFO, status,
369
                                "Failed to write pstate_control [0x%x] to "
370
                                "smi_command [0x%x]", acpi_gbl_FADT.pstate_control,
371
                                acpi_gbl_FADT.smi_command));
372
                module_put(calling_module);
373
                return status;
374
        }
375
 
376
        /* Success. If there's no _PPC, we need to fear nothing, so
377
         * we can allow the cpufreq driver to be rmmod'ed. */
378
        is_done = 1;
379
 
380
        if (!(acpi_processor_ppc_status & PPC_IN_USE))
381
                module_put(calling_module);
382
 
383
        return 0;
384
}
385
 
386
EXPORT_SYMBOL(acpi_processor_notify_smm);
387
 
388
#ifdef CONFIG_X86_ACPI_CPUFREQ_PROC_INTF
389
/* /proc/acpi/processor/../performance interface (DEPRECATED) */
390
 
391
static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file);
392
static struct file_operations acpi_processor_perf_fops = {
393
        .open = acpi_processor_perf_open_fs,
394
        .read = seq_read,
395
        .llseek = seq_lseek,
396
        .release = single_release,
397
};
398
 
399
static int acpi_processor_perf_seq_show(struct seq_file *seq, void *offset)
400
{
401
        struct acpi_processor *pr = seq->private;
402
        int i;
403
 
404
 
405
        if (!pr)
406
                goto end;
407
 
408
        if (!pr->performance) {
409
                seq_puts(seq, "<not supported>\n");
410
                goto end;
411
        }
412
 
413
        seq_printf(seq, "state count:             %d\n"
414
                   "active state:            P%d\n",
415
                   pr->performance->state_count, pr->performance->state);
416
 
417
        seq_puts(seq, "states:\n");
418
        for (i = 0; i < pr->performance->state_count; i++)
419
                seq_printf(seq,
420
                           "   %cP%d:                  %d MHz, %d mW, %d uS\n",
421
                           (i == pr->performance->state ? '*' : ' '), i,
422
                           (u32) pr->performance->states[i].core_frequency,
423
                           (u32) pr->performance->states[i].power,
424
                           (u32) pr->performance->states[i].transition_latency);
425
 
426
      end:
427
        return 0;
428
}
429
 
430
static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file)
431
{
432
        return single_open(file, acpi_processor_perf_seq_show,
433
                           PDE(inode)->data);
434
}
435
 
436
static void acpi_cpufreq_add_file(struct acpi_processor *pr)
437
{
438
        struct proc_dir_entry *entry = NULL;
439
        struct acpi_device *device = NULL;
440
 
441
 
442
        if (acpi_bus_get_device(pr->handle, &device))
443
                return;
444
 
445
        /* add file 'performance' [R/W] */
446
        entry = create_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE,
447
                                  S_IFREG | S_IRUGO,
448
                                  acpi_device_dir(device));
449
        if (entry){
450
                entry->proc_fops = &acpi_processor_perf_fops;
451
                entry->data = acpi_driver_data(device);
452
                entry->owner = THIS_MODULE;
453
        }
454
        return;
455
}
456
 
457
static void acpi_cpufreq_remove_file(struct acpi_processor *pr)
458
{
459
        struct acpi_device *device = NULL;
460
 
461
 
462
        if (acpi_bus_get_device(pr->handle, &device))
463
                return;
464
 
465
        /* remove file 'performance' */
466
        remove_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE,
467
                          acpi_device_dir(device));
468
 
469
        return;
470
}
471
 
472
#else
473
static void acpi_cpufreq_add_file(struct acpi_processor *pr)
474
{
475
        return;
476
}
477
static void acpi_cpufreq_remove_file(struct acpi_processor *pr)
478
{
479
        return;
480
}
481
#endif                          /* CONFIG_X86_ACPI_CPUFREQ_PROC_INTF */
482
 
483
static int acpi_processor_get_psd(struct acpi_processor *pr)
484
{
485
        int result = 0;
486
        acpi_status status = AE_OK;
487
        struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
488
        struct acpi_buffer format = {sizeof("NNNNN"), "NNNNN"};
489
        struct acpi_buffer state = {0, NULL};
490
        union acpi_object  *psd = NULL;
491
        struct acpi_psd_package *pdomain;
492
 
493
        status = acpi_evaluate_object(pr->handle, "_PSD", NULL, &buffer);
494
        if (ACPI_FAILURE(status)) {
495
                return -ENODEV;
496
        }
497
 
498
        psd = buffer.pointer;
499
        if (!psd || (psd->type != ACPI_TYPE_PACKAGE)) {
500
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n"));
501
                result = -EFAULT;
502
                goto end;
503
        }
504
 
505
        if (psd->package.count != 1) {
506
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n"));
507
                result = -EFAULT;
508
                goto end;
509
        }
510
 
511
        pdomain = &(pr->performance->domain_info);
512
 
513
        state.length = sizeof(struct acpi_psd_package);
514
        state.pointer = pdomain;
515
 
516
        status = acpi_extract_package(&(psd->package.elements[0]),
517
                &format, &state);
518
        if (ACPI_FAILURE(status)) {
519
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n"));
520
                result = -EFAULT;
521
                goto end;
522
        }
523
 
524
        if (pdomain->num_entries != ACPI_PSD_REV0_ENTRIES) {
525
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _PSD:num_entries\n"));
526
                result = -EFAULT;
527
                goto end;
528
        }
529
 
530
        if (pdomain->revision != ACPI_PSD_REV0_REVISION) {
531
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _PSD:revision\n"));
532
                result = -EFAULT;
533
                goto end;
534
        }
535
 
536
end:
537
        kfree(buffer.pointer);
538
        return result;
539
}
540
 
541
int acpi_processor_preregister_performance(
542
                struct acpi_processor_performance *performance)
543
{
544
        int count, count_target;
545
        int retval = 0;
546
        unsigned int i, j;
547
        cpumask_t covered_cpus;
548
        struct acpi_processor *pr;
549
        struct acpi_psd_package *pdomain;
550
        struct acpi_processor *match_pr;
551
        struct acpi_psd_package *match_pdomain;
552
 
553
        mutex_lock(&performance_mutex);
554
 
555
        retval = 0;
556
 
557
        /* Call _PSD for all CPUs */
558
        for_each_possible_cpu(i) {
559
                pr = processors[i];
560
                if (!pr) {
561
                        /* Look only at processors in ACPI namespace */
562
                        continue;
563
                }
564
 
565
                if (pr->performance) {
566
                        retval = -EBUSY;
567
                        continue;
568
                }
569
 
570
                if (!performance || !percpu_ptr(performance, i)) {
571
                        retval = -EINVAL;
572
                        continue;
573
                }
574
 
575
                pr->performance = percpu_ptr(performance, i);
576
                cpu_set(i, pr->performance->shared_cpu_map);
577
                if (acpi_processor_get_psd(pr)) {
578
                        retval = -EINVAL;
579
                        continue;
580
                }
581
        }
582
        if (retval)
583
                goto err_ret;
584
 
585
        /*
586
         * Now that we have _PSD data from all CPUs, lets setup P-state
587
         * domain info.
588
         */
589
        for_each_possible_cpu(i) {
590
                pr = processors[i];
591
                if (!pr)
592
                        continue;
593
 
594
                /* Basic validity check for domain info */
595
                pdomain = &(pr->performance->domain_info);
596
                if ((pdomain->revision != ACPI_PSD_REV0_REVISION) ||
597
                    (pdomain->num_entries != ACPI_PSD_REV0_ENTRIES)) {
598
                        retval = -EINVAL;
599
                        goto err_ret;
600
                }
601
                if (pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ALL &&
602
                    pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ANY &&
603
                    pdomain->coord_type != DOMAIN_COORD_TYPE_HW_ALL) {
604
                        retval = -EINVAL;
605
                        goto err_ret;
606
                }
607
        }
608
 
609
        cpus_clear(covered_cpus);
610
        for_each_possible_cpu(i) {
611
                pr = processors[i];
612
                if (!pr)
613
                        continue;
614
 
615
                if (cpu_isset(i, covered_cpus))
616
                        continue;
617
 
618
                pdomain = &(pr->performance->domain_info);
619
                cpu_set(i, pr->performance->shared_cpu_map);
620
                cpu_set(i, covered_cpus);
621
                if (pdomain->num_processors <= 1)
622
                        continue;
623
 
624
                /* Validate the Domain info */
625
                count_target = pdomain->num_processors;
626
                count = 1;
627
                if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ALL)
628
                        pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ALL;
629
                else if (pdomain->coord_type == DOMAIN_COORD_TYPE_HW_ALL)
630
                        pr->performance->shared_type = CPUFREQ_SHARED_TYPE_HW;
631
                else if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ANY)
632
                        pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ANY;
633
 
634
                for_each_possible_cpu(j) {
635
                        if (i == j)
636
                                continue;
637
 
638
                        match_pr = processors[j];
639
                        if (!match_pr)
640
                                continue;
641
 
642
                        match_pdomain = &(match_pr->performance->domain_info);
643
                        if (match_pdomain->domain != pdomain->domain)
644
                                continue;
645
 
646
                        /* Here i and j are in the same domain */
647
 
648
                        if (match_pdomain->num_processors != count_target) {
649
                                retval = -EINVAL;
650
                                goto err_ret;
651
                        }
652
 
653
                        if (pdomain->coord_type != match_pdomain->coord_type) {
654
                                retval = -EINVAL;
655
                                goto err_ret;
656
                        }
657
 
658
                        cpu_set(j, covered_cpus);
659
                        cpu_set(j, pr->performance->shared_cpu_map);
660
                        count++;
661
                }
662
 
663
                for_each_possible_cpu(j) {
664
                        if (i == j)
665
                                continue;
666
 
667
                        match_pr = processors[j];
668
                        if (!match_pr)
669
                                continue;
670
 
671
                        match_pdomain = &(match_pr->performance->domain_info);
672
                        if (match_pdomain->domain != pdomain->domain)
673
                                continue;
674
 
675
                        match_pr->performance->shared_type =
676
                                        pr->performance->shared_type;
677
                        match_pr->performance->shared_cpu_map =
678
                                pr->performance->shared_cpu_map;
679
                }
680
        }
681
 
682
err_ret:
683
        for_each_possible_cpu(i) {
684
                pr = processors[i];
685
                if (!pr || !pr->performance)
686
                        continue;
687
 
688
                /* Assume no coordination on any error parsing domain info */
689
                if (retval) {
690
                        cpus_clear(pr->performance->shared_cpu_map);
691
                        cpu_set(i, pr->performance->shared_cpu_map);
692
                        pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ALL;
693
                }
694
                pr->performance = NULL; /* Will be set for real in register */
695
        }
696
 
697
        mutex_unlock(&performance_mutex);
698
        return retval;
699
}
700
EXPORT_SYMBOL(acpi_processor_preregister_performance);
701
 
702
 
703
int
704
acpi_processor_register_performance(struct acpi_processor_performance
705
                                    *performance, unsigned int cpu)
706
{
707
        struct acpi_processor *pr;
708
 
709
 
710
        if (!(acpi_processor_ppc_status & PPC_REGISTERED))
711
                return -EINVAL;
712
 
713
        mutex_lock(&performance_mutex);
714
 
715
        pr = processors[cpu];
716
        if (!pr) {
717
                mutex_unlock(&performance_mutex);
718
                return -ENODEV;
719
        }
720
 
721
        if (pr->performance) {
722
                mutex_unlock(&performance_mutex);
723
                return -EBUSY;
724
        }
725
 
726
        WARN_ON(!performance);
727
 
728
        pr->performance = performance;
729
 
730
        if (acpi_processor_get_performance_info(pr)) {
731
                pr->performance = NULL;
732
                mutex_unlock(&performance_mutex);
733
                return -EIO;
734
        }
735
 
736
        acpi_cpufreq_add_file(pr);
737
 
738
        mutex_unlock(&performance_mutex);
739
        return 0;
740
}
741
 
742
EXPORT_SYMBOL(acpi_processor_register_performance);
743
 
744
void
745
acpi_processor_unregister_performance(struct acpi_processor_performance
746
                                      *performance, unsigned int cpu)
747
{
748
        struct acpi_processor *pr;
749
 
750
 
751
        mutex_lock(&performance_mutex);
752
 
753
        pr = processors[cpu];
754
        if (!pr) {
755
                mutex_unlock(&performance_mutex);
756
                return;
757
        }
758
 
759
        if (pr->performance)
760
                kfree(pr->performance->states);
761
        pr->performance = NULL;
762
 
763
        acpi_cpufreq_remove_file(pr);
764
 
765
        mutex_unlock(&performance_mutex);
766
 
767
        return;
768
}
769
 
770
EXPORT_SYMBOL(acpi_processor_unregister_performance);

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.