diff options
author | Werner Zeh <werner.zeh@siemens.com> | 2017-05-17 10:13:24 +0200 |
---|---|---|
committer | Werner Zeh <werner.zeh@siemens.com> | 2017-05-18 13:09:17 +0200 |
commit | 43314ffae53b813c6a0d6e34723921316cf46f45 (patch) | |
tree | accfd1e7e84330d347f91b10ec8253ec9fc21f0c /src/soc/broadcom/cygnus/ns16550.c | |
parent | e87564ffe7d0636699467b776a24adffb2f11cca (diff) | |
download | coreboot-43314ffae53b813c6a0d6e34723921316cf46f45.tar.xz |
uart: Fix bug in {uart8250, uart8250_mem, ns16550}_rx_byte functions
We have several different UART implementations of which three support a
timeout when receiving characters. In all of these three implementations
there is a bug where when the timeout is hit the last received character
will be returned instead of the needed 0.
The problem is that the timeout variable i is decremented after it has
been checked in the while-loop. That leads to the fact that when the
while-loop is aborted due to a timeout i will contain 0xffffffff and not
0. Thus in turn will fool the following if-statement leading to wrong
return value to the caller in this case. Therefore the caller will see a
received character event if there is none.
Change-Id: I23ff531a1e729e816764f1a071484c924dcb0f85
Signed-off-by: Werner Zeh <werner.zeh@siemens.com>
Reviewed-on: https://review.coreboot.org/19731
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Diffstat (limited to 'src/soc/broadcom/cygnus/ns16550.c')
-rw-r--r-- | src/soc/broadcom/cygnus/ns16550.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/src/soc/broadcom/cygnus/ns16550.c b/src/soc/broadcom/cygnus/ns16550.c index 71a4cb08ef..aa9dd2d818 100644 --- a/src/soc/broadcom/cygnus/ns16550.c +++ b/src/soc/broadcom/cygnus/ns16550.c @@ -84,8 +84,10 @@ static int ns16550_tst_byte(void) static unsigned char ns16550_rx_byte(void) { unsigned long int i = SINGLE_CHAR_TIMEOUT; - while (i-- && !ns16550_tst_byte()) + while (i && !ns16550_tst_byte()) { udelay(1); + i--; + } if (i) return read32(®s->rbr); else |