Loading drivers/acpi/processor_idle.c +63 −48 Original line number Diff line number Diff line Loading @@ -197,6 +197,19 @@ static inline u32 ticks_elapsed_in_us(u32 t1, u32 t2) return PM_TIMER_TICKS_TO_US((0xFFFFFFFF - t1) + t2); } static void acpi_safe_halt(void) { current_thread_info()->status &= ~TS_POLLING; /* * TS_POLLING-cleared state must be visible before we * test NEED_RESCHED: */ smp_mb(); if (!need_resched()) safe_halt(); current_thread_info()->status |= TS_POLLING; } #ifndef CONFIG_CPU_IDLE static void Loading Loading @@ -239,19 +252,6 @@ acpi_processor_power_activate(struct acpi_processor *pr, return; } static void acpi_safe_halt(void) { current_thread_info()->status &= ~TS_POLLING; /* * TS_POLLING-cleared state must be visible before we * test NEED_RESCHED: */ smp_mb(); if (!need_resched()) safe_halt(); current_thread_info()->status |= TS_POLLING; } static atomic_t c3_cpu_count; /* Common C-state entry for C2, C3, .. */ Loading Loading @@ -1373,15 +1373,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, if (pr->flags.bm_check) acpi_idle_update_bm_rld(pr, cx); current_thread_info()->status &= ~TS_POLLING; /* * TS_POLLING-cleared state must be visible before we test * NEED_RESCHED: */ smp_mb(); if (!need_resched()) safe_halt(); current_thread_info()->status |= TS_POLLING; acpi_safe_halt(); cx->usage++; Loading @@ -1399,6 +1391,8 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, struct acpi_processor *pr; struct acpi_processor_cx *cx = cpuidle_get_statedata(state); u32 t1, t2; int sleep_ticks = 0; pr = processors[smp_processor_id()]; if (unlikely(!pr)) Loading Loading @@ -1428,6 +1422,8 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, ACPI_FLUSH_CPU_CACHE(); t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); /* Tell the scheduler that we are going deep-idle: */ sched_clock_idle_sleep_event(); acpi_state_timer_broadcast(pr, cx, 1); acpi_idle_do_entry(cx); t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); Loading @@ -1436,6 +1432,10 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, /* TSC could halt in idle, so notify users */ mark_tsc_unstable("TSC halts in idle");; #endif sleep_ticks = ticks_elapsed(t1, t2); /* Tell the scheduler how much we idled: */ sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS); local_irq_enable(); current_thread_info()->status |= TS_POLLING; Loading @@ -1443,7 +1443,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, cx->usage++; acpi_state_timer_broadcast(pr, cx, 0); cx->time += ticks_elapsed(t1, t2); cx->time += sleep_ticks; return ticks_elapsed_in_us(t1, t2); } Loading @@ -1463,6 +1463,8 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, struct acpi_processor *pr; struct acpi_processor_cx *cx = cpuidle_get_statedata(state); u32 t1, t2; int sleep_ticks = 0; pr = processors[smp_processor_id()]; if (unlikely(!pr)) Loading @@ -1471,6 +1473,15 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, if (acpi_idle_suspend) return(acpi_idle_enter_c1(dev, state)); if (acpi_idle_bm_check()) { if (dev->safe_state) { return dev->safe_state->enter(dev, dev->safe_state); } else { acpi_safe_halt(); return 0; } } local_irq_disable(); current_thread_info()->status &= ~TS_POLLING; /* Loading @@ -1485,37 +1496,44 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, return 0; } /* Tell the scheduler that we are going deep-idle: */ sched_clock_idle_sleep_event(); /* * Must be done before busmaster disable as we might need to * access HPET ! */ acpi_state_timer_broadcast(pr, cx, 1); if (acpi_idle_bm_check()) { cx = pr->power.bm_state; acpi_idle_update_bm_rld(pr, cx); t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); acpi_idle_do_entry(cx); t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); } else { acpi_idle_update_bm_rld(pr, cx); /* * disable bus master * bm_check implies we need ARB_DIS * !bm_check implies we need cache flush * bm_control implies whether we can do ARB_DIS * * That leaves a case where bm_check is set and bm_control is * not set. In that case we cannot do much, we enter C3 * without doing anything. */ if (pr->flags.bm_check && pr->flags.bm_control) { spin_lock(&c3_lock); c3_cpu_count++; /* Disable bus master arbitration when all CPUs are in C3 */ if (c3_cpu_count == num_online_cpus()) acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1); spin_unlock(&c3_lock); } else if (!pr->flags.bm_check) { ACPI_FLUSH_CPU_CACHE(); } t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); acpi_idle_do_entry(cx); t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); spin_lock(&c3_lock); /* Re-enable bus master arbitration */ if (c3_cpu_count == num_online_cpus()) if (pr->flags.bm_check && pr->flags.bm_control) { spin_lock(&c3_lock); acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0); c3_cpu_count--; spin_unlock(&c3_lock); Loading @@ -1525,6 +1543,9 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, /* TSC could halt in idle, so notify users */ mark_tsc_unstable("TSC halts in idle"); #endif sleep_ticks = ticks_elapsed(t1, t2); /* Tell the scheduler how much we idled: */ sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS); local_irq_enable(); current_thread_info()->status |= TS_POLLING; Loading @@ -1532,7 +1553,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, cx->usage++; acpi_state_timer_broadcast(pr, cx, 0); cx->time += ticks_elapsed(t1, t2); cx->time += sleep_ticks; return ticks_elapsed_in_us(t1, t2); } Loading Loading @@ -1584,12 +1605,14 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) case ACPI_STATE_C1: state->flags |= CPUIDLE_FLAG_SHALLOW; state->enter = acpi_idle_enter_c1; dev->safe_state = state; break; case ACPI_STATE_C2: state->flags |= CPUIDLE_FLAG_BALANCED; state->flags |= CPUIDLE_FLAG_TIME_VALID; state->enter = acpi_idle_enter_simple; dev->safe_state = state; break; case ACPI_STATE_C3: Loading @@ -1610,14 +1633,6 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) if (!count) return -EINVAL; /* find the deepest state that can handle active BM */ if (pr->flags.bm_check) { for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) if (pr->power.states[i].type == ACPI_STATE_C3) break; pr->power.bm_state = &pr->power.states[i-1]; } return 0; } Loading include/acpi/processor.h +0 −1 Original line number Diff line number Diff line Loading @@ -78,7 +78,6 @@ struct acpi_processor_cx { struct acpi_processor_power { struct cpuidle_device dev; struct acpi_processor_cx *state; struct acpi_processor_cx *bm_state; unsigned long bm_check_timestamp; u32 default_state; u32 bm_activity; Loading include/linux/cpuidle.h +1 −0 Original line number Diff line number Diff line Loading @@ -92,6 +92,7 @@ struct cpuidle_device { struct kobject kobj; struct completion kobj_unregister; void *governor_data; struct cpuidle_state *safe_state; }; DECLARE_PER_CPU(struct cpuidle_device *, cpuidle_devices); Loading Loading
drivers/acpi/processor_idle.c +63 −48 Original line number Diff line number Diff line Loading @@ -197,6 +197,19 @@ static inline u32 ticks_elapsed_in_us(u32 t1, u32 t2) return PM_TIMER_TICKS_TO_US((0xFFFFFFFF - t1) + t2); } static void acpi_safe_halt(void) { current_thread_info()->status &= ~TS_POLLING; /* * TS_POLLING-cleared state must be visible before we * test NEED_RESCHED: */ smp_mb(); if (!need_resched()) safe_halt(); current_thread_info()->status |= TS_POLLING; } #ifndef CONFIG_CPU_IDLE static void Loading Loading @@ -239,19 +252,6 @@ acpi_processor_power_activate(struct acpi_processor *pr, return; } static void acpi_safe_halt(void) { current_thread_info()->status &= ~TS_POLLING; /* * TS_POLLING-cleared state must be visible before we * test NEED_RESCHED: */ smp_mb(); if (!need_resched()) safe_halt(); current_thread_info()->status |= TS_POLLING; } static atomic_t c3_cpu_count; /* Common C-state entry for C2, C3, .. */ Loading Loading @@ -1373,15 +1373,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, if (pr->flags.bm_check) acpi_idle_update_bm_rld(pr, cx); current_thread_info()->status &= ~TS_POLLING; /* * TS_POLLING-cleared state must be visible before we test * NEED_RESCHED: */ smp_mb(); if (!need_resched()) safe_halt(); current_thread_info()->status |= TS_POLLING; acpi_safe_halt(); cx->usage++; Loading @@ -1399,6 +1391,8 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, struct acpi_processor *pr; struct acpi_processor_cx *cx = cpuidle_get_statedata(state); u32 t1, t2; int sleep_ticks = 0; pr = processors[smp_processor_id()]; if (unlikely(!pr)) Loading Loading @@ -1428,6 +1422,8 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, ACPI_FLUSH_CPU_CACHE(); t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); /* Tell the scheduler that we are going deep-idle: */ sched_clock_idle_sleep_event(); acpi_state_timer_broadcast(pr, cx, 1); acpi_idle_do_entry(cx); t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); Loading @@ -1436,6 +1432,10 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, /* TSC could halt in idle, so notify users */ mark_tsc_unstable("TSC halts in idle");; #endif sleep_ticks = ticks_elapsed(t1, t2); /* Tell the scheduler how much we idled: */ sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS); local_irq_enable(); current_thread_info()->status |= TS_POLLING; Loading @@ -1443,7 +1443,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, cx->usage++; acpi_state_timer_broadcast(pr, cx, 0); cx->time += ticks_elapsed(t1, t2); cx->time += sleep_ticks; return ticks_elapsed_in_us(t1, t2); } Loading @@ -1463,6 +1463,8 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, struct acpi_processor *pr; struct acpi_processor_cx *cx = cpuidle_get_statedata(state); u32 t1, t2; int sleep_ticks = 0; pr = processors[smp_processor_id()]; if (unlikely(!pr)) Loading @@ -1471,6 +1473,15 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, if (acpi_idle_suspend) return(acpi_idle_enter_c1(dev, state)); if (acpi_idle_bm_check()) { if (dev->safe_state) { return dev->safe_state->enter(dev, dev->safe_state); } else { acpi_safe_halt(); return 0; } } local_irq_disable(); current_thread_info()->status &= ~TS_POLLING; /* Loading @@ -1485,37 +1496,44 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, return 0; } /* Tell the scheduler that we are going deep-idle: */ sched_clock_idle_sleep_event(); /* * Must be done before busmaster disable as we might need to * access HPET ! */ acpi_state_timer_broadcast(pr, cx, 1); if (acpi_idle_bm_check()) { cx = pr->power.bm_state; acpi_idle_update_bm_rld(pr, cx); t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); acpi_idle_do_entry(cx); t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); } else { acpi_idle_update_bm_rld(pr, cx); /* * disable bus master * bm_check implies we need ARB_DIS * !bm_check implies we need cache flush * bm_control implies whether we can do ARB_DIS * * That leaves a case where bm_check is set and bm_control is * not set. In that case we cannot do much, we enter C3 * without doing anything. */ if (pr->flags.bm_check && pr->flags.bm_control) { spin_lock(&c3_lock); c3_cpu_count++; /* Disable bus master arbitration when all CPUs are in C3 */ if (c3_cpu_count == num_online_cpus()) acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1); spin_unlock(&c3_lock); } else if (!pr->flags.bm_check) { ACPI_FLUSH_CPU_CACHE(); } t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); acpi_idle_do_entry(cx); t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); spin_lock(&c3_lock); /* Re-enable bus master arbitration */ if (c3_cpu_count == num_online_cpus()) if (pr->flags.bm_check && pr->flags.bm_control) { spin_lock(&c3_lock); acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0); c3_cpu_count--; spin_unlock(&c3_lock); Loading @@ -1525,6 +1543,9 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, /* TSC could halt in idle, so notify users */ mark_tsc_unstable("TSC halts in idle"); #endif sleep_ticks = ticks_elapsed(t1, t2); /* Tell the scheduler how much we idled: */ sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS); local_irq_enable(); current_thread_info()->status |= TS_POLLING; Loading @@ -1532,7 +1553,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, cx->usage++; acpi_state_timer_broadcast(pr, cx, 0); cx->time += ticks_elapsed(t1, t2); cx->time += sleep_ticks; return ticks_elapsed_in_us(t1, t2); } Loading Loading @@ -1584,12 +1605,14 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) case ACPI_STATE_C1: state->flags |= CPUIDLE_FLAG_SHALLOW; state->enter = acpi_idle_enter_c1; dev->safe_state = state; break; case ACPI_STATE_C2: state->flags |= CPUIDLE_FLAG_BALANCED; state->flags |= CPUIDLE_FLAG_TIME_VALID; state->enter = acpi_idle_enter_simple; dev->safe_state = state; break; case ACPI_STATE_C3: Loading @@ -1610,14 +1633,6 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) if (!count) return -EINVAL; /* find the deepest state that can handle active BM */ if (pr->flags.bm_check) { for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) if (pr->power.states[i].type == ACPI_STATE_C3) break; pr->power.bm_state = &pr->power.states[i-1]; } return 0; } Loading
include/acpi/processor.h +0 −1 Original line number Diff line number Diff line Loading @@ -78,7 +78,6 @@ struct acpi_processor_cx { struct acpi_processor_power { struct cpuidle_device dev; struct acpi_processor_cx *state; struct acpi_processor_cx *bm_state; unsigned long bm_check_timestamp; u32 default_state; u32 bm_activity; Loading
include/linux/cpuidle.h +1 −0 Original line number Diff line number Diff line Loading @@ -92,6 +92,7 @@ struct cpuidle_device { struct kobject kobj; struct completion kobj_unregister; void *governor_data; struct cpuidle_state *safe_state; }; DECLARE_PER_CPU(struct cpuidle_device *, cpuidle_devices); Loading