Re: [PATCH 2/2] tty: max310x: Fail probe when external clock crystal is not stable

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Jan,

On Wed, Aug 28, 2019 at 10:29:30PM +0200, Jan Kundrát wrote:
> On (some) of my boards, it appears that it takes up to three *checks* of
> this register's value for the external crystal to settle so that it is
> reported as "ready" by the chip. For example, on one of these boards it
> always succeeds upon a third try no matter if the individual waits are
> for 1ms or for 10ms. The original timeout of 10ms is therefore not ideal
> as it was generating false warnings on working HW for me. Let's solve
> this by retrying up to 20 times (i.e., 200ms).
> 
> With this retrying in place, it is now also possible to fail device
> initialization altogether. A stable clock is really required in order to
> use this UART, so log an error message and bail out if the chip keeps
> saying "nope".
> 
> Tested on several MAX14830 PCBs.
> 
> Signed-off-by: Jan Kundrát <jan.kundrat@xxxxxxxxx>
> ---
>  drivers/tty/serial/max310x.c | 15 +++++++++++----
>  1 file changed, 11 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
> index 0e0c2740ec7e..e8cd09d3e86f 100644
> --- a/drivers/tty/serial/max310x.c
> +++ b/drivers/tty/serial/max310x.c
> @@ -610,11 +610,14 @@ static int max310x_set_ref_clk(struct device *dev, struct max310x_port *s,
>  
>  	/* Wait for crystal */
>  	if (xtal) {
> -		unsigned int val;
> -		msleep(10);
> -		regmap_read(s->regmap, MAX310X_STS_IRQSTS_REG, &val);
> +		unsigned int val, i;
> +		for (i = 0; i < 20 && !(val & MAX310X_STS_CLKREADY_BIT); ++i) {

Don't you get a "'val' used uninitialized" compile-time warning here? Anyway
it must be zeroed before usage otherwise you might occasionally/permanently
end up with skipping this loop and the next conditional statement.

Though the former code was also buggy since in case if regmap_read() method
returned a non-zero value, the 'val' variable would be left uninitialized.
But this is a generic problem of the driver code, since it's a bit clumsy
at some places (I mean magic number literals and return values left untested).

I would also suggest to define and use the constants like MAX310X_XTAL_WAIT_RETRIES
and MAX310X_XTAL_WAIT_DELAY, so to parametrise this check-delay-loop.
Though it is up to you and the driver maintainer whether it's necessary to be
done.

-Sergey

> +			msleep(10);
> +			regmap_read(s->regmap, MAX310X_STS_IRQSTS_REG, &val);
> +		}
>  		if (!(val & MAX310X_STS_CLKREADY_BIT)) {
> -			dev_warn(dev, "clock is not stable yet\n");
> +			dev_err(dev, "clock is not stable\n");
> +			return -EAGAIN;
>  		}
>  	}
>  
> @@ -1301,6 +1304,10 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
>  	}
>  
>  	uartclk = max310x_set_ref_clk(dev, s, freq, xtal);
> +	if (uartclk < 0) {
> +		ret = uartclk;
> +		goto out_uart;
> +	}
>  	dev_dbg(dev, "Reference clock set to %i Hz\n", uartclk);
>  
>  	for (i = 0; i < devtype->nr; i++) {
> -- 
> 2.21.0
> 
> 



[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux PPP]     [Linux FS]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Linmodem]     [Device Mapper]     [Linux Kernel for ARM]

  Powered by Linux