From patchwork Tue Sep 18 08:52:08 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean Pihet X-Patchwork-Id: 1471451 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork1.kernel.org (Postfix) with ESMTP id 107B8400EC for ; Tue, 18 Sep 2012 09:00:34 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TDtae-0004hS-Ah; Tue, 18 Sep 2012 08:55:33 +0000 Received: from mail-wg0-f49.google.com ([74.125.82.49]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1TDtXq-0002to-NT for linux-arm-kernel@lists.infradead.org; Tue, 18 Sep 2012 08:52:47 +0000 Received: by wgbdt14 with SMTP id dt14so1585532wgb.18 for ; Tue, 18 Sep 2012 01:52:29 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references :x-gm-message-state; bh=UjBaGN027tuEDSPGscCbsKVNbCcnwM+9T4ZK30nJQFc=; b=Ul5XF1PVRQB2rjrpXAEsrkWFnRZyByJBrwToMDTOaOQ5wCPbQaGz5HZ6F6AlT6H1CO pvIYNtfTWMBmiRMHkjRZxMdsXAIzXL/gtc4gBFDCOE8NWxK9DVFUoRgiMvOTFfuSbjJ7 G4eqP3DXL7qWktS1LACiKYlSsD6KVeyknZ7RwNESwBitH7MnXy3VKP7wb/F5a+dtylVh GgWo/ujrwTGtr3JWlN75mmf/37JC5xTjzx7RY451z8B9zgaPLRAxWe3Gb38tMBCADtP7 2vZ5UbhUGsIBLukbro2PPESWTMNxwuWtUBjZjbr45ghKBA0bIdBt6O92fqfOteBYbW+Y P1Tw== Received: by 10.180.104.197 with SMTP id gg5mr21806186wib.9.1347958349348; Tue, 18 Sep 2012 01:52:29 -0700 (PDT) Received: from localhost.localdomain (179.59-66-87.adsl-dyn.isp.belgacom.be. [87.66.59.179]) by mx.google.com with ESMTPS id ct3sm21831091wib.5.2012.09.18.01.52.28 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 18 Sep 2012 01:52:28 -0700 (PDT) From: Jean Pihet To: linux-omap@vger.kernel.org, paul@pwsan.com, linux-arm-kernel@lists.infradead.org, khilman@ti.com Subject: [PATCH 4/8] ARM: OMAP3: cpuidle: next C-state decision depends on the PM QoS MPU and CORE constraints Date: Tue, 18 Sep 2012 10:52:08 +0200 Message-Id: <1347958332-2205-5-git-send-email-j-pihet@ti.com> X-Mailer: git-send-email 1.7.7.6 In-Reply-To: <1347958332-2205-1-git-send-email-j-pihet@ti.com> References: <1347958332-2205-1-git-send-email-j-pihet@ti.com> X-Gm-Message-State: ALoCoQla+c++yzS0IKdah3ue4DJ2bk+wOm88Znzp2k//2UJhoK4wrDp4EYArCbcTYtnhKuXaNJ/x X-Spam-Note: CRM114 invocation failed X-Spam-Score: -2.6 (--) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-2.6 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [74.125.82.49 listed in list.dnswl.org] -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: Jean Pihet X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org The MPU latency figures for cpuidle include the MPU itself and also the peripherals needed for the MPU to execute instructions (e.g. main memory, caches, IRQ controller, MMU etc). On OMAP3 those peripherals belong to the MPU and CORE power domains and so the cpuidle C-states are a combination of MPU and CORE states. This patch implements the relation between the cpuidle and per- device PM QoS frameworks in the OMAP3 specific idle callbacks. The chosen C-state shall satisfy the following conditions: . it satisfies the enable_off_mode flag, . the next state for MPU and CORE power domains is not lower than the next state calculated by the per-device PM QoS. Tested on OMAP3 Beagleboard in RET/OFF using wake-up latency constraints on MPU, CORE and PER. Signed-off-by: Jean Pihet --- arch/arm/mach-omap2/cpuidle34xx.c | 49 +++++++++++++++++++++++++------------ 1 files changed, 33 insertions(+), 16 deletions(-) diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c index 4ca37d2..ca6cb71 100644 --- a/arch/arm/mach-omap2/cpuidle34xx.c +++ b/arch/arm/mach-omap2/cpuidle34xx.c @@ -76,8 +76,8 @@ static struct omap3_idle_statedata omap3_idle_data[] = { static struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd; static int __omap3_enter_idle(struct cpuidle_device *dev, - struct cpuidle_driver *drv, - int index) + struct cpuidle_driver *drv, + int index) { struct omap3_idle_statedata *cx = &omap3_idle_data[index]; u32 mpu_state = cx->mpu_state, core_state = cx->core_state; @@ -134,10 +134,14 @@ return_sleep_time: * * Called from the CPUidle framework to program the device to the * specified target state selected by the governor. + * + * Note: this function does not check for any pending activity or dependency + * between power domains states, so the caller shall check the parameters + * correctness. */ static inline int omap3_enter_idle(struct cpuidle_device *dev, - struct cpuidle_driver *drv, - int index) + struct cpuidle_driver *drv, + int index) { return cpuidle_wrap_enter(dev, drv, index, __omap3_enter_idle); } @@ -152,8 +156,10 @@ static inline int omap3_enter_idle(struct cpuidle_device *dev, * to the caller. Else, this function searches for a lower c-state which is * still valid (as defined in omap3_power_states[]) and returns its index. * - * A state is valid if the 'valid' field is enabled and - * if it satisfies the enable_off_mode condition. + * A state is valid if: + * . it satisfies the enable_off_mode flag, + * . the next state for MPU and CORE power domains is not lower than the + * state programmed by the per-device PM QoS. */ static int next_valid_state(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) @@ -161,6 +167,8 @@ static int next_valid_state(struct cpuidle_device *dev, struct omap3_idle_statedata *cx = &omap3_idle_data[index]; u32 mpu_deepest_state = PWRDM_FUNC_PWRST_CSWR; u32 core_deepest_state = PWRDM_FUNC_PWRST_CSWR; + u32 mpu_pm_qos_next_state = mpu_pd->wkup_lat_next_state; + u32 core_pm_qos_next_state = core_pd->wkup_lat_next_state; int idx; int next_index = 0; /* C1 is the default value */ @@ -177,7 +185,9 @@ static int next_valid_state(struct cpuidle_device *dev, /* Check if current state is valid */ if ((cx->mpu_state >= mpu_deepest_state) && - (cx->core_state >= core_deepest_state)) + (cx->core_state >= core_deepest_state) && + (cx->mpu_state >= mpu_pm_qos_next_state) && + (cx->core_state >= core_pm_qos_next_state)) return index; /* @@ -187,7 +197,9 @@ static int next_valid_state(struct cpuidle_device *dev, for (idx = index - 1; idx >= 0; idx--) { cx = &omap3_idle_data[idx]; if ((cx->mpu_state >= mpu_deepest_state) && - (cx->core_state >= core_deepest_state)) { + (cx->core_state >= core_deepest_state) && + (cx->mpu_state >= mpu_pm_qos_next_state) && + (cx->core_state >= core_pm_qos_next_state)) { next_index = idx; break; } @@ -223,14 +235,6 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev, else new_state_idx = next_valid_state(dev, drv, index); - /* - * FIXME: we currently manage device-specific idle states - * for PER and CORE in combination with CPU-specific - * idle states. This is wrong, and device-specific - * idle management needs to be separated out into - * its own code. - */ - /* Program PER state */ cx = &omap3_idle_data[new_state_idx]; core_next_state = cx->core_state; @@ -264,6 +268,19 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev, DEFINE_PER_CPU(struct cpuidle_device, omap3_idle_dev); +/* + * Note about the latency related fields of the cpuidle_driver struct: + * + * - exit_latency = sleep + wake-up latencies of the MPU, + * which include the MPU itself and the peripherals needed + * for the MPU to execute instructions (e.g. main memory, + * caches, IRQ controller, MMU etc). Some of those peripherals + * can belong to other power domains than the MPU subsystem and so + * the corresponding latencies must be included in this figure + * + * - target_residency: required amount of time in the C state + * to break even on energy cost + */ struct cpuidle_driver omap3_idle_driver = { .name = "omap3_idle", .owner = THIS_MODULE,