* [PATCH 0/2] cpufreq: fix transition_ongoing count for powernow-k8
@ 2013-09-13 12:59 Viresh Kumar
2013-09-13 12:59 ` [PATCH 1/2] cpufreq: Create cpufreq_transition_complete() Viresh Kumar
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Viresh Kumar @ 2013-09-13 12:59 UTC (permalink / raw)
To: rjw; +Cc: linaro-kernel, patches, cpufreq, linux-pm, linux-kernel,
Viresh Kumar
This has been running in my mind since few days... That we have fixed cpufreq
core and all other drivers for transition serialization but what about
powernow-k8? It is somewhat special (even more than exynos5440).. It queues a
work from ->target() and may or maynot send notifications at all..
Finally I have got a solution now (detailed logs in the patch)..
These must go with following patchset:
https://lkml.org/lkml/2013/9/12/173
Compile tested only..
Viresh Kumar (2):
cpufreq: Create cpufreq_transition_complete()
cpufreq: powernow-k8: mark freq transition complete on error cases
drivers/cpufreq/cpufreq.c | 25 ++++++++++++-----------
drivers/cpufreq/powernow-k8.c | 47 +++++++++++++++++++++++++++++++------------
include/linux/cpufreq.h | 7 +++++++
3 files changed, 54 insertions(+), 25 deletions(-)
--
1.7.12.rc2.18.g61b472e
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/2] cpufreq: Create cpufreq_transition_complete()
2013-09-13 12:59 [PATCH 0/2] cpufreq: fix transition_ongoing count for powernow-k8 Viresh Kumar
@ 2013-09-13 12:59 ` Viresh Kumar
2013-09-13 12:59 ` [PATCH 2/2] cpufreq: powernow-k8: mark freq transition complete on error cases Viresh Kumar
2013-09-13 23:42 ` [PATCH 0/2] cpufreq: fix transition_ongoing count for powernow-k8 Rafael J. Wysocki
2 siblings, 0 replies; 5+ messages in thread
From: Viresh Kumar @ 2013-09-13 12:59 UTC (permalink / raw)
To: rjw; +Cc: linaro-kernel, patches, cpufreq, linux-pm, linux-kernel,
Viresh Kumar
Following patch "cpufreq: make sure frequency transitions are serialized"
guarantees that we don't have any races while changing cpu frequency or sending
notifications. It handled a special case with CPUFREQ_ASYNC_NOTIFICATION flag
for drivers that don't complete their freq change from ->target() and exynos5440
driver is well adopted to it as well..
There is one more driver powernow-k8 that has similar implementation, schedules
a work for doing transitions. All is good if that work function does
notifications on every call to it and so the transition_ongoing count stays
stable. But there are chances that the work function may return without actually
doing the notifications, in which case transition_ongoing count will not be set
to zero and so no transitions would be possible after that.
This patch adds another routine cpufreq_transition_complete() which would be
used by powernow-k8 (or even exynos5440 if required), that will be used to mark
end of transition in such cases.
Later patch will change powernow-k8 to use this routine.
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
drivers/cpufreq/cpufreq.c | 25 +++++++++++++------------
include/linux/cpufreq.h | 7 +++++++
2 files changed, 20 insertions(+), 12 deletions(-)
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index f8b0889..cf283f3 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -265,6 +265,16 @@ static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
}
#endif
+void cpufreq_transition_complete(struct cpufreq_policy *policy)
+{
+ unsigned long flags;
+
+ write_lock_irqsave(&cpufreq_driver_lock, flags);
+ policy->transition_ongoing--;
+ write_unlock_irqrestore(&cpufreq_driver_lock, flags);
+}
+EXPORT_SYMBOL_GPL(cpufreq_transition_complete);
+
static void __cpufreq_notify_transition(struct cpufreq_policy *policy,
struct cpufreq_freqs *freqs, unsigned int state)
{
@@ -350,16 +360,12 @@ void cpufreq_notify_transition(struct cpufreq_policy *policy,
if ((cpufreq_driver->flags & CPUFREQ_ASYNC_NOTIFICATION)
&& (state == CPUFREQ_POSTCHANGE)) {
- unsigned long flags;
-
/*
* Some drivers don't send POSTCHANGE notification from their
* ->target() but from some kind of bottom half and so we are
* ending transaction here..
*/
- write_lock_irqsave(&cpufreq_driver_lock, flags);
- policy->transition_ongoing--;
- write_unlock_irqrestore(&cpufreq_driver_lock, flags);
+ cpufreq_transition_complete(policy);
}
}
EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
@@ -1430,9 +1436,7 @@ static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq,
if (cpufreq_driver->flags & CPUFREQ_ASYNC_NOTIFICATION)
return;
- write_lock_irqsave(&cpufreq_driver_lock, flags);
- policy->transition_ongoing--;
- write_unlock_irqrestore(&cpufreq_driver_lock, flags);
+ cpufreq_transition_complete(policy);
}
/**
@@ -1754,10 +1758,7 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
&& (retval == -EINPROGRESS))
return retval;
- write_lock_irqsave(&cpufreq_driver_lock, flags);
- policy->transition_ongoing--;
- write_unlock_irqrestore(&cpufreq_driver_lock, flags);
-
+ cpufreq_transition_complete(policy);
return retval;
}
EXPORT_SYMBOL_GPL(__cpufreq_driver_target);
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index c770bc0..10ab22d 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -231,6 +231,13 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver_data);
const char *cpufreq_get_current_driver(void);
+/*
+ * Only for drivers which have CPUFREQ_ASYNC_NOTIFICATION flag set and they need
+ * to mark transaction over before starting any notifications, otherwise the
+ * POSTCHANGE notification already does this.
+ */
+void cpufreq_transition_complete(struct cpufreq_policy *policy);
+
static inline void cpufreq_verify_within_limits(struct cpufreq_policy *policy,
unsigned int min, unsigned int max)
{
--
1.7.12.rc2.18.g61b472e
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/2] cpufreq: powernow-k8: mark freq transition complete on error cases
2013-09-13 12:59 [PATCH 0/2] cpufreq: fix transition_ongoing count for powernow-k8 Viresh Kumar
2013-09-13 12:59 ` [PATCH 1/2] cpufreq: Create cpufreq_transition_complete() Viresh Kumar
@ 2013-09-13 12:59 ` Viresh Kumar
2013-09-13 23:42 ` [PATCH 0/2] cpufreq: fix transition_ongoing count for powernow-k8 Rafael J. Wysocki
2 siblings, 0 replies; 5+ messages in thread
From: Viresh Kumar @ 2013-09-13 12:59 UTC (permalink / raw)
To: rjw; +Cc: linaro-kernel, patches, cpufreq, linux-pm, linux-kernel,
Viresh Kumar
Following patch "cpufreq: make sure frequency transitions are serialized"
guarantees that we don't have any races while changing cpu frequency or sending
notifications. It handled a special case with CPUFREQ_ASYNC_NOTIFICATION flag
for drivers that don't complete their freq change from ->target() and exynos5440
driver is well adopted to it as well..
There is one more driver powernow-k8 that has similar implementation, schedules
a work for doing transitions. All is good if that work function does
notifications on every call to it and so the transition_ongoing count stays
stable. But there are chances that the work function may return without actually
doing the notifications, in which case transition_ongoing count will not be set
to zero and so no transitions would be possible after that.
This patch fixes powernow-k8 driver to get transition_ongoing count stable. It
does following to ensure proper working of this driver:
- return -EINPROGRESS from ->target() so that core doesn't mark transfer over at
the end of ->target().
- mark cpufreq_driver->flags with CPUFREQ_ASYNC_NOTIFICATION, so that core knows
that driver would terminate its transition.
- call cpufreq_transition_complete() whenever we are returning before sending
notifications
Hopefully things will work well after this patch, only compiled tested at my
end.
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
drivers/cpufreq/powernow-k8.c | 47 +++++++++++++++++++++++++++++++------------
1 file changed, 34 insertions(+), 13 deletions(-)
diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c
index 2344a9e..8215bbc 100644
--- a/drivers/cpufreq/powernow-k8.c
+++ b/drivers/cpufreq/powernow-k8.c
@@ -952,7 +952,7 @@ static int transition_frequency_fidvid(struct powernow_k8_data *data,
if ((data->currvid == vid) && (data->currfid == fid)) {
pr_debug("target matches current values (fid 0x%x, vid 0x%x)\n",
fid, vid);
- return 0;
+ return -EALREADY;
}
pr_debug("cpu %d, changing to fid 0x%x, vid 0x%x\n",
@@ -993,22 +993,27 @@ static long powernowk8_target_fn(void *arg)
unsigned int newstate;
int ret;
- if (!data)
- return -EINVAL;
+ if (!data) {
+ ret = -EINVAL;
+ goto transition_complete;
+ }
checkfid = data->currfid;
checkvid = data->currvid;
if (pending_bit_stuck()) {
printk(KERN_ERR PFX "failing targ, change pending bit set\n");
- return -EIO;
+ ret = -EIO;
+ goto transition_complete;
}
pr_debug("targ: cpu %d, %d kHz, min %d, max %d, relation %d\n",
pol->cpu, targfreq, pol->min, pol->max, relation);
- if (query_current_values_with_pending_wait(data))
- return -EIO;
+ if (query_current_values_with_pending_wait(data)) {
+ ret = -EIO;
+ goto transition_complete;
+ }
pr_debug("targ: curr fid 0x%x, vid 0x%x\n",
data->currfid, data->currvid);
@@ -1022,25 +1027,36 @@ static long powernowk8_target_fn(void *arg)
}
if (cpufreq_frequency_table_target(pol, data->powernow_table,
- targfreq, relation, &newstate))
- return -EIO;
+ targfreq, relation, &newstate)) {
+ ret = -EIO;
+ goto transition_complete;
+ }
mutex_lock(&fidvid_mutex);
powernow_k8_acpi_pst_values(data, newstate);
ret = transition_frequency_fidvid(data, newstate);
+ mutex_unlock(&fidvid_mutex);
if (ret) {
- printk(KERN_ERR PFX "transition frequency failed\n");
- mutex_unlock(&fidvid_mutex);
- return 1;
+ /* Not a error case, just need to mark transition complete */
+ if (ret == -EALREADY) {
+ ret = 0;
+ } else {
+ printk(KERN_ERR PFX "transition frequency failed\n");
+ ret = 1;
+ }
+ goto transition_complete;
}
- mutex_unlock(&fidvid_mutex);
pol->cur = find_khz_freq_from_fid(data->currfid);
return 0;
+
+transition_complete:
+ cpufreq_transition_complete(pol);
+ return ret;
}
/* Driver entry point to switch to the target frequency */
@@ -1049,8 +1065,12 @@ static int powernowk8_target(struct cpufreq_policy *pol,
{
struct powernowk8_target_arg pta = { .pol = pol, .targfreq = targfreq,
.relation = relation };
+ int ret;
- return work_on_cpu(pol->cpu, powernowk8_target_fn, &pta);
+ ret = work_on_cpu(pol->cpu, powernowk8_target_fn, &pta);
+ if (!ret)
+ ret = -EINPROGRESS; /* Mark transition as In-progress */
+ return ret;
}
/* Driver entry point to verify the policy and range of frequencies */
@@ -1233,6 +1253,7 @@ static struct freq_attr *powernow_k8_attr[] = {
};
static struct cpufreq_driver cpufreq_amd64_driver = {
+ .flags = CPUFREQ_ASYNC_NOTIFICATION,
.verify = powernowk8_verify,
.target = powernowk8_target,
.bios_limit = acpi_processor_get_bios_limit,
--
1.7.12.rc2.18.g61b472e
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 0/2] cpufreq: fix transition_ongoing count for powernow-k8
2013-09-13 12:59 [PATCH 0/2] cpufreq: fix transition_ongoing count for powernow-k8 Viresh Kumar
2013-09-13 12:59 ` [PATCH 1/2] cpufreq: Create cpufreq_transition_complete() Viresh Kumar
2013-09-13 12:59 ` [PATCH 2/2] cpufreq: powernow-k8: mark freq transition complete on error cases Viresh Kumar
@ 2013-09-13 23:42 ` Rafael J. Wysocki
2013-09-14 4:29 ` Viresh Kumar
2 siblings, 1 reply; 5+ messages in thread
From: Rafael J. Wysocki @ 2013-09-13 23:42 UTC (permalink / raw)
To: Viresh Kumar; +Cc: linaro-kernel, patches, cpufreq, linux-pm, linux-kernel
On Friday, September 13, 2013 06:29:37 PM Viresh Kumar wrote:
> This has been running in my mind since few days... That we have fixed cpufreq
> core and all other drivers for transition serialization but what about
> powernow-k8? It is somewhat special (even more than exynos5440).. It queues a
> work from ->target() and may or maynot send notifications at all..
>
> Finally I have got a solution now (detailed logs in the patch)..
> These must go with following patchset:
The "must go" here is a totally wrong way of speaking about things, because I'm
not sure I'll take this patch series yet.
> https://lkml.org/lkml/2013/9/12/173
Thanks,
Rafael
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 0/2] cpufreq: fix transition_ongoing count for powernow-k8
2013-09-13 23:42 ` [PATCH 0/2] cpufreq: fix transition_ongoing count for powernow-k8 Rafael J. Wysocki
@ 2013-09-14 4:29 ` Viresh Kumar
0 siblings, 0 replies; 5+ messages in thread
From: Viresh Kumar @ 2013-09-14 4:29 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: Lists linaro-kernel, Patch Tracking, cpufreq@vger.kernel.org,
linux-pm@vger.kernel.org, Linux Kernel Mailing List
On 14 September 2013 05:12, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> On Friday, September 13, 2013 06:29:37 PM Viresh Kumar wrote:
>> This has been running in my mind since few days... That we have fixed cpufreq
>> core and all other drivers for transition serialization but what about
>> powernow-k8? It is somewhat special (even more than exynos5440).. It queues a
>> work from ->target() and may or maynot send notifications at all..
>>
>> Finally I have got a solution now (detailed logs in the patch)..
>> These must go with following patchset:
>
> The "must go" here is a totally wrong way of speaking about things, because I'm
> not sure I'll take this patch series yet.
>
>> https://lkml.org/lkml/2013/9/12/173
The "must go" was about keeping all four patches together, rather than
forcing you to take them all..
Sorry for the confusion..
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2013-09-14 4:29 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-09-13 12:59 [PATCH 0/2] cpufreq: fix transition_ongoing count for powernow-k8 Viresh Kumar
2013-09-13 12:59 ` [PATCH 1/2] cpufreq: Create cpufreq_transition_complete() Viresh Kumar
2013-09-13 12:59 ` [PATCH 2/2] cpufreq: powernow-k8: mark freq transition complete on error cases Viresh Kumar
2013-09-13 23:42 ` [PATCH 0/2] cpufreq: fix transition_ongoing count for powernow-k8 Rafael J. Wysocki
2013-09-14 4:29 ` Viresh Kumar
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).