From patchwork Wed Apr 10 14:22:10 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Lezcano X-Patchwork-Id: 16021 Return-Path: X-Original-To: linaro@staging.patches.linaro.org Delivered-To: linaro@staging.patches.linaro.org Received: from mail-la0-f72.google.com (mail-la0-f72.google.com [209.85.215.72]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id C893323912 for ; Wed, 10 Apr 2013 14:23:07 +0000 (UTC) Received: by mail-la0-f72.google.com with SMTP id fr10sf694118lab.7 for ; Wed, 10 Apr 2013 07:22:47 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:mime-version:x-beenthere:x-received:received-spf :x-received:x-forwarded-to:x-forwarded-for:delivered-to:x-received :received-spf:x-received:from:to:cc:subject:date:message-id:x-mailer :in-reply-to:references:x-gm-message-state:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :x-google-group-id:list-post:list-help:list-archive:list-unsubscribe; bh=K7QgqeVbTXsPfZD6XMRL1bFyqLKKdYMA1me4rbHr2m4=; b=e/I7HtgFlAAxp/jfL6hkNym+tSgObr/J6pytLre4iokjRO3YvVvpB3CLzgbVvfgF+J cOaagvN4g0k8VZp3i/u39VggrL/cFwvXgkPuDcZ2VDnzg+PETtnNhQH4C36LUAYT0lM0 n1prvuYWO3mPDugAGnAs66udnQ0PjIJwgGR9vUq91Ax26Kfw0ptxwarAdbfO1rz7nP3S NEysNJ9bEbCbe/zC24W7J0HWryBEGZwxaVkKw7zW58CN9y8TGVvwfxPp3ZOBQ8Vr0u9j t10fLri/fuEOqf79zLkVRsqKx8q92OiusbwTukHnoHd63Oxvau1qDhEnF7wRToGkmLPC +FTg== X-Received: by 10.180.106.73 with SMTP id gs9mr5283007wib.2.1365603766895; Wed, 10 Apr 2013 07:22:46 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.180.78.169 with SMTP id c9ls202404wix.13.gmail; Wed, 10 Apr 2013 07:22:46 -0700 (PDT) X-Received: by 10.180.87.193 with SMTP id ba1mr3875718wib.10.1365603766832; Wed, 10 Apr 2013 07:22:46 -0700 (PDT) Received: from mail-ve0-f180.google.com (mail-ve0-f180.google.com [209.85.128.180]) by mx.google.com with ESMTPS id r12si8080134wik.124.2013.04.10.07.22.46 (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 10 Apr 2013 07:22:46 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.128.180 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.128.180; Received: by mail-ve0-f180.google.com with SMTP id c13so443610vea.25 for ; Wed, 10 Apr 2013 07:22:45 -0700 (PDT) X-Received: by 10.52.25.72 with SMTP id a8mr1420745vdg.47.1365603765444; Wed, 10 Apr 2013 07:22:45 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.58.85.136 with SMTP id h8csp107464vez; Wed, 10 Apr 2013 07:22:44 -0700 (PDT) X-Received: by 10.180.87.170 with SMTP id az10mr3916841wib.3.1365603764481; Wed, 10 Apr 2013 07:22:44 -0700 (PDT) Received: from mail-wi0-x229.google.com (mail-wi0-x229.google.com [2a00:1450:400c:c05::229]) by mx.google.com with ESMTPS id ge2si52617wjb.78.2013.04.10.07.22.44 (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 10 Apr 2013 07:22:44 -0700 (PDT) Received-SPF: neutral (google.com: 2a00:1450:400c:c05::229 is neither permitted nor denied by best guess record for domain of daniel.lezcano@linaro.org) client-ip=2a00:1450:400c:c05::229; Received: by mail-wi0-f169.google.com with SMTP id c10so6216521wiw.0 for ; Wed, 10 Apr 2013 07:22:44 -0700 (PDT) X-Received: by 10.194.5.196 with SMTP id u4mr3870293wju.54.1365603764062; Wed, 10 Apr 2013 07:22:44 -0700 (PDT) Received: from mai.home (AToulouse-654-1-413-119.w82-125.abo.wanadoo.fr. [82.125.160.119]) by mx.google.com with ESMTPS id dp5sm32126938wib.1.2013.04.10.07.22.40 (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 10 Apr 2013 07:22:43 -0700 (PDT) From: Daniel Lezcano To: rjw@sisk.pl Cc: linus.walleij@linaro.org, jason@lakedaemon.net, andrew@lunn.ch, kernel@pengutronix.de, swarren@wwwdotorg.org, santosh.shilimkar@ti.com, nicolas.ferre@atmel.com, plagnioj@jcrosoft.com, linux@maxim.org.za, rob.herring@calxeda.com, nsekhar@ti.com, horms@verge.net.au, magnus.damm@gmail.com, deepthi@linux.vnet.ibm.com, lethal@linux-sh.org, jkosina@suse.cz, kgene.kim@samsung.com, khilman@deeprootsystems.com, tony@atomide.com, linux-pm@vger.kernel.org, patches@linaro.org, linux-arm-kernel@lists.infradead.org, linaro-kernel@lists.linaro.org, josephl@nvidia.com Subject: [PATCH 05/18] cpuidle: make a single register function for all Date: Wed, 10 Apr 2013 16:22:10 +0200 Message-Id: <1365603743-5618-6-git-send-email-daniel.lezcano@linaro.org> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1365603743-5618-1-git-send-email-daniel.lezcano@linaro.org> References: <1365603743-5618-1-git-send-email-daniel.lezcano@linaro.org> X-Gm-Message-State: ALoCoQlUvKx1cVNPidIY5sdxC7LWFXO/fwFww8kJM2cvEeXteBKdcVWHxtG5LbmD+F/i2Ftm9xx8 X-Original-Sender: daniel.lezcano@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.128.180 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 Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , The usual scheme to initialize a cpuidle driver on a SMP is: cpuidle_register_driver(drv); for_each_possible_cpu(cpu) { device = &per_cpu(cpuidle_dev, cpu); cpuidle_register_device(device); } This code is duplicated in each cpuidle driver. On UP systems, it is done this way: cpuidle_register_driver(drv); device = &per_cpu(cpuidle_dev, cpu); cpuidle_register_device(device); On UP, the macro 'for_each_cpu' does one iteration: #define for_each_cpu(cpu, mask) \ for ((cpu) = 0; (cpu) < 1; (cpu)++, (void)mask) Hence, the initialization loop is the same for UP than SMP. Beside, we saw different bugs / mis-initialization / return code unchecked in the different drivers, the code is duplicated including bugs. After fixing all these ones, it appears the initialization pattern is the same for everyone. Let's add a wrapper function doing this initialization with a cpumask parameter for the coupled idle states and use it for all the drivers. That will save a lot of LOC, consolidate the code, and the modifications in the future could be done in a single place. Another benefit is the consolidation of the cpuidle_device variable which is now in the cpuidle framework and no longer spread accross the different arch specific drivers. Signed-off-by: Daniel Lezcano --- drivers/cpuidle/cpuidle.c | 65 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/cpuidle.h | 9 +++++-- 2 files changed, 72 insertions(+), 2 deletions(-) diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 0da795b..3a5454b 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -24,6 +24,7 @@ #include "cpuidle.h" DEFINE_PER_CPU(struct cpuidle_device *, cpuidle_devices); +DEFINE_PER_CPU(struct cpuidle_device, cpuidle_dev); DEFINE_MUTEX(cpuidle_lock); LIST_HEAD(cpuidle_detected_devices); @@ -453,6 +454,70 @@ void cpuidle_unregister_device(struct cpuidle_device *dev) EXPORT_SYMBOL_GPL(cpuidle_unregister_device); +/* + * cpuidle_unregister: unregister a driver and the devices. This function + * can be used only if the driver has been previously registered through + * the cpuidle_register function. + * + * @drv: a valid pointer to a struct cpuidle_driver + */ +void cpuidle_unregister(struct cpuidle_driver *drv) +{ + int cpu; + struct cpuidle_device *device; + + for_each_possible_cpu(cpu) { + device = &per_cpu(cpuidle_dev, cpu); + cpuidle_unregister_device(device); + } + + cpuidle_unregister_driver(drv); +} +EXPORT_SYMBOL_GPL(cpuidle_unregister); + +/** + * cpuidle_register: registers the driver and the cpu devices with the + * coupled_cpus passed as parameter. This function is used for all common + * initialization pattern there are in the arch specific drivers. The + * devices is globally defined in this file. + * + * @drv : a valid pointer to a struct cpuidle_driver + * @coupled_cpus: a cpumask for the coupled states + * + * Returns 0 on success, < 0 otherwise + */ +int cpuidle_register(struct cpuidle_driver *drv, + const struct cpumask *const coupled_cpus) +{ + int ret, cpu; + struct cpuidle_device *device; + + ret = cpuidle_register_driver(drv); + if (ret) { + printk(KERN_ERR "failed to register cpuidle driver\n"); + return ret; + } + + for_each_possible_cpu(cpu) { + device = &per_cpu(cpuidle_dev, cpu); + device->cpu = cpu; +#ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED + device->coupled_cpus = *coupled_cpus; +#endif + ret = cpuidle_register_device(device); + if (!ret) + continue; + + printk(KERN_ERR "Failed to register cpuidle " + "device for cpu%d\n", cpu); + cpuidle_unregister(drv); + break; + } + + return 0; +} +EXPORT_SYMBOL_GPL(cpuidle_register); + #ifdef CONFIG_SMP static void smp_callback(void *v) diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 79e3811..3c86faa 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -123,7 +123,9 @@ extern void cpuidle_driver_unref(void); extern void cpuidle_unregister_driver(struct cpuidle_driver *drv); extern int cpuidle_register_device(struct cpuidle_device *dev); extern void cpuidle_unregister_device(struct cpuidle_device *dev); - +extern int cpuidle_register(struct cpuidle_driver *drv, + const struct cpumask *const coupled_cpus); +extern void cpuidle_unregister(struct cpuidle_driver *drv); extern void cpuidle_pause_and_lock(void); extern void cpuidle_resume_and_unlock(void); extern void cpuidle_pause(void); @@ -148,7 +150,10 @@ static inline void cpuidle_unregister_driver(struct cpuidle_driver *drv) { } static inline int cpuidle_register_device(struct cpuidle_device *dev) {return -ENODEV; } static inline void cpuidle_unregister_device(struct cpuidle_device *dev) { } - +static inline int cpuidle_register(struct cpuidle_driver *drv, + const struct cpumask *const coupled_cpus) +{return -ENODEV; } +static inline void cpuidle_unregister(struct cpuidle_driver *drv) { } static inline void cpuidle_pause_and_lock(void) { } static inline void cpuidle_resume_and_unlock(void) { } static inline void cpuidle_pause(void) { }