diff mbox

[RFCv7,02/10] cpufreq: introduce cpufreq_driver_is_slow

Message ID 1456190570-4475-3-git-send-email-smuckle@linaro.org (mailing list archive)
State RFC, archived
Headers show

Commit Message

Steve Muckle Feb. 23, 2016, 1:22 a.m. UTC
From: Michael Turquette <mturquette@baylibre.com>

Some architectures and platforms perform CPU frequency transitions
through a non-blocking method, while some might block or sleep. Even
when frequency transitions do not block or sleep they may be very slow.
This distinction is important when trying to change frequency from
a non-interruptible context in a scheduler hot path.

Describe this distinction with a cpufreq driver flag,
CPUFREQ_DRIVER_FAST. The default is to not have this flag set,
thus erring on the side of caution.

cpufreq_driver_is_slow() is also introduced in this patch. Setting
the above flag will allow this function to return false.

[smuckle@linaro.org: change flag/API to include drivers that are too
 slow for scheduler hot paths, in addition to those that block/sleep]

Cc: Rafael J. Wysocki <rafael@kernel.org>
Cc: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Michael Turquette <mturquette@baylibre.com>
Signed-off-by: Steve Muckle <smuckle@linaro.org>
---
 drivers/cpufreq/cpufreq.c | 6 ++++++
 include/linux/cpufreq.h   | 9 +++++++++
 2 files changed, 15 insertions(+)

Comments

Rafael J. Wysocki Feb. 23, 2016, 1:31 a.m. UTC | #1
On Tue, Feb 23, 2016 at 2:22 AM, Steve Muckle <steve.muckle@linaro.org> wrote:
> From: Michael Turquette <mturquette@baylibre.com>
>
> Some architectures and platforms perform CPU frequency transitions
> through a non-blocking method, while some might block or sleep. Even
> when frequency transitions do not block or sleep they may be very slow.
> This distinction is important when trying to change frequency from
> a non-interruptible context in a scheduler hot path.
>
> Describe this distinction with a cpufreq driver flag,
> CPUFREQ_DRIVER_FAST. The default is to not have this flag set,
> thus erring on the side of caution.
>
> cpufreq_driver_is_slow() is also introduced in this patch. Setting
> the above flag will allow this function to return false.
>
> [smuckle@linaro.org: change flag/API to include drivers that are too
>  slow for scheduler hot paths, in addition to those that block/sleep]
>
> Cc: Rafael J. Wysocki <rafael@kernel.org>
> Cc: Viresh Kumar <viresh.kumar@linaro.org>
> Signed-off-by: Michael Turquette <mturquette@baylibre.com>
> Signed-off-by: Steve Muckle <smuckle@linaro.org>

Something more sophisticated than this is needed, because one driver
may actually be able to do "fast" switching in some cases and may not
be able to do that in other cases.

For example, in the acpi-cpufreq case all depends on what's there in
the ACPI tables.

Thanks,
Rafael
--
To unsubscribe from this list: send the line "unsubscribe linux-pm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Michael Turquette Feb. 26, 2016, 12:50 a.m. UTC | #2
Quoting Rafael J. Wysocki (2016-02-22 17:31:09)
> On Tue, Feb 23, 2016 at 2:22 AM, Steve Muckle <steve.muckle@linaro.org> wrote:
> > From: Michael Turquette <mturquette@baylibre.com>
> >
> > Some architectures and platforms perform CPU frequency transitions
> > through a non-blocking method, while some might block or sleep. Even
> > when frequency transitions do not block or sleep they may be very slow.
> > This distinction is important when trying to change frequency from
> > a non-interruptible context in a scheduler hot path.
> >
> > Describe this distinction with a cpufreq driver flag,
> > CPUFREQ_DRIVER_FAST. The default is to not have this flag set,
> > thus erring on the side of caution.
> >
> > cpufreq_driver_is_slow() is also introduced in this patch. Setting
> > the above flag will allow this function to return false.
> >
> > [smuckle@linaro.org: change flag/API to include drivers that are too
> >  slow for scheduler hot paths, in addition to those that block/sleep]
> >
> > Cc: Rafael J. Wysocki <rafael@kernel.org>
> > Cc: Viresh Kumar <viresh.kumar@linaro.org>
> > Signed-off-by: Michael Turquette <mturquette@baylibre.com>
> > Signed-off-by: Steve Muckle <smuckle@linaro.org>
> 
> Something more sophisticated than this is needed, because one driver
> may actually be able to do "fast" switching in some cases and may not
> be able to do that in other cases.

