linux-tegra.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Re: [PATCH v3 1/6] regulator: core: validate selector against linear_min_sel
       [not found] ` <1605280870-32432-2-git-send-email-claudiu.beznea@microchip.com>
@ 2020-11-24  9:36   ` Jon Hunter
  2020-11-24 11:14     ` Claudiu.Beznea
  0 siblings, 1 reply; 5+ messages in thread
From: Jon Hunter @ 2020-11-24  9:36 UTC (permalink / raw)
  To: Claudiu Beznea, lgirdwood, broonie
  Cc: s.hauer, ttynkkynen, linus.walleij, axel.lin, linux-kernel,
	linux-arm-kernel, linux-tegra


On 13/11/2020 15:21, Claudiu Beznea wrote:
> There are regulators who's min selector is not zero. Selectors loops
> (looping b/w zero and regulator::desc::n_voltages) might throw errors
> because invalid selectors are used (lower than
> regulator::desc::linear_min_sel). For this situations validate selectors
> against regulator::desc::linear_min_sel.


After this commit was merged, I noticed a regression in the DFLL (CPU
clock source) on Tegra124. The DFLL driver
(drivers/clk/tegra/clk-dfll.c) calls regulator_list_voltage() in a loop
to determine the selector for a given voltage (see function
find_vdd_map_entry_exact()).

Currently, the DFLL driver queries the number of voltages provided by
the regulator by calling regulator_count_voltages() and then starting
from 0, iterates through the number of voltages to find the selector
value for the voltage it is looking for by calling
regulator_list_voltage(). It assumes that any negative value returned by
calling regulator_list_voltage() is an error and this will cause the
loop up to terminate.

In this case the regulator in question is the as3722 and the
linear_min_sel for this regulator is 1 and so when the DFLL driver calls
regulator_list_voltage() with a selector value of 0 it now returns a
negative error code, as expected by this change, and this terminates the
loop up in the DFLL driver. So I can clearly see why this is happening
and I could fix up the DFLL driver to avoid this.

Before doing so, I wanted to ask if that is the correct fix here,
because it seems a bit odd that regulator_count_voltages() returns N
voltages, but if the min selector value is greater than 0, then actually
there are less than N. However, changing the number of voltages
supported by the regulator to be N - linear_min_sel does not make sense
either because then we need to know the linear_min_sel in order to
determine the first valid voltage.

In case of the as3722, the value 0 means that the regulator is powered
down. So it is a valid setting and equates to 0 volts at the output AFAICT.

Please let me know your thoughts are the correct way to fix this up.

Thanks
Jon

-- 
nvpublic

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v3 1/6] regulator: core: validate selector against linear_min_sel
  2020-11-24  9:36   ` [PATCH v3 1/6] regulator: core: validate selector against linear_min_sel Jon Hunter
