mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
ACPI / processor_idle: Add support for Low Power Idle(LPI) states
ACPI 6.0 introduced an optional object _LPI that provides an alternate method to describe Low Power Idle states. It defines the local power states for each node in a hierarchical processor topology. The OSPM can use _LPI object to select a local power state for each level of processor hierarchy in the system. They used to produce a composite power state request that is presented to the platform by the OSPM. Since multiple processors affect the idle state for any non-leaf hierarchy node, coordination of idle state requests between the processors is required. ACPI supports two different coordination schemes: Platform coordinated and OS initiated. This patch adds initial support for Platform coordination scheme of LPI. Signed-off-by: Sudeep Holla <sudeep.holla@arm.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
committed by
Rafael J. Wysocki
parent
35ae713355
commit
a36a7fecfe
+13
-1
@@ -302,6 +302,14 @@ out_kfree:
|
|||||||
EXPORT_SYMBOL(acpi_run_osc);
|
EXPORT_SYMBOL(acpi_run_osc);
|
||||||
|
|
||||||
bool osc_sb_apei_support_acked;
|
bool osc_sb_apei_support_acked;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ACPI 6.0 Section 8.4.4.2 Idle State Coordination
|
||||||
|
* OSPM supports platform coordinated low power idle(LPI) states
|
||||||
|
*/
|
||||||
|
bool osc_pc_lpi_support_confirmed;
|
||||||
|
EXPORT_SYMBOL_GPL(osc_pc_lpi_support_confirmed);
|
||||||
|
|
||||||
static u8 sb_uuid_str[] = "0811B06E-4A27-44F9-8D60-3CBBC22E7B48";
|
static u8 sb_uuid_str[] = "0811B06E-4A27-44F9-8D60-3CBBC22E7B48";
|
||||||
static void acpi_bus_osc_support(void)
|
static void acpi_bus_osc_support(void)
|
||||||
{
|
{
|
||||||
@@ -322,6 +330,7 @@ static void acpi_bus_osc_support(void)
|
|||||||
capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PPC_OST_SUPPORT;
|
capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PPC_OST_SUPPORT;
|
||||||
|
|
||||||
capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_HOTPLUG_OST_SUPPORT;
|
capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_HOTPLUG_OST_SUPPORT;
|
||||||
|
capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PCLPI_SUPPORT;
|
||||||
|
|
||||||
if (!ghes_disable)
|
if (!ghes_disable)
|
||||||
capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_APEI_SUPPORT;
|
capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_APEI_SUPPORT;
|
||||||
@@ -329,9 +338,12 @@ static void acpi_bus_osc_support(void)
|
|||||||
return;
|
return;
|
||||||
if (ACPI_SUCCESS(acpi_run_osc(handle, &context))) {
|
if (ACPI_SUCCESS(acpi_run_osc(handle, &context))) {
|
||||||
u32 *capbuf_ret = context.ret.pointer;
|
u32 *capbuf_ret = context.ret.pointer;
|
||||||
if (context.ret.length > OSC_SUPPORT_DWORD)
|
if (context.ret.length > OSC_SUPPORT_DWORD) {
|
||||||
osc_sb_apei_support_acked =
|
osc_sb_apei_support_acked =
|
||||||
capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_APEI_SUPPORT;
|
capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_APEI_SUPPORT;
|
||||||
|
osc_pc_lpi_support_confirmed =
|
||||||
|
capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_PCLPI_SUPPORT;
|
||||||
|
}
|
||||||
kfree(context.ret.pointer);
|
kfree(context.ret.pointer);
|
||||||
}
|
}
|
||||||
/* do we need to check other returned cap? Sounds no */
|
/* do we need to check other returned cap? Sounds no */
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ static void acpi_processor_notify(acpi_handle handle, u32 event, void *data)
|
|||||||
pr->performance_platform_limit);
|
pr->performance_platform_limit);
|
||||||
break;
|
break;
|
||||||
case ACPI_PROCESSOR_NOTIFY_POWER:
|
case ACPI_PROCESSOR_NOTIFY_POWER:
|
||||||
acpi_processor_cst_has_changed(pr);
|
acpi_processor_power_state_has_changed(pr);
|
||||||
acpi_bus_generate_netlink_event(device->pnp.device_class,
|
acpi_bus_generate_netlink_event(device->pnp.device_class,
|
||||||
dev_name(&device->dev), event, 0);
|
dev_name(&device->dev), event, 0);
|
||||||
break;
|
break;
|
||||||
|
|||||||
+411
-55
File diff suppressed because it is too large
Load Diff
@@ -39,6 +39,7 @@
|
|||||||
#define ACPI_CSTATE_SYSTEMIO 0
|
#define ACPI_CSTATE_SYSTEMIO 0
|
||||||
#define ACPI_CSTATE_FFH 1
|
#define ACPI_CSTATE_FFH 1
|
||||||
#define ACPI_CSTATE_HALT 2
|
#define ACPI_CSTATE_HALT 2
|
||||||
|
#define ACPI_CSTATE_INTEGER 3
|
||||||
|
|
||||||
#define ACPI_CX_DESC_LEN 32
|
#define ACPI_CX_DESC_LEN 32
|
||||||
|
|
||||||
@@ -67,9 +68,25 @@ struct acpi_processor_cx {
|
|||||||
char desc[ACPI_CX_DESC_LEN];
|
char desc[ACPI_CX_DESC_LEN];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct acpi_lpi_state {
|
||||||
|
u32 min_residency;
|
||||||
|
u32 wake_latency; /* worst case */
|
||||||
|
u32 flags;
|
||||||
|
u32 arch_flags;
|
||||||
|
u32 res_cnt_freq;
|
||||||
|
u32 enable_parent_state;
|
||||||
|
u64 address;
|
||||||
|
u8 index;
|
||||||
|
u8 entry_method;
|
||||||
|
char desc[ACPI_CX_DESC_LEN];
|
||||||
|
};
|
||||||
|
|
||||||
struct acpi_processor_power {
|
struct acpi_processor_power {
|
||||||
int count;
|
int count;
|
||||||
struct acpi_processor_cx states[ACPI_PROCESSOR_MAX_POWER];
|
union {
|
||||||
|
struct acpi_processor_cx states[ACPI_PROCESSOR_MAX_POWER];
|
||||||
|
struct acpi_lpi_state lpi_states[ACPI_PROCESSOR_MAX_POWER];
|
||||||
|
};
|
||||||
int timer_broadcast_on_state;
|
int timer_broadcast_on_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -189,6 +206,7 @@ struct acpi_processor_flags {
|
|||||||
u8 bm_control:1;
|
u8 bm_control:1;
|
||||||
u8 bm_check:1;
|
u8 bm_check:1;
|
||||||
u8 has_cst:1;
|
u8 has_cst:1;
|
||||||
|
u8 has_lpi:1;
|
||||||
u8 power_setup_done:1;
|
u8 power_setup_done:1;
|
||||||
u8 bm_rld_set:1;
|
u8 bm_rld_set:1;
|
||||||
u8 need_hotplug_init:1;
|
u8 need_hotplug_init:1;
|
||||||
@@ -371,7 +389,7 @@ extern struct cpuidle_driver acpi_idle_driver;
|
|||||||
#ifdef CONFIG_ACPI_PROCESSOR_IDLE
|
#ifdef CONFIG_ACPI_PROCESSOR_IDLE
|
||||||
int acpi_processor_power_init(struct acpi_processor *pr);
|
int acpi_processor_power_init(struct acpi_processor *pr);
|
||||||
int acpi_processor_power_exit(struct acpi_processor *pr);
|
int acpi_processor_power_exit(struct acpi_processor *pr);
|
||||||
int acpi_processor_cst_has_changed(struct acpi_processor *pr);
|
int acpi_processor_power_state_has_changed(struct acpi_processor *pr);
|
||||||
int acpi_processor_hotplug(struct acpi_processor *pr);
|
int acpi_processor_hotplug(struct acpi_processor *pr);
|
||||||
#else
|
#else
|
||||||
static inline int acpi_processor_power_init(struct acpi_processor *pr)
|
static inline int acpi_processor_power_init(struct acpi_processor *pr)
|
||||||
@@ -384,7 +402,7 @@ static inline int acpi_processor_power_exit(struct acpi_processor *pr)
|
|||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int acpi_processor_cst_has_changed(struct acpi_processor *pr)
|
static inline int acpi_processor_power_state_has_changed(struct acpi_processor *pr)
|
||||||
{
|
{
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -444,8 +444,12 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context);
|
|||||||
#define OSC_SB_HOTPLUG_OST_SUPPORT 0x00000008
|
#define OSC_SB_HOTPLUG_OST_SUPPORT 0x00000008
|
||||||
#define OSC_SB_APEI_SUPPORT 0x00000010
|
#define OSC_SB_APEI_SUPPORT 0x00000010
|
||||||
#define OSC_SB_CPC_SUPPORT 0x00000020
|
#define OSC_SB_CPC_SUPPORT 0x00000020
|
||||||
|
#define OSC_SB_CPCV2_SUPPORT 0x00000040
|
||||||
|
#define OSC_SB_PCLPI_SUPPORT 0x00000080
|
||||||
|
#define OSC_SB_OSLPI_SUPPORT 0x00000100
|
||||||
|
|
||||||
extern bool osc_sb_apei_support_acked;
|
extern bool osc_sb_apei_support_acked;
|
||||||
|
extern bool osc_pc_lpi_support_confirmed;
|
||||||
|
|
||||||
/* PCI Host Bridge _OSC: Capabilities DWORD 2: Support Field */
|
/* PCI Host Bridge _OSC: Capabilities DWORD 2: Support Field */
|
||||||
#define OSC_PCI_EXT_CONFIG_SUPPORT 0x00000001
|
#define OSC_PCI_EXT_CONFIG_SUPPORT 0x00000001
|
||||||
|
|||||||
Reference in New Issue
Block a user