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 + -
显示快捷键?