How many frequencies would cpufreq optimally like to manage?
Hello everyone,
I'm running kernel 3.14 on an ARM Cortex-A9 based SoC. The baseline frequency for the ARM CPU is 999 MHz.
The SoC provides a way to dynamically change the CPU frequency, dividing it by N/16 (N=32..4095) [Actually, I think there are also ways to divide by 1.x, but I need to read the docs again.]
I'm writing the platform-specific cpufreq driver.
I could expose hundreds of frequencies to cpufreq, but I don't think that would be very productive. Correct?
(Note: I can't offer ANY frequency.)
My question is: how many frequencies should I expose for "optimal" behavior of cpufreq?
I'm thinking I would only expose div={2,3,5} meaning the available scaled frequencies would be {500,333,200} MHz. Are these enough? Should there be more? Should I go lower than 200 MHz?
I'm also wondering about the cpuinfo_transition_latency variable. It seems to be a constant. On my SoC, the latency depends on the "width" of the frequency jump. Specifically, the CPU will change frequency at 15 MHz/us. So if we're jumping from 1000 to 500 MHz, it will take 33 us. From 500 to 333 will take 11 us.
Should I document the max latency? (i.e. for the "widest" jump) Can the governor request to jump from cpuinfo_min_freq to cpuinfo_max_freq directly, skipping intermediate frequencies? If so, should I just program
cpuinfo_transition_latency =
(((cpuinfo_max_freq - cpuinfo_min_freq) / 1000) / 15) * 1000
= (cpuinfo_max_freq - cpuinfo_min_freq) / 15 (in ns) = 53280 ns in my example
Since governors.txt suggests a sampling rate of 10 ms, I suppose a transition_latency of 50 us is acceptable?
Regards.
Quoted 1 line · Mason
Hello everyone,
Hi,
The right list is linux-pm and try to cc maintainers from MAINTAINERS file as they can respond quickly then.
Quoted 7 lines
I'm running kernel 3.14 on an ARM Cortex-A9 based SoC. The baseline frequency for the ARM CPU is 999 MHz.
The SoC provides a way to dynamically change the CPU frequency, dividing it by N/16 (N=32..4095) [Actually, I think there are also ways to divide by 1.x, but I need to read the docs again.]
Quoted 7 lines
I'm writing the platform-specific cpufreq driver.
I could expose hundreds of frequencies to cpufreq, but I don't think that would be very productive. Correct?
(Note: I can't offer ANY frequency.)My question is: how many frequencies should I expose for "optimal" behavior of cpufreq?
You can specify as many number of frequencies as you want. The framework doesn't have any upper cap on that. But there is no point specifying 500 MHz and 510 MHz, you wouldn't save much power with 500 :)
So, just gap them smartly. Normally people gap them to 100 MHz. But if there is a voltage change required at some specific freq, suppose 550 MHz, then its better you specific that as well..
Quoted 2 lines
I'm thinking I would only expose div={2,3,5} meaning the available scaled frequencies would be {500,333,200} MHz. Are these enough?
I thought you can goto 1 GHz.. Why not the upper ones then?
Quoted 1 line
Should there be more? Should I go lower than 200 MHz?
If that really saves power.
Quoted 7 lines
I'm also wondering about the
cpuinfo_transition_latencyvariable. It seems to be a constant. On my SoC, the latency depends on the "width" of the frequency jump. Specifically, the CPU will change frequency at 15 MHz/us. So if we're jumping from 1000 to 500 MHz, it will take 33 us. From 500 to 333 will take 11 us.Should I document the max latency? (i.e. for the "widest" jump)
Yes.
Quoted 2 lines
Can the governor request to jump from
cpuinfo_min_freqtocpuinfo_max_freqdirectly, skipping intermediate frequencies?
Yes, its a normal case for ondemand governor.
Quoted 10 lines
If so, should I just program
cpuinfo_transition_latency=
(((cpuinfo_max_freq-cpuinfo_min_freq) / 1000) / 15) * 1000= (
cpuinfo_max_freq-cpuinfo_min_freq) / 15 (in ns) = 53280 ns in my exampleSince governors.txt suggests a sampling rate of 10 ms, I suppose a
transition_latencyof 50 us is acceptable?
Yes.
Quoted 6 lines · Viresh Kumar
Quoted 1 line · Mason
Hello everyone,
The right list is linux-pm and try to cc maintainers from
MAINTAINERSfile as they can respond quickly then.
Sorry about that. I wasn't even aware that an index like MAINTAINERS existed AND was kept up-to-date.
Quoted 12 lines
Quoted 12 lines
I'm running kernel 3.14 on an ARM Cortex-A9 based SoC. The baseline frequency for the ARM CPU is 999 MHz.
The SoC provides a way to dynamically change the CPU frequency, dividing it by N/16 (N=32..4095) [Actually, I think there are also ways to divide by 1.x, but I need to read the docs again.]
I'm writing the platform-specific cpufreq driver.
I could expose hundreds of frequencies to cpufreq, but I don't think that would be very productive. Correct?
(Note: I can't offer ANY frequency.)
Quoted 6 lines
Quoted 2 lines
My question is: how many frequencies should I expose for "optimal" behavior of cpufreq?
You can specify as many number of frequencies as you want. The framework doesn't have any upper cap on that. But there is no point specifying 500 MHz and 510 MHz, you wouldn't save much power with 500 :)
Suppose I expose 100 frequencies. Aside from wasting memory, isn't there also a risk that cpufreq will take time, ramping up/down through similar frequencies? (Or does it just say "jump to THAT frequency" skipping useless intermediate frequencies?)
Quoted 3 lines
So, just gap them smartly. Normally people gap them to 100 MHz. But if there is a voltage change required at some specific freq, suppose 550 MHz, then its better you specific that as well..
Point taken.
Quoted 4 lines
Quoted 2 lines
I'm thinking I would only expose div={2,3,5} meaning the available scaled frequencies would be {500,333,200} MHz. Are these enough?
I thought you can goto 1 GHz.. Why not the upper ones then?
The actual formula for dividers isdiv(I,F) = if I > 1 then I+F/16 else I+F/(32-F)
I=1..255 F=0..15
So, I can use (for example) div={1, 1.33, 2, 4, 8} to offer freq={999,750,500,250,125}
Quoted 3 lines
Quoted 1 line
Should there be more? Should I go lower than 200 MHz?
If that really saves power.
There is a trade-off, tough.
My concern is this: suppose the CPU cores are set to e.g. 54 MHz. Suddenly, the driver for an important subsystem needs to speak with the corresponding device, with hard deadlines in the comms protocol. Will the CPU ramp up fast enough (assuming ondemand governor).
And the end of this message is as good a place as any to thank you for having answered my many questions.
Regards.
Quoted 5 lines · Mason
On 20/11/2014 10:13, Viresh Kumar wrote:
Suppose I expose 100 frequencies. Aside from wasting memory, isn't there also a risk that cpufreq will take time, ramping up/down through similar frequencies? (Or does it just say "jump to THAT frequency" skipping useless intermediate frequencies?)
Some time might be wasted for similar frequencies, moreover for every change we have to traverse 100 frequencies to see which one fits best.
Quoted 6 lines
There is a trade-off, tough.
My concern is this: suppose the CPU cores are set to e.g. 54 MHz. Suddenly, the driver for an important subsystem needs to speak with the corresponding device, with hard deadlines in the comms protocol. Will the CPU ramp up fast enough (assuming ondemand governor).
All current governors depend on background timers for their functionality. These timers run at some sampling rate (in ms) and that time we change CPU's frequency depending on existing load on system.. So, that might not be fast enough.
Quoted 2 lines
And the end of this message is as good a place as any to thank you for having answered my many questions.
Your welcome :)
Quoted 4 lines · Viresh Kumar
All current governors depend on background timers for their functionality. These timers run at some sampling rate (in ms) and that time we change CPU's frequency depending on existing load on system.. So, that might not be fast enough.
As far as I can tell, on my SoC, the timer runs at 27 MHz. But I have no idea how often it fires an interrupt.
I've been studying other cpufreq drivers, especially the OMAP driver. I noticed that there is a lot of generic infrastructure that our driver wasn't using, such as...
cpufreq_generic_init
cpufreq_generic_exit
cpufreq_generic_frequency_table_verify
cpufreq_generic_attr
I've changed our driver to use those.
I'm still confused about cpufreq_generic_get. This is not a typical get/put type function, right?
What is it supposed to get?
Apparently, the actual frequency of the 'cpu-th' CPU? I see that it calls clk_get_rate(policy->clk)
This 'struct clk' is an elusive beast.
Where is it defined? I only run into forward declarations.
On my platform, clk_get_accuracy returns -524 unconditionally, and clk_prepare just returns 0.
of_clk_get and of_clk_get_by_name both return ERR_PTR(-2)
I suppose all this means I can't use this infrastructure "as-is", correct? Where can I read more about it?
How is the kernel supposed to know what frequency each core is running at? I imagine that's what the .get method override is for?
One more question (for now). Is the .get method supposed to return numbers that match in freq_table, or can they be slightly different? For example, I've defined my freq_table like this:
static struct cpufreq_frequency_table freq_table[] = {
{ .driver_data = REG_VAL(1,0), .frequency = 999000 },
{ .driver_data = REG_VAL(1,8), .frequency = 750000 },
{ .driver_data = REG_VAL(2,0), .frequency = 500000 },
{ .driver_data = REG_VAL(4,0), .frequency = 250000 },
{ .driver_data = REG_VAL(8,0), .frequency = 125000 },
{ .frequency = CPUFREQ_TABLE_END },
};but the 3rd frequency is actually 999/2 MHz, not 500 MHz, etc. Will that be a problem?
Regards.
Quoted 2 lines · Mason
As far as I can tell, on my SoC, the timer runs at 27 MHz. But I have no idea how often it fires an interrupt.
27 MHz is the freq it runs at, but we get interrupt based on the value programmed in the timer counter.
Look for CONFIG_HZ in your .config, that will tell you number of ticks you are getting per second.
But cpufreq works in another level and so it doesn't depend on both these.
Look for: /sys/devices/system/cpu/cpufreq/ondemand/sampling_rate
this is the rate at which cpufreq core checks if cpu's freq require revisiting.
Quoted 10 lines
I've been studying other cpufreq drivers, especially the OMAP driver. I noticed that there is a lot of generic infrastructure that our driver wasn't using, such as...
cpufreq_generic_init
cpufreq_generic_exit
cpufreq_generic_frequency_table_verify
cpufreq_generic_attrI've changed our driver to use those.
Gud.
Quoted 2 lines
I'm still confused about
cpufreq_generic_get. This is not a typical get/put type function, right?
Correct, this should return the current frequency the CPU is running at.
Quoted 3 lines
What is it supposed to get?
Apparently, the actual frequency of the 'cpu-th' CPU? I see that it callsclk_get_rate(policy->clk)
Yes.
Quoted 2 lines
This 'struct clk' is an elusive beast.
Where is it defined? I only run into forward declarations.
Its architecture specific. What's the architecture you are working on? You may implement your own routine instead of cpufreq_generic_get().
Quoted 1 line
On my platform,
clk_get_accuracyreturns -524 unconditionally,
That might be an error.
Quoted 6 lines
and
clk_preparejust returns 0.
of_clk_getandof_clk_get_by_nameboth returnERR_PTR(-2)I suppose all this means I can't use this infrastructure "as-is", correct? Where can I read more about it?
Yes. Documentation/clk.txt.
Quoted 2 lines
How is the kernel supposed to know what frequency each core is running at? I imagine that's what the .get method override is for?
Yeah. You should be able to get some call from your architecture.
Quoted 2 lines
One more question (for now). Is the .get method supposed to return numbers that match in
freq_table, or can they be slightly different? For example,
They should match.
Quoted 11 lines
I've defined my
freq_tablelike this:static struct cpufreq_frequency_table freq_table[] = { { .driver_data = REG_VAL(1,0), .frequency = 999000 }, { .driver_data = REG_VAL(1,8), .frequency = 750000 }, { .driver_data = REG_VAL(2,0), .frequency = 500000 }, { .driver_data = REG_VAL(4,0), .frequency = 250000 }, { .driver_data = REG_VAL(8,0), .frequency = 125000 }, { .frequency = CPUFREQ_TABLE_END }, };
Quoted 2 lines
but the 3rd frequency is actually 999/2 MHz, not 500 MHz, etc. Will that be a problem?
Maybe, but it depends on what your ->get() returns.
Quoted 5 lines · Viresh Kumar
Quoted 2 lines · Mason
As far as I can tell, on my SoC, the timer runs at 27 MHz. But I have no idea how often it fires an interrupt.
Quoted 8 lines
27 MHz is the freq it runs at, but we get interrupt based on the value programmed in the timer counter.
Look for
CONFIG_HZin your .config, that will tell you number of ticks you are getting per second.But cpufreq works in another level and so it doesn't depend on both these.
If I remember correctly (please correct me if I am mistaken), the kernel keeps a list of timers, ordered by deadline, and dynamically configures the system timer to fire at the next deadline.
Quoted 2 lines
Look for:
/sys/devices/system/cpu/cpufreq/ondemand/sampling_ratethis is the rate at which cpufreq core checks if cpu's freq require revisiting.
I think setting the sampling rate to 50 ms should make the system reactive enough to load swings?
Quoted 5 lines
Quoted 2 lines
This 'struct clk' is an elusive beast.
Where is it defined? I only run into forward declarations.Its architecture specific. What's the architecture you are working on? You may implement your own routine instead of
cpufreq_generic_get().
The SoC is made by Sigma Designs. It is based on the ARM Cortex-A9.
Quoted 1 line
Yes.
Documentation/clk.txt.
Oh boy! platform, device tree, cpu-freq, cpuidle, clk, ... so much to learn, so few hours in a day.
Quoted 1 line
Yeah. You should be able to get some call from your architecture.
OK, I have to fix that function along with the cpufreq update.
Regards.
Quoted 4 lines · Mason
If I remember correctly (please correct me if I am mistaken), the kernel keeps a list of timers, ordered by deadline, and dynamically configures the system timer to fire at the next deadline.
Yes.
Quoted 5 lines
Quoted 2 lines
Look for:
/sys/devices/system/cpu/cpufreq/ondemand/sampling_ratethis is the rate at which cpufreq core checks if cpu's freq require revisiting.I think setting the sampling rate to 50 ms should make the system reactive enough to load swings?
Depends on the kind of load system is under. If load changes quite frequently then 50 ms can be a very big value. If it doesn't then 50 ms might be good. But it has to be tuned properly based on how much load the system has and how much power it consumes.
Some information about that tuning can be found here:
https://www.youtube.com/watch?v=he1UO__K9ao
This is an presentation given by Mathieu Poirier (Linaro) about the work done on ARM's big LITTLE architecture.
Slides: http://events.linuxfoundation.org/images/stories/slides/elc2013_poirier.pdf
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
This 'struct clk' is an elusive beast.
Where is it defined? I only run into forward declarations.Its architecture specific. What's the architecture you are working on? You may implement your own routine instead of
cpufreq_generic_get().The SoC is made by Sigma Designs. It is based on the ARM Cortex-A9.
Okay, life should be easy then. Normally there will be few programmable PLLs on your platform. You need to write a clock driver for them similar to the ones present here: drivers/clk/
And then you can reuse cpufreq-dt.c cpufreq driver, which is generic enough for everybody :)
Quoted 4 lines
Quoted 1 line
Yes.
Documentation/clk.txt.Oh boy! platform, device tree, cpu-freq, cpuidle, clk, ... so much to learn, so few hours in a day.
:)