cpuidle: mwait on softirq_pending & remove wakeup ipis

For cpu which enter deep C state via monitor/mwait, wakeup can be done
by writing to the monitored memory. So once monitor softirq_pending,
we can remove the redundant ipis.

Signed-off-by: Yu Ke <ke.yu@intel.com>
Signed-off-by: Wei Gang <gang.wei@intel.com>
This commit is contained in:
Keir Fraser committed 2010-04-06 06:52:11 +01:00
1 parent 4e8bf17138
commit 3d521e933e
3 files changed
+47 -2

No files matched your search

+43 -2
View File
@@ -69,6 +69,14 @@ boolean_param("lapic_timer_c2_ok", local_apic_timer_c2_ok);
static struct acpi_processor_power *__read_mostly processor_powers[NR_CPUS];
static char* acpi_cstate_method_name[] =
{
"NONE",
"SYSIO",
"FFH",
"HALT"
};
static void print_acpi_power(uint32_t cpu, struct acpi_processor_power *power)
{
uint32_t i, idle_usage = 0;
@@ -92,6 +100,7 @@ static void print_acpi_power(uint32_t cpu, struct acpi_processor_power *power)
printk("type[C%d] ", power->states[i].type);
printk("latency[%03d] ", power->states[i].latency);
printk("usage[%08d] ", power->states[i].usage);
printk("method[%5s] ", acpi_cstate_method_name[power->states[i].entry_method]);
printk("duration[%"PRId64"]\n", res);
}
printk(" C0:\tusage[%08d] duration[%"PRId64"]\n",
@@ -140,11 +149,43 @@ static void acpi_safe_halt(void)
#define MWAIT_ECX_INTERRUPT_BREAK (0x1)
/*
* The bit is set iff cpu use monitor/mwait to enter C state
* with this flag set, CPU can be waken up from C state
* by writing to specific memory address, instead of sending IPI
*/
static cpumask_t cpuidle_mwait_flags;
void cpuidle_wakeup_mwait(cpumask_t *mask)
{
cpumask_t target;
int cpu;
cpus_and(target, *mask, cpuidle_mwait_flags);
/* cpu is 'mwait'ing at softirq_pending,
writing to it will wake up CPU */
for_each_cpu_mask(cpu, target)
set_bit(TIMER_SOFTIRQ, &softirq_pending(cpu));
cpus_andnot(*mask, *mask, cpuidle_mwait_flags);
}
static void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
{
__monitor((void *)current, 0, 0);
int cpu = smp_processor_id();
__monitor((void *)&softirq_pending(cpu), 0, 0);
smp_mb();
__mwait(eax, ecx);
if (!softirq_pending(cpu))
{
cpu_set(cpu, cpuidle_mwait_flags);
__mwait(eax, ecx);
cpu_clear(cpu, cpuidle_mwait_flags);
}
}
static void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx *cx)
+2
View File
@@ -166,6 +166,8 @@ static int evt_do_broadcast(cpumask_t mask)
ret = 1;
}
cpuidle_wakeup_mwait(&mask);
if ( !cpus_empty(mask) )
{
cpumask_raise_softirq(mask, TIMER_SOFTIRQ);
+2
View File
@@ -86,6 +86,8 @@ struct cpuidle_governor
extern struct cpuidle_governor *cpuidle_current_governor;
void cpuidle_disable_deep_cstate(void);
extern void cpuidle_wakeup_mwait(cpumask_t *mask);
#define CPUIDLE_DRIVER_STATE_START 1
#endif /* _XEN_CPUIDLE_H */
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.