Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 74

kernel-2.6.18-238.el5.src.rpm

From: Stanislaw Gruszka <sgruszka@redhat.com>
Date: Tue, 7 Apr 2009 11:48:31 +0200
Subject: [acpi] CPU P-state limits ignored by OS
Message-id: 20090407114831.40bdb2db@dhcp-lab-109.englab.brq.redhat.com
O-Subject: [RHEL5.4 PATCH] BZ494288: CPU P-state limits (via acpi _ppc) ignored by OS
Bugzilla: 494288
RH-Acked-by: Pete Zaitcev <zaitcev@redhat.com>
RH-Acked-by: Brian Maly <bmaly@redhat.com>

BZ#494288
=========
https://bugzilla.redhat.com/show_bug.cgi?id=494288

Description:
============
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. With no pr->performance other cpufreq driver is unable to limit
P-stats when BIOS ask for it. The patch fix this problem. It also remove double
checks in P domain basic validity code and move these checks to function where
_PSD data is captured.

kABI Status:
============
No symbols were harmed.

Brew:
====
http://brewweb.devel.redhat.com/brew/taskinfo?taskID=1751995

Upstream Status:
===============
Merged in commit:
e1eb47797ac0773cb3efe7495e14fc26e18a23c2

Test Status:
============
Bug is not reproductable on RHEL5. I tested the patch only to see, if it not
cause any other problems.

diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index 473a5b7..38430d8 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -610,6 +610,14 @@ static int acpi_processor_get_psd(struct acpi_processor	*pr)
 		goto end;
 	}
 
+	if (pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ALL &&
+	    pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ANY &&
+	    pdomain->coord_type != DOMAIN_COORD_TYPE_HW_ALL) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR "Invalid _PSD:coord_type\n"));
+		result = -EFAULT;
+		goto end;
+	}
+
 end:
 	kfree(buffer.pointer);
 	return result;
@@ -629,9 +637,10 @@ int acpi_processor_preregister_performance(
 
 	mutex_lock(&performance_mutex);
 
-	retval = 0;
-
-	/* Call _PSD for all CPUs */
+	/*
+	 * Check if another driver has already registered, and abort before
+	 * changing pr->performance if it has. Check input data as well.
+	 */
 	for_each_possible_cpu(i) {
 		pr = processors[i];
 		if (!pr) {
@@ -641,13 +650,20 @@ int acpi_processor_preregister_performance(
 
 		if (pr->performance) {
 			retval = -EBUSY;
-			continue;
+			goto err_out;
 		}
 
 		if (!performance || !performance[i]) {
 			retval = -EINVAL;
-			continue;
+			goto err_out;
 		}
+	}
+
+	/* Call _PSD for all CPUs */
+	for_each_possible_cpu(i) {
+		pr = processors[i];
+		if (!pr)
+			continue;
 
 		pr->performance = performance[i];
 		cpu_set(i, pr->performance->shared_cpu_map);
@@ -663,26 +679,6 @@ int acpi_processor_preregister_performance(
 	 * Now that we have _PSD data from all CPUs, lets setup P-state 
 	 * domain info.
 	 */
-	for_each_possible_cpu(i) {
-		pr = processors[i];
-		if (!pr)
-			continue;
-
-		/* Basic validity check for domain info */
-		pdomain = &(pr->performance->domain_info);
-		if ((pdomain->revision != ACPI_PSD_REV0_REVISION) ||
-		    (pdomain->num_entries != ACPI_PSD_REV0_ENTRIES)) {
-			retval = -EINVAL;
-			goto err_ret;
-		}
-		if (pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ALL &&
-		    pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ANY &&
-		    pdomain->coord_type != DOMAIN_COORD_TYPE_HW_ALL) {
-			retval = -EINVAL;
-			goto err_ret;
-		}
-	}
-
 	cpus_clear(covered_cpus);
 	for_each_possible_cpu(i) {
 		pr = processors[i];
@@ -771,6 +767,7 @@ err_ret:
 		pr->performance = NULL; /* Will be set for real in register */
 	}
 
+err_out:
 	mutex_unlock(&performance_mutex);
 	return retval;
 }