* Re: Recent "Run the driver callback directly" patch breaks libertas suspend
From: Rafael J. Wysocki @ 2012-03-25 21:25 UTC (permalink / raw)
To: NeilBrown; +Cc: linux-pm, Chris Ball, linux-mmc, lkml
In-Reply-To: <201203252309.48705.rjw@sisk.pl>
On Sunday, March 25, 2012, Rafael J. Wysocki wrote:
> Hi,
>
> On Sunday, March 25, 2012, NeilBrown wrote:
> >
> > Hi Rafael,
> >
> > Your recent patch:
> > commit 35cd133c
> > PM: Run the driver callback directly if the subsystem one is not there
> >
> > breaks suspend for my libertas wifi and probably other SDIO devices.
>
> Well, the patch is not recent. The _commit_ is more than three months old
> and the patch has been around since the last November (at least).
>
> > SDIO (and possible MMC in general) has a protocol where the suspend
> > method can return -ENOSYS and this means "There is no point in suspending,
> > just turn me off".
> >
> > The device itself "mmc1:0001" (I think) doesn't have any bus etc 'suspend'
> > function so the new code call the device's suspend function which returns
> > ENOSYS and the suspend fails.
> >
> > The previous code ignores the device as there is no bus suspend, and when it
> > gets to suspend the ancestor - which for me is omap_hsmmc.1, it calls the
> > device suspend function catches the ENOSYS, and turns it off.
>
> Well, I can only call that a blatant abuse of the PM infrastructure.
>
> > I suspect just reverting it isn't the right long term solution, however I
> > can confirm that it works for me for now.
>
> It's not a solution at all, because there's code that depends on it already in
> the tree and the fact that it works for you doesn't mean it won't break other
> systems. So no, it's not an option.
>
> > I'm happy to try any alternate fixes you would like to suggest (but I cannot
> > promise how quickly I will get the testing done).
> >
> > (I'm testing with 3.3)
>
> The only fix I can think of is to rework SDIO to stop abusing the PM callbacks.
> I'll have a look at that next week, although I can't promise anything any time
> soon, because I'm heading to San Francisco on Saturday.
Well, this is kind of a long shot, but I wonder if the patch below makes
any difference?
Rafael
---
drivers/mmc/core/sdio_bus.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
Index: linux/drivers/mmc/core/sdio_bus.c
===================================================================
--- linux.orig/drivers/mmc/core/sdio_bus.c
+++ linux/drivers/mmc/core/sdio_bus.c
@@ -192,9 +192,15 @@ static int sdio_bus_remove(struct device
return ret;
}
-#ifdef CONFIG_PM_RUNTIME
+#ifdef CONFIG_PM
+
+static int pm_no_operation(struct device *dev)
+{
+ return 0;
+}
static const struct dev_pm_ops sdio_bus_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(pm_no_operation, pm_no_operation)
SET_RUNTIME_PM_OPS(
pm_generic_runtime_suspend,
pm_generic_runtime_resume,
@@ -204,11 +210,11 @@ static const struct dev_pm_ops sdio_bus_
#define SDIO_PM_OPS_PTR (&sdio_bus_pm_ops)
-#else /* !CONFIG_PM_RUNTIME */
+#else /* !CONFIG_PM */
#define SDIO_PM_OPS_PTR NULL
-#endif /* !CONFIG_PM_RUNTIME */
+#endif /* !CONFIG_PM */
static struct bus_type sdio_bus_type = {
.name = "sdio",
^ permalink raw reply
* Re: Recent "Run the driver callback directly" patch breaks libertas suspend
From: NeilBrown @ 2012-03-25 21:45 UTC (permalink / raw)
To: Rafael J. Wysocki; +Cc: linux-pm, Chris Ball, linux-mmc, lkml
In-Reply-To: <201203252325.37478.rjw@sisk.pl>
[-- Attachment #1.1: Type: text/plain, Size: 3671 bytes --]
On Sun, 25 Mar 2012 23:25:37 +0200 "Rafael J. Wysocki" <rjw@sisk.pl> wrote:
> On Sunday, March 25, 2012, Rafael J. Wysocki wrote:
> > Hi,
> >
> > On Sunday, March 25, 2012, NeilBrown wrote:
> > >
> > > Hi Rafael,
> > >
> > > Your recent patch:
> > > commit 35cd133c
> > > PM: Run the driver callback directly if the subsystem one is not there
> > >
> > > breaks suspend for my libertas wifi and probably other SDIO devices.
> >
> > Well, the patch is not recent. The _commit_ is more than three months old
> > and the patch has been around since the last November (at least).
> >
> > > SDIO (and possible MMC in general) has a protocol where the suspend
> > > method can return -ENOSYS and this means "There is no point in suspending,
> > > just turn me off".
> > >
> > > The device itself "mmc1:0001" (I think) doesn't have any bus etc 'suspend'
> > > function so the new code call the device's suspend function which returns
> > > ENOSYS and the suspend fails.
> > >
> > > The previous code ignores the device as there is no bus suspend, and when it
> > > gets to suspend the ancestor - which for me is omap_hsmmc.1, it calls the
> > > device suspend function catches the ENOSYS, and turns it off.
> >
> > Well, I can only call that a blatant abuse of the PM infrastructure.
> >
> > > I suspect just reverting it isn't the right long term solution, however I
> > > can confirm that it works for me for now.
> >
> > It's not a solution at all, because there's code that depends on it already in
> > the tree and the fact that it works for you doesn't mean it won't break other
> > systems. So no, it's not an option.
> >
> > > I'm happy to try any alternate fixes you would like to suggest (but I cannot
> > > promise how quickly I will get the testing done).
> > >
> > > (I'm testing with 3.3)
> >
> > The only fix I can think of is to rework SDIO to stop abusing the PM callbacks.
> > I'll have a look at that next week, although I can't promise anything any time
> > soon, because I'm heading to San Francisco on Saturday.
>
> Well, this is kind of a long shot, but I wonder if the patch below makes
> any difference?
Hi Rafael,
thanks for looking into this so quickly.
I removed the revert and applied this patch instead and can confirm that
suspend completes now (and resume works and the wifi works after resume).
Further, this patch fits with my (fairly shallow) understanding of the
problem.
Thanks!
NeilBrown
>
> Rafael
>
> ---
> drivers/mmc/core/sdio_bus.c | 12 +++++++++---
> 1 file changed, 9 insertions(+), 3 deletions(-)
>
> Index: linux/drivers/mmc/core/sdio_bus.c
> ===================================================================
> --- linux.orig/drivers/mmc/core/sdio_bus.c
> +++ linux/drivers/mmc/core/sdio_bus.c
> @@ -192,9 +192,15 @@ static int sdio_bus_remove(struct device
> return ret;
> }
>
> -#ifdef CONFIG_PM_RUNTIME
> +#ifdef CONFIG_PM
> +
> +static int pm_no_operation(struct device *dev)
> +{
> + return 0;
> +}
>
> static const struct dev_pm_ops sdio_bus_pm_ops = {
> + SET_SYSTEM_SLEEP_PM_OPS(pm_no_operation, pm_no_operation)
> SET_RUNTIME_PM_OPS(
> pm_generic_runtime_suspend,
> pm_generic_runtime_resume,
> @@ -204,11 +210,11 @@ static const struct dev_pm_ops sdio_bus_
>
> #define SDIO_PM_OPS_PTR (&sdio_bus_pm_ops)
>
> -#else /* !CONFIG_PM_RUNTIME */
> +#else /* !CONFIG_PM */
>
> #define SDIO_PM_OPS_PTR NULL
>
> -#endif /* !CONFIG_PM_RUNTIME */
> +#endif /* !CONFIG_PM */
>
> static struct bus_type sdio_bus_type = {
> .name = "sdio",
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 828 bytes --]
[-- Attachment #2: Type: text/plain, Size: 0 bytes --]
^ permalink raw reply
* [PATCH 1/3] cpuidle: use the driver's state_count as default
From: Daniel Lezcano @ 2012-03-26 12:51 UTC (permalink / raw)
To: lenb; +Cc: linux-pm, linaro-dev, patches
If the state_count is not initialized for the device use
the driver's state count as the default. That will prevent
to add it manually in the cpuidle driver initialization
routine and will save us from duplicate line of code.
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
drivers/cpuidle/cpuidle.c | 2 +-
drivers/cpuidle/driver.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index 27f77a4..b8a1faf 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -268,7 +268,7 @@ int cpuidle_enable_device(struct cpuidle_device *dev)
if (!drv || !cpuidle_curr_governor)
return -EIO;
if (!dev->state_count)
- return -EINVAL;
+ dev->state_count = drv->state_count;
if (dev->registered == 0) {
ret = __cpuidle_register_device(dev);
diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c
index 284d7af..40cd3f3 100644
--- a/drivers/cpuidle/driver.c
+++ b/drivers/cpuidle/driver.c
@@ -47,7 +47,7 @@ static void __cpuidle_register_driver(struct cpuidle_driver *drv)
*/
int cpuidle_register_driver(struct cpuidle_driver *drv)
{
- if (!drv)
+ if (!drv || !drv->state_count)
return -EINVAL;
if (cpuidle_disabled())
--
1.7.5.4
^ permalink raw reply related
* [PATCH 2/3] cpuidle: remove useless array definition in cpuidle_structure
From: Daniel Lezcano @ 2012-03-26 12:51 UTC (permalink / raw)
To: lenb-DgEjT+Ai2ygdnm+yROfE0A
Cc: linux-pm-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
linaro-dev-cunTk1MwBs8s++Sfvej+rw, patches-QSEj5FYQhm4dnm+yROfE0A
In-Reply-To: <1332766288-30412-1-git-send-email-daniel.lezcano-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
All the modules name are ro-data, it is never copied to the array.
eg.
static struct cpuidle_driver intel_idle_driver = {
.name = "intel_idle",
.owner = THIS_MODULE,
};
It safe to assign the pointer of this ro-data to a const char *.
By this way we save 12 bytes.
Signed-off-by: Daniel Lezcano <daniel.lezcano-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Acked-by: Deepthi Dharwar <deepthi-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
Tested-by: Deepthi Dharwar <deepthi-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
---
include/linux/cpuidle.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
index ca4e498..f7f1d90 100644
--- a/include/linux/cpuidle.h
+++ b/include/linux/cpuidle.h
@@ -120,7 +120,7 @@ static inline int cpuidle_get_last_residency(struct cpuidle_device *dev)
****************************/
struct cpuidle_driver {
- char name[CPUIDLE_NAME_LEN];
+ const char *name;
struct module *owner;
unsigned int power_specified:1;
--
1.7.5.4
^ permalink raw reply related
* [PATCH 3/3] cpuidle: remove unused 'governor_data' field
From: Daniel Lezcano @ 2012-03-26 12:51 UTC (permalink / raw)
To: lenb-DgEjT+Ai2ygdnm+yROfE0A
Cc: linux-pm-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
linaro-dev-cunTk1MwBs8s++Sfvej+rw, patches-QSEj5FYQhm4dnm+yROfE0A
In-Reply-To: <1332766288-30412-1-git-send-email-daniel.lezcano-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
As far as I can see, this field is never used in the code.
Signed-off-by: Daniel Lezcano <daniel.lezcano-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
include/linux/cpuidle.h | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
index f7f1d90..f3ebbba 100644
--- a/include/linux/cpuidle.h
+++ b/include/linux/cpuidle.h
@@ -98,7 +98,6 @@ struct cpuidle_device {
struct list_head device_list;
struct kobject kobj;
struct completion kobj_unregister;
- void *governor_data;
};
DECLARE_PER_CPU(struct cpuidle_device *, cpuidle_devices);
--
1.7.5.4
^ permalink raw reply related
* Reminder about your invitation from Kunjan Shah
From: Kunjan Shah (LinkedIn Invitations) @ 2012-03-27 9:35 UTC (permalink / raw)
To: linux-pm
[-- Attachment #1.1: Type: text/plain, Size: 811 bytes --]
LinkedIn
------------
This is a reminder that on March 24, Kunjan Shah sent you an invitation to become part of their professional network at LinkedIn.
Accept Kunjan Shah's Invitation
----------
On March 24, Kunjan Shah wrote:
> To: [linux-pm@lists.linux-foundation.org]
> From: Kunjan Shah [kunjanpshah@gmail.com]
> Subject: Invitation to connect on LinkedIn
>
> I'd like to add you to my professional network on LinkedIn.
>
> - Kunjan
----------
You are receiving Reminder emails for pending invitations. Click to unsubscribe:
http://www.linkedin.com/e/8tznj9-h0ar2iyz-u/Tu26r8ft-NY4IGf2LXhCd4a2-9TSX366pN_su_TZ_g0SzZKV-Ijl/goo/linux-pm%40lists%2Elinux-foundation%2Eorg/20060/I2227723104_1/?hs=false&tok=0CZYVO6BF_Zl81
(c) 2012 LinkedIn Corporation. 2029 Stierlin Ct, Mountain View, CA 94043, USA.
[-- Attachment #1.2: Type: text/html, Size: 5954 bytes --]
[-- Attachment #2: Type: text/plain, Size: 0 bytes --]
^ permalink raw reply
* Re: Regarding Devfreq
From: Satendra... @ 2012-03-28 12:11 UTC (permalink / raw)
To: linux-pm
In-Reply-To: <0M18009PVCPE8JM0@mailout1.samsung.com>
[-- Attachment #1.1.1: Type: text/plain, Size: 4594 bytes --]
Hi Ham,
In the below struct :
struct devfreq_dev_status {
/* both since the last measure */
unsigned long total_time;
unsigned long busy_time;
unsigned long current_frequency;
void *private_data;
};
How to calculate total_time/busy_time? Does it require hardware support
(may be some performance counters)?
Thanks,
Satendra
On 21 March 2012 15:49, 함명주 <myungjoo.ham@samsung.com> wrote:
> Hi Stendra,
>
>
>
> - Bascially, you can determine the voltage based on frequency; thus, we do
> not need to determint voltages at DVFS framework. It is corresponding
> device driver's responsibility even when we have AVS features. Thus, yes,
> the target callback needs to control both frequency and voltage (and
> anything else required to change the frequency/voltage)
>
>
>
> - I recommend to use regulator framework to control regulators unless you
> really really need to ignore regulator framework. Don't reinvent the wheel.
>
>
>
> - The three steps you've mentioned are correct.
>
>
>
> - The mailing list is opened to all. You are welcomed to use it (CC'ed
> linux-pm) and just CC needed people.
>
>
>
>
>
> Cheers!
>
> MyungJoo.
>
>
>
> ------- *Original Message* -------
>
> *Sender* : Satendra...<satendra.pratap@gmail.com>
>
> *Date* : 2012-03-21 19:03 (GMT+09:00)
>
> *Title* : Re: Re: Regarding Devfreq
>
>
> Hi Ham,
>
> Thank you very much for your reply. I will try not to disturb you much.
> In Devfreq I dont see any API related to voltage scaling. Is it the
> "->target" function's (in struct devfreq_dev_profile)
> responsibility to change the voltage as well with frequency?
> Do we really need to register our regulators using regulator framework of
> linux for voltage scaling?
>
> For a clear understanding I need to do following to use devfreq (I am
> sorry as I may be verifying it again):
> - define an instance of "struct devfreq_dev_profile" and provide
> implementations of target, get_dev_status and exit callbacks
> - Implement our choice of governer or use any one from already implemented
> ones.
> - call "devfreq_add_device" function from our driver's probe function.
>
> is that it? or do we need to do something else also?
>
> Thanks,
> Satendra
>
>
> On 21 March 2012 15:14, 함명주 <myungjoo.ham@samsung.com> wrote:
>
>> Hello Satendra,
>>
>>
>>
>> - For Devfreq, OPP is optional though recommended for easier
>> implementation. You can still implement all the needed things without OPP.
>> OPP is just a simple data structure to store pairs of voltage and frequency.
>>
>>
>>
>> - Yes, you need to call devfreq_add_device() and supply the required
>> data. You can implement your own governor or use one of predefined
>> governors. Runtime replacement of governors like CPUfreq is "TODO" for now.
>>
>>
>>
>> - For example, you can see /drivers/devfreq/exynos4_bus.c. GPU, Display
>> devfreq drivers are under development in other companies (ARM).
>>
>>
>>
>> Cheers!
>>
>> MyungJoo.
>>
>>
>>
>>
>>
>> ------- *Original Message* -------
>>
>> *Sender* : Satendra...<satendra.pratap@gmail.com>
>>
>> *Date* : 2012-03-21 17:31 (GMT+09:00)
>>
>> *Title* : Re: Regarding Devfreq
>>
>>
>> Hi Ham,
>>
>> I have studied DVFS and what I feel is that we need to use OPP and
>> Voltage regulator interfaces also to
>> maintain Optimum Performance Points and to provide APIs to change the
>> voltage.
>> What I feel is that to use DVFS every driver has to
>> call devfreq_add_device function to register that device to
>> the devfreq framework. And in order to do that we have to
>> implement devfreq_dev_profile and our choice of governer.
>>
>> I appreciate your help.
>>
>> Thanks,
>> Satendra
>>
>> On 20 March 2012 12:16, Satendra... <satendra.pratap@gmail.com> wrote:
>>
>>> Hi Ham,
>>>
>>> We are working on a new SoC for our new product and would want to use
>>> your Devfreq
>>> framework for our devices. Would you please let me know any other
>>> implementation which
>>> uses devfreq ? so that we could take that as a reference.
>>> Or we would be the first one to start?
>>>
>>> Thanks,
>>> Satendra
>>>
>>
>>
>>
>>
>>
>> --
>>
>> MyungJoo Ham (함명주), PHD
>> System S/W Lab, S/W Platform Team, Software Center
>> Samsung Electronics
>> Cell: +82-10-6714-2858
>>
>>
>>
>>
>
>
>
>
> --
>
> MyungJoo Ham (함명주), PHD
> System S/W Lab, S/W Platform Team, Software Center
> Samsung Electronics
> Cell: +82-10-6714-2858
>
>
>
>
[-- Attachment #1.1.2: Type: text/html, Size: 7365 bytes --]
[-- Attachment #1.2: 201203211919122_7EUABGFC.jpg --]
[-- Type: image/jpeg, Size: 72722 bytes --]
[-- Attachment #1.3: 201203211919047_QKNMBDIF.jpg --]
[-- Type: image/jpeg, Size: 72722 bytes --]
[-- Attachment #2: Type: text/plain, Size: 0 bytes --]
^ permalink raw reply
* Re: Regarding Devfreq
From: MyungJoo Ham @ 2012-03-29 2:14 UTC (permalink / raw)
To: Satendra...; +Cc: linux-pm
In-Reply-To: <CAChS5kPtG3kk9dH9twMp68XKs6eLgQSiN49_ehsHAEddCHsJDg@mail.gmail.com>
2012/3/28 Satendra... <satendra.pratap@gmail.com>
>
> Hi Ham,
>
> In the below struct :
> struct devfreq_dev_status {
> /* both since the last measure */
> unsigned long total_time;
> unsigned long busy_time;
> unsigned long current_frequency;
> void *private_data;
> };
>
> How to calculate total_time/busy_time? Does it require hardware support
> (may be some performance counters)?
>
> Thanks,
> Satendra
It is decided by each devfreq device driver, which is why
get_dev_status() is to be provided by the devfreq device driver.
If the device has performance counters, then, it's great, but
performance counters are not mandatory.
Here goes a list of mechanisms to fetch busy/total time:
- Performance counters
- Measure the time between "operation start" and "operation end" and
accumulate the time (getting busy time. probably by ktime?)
- Measure the idle time (CPUIDLE/CPUFREQ does this)
- Count the number of operation and calculate the operational time
based on the number.
- and so on.
As you can see in the list, you don't need a hardware support such as
performance counters.
Cheers!
MyungJoo.
>
>
> On 21 March 2012 15:49, 함명주 <myungjoo.ham@samsung.com> wrote:
>>
>> Hi Stendra,
>>
>>
>>
>> - Bascially, you can determine the voltage based on frequency; thus, we
>> do not need to determint voltages at DVFS framework. It is corresponding
>> device driver's responsibility even when we have AVS features. Thus, yes,
>> the target callback needs to control both frequency and voltage (and
>> anything else required to change the frequency/voltage)
>>
>>
>>
>> - I recommend to use regulator framework to control regulators unless you
>> really really need to ignore regulator framework. Don't reinvent the wheel.
>>
>>
>>
>> - The three steps you've mentioned are correct.
>>
>>
>>
>> - The mailing list is opened to all. You are welcomed to use it (CC'ed
>> linux-pm) and just CC needed people.
>>
>>
>>
>>
>>
>> Cheers!
>>
>> MyungJoo.
>>
>>
>>
>> ------- Original Message -------
>>
>> Sender : Satendra...<satendra.pratap@gmail.com>
>>
>> Date : 2012-03-21 19:03 (GMT+09:00)
>>
>> Title : Re: Re: Regarding Devfreq
>>
>>
>>
>> Hi Ham,
>>
>> Thank you very much for your reply. I will try not to disturb you much.
>> In Devfreq I dont see any API related to voltage scaling. Is it the
>> "->target" function's (in struct devfreq_dev_profile)
>> responsibility to change the voltage as well with frequency?
>> Do we really need to register our regulators using regulator framework of
>> linux for voltage scaling?
>>
>> For a clear understanding I need to do following to use devfreq (I am
>> sorry as I may be verifying it again):
>> - define an instance of "struct devfreq_dev_profile" and provide
>> implementations of target, get_dev_status and exit callbacks
>> - Implement our choice of governer or use any one from already
>> implemented ones.
>> - call "devfreq_add_device" function from our driver's probe function.
>>
>> is that it? or do we need to do something else also?
>>
>> Thanks,
>> Satendra
>>
>>
>> On 21 March 2012 15:14, 함명주 <myungjoo.ham@samsung.com> wrote:
>>>
>>> Hello Satendra,
>>>
>>>
>>>
>>> - For Devfreq, OPP is optional though recommended for easier
>>> implementation. You can still implement all the needed things without OPP.
>>> OPP is just a simple data structure to store pairs of voltage and frequency.
>>>
>>>
>>>
>>> - Yes, you need to call devfreq_add_device() and supply the required
>>> data. You can implement your own governor or use one of predefined
>>> governors. Runtime replacement of governors like CPUfreq is "TODO" for now.
>>>
>>>
>>>
>>> - For example, you can see /drivers/devfreq/exynos4_bus.c. GPU, Display
>>> devfreq drivers are under development in other companies (ARM).
>>>
>>>
>>>
>>> Cheers!
>>>
>>> MyungJoo.
>>>
>>>
>>>
>>>
>>>
>>> ------- Original Message -------
>>>
>>> Sender : Satendra...<satendra.pratap@gmail.com>
>>>
>>> Date : 2012-03-21 17:31 (GMT+09:00)
>>>
>>> Title : Re: Regarding Devfreq
>>>
>>>
>>>
>>> Hi Ham,
>>>
>>> I have studied DVFS and what I feel is that we need to use OPP and
>>> Voltage regulator interfaces also to
>>> maintain Optimum Performance Points and to provide APIs to change the
>>> voltage.
>>> What I feel is that to use DVFS every driver has to
>>> call devfreq_add_device function to register that device to
>>> the devfreq framework. And in order to do that we have to
>>> implement devfreq_dev_profile and our choice of governer.
>>>
>>> I appreciate your help.
>>>
>>> Thanks,
>>> Satendra
>>>
>>> On 20 March 2012 12:16, Satendra... <satendra.pratap@gmail.com> wrote:
>>>>
>>>> Hi Ham,
>>>>
>>>> We are working on a new SoC for our new product and would want to use
>>>> your Devfreq
>>>> framework for our devices. Would you please let me know any other
>>>> implementation which
>>>> uses devfreq ? so that we could take that as a reference.
>>>> Or we would be the first one to start?
>>>>
>>>> Thanks,
>>>> Satendra
>>>
>>>
>>>
>>>
>>>
>>>
>>> --
>>>
>>> MyungJoo Ham (함명주), PHD
>>>
>>> System S/W Lab, S/W Platform Team, Software Center
>>> Samsung Electronics
>>> Cell: +82-10-6714-2858
>>>
>>>
>>
>>
>>
>>
>>
>>
>> --
>>
>> MyungJoo Ham (함명주), PHD
>>
>> System S/W Lab, S/W Platform Team, Software Center
>> Samsung Electronics
>> Cell: +82-10-6714-2858
>>
>>
>
>
>
> _______________________________________________
> linux-pm mailing list
> linux-pm@lists.linux-foundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/linux-pm
--
MyungJoo Ham, Ph.D.
System S/W Lab, S/W Center, Samsung Electronics
_______________________________________________
linux-pm mailing list
linux-pm@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/linux-pm
^ permalink raw reply
* Regarding CPU idle C states
From: Zhichao Li @ 2012-03-29 20:58 UTC (permalink / raw)
To: linux-pm
Hi,
I am a third year PhD student working on power management in storage
systems, under the Linux platform.
We are exploring CPU DVFS, and also idle CPU C states. We figured out
that the scheduling of CPU frequencies is exported to user level with
the "userspace" governor. However, it seems the multiple idle C states
are only scheduled in the kernel space (governors like "menu" and
"ladder").
We wonder whether there is any existing kernel module or existing
kernel patch that can export the various idle CPU C states to the user
level for user's control as well. If you could guide us to such
code/patch, or if you have plan to do so, we'd be more than happy to
help you testing the code for various idle CPU C states in the user
level.
Thanks for your time. Appreciated it!
Regards,
--
Zhichao Li
File Systems and Storage Lab
Computer Science Department
Stony Brook University
^ permalink raw reply
* Re: Regarding CPU idle C states
From: Valentin, Eduardo @ 2012-03-30 6:41 UTC (permalink / raw)
To: Zhichao Li, ShuoX Liu; +Cc: linux-pm
In-Reply-To: <CAOUN_DfbAAsAmySTOQ_-zQLbFnCEOnvSsjdXevs9OBXkAgGCUQ@mail.gmail.com>
Hello Zhichao,
On Thu, Mar 29, 2012 at 11:58 PM, Zhichao Li <lzcmichael@gmail.com> wrote:
> Hi,
>
> I am a third year PhD student working on power management in storage
> systems, under the Linux platform.
Good :-)
>
> We are exploring CPU DVFS, and also idle CPU C states. We figured out
> that the scheduling of CPU frequencies is exported to user level with
> the "userspace" governor. However, it seems the multiple idle C states
> are only scheduled in the kernel space (governors like "menu" and
> "ladder").
OK. Which kind of exploration you are performing? Any published paper
you would like to point?
>
> We wonder whether there is any existing kernel module or existing
> kernel patch that can export the various idle CPU C states to the user
> level for user's control as well. If you could guide us to such
> code/patch, or if you have plan to do so, we'd be more than happy to
> help you testing the code for various idle CPU C states in the user
> level.
Have you seen this patch?
https://lkml.org/lkml/2012/3/5/30
It's original purpose is for debugging. One can enable of disable the
C states available. There has been some discussion about that patch
regarding its usage for userspace based governors. But it should be
enough for your purpose. In theory you could keep enabled only the C
state you want to force to be reached.
>
> Thanks for your time. Appreciated it!
>
> Regards,
>
> --
> Zhichao Li
> File Systems and Storage Lab
> Computer Science Department
> Stony Brook University
> _______________________________________________
> linux-pm mailing list
> linux-pm@lists.linux-foundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/linux-pm
--
Eduardo Valentin
^ permalink raw reply
* ACPI & Power Management patches for Linux-3.4
From: Len Brown @ 2012-03-30 10:13 UTC (permalink / raw)
To: linux-acpi, linux-pm; +Cc: linux-kernel
Here is the ACPI & PM queue for the Linux-3.4 merge window.
Had to drop a couple of patches due to merge conflicts --
hopefully will get back to those shortly...
Let me know what I missed.
thanks,
Len Brown, Intel Open Source Technology Center
^ permalink raw reply
* [PATCH 01/76] x86, acpi, tboot: Have a ACPI os prepare sleep instead of calling tboot_sleep.
From: Len Brown @ 2012-03-30 10:13 UTC (permalink / raw)
To: linux-acpi, linux-pm
Cc: linux-kernel, Tang Liang, Len Brown, Konrad Rzeszutek Wilk
In-Reply-To: <1333102459-23750-1-git-send-email-lenb@kernel.org>
From: Tang Liang <liang.tang@oracle.com>
The ACPI suspend path makes a call to tboot_sleep right before
it writes the PM1A, PM1B values. We replace the direct call to
tboot via an registration callback similar to __acpi_register_gsi.
CC: Len Brown <len.brown@intel.com>
Acked-by: Joseph Cihula <joseph.cihula@intel.com>
Acked-by: Rafael J. Wysocki <rjw@sisk.pl>
[v1: Added __attribute__ ((unused))]
[v2: Introduced a wrapper instead of changing tboot_sleep return values]
[v3: Added return value AE_CTRL_SKIP for acpi_os_sleep_prepare]
Signed-off-by: Tang Liang <liang.tang@oracle.com>
[v1: Fix compile issues on IA64 and PPC64]
[v2: Fix where __acpi_os_prepare_sleep==NULL and did not go in sleep properly]
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
arch/x86/kernel/tboot.c | 8 ++++++++
drivers/acpi/acpica/hwsleep.c | 10 +++++++---
drivers/acpi/osl.c | 24 ++++++++++++++++++++++++
include/acpi/acexcep.h | 1 +
include/linux/acpi.h | 10 ++++++++++
include/linux/tboot.h | 1 -
6 files changed, 50 insertions(+), 4 deletions(-)
diff --git a/arch/x86/kernel/tboot.c b/arch/x86/kernel/tboot.c
index e2410e2..1a4ab7d 100644
--- a/arch/x86/kernel/tboot.c
+++ b/arch/x86/kernel/tboot.c
@@ -297,6 +297,12 @@ void tboot_sleep(u8 sleep_state, u32 pm1a_control, u32 pm1b_control)
tboot_shutdown(acpi_shutdown_map[sleep_state]);
}
+static int tboot_sleep_wrapper(u8 sleep_state, u32 pm1a_control,
+ u32 pm1b_control)
+{
+ tboot_sleep(sleep_state, pm1a_control, pm1b_control);
+ return 0;
+}
static atomic_t ap_wfs_count;
@@ -345,6 +351,8 @@ static __init int tboot_late_init(void)
atomic_set(&ap_wfs_count, 0);
register_hotcpu_notifier(&tboot_cpu_notifier);
+
+ acpi_os_set_prepare_sleep(&tboot_sleep_wrapper);
return 0;
}
diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c
index d52da30..992359a 100644
--- a/drivers/acpi/acpica/hwsleep.c
+++ b/drivers/acpi/acpica/hwsleep.c
@@ -43,9 +43,9 @@
*/
#include <acpi/acpi.h>
+#include <linux/acpi.h>
#include "accommon.h"
#include "actables.h"
-#include <linux/tboot.h>
#include <linux/module.h>
#define _COMPONENT ACPI_HARDWARE
@@ -344,8 +344,12 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
ACPI_FLUSH_CPU_CACHE();
- tboot_sleep(sleep_state, pm1a_control, pm1b_control);
-
+ status = acpi_os_prepare_sleep(sleep_state, pm1a_control,
+ pm1b_control);
+ if (ACPI_SKIP(status))
+ return_ACPI_STATUS(AE_OK);
+ if (ACPI_FAILURE(status))
+ return_ACPI_STATUS(status);
/* Write #2: Write both SLP_TYP + SLP_EN */
status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control);
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index f31c5c5..f3aae4b 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -76,6 +76,9 @@ EXPORT_SYMBOL(acpi_in_debugger);
extern char line_buf[80];
#endif /*ENABLE_DEBUGGER */
+static int (*__acpi_os_prepare_sleep)(u8 sleep_state, u32 pm1a_ctrl,
+ u32 pm1b_ctrl);
+
static acpi_osd_handler acpi_irq_handler;
static void *acpi_irq_context;
static struct workqueue_struct *kacpid_wq;
@@ -1659,3 +1662,24 @@ acpi_status acpi_os_terminate(void)
return AE_OK;
}
+
+acpi_status acpi_os_prepare_sleep(u8 sleep_state, u32 pm1a_control,
+ u32 pm1b_control)
+{
+ int rc = 0;
+ if (__acpi_os_prepare_sleep)
+ rc = __acpi_os_prepare_sleep(sleep_state,
+ pm1a_control, pm1b_control);
+ if (rc < 0)
+ return AE_ERROR;
+ else if (rc > 0)
+ return AE_CTRL_SKIP;
+
+ return AE_OK;
+}
+
+void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state,
+ u32 pm1a_ctrl, u32 pm1b_ctrl))
+{
+ __acpi_os_prepare_sleep = func;
+}
diff --git a/include/acpi/acexcep.h b/include/acpi/acexcep.h
index 5b6c391..fa0d22c 100644
--- a/include/acpi/acexcep.h
+++ b/include/acpi/acexcep.h
@@ -57,6 +57,7 @@
#define ACPI_SUCCESS(a) (!(a))
#define ACPI_FAILURE(a) (a)
+#define ACPI_SKIP(a) (a == AE_CTRL_SKIP)
#define AE_OK (acpi_status) 0x0000
/*
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 6001b4da..fccd017 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -359,4 +359,14 @@ static inline int suspend_nvs_register(unsigned long a, unsigned long b)
}
#endif
+#ifdef CONFIG_ACPI
+void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state,
+ u32 pm1a_ctrl, u32 pm1b_ctrl));
+
+acpi_status acpi_os_prepare_sleep(u8 sleep_state,
+ u32 pm1a_control, u32 pm1b_control);
+#else
+#define acpi_os_set_prepare_sleep(func, pm1a_ctrl, pm1b_ctrl) do { } while (0)
+#endif
+
#endif /*_LINUX_ACPI_H*/
diff --git a/include/linux/tboot.h b/include/linux/tboot.h
index 1dba6ee..c75128b 100644
--- a/include/linux/tboot.h
+++ b/include/linux/tboot.h
@@ -143,7 +143,6 @@ static inline int tboot_enabled(void)
extern void tboot_probe(void);
extern void tboot_shutdown(u32 shutdown_type);
-extern void tboot_sleep(u8 sleep_state, u32 pm1a_control, u32 pm1b_control);
extern struct acpi_table_header *tboot_get_dmar_table(
struct acpi_table_header *dmar_tbl);
extern int tboot_force_iommu(void);
--
1.7.10.rc2.19.gfae9d
^ permalink raw reply related
* [PATCH 02/76] tboot: Add return values for tboot_sleep
From: Len Brown @ 2012-03-30 10:13 UTC (permalink / raw)
To: linux-acpi, linux-pm; +Cc: linux-kernel, Konrad Rzeszutek Wilk
In-Reply-To: <09f98a825a821f7a3f1b162f9ed023f37213a63b.1333101989.git.len.brown@intel.com>
From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
.. as appropiately. As tboot_sleep now returns values.
remove tboot_sleep_wrapper.
Suggested-and-Acked-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Joseph Cihula <joseph.cihula@intel.com>
[v1: Return -1/0/+1 instead of ACPI_xx values]
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
arch/x86/kernel/tboot.c | 13 ++++---------
1 file changed, 4 insertions(+), 9 deletions(-)
diff --git a/arch/x86/kernel/tboot.c b/arch/x86/kernel/tboot.c
index 1a4ab7d..6410744 100644
--- a/arch/x86/kernel/tboot.c
+++ b/arch/x86/kernel/tboot.c
@@ -272,7 +272,7 @@ static void tboot_copy_fadt(const struct acpi_table_fadt *fadt)
offsetof(struct acpi_table_facs, firmware_waking_vector);
}
-void tboot_sleep(u8 sleep_state, u32 pm1a_control, u32 pm1b_control)
+static int tboot_sleep(u8 sleep_state, u32 pm1a_control, u32 pm1b_control)
{
static u32 acpi_shutdown_map[ACPI_S_STATE_COUNT] = {
/* S0,1,2: */ -1, -1, -1,
@@ -281,7 +281,7 @@ void tboot_sleep(u8 sleep_state, u32 pm1a_control, u32 pm1b_control)
/* S5: */ TB_SHUTDOWN_S5 };
if (!tboot_enabled())
- return;
+ return 0;
tboot_copy_fadt(&acpi_gbl_FADT);
tboot->acpi_sinfo.pm1a_cnt_val = pm1a_control;
@@ -292,15 +292,10 @@ void tboot_sleep(u8 sleep_state, u32 pm1a_control, u32 pm1b_control)
if (sleep_state >= ACPI_S_STATE_COUNT ||
acpi_shutdown_map[sleep_state] == -1) {
pr_warning("unsupported sleep state 0x%x\n", sleep_state);
- return;
+ return -1;
}
tboot_shutdown(acpi_shutdown_map[sleep_state]);
-}
-static int tboot_sleep_wrapper(u8 sleep_state, u32 pm1a_control,
- u32 pm1b_control)
-{
- tboot_sleep(sleep_state, pm1a_control, pm1b_control);
return 0;
}
@@ -352,7 +347,7 @@ static __init int tboot_late_init(void)
atomic_set(&ap_wfs_count, 0);
register_hotcpu_notifier(&tboot_cpu_notifier);
- acpi_os_set_prepare_sleep(&tboot_sleep_wrapper);
+ acpi_os_set_prepare_sleep(&tboot_sleep);
return 0;
}
--
1.7.10.rc2.19.gfae9d
^ permalink raw reply related
* [PATCH 03/76] ACPI: ignore FADT reset-reg-sup flag
From: Len Brown @ 2012-03-30 10:13 UTC (permalink / raw)
To: linux-acpi, linux-pm; +Cc: linux-kernel, Len Brown
In-Reply-To: <09f98a825a821f7a3f1b162f9ed023f37213a63b.1333101989.git.len.brown@intel.com>
From: Len Brown <len.brown@intel.com>
we check that the address is non-zero later anyway.
https://bugzilla.kernel.org/show_bug.cgi?id=11533
Signed-off-by: Len Brown <len.brown@intel.com>
---
drivers/acpi/acpica/hwxface.c | 3 +--
drivers/acpi/reboot.c | 3 +--
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c
index 9d38eb6..fe1fb63 100644
--- a/drivers/acpi/acpica/hwxface.c
+++ b/drivers/acpi/acpica/hwxface.c
@@ -74,8 +74,7 @@ acpi_status acpi_reset(void)
/* Check if the reset register is supported */
- if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) ||
- !reset_reg->address) {
+ if (!reset_reg->address) {
return_ACPI_STATUS(AE_NOT_EXIST);
}
diff --git a/drivers/acpi/reboot.c b/drivers/acpi/reboot.c
index a6c77e8b..c1d6124 100644
--- a/drivers/acpi/reboot.c
+++ b/drivers/acpi/reboot.c
@@ -23,8 +23,7 @@ void acpi_reboot(void)
/* Is the reset register supported? The spec says we should be
* checking the bit width and bit offset, but Windows ignores
* these fields */
- if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER))
- return;
+ /* Ignore also acpi_gbl_FADT.flags.ACPI_FADT_RESET_REGISTER */
reset_value = acpi_gbl_FADT.reset_value;
--
1.7.10.rc2.19.gfae9d
^ permalink raw reply related
* [PATCH 04/76] ACPICA: Fix regression in FADT revision checks
From: Len Brown @ 2012-03-30 10:13 UTC (permalink / raw)
To: linux-acpi, linux-pm; +Cc: Len Brown, Julian Anastasov, linux-kernel
In-Reply-To: <09f98a825a821f7a3f1b162f9ed023f37213a63b.1333101989.git.len.brown@intel.com>
From: Julian Anastasov <ja@ssi.bg>
commit 64b3db22c04586997ab4be46dd5a5b99f8a2d390 (2.6.39),
"Remove use of unreliable FADT revision field" causes regression
for old P4 systems because now cst_control and other fields are
not reset to 0.
The effect is that acpi_processor_power_init will notice
cst_control != 0 and a write to CST_CNT register is performed
that should not happen. As result, the system oopses after the
"No _CST, giving up" message, sometimes in acpi_ns_internalize_name,
sometimes in acpi_ns_get_type, usually at random places. May be
during migration to CPU 1 in acpi_processor_get_throttling.
Every one of these settings help to avoid this problem:
- acpi=off
- processor.nocst=1
- maxcpus=1
The fix is to update acpi_gbl_FADT.header.length after
the original value is used to check for old revisions.
https://bugzilla.kernel.org/show_bug.cgi?id=42700
https://bugzilla.redhat.com/show_bug.cgi?id=727865
Signed-off-by: Julian Anastasov <ja@ssi.bg>
Acked-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
---
drivers/acpi/acpica/tbfadt.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c
index c5d8704..4c9c760 100644
--- a/drivers/acpi/acpica/tbfadt.c
+++ b/drivers/acpi/acpica/tbfadt.c
@@ -363,10 +363,6 @@ static void acpi_tb_convert_fadt(void)
u32 address32;
u32 i;
- /* Update the local FADT table header length */
-
- acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt);
-
/*
* Expand the 32-bit FACS and DSDT addresses to 64-bit as necessary.
* Later code will always use the X 64-bit field. Also, check for an
@@ -408,6 +404,10 @@ static void acpi_tb_convert_fadt(void)
acpi_gbl_FADT.boot_flags = 0;
}
+ /* Update the local FADT table header length */
+
+ acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt);
+
/*
* Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X"
* generic address structures as necessary. Later code will always use
--
1.7.10.rc2.19.gfae9d
^ permalink raw reply related
* [PATCH 05/76] cpuidle: Add common time keeping and irq enabling
From: Len Brown @ 2012-03-30 10:13 UTC (permalink / raw)
To: linux-acpi, linux-pm; +Cc: linux-kernel, Robert Lee, Len Brown
In-Reply-To: <09f98a825a821f7a3f1b162f9ed023f37213a63b.1333101989.git.len.brown@intel.com>
From: Robert Lee <rob.lee@linaro.org>
Make necessary changes to implement time keeping and irq enabling
in the core cpuidle code. This will allow the removal of these
functionalities from various platform cpuidle implementations whose
timekeeping and irq enabling follows the form in this common code.
Signed-off-by: Robert Lee <rob.lee@linaro.org>
Tested-by: Jean Pihet <j-pihet@ti.com>
Tested-by: Amit Daniel <amit.kachhap@linaro.org>
Tested-by: Robert Lee <rob.lee@linaro.org>
Reviewed-by: Kevin Hilman <khilman@ti.com>
Reviewed-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Reviewed-by: Deepthi Dharwar <deepthi@linux.vnet.ibm.com>
Acked-by: Jean Pihet <j-pihet@ti.com>
Signed-off-by: Len Brown <len.brown@intel.com>
---
arch/arm/include/asm/cpuidle.h | 29 ++++++++++++++++++
arch/arm/kernel/Makefile | 2 +-
arch/arm/kernel/cpuidle.c | 21 +++++++++++++
drivers/cpuidle/cpuidle.c | 66 +++++++++++++++++++++++++++++++++++-----
include/linux/cpuidle.h | 13 +++++++-
5 files changed, 122 insertions(+), 9 deletions(-)
create mode 100644 arch/arm/include/asm/cpuidle.h
create mode 100644 arch/arm/kernel/cpuidle.c
diff --git a/arch/arm/include/asm/cpuidle.h b/arch/arm/include/asm/cpuidle.h
new file mode 100644
index 0000000..2fca60a
--- /dev/null
+++ b/arch/arm/include/asm/cpuidle.h
@@ -0,0 +1,29 @@
+#ifndef __ASM_ARM_CPUIDLE_H
+#define __ASM_ARM_CPUIDLE_H
+
+#ifdef CONFIG_CPU_IDLE
+extern int arm_cpuidle_simple_enter(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv, int index);
+#else
+static inline int arm_cpuidle_simple_enter(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv, int index) { return -ENODEV; }
+#endif
+
+/* Common ARM WFI state */
+#define ARM_CPUIDLE_WFI_STATE_PWR(p) {\
+ .enter = arm_cpuidle_simple_enter,\
+ .exit_latency = 1,\
+ .target_residency = 1,\
+ .power_usage = p,\
+ .flags = CPUIDLE_FLAG_TIME_VALID,\
+ .name = "WFI",\
+ .desc = "ARM WFI",\
+}
+
+/*
+ * in case power_specified == 1, give a default WFI power value needed
+ * by some governors
+ */
+#define ARM_CPUIDLE_WFI_STATE ARM_CPUIDLE_WFI_STATE_PWR(UINT_MAX)
+
+#endif
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 43b740d..940c27f 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -21,7 +21,7 @@ obj-$(CONFIG_DEPRECATED_PARAM_STRUCT) += compat.o
obj-$(CONFIG_LEDS) += leds.o
obj-$(CONFIG_OC_ETM) += etm.o
-
+obj-$(CONFIG_CPU_IDLE) += cpuidle.o
obj-$(CONFIG_ISA_DMA_API) += dma.o
obj-$(CONFIG_ARCH_ACORN) += ecard.o
obj-$(CONFIG_FIQ) += fiq.o fiqasm.o
diff --git a/arch/arm/kernel/cpuidle.c b/arch/arm/kernel/cpuidle.c
new file mode 100644
index 0000000..89545f6
--- /dev/null
+++ b/arch/arm/kernel/cpuidle.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2012 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/cpuidle.h>
+#include <asm/proc-fns.h>
+
+int arm_cpuidle_simple_enter(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv, int index)
+{
+ cpu_do_idle();
+
+ return index;
+}
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index 59f4261..4869b55 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -53,6 +53,24 @@ static void cpuidle_kick_cpus(void) {}
static int __cpuidle_register_device(struct cpuidle_device *dev);
+static inline int cpuidle_enter(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv, int index)
+{
+ struct cpuidle_state *target_state = &drv->states[index];
+ return target_state->enter(dev, drv, index);
+}
+
+static inline int cpuidle_enter_tk(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv, int index)
+{
+ return cpuidle_wrap_enter(dev, drv, index, cpuidle_enter);
+}
+
+typedef int (*cpuidle_enter_t)(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv, int index);
+
+static cpuidle_enter_t cpuidle_enter_ops;
+
/**
* cpuidle_idle_call - the main idle loop
*
@@ -63,7 +81,6 @@ int cpuidle_idle_call(void)
{
struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices);
struct cpuidle_driver *drv = cpuidle_get_driver();
- struct cpuidle_state *target_state;
int next_state, entered_state;
if (off)
@@ -92,12 +109,10 @@ int cpuidle_idle_call(void)
return 0;
}
- target_state = &drv->states[next_state];
-
trace_power_start(POWER_CSTATE, next_state, dev->cpu);
trace_cpu_idle(next_state, dev->cpu);
- entered_state = target_state->enter(dev, drv, next_state);
+ entered_state = cpuidle_enter_ops(dev, drv, next_state);
trace_power_end(dev->cpu);
trace_cpu_idle(PWR_EVENT_EXIT, dev->cpu);
@@ -110,6 +125,8 @@ int cpuidle_idle_call(void)
dev->states_usage[entered_state].time +=
(unsigned long long)dev->last_residency;
dev->states_usage[entered_state].usage++;
+ } else {
+ dev->last_residency = 0;
}
/* give the governor an opportunity to reflect on the outcome */
@@ -164,6 +181,37 @@ void cpuidle_resume_and_unlock(void)
EXPORT_SYMBOL_GPL(cpuidle_resume_and_unlock);
+/**
+ * cpuidle_wrap_enter - performs timekeeping and irqen around enter function
+ * @dev: pointer to a valid cpuidle_device object
+ * @drv: pointer to a valid cpuidle_driver object
+ * @index: index of the target cpuidle state.
+ */
+int cpuidle_wrap_enter(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv, int index,
+ int (*enter)(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv, int index))
+{
+ ktime_t time_start, time_end;
+ s64 diff;
+
+ time_start = ktime_get();
+
+ index = enter(dev, drv, index);
+
+ time_end = ktime_get();
+
+ local_irq_enable();
+
+ diff = ktime_to_us(ktime_sub(time_end, time_start));
+ if (diff > INT_MAX)
+ diff = INT_MAX;
+
+ dev->last_residency = (int) diff;
+
+ return index;
+}
+
#ifdef CONFIG_ARCH_HAS_CPU_RELAX
static int poll_idle(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index)
@@ -212,10 +260,11 @@ static void poll_idle_init(struct cpuidle_driver *drv) {}
int cpuidle_enable_device(struct cpuidle_device *dev)
{
int ret, i;
+ struct cpuidle_driver *drv = cpuidle_get_driver();
if (dev->enabled)
return 0;
- if (!cpuidle_get_driver() || !cpuidle_curr_governor)
+ if (!drv || !cpuidle_curr_governor)
return -EIO;
if (!dev->state_count)
return -EINVAL;
@@ -226,13 +275,16 @@ int cpuidle_enable_device(struct cpuidle_device *dev)
return ret;
}
- poll_idle_init(cpuidle_get_driver());
+ cpuidle_enter_ops = drv->en_core_tk_irqen ?
+ cpuidle_enter_tk : cpuidle_enter;
+
+ poll_idle_init(drv);
if ((ret = cpuidle_add_state_sysfs(dev)))
return ret;
if (cpuidle_curr_governor->enable &&
- (ret = cpuidle_curr_governor->enable(cpuidle_get_driver(), dev)))
+ (ret = cpuidle_curr_governor->enable(drv, dev)))
goto fail_sysfs;
for (i = 0; i < dev->state_count; i++) {
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
index 712abcc..927db28 100644
--- a/include/linux/cpuidle.h
+++ b/include/linux/cpuidle.h
@@ -15,6 +15,7 @@
#include <linux/list.h>
#include <linux/kobject.h>
#include <linux/completion.h>
+#include <linux/hrtimer.h>
#define CPUIDLE_STATE_MAX 8
#define CPUIDLE_NAME_LEN 16
@@ -122,6 +123,8 @@ struct cpuidle_driver {
struct module *owner;
unsigned int power_specified:1;
+ /* set to 1 to use the core cpuidle time keeping (for all states). */
+ unsigned int en_core_tk_irqen:1;
struct cpuidle_state states[CPUIDLE_STATE_MAX];
int state_count;
int safe_state_index;
@@ -140,7 +143,10 @@ extern void cpuidle_pause_and_lock(void);
extern void cpuidle_resume_and_unlock(void);
extern int cpuidle_enable_device(struct cpuidle_device *dev);
extern void cpuidle_disable_device(struct cpuidle_device *dev);
-
+extern int cpuidle_wrap_enter(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv, int index,
+ int (*enter)(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv, int index));
#else
static inline void disable_cpuidle(void) { }
static inline int cpuidle_idle_call(void) { return -ENODEV; }
@@ -157,6 +163,11 @@ static inline void cpuidle_resume_and_unlock(void) { }
static inline int cpuidle_enable_device(struct cpuidle_device *dev)
{return -ENODEV; }
static inline void cpuidle_disable_device(struct cpuidle_device *dev) { }
+static inline int cpuidle_wrap_enter(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv, int index,
+ int (*enter)(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv, int index))
+{ return -ENODEV; }
#endif
--
1.7.10.rc2.19.gfae9d
^ permalink raw reply related
* [PATCH 06/76] ARM: at91: Consolidate time keeping and irq enable
From: Len Brown @ 2012-03-30 10:13 UTC (permalink / raw)
To: linux-acpi, linux-pm; +Cc: linux-kernel, Robert Lee, Len Brown
In-Reply-To: <09f98a825a821f7a3f1b162f9ed023f37213a63b.1333101989.git.len.brown@intel.com>
From: Robert Lee <rob.lee@linaro.org>
Enable core cpuidle timekeeping and irq enabling and remove that
handling from this code.
Signed-off-by: Robert Lee <rob.lee@linaro.org>
Reviewed-by: Kevin Hilman <khilman@ti.com>
Reviewed-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Acked-by: Jean Pihet <j-pihet@ti.com>
Signed-off-by: Len Brown <len.brown@intel.com>
---
arch/arm/mach-at91/cpuidle.c | 67 +++++++++++++++---------------------------
1 file changed, 24 insertions(+), 43 deletions(-)
diff --git a/arch/arm/mach-at91/cpuidle.c b/arch/arm/mach-at91/cpuidle.c
index a851e6c..d40b3f3 100644
--- a/arch/arm/mach-at91/cpuidle.c
+++ b/arch/arm/mach-at91/cpuidle.c
@@ -17,9 +17,10 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/cpuidle.h>
-#include <asm/proc-fns.h>
#include <linux/io.h>
#include <linux/export.h>
+#include <asm/proc-fns.h>
+#include <asm/cpuidle.h>
#include "pm.h"
@@ -27,66 +28,46 @@
static DEFINE_PER_CPU(struct cpuidle_device, at91_cpuidle_device);
-static struct cpuidle_driver at91_idle_driver = {
- .name = "at91_idle",
- .owner = THIS_MODULE,
-};
-
/* Actual code that puts the SoC in different idle states */
static int at91_enter_idle(struct cpuidle_device *dev,
struct cpuidle_driver *drv,
int index)
{
- struct timeval before, after;
- int idle_time;
u32 saved_lpr;
- local_irq_disable();
- do_gettimeofday(&before);
- if (index == 0)
- /* Wait for interrupt state */
- cpu_do_idle();
- else if (index == 1) {
- asm("b 1f; .align 5; 1:");
- asm("mcr p15, 0, r0, c7, c10, 4"); /* drain write buffer */
- saved_lpr = sdram_selfrefresh_enable();
- cpu_do_idle();
- sdram_selfrefresh_disable(saved_lpr);
- }
- do_gettimeofday(&after);
- local_irq_enable();
- idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
- (after.tv_usec - before.tv_usec);
+ __asm__("b 1f; .align 5; 1:\n"
+ " mcr p15, 0, r0, c7, c10, 4"); /* drain write buffer */
+
+ saved_lpr = sdram_selfrefresh_enable();
+ cpu_do_idle();
+ sdram_selfrefresh_disable(saved_lpr);
- dev->last_residency = idle_time;
return index;
}
+static struct cpuidle_driver at91_idle_driver = {
+ .name = "at91_idle",
+ .owner = THIS_MODULE,
+ .en_core_tk_irqen = 1,
+ .states[0] = ARM_CPUIDLE_WFI_STATE,
+ .states[1] = {
+ .enter = at91_enter_idle,
+ .exit_latency = 10,
+ .target_residency = 100000,
+ .flags = CPUIDLE_FLAG_TIME_VALID,
+ .name = "RAM_SR",
+ .desc = "WFI and DDR Self Refresh",
+ },
+ .state_count = AT91_MAX_STATES,
+};
+
/* Initialize CPU idle by registering the idle states */
static int at91_init_cpuidle(void)
{
struct cpuidle_device *device;
- struct cpuidle_driver *driver = &at91_idle_driver;
device = &per_cpu(at91_cpuidle_device, smp_processor_id());
device->state_count = AT91_MAX_STATES;
- driver->state_count = AT91_MAX_STATES;
-
- /* Wait for interrupt state */
- driver->states[0].enter = at91_enter_idle;
- driver->states[0].exit_latency = 1;
- driver->states[0].target_residency = 10000;
- driver->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
- strcpy(driver->states[0].name, "WFI");
- strcpy(driver->states[0].desc, "Wait for interrupt");
-
- /* Wait for interrupt and RAM self refresh state */
- driver->states[1].enter = at91_enter_idle;
- driver->states[1].exit_latency = 10;
- driver->states[1].target_residency = 10000;
- driver->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
- strcpy(driver->states[1].name, "RAM_SR");
- strcpy(driver->states[1].desc, "WFI and RAM Self Refresh");
cpuidle_register_driver(&at91_idle_driver);
--
1.7.10.rc2.19.gfae9d
^ permalink raw reply related
* [PATCH 07/76] ARM: kirkwood: Consolidate time keeping and irq enable
From: Len Brown @ 2012-03-30 10:13 UTC (permalink / raw)
To: linux-acpi, linux-pm; +Cc: Len Brown, Robert Lee, linux-kernel
In-Reply-To: <09f98a825a821f7a3f1b162f9ed023f37213a63b.1333101989.git.len.brown@intel.com>
From: Robert Lee <rob.lee@linaro.org>
Enable core cpuidle timekeeping and irq enabling and remove that
handling from this code.
Signed-off-by: Robert Lee <rob.lee@linaro.org>
Reviewed-by: Kevin Hilman <khilman@ti.com>
Reviewed-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Acked-by: Jean Pihet <j-pihet@ti.com>
Signed-off-by: Len Brown <len.brown@intel.com>
---
arch/arm/mach-kirkwood/cpuidle.c | 72 +++++++++++---------------------------
1 file changed, 21 insertions(+), 51 deletions(-)
diff --git a/arch/arm/mach-kirkwood/cpuidle.c b/arch/arm/mach-kirkwood/cpuidle.c
index 7088180..0f17109 100644
--- a/arch/arm/mach-kirkwood/cpuidle.c
+++ b/arch/arm/mach-kirkwood/cpuidle.c
@@ -20,77 +20,47 @@
#include <linux/io.h>
#include <linux/export.h>
#include <asm/proc-fns.h>
+#include <asm/cpuidle.h>
#include <mach/kirkwood.h>
#define KIRKWOOD_MAX_STATES 2
-static struct cpuidle_driver kirkwood_idle_driver = {
- .name = "kirkwood_idle",
- .owner = THIS_MODULE,
-};
-
-static DEFINE_PER_CPU(struct cpuidle_device, kirkwood_cpuidle_device);
-
/* Actual code that puts the SoC in different idle states */
static int kirkwood_enter_idle(struct cpuidle_device *dev,
struct cpuidle_driver *drv,
int index)
{
- struct timeval before, after;
- int idle_time;
-
- local_irq_disable();
- do_gettimeofday(&before);
- if (index == 0)
- /* Wait for interrupt state */
- cpu_do_idle();
- else if (index == 1) {
- /*
- * Following write will put DDR in self refresh.
- * Note that we have 256 cycles before DDR puts it
- * self in self-refresh, so the wait-for-interrupt
- * call afterwards won't get the DDR from self refresh
- * mode.
- */
- writel(0x7, DDR_OPERATION_BASE);
- cpu_do_idle();
- }
- do_gettimeofday(&after);
- local_irq_enable();
- idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
- (after.tv_usec - before.tv_usec);
-
- /* Update last residency */
- dev->last_residency = idle_time;
+ writel(0x7, DDR_OPERATION_BASE);
+ cpu_do_idle();
return index;
}
+static struct cpuidle_driver kirkwood_idle_driver = {
+ .name = "kirkwood_idle",
+ .owner = THIS_MODULE,
+ .en_core_tk_irqen = 1,
+ .states[0] = ARM_CPUIDLE_WFI_STATE,
+ .states[1] = {
+ .enter = kirkwood_enter_idle,
+ .exit_latency = 10,
+ .target_residency = 100000,
+ .flags = CPUIDLE_FLAG_TIME_VALID,
+ .name = "DDR SR",
+ .desc = "WFI and DDR Self Refresh",
+ },
+ .state_count = KIRKWOOD_MAX_STATES,
+};
+
+static DEFINE_PER_CPU(struct cpuidle_device, kirkwood_cpuidle_device);
+
/* Initialize CPU idle by registering the idle states */
static int kirkwood_init_cpuidle(void)
{
struct cpuidle_device *device;
- struct cpuidle_driver *driver = &kirkwood_idle_driver;
device = &per_cpu(kirkwood_cpuidle_device, smp_processor_id());
device->state_count = KIRKWOOD_MAX_STATES;
- driver->state_count = KIRKWOOD_MAX_STATES;
-
- /* Wait for interrupt state */
- driver->states[0].enter = kirkwood_enter_idle;
- driver->states[0].exit_latency = 1;
- driver->states[0].target_residency = 10000;
- driver->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
- strcpy(driver->states[0].name, "WFI");
- strcpy(driver->states[0].desc, "Wait for interrupt");
-
- /* Wait for interrupt and DDR self refresh state */
- driver->states[1].enter = kirkwood_enter_idle;
- driver->states[1].exit_latency = 10;
- driver->states[1].target_residency = 10000;
- driver->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
- strcpy(driver->states[1].name, "DDR SR");
- strcpy(driver->states[1].desc, "WFI and DDR Self Refresh");
cpuidle_register_driver(&kirkwood_idle_driver);
if (cpuidle_register_device(device)) {
--
1.7.10.rc2.19.gfae9d
^ permalink raw reply related
* [PATCH 08/76] ARM: davinci: Consolidate time keeping and irq enable
From: Len Brown @ 2012-03-30 10:13 UTC (permalink / raw)
To: linux-acpi, linux-pm; +Cc: linux-kernel, Robert Lee, Len Brown
In-Reply-To: <09f98a825a821f7a3f1b162f9ed023f37213a63b.1333101989.git.len.brown@intel.com>
From: Robert Lee <rob.lee@linaro.org>
Enable core cpuidle timekeeping and irq enabling and remove that
handling from this code.
Signed-off-by: Robert Lee <rob.lee@linaro.org>
Reviewed-by: Kevin Hilman <khilman@ti.com>
Reviewed-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Acked-by: Jean Pihet <j-pihet@ti.com>
Signed-off-by: Len Brown <len.brown@intel.com>
---
arch/arm/mach-davinci/cpuidle.c | 82 ++++++++++++++++-----------------------
1 file changed, 33 insertions(+), 49 deletions(-)
diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c
index a30c7c5..93ae096 100644
--- a/arch/arm/mach-davinci/cpuidle.c
+++ b/arch/arm/mach-davinci/cpuidle.c
@@ -18,6 +18,7 @@
#include <linux/io.h>
#include <linux/export.h>
#include <asm/proc-fns.h>
+#include <asm/cpuidle.h>
#include <mach/cpuidle.h>
#include <mach/ddr2.h>
@@ -30,12 +31,42 @@ struct davinci_ops {
u32 flags;
};
+/* Actual code that puts the SoC in different idle states */
+static int davinci_enter_idle(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv,
+ int index)
+{
+ struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
+ struct davinci_ops *ops = cpuidle_get_statedata(state_usage);
+
+ if (ops && ops->enter)
+ ops->enter(ops->flags);
+
+ index = cpuidle_wrap_enter(dev, drv, index,
+ arm_cpuidle_simple_enter);
+
+ if (ops && ops->exit)
+ ops->exit(ops->flags);
+
+ return index;
+}
+
/* fields in davinci_ops.flags */
#define DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN BIT(0)
static struct cpuidle_driver davinci_idle_driver = {
- .name = "cpuidle-davinci",
- .owner = THIS_MODULE,
+ .name = "cpuidle-davinci",
+ .owner = THIS_MODULE,
+ .states[0] = ARM_CPUIDLE_WFI_STATE,
+ .states[1] = {
+ .enter = davinci_enter_idle,
+ .exit_latency = 10,
+ .target_residency = 100000,
+ .flags = CPUIDLE_FLAG_TIME_VALID,
+ .name = "DDR SR",
+ .desc = "WFI and DDR Self Refresh",
+ },
+ .state_count = DAVINCI_CPUIDLE_MAX_STATES,
};
static DEFINE_PER_CPU(struct cpuidle_device, davinci_cpuidle_device);
@@ -77,41 +108,10 @@ static struct davinci_ops davinci_states[DAVINCI_CPUIDLE_MAX_STATES] = {
},
};
-/* Actual code that puts the SoC in different idle states */
-static int davinci_enter_idle(struct cpuidle_device *dev,
- struct cpuidle_driver *drv,
- int index)
-{
- struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
- struct davinci_ops *ops = cpuidle_get_statedata(state_usage);
- struct timeval before, after;
- int idle_time;
-
- local_irq_disable();
- do_gettimeofday(&before);
-
- if (ops && ops->enter)
- ops->enter(ops->flags);
- /* Wait for interrupt state */
- cpu_do_idle();
- if (ops && ops->exit)
- ops->exit(ops->flags);
-
- do_gettimeofday(&after);
- local_irq_enable();
- idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
- (after.tv_usec - before.tv_usec);
-
- dev->last_residency = idle_time;
-
- return index;
-}
-
static int __init davinci_cpuidle_probe(struct platform_device *pdev)
{
int ret;
struct cpuidle_device *device;
- struct cpuidle_driver *driver = &davinci_idle_driver;
struct davinci_cpuidle_config *pdata = pdev->dev.platform_data;
device = &per_cpu(davinci_cpuidle_device, smp_processor_id());
@@ -123,27 +123,11 @@ static int __init davinci_cpuidle_probe(struct platform_device *pdev)
ddr2_reg_base = pdata->ddr2_ctlr_base;
- /* Wait for interrupt state */
- driver->states[0].enter = davinci_enter_idle;
- driver->states[0].exit_latency = 1;
- driver->states[0].target_residency = 10000;
- driver->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
- strcpy(driver->states[0].name, "WFI");
- strcpy(driver->states[0].desc, "Wait for interrupt");
-
- /* Wait for interrupt and DDR self refresh state */
- driver->states[1].enter = davinci_enter_idle;
- driver->states[1].exit_latency = 10;
- driver->states[1].target_residency = 10000;
- driver->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
- strcpy(driver->states[1].name, "DDR SR");
- strcpy(driver->states[1].desc, "WFI and DDR Self Refresh");
if (pdata->ddr2_pdown)
davinci_states[1].flags |= DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN;
cpuidle_set_statedata(&device->states_usage[1], &davinci_states[1]);
device->state_count = DAVINCI_CPUIDLE_MAX_STATES;
- driver->state_count = DAVINCI_CPUIDLE_MAX_STATES;
ret = cpuidle_register_driver(&davinci_idle_driver);
if (ret) {
--
1.7.10.rc2.19.gfae9d
^ permalink raw reply related
* [PATCH 09/76] ARM: omap: Consolidate OMAP3 time keeping and irq enable
From: Len Brown @ 2012-03-30 10:13 UTC (permalink / raw)
To: linux-acpi, linux-pm; +Cc: Len Brown, Robert Lee, linux-kernel
In-Reply-To: <09f98a825a821f7a3f1b162f9ed023f37213a63b.1333101989.git.len.brown@intel.com>
From: Robert Lee <rob.lee@linaro.org>
Use core cpuidle timekeeping and irqen wrapper and remove that
handling from this code.
Signed-off-by: Robert Lee <rob.lee@linaro.org>
Reviewed-by: Kevin Hilman <khilman@ti.com>
Reviewed-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Tested-by: Jean Pihet <j-pihet@ti.com>
Acked-by: Jean Pihet <j-pihet@ti.com>
Signed-off-by: Len Brown <len.brown@intel.com>
---
arch/arm/mach-omap2/cpuidle34xx.c | 42 +++++++++++++++----------------------
1 file changed, 17 insertions(+), 25 deletions(-)
diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
index 464cffd..5358664 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -87,29 +87,14 @@ static int _cpuidle_deny_idle(struct powerdomain *pwrdm,
return 0;
}
-/**
- * omap3_enter_idle - Programs OMAP3 to enter the specified state
- * @dev: cpuidle device
- * @drv: cpuidle driver
- * @index: the index of state to be entered
- *
- * Called from the CPUidle framework to program the device to the
- * specified target state selected by the governor.
- */
-static int omap3_enter_idle(struct cpuidle_device *dev,
+static int __omap3_enter_idle(struct cpuidle_device *dev,
struct cpuidle_driver *drv,
int index)
{
struct omap3_idle_statedata *cx =
cpuidle_get_statedata(&dev->states_usage[index]);
- struct timespec ts_preidle, ts_postidle, ts_idle;
u32 mpu_state = cx->mpu_state, core_state = cx->core_state;
- int idle_time;
-
- /* Used to keep track of the total time in idle */
- getnstimeofday(&ts_preidle);
- local_irq_disable();
local_fiq_disable();
pwrdm_set_next_pwrst(mpu_pd, mpu_state);
@@ -148,22 +133,29 @@ static int omap3_enter_idle(struct cpuidle_device *dev,
}
return_sleep_time:
- getnstimeofday(&ts_postidle);
- ts_idle = timespec_sub(ts_postidle, ts_preidle);
- local_irq_enable();
local_fiq_enable();
- idle_time = ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * \
- USEC_PER_SEC;
-
- /* Update cpuidle counters */
- dev->last_residency = idle_time;
-
return index;
}
/**
+ * omap3_enter_idle - Programs OMAP3 to enter the specified state
+ * @dev: cpuidle device
+ * @drv: cpuidle driver
+ * @index: the index of state to be entered
+ *
+ * Called from the CPUidle framework to program the device to the
+ * specified target state selected by the governor.
+ */
+static inline int omap3_enter_idle(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv,
+ int index)
+{
+ return cpuidle_wrap_enter(dev, drv, index, __omap3_enter_idle);
+}
+
+/**
* next_valid_state - Find next valid C-state
* @dev: cpuidle device
* @drv: cpuidle driver
--
1.7.10.rc2.19.gfae9d
^ permalink raw reply related
* [PATCH 10/76] ARM: omap: Consolidate OMAP4 time keeping and irq enable
From: Len Brown @ 2012-03-30 10:13 UTC (permalink / raw)
To: linux-acpi, linux-pm; +Cc: linux-kernel, Robert Lee, Len Brown
In-Reply-To: <09f98a825a821f7a3f1b162f9ed023f37213a63b.1333101989.git.len.brown@intel.com>
From: Robert Lee <rob.lee@linaro.org>
Enable core cpuidle timekeeping and irq enabling and remove that
handling from this code.
Signed-off-by: Robert Lee <rob.lee@linaro.org>
Reviewed-by: Kevin Hilman <khilman@ti.com>
Reviewed-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Acked-by: Jean Pihet <j-pihet@ti.com>
Signed-off-by: Len Brown <len.brown@intel.com>
---
arch/arm/mach-omap2/cpuidle44xx.c | 21 +++------------------
1 file changed, 3 insertions(+), 18 deletions(-)
diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c
index 72e018b..f386cbe 100644
--- a/arch/arm/mach-omap2/cpuidle44xx.c
+++ b/arch/arm/mach-omap2/cpuidle44xx.c
@@ -62,15 +62,9 @@ static int omap4_enter_idle(struct cpuidle_device *dev,
{
struct omap4_idle_statedata *cx =
cpuidle_get_statedata(&dev->states_usage[index]);
- struct timespec ts_preidle, ts_postidle, ts_idle;
u32 cpu1_state;
- int idle_time;
int cpu_id = smp_processor_id();
- /* Used to keep track of the total time in idle */
- getnstimeofday(&ts_preidle);
-
- local_irq_disable();
local_fiq_disable();
/*
@@ -128,26 +122,17 @@ static int omap4_enter_idle(struct cpuidle_device *dev,
if (index > 0)
clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu_id);
- getnstimeofday(&ts_postidle);
- ts_idle = timespec_sub(ts_postidle, ts_preidle);
-
- local_irq_enable();
local_fiq_enable();
- idle_time = ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * \
- USEC_PER_SEC;
-
- /* Update cpuidle counters */
- dev->last_residency = idle_time;
-
return index;
}
DEFINE_PER_CPU(struct cpuidle_device, omap4_idle_dev);
struct cpuidle_driver omap4_idle_driver = {
- .name = "omap4_idle",
- .owner = THIS_MODULE,
+ .name = "omap4_idle",
+ .owner = THIS_MODULE,
+ .en_core_tk_irqen = 1,
};
static inline void _fill_cstate(struct cpuidle_driver *drv,
--
1.7.10.rc2.19.gfae9d
^ permalink raw reply related
* [PATCH 11/76] ARM: shmobile: Consolidate time keeping and irq enable
From: Len Brown @ 2012-03-30 10:13 UTC (permalink / raw)
To: linux-acpi, linux-pm; +Cc: linux-kernel, Robert Lee, Len Brown
In-Reply-To: <09f98a825a821f7a3f1b162f9ed023f37213a63b.1333101989.git.len.brown@intel.com>
From: Robert Lee <rob.lee@linaro.org>
Enable core cpuidle timekeeping and irq enabling and remove that
handling from this code.
Signed-off-by: Robert Lee <rob.lee@linaro.org>
Reviewed-by: Kevin Hilman <khilman@ti.com>
Reviewed-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Acked-by: Jean Pihet <j-pihet@ti.com>
Signed-off-by: Len Brown <len.brown@intel.com>
---
arch/arm/mach-shmobile/cpuidle.c | 31 +++++++------------------------
1 file changed, 7 insertions(+), 24 deletions(-)
diff --git a/arch/arm/mach-shmobile/cpuidle.c b/arch/arm/mach-shmobile/cpuidle.c
index 1b23342..ca23b20 100644
--- a/arch/arm/mach-shmobile/cpuidle.c
+++ b/arch/arm/mach-shmobile/cpuidle.c
@@ -14,6 +14,7 @@
#include <linux/module.h>
#include <linux/err.h>
#include <asm/system.h>
+#include <asm/cpuidle.h>
#include <asm/io.h>
static void shmobile_enter_wfi(void)
@@ -29,37 +30,19 @@ static int shmobile_cpuidle_enter(struct cpuidle_device *dev,
struct cpuidle_driver *drv,
int index)
{
- ktime_t before, after;
-
- before = ktime_get();
-
- local_irq_disable();
- local_fiq_disable();
-
shmobile_cpuidle_modes[index]();
- local_irq_enable();
- local_fiq_enable();
-
- after = ktime_get();
- dev->last_residency = ktime_to_ns(ktime_sub(after, before)) >> 10;
-
return index;
}
static struct cpuidle_device shmobile_cpuidle_dev;
static struct cpuidle_driver shmobile_cpuidle_driver = {
- .name = "shmobile_cpuidle",
- .owner = THIS_MODULE,
- .states[0] = {
- .name = "C1",
- .desc = "WFI",
- .exit_latency = 1,
- .target_residency = 1 * 2,
- .flags = CPUIDLE_FLAG_TIME_VALID,
- },
- .safe_state_index = 0, /* C1 */
- .state_count = 1,
+ .name = "shmobile_cpuidle",
+ .owner = THIS_MODULE,
+ .en_core_tk_irqen = 1,
+ .states[0] = ARM_CPUIDLE_WFI_STATE,
+ .safe_state_index = 0, /* C1 */
+ .state_count = 1,
};
void (*shmobile_cpuidle_setup)(struct cpuidle_driver *drv);
--
1.7.10.rc2.19.gfae9d
^ permalink raw reply related
* [PATCH 12/76] SH: shmobile: Consolidate time keeping and irq enable
From: Len Brown @ 2012-03-30 10:13 UTC (permalink / raw)
To: linux-acpi, linux-pm; +Cc: linux-kernel, Robert Lee, Len Brown
In-Reply-To: <09f98a825a821f7a3f1b162f9ed023f37213a63b.1333101989.git.len.brown@intel.com>
From: Robert Lee <rob.lee@linaro.org>
Enable core cpuidle timekeeping and irq enabling and remove that
handling from this code.
Signed-off-by: Robert Lee <rob.lee@linaro.org>
Reviewed-by: Kevin Hilman <khilman@ti.com>
Reviewed-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Acked-by: Jean Pihet <j-pihet@ti.com>
Signed-off-by: Len Brown <len.brown@intel.com>
---
arch/sh/kernel/cpu/shmobile/cpuidle.c | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/arch/sh/kernel/cpu/shmobile/cpuidle.c b/arch/sh/kernel/cpu/shmobile/cpuidle.c
index 6d62eb4..1ddc876 100644
--- a/arch/sh/kernel/cpu/shmobile/cpuidle.c
+++ b/arch/sh/kernel/cpu/shmobile/cpuidle.c
@@ -29,7 +29,6 @@ static int cpuidle_sleep_enter(struct cpuidle_device *dev,
int index)
{
unsigned long allowed_mode = SUSP_SH_SLEEP;
- ktime_t before, after;
int requested_state = index;
int allowed_state;
int k;
@@ -47,19 +46,16 @@ static int cpuidle_sleep_enter(struct cpuidle_device *dev,
*/
k = min_t(int, allowed_state, requested_state);
- before = ktime_get();
sh_mobile_call_standby(cpuidle_mode[k]);
- after = ktime_get();
-
- dev->last_residency = (int)ktime_to_ns(ktime_sub(after, before)) >> 10;
return k;
}
static struct cpuidle_device cpuidle_dev;
static struct cpuidle_driver cpuidle_driver = {
- .name = "sh_idle",
- .owner = THIS_MODULE,
+ .name = "sh_idle",
+ .owner = THIS_MODULE,
+ .en_core_tk_irqen = 1,
};
void sh_mobile_setup_cpuidle(void)
--
1.7.10.rc2.19.gfae9d
^ permalink raw reply related
* [PATCH 13/76] drivers/thermal/thermal_sys.c: fix build warning
From: Len Brown @ 2012-03-30 10:13 UTC (permalink / raw)
To: linux-acpi, linux-pm
Cc: Fabio Estevam, Len Brown, linux-kernel, Jean Delvare,
Andrew Morton, Fabio Estevam
In-Reply-To: <09f98a825a821f7a3f1b162f9ed023f37213a63b.1333101989.git.len.brown@intel.com>
From: Fabio Estevam <festevam@gmail.com>
With CONFIG_NET=n:
drivers/thermal/thermal_sys.c:63: warning: 'thermal_event_seqnum' defined but not used
Move 'thermal_event_seqnum' definition inside the '#ifdef CONFIG_NET'
[akpm@linux-foundation.org: make thermal_event_seqnum local to generate_netlink_event()]
Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com>
Acked-by: Guenter Roeck <guenter.roeck@ericsson.com>
Acked-by: Durgadoss R <durgadoss.r@intel.com>
Cc: Jean Delvare <khali@linux-fr.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Len Brown <len.brown@intel.com>
---
drivers/thermal/thermal_sys.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 220ce7e..859b80b 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -60,8 +60,6 @@ static LIST_HEAD(thermal_tz_list);
static LIST_HEAD(thermal_cdev_list);
static DEFINE_MUTEX(thermal_list_lock);
-static unsigned int thermal_event_seqnum;
-
static int get_idr(struct idr *idr, struct mutex *lock, int *id)
{
int err;
@@ -1312,6 +1310,7 @@ int thermal_generate_netlink_event(u32 orig, enum events event)
void *msg_header;
int size;
int result;
+ static unsigned int thermal_event_seqnum;
/* allocate memory */
size = nla_total_size(sizeof(struct thermal_genl_event)) + \
--
1.7.10.rc2.19.gfae9d
^ permalink raw reply related
* [PATCH 14/76] thermal_sys: remove unnecessary line continuations
From: Len Brown @ 2012-03-30 10:13 UTC (permalink / raw)
To: linux-acpi, linux-pm; +Cc: Joe Perches, Len Brown, Andrew Morton, linux-kernel
In-Reply-To: <09f98a825a821f7a3f1b162f9ed023f37213a63b.1333101989.git.len.brown@intel.com>
From: Joe Perches <joe@perches.com>
Line continations are not necessary in function calls or statements.
Remove them.
Signed-off-by: Joe Perches <joe@perches.com>
Reviewed-by: Jesper Juhl <jj@chaosbits.net>
Cc: Len Brown <lenb@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Len Brown <len.brown@intel.com>
---
drivers/thermal/thermal_sys.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 859b80b..71802ca 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -281,8 +281,7 @@ passive_show(struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR(type, 0444, type_show, NULL);
static DEVICE_ATTR(temp, 0444, temp_show, NULL);
static DEVICE_ATTR(mode, 0644, mode_show, mode_store);
-static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, \
- passive_store);
+static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store);
static struct device_attribute trip_point_attrs[] = {
__ATTR(trip_point_0_type, 0444, trip_point_type_show, NULL),
@@ -1313,8 +1312,8 @@ int thermal_generate_netlink_event(u32 orig, enum events event)
static unsigned int thermal_event_seqnum;
/* allocate memory */
- size = nla_total_size(sizeof(struct thermal_genl_event)) + \
- nla_total_size(0);
+ size = nla_total_size(sizeof(struct thermal_genl_event)) +
+ nla_total_size(0);
skb = genlmsg_new(size, GFP_ATOMIC);
if (!skb)
@@ -1330,8 +1329,8 @@ int thermal_generate_netlink_event(u32 orig, enum events event)
}
/* fill the data */
- attr = nla_reserve(skb, THERMAL_GENL_ATTR_EVENT, \
- sizeof(struct thermal_genl_event));
+ attr = nla_reserve(skb, THERMAL_GENL_ATTR_EVENT,
+ sizeof(struct thermal_genl_event));
if (!attr) {
nlmsg_free(skb);
--
1.7.10.rc2.19.gfae9d
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox