Commit 2f041d0b authored by Dominik Brodowski's avatar Dominik Brodowski Committed by Len Brown

[ACPI] Abstract the registration method between low-level drivers

and the ACPI Processor P-States driver.

from Dominik Brodowski
parent 174b4ac0
...@@ -51,7 +51,12 @@ MODULE_DESCRIPTION(ACPI_PROCESSOR_DRIVER_NAME); ...@@ -51,7 +51,12 @@ MODULE_DESCRIPTION(ACPI_PROCESSOR_DRIVER_NAME);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static struct acpi_processor_performance *performance[NR_CPUS]; struct cpufreq_acpi_io {
struct acpi_processor_performance acpi_data;
struct cpufreq_frequency_table freq_table[ACPI_PROCESSOR_MAX_PERFORMANCE];
};
static struct cpufreq_acpi_io *acpi_io_data[NR_CPUS];
static int static int
...@@ -93,7 +98,7 @@ acpi_processor_read_port( ...@@ -93,7 +98,7 @@ acpi_processor_read_port(
static int static int
acpi_processor_set_performance ( acpi_processor_set_performance (
struct acpi_processor_performance *perf, struct cpufreq_acpi_io *data,
unsigned int cpu, unsigned int cpu,
int state) int state)
{ {
...@@ -106,28 +111,19 @@ acpi_processor_set_performance ( ...@@ -106,28 +111,19 @@ acpi_processor_set_performance (
ACPI_FUNCTION_TRACE("acpi_processor_set_performance"); ACPI_FUNCTION_TRACE("acpi_processor_set_performance");
if (!perf) if (state == data->acpi_data.state) {
return_VALUE(-EINVAL);
if (state >= perf->state_count) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN,
"Invalid target state (P%d)\n", state));
return_VALUE(-ENODEV);
}
if (state == perf->state) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Already at target state (P%d)\n", state)); "Already at target state (P%d)\n", state));
return_VALUE(0); return_VALUE(0);
} }
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Transitioning from P%d to P%d\n", ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Transitioning from P%d to P%d\n",
perf->state, state)); data->acpi_data.state, state));
/* cpufreq frequency struct */ /* cpufreq frequency struct */
cpufreq_freqs.cpu = cpu; cpufreq_freqs.cpu = cpu;
cpufreq_freqs.old = perf->states[perf->state].core_frequency * 1000; cpufreq_freqs.old = data->freq_table[data->acpi_data.state].frequency;
cpufreq_freqs.new = perf->states[state].core_frequency * 1000; cpufreq_freqs.new = data->freq_table[state].frequency;
/* notify cpufreq */ /* notify cpufreq */
cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE); cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE);
...@@ -137,9 +133,9 @@ acpi_processor_set_performance ( ...@@ -137,9 +133,9 @@ acpi_processor_set_performance (
* control_register. * control_register.
*/ */
port = perf->control_register; port = data->acpi_data.control_register.address;
bit_width = perf->control_register_bit_width; bit_width = data->acpi_data.control_register.bit_width;
value = (u32) perf->states[state].control; value = (u32) data->acpi_data.states[state].control;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Writing 0x%08x to port 0x%04x\n", value, port)); "Writing 0x%08x to port 0x%04x\n", value, port));
...@@ -158,12 +154,12 @@ acpi_processor_set_performance ( ...@@ -158,12 +154,12 @@ acpi_processor_set_performance (
* giving up. * giving up.
*/ */
port = perf->status_register; port = data->acpi_data.status_register.address;
bit_width = perf->status_register_bit_width; bit_width = data->acpi_data.status_register.bit_width;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Looking for 0x%08x from port 0x%04x\n", "Looking for 0x%08x from port 0x%04x\n",
(u32) perf->states[state].status, port)); (u32) data->acpi_data.states[state].status, port));
for (i=0; i<100; i++) { for (i=0; i<100; i++) {
ret = acpi_processor_read_port(port, bit_width, &value); ret = acpi_processor_read_port(port, bit_width, &value);
...@@ -172,7 +168,7 @@ acpi_processor_set_performance ( ...@@ -172,7 +168,7 @@ acpi_processor_set_performance (
"Invalid port width 0x%04x\n", bit_width)); "Invalid port width 0x%04x\n", bit_width));
return_VALUE(ret); return_VALUE(ret);
} }
if (value == (u32) perf->states[state].status) if (value == (u32) data->acpi_data.states[state].status)
break; break;
udelay(10); udelay(10);
} }
...@@ -180,7 +176,7 @@ acpi_processor_set_performance ( ...@@ -180,7 +176,7 @@ acpi_processor_set_performance (
/* notify cpufreq */ /* notify cpufreq */
cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE); cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE);
if (value != (u32) perf->states[state].status) { if (value != (u32) data->acpi_data.states[state].status) {
unsigned int tmp = cpufreq_freqs.new; unsigned int tmp = cpufreq_freqs.new;
cpufreq_freqs.new = cpufreq_freqs.old; cpufreq_freqs.new = cpufreq_freqs.old;
cpufreq_freqs.old = tmp; cpufreq_freqs.old = tmp;
...@@ -194,7 +190,7 @@ acpi_processor_set_performance ( ...@@ -194,7 +190,7 @@ acpi_processor_set_performance (
"Transition successful after %d microseconds\n", "Transition successful after %d microseconds\n",
i * 10)); i * 10));
perf->state = state; data->acpi_data.state = state;
return_VALUE(0); return_VALUE(0);
} }
...@@ -206,21 +202,21 @@ acpi_cpufreq_target ( ...@@ -206,21 +202,21 @@ acpi_cpufreq_target (
unsigned int target_freq, unsigned int target_freq,
unsigned int relation) unsigned int relation)
{ {
struct acpi_processor_performance *perf = performance[policy->cpu]; struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
unsigned int next_state = 0; unsigned int next_state = 0;
unsigned int result = 0; unsigned int result = 0;
ACPI_FUNCTION_TRACE("acpi_cpufreq_setpolicy"); ACPI_FUNCTION_TRACE("acpi_cpufreq_setpolicy");
result = cpufreq_frequency_table_target(policy, result = cpufreq_frequency_table_target(policy,
perf->freq_table, data->freq_table,
target_freq, target_freq,
relation, relation,
&next_state); &next_state);
if (result) if (result)
return_VALUE(result); return_VALUE(result);
result = acpi_processor_set_performance (perf, policy->cpu, next_state); result = acpi_processor_set_performance (data, policy->cpu, next_state);
return_VALUE(result); return_VALUE(result);
} }
...@@ -231,17 +227,12 @@ acpi_cpufreq_verify ( ...@@ -231,17 +227,12 @@ acpi_cpufreq_verify (
struct cpufreq_policy *policy) struct cpufreq_policy *policy)
{ {
unsigned int result = 0; unsigned int result = 0;
struct acpi_processor_performance *perf = performance[policy->cpu]; struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
ACPI_FUNCTION_TRACE("acpi_cpufreq_verify"); ACPI_FUNCTION_TRACE("acpi_cpufreq_verify");
result = cpufreq_frequency_table_verify(policy, result = cpufreq_frequency_table_verify(policy,
perf->freq_table); data->freq_table);
cpufreq_verify_within_limits(
policy,
perf->states[perf->state_count - 1].core_frequency * 1000,
perf->states[0].core_frequency * 1000);
return_VALUE(result); return_VALUE(result);
} }
...@@ -253,31 +244,40 @@ acpi_cpufreq_cpu_init ( ...@@ -253,31 +244,40 @@ acpi_cpufreq_cpu_init (
{ {
unsigned int i; unsigned int i;
unsigned int cpu = policy->cpu; unsigned int cpu = policy->cpu;
struct acpi_processor_performance *perf; struct cpufreq_acpi_io *data;
unsigned int result = 0; unsigned int result = 0;
ACPI_FUNCTION_TRACE("acpi_cpufreq_cpu_init"); ACPI_FUNCTION_TRACE("acpi_cpufreq_cpu_init");
perf = kmalloc(sizeof(struct acpi_processor_performance), GFP_KERNEL); data = kmalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL);
if (!perf) if (!data)
return_VALUE(-ENOMEM); return_VALUE(-ENOMEM);
memset(perf, 0, sizeof(struct acpi_processor_performance)); memset(data, 0, sizeof(struct cpufreq_acpi_io));
performance[cpu] = perf; acpi_io_data[cpu] = data;
result = acpi_processor_register_performance(perf, cpu); result = acpi_processor_register_performance(&data->acpi_data, cpu);
if (result) if (result)
goto err_free; goto err_free;
/* capability check */ /* capability check */
if (perf->state_count <= 1) if (data->acpi_data.state_count <= 1) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No P-States\n"));
goto err_unreg;
}
if ((data->acpi_data.control_register.space_id != ACPI_ADR_SPACE_SYSTEM_IO) ||
(data->acpi_data.status_register.space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unsupported address space [%d, %d]\n",
(u32) (data->acpi_data.control_register.space_id),
(u32) (data->acpi_data.status_register.space_id)));
goto err_unreg; goto err_unreg;
}
/* detect transition latency */ /* detect transition latency */
policy->cpuinfo.transition_latency = 0; policy->cpuinfo.transition_latency = 0;
for (i=0; i<perf->state_count; i++) { for (i=0; i<data->acpi_data.state_count; i++) {
if ((perf->states[i].transition_latency * 1000) > policy->cpuinfo.transition_latency) if ((data->acpi_data.states[i].transition_latency * 1000) > policy->cpuinfo.transition_latency)
policy->cpuinfo.transition_latency = perf->states[i].transition_latency * 1000; policy->cpuinfo.transition_latency = data->acpi_data.states[i].transition_latency * 1000;
} }
policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
...@@ -285,36 +285,36 @@ acpi_cpufreq_cpu_init ( ...@@ -285,36 +285,36 @@ acpi_cpufreq_cpu_init (
* The current speed is unknown and not detectable by ACPI... argh! Assume * The current speed is unknown and not detectable by ACPI... argh! Assume
* it's P0, it will be set to this value later during initialization. * it's P0, it will be set to this value later during initialization.
*/ */
policy->cur = perf->states[0].core_frequency * 1000; policy->cur = data->acpi_data.states[0].core_frequency * 1000;
/* table init */ /* table init */
for (i=0; i<=perf->state_count; i++) for (i=0; i<=data->acpi_data.state_count; i++)
{ {
perf->freq_table[i].index = i; data->freq_table[i].index = i;
if (i<perf->state_count) if (i<data->acpi_data.state_count)
perf->freq_table[i].frequency = perf->states[i].core_frequency * 1000; data->freq_table[i].frequency = data->acpi_data.states[i].core_frequency * 1000;
else else
perf->freq_table[i].frequency = CPUFREQ_TABLE_END; data->freq_table[i].frequency = CPUFREQ_TABLE_END;
} }
result = cpufreq_frequency_table_cpuinfo(policy, &perf->freq_table[0]); result = cpufreq_frequency_table_cpuinfo(policy, &data->freq_table[0]);
printk(KERN_INFO "cpufreq: CPU%u - ACPI performance management activated.\n", printk(KERN_INFO "cpufreq: CPU%u - ACPI performance management activated.\n",
cpu); cpu);
for (i = 0; i < perf->state_count; i++) for (i = 0; i < data->acpi_data.state_count; i++)
printk(KERN_INFO "cpufreq: %cP%d: %d MHz, %d mW, %d uS\n", printk(KERN_INFO "cpufreq: %cP%d: %d MHz, %d mW, %d uS\n",
(i == perf->state?'*':' '), i, (i == data->acpi_data.state?'*':' '), i,
(u32) perf->states[i].core_frequency, (u32) data->acpi_data.states[i].core_frequency,
(u32) perf->states[i].power, (u32) data->acpi_data.states[i].power,
(u32) perf->states[i].transition_latency); (u32) data->acpi_data.states[i].transition_latency);
return_VALUE(result); return_VALUE(result);
err_unreg: err_unreg:
acpi_processor_unregister_performance(perf, cpu); acpi_processor_unregister_performance(&data->acpi_data, cpu);
err_free: err_free:
kfree(perf); kfree(data);
performance[cpu] = NULL; acpi_io_data[cpu] = NULL;
return_VALUE(result); return_VALUE(result);
} }
...@@ -324,14 +324,15 @@ static int ...@@ -324,14 +324,15 @@ static int
acpi_cpufreq_cpu_exit ( acpi_cpufreq_cpu_exit (
struct cpufreq_policy *policy) struct cpufreq_policy *policy)
{ {
struct acpi_processor_performance *perf = performance[policy->cpu]; struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
ACPI_FUNCTION_TRACE("acpi_cpufreq_cpu_exit"); ACPI_FUNCTION_TRACE("acpi_cpufreq_cpu_exit");
if (perf) { if (data) {
performance[policy->cpu] = NULL; acpi_io_data[policy->cpu] = NULL;
acpi_processor_unregister_performance(perf, policy->cpu); acpi_processor_unregister_performance(&data->acpi_data, policy->cpu);
kfree(perf); kfree(data);
} }
return_VALUE(0); return_VALUE(0);
......
...@@ -871,7 +871,6 @@ acpi_processor_get_performance_control ( ...@@ -871,7 +871,6 @@ acpi_processor_get_performance_control (
struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
union acpi_object *pct = NULL; union acpi_object *pct = NULL;
union acpi_object obj = {0}; union acpi_object obj = {0};
struct acpi_pct_register *reg = NULL;
ACPI_FUNCTION_TRACE("acpi_processor_get_performance_control"); ACPI_FUNCTION_TRACE("acpi_processor_get_performance_control");
...@@ -903,19 +902,9 @@ acpi_processor_get_performance_control ( ...@@ -903,19 +902,9 @@ acpi_processor_get_performance_control (
result = -EFAULT; result = -EFAULT;
goto end; goto end;
} }
memcpy(&pr->performance->control_register, obj.buffer.pointer, sizeof(struct acpi_pct_register));
reg = (struct acpi_pct_register *) (obj.buffer.pointer);
if (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Unsupported address space [%d] (control_register)\n",
(u32) reg->space_id));
result = -EFAULT;
goto end;
}
pr->performance->control_register = (u16) reg->address;
pr->performance->control_register_bit_width = reg->bit_width;
/* /*
* status_register * status_register
*/ */
...@@ -931,23 +920,7 @@ acpi_processor_get_performance_control ( ...@@ -931,23 +920,7 @@ acpi_processor_get_performance_control (
goto end; goto end;
} }
reg = (struct acpi_pct_register *) (obj.buffer.pointer); memcpy(&pr->performance->status_register, obj.buffer.pointer, sizeof(struct acpi_pct_register));
if (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Unsupported address space [%d] (status_register)\n",
(u32) reg->space_id));
result = -EFAULT;
goto end;
}
pr->performance->status_register = (u16) reg->address;
pr->performance->status_register_bit_width = reg->bit_width;
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"control_register[0x%04x] status_register[0x%04x]\n",
pr->performance->control_register,
pr->performance->status_register));
end: end:
acpi_os_free(buffer.pointer); acpi_os_free(buffer.pointer);
......
...@@ -68,15 +68,12 @@ struct acpi_processor_px { ...@@ -68,15 +68,12 @@ struct acpi_processor_px {
}; };
struct acpi_processor_performance { struct acpi_processor_performance {
int state; unsigned int state;
int platform_limit; unsigned int platform_limit;
u16 control_register; struct acpi_pct_register control_register;
u16 status_register; struct acpi_pct_register status_register;
u8 control_register_bit_width; unsigned int state_count;
u8 status_register_bit_width;
int state_count;
struct acpi_processor_px states[ACPI_PROCESSOR_MAX_PERFORMANCE]; struct acpi_processor_px states[ACPI_PROCESSOR_MAX_PERFORMANCE];
struct cpufreq_frequency_table freq_table[ACPI_PROCESSOR_MAX_PERFORMANCE];
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment