summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRasmus Villemoes <ravi@prevas.dk>2024-10-03 16:10:27 +0200
committerTom Rini <trini@konsulko.com>2024-10-16 15:54:31 -0600
commitf4e7a399480c453df055b521ceda4c57ffb8e99e (patch)
tree4b56c7f8d758e04d7a39f76411168277433cb83c
parente698608680d1250ea50213551ce7c2b296529930 (diff)
serial: do not overwrite not-consumed characters in rx buffer
Before the previous patch, pasting a string of length x > CONFIG_SERIAL_RX_BUFFER_SIZE results in getting the last (x%CONFIG_SERIAL_RX_BUFFER_SIZE) characters from that string. With the previous patch, one instead gets the last CONFIG_SERIAL_RX_BUFFER_SIZE characters repeatedly until the ->rd_ptr catches up. Both behaviours are counter-intuitive, and happen because the code that checks for a character available from the hardware does not account for whether there is actually room in the software buffer to receive it. Fix that by adding such accounting. This also brings the software buffering more in line with how most hardware FIFOs behave (first received characters are kept, overflowing characters are dropped). Signed-off-by: Rasmus Villemoes <ravi@prevas.dk> Reviewed-by: Simon Glass <sjg@chromium.org>
-rw-r--r--drivers/serial/serial-uclass.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c
index 05fe9645bee..28d7a202afc 100644
--- a/drivers/serial/serial-uclass.c
+++ b/drivers/serial/serial-uclass.c
@@ -328,10 +328,11 @@ static int __serial_tstc(struct udevice *dev)
static int _serial_tstc(struct udevice *dev)
{
struct serial_dev_priv *upriv = dev_get_uclass_priv(dev);
- uint wr;
+ uint wr, avail;
- /* Read all available chars into the RX buffer */
- while (__serial_tstc(dev)) {
+ /* Read all available chars into the RX buffer while there's room */
+ avail = CONFIG_SERIAL_RX_BUFFER_SIZE - (upriv->wr_ptr - upriv->rd_ptr);
+ while (avail-- && __serial_tstc(dev)) {
wr = upriv->wr_ptr++ % CONFIG_SERIAL_RX_BUFFER_SIZE;
upriv->buf[wr] = __serial_getc(dev);
}