From patchwork Fri Jun 7 21:53:09 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Lezcano X-Patchwork-Id: 17693 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-qe0-f71.google.com (mail-qe0-f71.google.com [209.85.128.71]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id BB61725E1F for ; Fri, 7 Jun 2013 21:53:17 +0000 (UTC) Received: by mail-qe0-f71.google.com with SMTP id 1sf4879363qee.2 for ; Fri, 07 Jun 2013 14:53:17 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=mime-version:x-beenthere:x-forwarded-to:x-forwarded-for :delivered-to:from:to:cc:subject:date:message-id:x-mailer :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=YuahiPitT8xea+GQl5vWB49G3wnwsg1kK2bGHL+3US0=; b=kNdbipNjsqAAWATPNC75qg+qtwSe0PemX4QcUnGjVGQKKxauEzBp5fqlnOLYW7/LHa g1kHJXBvHjAhaqmyLmy3Q19brl6vr6RVkQrwwr2o1+xn6Qk0NpoZZo5AD1BYVlRGF3Mq JKmxS0UKIah2YdSufjF6fgvldEaEyVu2LCvmyC88WcrGVhCYnLEp2lhV3q0GSDJ8w3sW +LSsiK8cu0BHYGBoiV9SAgFyRsDcrfITB7h5+94mXxUUXUTGK7GFKSYASWkaiic5qMYD Vg/5aNxOhNNSf3y3hHH+GIiR8Qv1t3YpQCBPxfwUtniPD8yGhFixhmJbb0tc6J2KjPPH WOEw== X-Received: by 10.236.150.103 with SMTP id y67mr411224yhj.21.1370641997069; Fri, 07 Jun 2013 14:53:17 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.119.129 with SMTP id ku1ls2037994qeb.49.gmail; Fri, 07 Jun 2013 14:53:16 -0700 (PDT) X-Received: by 10.52.170.165 with SMTP id an5mr171776vdc.89.1370641996714; Fri, 07 Jun 2013 14:53:16 -0700 (PDT) Received: from mail-vc0-f169.google.com (mail-vc0-f169.google.com [209.85.220.169]) by mx.google.com with ESMTPS id zp6si284601vdb.28.2013.06.07.14.53.16 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 07 Jun 2013 14:53:16 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.220.169 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.169; Received: by mail-vc0-f169.google.com with SMTP id ia10so3164702vcb.28 for ; Fri, 07 Jun 2013 14:53:16 -0700 (PDT) X-Received: by 10.220.170.72 with SMTP id c8mr245897vcz.14.1370641996192; Fri, 07 Jun 2013 14:53:16 -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.221.10.206 with SMTP id pb14csp131435vcb; Fri, 7 Jun 2013 14:53:15 -0700 (PDT) X-Received: by 10.180.211.197 with SMTP id ne5mr272553wic.54.1370641994502; Fri, 07 Jun 2013 14:53:14 -0700 (PDT) Received: from mail-wi0-x22e.google.com (mail-wi0-x22e.google.com [2a00:1450:400c:c05::22e]) by mx.google.com with ESMTPS id ls2si265767wjb.20.2013.06.07.14.53.14 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 07 Jun 2013 14:53:14 -0700 (PDT) Received-SPF: neutral (google.com: 2a00:1450:400c:c05::22e is neither permitted nor denied by best guess record for domain of daniel.lezcano@linaro.org) client-ip=2a00:1450:400c:c05::22e; Received: by mail-wi0-f174.google.com with SMTP id k10so1631187wiv.7 for ; Fri, 07 Jun 2013 14:53:13 -0700 (PDT) X-Received: by 10.194.176.41 with SMTP id cf9mr302316wjc.66.1370641993906; Fri, 07 Jun 2013 14:53:13 -0700 (PDT) Received: from mai.home (AToulouse-654-1-404-219.w82-125.abo.wanadoo.fr. [82.125.3.219]) by mx.google.com with ESMTPSA id fu14sm24661498wic.8.2013.06.07.14.53.11 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 07 Jun 2013 14:53:12 -0700 (PDT) From: Daniel Lezcano To: rjw@sisk.pl Cc: francescolavra.fl@gmail.com, lenb@kernel.org, linaro-kernel@lists.linaro.org, patches@linaro.org, linux-pm@vger.kernel.org Subject: [PATCH V4 1/2] cpuidle: simplify multiple driver support Date: Fri, 7 Jun 2013 23:53:09 +0200 Message-Id: <1370641990-13884-1-git-send-email-daniel.lezcano@linaro.org> X-Mailer: git-send-email 1.7.9.5 X-Gm-Message-State: ALoCoQmsmsGJObfP0CQn51GVl9CCAAfQo2PmoB6OpEz5np8R6XVIFLqOnbjbFe9wVEJS5EvgfRq0 X-Original-Sender: daniel.lezcano@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.220.169 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: , Commit bf4d1b5ddb78f86078ac6ae0415802d5f0c68f92 brought the multiple driver support. The code added a couple of new API to register the driver per cpu. That led to some code complexity to handle the kernel config options when the multiple driver support is enabled or not, which is not really necessary. The code has to be compatible when the multiple driver support is not enabled, and the multiple driver support has to be compatible with the old api. This patch removes this API, which is not yet used by any driver but needed for the HMP cpuidle drivers which will come soon, and replaces its usage by a cpumask pointer in the cpuidle driver structure telling what cpus are handled by the driver. That let the API cpuidle_[un]register_driver to be used for the multiple driver support and also the cpuidle_[un]register functions, added recently in the cpuidle framework. Signed-off-by: Daniel Lezcano --- [V4] - uninitialize per cpu driver variable on error - rollback indentation in cpuidle.h [V3] - moved the kerneldoc and comments to a separate patch [V2]: - fixed bad refcount check - inverted clockevent notify off order at unregister time drivers/cpuidle/cpuidle.c | 4 +- drivers/cpuidle/driver.c | 192 +++++++++++++++++++-------------------------- include/linux/cpuidle.h | 6 +- 3 files changed, 84 insertions(+), 118 deletions(-) diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index c3a93fe..fdc432f 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -466,7 +466,7 @@ void cpuidle_unregister(struct cpuidle_driver *drv) int cpu; struct cpuidle_device *device; - for_each_possible_cpu(cpu) { + for_each_cpu(cpu, drv->cpumask) { device = &per_cpu(cpuidle_dev, cpu); cpuidle_unregister_device(device); } @@ -498,7 +498,7 @@ int cpuidle_register(struct cpuidle_driver *drv, return ret; } - for_each_possible_cpu(cpu) { + for_each_cpu(cpu, drv->cpumask) { device = &per_cpu(cpuidle_dev, cpu); device->cpu = cpu; diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c index 8dfaaae..e75fa54 100644 --- a/drivers/cpuidle/driver.c +++ b/drivers/cpuidle/driver.c @@ -18,167 +18,140 @@ DEFINE_SPINLOCK(cpuidle_driver_lock); -static void __cpuidle_set_cpu_driver(struct cpuidle_driver *drv, int cpu); -static struct cpuidle_driver * __cpuidle_get_cpu_driver(int cpu); +#ifdef CONFIG_CPU_IDLE_MULTIPLE_DRIVERS -static void cpuidle_setup_broadcast_timer(void *arg) +static DEFINE_PER_CPU(struct cpuidle_driver *, cpuidle_drivers); + +static struct cpuidle_driver *__cpuidle_get_cpu_driver(int cpu) { - int cpu = smp_processor_id(); - clockevents_notify((long)(arg), &cpu); + return per_cpu(cpuidle_drivers, cpu); } -static void __cpuidle_driver_init(struct cpuidle_driver *drv, int cpu) +static inline void __cpuidle_unset_driver(struct cpuidle_driver *drv) { - int i; - - drv->refcnt = 0; + int cpu; - for (i = drv->state_count - 1; i >= 0 ; i--) { + for_each_cpu(cpu, drv->cpumask) { - if (!(drv->states[i].flags & CPUIDLE_FLAG_TIMER_STOP)) + if (drv != __cpuidle_get_cpu_driver(cpu)) continue; - drv->bctimer = 1; - on_each_cpu_mask(get_cpu_mask(cpu), cpuidle_setup_broadcast_timer, - (void *)CLOCK_EVT_NOTIFY_BROADCAST_ON, 1); - break; + per_cpu(cpuidle_drivers, cpu) = NULL; } } -static int __cpuidle_register_driver(struct cpuidle_driver *drv, int cpu) +static inline int __cpuidle_set_driver(struct cpuidle_driver *drv) { - if (!drv || !drv->state_count) - return -EINVAL; - - if (cpuidle_disabled()) - return -ENODEV; + int cpu; - if (__cpuidle_get_cpu_driver(cpu)) - return -EBUSY; + for_each_cpu(cpu, drv->cpumask) { - __cpuidle_driver_init(drv, cpu); + if (__cpuidle_get_cpu_driver(cpu)) { + __cpuidle_unset_driver(drv); + return -EBUSY; + } - __cpuidle_set_cpu_driver(drv, cpu); + per_cpu(cpuidle_drivers, cpu) = drv; + } return 0; } -static void __cpuidle_unregister_driver(struct cpuidle_driver *drv, int cpu) -{ - if (drv != __cpuidle_get_cpu_driver(cpu)) - return; +#else - if (!WARN_ON(drv->refcnt > 0)) - __cpuidle_set_cpu_driver(NULL, cpu); +static struct cpuidle_driver *cpuidle_curr_driver; - if (drv->bctimer) { - drv->bctimer = 0; - on_each_cpu_mask(get_cpu_mask(cpu), cpuidle_setup_broadcast_timer, - (void *)CLOCK_EVT_NOTIFY_BROADCAST_OFF, 1); - } +static inline struct cpuidle_driver *__cpuidle_get_cpu_driver(int cpu) +{ + return cpuidle_curr_driver; } -#ifdef CONFIG_CPU_IDLE_MULTIPLE_DRIVERS +static inline int __cpuidle_set_driver(struct cpuidle_driver *drv) +{ + if (cpuidle_curr_driver) + return -EBUSY; -static DEFINE_PER_CPU(struct cpuidle_driver *, cpuidle_drivers); + cpuidle_curr_driver = drv; -static void __cpuidle_set_cpu_driver(struct cpuidle_driver *drv, int cpu) -{ - per_cpu(cpuidle_drivers, cpu) = drv; + return 0; } -static struct cpuidle_driver *__cpuidle_get_cpu_driver(int cpu) +static inline void __cpuidle_unset_driver(struct cpuidle_driver *drv) { - return per_cpu(cpuidle_drivers, cpu); + if (drv == cpuidle_curr_driver) + cpuidle_curr_driver = NULL; } -static void __cpuidle_unregister_all_cpu_driver(struct cpuidle_driver *drv) +#endif + +static void cpuidle_setup_broadcast_timer(void *arg) { - int cpu; - for_each_present_cpu(cpu) - __cpuidle_unregister_driver(drv, cpu); + int cpu = smp_processor_id(); + clockevents_notify((long)(arg), &cpu); } -static int __cpuidle_register_all_cpu_driver(struct cpuidle_driver *drv) +static int __cpuidle_driver_init(struct cpuidle_driver *drv) { - int ret = 0; - int i, cpu; + int i; - for_each_present_cpu(cpu) { - ret = __cpuidle_register_driver(drv, cpu); - if (ret) - break; - } + drv->refcnt = 0; - if (ret) - for_each_present_cpu(i) { - if (i == cpu) - break; - __cpuidle_unregister_driver(drv, i); - } + if (!drv->cpumask) + drv->cpumask = (struct cpumask *)cpu_possible_mask; + for (i = drv->state_count - 1; i >= 0 ; i--) { - return ret; + if (!(drv->states[i].flags & CPUIDLE_FLAG_TIMER_STOP)) + continue; + + drv->bctimer = 1; + break; + } + + return 0; } -int cpuidle_register_cpu_driver(struct cpuidle_driver *drv, int cpu) +static int __cpuidle_register_driver(struct cpuidle_driver *drv) { int ret; - spin_lock(&cpuidle_driver_lock); - ret = __cpuidle_register_driver(drv, cpu); - spin_unlock(&cpuidle_driver_lock); + if (!drv || !drv->state_count) + return -EINVAL; - return ret; -} + if (cpuidle_disabled()) + return -ENODEV; -void cpuidle_unregister_cpu_driver(struct cpuidle_driver *drv, int cpu) -{ - spin_lock(&cpuidle_driver_lock); - __cpuidle_unregister_driver(drv, cpu); - spin_unlock(&cpuidle_driver_lock); -} + ret = __cpuidle_driver_init(drv); + if (ret) + return ret; -/** - * cpuidle_register_driver - registers a driver - * @drv: the driver - */ -int cpuidle_register_driver(struct cpuidle_driver *drv) -{ - int ret; + ret = __cpuidle_set_driver(drv); + if (ret) + return ret; - spin_lock(&cpuidle_driver_lock); - ret = __cpuidle_register_all_cpu_driver(drv); - spin_unlock(&cpuidle_driver_lock); + if (drv->bctimer) + on_each_cpu_mask(drv->cpumask, cpuidle_setup_broadcast_timer, + (void *)CLOCK_EVT_NOTIFY_BROADCAST_ON, 1); - return ret; + return 0; } -EXPORT_SYMBOL_GPL(cpuidle_register_driver); /** * cpuidle_unregister_driver - unregisters a driver * @drv: the driver */ -void cpuidle_unregister_driver(struct cpuidle_driver *drv) +static void __cpuidle_unregister_driver(struct cpuidle_driver *drv) { - spin_lock(&cpuidle_driver_lock); - __cpuidle_unregister_all_cpu_driver(drv); - spin_unlock(&cpuidle_driver_lock); -} -EXPORT_SYMBOL_GPL(cpuidle_unregister_driver); - -#else - -static struct cpuidle_driver *cpuidle_curr_driver; + if (WARN_ON(drv->refcnt > 0)) + return; -static inline void __cpuidle_set_cpu_driver(struct cpuidle_driver *drv, int cpu) -{ - cpuidle_curr_driver = drv; -} + if (drv->bctimer) { + drv->bctimer = 0; + on_each_cpu_mask(drv->cpumask, cpuidle_setup_broadcast_timer, + (void *)CLOCK_EVT_NOTIFY_BROADCAST_OFF, 1); + } -static inline struct cpuidle_driver *__cpuidle_get_cpu_driver(int cpu) -{ - return cpuidle_curr_driver; + __cpuidle_unset_driver(drv); } /** @@ -187,13 +160,11 @@ static inline struct cpuidle_driver *__cpuidle_get_cpu_driver(int cpu) */ int cpuidle_register_driver(struct cpuidle_driver *drv) { - int ret, cpu; + int ret; - cpu = get_cpu(); spin_lock(&cpuidle_driver_lock); - ret = __cpuidle_register_driver(drv, cpu); + ret = __cpuidle_register_driver(drv); spin_unlock(&cpuidle_driver_lock); - put_cpu(); return ret; } @@ -205,16 +176,11 @@ EXPORT_SYMBOL_GPL(cpuidle_register_driver); */ void cpuidle_unregister_driver(struct cpuidle_driver *drv) { - int cpu; - - cpu = get_cpu(); spin_lock(&cpuidle_driver_lock); - __cpuidle_unregister_driver(drv, cpu); + __cpuidle_unregister_driver(drv); spin_unlock(&cpuidle_driver_lock); - put_cpu(); } EXPORT_SYMBOL_GPL(cpuidle_unregister_driver); -#endif /** * cpuidle_get_driver - return the current driver diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 8f04062..0bc4b74 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -111,6 +111,9 @@ struct cpuidle_driver { struct cpuidle_state states[CPUIDLE_STATE_MAX]; int state_count; int safe_state_index; + + /* the driver handles the cpus in cpumask */ + struct cpumask *cpumask; }; #ifdef CONFIG_CPU_IDLE @@ -135,9 +138,6 @@ extern void cpuidle_disable_device(struct cpuidle_device *dev); extern int cpuidle_play_dead(void); extern struct cpuidle_driver *cpuidle_get_cpu_driver(struct cpuidle_device *dev); -extern int cpuidle_register_cpu_driver(struct cpuidle_driver *drv, int cpu); -extern void cpuidle_unregister_cpu_driver(struct cpuidle_driver *drv, int cpu); - #else static inline void disable_cpuidle(void) { } static inline int cpuidle_idle_call(void) { return -ENODEV; }