@ 2020-11-24 11:14     ` Claudiu.Beznea
  2020-11-24 13:41       ` Jon Hunter
  2020-11-24 14:11       ` Mark Brown
  0 siblings, 2 replies; 5+ messages in thread
From: Claudiu.Beznea @ 2020-11-24 11:14 UTC (permalink / raw)
  To: jonathanh, lgirdwood, broonie
  Cc: s.hauer, ttynkkynen, linus.walleij, axel.lin, linux-kernel,
	linux-arm-kernel, linux-tegra

Hi Jon,

On 24.11.2020 11:36, Jon Hunter wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> On 13/11/2020 15:21, Claudiu Beznea wrote:
>> There are regulators who's min selector is not zero. Selectors loops
>> (looping b/w zero and regulator::desc::n_voltages) might throw errors
>> because invalid selectors are used (lower than
>> regulator::desc::linear_min_sel). For this situations validate selectors
>> against regulator::desc::linear_min_sel.
> 
> 
> After this commit was merged, I noticed a regression in the DFLL (CPU
> clock source) on Tegra124. The DFLL driver
> (drivers/clk/tegra/clk-dfll.c) calls regulator_list_voltage() in a loop
> to determine the selector for a given voltage (see function
> find_vdd_map_entry_exact()).
> 
> Currently, the DFLL driver queries the number of voltages provided by
> the regulator by calling regulator_count_voltages() and then starting
> from 0, iterates through the number of voltages to find the selector
> value for the voltage it is looking for by calling
> regulator_list_voltage(). It assumes that any negative value returned by
> calling regulator_list_voltage() is an error and this will cause the
> loop up to terminate.
> 
> In this case the regulator in question is the as3722 and the
> linear_min_sel for this regulator is 1 and so when the DFLL driver calls
> regulator_list_voltage() with a selector value of 0 it now returns a
> negative error code, as expected by this change, and this terminates the
> loop up in the DFLL driver. So I can clearly see why this is happening
> and I could fix up the DFLL driver to avoid this.
> 
> Before doing so, I wanted to ask if that is the correct fix here,
> because it seems a bit odd that regulator_count_voltages() returns N
> voltages, but if the min selector value is greater than 0, then actually
> there are less than N. However, changing the number of voltages
> supported by the regulator to be N - linear_min_sel does not make sense
> either because then we need to know the linear_min_sel in order to
> determine the first valid voltage.
> 
> In case of the as3722, the value 0 means that the regulator is powered
> down. So it is a valid setting and equates to 0 volts at the output AFAICT.
> 
> Please let me know your thoughts are the correct way to fix this up.

I would say that a solution would be to have a new helper to retrieve the
linear_min_sel (e.g. regulator_min_sel()) and use this for all the
consumers of regulator_list_voltage() and the other APIs that patch
"regulator: core: validate selector against linear_min_sel" has changed
(regulator_list_voltage_table(), regulator_set_voltage_time()). With this
change the loop in find_vdd_map_entry_exact() should be b/w
regulator_min_sel() and regulator_count_voltages().

Maybe Mark has a better solution for this.

Thank you,
Claudiu

> 
> Thanks
> Jon
> 
> --
> nvpublic
> 

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v3 1/6] regulator: core: validate selector against linear_min_sel
  2020-11-24 11:14     ` Claudiu.Beznea
@ 2020-11-24 13:41       ` Jon Hunter
  2020-11-25 10:46         ` Claudiu.Beznea
  2020-11-24 14:11       ` Mark Brown
  1 sibling, 1 reply; 5+ messages in thread
From: Jon Hunter @ 2020-11-24 13:41 UTC (permalink / raw)
  To: Claudiu.Beznea, lgirdwood, broonie
  Cc: s.hauer, ttynkkynen, linus.walleij, axel.lin, linux-kernel,
	linux-arm-kernel, linux-tegra


On 24/11/2020 11:14, Claudiu.Beznea@microchip.com wrote:

...

> I would say that a solution would be to have a new helper to retrieve the
> linear_min_sel (e.g. regulator_min_sel()) and use this for all the
> consumers of regulator_list_voltage() and the other APIs that patch
> "regulator: core: validate selector against linear_min_sel" has changed
> (regulator_list_voltage_table(), regulator_set_voltage_time()). With this
> change the loop in find_vdd_map_entry_exact() should be b/w
> regulator_min_sel() and regulator_count_voltages().
> 
> Maybe Mark has a better solution for this.


By the way, I don't think that Tegra is alone here. I see some other
drivers doing some similar things [0][1][2] and so I am wondering if
this is going to be a problem for a few drivers.

Jon

[0]
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/mmc/core/regulator.c#n61
[1]
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/cpufreq/s3c2416-cpufreq.c#n263
[2]
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/leds/leds-regulator.c#n29

-- 
nvpublic

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v3 1/6] regulator: core: validate selector against linear_min_sel
  2020-11-24 11:14     ` Claudiu.Beznea
  2020-11-24 13:41       ` Jon Hunter
@ 2020-11-24 14:11       ` Mark Brown
  1 sibling, 0 replies; 5+ messages in thread
From: Mark Brown @ 2020-11-24 14:11 UTC (permalink / raw)
  To: Claudiu.Beznea
  Cc: jonathanh, lgirdwood, s.hauer, ttynkkynen, linus.walleij,
	axel.lin, linux-kernel, linux-arm-kernel, linux-tegra

