From patchwork Tue Jan 8 06:40:36 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: rajagopal.venkat@linaro.org X-Patchwork-Id: 13903 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 51D5A23E2D for ; Tue, 8 Jan 2013 06:44:50 +0000 (UTC) Received: from mail-vc0-f170.google.com (mail-vc0-f170.google.com [209.85.220.170]) by fiordland.canonical.com (Postfix) with ESMTP id E5B7EA1954F for ; Tue, 8 Jan 2013 06:44:49 +0000 (UTC) Received: by mail-vc0-f170.google.com with SMTP id fl11so57292vcb.1 for ; Mon, 07 Jan 2013 22:44:49 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=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 :x-gm-message-state; bh=FlHnkw6ZbB/oDR+6G6d98RNfLaJoSAwENbcLQDG8lz0=; b=cmePSFQRT4dFJsckm00oiVatCyj0RNFAY0C1TJpQbb23Zx5VFU01bjOnpYcVCumSGs 9NKvEBI0rqjtofeypF+xc7yWY8xemZ1yJtovVB6wprjnih4koKfVsaOTcUijhAJPcfDg mw4u1hVZvEXQeLCOETDdFUvKS2kdmB3ctjOBtw+KMTjfGghPmpYTeTgMCls2i0YCdgtc s5KtQkZTBaGSAP0YyF+2ocLeS7WFfppz/3KmQw8MIJzVbqmO7DIEl+LKBEM1b+zocDDW Y5woxwaIwtOW7N1BKpQibYuSoWBsOS0Jzg2q+Jm9C0ZUgbWfol1eTaJ9UPPSK/rdraoO 2TFQ== X-Received: by 10.52.18.207 with SMTP id y15mr74141335vdd.8.1357627489338; Mon, 07 Jan 2013 22:44:49 -0800 (PST) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.58.145.101 with SMTP id st5csp96601veb; Mon, 7 Jan 2013 22:44:48 -0800 (PST) X-Received: by 10.68.237.135 with SMTP id vc7mr195019173pbc.2.1357627487843; Mon, 07 Jan 2013 22:44:47 -0800 (PST) Received: from mail-da0-f44.google.com (mail-da0-f44.google.com [209.85.210.44]) by mx.google.com with ESMTPS id c9si62008204pax.191.2013.01.07.22.44.46 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 07 Jan 2013 22:44:47 -0800 (PST) Received-SPF: neutral (google.com: 209.85.210.44 is neither permitted nor denied by best guess record for domain of rajagopal.venkat@linaro.org) client-ip=209.85.210.44; Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.210.44 is neither permitted nor denied by best guess record for domain of rajagopal.venkat@linaro.org) smtp.mail=rajagopal.venkat@linaro.org Received: by mail-da0-f44.google.com with SMTP id z20so41166dae.17 for ; Mon, 07 Jan 2013 22:44:46 -0800 (PST) X-Received: by 10.68.220.161 with SMTP id px1mr43581366pbc.167.1357627486623; Mon, 07 Jan 2013 22:44:46 -0800 (PST) Received: from localhost.localdomain ([115.184.56.205]) by mx.google.com with ESMTPS id qb3sm39077169pbb.35.2013.01.07.22.44.40 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 07 Jan 2013 22:44:45 -0800 (PST) From: Rajagopal Venkat To: myungjoo.ham@samsung.com, kyungmin.park@samsung.com, mturquette@linaro.org, rjw@sisk.pl Cc: patches@linaro.org, linaro-dev@lists.linaro.org, linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org, Rajagopal Venkat Subject: [RFC PATCH] PM / devfreq: Add runtime-pm support Date: Tue, 8 Jan 2013 12:10:36 +0530 Message-Id: <1357627236-16485-1-git-send-email-rajagopal.venkat@linaro.org> X-Mailer: git-send-email 1.7.10.4 X-Gm-Message-State: ALoCoQmgrxXMmgu1sovbcWQ1WOsLVNmwRC9OlRyN+ApbZmJY9er62p+0ESu2PGuoq71vckz0YXyk Instead of devfreq device driver explicitly calling devfreq suspend and resume apis perhaps from runtime-pm suspend and resume callbacks, let devfreq core handle it automatically. Attach devfreq core to runtime-pm framework so that, devfreq device driver pm_runtime_suspend() will automatically suspend the devfreq and pm_runtime_resume() will resume the devfreq. Signed-off-by: Rajagopal Venkat --- drivers/devfreq/devfreq.c | 89 ++++++++++++++++++++++++++++++++++++++------- include/linux/devfreq.h | 12 ------ 2 files changed, 76 insertions(+), 25 deletions(-) diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 4c50235..781ea47 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -25,10 +25,9 @@ #include #include #include +#include #include "governor.h" -static struct class *devfreq_class; - /* * devfreq core provides delayed work based load monitoring helper * functions. Governors can use these or can implement their own @@ -42,6 +41,9 @@ static LIST_HEAD(devfreq_governor_list); static LIST_HEAD(devfreq_list); static DEFINE_MUTEX(devfreq_list_lock); +static int devfreq_suspend_device(struct devfreq *devfreq); +static int devfreq_resume_device(struct devfreq *devfreq); + /** * find_device_devfreq() - find devfreq struct using device pointer * @dev: device pointer used to lookup device devfreq. @@ -453,6 +455,61 @@ static void devfreq_dev_release(struct device *dev) _remove_devfreq(devfreq, true); } +static int devfreq_runtime_suspend(struct device *dev) +{ + int ret; + struct devfreq *devfreq; + + mutex_lock(&devfreq_list_lock); + devfreq = find_device_devfreq(dev); + mutex_unlock(&devfreq_list_lock); + + ret = devfreq_suspend_device(devfreq); + if (ret < 0) + goto out; + + ret = pm_generic_runtime_suspend(dev); +out: + return ret; +} + +static int devfreq_runtime_resume(struct device *dev) +{ + int ret; + struct devfreq *devfreq; + + mutex_lock(&devfreq_list_lock); + devfreq = find_device_devfreq(dev); + mutex_unlock(&devfreq_list_lock); + + ret = devfreq_resume_device(devfreq); + if (ret < 0) + goto out; + + ret = pm_generic_runtime_resume(dev); +out: + return ret; +} + +static int devfreq_runtime_idle(struct device *dev) +{ + return pm_generic_runtime_idle(dev); +} + +static const struct dev_pm_ops devfreq_pm_ops = { + SET_RUNTIME_PM_OPS( + devfreq_runtime_suspend, + devfreq_runtime_resume, + devfreq_runtime_idle + ) +}; + +static struct class devfreq_class = { + .name = "devfreq", + .owner = THIS_MODULE, + .pm = &devfreq_pm_ops, +}; + /** * devfreq_add_device() - Add devfreq feature to the device * @dev: the device to add devfreq feature. @@ -494,8 +551,9 @@ struct devfreq *devfreq_add_device(struct device *dev, mutex_init(&devfreq->lock); mutex_lock(&devfreq->lock); + dev->class = &devfreq_class; devfreq->dev.parent = dev; - devfreq->dev.class = devfreq_class; + devfreq->dev.class = &devfreq_class; devfreq->dev.release = devfreq_dev_release; devfreq->profile = profile; strncpy(devfreq->governor_name, governor_name, DEVFREQ_NAME_LEN); @@ -538,6 +596,9 @@ struct devfreq *devfreq_add_device(struct device *dev, goto err_init; } + pm_runtime_get_noresume(dev); + pm_runtime_set_active(dev); + return devfreq; err_init: @@ -569,7 +630,7 @@ EXPORT_SYMBOL(devfreq_remove_device); * devfreq_suspend_device() - Suspend devfreq of a device. * @devfreq: the devfreq instance to be suspended */ -int devfreq_suspend_device(struct devfreq *devfreq) +static int devfreq_suspend_device(struct devfreq *devfreq) { if (!devfreq) return -EINVAL; @@ -580,13 +641,12 @@ int devfreq_suspend_device(struct devfreq *devfreq) return devfreq->governor->event_handler(devfreq, DEVFREQ_GOV_SUSPEND, NULL); } -EXPORT_SYMBOL(devfreq_suspend_device); /** * devfreq_resume_device() - Resume devfreq of a device. * @devfreq: the devfreq instance to be resumed */ -int devfreq_resume_device(struct devfreq *devfreq) +static int devfreq_resume_device(struct devfreq *devfreq) { if (!devfreq) return -EINVAL; @@ -597,12 +657,12 @@ int devfreq_resume_device(struct devfreq *devfreq) return devfreq->governor->event_handler(devfreq, DEVFREQ_GOV_RESUME, NULL); } -EXPORT_SYMBOL(devfreq_resume_device); /** * devfreq_add_governor() - Add devfreq governor * @governor: the devfreq governor to be added */ + int devfreq_add_governor(struct devfreq_governor *governor) { struct devfreq_governor *g; @@ -770,6 +830,7 @@ out: ret = count; return ret; } + static ssize_t show_available_governors(struct device *d, struct device_attribute *attr, char *buf) @@ -992,19 +1053,21 @@ static struct device_attribute devfreq_attrs[] = { static int __init devfreq_init(void) { - devfreq_class = class_create(THIS_MODULE, "devfreq"); - if (IS_ERR(devfreq_class)) { + int err; + + err = class_register(&devfreq_class); + if (err < 0) { pr_err("%s: couldn't create class\n", __FILE__); - return PTR_ERR(devfreq_class); + return err; } devfreq_wq = create_freezable_workqueue("devfreq_wq"); if (IS_ERR(devfreq_wq)) { - class_destroy(devfreq_class); + class_unregister(&devfreq_class); pr_err("%s: couldn't create workqueue\n", __FILE__); return PTR_ERR(devfreq_wq); } - devfreq_class->dev_attrs = devfreq_attrs; + devfreq_class.dev_attrs = devfreq_attrs; return 0; } @@ -1012,7 +1075,7 @@ subsys_initcall(devfreq_init); static void __exit devfreq_exit(void) { - class_destroy(devfreq_class); + class_unregister(&devfreq_class); destroy_workqueue(devfreq_wq); } module_exit(devfreq_exit); diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h index e83ef39..b84840c 100644 --- a/include/linux/devfreq.h +++ b/include/linux/devfreq.h @@ -181,8 +181,6 @@ extern struct devfreq *devfreq_add_device(struct device *dev, const char *governor_name, void *data); extern int devfreq_remove_device(struct devfreq *devfreq); -extern int devfreq_suspend_device(struct devfreq *devfreq); -extern int devfreq_resume_device(struct devfreq *devfreq); /* Helper functions for devfreq user device driver with OPP. */ extern struct opp *devfreq_recommended_opp(struct device *dev, @@ -226,16 +224,6 @@ static int devfreq_remove_device(struct devfreq *devfreq) return 0; } -static int devfreq_suspend_device(struct devfreq *devfreq) -{ - return 0; -} - -static int devfreq_resume_device(struct devfreq *devfreq) -{ - return 0; -} - static struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq, u32 flags) {