* re: thermal: cpu_cooling: Use cpufreq_dev->freq_table for finding level/freq
@ 2015-06-10 15:02 Dan Carpenter
2015-06-11 3:05 ` Viresh Kumar
0 siblings, 1 reply; 3+ messages in thread
From: Dan Carpenter @ 2015-06-10 15:02 UTC (permalink / raw)
To: viresh.kumar; +Cc: linux-pm
Hello Viresh Kumar,
The patch 4843c4a19049: "thermal: cpu_cooling: Use
cpufreq_dev->freq_table for finding level/freq" from Dec 4, 2014,
leads to the following static checker warning:
drivers/thermal/cpu_cooling.c:163 get_level()
warn: potential off by one 'cpufreq_dev->freq_table[]' limit 'cpufreq_dev->max_level'
drivers/thermal/cpu_cooling.c
157 static unsigned long get_level(struct cpufreq_cooling_device *cpufreq_dev,
158 unsigned int freq)
159 {
160 unsigned long level;
161
162 for (level = 0; level <= cpufreq_dev->max_level; level++) {
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
163 if (freq == cpufreq_dev->freq_table[level])
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Reading beyond the end of the array.
164 return level;
165
166 if (freq > cpufreq_dev->freq_table[level])
167 break;
168 }
169
170 return THERMAL_CSTATE_INVALID;
171 }
The truth is that I have lots of checks that I can't publish, like for
example, if you use something with the word "size" or "max" as an index.
Obviously, it looks like <= should probably be < but just because it
looks wrong doesn't mean it is wrong. I searched for ->max_level and
read the documentation:
* @max_level: maximum cooling level. One less than total number of valid
* cpufreq frequencies.
The documentation is very clear that this loop is correct. It also
turns out that it used consistently almost throughout. But when I see
these unusual limits, I know it is often difficult to be 100%
consistent so I kept looking. It turns out there is off by one mistake
when we allocate the buffer.
cpufreq_dev->freq_table = kmalloc(sizeof(*cpufreq_dev->freq_table) *
cpufreq_dev->max_level, GFP_KERNEL);
It should be allocating:
sizeof(*cpufreq_dev->freq_table) * (cpufreq_dev->max_level + 1)
We could just change the allocation, but really this kind of unusual
limit is just going to cause more headaches in the future...
regards,
dan carpenter
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: thermal: cpu_cooling: Use cpufreq_dev->freq_table for finding level/freq
2015-06-10 15:02 thermal: cpu_cooling: Use cpufreq_dev->freq_table for finding level/freq Dan Carpenter
@ 2015-06-11 3:05 ` Viresh Kumar
2015-06-11 7:14 ` Dan Carpenter
0 siblings, 1 reply; 3+ messages in thread
From: Viresh Kumar @ 2015-06-11 3:05 UTC (permalink / raw)
To: Dan Carpenter; +Cc: linux-pm
Hi Dan,
On 10-06-15, 18:02, Dan Carpenter wrote:
> The documentation is very clear that this loop is correct. It also
> turns out that it used consistently almost throughout.
Right.
> But when I see
> these unusual limits, I know it is often difficult to be 100%
> consistent so I kept looking. It turns out there is off by one mistake
> when we allocate the buffer.
>
> cpufreq_dev->freq_table = kmalloc(sizeof(*cpufreq_dev->freq_table) *
> cpufreq_dev->max_level, GFP_KERNEL);
>
> It should be allocating:
>
> sizeof(*cpufreq_dev->freq_table) * (cpufreq_dev->max_level + 1)
Not really. This is how the code looks:
/* Find max levels */
cpufreq_for_each_valid_entry(pos, table)
cpufreq_dev->max_level++;
cpufreq_dev->freq_table = kmalloc(sizeof(*cpufreq_dev->freq_table) *
cpufreq_dev->max_level, GFP_KERNEL);
if (!cpufreq_dev->freq_table) {
cool_dev = ERR_PTR(-ENOMEM);
goto free_cdev;
}
/* max_level is an index, not a counter */
cpufreq_dev->max_level--;
So when the block was allocated, max_level was total number of levels
and was reduced later only.
> We could just change the allocation, but really this kind of unusual
> limit is just going to cause more headaches in the future...
I understand your concern, but it all happened because of the way
thermal layer expects the state. It wants state to be the index or
level of the cooling state. And that corresponds to the index in
cpufreq table. And so was kept this way.
--
viresh
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: thermal: cpu_cooling: Use cpufreq_dev->freq_table for finding level/freq
2015-06-11 3:05 ` Viresh Kumar
@ 2015-06-11 7:14 ` Dan Carpenter
0 siblings, 0 replies; 3+ messages in thread
From: Dan Carpenter @ 2015-06-11 7:14 UTC (permalink / raw)
To: Viresh Kumar; +Cc: linux-pm
On Thu, Jun 11, 2015 at 08:35:42AM +0530, Viresh Kumar wrote:
> /* max_level is an index, not a counter */
> cpufreq_dev->max_level--;
Argh... I am an idiot. Sorry for the noise.
regards,
dan carpenter
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2015-06-11 7:14 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-06-10 15:02 thermal: cpu_cooling: Use cpufreq_dev->freq_table for finding level/freq Dan Carpenter
2015-06-11 3:05 ` Viresh Kumar
2015-06-11 7:14 ` Dan Carpenter
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).