* [PATCH] 2/3 Dynamic cpufreq governor and updates to ACPI P-state driver
@ 2003-10-21 2:56 ` Pallipadi, Venkatesh
0 siblings, 0 replies; 2+ messages in thread
From: Pallipadi, Venkatesh @ 2003-10-21 2:56 UTC (permalink / raw)
To: cpufreq, linux-kernel, linux-acpi
Cc: Nakajima, Jun, Mallick, Asit K, Dominik Brodowski
[-- Attachment #1: Type: text/plain, Size: 8959 bytes --]
Patch 2/3: Introduce HT-synchronization in the ACPI P-state
Driver, to take care of shared CPU frequency between HT siblings.
diffstat dbs2.patch
arch/i386/kernel/cpu/cpufreq/acpi.c | 169
++++++++++++++++++++++++++++++++++--
include/acpi/processor.h | 15 +++
2 files changed, 178 insertions(+), 6 deletions(-)
diff -purN linux-2.6.0-test7/arch/i386/kernel/cpu/cpufreq/acpi.c
linux-2.6.0-test7-dbs/arch/i386/kernel/cpu/cpufreq/acpi.c
--- linux-2.6.0-test7/arch/i386/kernel/cpu/cpufreq/acpi.c
2003-10-20 13:31:10.000000000 -0700
+++ linux-2.6.0-test7-dbs/arch/i386/kernel/cpu/cpufreq/acpi.c
2003-10-20 13:29:41.000000000 -0700
@@ -34,6 +34,7 @@
#include <asm/io.h>
#include <asm/delay.h>
#include <asm/uaccess.h>
+#include <linux/sem.h>
#include <linux/acpi.h>
#include <acpi/processor.h>
@@ -362,7 +363,8 @@ acpi_processor_set_performance (
cpufreq_freqs.new = perf->states[state].core_frequency * 1000;
/* notify cpufreq */
- cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE);
+ perf->domainp->cpufreq_notify_transition_ptr(
+ &cpufreq_freqs, CPUFREQ_PRECHANGE);
/*
* First we write the target state's 'control' value to the
@@ -390,14 +392,17 @@ acpi_processor_set_performance (
value = param.retval;
/* notify cpufreq */
- cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE);
+ perf->domainp->cpufreq_notify_transition_ptr(
+ &cpufreq_freqs, CPUFREQ_POSTCHANGE);
if (value != (u16) perf->states[state].status) {
unsigned int tmp = cpufreq_freqs.new;
cpufreq_freqs.new = cpufreq_freqs.old;
cpufreq_freqs.old = tmp;
- cpufreq_notify_transition(&cpufreq_freqs,
CPUFREQ_PRECHANGE);
- cpufreq_notify_transition(&cpufreq_freqs,
CPUFREQ_POSTCHANGE);
+ perf->domainp->cpufreq_notify_transition_ptr(
+ &cpufreq_freqs, CPUFREQ_PRECHANGE);
+ perf->domainp->cpufreq_notify_transition_ptr(
+ &cpufreq_freqs, CPUFREQ_POSTCHANGE);
ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Transition failed\n"));
return_VALUE(-ENODEV);
}
@@ -568,7 +573,8 @@ acpi_cpufreq_target (
if (result)
return_VALUE(result);
- result = acpi_processor_set_performance (perf, next_state);
+ result = perf->domainp->acpi_processor_set_performance_ptr(
+ perf, next_state);
return_VALUE(result);
}
@@ -630,6 +636,144 @@ acpi_processor_get_performance_info (
return_VALUE(0);
}
+static struct acpi_processor_domain acpi_processor_domain_def = {
+ .sem = __MUTEX_INITIALIZER(acpi_processor_domain_def.sem),
+ .ref_cnt = 0,
+ .acpi_processor_set_performance_ptr =
acpi_processor_set_performance,
+ .cpufreq_notify_transition_ptr = cpufreq_notify_transition,
+};
+
+#ifdef CONFIG_X86_HT
+static void cpufreq_notify_transition_ht(struct cpufreq_freqs
*cpufreq_freqs, unsigned int state)
+{
+ unsigned int cpu = cpufreq_freqs->cpu;
+ ACPI_FUNCTION_TRACE("cpufreq_notify_transition_ht");
+ cpufreq_notify_transition(cpufreq_freqs, state);
+ cpufreq_freqs->cpu = cpu_sibling_map[cpu];
+ cpufreq_notify_transition(cpufreq_freqs, state);
+ cpufreq_freqs->cpu = cpu;
+ return_VOID;
+}
+
+static int acpi_processor_set_performance_ht(struct
acpi_processor_performance *perf, int state)
+{
+ struct acpi_processor_domain *domainp = perf->domainp;
+ int result = 0;
+ int i;
+ int lo_state; /* highest freq */
+
+ ACPI_FUNCTION_TRACE("acpi_processor_set_performance_ht");
+ down(&(domainp->sem));
+ /*
+ * Transition into new state, only if it is the lowest among
+ * all sibling requested states.
+ * semaphore below should be held across the package.
+ */
+ perf->requested_state = state;
+ lo_state = state;
+ for (i = 0; i < domainp->ref_cnt; i++) {
+ if (performance[domainp->members[i]].requested_state <
lo_state)
+ lo_state =
+
performance[domainp->members[i]].requested_state;
+ }
+
+ if (lo_state == domainp->cur_state) {
+ up(&(domainp->sem));
+ return_VALUE(0);
+ }
+
+ result = acpi_processor_set_performance(perf, lo_state);
+ if (result == 0) {
+ domainp->cur_state = lo_state;
+ for (i = 0; i < domainp->ref_cnt; i++)
+ performance[domainp->members[i]].state =
lo_state;
+ }
+
+ up(&(domainp->sem));
+ return_VALUE(result);
+}
+
+static int
+acpi_processor_domain_ht_init(
+ struct acpi_processor_performance *perf, int cpu)
+{
+ int sibling_cpu = cpu_sibling_map[cpu];
+ struct acpi_processor_domain *domainp;
+
+ ACPI_FUNCTION_TRACE("acpi_processor_domain_ht_init");
+ if (cpu < sibling_cpu) {
+ domainp = kmalloc(sizeof(struct acpi_processor_domain),
+ GFP_KERNEL);
+ if (domainp == NULL)
+ return_VALUE(-ENOMEM);
+
+ init_MUTEX(&(domainp->sem));
+ domainp->acpi_processor_set_performance_ptr =
+ acpi_processor_set_performance_ht;
+ domainp->cpufreq_notify_transition_ptr =
+ cpufreq_notify_transition_ht;
+ domainp->cur_state = 0;
+ domainp->ref_cnt = 0;
+ domainp->members[domainp->ref_cnt] = cpu;
+ domainp->ref_cnt++;
+ perf[cpu].domainp = domainp;
+ } else {
+ perf[cpu].domainp = perf[sibling_cpu].domainp;
+ domainp = perf[cpu].domainp;
+ if (domainp->ref_cnt == ACPI_MAX_CPUS_PER_DOMAIN) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Only %d CPUS per domain is
supported\n",
+ ACPI_MAX_CPUS_PER_DOMAIN));
+ return_VALUE(-1);
+ }
+ domainp->members[domainp->ref_cnt] = cpu;
+ domainp->ref_cnt++;
+ }
+ return_VALUE(0);
+}
+#endif /* CONFIG_X86_HT */
+
+static int
+acpi_processor_domain_init(struct acpi_processor_performance *perf, int
cpu)
+{
+
+#ifdef CONFIG_X86_HT
+ int ht_present = ((cpu_has_ht) && (smp_num_siblings == 2));
+#endif
+
+ ACPI_FUNCTION_TRACE("acpi_processor_domain_init");
+
+#ifdef CONFIG_X86_HT
+ if (ht_present) {
+ int retval;
+ retval = acpi_processor_domain_ht_init(perf, cpu);
+ return_VALUE(retval);
+ }
+ /* FALLTHRU and use default domain structure */
+#endif
+ perf[cpu].domainp = &acpi_processor_domain_def;
+ return_VALUE(0);
+}
+
+static void
+acpi_processor_domain_exit(struct acpi_processor_performance *perf, int
cpu)
+{
+ ACPI_FUNCTION_TRACE("acpi_processor_domain_exit");
+#ifdef CONFIG_X86_HT
+ if (!perf[cpu].domainp)
+ return_VOID;
+
+ if (perf[cpu].domainp == &acpi_processor_domain_def)
+ return_VOID;
+
+ perf[cpu].domainp->ref_cnt--;
+ if (perf[cpu].domainp->ref_cnt == 0) {
+ kfree(perf[cpu].domainp);
+ perf[cpu].domainp = NULL;
+ }
+#endif /* CONFIG_X86_HT */
+ return_VOID;
+}
static int
acpi_cpufreq_cpu_init (
@@ -742,8 +886,13 @@ acpi_cpufreq_init (void)
/* register struct acpi_processor_performance performance */
for (i=0; i<NR_CPUS; i++) {
- if (cpu_online(i))
+ if (cpu_online(i)) {
acpi_processor_register_performance(&performance[i], &pr, i);
+ if (acpi_processor_domain_init(performance, i) <
0) {
+ result = -ENOMEM;
+ goto err0;
+ }
+ }
}
/* initialize */
@@ -804,6 +953,10 @@ acpi_cpufreq_init (void)
cpufreq_unregister_driver(&acpi_cpufreq_driver);
err0:
+ for (i = 0; i < NR_CPUS; i++)
+ if (cpu_online(i))
+ acpi_processor_domain_exit(performance, i);
+
/* unregister struct acpi_processor_performance performance */
for (i=0; i<NR_CPUS; i++) {
if (performance[i].pr) {
@@ -842,6 +995,10 @@ acpi_cpufreq_exit (void)
}
}
+ for (i = 0; i < NR_CPUS; i++)
+ if (cpu_online(i))
+ acpi_processor_domain_exit(performance, i);
+
kfree(performance);
return_VOID;
diff -purN linux-2.6.0-test7/include/acpi/processor.h
linux-2.6.0-test7-dbs/include/acpi/processor.h
--- linux-2.6.0-test7/include/acpi/processor.h 2003-10-20
13:31:10.000000000 -0700
+++ linux-2.6.0-test7-dbs/include/acpi/processor.h 2003-10-20
13:08:11.000000000 -0700
@@ -2,6 +2,7 @@
#define __ACPI_PROCESSOR_H
#include <linux/kernel.h>
+#include <linux/sem.h>
#define ACPI_PROCESSOR_BUSY_METRIC 10
@@ -74,6 +75,8 @@ struct acpi_processor_performance {
u16 status_register;
int state_count;
int space_id;
+ int requested_state;
+ struct acpi_processor_domain *domainp;
struct acpi_processor_px states[ACPI_PROCESSOR_MAX_PERFORMANCE];
struct cpufreq_frequency_table
freq_table[ACPI_PROCESSOR_MAX_PERFORMANCE];
struct acpi_processor *pr;
@@ -132,6 +135,18 @@ struct acpi_processor {
struct acpi_processor_limit limit;
};
+#define ACPI_MAX_CPUS_PER_DOMAIN 2
+struct acpi_processor_domain {
+ /* Domain wide data */
+ struct semaphore sem;
+ int cur_state;
+ int ref_cnt;
+ int members[ACPI_MAX_CPUS_PER_DOMAIN];
+ /* Domain wide function pointers */
+ int (*acpi_processor_set_performance_ptr)(struct
acpi_processor_performance *perf, int state);
+ void (*cpufreq_notify_transition_ptr)(struct cpufreq_freqs
*cpufreq_freqs, unsigned int state);
+};
+
extern int acpi_processor_get_platform_limit (
struct acpi_processor* pr);
extern int acpi_processor_register_performance (
[-- Attachment #2: dbs2.patch --]
[-- Type: application/octet-stream, Size: 8331 bytes --]
diff -purN linux-2.6.0-test7/arch/i386/kernel/cpu/cpufreq/acpi.c linux-2.6.0-test7-dbs/arch/i386/kernel/cpu/cpufreq/acpi.c
--- linux-2.6.0-test7/arch/i386/kernel/cpu/cpufreq/acpi.c 2003-10-20 13:31:10.000000000 -0700
+++ linux-2.6.0-test7-dbs/arch/i386/kernel/cpu/cpufreq/acpi.c 2003-10-20 13:29:41.000000000 -0700
@@ -34,6 +34,7 @@
#include <asm/io.h>
#include <asm/delay.h>
#include <asm/uaccess.h>
+#include <linux/sem.h>
#include <linux/acpi.h>
#include <acpi/processor.h>
@@ -362,7 +363,8 @@ acpi_processor_set_performance (
cpufreq_freqs.new = perf->states[state].core_frequency * 1000;
/* notify cpufreq */
- cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE);
+ perf->domainp->cpufreq_notify_transition_ptr(
+ &cpufreq_freqs, CPUFREQ_PRECHANGE);
/*
* First we write the target state's 'control' value to the
@@ -390,14 +392,17 @@ acpi_processor_set_performance (
value = param.retval;
/* notify cpufreq */
- cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE);
+ perf->domainp->cpufreq_notify_transition_ptr(
+ &cpufreq_freqs, CPUFREQ_POSTCHANGE);
if (value != (u16) perf->states[state].status) {
unsigned int tmp = cpufreq_freqs.new;
cpufreq_freqs.new = cpufreq_freqs.old;
cpufreq_freqs.old = tmp;
- cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE);
- cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE);
+ perf->domainp->cpufreq_notify_transition_ptr(
+ &cpufreq_freqs, CPUFREQ_PRECHANGE);
+ perf->domainp->cpufreq_notify_transition_ptr(
+ &cpufreq_freqs, CPUFREQ_POSTCHANGE);
ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Transition failed\n"));
return_VALUE(-ENODEV);
}
@@ -568,7 +573,8 @@ acpi_cpufreq_target (
if (result)
return_VALUE(result);
- result = acpi_processor_set_performance (perf, next_state);
+ result = perf->domainp->acpi_processor_set_performance_ptr(
+ perf, next_state);
return_VALUE(result);
}
@@ -630,6 +636,144 @@ acpi_processor_get_performance_info (
return_VALUE(0);
}
+static struct acpi_processor_domain acpi_processor_domain_def = {
+ .sem = __MUTEX_INITIALIZER(acpi_processor_domain_def.sem),
+ .ref_cnt = 0,
+ .acpi_processor_set_performance_ptr = acpi_processor_set_performance,
+ .cpufreq_notify_transition_ptr = cpufreq_notify_transition,
+};
+
+#ifdef CONFIG_X86_HT
+static void cpufreq_notify_transition_ht(struct cpufreq_freqs *cpufreq_freqs, unsigned int state)
+{
+ unsigned int cpu = cpufreq_freqs->cpu;
+ ACPI_FUNCTION_TRACE("cpufreq_notify_transition_ht");
+ cpufreq_notify_transition(cpufreq_freqs, state);
+ cpufreq_freqs->cpu = cpu_sibling_map[cpu];
+ cpufreq_notify_transition(cpufreq_freqs, state);
+ cpufreq_freqs->cpu = cpu;
+ return_VOID;
+}
+
+static int acpi_processor_set_performance_ht(struct acpi_processor_performance *perf, int state)
+{
+ struct acpi_processor_domain *domainp = perf->domainp;
+ int result = 0;
+ int i;
+ int lo_state; /* highest freq */
+
+ ACPI_FUNCTION_TRACE("acpi_processor_set_performance_ht");
+ down(&(domainp->sem));
+ /*
+ * Transition into new state, only if it is the lowest among
+ * all sibling requested states.
+ * semaphore below should be held across the package.
+ */
+ perf->requested_state = state;
+ lo_state = state;
+ for (i = 0; i < domainp->ref_cnt; i++) {
+ if (performance[domainp->members[i]].requested_state < lo_state)
+ lo_state =
+ performance[domainp->members[i]].requested_state;
+ }
+
+ if (lo_state == domainp->cur_state) {
+ up(&(domainp->sem));
+ return_VALUE(0);
+ }
+
+ result = acpi_processor_set_performance(perf, lo_state);
+ if (result == 0) {
+ domainp->cur_state = lo_state;
+ for (i = 0; i < domainp->ref_cnt; i++)
+ performance[domainp->members[i]].state = lo_state;
+ }
+
+ up(&(domainp->sem));
+ return_VALUE(result);
+}
+
+static int
+acpi_processor_domain_ht_init(
+ struct acpi_processor_performance *perf, int cpu)
+{
+ int sibling_cpu = cpu_sibling_map[cpu];
+ struct acpi_processor_domain *domainp;
+
+ ACPI_FUNCTION_TRACE("acpi_processor_domain_ht_init");
+ if (cpu < sibling_cpu) {
+ domainp = kmalloc(sizeof(struct acpi_processor_domain),
+ GFP_KERNEL);
+ if (domainp == NULL)
+ return_VALUE(-ENOMEM);
+
+ init_MUTEX(&(domainp->sem));
+ domainp->acpi_processor_set_performance_ptr =
+ acpi_processor_set_performance_ht;
+ domainp->cpufreq_notify_transition_ptr =
+ cpufreq_notify_transition_ht;
+ domainp->cur_state = 0;
+ domainp->ref_cnt = 0;
+ domainp->members[domainp->ref_cnt] = cpu;
+ domainp->ref_cnt++;
+ perf[cpu].domainp = domainp;
+ } else {
+ perf[cpu].domainp = perf[sibling_cpu].domainp;
+ domainp = perf[cpu].domainp;
+ if (domainp->ref_cnt == ACPI_MAX_CPUS_PER_DOMAIN) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Only %d CPUS per domain is supported\n",
+ ACPI_MAX_CPUS_PER_DOMAIN));
+ return_VALUE(-1);
+ }
+ domainp->members[domainp->ref_cnt] = cpu;
+ domainp->ref_cnt++;
+ }
+ return_VALUE(0);
+}
+#endif /* CONFIG_X86_HT */
+
+static int
+acpi_processor_domain_init(struct acpi_processor_performance *perf, int cpu)
+{
+
+#ifdef CONFIG_X86_HT
+ int ht_present = ((cpu_has_ht) && (smp_num_siblings == 2));
+#endif
+
+ ACPI_FUNCTION_TRACE("acpi_processor_domain_init");
+
+#ifdef CONFIG_X86_HT
+ if (ht_present) {
+ int retval;
+ retval = acpi_processor_domain_ht_init(perf, cpu);
+ return_VALUE(retval);
+ }
+ /* FALLTHRU and use default domain structure */
+#endif
+ perf[cpu].domainp = &acpi_processor_domain_def;
+ return_VALUE(0);
+}
+
+static void
+acpi_processor_domain_exit(struct acpi_processor_performance *perf, int cpu)
+{
+ ACPI_FUNCTION_TRACE("acpi_processor_domain_exit");
+#ifdef CONFIG_X86_HT
+ if (!perf[cpu].domainp)
+ return_VOID;
+
+ if (perf[cpu].domainp == &acpi_processor_domain_def)
+ return_VOID;
+
+ perf[cpu].domainp->ref_cnt--;
+ if (perf[cpu].domainp->ref_cnt == 0) {
+ kfree(perf[cpu].domainp);
+ perf[cpu].domainp = NULL;
+ }
+#endif /* CONFIG_X86_HT */
+ return_VOID;
+}
static int
acpi_cpufreq_cpu_init (
@@ -742,8 +886,13 @@ acpi_cpufreq_init (void)
/* register struct acpi_processor_performance performance */
for (i=0; i<NR_CPUS; i++) {
- if (cpu_online(i))
+ if (cpu_online(i)) {
acpi_processor_register_performance(&performance[i], &pr, i);
+ if (acpi_processor_domain_init(performance, i) < 0) {
+ result = -ENOMEM;
+ goto err0;
+ }
+ }
}
/* initialize */
@@ -804,6 +953,10 @@ acpi_cpufreq_init (void)
cpufreq_unregister_driver(&acpi_cpufreq_driver);
err0:
+ for (i = 0; i < NR_CPUS; i++)
+ if (cpu_online(i))
+ acpi_processor_domain_exit(performance, i);
+
/* unregister struct acpi_processor_performance performance */
for (i=0; i<NR_CPUS; i++) {
if (performance[i].pr) {
@@ -842,6 +995,10 @@ acpi_cpufreq_exit (void)
}
}
+ for (i = 0; i < NR_CPUS; i++)
+ if (cpu_online(i))
+ acpi_processor_domain_exit(performance, i);
+
kfree(performance);
return_VOID;
diff -purN linux-2.6.0-test7/include/acpi/processor.h linux-2.6.0-test7-dbs/include/acpi/processor.h
--- linux-2.6.0-test7/include/acpi/processor.h 2003-10-20 13:31:10.000000000 -0700
+++ linux-2.6.0-test7-dbs/include/acpi/processor.h 2003-10-20 13:08:11.000000000 -0700
@@ -2,6 +2,7 @@
#define __ACPI_PROCESSOR_H
#include <linux/kernel.h>
+#include <linux/sem.h>
#define ACPI_PROCESSOR_BUSY_METRIC 10
@@ -74,6 +75,8 @@ struct acpi_processor_performance {
u16 status_register;
int state_count;
int space_id;
+ int requested_state;
+ struct acpi_processor_domain *domainp;
struct acpi_processor_px states[ACPI_PROCESSOR_MAX_PERFORMANCE];
struct cpufreq_frequency_table freq_table[ACPI_PROCESSOR_MAX_PERFORMANCE];
struct acpi_processor *pr;
@@ -132,6 +135,18 @@ struct acpi_processor {
struct acpi_processor_limit limit;
};
+#define ACPI_MAX_CPUS_PER_DOMAIN 2
+struct acpi_processor_domain {
+ /* Domain wide data */
+ struct semaphore sem;
+ int cur_state;
+ int ref_cnt;
+ int members[ACPI_MAX_CPUS_PER_DOMAIN];
+ /* Domain wide function pointers */
+ int (*acpi_processor_set_performance_ptr)(struct acpi_processor_performance *perf, int state);
+ void (*cpufreq_notify_transition_ptr)(struct cpufreq_freqs *cpufreq_freqs, unsigned int state);
+};
+
extern int acpi_processor_get_platform_limit (
struct acpi_processor* pr);
extern int acpi_processor_register_performance (
^ permalink raw reply [flat|nested] 2+ messages in thread
* [PATCH] 2/3 Dynamic cpufreq governor and updates to ACPI P-state driver
@ 2003-10-21 2:56 ` Pallipadi, Venkatesh
0 siblings, 0 replies; 2+ messages in thread
From: Pallipadi, Venkatesh @ 2003-10-21 2:56 UTC (permalink / raw)
To: cpufreq, linux-kernel, linux-acpi
Cc: Mallick, Asit K, Nakajima, Jun, Dominik Brodowski
[-- Attachment #1: Type: text/plain, Size: 8959 bytes --]
Patch 2/3: Introduce HT-synchronization in the ACPI P-state
Driver, to take care of shared CPU frequency between HT siblings.
diffstat dbs2.patch
arch/i386/kernel/cpu/cpufreq/acpi.c | 169
++++++++++++++++++++++++++++++++++--
include/acpi/processor.h | 15 +++
2 files changed, 178 insertions(+), 6 deletions(-)
diff -purN linux-2.6.0-test7/arch/i386/kernel/cpu/cpufreq/acpi.c
linux-2.6.0-test7-dbs/arch/i386/kernel/cpu/cpufreq/acpi.c
--- linux-2.6.0-test7/arch/i386/kernel/cpu/cpufreq/acpi.c
2003-10-20 13:31:10.000000000 -0700
+++ linux-2.6.0-test7-dbs/arch/i386/kernel/cpu/cpufreq/acpi.c
2003-10-20 13:29:41.000000000 -0700
@@ -34,6 +34,7 @@
#include <asm/io.h>
#include <asm/delay.h>
#include <asm/uaccess.h>
+#include <linux/sem.h>
#include <linux/acpi.h>
#include <acpi/processor.h>
@@ -362,7 +363,8 @@ acpi_processor_set_performance (
cpufreq_freqs.new = perf->states[state].core_frequency * 1000;
/* notify cpufreq */
- cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE);
+ perf->domainp->cpufreq_notify_transition_ptr(
+ &cpufreq_freqs, CPUFREQ_PRECHANGE);
/*
* First we write the target state's 'control' value to the
@@ -390,14 +392,17 @@ acpi_processor_set_performance (
value = param.retval;
/* notify cpufreq */
- cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE);
+ perf->domainp->cpufreq_notify_transition_ptr(
+ &cpufreq_freqs, CPUFREQ_POSTCHANGE);
if (value != (u16) perf->states[state].status) {
unsigned int tmp = cpufreq_freqs.new;
cpufreq_freqs.new = cpufreq_freqs.old;
cpufreq_freqs.old = tmp;
- cpufreq_notify_transition(&cpufreq_freqs,
CPUFREQ_PRECHANGE);
- cpufreq_notify_transition(&cpufreq_freqs,
CPUFREQ_POSTCHANGE);
+ perf->domainp->cpufreq_notify_transition_ptr(
+ &cpufreq_freqs, CPUFREQ_PRECHANGE);
+ perf->domainp->cpufreq_notify_transition_ptr(
+ &cpufreq_freqs, CPUFREQ_POSTCHANGE);
ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Transition failed\n"));
return_VALUE(-ENODEV);
}
@@ -568,7 +573,8 @@ acpi_cpufreq_target (
if (result)
return_VALUE(result);
- result = acpi_processor_set_performance (perf, next_state);
+ result = perf->domainp->acpi_processor_set_performance_ptr(
+ perf, next_state);
return_VALUE(result);
}
@@ -630,6 +636,144 @@ acpi_processor_get_performance_info (
return_VALUE(0);
}
+static struct acpi_processor_domain acpi_processor_domain_def = {
+ .sem = __MUTEX_INITIALIZER(acpi_processor_domain_def.sem),
+ .ref_cnt = 0,
+ .acpi_processor_set_performance_ptr =
acpi_processor_set_performance,
+ .cpufreq_notify_transition_ptr = cpufreq_notify_transition,
+};
+
+#ifdef CONFIG_X86_HT
+static void cpufreq_notify_transition_ht(struct cpufreq_freqs
*cpufreq_freqs, unsigned int state)
+{
+ unsigned int cpu = cpufreq_freqs->cpu;
+ ACPI_FUNCTION_TRACE("cpufreq_notify_transition_ht");
+ cpufreq_notify_transition(cpufreq_freqs, state);
+ cpufreq_freqs->cpu = cpu_sibling_map[cpu];
+ cpufreq_notify_transition(cpufreq_freqs, state);
+ cpufreq_freqs->cpu = cpu;
+ return_VOID;
+}
+
+static int acpi_processor_set_performance_ht(struct
acpi_processor_performance *perf, int state)
+{
+ struct acpi_processor_domain *domainp = perf->domainp;
+ int result = 0;
+ int i;
+ int lo_state; /* highest freq */
+
+ ACPI_FUNCTION_TRACE("acpi_processor_set_performance_ht");
+ down(&(domainp->sem));
+ /*
+ * Transition into new state, only if it is the lowest among
+ * all sibling requested states.
+ * semaphore below should be held across the package.
+ */
+ perf->requested_state = state;
+ lo_state = state;
+ for (i = 0; i < domainp->ref_cnt; i++) {
+ if (performance[domainp->members[i]].requested_state <
lo_state)
+ lo_state =
+
performance[domainp->members[i]].requested_state;
+ }
+
+ if (lo_state == domainp->cur_state) {
+ up(&(domainp->sem));
+ return_VALUE(0);
+ }
+
+ result = acpi_processor_set_performance(perf, lo_state);
+ if (result == 0) {
+ domainp->cur_state = lo_state;
+ for (i = 0; i < domainp->ref_cnt; i++)
+ performance[domainp->members[i]].state =
lo_state;
+ }
+
+ up(&(domainp->sem));
+ return_VALUE(result);
+}
+
+static int
+acpi_processor_domain_ht_init(
+ struct acpi_processor_performance *perf, int cpu)
+{
+ int sibling_cpu = cpu_sibling_map[cpu];
+ struct acpi_processor_domain *domainp;
+
+ ACPI_FUNCTION_TRACE("acpi_processor_domain_ht_init");
+ if (cpu < sibling_cpu) {
+ domainp = kmalloc(sizeof(struct acpi_processor_domain),
+ GFP_KERNEL);
+ if (domainp == NULL)
+ return_VALUE(-ENOMEM);
+
+ init_MUTEX(&(domainp->sem));
+ domainp->acpi_processor_set_performance_ptr =
+ acpi_processor_set_performance_ht;
+ domainp->cpufreq_notify_transition_ptr =
+ cpufreq_notify_transition_ht;
+ domainp->cur_state = 0;
+ domainp->ref_cnt = 0;
+ domainp->members[domainp->ref_cnt] = cpu;
+ domainp->ref_cnt++;
+ perf[cpu].domainp = domainp;
+ } else {
+ perf[cpu].domainp = perf[sibling_cpu].domainp;
+ domainp = perf[cpu].domainp;
+ if (domainp->ref_cnt == ACPI_MAX_CPUS_PER_DOMAIN) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Only %d CPUS per domain is
supported\n",
+ ACPI_MAX_CPUS_PER_DOMAIN));
+ return_VALUE(-1);
+ }
+ domainp->members[domainp->ref_cnt] = cpu;
+ domainp->ref_cnt++;
+ }
+ return_VALUE(0);
+}
+#endif /* CONFIG_X86_HT */
+
+static int
+acpi_processor_domain_init(struct acpi_processor_performance *perf, int
cpu)
+{
+
+#ifdef CONFIG_X86_HT
+ int ht_present = ((cpu_has_ht) && (smp_num_siblings == 2));
+#endif
+
+ ACPI_FUNCTION_TRACE("acpi_processor_domain_init");
+
+#ifdef CONFIG_X86_HT
+ if (ht_present) {
+ int retval;
+ retval = acpi_processor_domain_ht_init(perf, cpu);
+ return_VALUE(retval);
+ }
+ /* FALLTHRU and use default domain structure */
+#endif
+ perf[cpu].domainp = &acpi_processor_domain_def;
+ return_VALUE(0);
+}
+
+static void
+acpi_processor_domain_exit(struct acpi_processor_performance *perf, int
cpu)
+{
+ ACPI_FUNCTION_TRACE("acpi_processor_domain_exit");
+#ifdef CONFIG_X86_HT
+ if (!perf[cpu].domainp)
+ return_VOID;
+
+ if (perf[cpu].domainp == &acpi_processor_domain_def)
+ return_VOID;
+
+ perf[cpu].domainp->ref_cnt--;
+ if (perf[cpu].domainp->ref_cnt == 0) {
+ kfree(perf[cpu].domainp);
+ perf[cpu].domainp = NULL;
+ }
+#endif /* CONFIG_X86_HT */
+ return_VOID;
+}
static int
acpi_cpufreq_cpu_init (
@@ -742,8 +886,13 @@ acpi_cpufreq_init (void)
/* register struct acpi_processor_performance performance */
for (i=0; i<NR_CPUS; i++) {
- if (cpu_online(i))
+ if (cpu_online(i)) {
acpi_processor_register_performance(&performance[i], &pr, i);
+ if (acpi_processor_domain_init(performance, i) <
0) {
+ result = -ENOMEM;
+ goto err0;
+ }
+ }
}
/* initialize */
@@ -804,6 +953,10 @@ acpi_cpufreq_init (void)
cpufreq_unregister_driver(&acpi_cpufreq_driver);
err0:
+ for (i = 0; i < NR_CPUS; i++)
+ if (cpu_online(i))
+ acpi_processor_domain_exit(performance, i);
+
/* unregister struct acpi_processor_performance performance */
for (i=0; i<NR_CPUS; i++) {
if (performance[i].pr) {
@@ -842,6 +995,10 @@ acpi_cpufreq_exit (void)
}
}
+ for (i = 0; i < NR_CPUS; i++)
+ if (cpu_online(i))
+ acpi_processor_domain_exit(performance, i);
+
kfree(performance);
return_VOID;
diff -purN linux-2.6.0-test7/include/acpi/processor.h
linux-2.6.0-test7-dbs/include/acpi/processor.h
--- linux-2.6.0-test7/include/acpi/processor.h 2003-10-20
13:31:10.000000000 -0700
+++ linux-2.6.0-test7-dbs/include/acpi/processor.h 2003-10-20
13:08:11.000000000 -0700
@@ -2,6 +2,7 @@
#define __ACPI_PROCESSOR_H
#include <linux/kernel.h>
+#include <linux/sem.h>
#define ACPI_PROCESSOR_BUSY_METRIC 10
@@ -74,6 +75,8 @@ struct acpi_processor_performance {
u16 status_register;
int state_count;
int space_id;
+ int requested_state;
+ struct acpi_processor_domain *domainp;
struct acpi_processor_px states[ACPI_PROCESSOR_MAX_PERFORMANCE];
struct cpufreq_frequency_table
freq_table[ACPI_PROCESSOR_MAX_PERFORMANCE];
struct acpi_processor *pr;
@@ -132,6 +135,18 @@ struct acpi_processor {
struct acpi_processor_limit limit;
};
+#define ACPI_MAX_CPUS_PER_DOMAIN 2
+struct acpi_processor_domain {
+ /* Domain wide data */
+ struct semaphore sem;
+ int cur_state;
+ int ref_cnt;
+ int members[ACPI_MAX_CPUS_PER_DOMAIN];
+ /* Domain wide function pointers */
+ int (*acpi_processor_set_performance_ptr)(struct
acpi_processor_performance *perf, int state);
+ void (*cpufreq_notify_transition_ptr)(struct cpufreq_freqs
*cpufreq_freqs, unsigned int state);
+};
+
extern int acpi_processor_get_platform_limit (
struct acpi_processor* pr);
extern int acpi_processor_register_performance (
[-- Attachment #2: dbs2.patch --]
[-- Type: application/octet-stream, Size: 8331 bytes --]
diff -purN linux-2.6.0-test7/arch/i386/kernel/cpu/cpufreq/acpi.c linux-2.6.0-test7-dbs/arch/i386/kernel/cpu/cpufreq/acpi.c
--- linux-2.6.0-test7/arch/i386/kernel/cpu/cpufreq/acpi.c 2003-10-20 13:31:10.000000000 -0700
+++ linux-2.6.0-test7-dbs/arch/i386/kernel/cpu/cpufreq/acpi.c 2003-10-20 13:29:41.000000000 -0700
@@ -34,6 +34,7 @@
#include <asm/io.h>
#include <asm/delay.h>
#include <asm/uaccess.h>
+#include <linux/sem.h>
#include <linux/acpi.h>
#include <acpi/processor.h>
@@ -362,7 +363,8 @@ acpi_processor_set_performance (
cpufreq_freqs.new = perf->states[state].core_frequency * 1000;
/* notify cpufreq */
- cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE);
+ perf->domainp->cpufreq_notify_transition_ptr(
+ &cpufreq_freqs, CPUFREQ_PRECHANGE);
/*
* First we write the target state's 'control' value to the
@@ -390,14 +392,17 @@ acpi_processor_set_performance (
value = param.retval;
/* notify cpufreq */
- cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE);
+ perf->domainp->cpufreq_notify_transition_ptr(
+ &cpufreq_freqs, CPUFREQ_POSTCHANGE);
if (value != (u16) perf->states[state].status) {
unsigned int tmp = cpufreq_freqs.new;
cpufreq_freqs.new = cpufreq_freqs.old;
cpufreq_freqs.old = tmp;
- cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE);
- cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE);
+ perf->domainp->cpufreq_notify_transition_ptr(
+ &cpufreq_freqs, CPUFREQ_PRECHANGE);
+ perf->domainp->cpufreq_notify_transition_ptr(
+ &cpufreq_freqs, CPUFREQ_POSTCHANGE);
ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Transition failed\n"));
return_VALUE(-ENODEV);
}
@@ -568,7 +573,8 @@ acpi_cpufreq_target (
if (result)
return_VALUE(result);
- result = acpi_processor_set_performance (perf, next_state);
+ result = perf->domainp->acpi_processor_set_performance_ptr(
+ perf, next_state);
return_VALUE(result);
}
@@ -630,6 +636,144 @@ acpi_processor_get_performance_info (
return_VALUE(0);
}
+static struct acpi_processor_domain acpi_processor_domain_def = {
+ .sem = __MUTEX_INITIALIZER(acpi_processor_domain_def.sem),
+ .ref_cnt = 0,
+ .acpi_processor_set_performance_ptr = acpi_processor_set_performance,
+ .cpufreq_notify_transition_ptr = cpufreq_notify_transition,
+};
+
+#ifdef CONFIG_X86_HT
+static void cpufreq_notify_transition_ht(struct cpufreq_freqs *cpufreq_freqs, unsigned int state)
+{
+ unsigned int cpu = cpufreq_freqs->cpu;
+ ACPI_FUNCTION_TRACE("cpufreq_notify_transition_ht");
+ cpufreq_notify_transition(cpufreq_freqs, state);
+ cpufreq_freqs->cpu = cpu_sibling_map[cpu];
+ cpufreq_notify_transition(cpufreq_freqs, state);
+ cpufreq_freqs->cpu = cpu;
+ return_VOID;
+}
+
+static int acpi_processor_set_performance_ht(struct acpi_processor_performance *perf, int state)
+{
+ struct acpi_processor_domain *domainp = perf->domainp;
+ int result = 0;
+ int i;
+ int lo_state; /* highest freq */
+
+ ACPI_FUNCTION_TRACE("acpi_processor_set_performance_ht");
+ down(&(domainp->sem));
+ /*
+ * Transition into new state, only if it is the lowest among
+ * all sibling requested states.
+ * semaphore below should be held across the package.
+ */
+ perf->requested_state = state;
+ lo_state = state;
+ for (i = 0; i < domainp->ref_cnt; i++) {
+ if (performance[domainp->members[i]].requested_state < lo_state)
+ lo_state =
+ performance[domainp->members[i]].requested_state;
+ }
+
+ if (lo_state == domainp->cur_state) {
+ up(&(domainp->sem));
+ return_VALUE(0);
+ }
+
+ result = acpi_processor_set_performance(perf, lo_state);
+ if (result == 0) {
+ domainp->cur_state = lo_state;
+ for (i = 0; i < domainp->ref_cnt; i++)
+ performance[domainp->members[i]].state = lo_state;
+ }
+
+ up(&(domainp->sem));
+ return_VALUE(result);
+}
+
+static int
+acpi_processor_domain_ht_init(
+ struct acpi_processor_performance *perf, int cpu)
+{
+ int sibling_cpu = cpu_sibling_map[cpu];
+ struct acpi_processor_domain *domainp;
+
+ ACPI_FUNCTION_TRACE("acpi_processor_domain_ht_init");
+ if (cpu < sibling_cpu) {
+ domainp = kmalloc(sizeof(struct acpi_processor_domain),
+ GFP_KERNEL);
+ if (domainp == NULL)
+ return_VALUE(-ENOMEM);
+
+ init_MUTEX(&(domainp->sem));
+ domainp->acpi_processor_set_performance_ptr =
+ acpi_processor_set_performance_ht;
+ domainp->cpufreq_notify_transition_ptr =
+ cpufreq_notify_transition_ht;
+ domainp->cur_state = 0;
+ domainp->ref_cnt = 0;
+ domainp->members[domainp->ref_cnt] = cpu;
+ domainp->ref_cnt++;
+ perf[cpu].domainp = domainp;
+ } else {
+ perf[cpu].domainp = perf[sibling_cpu].domainp;
+ domainp = perf[cpu].domainp;
+ if (domainp->ref_cnt == ACPI_MAX_CPUS_PER_DOMAIN) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Only %d CPUS per domain is supported\n",
+ ACPI_MAX_CPUS_PER_DOMAIN));
+ return_VALUE(-1);
+ }
+ domainp->members[domainp->ref_cnt] = cpu;
+ domainp->ref_cnt++;
+ }
+ return_VALUE(0);
+}
+#endif /* CONFIG_X86_HT */
+
+static int
+acpi_processor_domain_init(struct acpi_processor_performance *perf, int cpu)
+{
+
+#ifdef CONFIG_X86_HT
+ int ht_present = ((cpu_has_ht) && (smp_num_siblings == 2));
+#endif
+
+ ACPI_FUNCTION_TRACE("acpi_processor_domain_init");
+
+#ifdef CONFIG_X86_HT
+ if (ht_present) {
+ int retval;
+ retval = acpi_processor_domain_ht_init(perf, cpu);
+ return_VALUE(retval);
+ }
+ /* FALLTHRU and use default domain structure */
+#endif
+ perf[cpu].domainp = &acpi_processor_domain_def;
+ return_VALUE(0);
+}
+
+static void
+acpi_processor_domain_exit(struct acpi_processor_performance *perf, int cpu)
+{
+ ACPI_FUNCTION_TRACE("acpi_processor_domain_exit");
+#ifdef CONFIG_X86_HT
+ if (!perf[cpu].domainp)
+ return_VOID;
+
+ if (perf[cpu].domainp == &acpi_processor_domain_def)
+ return_VOID;
+
+ perf[cpu].domainp->ref_cnt--;
+ if (perf[cpu].domainp->ref_cnt == 0) {
+ kfree(perf[cpu].domainp);
+ perf[cpu].domainp = NULL;
+ }
+#endif /* CONFIG_X86_HT */
+ return_VOID;
+}
static int
acpi_cpufreq_cpu_init (
@@ -742,8 +886,13 @@ acpi_cpufreq_init (void)
/* register struct acpi_processor_performance performance */
for (i=0; i<NR_CPUS; i++) {
- if (cpu_online(i))
+ if (cpu_online(i)) {
acpi_processor_register_performance(&performance[i], &pr, i);
+ if (acpi_processor_domain_init(performance, i) < 0) {
+ result = -ENOMEM;
+ goto err0;
+ }
+ }
}
/* initialize */
@@ -804,6 +953,10 @@ acpi_cpufreq_init (void)
cpufreq_unregister_driver(&acpi_cpufreq_driver);
err0:
+ for (i = 0; i < NR_CPUS; i++)
+ if (cpu_online(i))
+ acpi_processor_domain_exit(performance, i);
+
/* unregister struct acpi_processor_performance performance */
for (i=0; i<NR_CPUS; i++) {
if (performance[i].pr) {
@@ -842,6 +995,10 @@ acpi_cpufreq_exit (void)
}
}
+ for (i = 0; i < NR_CPUS; i++)
+ if (cpu_online(i))
+ acpi_processor_domain_exit(performance, i);
+
kfree(performance);
return_VOID;
diff -purN linux-2.6.0-test7/include/acpi/processor.h linux-2.6.0-test7-dbs/include/acpi/processor.h
--- linux-2.6.0-test7/include/acpi/processor.h 2003-10-20 13:31:10.000000000 -0700
+++ linux-2.6.0-test7-dbs/include/acpi/processor.h 2003-10-20 13:08:11.000000000 -0700
@@ -2,6 +2,7 @@
#define __ACPI_PROCESSOR_H
#include <linux/kernel.h>
+#include <linux/sem.h>
#define ACPI_PROCESSOR_BUSY_METRIC 10
@@ -74,6 +75,8 @@ struct acpi_processor_performance {
u16 status_register;
int state_count;
int space_id;
+ int requested_state;
+ struct acpi_processor_domain *domainp;
struct acpi_processor_px states[ACPI_PROCESSOR_MAX_PERFORMANCE];
struct cpufreq_frequency_table freq_table[ACPI_PROCESSOR_MAX_PERFORMANCE];
struct acpi_processor *pr;
@@ -132,6 +135,18 @@ struct acpi_processor {
struct acpi_processor_limit limit;
};
+#define ACPI_MAX_CPUS_PER_DOMAIN 2
+struct acpi_processor_domain {
+ /* Domain wide data */
+ struct semaphore sem;
+ int cur_state;
+ int ref_cnt;
+ int members[ACPI_MAX_CPUS_PER_DOMAIN];
+ /* Domain wide function pointers */
+ int (*acpi_processor_set_performance_ptr)(struct acpi_processor_performance *perf, int state);
+ void (*cpufreq_notify_transition_ptr)(struct cpufreq_freqs *cpufreq_freqs, unsigned int state);
+};
+
extern int acpi_processor_get_platform_limit (
struct acpi_processor* pr);
extern int acpi_processor_register_performance (
[-- Attachment #3: Type: text/plain, Size: 143 bytes --]
_______________________________________________
Cpufreq mailing list
Cpufreq@www.linux.org.uk
http://www.linux.org.uk/mailman/listinfo/cpufreq
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2003-10-21 2:58 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-10-21 2:56 [PATCH] 2/3 Dynamic cpufreq governor and updates to ACPI P-state driver Pallipadi, Venkatesh
2003-10-21 2:56 ` Pallipadi, Venkatesh
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.