From dacd041a94b4150a90b401ef2098ae0015c7fa97 Mon Sep 17 00:00:00 2001 From: Masayuki Ishikawa Date: Wed, 16 Oct 2019 13:09:03 +0000 Subject: [PATCH] Merged in masayuki2009/nuttx.nuttx/fix_serial_driver_for_smp (pull request #1052) drivers: serial: Fix data corruption when outputting data in SMP mode Signed-off-by: Masayuki Ishikawa Approved-by: Gregory Nutt --- drivers/serial/serial.c | 26 +++++++++++++++++++++----- drivers/serial/serial_io.c | 12 ++++++++++++ 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c index 234f7252247..8ef0058da40 100644 --- a/drivers/serial/serial.c +++ b/drivers/serial/serial.c @@ -229,6 +229,10 @@ static int uart_putxmitchar(FAR uart_dev_t *dev, int ch, bool oktoblock) int nexthead; int ret; +#ifdef CONFIG_SMP + flags = enter_critical_section(); +#endif + /* Increment to see what the next head pointer will be. We need to use the "next" * head pointer to determine when the circular buffer would overrun */ @@ -251,7 +255,8 @@ static int uart_putxmitchar(FAR uart_dev_t *dev, int ch, bool oktoblock) dev->xmit.buffer[dev->xmit.head] = ch; dev->xmit.head = nexthead; - return OK; + ret = OK; + goto err_out; } /* The TX buffer is full. Should be block, waiting for the hardware @@ -325,7 +330,8 @@ static int uart_putxmitchar(FAR uart_dev_t *dev, int ch, bool oktoblock) if (dev->disconnected) { - return -ENOTCONN; + ret = -ENOTCONN; + goto err_out; } #endif /* Check if we were awakened by signal. */ @@ -336,7 +342,8 @@ static int uart_putxmitchar(FAR uart_dev_t *dev, int ch, bool oktoblock) * non-full will abort the transfer. */ - return -EINTR; + ret = -EINTR; + goto err_out; } } @@ -346,7 +353,8 @@ static int uart_putxmitchar(FAR uart_dev_t *dev, int ch, bool oktoblock) else { - return -EAGAIN; + ret = -EAGAIN; + goto err_out; } } @@ -354,7 +362,15 @@ static int uart_putxmitchar(FAR uart_dev_t *dev, int ch, bool oktoblock) * unreachable. */ - return OK; + ret = OK; + +err_out: + +#ifdef CONFIG_SMP + leave_critical_section(flags); +#endif + + return ret; } /************************************************************************************ diff --git a/drivers/serial/serial_io.c b/drivers/serial/serial_io.c index 94a41e8b077..97a31bb4811 100644 --- a/drivers/serial/serial_io.c +++ b/drivers/serial/serial_io.c @@ -39,6 +39,10 @@ #include +#ifdef CONFIG_SMP +# include +#endif + #include #include #include @@ -65,6 +69,10 @@ void uart_xmitchars(FAR uart_dev_t *dev) { uint16_t nbytes = 0; +#ifdef CONFIG_SMP + irqstate_t flags = enter_critical_section(); +#endif + /* Send while we still have data in the TX buffer & room in the fifo */ while (dev->xmit.head != dev->xmit.tail && uart_txready(dev)) @@ -104,6 +112,10 @@ void uart_xmitchars(FAR uart_dev_t *dev) { uart_datasent(dev); } + +#ifdef CONFIG_SMP + leave_critical_section(flags); +#endif } /************************************************************************************