[-- Attachment #1: Type: text/plain, Size: 1361 bytes --]

On Tue, Nov 24, 2020 at 11:14:54AM +0000, Claudiu.Beznea@microchip.com wrote:
> On 24.11.2020 11:36, Jon Hunter wrote:

> > Before doing so, I wanted to ask if that is the correct fix here,
> > because it seems a bit odd that regulator_count_voltages() returns N
> > voltages, but if the min selector value is greater than 0, then actually
> > there are less than N. However, changing the number of voltages
> > supported by the regulator to be N - linear_min_sel does not make sense
> > either because then we need to know the linear_min_sel in order to
> > determine the first valid voltage.

> I would say that a solution would be to have a new helper to retrieve the
> linear_min_sel (e.g. regulator_min_sel()) and use this for all the
> consumers of regulator_list_voltage() and the other APIs that patch
> "regulator: core: validate selector against linear_min_sel" has changed
> (regulator_list_voltage_table(), regulator_set_voltage_time()). With this
> change the loop in find_vdd_map_entry_exact() should be b/w
> regulator_min_sel() and regulator_count_voltages().

We need an incremental fix to return 0 rather than an error for things
below the minimum selector, it's not invalid for there to be holes in
the range of selectors and this is just an example of that.  Consumers
need to be able to cope with skipping over values that can't be mapped.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v3 1/6] regulator: core: validate selector against linear_min_sel
  2020-11-24 13:41       ` Jon Hunter
@ 2020-11-25 10:46         ` Claudiu.Beznea
  0 siblings, 0 replies; 5+ messages in thread
From: Claudiu.Beznea @ 2020-11-25 10:46 UTC (permalink / raw)
  To: jonathanh, lgirdwood, broonie
  Cc: s.hauer, ttynkkynen, linus.walleij, axel.lin, linux-kernel,
	linux-arm-kernel, linux-tegra



On 24.11.2020 15:41, Jon Hunter wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> On 24/11/2020 11:14, Claudiu.Beznea@microchip.com wrote:
> 
> ...
> 
>> I would say that a solution would be to have a new helper to retrieve the
>> linear_min_sel (e.g. regulator_min_sel()) and use this for all the
>> consumers of regulator_list_voltage() and the other APIs that patch
>> "regulator: core: validate selector against linear_min_sel" has changed
>> (regulator_list_voltage_table(), regulator_set_voltage_time()). With this
>> change the loop in find_vdd_map_entry_exact() should be b/w
>> regulator_min_sel() and regulator_count_voltages().
>>
>> Maybe Mark has a better solution for this.
> 
> 
> By the way, I don't think that Tegra is alone here. I see some other
> drivers doing some similar things [0][1][2] and so I am wondering if
> this is going to be a problem for a few drivers.
> 

As far as I can tell most of the regulator_list_voltage() consumers are
checking the return value against a [min_uV, max_uV] range or if the return
value is a negative error code or zero. The consumers are looking a
selector that respect the above rule for the entire [0,
regulator_count_voltages()] range (I have to double check for the rest of
functions modified by my patch). In case of clk-dfll.c the
find_vdd_map_entry_exact() returns if it finds the 1st invalid selector:

	n_voltages = regulator_count_voltages(td->vdd_reg);
	for (i = 0; i < n_voltages; i++) {
		reg_uV = regulator_list_voltage(td->vdd_reg, i);
		if (reg_uV < 0)
			break;

		reg_volt_id = reg_uV / td->soc->alignment.step_uv;

		if (align_step == reg_volt_id)
			return i;
	}

Maybe it would be better if the loop continues in case reg_uV is negative
or zero? (the zero case is good for this function as it will make the
(align_step == reg_volt_id) to be false). But as Mark said in the previous
email, there could be regulators with gaps in between min_sel and n_voltages.

With the previous code it seems it worked because the
regulator_list_voltage() calls the as3722's list_voltage which is
regulator_list_voltage_linear() which checks the selector against
min_selector and returns zero in case the selector is lower than the
min_selector. Please correct me if I'm wrong.

Anyway, I will prepare a fix for my previous patch to return zero in case
the regulator_count_voltages() receives an invalid selector. That should
also fix the case with this driver.

Thank you,
Claudiu

> Jon
> 
> [0]
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/mmc/core/regulator.c#n61
> [1]
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/cpufreq/s3c2416-cpufreq.c#n263
> [2]
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/leds/leds-regulator.c#n29
> 
> --
> nvpublic
> 

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2020-11-25 10:47 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <1605280870-32432-1-git-send-email-claudiu.beznea@microchip.com>
     [not found] ` <1605280870-32432-2-git-send-email-claudiu.beznea@microchip.com>
2020-11-24  9:36   ` [PATCH v3 1/6] regulator: core: validate selector against linear_min_sel Jon Hunter
2020-11-24 11:14     ` Claudiu.Beznea
2020-11-24 13:41       ` Jon Hunter
2020-11-25 10:46         ` Claudiu.Beznea
2020-11-24 14:11       ` Mark Brown

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).