diff options
Diffstat (limited to 'drivers/acpi/processor_perflib.c')
| -rw-r--r-- | drivers/acpi/processor_perflib.c | 100 | 
1 files changed, 38 insertions, 62 deletions
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index ee87cb6f6e59..2261713d1aec 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -50,57 +50,13 @@ module_param(ignore_ppc, int, 0644);  MODULE_PARM_DESC(ignore_ppc, "If the frequency of your machine gets wrongly" \  		 "limited by BIOS, this should help"); -#define PPC_REGISTERED   1 -#define PPC_IN_USE       2 - -static int acpi_processor_ppc_status; - -static int acpi_processor_ppc_notifier(struct notifier_block *nb, -				       unsigned long event, void *data) -{ -	struct cpufreq_policy *policy = data; -	struct acpi_processor *pr; -	unsigned int ppc = 0; - -	if (ignore_ppc < 0) -		ignore_ppc = 0; - -	if (ignore_ppc) -		return 0; - -	if (event != CPUFREQ_ADJUST) -		return 0; - -	mutex_lock(&performance_mutex); - -	pr = per_cpu(processors, policy->cpu); -	if (!pr || !pr->performance) -		goto out; - -	ppc = (unsigned int)pr->performance_platform_limit; - -	if (ppc >= pr->performance->state_count) -		goto out; - -	cpufreq_verify_within_limits(policy, 0, -				     pr->performance->states[ppc]. -				     core_frequency * 1000); - -      out: -	mutex_unlock(&performance_mutex); - -	return 0; -} - -static struct notifier_block acpi_ppc_notifier_block = { -	.notifier_call = acpi_processor_ppc_notifier, -}; +static bool acpi_processor_ppc_in_use;  static int acpi_processor_get_platform_limit(struct acpi_processor *pr)  {  	acpi_status status = 0;  	unsigned long long ppc = 0; - +	int ret;  	if (!pr)  		return -EINVAL; @@ -112,7 +68,7 @@ static int acpi_processor_get_platform_limit(struct acpi_processor *pr)  	status = acpi_evaluate_integer(pr->handle, "_PPC", NULL, &ppc);  	if (status != AE_NOT_FOUND) -		acpi_processor_ppc_status |= PPC_IN_USE; +		acpi_processor_ppc_in_use = true;  	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {  		ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PPC")); @@ -124,6 +80,17 @@ static int acpi_processor_get_platform_limit(struct acpi_processor *pr)  	pr->performance_platform_limit = (int)ppc; +	if (ppc >= pr->performance->state_count || +	    unlikely(!dev_pm_qos_request_active(&pr->perflib_req))) +		return 0; + +	ret = dev_pm_qos_update_request(&pr->perflib_req, +			pr->performance->states[ppc].core_frequency * 1000); +	if (ret < 0) { +		pr_warn("Failed to update perflib freq constraint: CPU%d (%d)\n", +			pr->id, ret); +	} +  	return 0;  } @@ -184,23 +151,32 @@ int acpi_processor_get_bios_limit(int cpu, unsigned int *limit)  }  EXPORT_SYMBOL(acpi_processor_get_bios_limit); -void acpi_processor_ppc_init(void) +void acpi_processor_ignore_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"); +	if (ignore_ppc < 0) +		ignore_ppc = 0; +} + +void acpi_processor_ppc_init(int cpu) +{ +	struct acpi_processor *pr = per_cpu(processors, cpu); +	int ret; + +	ret = dev_pm_qos_add_request(get_cpu_device(cpu), +				     &pr->perflib_req, DEV_PM_QOS_MAX_FREQUENCY, +				     INT_MAX); +	if (ret < 0) { +		pr_err("Failed to add freq constraint for CPU%d (%d)\n", cpu, +		       ret); +		return; +	}  } -void acpi_processor_ppc_exit(void) +void acpi_processor_ppc_exit(int cpu)  { -	if (acpi_processor_ppc_status & PPC_REGISTERED) -		cpufreq_unregister_notifier(&acpi_ppc_notifier_block, -					    CPUFREQ_POLICY_NOTIFIER); +	struct acpi_processor *pr = per_cpu(processors, cpu); -	acpi_processor_ppc_status &= ~PPC_REGISTERED; +	dev_pm_qos_remove_request(&pr->perflib_req);  }  static int acpi_processor_get_performance_control(struct acpi_processor *pr) @@ -477,7 +453,7 @@ int acpi_processor_notify_smm(struct module *calling_module)  	static int is_done = 0;  	int result; -	if (!(acpi_processor_ppc_status & PPC_REGISTERED)) +	if (!acpi_processor_cpufreq_init)  		return -EBUSY;  	if (!try_module_get(calling_module)) @@ -513,7 +489,7 @@ int acpi_processor_notify_smm(struct module *calling_module)  	 * we can allow the cpufreq driver to be rmmod'ed. */  	is_done = 1; -	if (!(acpi_processor_ppc_status & PPC_IN_USE)) +	if (!acpi_processor_ppc_in_use)  		module_put(calling_module);  	return 0; @@ -742,7 +718,7 @@ acpi_processor_register_performance(struct acpi_processor_performance  {  	struct acpi_processor *pr; -	if (!(acpi_processor_ppc_status & PPC_REGISTERED)) +	if (!acpi_processor_cpufreq_init)  		return -EINVAL;  	mutex_lock(&performance_mutex);  |