Commit d0ea59e1 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

cpufreq: intel_pstate: Request P-states control from SMM if needed

Currently, intel_pstate is unable to control P-states on my
IvyBridge-based Acer Aspire S5, because they are controlled by SMM
on that machine by default and it is necessary to request OS control
of P-states from it via the SMI Command register exposed in the ACPI
FADT.  intel_pstate doesn't do that now, but acpi-cpufreq and other
cpufreq drivers for x86 platforms do.

Address this problem by making intel_pstate use the ACPI-defined
mechanism as well.  However, intel_pstate is not modular and it
doesn't need the module refcount tricks played by
acpi_processor_notify_smm(), so export the core of this function
to it as acpi_processor_pstate_control() and make it call that.
[The changes in processor_perflib.c related to this should not
make any functional difference for the acpi_processor_notify_smm()
users].

To be safe, only call acpi_processor_notify_smm() from intel_pstate
if ACPI _PPC support is enabled in it.
Suggested-by: default avatarSrinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: default avatarSrinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
parent f0da898b
...@@ -465,11 +465,33 @@ int acpi_processor_get_performance_info(struct acpi_processor *pr) ...@@ -465,11 +465,33 @@ int acpi_processor_get_performance_info(struct acpi_processor *pr)
return result; return result;
} }
EXPORT_SYMBOL_GPL(acpi_processor_get_performance_info); EXPORT_SYMBOL_GPL(acpi_processor_get_performance_info);
int acpi_processor_notify_smm(struct module *calling_module)
int acpi_processor_pstate_control(void)
{ {
acpi_status status; acpi_status status;
static int is_done = 0;
if (!acpi_gbl_FADT.smi_command || !acpi_gbl_FADT.pstate_control)
return 0;
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Writing pstate_control [0x%x] to smi_command [0x%x]\n",
acpi_gbl_FADT.pstate_control, acpi_gbl_FADT.smi_command));
status = acpi_os_write_port(acpi_gbl_FADT.smi_command,
(u32)acpi_gbl_FADT.pstate_control, 8);
if (ACPI_SUCCESS(status))
return 1;
ACPI_EXCEPTION((AE_INFO, status,
"Failed to write pstate_control [0x%x] to smi_command [0x%x]",
acpi_gbl_FADT.pstate_control, acpi_gbl_FADT.smi_command));
return -EIO;
}
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_ppc_status & PPC_REGISTERED))
return -EBUSY; return -EBUSY;
...@@ -492,26 +514,15 @@ int acpi_processor_notify_smm(struct module *calling_module) ...@@ -492,26 +514,15 @@ int acpi_processor_notify_smm(struct module *calling_module)
is_done = -EIO; is_done = -EIO;
/* Can't write pstate_control to smi_command if either value is zero */ result = acpi_processor_pstate_control();
if ((!acpi_gbl_FADT.smi_command) || (!acpi_gbl_FADT.pstate_control)) { if (!result) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No SMI port or pstate_control\n")); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No SMI port or pstate_control\n"));
module_put(calling_module); module_put(calling_module);
return 0; return 0;
} }
if (result < 0) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Writing pstate_control [0x%x] to smi_command [0x%x]\n",
acpi_gbl_FADT.pstate_control, acpi_gbl_FADT.smi_command));
status = acpi_os_write_port(acpi_gbl_FADT.smi_command,
(u32) acpi_gbl_FADT.pstate_control, 8);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Failed to write pstate_control [0x%x] to "
"smi_command [0x%x]", acpi_gbl_FADT.pstate_control,
acpi_gbl_FADT.smi_command));
module_put(calling_module); module_put(calling_module);
return status; return result;
} }
/* Success. If there's no _PPC, we need to fear nothing, so /* Success. If there's no _PPC, we need to fear nothing, so
......
...@@ -1909,9 +1909,20 @@ static bool __init intel_pstate_platform_pwr_mgmt_exists(void) ...@@ -1909,9 +1909,20 @@ static bool __init intel_pstate_platform_pwr_mgmt_exists(void)
return false; return false;
} }
static void intel_pstate_request_control_from_smm(void)
{
/*
* It may be unsafe to request P-states control from SMM if _PPC support
* has not been enabled.
*/
if (acpi_ppc)
acpi_processor_pstate_control();
}
#else /* CONFIG_ACPI not enabled */ #else /* CONFIG_ACPI not enabled */
static inline bool intel_pstate_platform_pwr_mgmt_exists(void) { return false; } static inline bool intel_pstate_platform_pwr_mgmt_exists(void) { return false; }
static inline bool intel_pstate_has_acpi_ppc(void) { return false; } static inline bool intel_pstate_has_acpi_ppc(void) { return false; }
static inline void intel_pstate_request_control_from_smm(void) {}
#endif /* CONFIG_ACPI */ #endif /* CONFIG_ACPI */
static const struct x86_cpu_id hwp_support_ids[] __initconst = { static const struct x86_cpu_id hwp_support_ids[] __initconst = {
...@@ -1963,6 +1974,8 @@ static int __init intel_pstate_init(void) ...@@ -1963,6 +1974,8 @@ static int __init intel_pstate_init(void)
if (!hwp_active && hwp_only) if (!hwp_active && hwp_only)
goto out; goto out;
intel_pstate_request_control_from_smm();
rc = cpufreq_register_driver(&intel_pstate_driver); rc = cpufreq_register_driver(&intel_pstate_driver);
if (rc) if (rc)
goto out; goto out;
......
...@@ -249,6 +249,7 @@ extern int acpi_processor_register_performance(struct acpi_processor_performance ...@@ -249,6 +249,7 @@ extern int acpi_processor_register_performance(struct acpi_processor_performance
*performance, unsigned int cpu); *performance, unsigned int cpu);
extern void acpi_processor_unregister_performance(unsigned int cpu); extern void acpi_processor_unregister_performance(unsigned int cpu);
int acpi_processor_pstate_control(void);
/* note: this locks both the calling module and the processor module /* note: this locks both the calling module and the processor module
if a _PPC object exists, rmmod is disallowed then */ if a _PPC object exists, rmmod is disallowed then */
int acpi_processor_notify_smm(struct module *calling_module); int acpi_processor_notify_smm(struct module *calling_module);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment