From patchwork Fri Feb 5 20:53:12 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Garrett X-Patchwork-Id: 77410 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o15Ks9jp024797 for ; Fri, 5 Feb 2010 20:54:10 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932958Ab0BEUyI (ORCPT ); Fri, 5 Feb 2010 15:54:08 -0500 Received: from jgarrett.org ([64.5.53.252]:41755 "EHLO jgarrett.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757041Ab0BEUyH (ORCPT ); Fri, 5 Feb 2010 15:54:07 -0500 Received: from jeff by jgarrett.org with local (Exim 3.36 #1 (Debian)) id 1NdVAu-00070w-00; Fri, 05 Feb 2010 14:53:12 -0600 Date: Fri, 5 Feb 2010 14:53:12 -0600 To: Len Brown Cc: Andi Kleen , linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org Subject: Re: acpi_idle: Very idle Core i7 machine never enters C3 Message-ID: <20100205205312.GA4532@jgarrett.org> References: <20100126084740.GA5265@jgarrett.org> <87y6jkee1b.fsf@basil.nowhere.org> <20100205160900.GA2736@jgarrett.org> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.13 (2006-08-11) From: Jeff Garrett Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Fri, 05 Feb 2010 20:54:10 +0000 (UTC) diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 7c0441f..8c636de 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -849,73 +851,6 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, return idle_time; } -/** - * acpi_idle_enter_simple - enters an ACPI state without BM handling - * @dev: the target CPU - * @state: the state data - */ -static int acpi_idle_enter_simple(struct cpuidle_device *dev, - struct cpuidle_state *state) -{ - struct acpi_processor *pr; - struct acpi_processor_cx *cx = cpuidle_get_statedata(state); - ktime_t kt1, kt2; - s64 idle_time; - s64 sleep_ticks = 0; - - pr = __get_cpu_var(processors); - - if (unlikely(!pr)) - return 0; - - if (acpi_idle_suspend) - return(acpi_idle_enter_c1(dev, state)); - - local_irq_disable(); - current_thread_info()->status &= ~TS_POLLING; - /* - * TS_POLLING-cleared state must be visible before we test - * NEED_RESCHED: - */ - smp_mb(); - - if (unlikely(need_resched())) { - current_thread_info()->status |= TS_POLLING; - local_irq_enable(); - return 0; - } - - /* - * Must be done before busmaster disable as we might need to - * access HPET ! - */ - lapic_timer_state_broadcast(pr, cx, 1); - - if (cx->type == ACPI_STATE_C3) - ACPI_FLUSH_CPU_CACHE(); - - kt1 = ktime_get_real(); - /* Tell the scheduler that we are going deep-idle: */ - sched_clock_idle_sleep_event(); - acpi_idle_do_entry(cx); - kt2 = ktime_get_real(); - idle_time = ktime_to_us(ktime_sub(kt2, kt1)); - - sleep_ticks = us_to_pm_timer_ticks(idle_time); - - /* 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; - - cx->usage++; - - lapic_timer_state_broadcast(pr, cx, 0); - cx->time += sleep_ticks; - return idle_time; -} - static int c3_cpu_count; static DEFINE_SPINLOCK(c3_lock); @@ -944,7 +879,7 @@ 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 (cx->type == ACPI_STATE_C3 && pr->flags.bm_check && acpi_idle_bm_check()) { if (dev->safe_state) { dev->last_state = dev->safe_state; return dev->safe_state->enter(dev, dev->safe_state); @@ -970,17 +905,24 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, return 0; } - acpi_unlazy_tlb(smp_processor_id()); + if (cx->type == ACPI_STATE_C3 && pr->flags.bm_check) + acpi_unlazy_tlb(smp_processor_id()); /* Tell the scheduler that we are going deep-idle: */ - sched_clock_idle_sleep_event(); + if (cx->type == ACPI_STATE_C3 && pr->flags.bm_check) + sched_clock_idle_sleep_event(); /* * Must be done before busmaster disable as we might need to * access HPET ! */ lapic_timer_state_broadcast(pr, cx, 1); + if (cx->type == ACPI_STATE_C3 && !pr->flags.bm_check) + ACPI_FLUSH_CPU_CACHE(); + kt1 = ktime_get_real(); + if (cx->type != ACPI_STATE_C3 || !pr->flags.bm_check) + sched_clock_idle_sleep_event(); /* * disable bus master * bm_check implies we need ARB_DIS @@ -991,21 +933,19 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, * not set. In that case we cannot do much, we enter C3 * without doing anything. */ - if (pr->flags.bm_check && pr->flags.bm_control) { + if (cx->type == ACPI_STATE_C3 && 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_write_bit_register(ACPI_BITREG_ARB_DISABLE, 1); spin_unlock(&c3_lock); - } else if (!pr->flags.bm_check) { - ACPI_FLUSH_CPU_CACHE(); } acpi_idle_do_entry(cx); /* Re-enable bus master arbitration */ - if (pr->flags.bm_check && pr->flags.bm_control) { + if (cx->type == ACPI_STATE_C3 && pr->flags.bm_check && pr->flags.bm_control) { spin_lock(&c3_lock); acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 0); c3_cpu_count--; @@ -1095,7 +1035,7 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) case ACPI_STATE_C2: state->flags |= CPUIDLE_FLAG_BALANCED; state->flags |= CPUIDLE_FLAG_TIME_VALID; - state->enter = acpi_idle_enter_simple; + state->enter = acpi_idle_enter_bm; dev->safe_state = state; break; @@ -1103,9 +1043,7 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) state->flags |= CPUIDLE_FLAG_DEEP; state->flags |= CPUIDLE_FLAG_TIME_VALID; state->flags |= CPUIDLE_FLAG_CHECK_BM; - state->enter = pr->flags.bm_check ? - acpi_idle_enter_bm : - acpi_idle_enter_simple; + state->enter = acpi_idle_enter_bm; break; }