diff options
Diffstat (limited to 'drivers/acpi/cppc_acpi.c')
| -rw-r--r-- | drivers/acpi/cppc_acpi.c | 45 | 
1 files changed, 45 insertions, 0 deletions
diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c index 1e15a9f25ae9..093675b1a1ff 100644 --- a/drivers/acpi/cppc_acpi.c +++ b/drivers/acpi/cppc_acpi.c @@ -424,6 +424,9 @@ bool acpi_cpc_valid(void)  	struct cpc_desc *cpc_ptr;  	int cpu; +	if (acpi_disabled) +		return false; +  	for_each_present_cpu(cpu) {  		cpc_ptr = per_cpu(cpc_desc_ptr, cpu);  		if (!cpc_ptr) @@ -1241,6 +1244,48 @@ out_err:  EXPORT_SYMBOL_GPL(cppc_get_perf_caps);  /** + * cppc_perf_ctrs_in_pcc - Check if any perf counters are in a PCC region. + * + * CPPC has flexibility about how CPU performance counters are accessed. + * One of the choices is PCC regions, which can have a high access latency. This + * routine allows callers of cppc_get_perf_ctrs() to know this ahead of time. + * + * Return: true if any of the counters are in PCC regions, false otherwise + */ +bool cppc_perf_ctrs_in_pcc(void) +{ +	int cpu; + +	for_each_present_cpu(cpu) { +		struct cpc_register_resource *ref_perf_reg; +		struct cpc_desc *cpc_desc; + +		cpc_desc = per_cpu(cpc_desc_ptr, cpu); + +		if (CPC_IN_PCC(&cpc_desc->cpc_regs[DELIVERED_CTR]) || +		    CPC_IN_PCC(&cpc_desc->cpc_regs[REFERENCE_CTR]) || +		    CPC_IN_PCC(&cpc_desc->cpc_regs[CTR_WRAP_TIME])) +			return true; + + +		ref_perf_reg = &cpc_desc->cpc_regs[REFERENCE_PERF]; + +		/* +		 * If reference perf register is not supported then we should +		 * use the nominal perf value +		 */ +		if (!CPC_SUPPORTED(ref_perf_reg)) +			ref_perf_reg = &cpc_desc->cpc_regs[NOMINAL_PERF]; + +		if (CPC_IN_PCC(ref_perf_reg)) +			return true; +	} + +	return false; +} +EXPORT_SYMBOL_GPL(cppc_perf_ctrs_in_pcc); + +/**   * cppc_get_perf_ctrs - Read a CPU's performance feedback counters.   * @cpunum: CPU from which to read counters.   * @perf_fb_ctrs: ptr to cppc_perf_fb_ctrs. See cppc_acpi.h  |