From patchwork Sun Sep 22 01:21:11 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 20521 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-qe0-f70.google.com (mail-qe0-f70.google.com [209.85.128.70]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 34A2C25E85 for ; Sun, 22 Sep 2013 01:23:28 +0000 (UTC) Received: by mail-qe0-f70.google.com with SMTP id b4sf1938761qen.5 for ; Sat, 21 Sep 2013 18:23:28 -0700 (PDT) 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:in-reply-to:references:in-reply-to:references :x-original-sender:x-original-authentication-results:precedence :mailing-list:list-id:list-post:list-help:list-archive :list-unsubscribe; bh=VaBhF6nMUKFxuT7qrEnWjcj7tD8vXov6RYR8LZSGHTA=; b=WiLy+t9MeCSLx4C9eH7Ug+Y4wzUfzSCK/IeGv4nAmzr+f/xWwsc9IkGUvqqGlTvI43 6Fk+cF3+3yJy0q4322Ivr3AxXxcTufzuLMm4LIm1oirINr6IGATaD6gp0jJK6YA69KbW UTTOw+jtrGiCj5g01Fow5++Rd+kBsbS8Q+sHPH6eaU01jhD8CV16m3BsHJSUtVIrU1ZD THJUK43Pvp8iEUaNqLk2x1HSO2vlsDwhqQ7IFWwZX19DGj7+ur6Kkge6jysb2JTxBxzM 74iBiIPmJukqXc85OAv9xy2Gb2AxW23nWiC9H4D0WSZlh/vLe7BjeS/OaU0v0x4Fqzcn Y2bA== X-Gm-Message-State: ALoCoQlORlxt1LRKd3ybi4Q5WinDa1s/2fZmKHMGjNMNHiqKFetUW+I1lPPgMxCQZN4Nu1O90Pcr X-Received: by 10.224.137.67 with SMTP id v3mr6643180qat.0.1379813008078; Sat, 21 Sep 2013 18:23:28 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.116.228 with SMTP id jz4ls745798qeb.51.gmail; Sat, 21 Sep 2013 18:23:28 -0700 (PDT) X-Received: by 10.52.116.74 with SMTP id ju10mr11857137vdb.20.1379813008006; Sat, 21 Sep 2013 18:23:28 -0700 (PDT) Received: from mail-vb0-f48.google.com (mail-vb0-f48.google.com [209.85.212.48]) by mx.google.com with ESMTPS id is10si4545546veb.70.1969.12.31.16.00.00 (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sat, 21 Sep 2013 18:23:28 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.212.48 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.212.48; Received: by mail-vb0-f48.google.com with SMTP id w16so1373810vbf.35 for ; Sat, 21 Sep 2013 18:23:27 -0700 (PDT) X-Received: by 10.58.117.71 with SMTP id kc7mr14191979veb.16.1379813007905; Sat, 21 Sep 2013 18:23:27 -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.220.174.196 with SMTP id u4csp91767vcz; Sat, 21 Sep 2013 18:23:27 -0700 (PDT) X-Received: by 10.66.218.98 with SMTP id pf2mr275240pac.120.1379813006864; Sat, 21 Sep 2013 18:23:26 -0700 (PDT) Received: from mail-pb0-f46.google.com (mail-pb0-f46.google.com [209.85.160.46]) by mx.google.com with ESMTPS id to1si17466948pab.254.1969.12.31.16.00.00 (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sat, 21 Sep 2013 18:23:26 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.160.46 is neither permitted nor denied by best guess record for domain of viresh.kumar@linaro.org) client-ip=209.85.160.46; Received: by mail-pb0-f46.google.com with SMTP id rq2so1821026pbb.19 for ; Sat, 21 Sep 2013 18:23:26 -0700 (PDT) X-Received: by 10.66.164.136 with SMTP id yq8mr16710618pab.67.1379813006466; Sat, 21 Sep 2013 18:23:26 -0700 (PDT) Received: from localhost ([122.167.152.64]) by mx.google.com with ESMTPSA id fy4sm24699384pbb.1.1969.12.31.16.00.00 (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Sat, 21 Sep 2013 18:23:26 -0700 (PDT) From: Viresh Kumar To: rjw@sisk.pl, daniel.lezcano@linaro.org Cc: linaro-kernel@lists.linaro.org, patches@linaro.org, linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org, Viresh Kumar Subject: [PATCH 19/21] cpuidle: create list of registered drivers Date: Sun, 22 Sep 2013 06:51:11 +0530 Message-Id: <7e9565e323c1e065eeb2a2a1075967bd21ee6066.1379779777.git.viresh.kumar@linaro.org> X-Mailer: git-send-email 1.7.12.rc2.18.g61b472e In-Reply-To: References: In-Reply-To: References: X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: viresh.kumar@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.212.48 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: , Currently we have multiple definitions of few routines based on following config option: CONFIG_CPU_IDLE_MULTIPLE_DRIVERS. These are present to save space by not creating per-cpu variable for platforms which need only one cpuidle driver to be registered for all CPUs. But this setup has a problem. For ARM multi-platform kernel use case this option will get enabled and so we will have per-cpu variables even for platforms that don't need it. The bigger problem is two separate code paths for such platforms for single & multi platform kernels. Which doesn't sound good. A better way of solving this problem would be to create cpuidle driver's list that can be used to manage all information we need. Then we don't really have to write any special code for handling platforms with CONFIG_CPU_IDLE_MULTIPLE_DRIVERS option set. This patch does it. Signed-off-by: Viresh Kumar --- drivers/cpuidle/driver.c | 106 ++++++++++++----------------------------------- include/linux/cpuidle.h | 1 + 2 files changed, 27 insertions(+), 80 deletions(-) diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c index a4a93b4..320b4ec 100644 --- a/drivers/cpuidle/driver.c +++ b/drivers/cpuidle/driver.c @@ -18,10 +18,19 @@ #include "cpuidle.h" DEFINE_SPINLOCK(cpuidle_driver_lock); +static LIST_HEAD(cpuidle_detected_drivers); -#ifdef CONFIG_CPU_IDLE_MULTIPLE_DRIVERS +static inline struct cpuidle_driver * +__cpuidle_get_driver(const struct cpumask *cpumask) +{ + struct cpuidle_driver *drv; + + list_for_each_entry(drv, &cpuidle_detected_drivers, driver_list) + if (cpumask_intersects(drv->cpumask, cpumask)) + return drv; -static DEFINE_PER_CPU(struct cpuidle_driver *, cpuidle_drivers); + return NULL; +} /** * __cpuidle_get_cpu_driver - return the cpuidle driver tied to a CPU. @@ -32,103 +41,39 @@ static DEFINE_PER_CPU(struct cpuidle_driver *, cpuidle_drivers); */ static inline struct cpuidle_driver *__cpuidle_get_cpu_driver(int cpu) { - return per_cpu(cpuidle_drivers, cpu); + return __cpuidle_get_driver(cpumask_of(cpu)); } /** - * __cpuidle_unset_driver - unset per CPU driver variables. + * __cpuidle_add_driver - adds a cpuidle driver to list. * @drv: a valid pointer to a struct cpuidle_driver * - * For each CPU in the driver's CPU mask, unset the registered driver per CPU - * variable. If @drv is different from the registered driver, the corresponding - * variable is not cleared. - */ -static inline void __cpuidle_unset_driver(struct cpuidle_driver *drv) -{ - int cpu; - - for_each_cpu(cpu, drv->cpumask) { - - if (drv != __cpuidle_get_cpu_driver(cpu)) - continue; - - per_cpu(cpuidle_drivers, cpu) = NULL; - } -} - -/** - * __cpuidle_set_driver - set per CPU driver variables for the given driver. - * @drv: a valid pointer to a struct cpuidle_driver - * - * For each CPU in the driver's cpumask, unset the registered driver per CPU - * to @drv. + * Adds cpuidle driver to cpuidle_detected_drivers list if no driver is already + * registered for any CPUs present in drv->cpumask. * * Returns 0 on success, -EBUSY if the CPUs have driver(s) already. */ -static inline int __cpuidle_set_driver(struct cpuidle_driver *drv) -{ - int cpu; - - for_each_cpu(cpu, drv->cpumask) { - - if (__cpuidle_get_cpu_driver(cpu)) { - __cpuidle_unset_driver(drv); - return -EBUSY; - } - - per_cpu(cpuidle_drivers, cpu) = drv; - } - - return 0; -} - -#else - -static struct cpuidle_driver *cpuidle_curr_driver; - -/** - * __cpuidle_get_cpu_driver - return the global cpuidle driver pointer. - * @cpu: ignored without the multiple driver support - * - * Return a pointer to a struct cpuidle_driver object or NULL if no driver was - * previously registered. - */ -static inline struct cpuidle_driver *__cpuidle_get_cpu_driver(int cpu) -{ - return cpuidle_curr_driver; -} - -/** - * __cpuidle_set_driver - assign the global cpuidle driver variable. - * @drv: pointer to a struct cpuidle_driver object - * - * Returns 0 on success, -EBUSY if the driver is already registered. - */ -static inline int __cpuidle_set_driver(struct cpuidle_driver *drv) +static inline int __cpuidle_add_driver(struct cpuidle_driver *drv) { - if (cpuidle_curr_driver) + if (__cpuidle_get_driver(drv->cpumask)) return -EBUSY; - cpuidle_curr_driver = drv; + list_add(&drv->driver_list, &cpuidle_detected_drivers); return 0; } /** - * __cpuidle_unset_driver - unset the global cpuidle driver variable. - * @drv: a pointer to a struct cpuidle_driver + * __cpuidle_remove_driver - remove cpuidle driver from list. + * @drv: a valid pointer to a struct cpuidle_driver * - * Reset the global cpuidle variable to NULL. If @drv does not match the - * registered driver, do nothing. + * Removes cpuidle driver from cpuidle_detected_drivers list. */ -static inline void __cpuidle_unset_driver(struct cpuidle_driver *drv) +static inline void __cpuidle_remove_driver(struct cpuidle_driver *drv) { - if (drv == cpuidle_curr_driver) - cpuidle_curr_driver = NULL; + list_del(&drv->driver_list); } -#endif - /** * cpuidle_setup_broadcast_timer - enable/disable the broadcast timer * @arg: a void pointer used to match the SMP cross call API @@ -158,6 +103,7 @@ static void __cpuidle_driver_init(struct cpuidle_driver *drv) int i; drv->refcnt = 0; + INIT_LIST_HEAD(&drv->driver_list); /* * Use all possible CPUs as the default, because if the kernel boots @@ -244,7 +190,7 @@ static int __cpuidle_register_driver(struct cpuidle_driver *drv) __cpuidle_driver_init(drv); - ret = __cpuidle_set_driver(drv); + ret = __cpuidle_add_driver(drv); if (ret) return ret; @@ -277,7 +223,7 @@ static void __cpuidle_unregister_driver(struct cpuidle_driver *drv) (void *)CLOCK_EVT_NOTIFY_BROADCAST_OFF, 1); } - __cpuidle_unset_driver(drv); + __cpuidle_remove_driver(drv); } /** diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 0f0da17..81b74d2 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -129,6 +129,7 @@ struct cpuidle_driver { /* the driver handles the cpus in cpumask */ struct cpumask *cpumask; + struct list_head driver_list; }; #ifdef CONFIG_CPU_IDLE