Those drivers can set the flag dynamically when they probe based on
their ACPI tables.

> 
> For example, in the acpi-cpufreq case all depends on what's there in
> the ACPI tables.

It's all a moot point until the locking in cpufreq is changed. Until
those changes are made it is a bad idea to call cpufreq_driver_target()
from schedule() context, regardless of the underlying hardware, and all
platforms should kick that work out to the kthread.

Regards,
Mike

> 
> Thanks,
> Rafael
--
To unsubscribe from this list: send the line "unsubscribe linux-pm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Steve Muckle Feb. 26, 2016, 1:07 a.m. UTC | #3
On 02/25/2016 04:50 PM, Michael Turquette wrote:
>> > Something more sophisticated than this is needed, because one driver
>> > may actually be able to do "fast" switching in some cases and may not
>> > be able to do that in other cases.
>
> Those drivers can set the flag dynamically when they probe based on
> their ACPI tables.

I was thinking that the reference here was to a driver that may be able
to do fast switching for some transitions and not for others, say
perhaps depending on the current and target frequencies, or the state of
the regulators, or other system conditions.

Rafael has proposed a fast_switch() addition to the cpufreq API which
currently returns void. Perhaps that could be extended to return success
or failure from the driver. The driver aborts if it cannot complete the
request atomically and quickly.

The scheduler-driven governor could attempt a fast switch if the
callback is installed (and the other criteria for the fast switch are
met, such as not throttled etc, no request already in flight etc). If
the fast switch aborts, fall back to the slow path.

I suppose the governor could also just see if policy->cur has changed as
opposed to checking cpufreq_driver_fast_switch's return value. But then
we can't tell the difference between the fast transition failing because
it must be re-attempted in the slow path, and the fast transition
failing because of some other more serious reason. In the latter case
the request should probably just be dropped rather than retried in the
slow path.
--
To unsubscribe from this list: send the line "unsubscribe linux-pm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Rafael J. Wysocki Feb. 26, 2016, 1:16 a.m. UTC | #4
On Thursday, February 25, 2016 04:50:29 PM Michael Turquette wrote:
> Quoting Rafael J. Wysocki (2016-02-22 17:31:09)
> > On Tue, Feb 23, 2016 at 2:22 AM, Steve Muckle <steve.muckle@linaro.org> wrote:
> > > From: Michael Turquette <mturquette@baylibre.com>
> > >
> > > Some architectures and platforms perform CPU frequency transitions
> > > through a non-blocking method, while some might block or sleep. Even
> > > when frequency transitions do not block or sleep they may be very slow.
> > > This distinction is important when trying to change frequency from
> > > a non-interruptible context in a scheduler hot path.
> > >
> > > Describe this distinction with a cpufreq driver flag,
> > > CPUFREQ_DRIVER_FAST. The default is to not have this flag set,
> > > thus erring on the side of caution.
> > >
> > > cpufreq_driver_is_slow() is also introduced in this patch. Setting
> > > the above flag will allow this function to return false.
> > >
> > > [smuckle@linaro.org: change flag/API to include drivers that are too
> > >  slow for scheduler hot paths, in addition to those that block/sleep]
> > >
> > > Cc: Rafael J. Wysocki <rafael@kernel.org>
> > > Cc: Viresh Kumar <viresh.kumar@linaro.org>
> > > Signed-off-by: Michael Turquette <mturquette@baylibre.com>
> > > Signed-off-by: Steve Muckle <smuckle@linaro.org>
> > 
> > Something more sophisticated than this is needed, because one driver
> > may actually be able to do "fast" switching in some cases and may not
> > be able to do that in other cases.
> 
> Those drivers can set the flag dynamically when they probe based on
> their ACPI tables.

