diff options
author | Stanislaw Gruszka <sgruszka@redhat.com> | 2009-03-24 08:41:59 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-03-27 21:11:55 -0400 |
commit | e1eb47797ac0773cb3efe7495e14fc26e18a23c2 (patch) | |
tree | 6e49293edde8c6482758caf5c30ec1dc3a89975f /drivers/acpi/processor_perflib.c | |
parent | 8e0ee43bc2c3e19db56a4adaa9a9b04ce885cd84 (diff) |
ACPI: Avoid wiping out pr->performance during preregistering
When cpufreq driver call acpi_processor_preregister_performance() , function
will clean up pr->performance even if there is possibly already registered
other cpufreq driver. The patch fix this potential problem. It also remove
double checks in P domain basic validity code and move these checks to function
where _PSD data is captured.
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/processor_perflib.c')
-rw-r--r-- | drivers/acpi/processor_perflib.c | 46 |
1 files changed, 21 insertions, 25 deletions
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 9cc769b587ff..215f1bf7d4c1 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c | |||
@@ -479,6 +479,13 @@ static int acpi_processor_get_psd(struct acpi_processor *pr) | |||
479 | goto end; | 479 | goto end; |
480 | } | 480 | } |
481 | 481 | ||
482 | if (pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ALL && | ||
483 | pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ANY && | ||
484 | pdomain->coord_type != DOMAIN_COORD_TYPE_HW_ALL) { | ||
485 | printk(KERN_ERR PREFIX "Invalid _PSD:coord_type\n"); | ||
486 | result = -EFAULT; | ||
487 | goto end; | ||
488 | } | ||
482 | end: | 489 | end: |
483 | kfree(buffer.pointer); | 490 | kfree(buffer.pointer); |
484 | return result; | 491 | return result; |
@@ -501,9 +508,10 @@ int acpi_processor_preregister_performance( | |||
501 | 508 | ||
502 | mutex_lock(&performance_mutex); | 509 | mutex_lock(&performance_mutex); |
503 | 510 | ||
504 | retval = 0; | 511 | /* |
505 | 512 | * Check if another driver has already registered, and abort before | |
506 | /* Call _PSD for all CPUs */ | 513 | * changing pr->performance if it has. Check input data as well. |
514 | */ | ||
507 | for_each_possible_cpu(i) { | 515 | for_each_possible_cpu(i) { |
508 | pr = per_cpu(processors, i); | 516 | pr = per_cpu(processors, i); |
509 | if (!pr) { | 517 | if (!pr) { |
@@ -513,13 +521,20 @@ int acpi_processor_preregister_performance( | |||
513 | 521 | ||
514 | if (pr->performance) { | 522 | if (pr->performance) { |
515 | retval = -EBUSY; | 523 | retval = -EBUSY; |
516 | continue; | 524 | goto err_out; |
517 | } | 525 | } |
518 | 526 | ||
519 | if (!performance || !percpu_ptr(performance, i)) { | 527 | if (!performance || !percpu_ptr(performance, i)) { |
520 | retval = -EINVAL; | 528 | retval = -EINVAL; |
521 | continue; | 529 | goto err_out; |
522 | } | 530 | } |
531 | } | ||
532 | |||
533 | /* Call _PSD for all CPUs */ | ||
534 | for_each_possible_cpu(i) { | ||
535 | pr = per_cpu(processors, i); | ||
536 | if (!pr) | ||
537 | continue; | ||
523 | 538 | ||
524 | pr->performance = percpu_ptr(performance, i); | 539 | pr->performance = percpu_ptr(performance, i); |
525 | cpumask_set_cpu(i, pr->performance->shared_cpu_map); | 540 | cpumask_set_cpu(i, pr->performance->shared_cpu_map); |
@@ -535,26 +550,6 @@ int acpi_processor_preregister_performance( | |||
535 | * Now that we have _PSD data from all CPUs, lets setup P-state | 550 | * Now that we have _PSD data from all CPUs, lets setup P-state |
536 | * domain info. | 551 | * domain info. |
537 | */ | 552 | */ |
538 | for_each_possible_cpu(i) { | ||
539 | pr = per_cpu(processors, i); | ||
540 | if (!pr) | ||
541 | continue; | ||
542 | |||
543 | /* Basic validity check for domain info */ | ||
544 | pdomain = &(pr->performance->domain_info); | ||
545 | if ((pdomain->revision != ACPI_PSD_REV0_REVISION) || | ||
546 | (pdomain->num_entries != ACPI_PSD_REV0_ENTRIES)) { | ||
547 | retval = -EINVAL; | ||
548 | goto err_ret; | ||
549 | } | ||
550 | if (pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ALL && | ||
551 | pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ANY && | ||
552 | pdomain->coord_type != DOMAIN_COORD_TYPE_HW_ALL) { | ||
553 | retval = -EINVAL; | ||
554 | goto err_ret; | ||
555 | } | ||
556 | } | ||
557 | |||
558 | cpumask_clear(covered_cpus); | 553 | cpumask_clear(covered_cpus); |
559 | for_each_possible_cpu(i) { | 554 | for_each_possible_cpu(i) { |
560 | pr = per_cpu(processors, i); | 555 | pr = per_cpu(processors, i); |
@@ -643,6 +638,7 @@ err_ret: | |||
643 | pr->performance = NULL; /* Will be set for real in register */ | 638 | pr->performance = NULL; /* Will be set for real in register */ |
644 | } | 639 | } |
645 | 640 | ||
641 | err_out: | ||
646 | mutex_unlock(&performance_mutex); | 642 | mutex_unlock(&performance_mutex); |
647 | free_cpumask_var(covered_cpus); | 643 | free_cpumask_var(covered_cpus); |
648 | return retval; | 644 | return retval; |