X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Facpi%2Fprocessor_perflib.c;h=cbb6f0814ce2dc706cb6b85e7ab3ae96b5d23e2e;hb=refs%2Fheads%2Fvserver;hp=a9a1a8fe319939029976cb168f66e33d68b8effe;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index a9a1a8fe3..cbb6f0814 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -26,7 +26,6 @@ * */ - #include #include #include @@ -35,6 +34,7 @@ #ifdef CONFIG_X86_ACPI_CPUFREQ_PROC_INTF #include #include +#include #include #endif @@ -42,16 +42,14 @@ #include #include - #define ACPI_PROCESSOR_COMPONENT 0x01000000 #define ACPI_PROCESSOR_CLASS "processor" #define ACPI_PROCESSOR_DRIVER_NAME "ACPI Processor Driver" #define ACPI_PROCESSOR_FILE_PERFORMANCE "performance" #define _COMPONENT ACPI_PROCESSOR_COMPONENT -ACPI_MODULE_NAME ("acpi_processor") +ACPI_MODULE_NAME("acpi_processor") - -static DECLARE_MUTEX(performance_sem); +static DEFINE_MUTEX(performance_mutex); /* * _PPC support is implemented as a CPUfreq policy notifier: @@ -69,14 +67,13 @@ static DECLARE_MUTEX(performance_sem); static int acpi_processor_ppc_status = 0; static int acpi_processor_ppc_notifier(struct notifier_block *nb, - unsigned long event, - void *data) + unsigned long event, void *data) { struct cpufreq_policy *policy = data; struct acpi_processor *pr; unsigned int ppc = 0; - down(&performance_sem); + mutex_lock(&performance_mutex); if (event != CPUFREQ_INCOMPATIBLE) goto out; @@ -85,39 +82,33 @@ static int acpi_processor_ppc_notifier(struct notifier_block *nb, if (!pr || !pr->performance) goto out; - ppc = (unsigned int) pr->performance_platform_limit; - if (!ppc) - goto out; + ppc = (unsigned int)pr->performance_platform_limit; - if (ppc > pr->performance->state_count) + if (ppc >= pr->performance->state_count) goto out; cpufreq_verify_within_limits(policy, 0, - pr->performance->states[ppc].core_frequency * 1000); + pr->performance->states[ppc]. + core_frequency * 1000); - out: - up(&performance_sem); + out: + mutex_unlock(&performance_mutex); return 0; } - static struct notifier_block acpi_ppc_notifier_block = { .notifier_call = acpi_processor_ppc_notifier, }; - -static int -acpi_processor_get_platform_limit ( - struct acpi_processor* pr) +static int acpi_processor_get_platform_limit(struct acpi_processor *pr) { - acpi_status status = 0; - unsigned long ppc = 0; + acpi_status status = 0; + unsigned long ppc = 0; - ACPI_FUNCTION_TRACE("acpi_processor_get_platform_limit"); if (!pr) - return_VALUE(-EINVAL); + return -EINVAL; /* * _PPC indicates the maximum state currently supported by the platform @@ -128,19 +119,17 @@ acpi_processor_get_platform_limit ( if (status != AE_NOT_FOUND) acpi_processor_ppc_status |= PPC_IN_USE; - if(ACPI_FAILURE(status) && status != AE_NOT_FOUND) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PPC\n")); - return_VALUE(-ENODEV); + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { + ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PPC")); + return -ENODEV; } - pr->performance_platform_limit = (int) ppc; + pr->performance_platform_limit = (int)ppc; - return_VALUE(0); + return 0; } - -int acpi_processor_ppc_has_changed( - struct acpi_processor *pr) +int acpi_processor_ppc_has_changed(struct acpi_processor *pr) { int ret = acpi_processor_get_platform_limit(pr); if (ret < 0) @@ -149,76 +138,44 @@ int acpi_processor_ppc_has_changed( return cpufreq_update_policy(pr->id); } - -void acpi_processor_ppc_init(void) { - if (!cpufreq_register_notifier(&acpi_ppc_notifier_block, CPUFREQ_POLICY_NOTIFIER)) +void acpi_processor_ppc_init(void) +{ + if (!cpufreq_register_notifier + (&acpi_ppc_notifier_block, CPUFREQ_POLICY_NOTIFIER)) acpi_processor_ppc_status |= PPC_REGISTERED; else - printk(KERN_DEBUG "Warning: Processor Platform Limit not supported.\n"); + printk(KERN_DEBUG + "Warning: Processor Platform Limit not supported.\n"); } - -void acpi_processor_ppc_exit(void) { +void acpi_processor_ppc_exit(void) +{ if (acpi_processor_ppc_status & PPC_REGISTERED) - cpufreq_unregister_notifier(&acpi_ppc_notifier_block, CPUFREQ_POLICY_NOTIFIER); + cpufreq_unregister_notifier(&acpi_ppc_notifier_block, + CPUFREQ_POLICY_NOTIFIER); acpi_processor_ppc_status &= ~PPC_REGISTERED; } -/* - * when registering a cpufreq driver with this ACPI processor driver, the - * _PCT and _PSS structures are read out and written into struct - * acpi_processor_performance. - */ -static int acpi_processor_set_pdc (struct acpi_processor *pr) -{ - acpi_status status = AE_OK; - u32 arg0_buf[3]; - union acpi_object arg0 = {ACPI_TYPE_BUFFER}; - struct acpi_object_list no_object = {1, &arg0}; - struct acpi_object_list *pdc; - - ACPI_FUNCTION_TRACE("acpi_processor_set_pdc"); - - arg0.buffer.length = 12; - arg0.buffer.pointer = (u8 *) arg0_buf; - arg0_buf[0] = ACPI_PDC_REVISION_ID; - arg0_buf[1] = 0; - arg0_buf[2] = 0; - - pdc = (pr->performance->pdc) ? pr->performance->pdc : &no_object; - - status = acpi_evaluate_object(pr->handle, "_PDC", pdc, NULL); - - if ((ACPI_FAILURE(status)) && (pr->performance->pdc)) - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Error evaluating _PDC, using legacy perf. control...\n")); - - return_VALUE(status); -} - - -static int -acpi_processor_get_performance_control ( - struct acpi_processor *pr) +static int acpi_processor_get_performance_control(struct acpi_processor *pr) { - int result = 0; - acpi_status status = 0; - struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; - union acpi_object *pct = NULL; - union acpi_object obj = {0}; + int result = 0; + acpi_status status = 0; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object *pct = NULL; + union acpi_object obj = { 0 }; - ACPI_FUNCTION_TRACE("acpi_processor_get_performance_control"); status = acpi_evaluate_object(pr->handle, "_PCT", NULL, &buffer); - if(ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PCT\n")); - return_VALUE(-ENODEV); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PCT")); + return -ENODEV; } - pct = (union acpi_object *) buffer.pointer; + pct = (union acpi_object *)buffer.pointer; if (!pct || (pct->type != ACPI_TYPE_PACKAGE) - || (pct->package.count != 2)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PCT data\n")); + || (pct->package.count != 2)) { + printk(KERN_ERR PREFIX "Invalid _PCT data\n"); result = -EFAULT; goto end; } @@ -230,15 +187,14 @@ acpi_processor_get_performance_control ( obj = pct->package.elements[0]; if ((obj.type != ACPI_TYPE_BUFFER) - || (obj.buffer.length < sizeof(struct acpi_pct_register)) - || (obj.buffer.pointer == NULL)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Invalid _PCT data (control_register)\n")); + || (obj.buffer.length < sizeof(struct acpi_pct_register)) + || (obj.buffer.pointer == NULL)) { + printk(KERN_ERR PREFIX "Invalid _PCT data (control_register)\n"); result = -EFAULT; goto end; } - memcpy(&pr->performance->control_register, obj.buffer.pointer, sizeof(struct acpi_pct_register)); - + memcpy(&pr->performance->control_register, obj.buffer.pointer, + sizeof(struct acpi_pct_register)); /* * status_register @@ -247,55 +203,53 @@ acpi_processor_get_performance_control ( obj = pct->package.elements[1]; if ((obj.type != ACPI_TYPE_BUFFER) - || (obj.buffer.length < sizeof(struct acpi_pct_register)) - || (obj.buffer.pointer == NULL)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Invalid _PCT data (status_register)\n")); + || (obj.buffer.length < sizeof(struct acpi_pct_register)) + || (obj.buffer.pointer == NULL)) { + printk(KERN_ERR PREFIX "Invalid _PCT data (status_register)\n"); result = -EFAULT; goto end; } - memcpy(&pr->performance->status_register, obj.buffer.pointer, sizeof(struct acpi_pct_register)); + memcpy(&pr->performance->status_register, obj.buffer.pointer, + sizeof(struct acpi_pct_register)); -end: - acpi_os_free(buffer.pointer); + end: + kfree(buffer.pointer); - return_VALUE(result); + return result; } - -static int -acpi_processor_get_performance_states ( - struct acpi_processor *pr) +static int acpi_processor_get_performance_states(struct acpi_processor *pr) { - int result = 0; - acpi_status status = AE_OK; - struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; - struct acpi_buffer format = {sizeof("NNNNNN"), "NNNNNN"}; - struct acpi_buffer state = {0, NULL}; - union acpi_object *pss = NULL; - int i; + int result = 0; + acpi_status status = AE_OK; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + struct acpi_buffer format = { sizeof("NNNNNN"), "NNNNNN" }; + struct acpi_buffer state = { 0, NULL }; + union acpi_object *pss = NULL; + int i; - ACPI_FUNCTION_TRACE("acpi_processor_get_performance_states"); status = acpi_evaluate_object(pr->handle, "_PSS", NULL, &buffer); - if(ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PSS\n")); - return_VALUE(-ENODEV); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PSS")); + return -ENODEV; } - pss = (union acpi_object *) buffer.pointer; + pss = buffer.pointer; if (!pss || (pss->type != ACPI_TYPE_PACKAGE)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSS data\n")); + printk(KERN_ERR PREFIX "Invalid _PSS data\n"); result = -EFAULT; goto end; } ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d performance states\n", - pss->package.count)); + pss->package.count)); pr->performance->state_count = pss->package.count; - pr->performance->states = kmalloc(sizeof(struct acpi_processor_px) * pss->package.count, GFP_KERNEL); + pr->performance->states = + kmalloc(sizeof(struct acpi_processor_px) * pss->package.count, + GFP_KERNEL); if (!pr->performance->states) { result = -ENOMEM; goto end; @@ -311,88 +265,77 @@ acpi_processor_get_performance_states ( ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Extracting state %d\n", i)); status = acpi_extract_package(&(pss->package.elements[i]), - &format, &state); + &format, &state); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSS data\n")); + ACPI_EXCEPTION((AE_INFO, status, "Invalid _PSS data")); result = -EFAULT; kfree(pr->performance->states); goto end; } ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "State [%d]: core_frequency[%d] power[%d] transition_latency[%d] bus_master_latency[%d] control[0x%x] status[0x%x]\n", - i, - (u32) px->core_frequency, - (u32) px->power, - (u32) px->transition_latency, - (u32) px->bus_master_latency, - (u32) px->control, - (u32) px->status)); + "State [%d]: core_frequency[%d] power[%d] transition_latency[%d] bus_master_latency[%d] control[0x%x] status[0x%x]\n", + i, + (u32) px->core_frequency, + (u32) px->power, + (u32) px->transition_latency, + (u32) px->bus_master_latency, + (u32) px->control, (u32) px->status)); if (!px->core_frequency) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSS data: freq is zero\n")); + printk(KERN_ERR PREFIX + "Invalid _PSS data: freq is zero\n"); result = -EFAULT; kfree(pr->performance->states); goto end; } } -end: - acpi_os_free(buffer.pointer); + end: + kfree(buffer.pointer); - return_VALUE(result); + return result; } - -static int -acpi_processor_get_performance_info ( - struct acpi_processor *pr) +static int acpi_processor_get_performance_info(struct acpi_processor *pr) { - int result = 0; - acpi_status status = AE_OK; - acpi_handle handle = NULL; + int result = 0; + acpi_status status = AE_OK; + acpi_handle handle = NULL; - ACPI_FUNCTION_TRACE("acpi_processor_get_performance_info"); if (!pr || !pr->performance || !pr->handle) - return_VALUE(-EINVAL); - - acpi_processor_set_pdc(pr); + return -EINVAL; status = acpi_get_handle(pr->handle, "_PCT", &handle); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "ACPI-based processor performance control unavailable\n")); - return_VALUE(-ENODEV); + "ACPI-based processor performance control unavailable\n")); + return -ENODEV; } result = acpi_processor_get_performance_control(pr); if (result) - return_VALUE(result); + return result; result = acpi_processor_get_performance_states(pr); if (result) - return_VALUE(result); - - result = acpi_processor_get_platform_limit(pr); - if (result) - return_VALUE(result); + return result; - return_VALUE(0); + return 0; } +int acpi_processor_notify_smm(struct module *calling_module) +{ + acpi_status status; + static int is_done = 0; -int acpi_processor_notify_smm(struct module *calling_module) { - acpi_status status; - static int is_done = 0; - - ACPI_FUNCTION_TRACE("acpi_processor_notify_smm"); if (!(acpi_processor_ppc_status & PPC_REGISTERED)) - return_VALUE(-EBUSY); + return -EBUSY; if (!try_module_get(calling_module)) - return_VALUE(-EINVAL); + return -EINVAL; /* is_done is set to negative if an error occured, * and to postitive if _no_ error occured, but SMM @@ -401,40 +344,41 @@ int acpi_processor_notify_smm(struct module *calling_module) { */ if (is_done > 0) { module_put(calling_module); - return_VALUE(0); - } - else if (is_done < 0) { + return 0; + } else if (is_done < 0) { module_put(calling_module); - return_VALUE(is_done); + return is_done; } is_done = -EIO; /* Can't write pstate_cnt to smi_cmd if either value is zero */ - if ((!acpi_fadt.smi_cmd) || - (!acpi_fadt.pstate_cnt)) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "No SMI port or pstate_cnt\n")); + if ((!acpi_fadt.smi_cmd) || (!acpi_fadt.pstate_cnt)) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No SMI port or pstate_cnt\n")); module_put(calling_module); - return_VALUE(0); + return 0; } - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Writing pstate_cnt [0x%x] to smi_cmd [0x%x]\n", acpi_fadt.pstate_cnt, acpi_fadt.smi_cmd)); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Writing pstate_cnt [0x%x] to smi_cmd [0x%x]\n", + acpi_fadt.pstate_cnt, acpi_fadt.smi_cmd)); /* FADT v1 doesn't support pstate_cnt, many BIOS vendors use * it anyway, so we need to support it... */ if (acpi_fadt_is_v1) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Using v1.0 FADT reserved value for pstate_cnt\n")); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Using v1.0 FADT reserved value for pstate_cnt\n")); } - status = acpi_os_write_port (acpi_fadt.smi_cmd, - (u32) acpi_fadt.pstate_cnt, 8); - if (ACPI_FAILURE (status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Failed to write pstate_cnt [0x%x] to " - "smi_cmd [0x%x]\n", acpi_fadt.pstate_cnt, acpi_fadt.smi_cmd)); + status = acpi_os_write_port(acpi_fadt.smi_cmd, + (u32) acpi_fadt.pstate_cnt, 8); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Failed to write pstate_cnt [0x%x] to " + "smi_cmd [0x%x]", acpi_fadt.pstate_cnt, + acpi_fadt.smi_cmd)); module_put(calling_module); - return_VALUE(status); + return status; } /* Success. If there's no _PPC, we need to fear nothing, so @@ -444,28 +388,27 @@ int acpi_processor_notify_smm(struct module *calling_module) { if (!(acpi_processor_ppc_status & PPC_IN_USE)) module_put(calling_module); - return_VALUE(0); + return 0; } -EXPORT_SYMBOL(acpi_processor_notify_smm); +EXPORT_SYMBOL(acpi_processor_notify_smm); #ifdef CONFIG_X86_ACPI_CPUFREQ_PROC_INTF /* /proc/acpi/processor/../performance interface (DEPRECATED) */ static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file); static struct file_operations acpi_processor_perf_fops = { - .open = acpi_processor_perf_open_fs, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, + .open = acpi_processor_perf_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, }; static int acpi_processor_perf_seq_show(struct seq_file *seq, void *offset) { - struct acpi_processor *pr = (struct acpi_processor *)seq->private; - int i; + struct acpi_processor *pr = seq->private; + int i; - ACPI_FUNCTION_TRACE("acpi_processor_perf_seq_show"); if (!pr) goto end; @@ -476,60 +419,57 @@ static int acpi_processor_perf_seq_show(struct seq_file *seq, void *offset) } seq_printf(seq, "state count: %d\n" - "active state: P%d\n", - pr->performance->state_count, - pr->performance->state); + "active state: P%d\n", + pr->performance->state_count, pr->performance->state); seq_puts(seq, "states:\n"); for (i = 0; i < pr->performance->state_count; i++) - seq_printf(seq, " %cP%d: %d MHz, %d mW, %d uS\n", - (i == pr->performance->state?'*':' '), i, - (u32) pr->performance->states[i].core_frequency, - (u32) pr->performance->states[i].power, - (u32) pr->performance->states[i].transition_latency); - -end: - return_VALUE(0); + seq_printf(seq, + " %cP%d: %d MHz, %d mW, %d uS\n", + (i == pr->performance->state ? '*' : ' '), i, + (u32) pr->performance->states[i].core_frequency, + (u32) pr->performance->states[i].power, + (u32) pr->performance->states[i].transition_latency); + + end: + return 0; } static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file) { return single_open(file, acpi_processor_perf_seq_show, - PDE(inode)->data); + PDE(inode)->data); } static ssize_t -acpi_processor_write_performance ( - struct file *file, - const char __user *buffer, - size_t count, - loff_t *data) +acpi_processor_write_performance(struct file *file, + const char __user * buffer, + size_t count, loff_t * data) { - int result = 0; - struct seq_file *m = (struct seq_file *) file->private_data; - struct acpi_processor *pr = (struct acpi_processor *) m->private; + int result = 0; + struct seq_file *m = file->private_data; + struct acpi_processor *pr = m->private; struct acpi_processor_performance *perf; - char state_string[12] = {'\0'}; - unsigned int new_state = 0; - struct cpufreq_policy policy; + char state_string[12] = { '\0' }; + unsigned int new_state = 0; + struct cpufreq_policy policy; - ACPI_FUNCTION_TRACE("acpi_processor_write_performance"); if (!pr || (count > sizeof(state_string) - 1)) - return_VALUE(-EINVAL); + return -EINVAL; perf = pr->performance; if (!perf) - return_VALUE(-EINVAL); + return -EINVAL; if (copy_from_user(state_string, buffer, count)) - return_VALUE(-EFAULT); + return -EFAULT; state_string[count] = '\0'; new_state = simple_strtoul(state_string, NULL, 0); if (new_state >= perf->state_count) - return_VALUE(-EINVAL); + return -EINVAL; cpufreq_get_policy(&policy, pr->id); @@ -539,128 +479,344 @@ acpi_processor_write_performance ( result = cpufreq_set_policy(&policy); if (result) - return_VALUE(result); + return result; - return_VALUE(count); + return count; } -static void -acpi_cpufreq_add_file ( - struct acpi_processor *pr) +static void acpi_cpufreq_add_file(struct acpi_processor *pr) { - struct proc_dir_entry *entry = NULL; - struct acpi_device *device = NULL; + struct proc_dir_entry *entry = NULL; + struct acpi_device *device = NULL; - ACPI_FUNCTION_TRACE("acpi_cpufreq_addfile"); if (acpi_bus_get_device(pr->handle, &device)) - return_VOID; + return; /* add file 'performance' [R/W] */ entry = create_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE, - S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device)); - if (!entry) - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Unable to create '%s' fs entry\n", - ACPI_PROCESSOR_FILE_PERFORMANCE)); - else { + S_IFREG | S_IRUGO | S_IWUSR, + acpi_device_dir(device)); + if (entry){ + acpi_processor_perf_fops.write = acpi_processor_write_performance; entry->proc_fops = &acpi_processor_perf_fops; - entry->proc_fops->write = acpi_processor_write_performance; entry->data = acpi_driver_data(device); entry->owner = THIS_MODULE; } - return_VOID; + return; } -static void -acpi_cpufreq_remove_file ( - struct acpi_processor *pr) +static void acpi_cpufreq_remove_file(struct acpi_processor *pr) { - struct acpi_device *device = NULL; + struct acpi_device *device = NULL; - ACPI_FUNCTION_TRACE("acpi_cpufreq_addfile"); if (acpi_bus_get_device(pr->handle, &device)) - return_VOID; + return; /* remove file 'performance' */ remove_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE, - acpi_device_dir(device)); + acpi_device_dir(device)); - return_VOID; + return; } #else -static void acpi_cpufreq_add_file (struct acpi_processor *pr) { return; } -static void acpi_cpufreq_remove_file (struct acpi_processor *pr) { return; } -#endif /* CONFIG_X86_ACPI_CPUFREQ_PROC_INTF */ +static void acpi_cpufreq_add_file(struct acpi_processor *pr) +{ + return; +} +static void acpi_cpufreq_remove_file(struct acpi_processor *pr) +{ + return; +} +#endif /* CONFIG_X86_ACPI_CPUFREQ_PROC_INTF */ + +static int acpi_processor_get_psd(struct acpi_processor *pr) +{ + int result = 0; + acpi_status status = AE_OK; + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + struct acpi_buffer format = {sizeof("NNNNN"), "NNNNN"}; + struct acpi_buffer state = {0, NULL}; + union acpi_object *psd = NULL; + struct acpi_psd_package *pdomain; + + status = acpi_evaluate_object(pr->handle, "_PSD", NULL, &buffer); + if (ACPI_FAILURE(status)) { + return -ENODEV; + } + + psd = buffer.pointer; + if (!psd || (psd->type != ACPI_TYPE_PACKAGE)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n")); + result = -EFAULT; + goto end; + } + + if (psd->package.count != 1) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n")); + result = -EFAULT; + goto end; + } + + pdomain = &(pr->performance->domain_info); + + state.length = sizeof(struct acpi_psd_package); + state.pointer = pdomain; + + status = acpi_extract_package(&(psd->package.elements[0]), + &format, &state); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n")); + result = -EFAULT; + goto end; + } + + if (pdomain->num_entries != ACPI_PSD_REV0_ENTRIES) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _PSD:num_entries\n")); + result = -EFAULT; + goto end; + } + + if (pdomain->revision != ACPI_PSD_REV0_REVISION) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _PSD:revision\n")); + result = -EFAULT; + goto end; + } + +end: + kfree(buffer.pointer); + return result; +} + +int acpi_processor_preregister_performance( + struct acpi_processor_performance **performance) +{ + int count, count_target; + int retval = 0; + unsigned int i, j; + cpumask_t covered_cpus; + struct acpi_processor *pr; + struct acpi_psd_package *pdomain; + struct acpi_processor *match_pr; + struct acpi_psd_package *match_pdomain; + + mutex_lock(&performance_mutex); + + retval = 0; + + /* Call _PSD for all CPUs */ + for_each_possible_cpu(i) { + pr = processors[i]; + if (!pr) { + /* Look only at processors in ACPI namespace */ + continue; + } + + if (pr->performance) { + retval = -EBUSY; + continue; + } + + if (!performance || !performance[i]) { + retval = -EINVAL; + continue; + } + + pr->performance = performance[i]; + cpu_set(i, pr->performance->shared_cpu_map); + if (acpi_processor_get_psd(pr)) { + retval = -EINVAL; + continue; + } + } + if (retval) + goto err_ret; + + /* + * 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]; + if (!pr) + continue; + + if (cpu_isset(i, covered_cpus)) + continue; + + pdomain = &(pr->performance->domain_info); + cpu_set(i, pr->performance->shared_cpu_map); + cpu_set(i, covered_cpus); + if (pdomain->num_processors <= 1) + continue; + + /* Validate the Domain info */ + count_target = pdomain->num_processors; + count = 1; + if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ALL) + pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ALL; + else if (pdomain->coord_type == DOMAIN_COORD_TYPE_HW_ALL) + pr->performance->shared_type = CPUFREQ_SHARED_TYPE_HW; + else if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ANY) + pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ANY; + + for_each_possible_cpu(j) { + if (i == j) + continue; + + match_pr = processors[j]; + if (!match_pr) + continue; + + match_pdomain = &(match_pr->performance->domain_info); + if (match_pdomain->domain != pdomain->domain) + continue; + + /* Here i and j are in the same domain */ + + if (match_pdomain->num_processors != count_target) { + retval = -EINVAL; + goto err_ret; + } + + if (pdomain->coord_type != match_pdomain->coord_type) { + retval = -EINVAL; + goto err_ret; + } + + cpu_set(j, covered_cpus); + cpu_set(j, pr->performance->shared_cpu_map); + count++; + } + + for_each_possible_cpu(j) { + if (i == j) + continue; + + match_pr = processors[j]; + if (!match_pr) + continue; + + match_pdomain = &(match_pr->performance->domain_info); + if (match_pdomain->domain != pdomain->domain) + continue; + + match_pr->performance->shared_type = + pr->performance->shared_type; + match_pr->performance->shared_cpu_map = + pr->performance->shared_cpu_map; + } + } + +err_ret: + for_each_possible_cpu(i) { + pr = processors[i]; + if (!pr || !pr->performance) + continue; + + /* Assume no coordination on any error parsing domain info */ + if (retval) { + cpus_clear(pr->performance->shared_cpu_map); + cpu_set(i, pr->performance->shared_cpu_map); + pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ALL; + } + pr->performance = NULL; /* Will be set for real in register */ + } + + mutex_unlock(&performance_mutex); + return retval; +} +EXPORT_SYMBOL(acpi_processor_preregister_performance); int -acpi_processor_register_performance ( - struct acpi_processor_performance * performance, - unsigned int cpu) +acpi_processor_register_performance(struct acpi_processor_performance + *performance, unsigned int cpu) { struct acpi_processor *pr; - ACPI_FUNCTION_TRACE("acpi_processor_register_performance"); if (!(acpi_processor_ppc_status & PPC_REGISTERED)) - return_VALUE(-EINVAL); + return -EINVAL; - down(&performance_sem); + mutex_lock(&performance_mutex); pr = processors[cpu]; if (!pr) { - up(&performance_sem); - return_VALUE(-ENODEV); + mutex_unlock(&performance_mutex); + return -ENODEV; } if (pr->performance) { - up(&performance_sem); - return_VALUE(-EBUSY); + mutex_unlock(&performance_mutex); + return -EBUSY; } + WARN_ON(!performance); + pr->performance = performance; if (acpi_processor_get_performance_info(pr)) { pr->performance = NULL; - up(&performance_sem); - return_VALUE(-EIO); + mutex_unlock(&performance_mutex); + return -EIO; } acpi_cpufreq_add_file(pr); - up(&performance_sem); - return_VALUE(0); + mutex_unlock(&performance_mutex); + return 0; } -EXPORT_SYMBOL(acpi_processor_register_performance); +EXPORT_SYMBOL(acpi_processor_register_performance); void -acpi_processor_unregister_performance ( - struct acpi_processor_performance * performance, - unsigned int cpu) +acpi_processor_unregister_performance(struct acpi_processor_performance + *performance, unsigned int cpu) { struct acpi_processor *pr; - ACPI_FUNCTION_TRACE("acpi_processor_unregister_performance"); - down(&performance_sem); + mutex_lock(&performance_mutex); pr = processors[cpu]; if (!pr) { - up(&performance_sem); - return_VOID; + mutex_unlock(&performance_mutex); + return; } - kfree(pr->performance->states); + if (pr->performance) + kfree(pr->performance->states); pr->performance = NULL; acpi_cpufreq_remove_file(pr); - up(&performance_sem); + mutex_unlock(&performance_mutex); - return_VOID; + return; } + EXPORT_SYMBOL(acpi_processor_unregister_performance);