No, they can't.

Being able to to the "fast" switching is a property of the policy and
the driver together and it may change with CPU going online/offline.

> > 
> > For example, in the acpi-cpufreq case all depends on what's there in
> > the ACPI tables.
> 
> It's all a moot point until the locking in cpufreq is changed.

No, it isn't.  Look at this, for example: https://patchwork.kernel.org/patch/8426741/

> Until those changes are made it is a bad idea to call cpufreq_driver_target()
> from schedule() context, regardless of the underlying hardware, and all
> platforms should kick that work out to the kthread.

Calling cpufreq_driver_target() from the scheduler is a bad idea overall,
not just because of the locking.

But there are other ways to switch frequencies from scheduler paths.  I run
such code on my test box daily without any problems.

Thanks,
Rafael

--
To unsubscribe from this list: send the line "unsubscribe linux-pm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Rafael J. Wysocki Feb. 26, 2016, 9 p.m. UTC | #5
On Fri, Feb 26, 2016 at 7:55 PM, Michael Turquette
<mturquette@baylibre.com> wrote:
> Quoting Rafael J. Wysocki (2016-02-25 17:16:17)
>> On Thursday, February 25, 2016 04:50:29 PM Michael Turquette wrote:
>> > Quoting Rafael J. Wysocki (2016-02-22 17:31:09)
>> > > On Tue, Feb 23, 2016 at 2:22 AM, Steve Muckle <steve.muckle@linaro.org> wrote:
>> > > For example, in the acpi-cpufreq case all depends on what's there in
>> > > the ACPI tables.
>> >
>> > It's all a moot point until the locking in cpufreq is changed.
>>
>> No, it isn't.  Look at this, for example: https://patchwork.kernel.org/patch/8426741/
>
> Thanks for the pointer. Do you mind Cc'ing me on future versions?

I'll do that.

Thanks,
Rafael
--
To unsubscribe from this list: send the line "unsubscribe linux-pm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index e979ec7..88e63ca 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -154,6 +154,12 @@  bool have_governor_per_policy(void)
 }
 EXPORT_SYMBOL_GPL(have_governor_per_policy);
 
+bool cpufreq_driver_is_slow(void)
+{
+	return !(cpufreq_driver->flags & CPUFREQ_DRIVER_FAST);
+}
+EXPORT_SYMBOL_GPL(cpufreq_driver_is_slow);
+
 struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy)
 {
 	if (have_governor_per_policy())
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 88a4215..93e1c1c 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -160,6 +160,7 @@  u64 get_cpu_idle_time(unsigned int cpu, u64 *wall, int io_busy);
 int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu);
 int cpufreq_update_policy(unsigned int cpu);
 bool have_governor_per_policy(void);
+bool cpufreq_driver_is_slow(void);
 struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy);
 #else
 static inline unsigned int cpufreq_get(unsigned int cpu)
@@ -316,6 +317,14 @@  struct cpufreq_driver {
  */
 #define CPUFREQ_NEED_INITIAL_FREQ_CHECK	(1 << 5)
 
+/*
+ * Indicates that it is safe to call cpufreq_driver_target from
+ * non-interruptable context in scheduler hot paths.  Drivers must
+ * opt-in to this flag, as the safe default is that they might sleep
+ * or be too slow for hot path use.
+ */
+#define CPUFREQ_DRIVER_FAST		(1 << 6)
+
 int cpufreq_register_driver(struct cpufreq_driver *driver_data);
 int cpufreq_unregister_driver(struct cpufreq_driver *driver_data);