processor_perflib.c
来自「linux 内核源代码」· C语言 代码 · 共 771 行 · 第 1/2 页
C
771 行
#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,};static int acpi_processor_perf_seq_show(struct seq_file *seq, void *offset){ struct acpi_processor *pr = seq->private; int i; if (!pr) goto end; if (!pr->performance) { seq_puts(seq, "<not supported>\n"); goto end; } seq_printf(seq, "state count: %d\n" "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 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);}static void acpi_cpufreq_add_file(struct acpi_processor *pr){ struct proc_dir_entry *entry = NULL; struct acpi_device *device = NULL; if (acpi_bus_get_device(pr->handle, &device)) return; /* add file 'performance' [R/W] */ entry = create_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE, S_IFREG | S_IRUGO, acpi_device_dir(device)); if (entry){ entry->proc_fops = &acpi_processor_perf_fops; entry->data = acpi_driver_data(device); entry->owner = THIS_MODULE; } return;}static void acpi_cpufreq_remove_file(struct acpi_processor *pr){ struct acpi_device *device = NULL; if (acpi_bus_get_device(pr->handle, &device)) return; /* remove file 'performance' */ remove_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE, acpi_device_dir(device)); return;}#elsestatic 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 || !percpu_ptr(performance, i)) { retval = -EINVAL; continue; } pr->performance = percpu_ptr(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);intacpi_processor_register_performance(struct acpi_processor_performance *performance, unsigned int cpu){ struct acpi_processor *pr; if (!(acpi_processor_ppc_status & PPC_REGISTERED)) return -EINVAL; mutex_lock(&performance_mutex); pr = processors[cpu]; if (!pr) { mutex_unlock(&performance_mutex); return -ENODEV; } if (pr->performance) { mutex_unlock(&performance_mutex); return -EBUSY; } WARN_ON(!performance); pr->performance = performance; if (acpi_processor_get_performance_info(pr)) { pr->performance = NULL; mutex_unlock(&performance_mutex); return -EIO; } acpi_cpufreq_add_file(pr); mutex_unlock(&performance_mutex); return 0;}EXPORT_SYMBOL(acpi_processor_register_performance);voidacpi_processor_unregister_performance(struct acpi_processor_performance *performance, unsigned int cpu){ struct acpi_processor *pr; mutex_lock(&performance_mutex); pr = processors[cpu]; if (!pr) { mutex_unlock(&performance_mutex); return; } if (pr->performance) kfree(pr->performance->states); pr->performance = NULL; acpi_cpufreq_remove_file(pr); mutex_unlock(&performance_mutex); return;}EXPORT_SYMBOL(acpi_processor_unregister_performance);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?