From patchwork Tue Feb 11 15:11:27 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Lezcano X-Patchwork-Id: 24465 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-ve0-f198.google.com (mail-ve0-f198.google.com [209.85.128.198]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 19680203F3 for ; Tue, 11 Feb 2014 15:12:01 +0000 (UTC) Received: by mail-ve0-f198.google.com with SMTP id pa12sf19104083veb.1 for ; Tue, 11 Feb 2014 07:12:01 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:sender:precedence:list-id:x-original-sender :x-original-authentication-results:mailing-list:list-post:list-help :list-archive:list-unsubscribe; bh=gQszklQSfWbTdaUmH+spB1O1OqFLJI6eR6cW7KMBYe8=; b=lsaqJvOef3UUvxzIYsKBRF78/x926p7AqwQ/esLXHwaIRQW/sXAdUiYY++h4bC+HKQ apZPAF0+dzCKaYYdx+DMjDgimZa9Tbma8UGahyT9Y1NGqdeqkFv5NWFV90zmPFG65fWX 4gZuAGwc0SNzaYmxj8HFztOasKX36jAb/xSJw4lN8LqgPOh9vspT8jiAPcVmglyNg797 WPFcP6PQ8y1GGlTQ9ADN+i/sJJyXLaEeKw3tNlsaja9ZleyppRW0WZtVvSk0EW0mx9sq k0lBglzCyfd4f8yc3zdutyRJs04+EQuDurfyM1ukAkcsBVfQhIhm2bzAOXzxXAaPMXgO w3bg== X-Gm-Message-State: ALoCoQlju2GPGlWXIt+GNL926uyx5kIZlLXnAAgxaRb/kl2qwi7NS0llyuaHHsRpirD6Q+kL6w20 X-Received: by 10.59.7.2 with SMTP id cy2mr13632904ved.9.1392131521053; Tue, 11 Feb 2014 07:12:01 -0800 (PST) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.91.110 with SMTP id y101ls2652828qgd.0.gmail; Tue, 11 Feb 2014 07:12:00 -0800 (PST) X-Received: by 10.58.207.13 with SMTP id ls13mr29392447vec.13.1392131520898; Tue, 11 Feb 2014 07:12:00 -0800 (PST) Received: from mail-vc0-f181.google.com (mail-vc0-f181.google.com [209.85.220.181]) by mx.google.com with ESMTPS id zp2si6012231vec.46.2014.02.11.07.12.00 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 11 Feb 2014 07:12:00 -0800 (PST) Received-SPF: neutral (google.com: 209.85.220.181 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.220.181; Received: by mail-vc0-f181.google.com with SMTP id ie18so5880917vcb.40 for ; Tue, 11 Feb 2014 07:12:00 -0800 (PST) X-Received: by 10.58.168.142 with SMTP id zw14mr594550veb.33.1392131520787; Tue, 11 Feb 2014 07:12:00 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.220.174.196 with SMTP id u4csp253446vcz; Tue, 11 Feb 2014 07:12:00 -0800 (PST) X-Received: by 10.68.133.193 with SMTP id pe1mr45235700pbb.56.1392131516877; Tue, 11 Feb 2014 07:11:56 -0800 (PST) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id m8si19341505pbq.59.2014.02.11.07.11.56; Tue, 11 Feb 2014 07:11:56 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751199AbaBKPLh (ORCPT + 27 others); Tue, 11 Feb 2014 10:11:37 -0500 Received: from mail-lb0-f173.google.com ([209.85.217.173]:36721 "EHLO mail-lb0-f173.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750743AbaBKPLg (ORCPT ); Tue, 11 Feb 2014 10:11:36 -0500 Received: by mail-lb0-f173.google.com with SMTP id s7so4449376lbd.18 for ; Tue, 11 Feb 2014 07:11:34 -0800 (PST) X-Received: by 10.152.234.202 with SMTP id ug10mr26987408lac.28.1392131494271; Tue, 11 Feb 2014 07:11:34 -0800 (PST) Received: from localhost.localdomain (AToulouse-654-1-479-183.w86-201.abo.wanadoo.fr. [86.201.194.183]) by mx.google.com with ESMTPSA id qx7sm19964004lbb.9.2014.02.11.07.11.31 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 11 Feb 2014 07:11:33 -0800 (PST) From: Daniel Lezcano To: mingo@kernel.org, peterz@infradead.org, tglx@linutronix.de, rjw@rjwysocki.net Cc: nicolas.pitre@linaro.org, preeti@linux.vnet.ibm.com, linux-kernel@vger.kernel.org Subject: [PATCH 1/5] idle/cpuidle: Split cpuidle_idle_call main function into smaller functions Date: Tue, 11 Feb 2014 16:11:27 +0100 Message-Id: <1392131491-5265-1-git-send-email-daniel.lezcano@linaro.org> X-Mailer: git-send-email 1.7.9.5 Sender: linux-kernel-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: daniel.lezcano@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.220.181 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , In order to allow better integration between the cpuidle framework and the scheduler, reducing the distance between these two sub-components will facilitate this integration by moving part of the cpuidle code in the idle task file and, because idle.c is in the sched directory, we have access to the scheduler's private structures. This patch splits the cpuidle_idle_call main entry function into 3 calls to a newly added API: 1. select the idle state 2. enter the idle state 3. reflect the idle state The cpuidle_idle_call calls these three functions to implement the main idle entry function. Signed-off-by: Daniel Lezcano Acked-by: Nicolas Pitre --- drivers/cpuidle/cpuidle.c | 102 ++++++++++++++++++++++++++++++++------------- include/linux/cpuidle.h | 14 +++++++ 2 files changed, 87 insertions(+), 29 deletions(-) diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index a55e68f..172ab6a 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -108,6 +108,71 @@ int cpuidle_enter_state(struct cpuidle_device *dev, struct cpuidle_driver *drv, } /** + * cpuidle_select - ask the cpuidle framework to choose an idle state + * + * @drv: the cpuidle driver + * @dev: the cpuidle device + * + * Returns the index of the idle state. On error it returns: + * -NODEV : the cpuidle framework is not available + * -EBUSY : the cpuidle framework is not initialized + */ +int cpuidle_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) +{ + if (off || !initialized) + return -ENODEV; + + if (!drv || !dev || !dev->enabled) + return -EBUSY; + + return cpuidle_curr_governor->select(drv, dev); +} + +/** + * cpuidle_enter - enter into the specified idle state + * + * @drv: the cpuidle driver tied with the cpu + * @dev: the cpuidle device + * @index: the index in the idle state table + * + * Returns the index in the idle state, < 0 in case of error. + * The error code depends on the backend driver + */ +int cpuidle_enter(struct cpuidle_driver *drv, struct cpuidle_device *dev, + int index) +{ + int entered_state; + bool broadcast = !!(drv->states[index].flags & CPUIDLE_FLAG_TIMER_STOP); + + if (broadcast) + clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu); + + if (cpuidle_state_is_coupled(dev, drv, index)) + entered_state = cpuidle_enter_state_coupled(dev, drv, index); + else + entered_state = cpuidle_enter_state(dev, drv, index); + + if (broadcast) + clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu); + + return entered_state; +} + +/** + * cpuidle_reflect - tell the underlying governor what was the state + * we were in + * + * @dev : the cpuidle device + * @index: the index in the idle state table + * + */ +void cpuidle_reflect(struct cpuidle_device *dev, int index) +{ + if (cpuidle_curr_governor->reflect) + cpuidle_curr_governor->reflect(dev, index); +} + +/** * cpuidle_idle_call - the main idle loop * * NOTE: no locks or semaphores should be used here @@ -116,51 +181,30 @@ int cpuidle_enter_state(struct cpuidle_device *dev, struct cpuidle_driver *drv, int cpuidle_idle_call(void) { struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices); - struct cpuidle_driver *drv; + struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev); int next_state, entered_state; - bool broadcast; - - if (off || !initialized) - return -ENODEV; - - /* check if the device is ready */ - if (!dev || !dev->enabled) - return -EBUSY; - - drv = cpuidle_get_cpu_driver(dev); /* ask the governor for the next state */ - next_state = cpuidle_curr_governor->select(drv, dev); + next_state = cpuidle_select(drv, dev); + if (next_state < 0) + return next_state; + if (need_resched()) { dev->last_residency = 0; /* give the governor an opportunity to reflect on the outcome */ - if (cpuidle_curr_governor->reflect) - cpuidle_curr_governor->reflect(dev, next_state); + cpuidle_reflect(dev, next_state); local_irq_enable(); return 0; } trace_cpu_idle_rcuidle(next_state, dev->cpu); - broadcast = !!(drv->states[next_state].flags & CPUIDLE_FLAG_TIMER_STOP); - - if (broadcast) - clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu); - - if (cpuidle_state_is_coupled(dev, drv, next_state)) - entered_state = cpuidle_enter_state_coupled(dev, drv, - next_state); - else - entered_state = cpuidle_enter_state(dev, drv, next_state); - - if (broadcast) - clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu); + entered_state = cpuidle_enter(drv, dev, next_state); trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu); /* give the governor an opportunity to reflect on the outcome */ - if (cpuidle_curr_governor->reflect) - cpuidle_curr_governor->reflect(dev, entered_state); + cpuidle_reflect(dev, entered_state); return 0; } diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 50fcbb0..bf06f37 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -119,6 +119,13 @@ struct cpuidle_driver { #ifdef CONFIG_CPU_IDLE extern void disable_cpuidle(void); + +extern int cpuidle_select(struct cpuidle_driver *drv, + struct cpuidle_device *dev); +extern int cpuidle_enter(struct cpuidle_driver *drv, + struct cpuidle_device *dev, int index); +extern void cpuidle_reflect(struct cpuidle_device *dev, int index); + extern int cpuidle_idle_call(void); extern int cpuidle_register_driver(struct cpuidle_driver *drv); extern struct cpuidle_driver *cpuidle_get_driver(void); @@ -141,6 +148,13 @@ extern int cpuidle_play_dead(void); extern struct cpuidle_driver *cpuidle_get_cpu_driver(struct cpuidle_device *dev); #else static inline void disable_cpuidle(void) { } +static inline int cpuidle_select(struct cpuidle_driver *drv, + struct cpuidle_device *dev) +{return -ENODEV; } +static inline int cpuidle_enter(struct cpuidle_driver *drv, + struct cpuidle_device *dev, int index) +{return -ENODEV; } +static inline void cpuidle_reflect(struct cpuidle_device *dev, int index) { } static inline int cpuidle_idle_call(void) { return -ENODEV; } static inline int cpuidle_register_driver(struct cpuidle_driver *drv) {return -ENODEV; }