[U-Boot] [PATCH 5/6] serial: ns16550: fix debug uart putc called before init

Marek Vasut marex at denx.de
Thu Aug 9 21:45:47 UTC 2018


On 08/09/2018 11:13 PM, Adam Ford wrote:
> On Thu, Aug 9, 2018 at 2:08 PM Simon Goldschmidt
> <simon.k.r.goldschmidt at gmail.com> wrote:
>>
>> If _debug_uart_putc() is called before _debug_uart_init(), the
>> ns16550 debug uart driver hangs in a tight loop waiting for the
>> tx FIFO to get empty.
>>
>> As this can happen via a printf sneaking in before the port calls
>> debug_uart_init(), let's rather ignore characters before the debug
>> uart is initialized.
>>
>> This is done by reading the baudrate divisor and aborting if is zero.
>>
>> Tested on socfpga_cyclone5_socrates.
>>
>> Signed-off-by: Simon Goldschmidt <simon.k.r.goldschmidt at gmail.com>
>> ---
>> v2:
>>  - this patch is new in v2 of the series. It replaces the printf/debug
>>   change in reset_manager_gen5.c from v1
>>
>>  drivers/serial/ns16550.c | 18 ++++++++++++++++--
>>  1 file changed, 16 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
>> index 9c80090aa7..475075c03c 100644
>> --- a/drivers/serial/ns16550.c
>> +++ b/drivers/serial/ns16550.c
>> @@ -266,12 +266,26 @@ static inline void _debug_uart_init(void)
>>         serial_dout(&com_port->lcr, UART_LCRVAL);
>>  }
>>
>> +static inline int NS16550_read_baud_divisor(struct NS16550 *com_port)
>> +{
>> +       int ret;
>> +
>> +       serial_dout(&com_port->lcr, UART_LCR_BKSE | UART_LCRVAL);
>> +       ret = serial_din(&com_port->dll) & 0xff;
>> +       ret |= (serial_din(&com_port->dlm) & 0xff) << 8;
>> +       serial_dout(&com_port->lcr, UART_LCRVAL);
>> +
>> +       return ret;
>> +}
>> +
>>  static inline void _debug_uart_putc(int ch)
>>  {
>>         struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE;
>>
>> -       while (!(serial_din(&com_port->lsr) & UART_LSR_THRE))
>> -               ;
>> +       while (!(serial_din(&com_port->lsr) & UART_LSR_THRE)) {
>> +               if (!NS16550_read_baud_divisor(com_port))
> 
> Unless there is a change that the read_baud_divisor will change while
> we're waiting for the character, could we move this check before the
> while statement?  This would reduce the check for the divisor to 1x
> and the while statement would only have one comparison to do.  I
> realize it's rather trivial, but the way I see it, there is no reason
> to do the while statement at all if the read_baud_divisor fails and
> there if there is a baud divisor, we should only need to check it
> once.

This looks like a massive hack -- what about having a flag which says
that the debug uart was/was not inited somewhere ?

-- 
Best regards,
Marek Vasut


More information about the U-Boot mailing list