From 74a06b81ab3770b1de1a7e0b0295361c9a216eba Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Wed, 16 Jan 2019 18:20:08 -0800 Subject: [PATCH] PM / devfreq: icc: Add suspend/resume APIs Absence of traffic is guaranteed when the device sitting behind a devbw device is suspended. In such cases, it is a waste of power to make non-zero bandwidth votes or to scale the devbw device. So, provide APIs to suspend/resume the devbw device as needed. Change-Id: Id58072aec7a9710eb917f248d9b9bd08d3a1ec6a Signed-off-by: Saravana Kannan [avajid@codeaurora.org: renamed devbw to icc and made minor styling change] Signed-off-by: Amir Vajid --- drivers/devfreq/bimc-bwmon.c | 15 +++++++++++---- drivers/devfreq/devfreq_icc.c | 24 +++++++++++++++++++----- include/soc/qcom/devfreq_icc.h | 10 ++++++++++ 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/drivers/devfreq/bimc-bwmon.c b/drivers/devfreq/bimc-bwmon.c index f6b6aa84a48c..8a9e4ef91824 100644 --- a/drivers/devfreq/bimc-bwmon.c +++ b/drivers/devfreq/bimc-bwmon.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2014, 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2015, 2019, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "bimc-bwmon: " fmt @@ -232,7 +232,6 @@ static void stop_bw_hwmon(struct bw_hwmon *hw) { struct bwmon *m = to_bwmon(hw); - disable_irq(m->irq); free_irq(m->irq, m); mon_disable(m); mon_irq_disable(m); @@ -244,7 +243,7 @@ static int suspend_bw_hwmon(struct bw_hwmon *hw) { struct bwmon *m = to_bwmon(hw); - disable_irq(m->irq); + free_irq(m->irq, m); mon_disable(m); mon_irq_disable(m); mon_irq_clear(m); @@ -255,11 +254,19 @@ static int suspend_bw_hwmon(struct bw_hwmon *hw) static int resume_bw_hwmon(struct bw_hwmon *hw) { struct bwmon *m = to_bwmon(hw); + int ret; mon_clear(m); mon_irq_enable(m); mon_enable(m); - enable_irq(m->irq); + ret = request_threaded_irq(m->irq, NULL, bwmon_intr_handler, + IRQF_ONESHOT | IRQF_SHARED, + dev_name(m->dev), m); + if (ret < 0) { + dev_err(m->dev, "Unable to register interrupt handler! (%d)\n", + ret); + return ret; + } return 0; } diff --git a/drivers/devfreq/devfreq_icc.c b/drivers/devfreq/devfreq_icc.c index a052bb7a17d9..28df27a35c31 100644 --- a/drivers/devfreq/devfreq_icc.c +++ b/drivers/devfreq/devfreq_icc.c @@ -163,11 +163,6 @@ int devfreq_add_icc(struct device *dev) return 0; } -static int devfreq_icc_probe(struct platform_device *pdev) -{ - return devfreq_add_icc(&pdev->dev); -} - int devfreq_remove_icc(struct device *dev) { struct dev_data *d = dev_get_drvdata(dev); @@ -177,6 +172,25 @@ int devfreq_remove_icc(struct device *dev) return 0; } +int devfreq_suspend_icc(struct device *dev) +{ + struct dev_data *d = dev_get_drvdata(dev); + + return devfreq_suspend_device(d->df); +} + +int devfreq_resume_icc(struct device *dev) +{ + struct dev_data *d = dev_get_drvdata(dev); + + return devfreq_resume_device(d->df); +} + +static int devfreq_icc_probe(struct platform_device *pdev) +{ + return devfreq_add_icc(&pdev->dev); +} + static int devfreq_icc_remove(struct platform_device *pdev) { return devfreq_remove_icc(&pdev->dev); diff --git a/include/soc/qcom/devfreq_icc.h b/include/soc/qcom/devfreq_icc.h index f3e830d43b4e..f64d12386d81 100644 --- a/include/soc/qcom/devfreq_icc.h +++ b/include/soc/qcom/devfreq_icc.h @@ -11,6 +11,8 @@ #ifdef CONFIG_QCOM_DEVFREQ_ICC int devfreq_add_icc(struct device *dev); int devfreq_remove_icc(struct device *dev); +int devfreq_suspend_icc(struct device *dev); +int devfreq_resume_icc(struct device *dev); #else static inline int devfreq_add_icc(struct device *dev) { @@ -20,6 +22,14 @@ static inline int devfreq_remove_icc(struct device *dev) { return 0; } +static inline int devfreq_suspend_icc(struct device *dev) +{ + return 0; +} +static inline int devfreq_resume_icc(struct device *dev) +{ + return 0; +} #endif #endif /* _DEVFREQ_ICC_H */