From patchwork Thu Apr 7 18:18:31 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Hilman X-Patchwork-Id: 693271 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p37IIcoO031729 for ; Thu, 7 Apr 2011 18:18:40 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755289Ab1DGSSS (ORCPT ); Thu, 7 Apr 2011 14:18:18 -0400 Received: from na3sys009aog108.obsmtp.com ([74.125.149.199]:35827 "EHLO na3sys009aog108.obsmtp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753106Ab1DGSSS (ORCPT ); Thu, 7 Apr 2011 14:18:18 -0400 Received: from mail-iw0-f169.google.com ([209.85.214.169]) (using TLSv1) by na3sys009aob108.postini.com ([74.125.148.12]) with SMTP ID DSNKTZ3/6ZeCx8nabeUXxnF7dKaa6zywY68N@postini.com; Thu, 07 Apr 2011 11:18:17 PDT Received: by iwg8 with SMTP id 8so3672483iwg.0 for ; Thu, 07 Apr 2011 11:18:16 -0700 (PDT) Received: by 10.42.220.67 with SMTP id hx3mr1827391icb.173.1302200295920; Thu, 07 Apr 2011 11:18:15 -0700 (PDT) Received: from localhost (c-24-18-179-55.hsd1.wa.comcast.net [24.18.179.55]) by mx.google.com with ESMTPS id gy41sm1293071ibb.39.2011.04.07.11.18.14 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 07 Apr 2011 11:18:15 -0700 (PDT) From: Kevin Hilman To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-omap@vger.kernel.org Cc: linux-pm@lists.linux-foundation.org, Len Brown , Nicole Chalhoub , Vincent Bour , Arjan van de Ven , Thomas Gleixner Subject: [PATCH] nohz: delay going tickless under CPU load to favor deeper C states Date: Thu, 7 Apr 2011 11:18:31 -0700 Message-Id: <1302200311-24263-1-git-send-email-khilman@ti.com> X-Mailer: git-send-email 1.7.4 Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Thu, 07 Apr 2011 18:18:43 +0000 (UTC) From: Nicole Chalhoub While there is CPU load, continue the periodic tick in order to give CPUidle another opportunity to pick a deeper C-state instead of spending potentially long idle times in a shallow C-state. Long winded version: When going idle with a high load average, CPUidle menu governor will decide to pick a shallow C-state since one of the guiding principles of the menu governor is "The busier the system, the less impact of C states is acceptable" (taken from cpuidle/governors/menu.c.) That makes perfect sense. However, there are missed power-saving opportunities for bursty workloads with long idle times (e.g. MP3 playback.) Given such a workload, because of the load average, CPUidle tends to pick a shallow C-state. Because we also go tickless, this shallow C-state is used for the duration of the idle period. If the idle period is long, a deeper C state would've resulted in better power savings. This patch delays going tickless when there is a load such that on the next tick, the CPUidle governor will have another opportunity to to pick a deeper C-state. Since the system will have been idle for potentially a full tick, the load average will drop and a deeper C state will most likely be chosen. Delaying NOHZ decisions until the load is zero improved the load estimation on our ARM/OMAP4 platform where HZ=128 and increased the time spent in deep C-states (~50% of idle time in C-states deeper than C1). A power saving of ~20mA at battery level is observed during MP3 playback on OMAP4/Blaze board. Signed-off-by: Nicole Chalhoub Signed-off-by: Vincent Bour Cc: Arjan van de Ven Cc: Thomas Gleixner [khilman@ti.com: rework changelog] Signed-off-by: Kevin Hilman --- kernel/time/tick-sched.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index d5097c4..418066c 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -324,7 +324,7 @@ void tick_nohz_stop_sched_tick(int inidle) } while (read_seqretry(&xtime_lock, seq)); if (rcu_needs_cpu(cpu) || printk_needs_cpu(cpu) || - arch_needs_cpu(cpu)) { + arch_needs_cpu(cpu) || this_cpu_load()) { next_jiffies = last_jiffies + 1; delta_jiffies = 1; } else {