The old code checked for overflow only once before the loop, which
meant a multi-byte write could silently overflow the FIFO when there
was space for some but not all bytes. Check per-byte instead, storing
as many bytes as possible before flagging ROVR. Only arm the FIFO
trigger timer when bytes were actually stored.
Fixes: 35548b06cf55 ("cadence_uart: initial version of device model")
Reported-by: Pavee Hui <[email protected]>
Signed-off-by: Marc-André Lureau <[email protected]>
---
hw/char/cadence_uart.c | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index eff6a3c4d17a..ae11caa11b82 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -284,14 +284,16 @@ static void uart_write_rx_fifo(void *opaque, const
uint8_t *buf, int size)
return;
}
- if (s->rx_count == CADENCE_UART_RX_FIFO_SIZE) {
- s->r[R_CISR] |= UART_INTR_ROVR;
- } else {
- for (i = 0; i < size; i++) {
- s->rx_fifo[s->rx_wpos] = buf[i];
- s->rx_wpos = (s->rx_wpos + 1) % CADENCE_UART_RX_FIFO_SIZE;
- s->rx_count++;
+ for (i = 0; i < size; i++) {
+ if (s->rx_count >= CADENCE_UART_RX_FIFO_SIZE) {
+ s->r[R_CISR] |= UART_INTR_ROVR;
+ break;
}
+ s->rx_fifo[s->rx_wpos] = buf[i];
+ s->rx_wpos = (s->rx_wpos + 1) % CADENCE_UART_RX_FIFO_SIZE;
+ s->rx_count++;
+ }
+ if (i > 0) {
timer_mod(s->fifo_trigger_handle, new_rx_time +
(s->char_tx_time * 4));
}
--
2.56.0.rc0.29.g47ce80527c56