Re: [PATCH v1 2/2] serial: 8250_dw: Revert "Improve clock rate setting"

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

 



On 19/01/18 16:02, Andy Shevchenko wrote:
> The commit
>
>   de9e33bdfa22 ("serial: 8250_dw: Improve clock rate setting")
>
> obviously tries to cure symptoms, and not a root cause.
>
> The root cause is the non-flexible rate calculation inside the
> corresponding clock driver.

The issue is the clock generating hardware in this particular platform
is only capable of generating finite clock rates from a fixed divider. 
So when dw8250_set_termios() requests baud * 16 it may get something
quite different - e.g. it requests 1.8432MHz for a baud rate of 115,200
and gets back 3MHz from clk_round_rate() as this is the nearest
achievable.  Before de9e33bdfa22, dw8250_set_termios() then sets the
clock to this rate which obviously doesn't work.

> What we need is to provide maximum UART
> divisor value to the clock driver to allow it do the job transparently
> to the caller.

So the clock driver should know that this clock is attached to a UART
with a fixed divider, and when 1.8432MHz is requested in the above
example it returns say 24MHz from clk_round_rate() because it knows that
the UART can divide this down to something within an acceptable range of
the requested rate for correct operation?

> Since from the initial commit message I have got no clue which clock
> driver actually needs to be amended, I leave this exercise to the people
> who know better the case.
>
> Moreover, it seems [1] the fix introduced a regression. And possible
> even one more [2].
>
> Taking above, revert the commit de9e33bdfa22 for now.
>
> [1]: https://www.spinics.net/lists/linux-serial/msg28872.html
> [2]: https://github.com/Dunedan/mbp-2016-linux/issues/29#issuecomment-357583782
>
> Cc: Ed Blake <ed.blake@xxxxxxxxxxx>
> Cc: Heikki Krogerus <heikki.krogerus@xxxxxxxxxxxxxxx>
> Cc: Lukas Wunner <lukas@xxxxxxxxx>
> Signed-off-by: Andy Shevchenko <andriy.shevchenko@xxxxxxxxxxxxxxx>
> ---
>  drivers/tty/serial/8250/8250_dw.c | 30 ++++++++++++------------------
>  1 file changed, 12 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
> index 7ab5c2643019..693fa66e7ec9 100644
> --- a/drivers/tty/serial/8250/8250_dw.c
> +++ b/drivers/tty/serial/8250/8250_dw.c
> @@ -245,31 +245,25 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
>  			       struct ktermios *old)
>  {
>  	unsigned int baud = tty_termios_baud_rate(termios);
> -	unsigned int target_rate, min_rate, max_rate;
>  	struct dw8250_data *d = p->private_data;
>  	long rate;
> -	int i, ret;
> +	int ret;
>  
>  	if (IS_ERR(d->clk) || !old)
>  		goto out;
>  
> -	/* Find a clk rate within +/-1.6% of an integer multiple of baudx16 */
> -	target_rate = baud * 16;
> -	min_rate = target_rate - (target_rate >> 6);
> -	max_rate = target_rate + (target_rate >> 6);
> -
> -	for (i = 1; i <= UART_DIV_MAX; i++) {
> -		rate = clk_round_rate(d->clk, i * target_rate);
> -		if (rate >= i * min_rate && rate <= i * max_rate)
> -			break;
> -	}
> -	if (i <= UART_DIV_MAX) {
> -		clk_disable_unprepare(d->clk);
> +	clk_disable_unprepare(d->clk);
> +	rate = clk_round_rate(d->clk, baud * 16);
> +	if (rate < 0)
> +		ret = rate;
> +	else if (rate == 0)
> +		ret = -ENOENT;
> +	else
>  		ret = clk_set_rate(d->clk, rate);
> -		clk_prepare_enable(d->clk);
> -		if (!ret)
> -			p->uartclk = rate;
> -	}
> +	clk_prepare_enable(d->clk);
> +
> +	if (!ret)
> +		p->uartclk = rate;
>  
>  out:
>  	p->status &= ~UPSTAT_AUTOCTS;

-- 
Ed

--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[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