linux-serial.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jon Hunter <jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
To: Laxman Dewangan
	<ldewangan-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>,
	Greg Kroah-Hartman
	<gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org>,
	Jiri Slaby <jslaby-AlSwsSmVLrQ@public.gmane.org>
Cc: linux-serial-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Shardar Shariff Md
	<smohammed-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>,
	Jon Hunter <jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
Subject: [PATCH 4/8] serial: tegra: handle race condition on uart rx side
Date: Tue, 5 May 2015 15:17:55 +0100	[thread overview]
Message-ID: <1430835479-6613-5-git-send-email-jonathanh@nvidia.com> (raw)
In-Reply-To: <1430835479-6613-1-git-send-email-jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>

From: Shardar Shariff Md <smohammed-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>

The tegra serial driver has two paths through which receive data is
copied up to the tty layer. These are:
1. DMA completion callback
2. UART RX interrupt

A UART RX interrupt occurs for either RX_TIMEOUT (data has been sitting
in the Rx FIFO for more than 4 character times without being read
because there is not enough data to reach the trigger level), End of
Receive Data event (receiver detects that data stops coming in for more
than 4 character times) or a receive error.

In the RX interrupt path, the following happens ...
- All RX DMA transfers are stopped
- Any data in the DMA buffer and RX FIFO are copied up to the tty layer.
- DMA is restarted/primed for the RX path

In the DMA completion callback, the DMA buffer is copied up to the tty
layer but there is no check to see if the RX interrupt could have
occurred between the DMA interrupt firing the the DMA callback running.
Hence, if a RX interrupt was to occur shortly after the DMA completion
interrupt, it is possible that the RX interrupt path has already copied
the DMA buffer before the DMA callback has been called. Therefore, when
the DMA callback is called, if the DMA is already in-progress, then this
indicates that the UART RX interrupt has already occurred and there is
nothing to do in the DMA callback. This race condition can cause
duplicated data to be received.

Signed-off-by: Shardar Shariff Md <smohammed-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
[jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org: Moved async_tx_ack() call to after check to see
 if DMA has completed because if the DMA is in progress we do not need
 to ACK yet. Changed the print from dev_info to dev_debug. Updated
 changelog to add more commentary on the race condition based upon
 feedback from author.]
Signed-off-by: Jon Hunter <jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 drivers/tty/serial/serial-tegra.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/serial/serial-tegra.c b/drivers/tty/serial/serial-tegra.c
index a53899c47e60..17d8a08b047b 100644
--- a/drivers/tty/serial/serial-tegra.c
+++ b/drivers/tty/serial/serial-tegra.c
@@ -583,10 +583,20 @@ static void tegra_uart_rx_dma_complete(void *args)
 	struct tty_struct *tty = tty_port_tty_get(&tup->uport.state->port);
 	struct tty_port *port = &u->state->port;
 	unsigned long flags;
+	struct dma_tx_state state;
+	enum dma_status status;
 
-	async_tx_ack(tup->rx_dma_desc);
 	spin_lock_irqsave(&u->lock, flags);
 
+	status = dmaengine_tx_status(tup->rx_dma_chan, tup->rx_cookie, &state);
+
+	if (status == DMA_IN_PROGRESS) {
+		dev_dbg(tup->uport.dev, "RX DMA is in progress\n");
+		goto done;
+	}
+
+	async_tx_ack(tup->rx_dma_desc);
+
 	/* Deactivate flow control to stop sender */
 	if (tup->rts_active)
 		set_rts(tup, false);
@@ -607,6 +617,7 @@ static void tegra_uart_rx_dma_complete(void *args)
 	if (tup->rts_active)
 		set_rts(tup, true);
 
+done:
 	spin_unlock_irqrestore(&u->lock, flags);
 }
 
-- 
1.9.1

  parent reply	other threads:[~2015-05-05 14:17 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-05-05 14:17 [PATCH 0/8] serial: tegra: various fixes Jon Hunter
     [not found] ` <1430835479-6613-1-git-send-email-jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2015-05-05 14:17   ` [PATCH 1/8] serial: tegra: Correct delay after TX flush Jon Hunter
2015-05-05 14:17   ` [PATCH 2/8] serial: tegra: Add delay after enabling FIFO mode Jon Hunter
2015-05-05 14:17   ` [PATCH 3/8] serial: tegra: check the count and read if any from dma Jon Hunter
2015-05-05 14:17   ` Jon Hunter [this message]
2015-05-05 14:17   ` [PATCH 5/8] serial: tegra: Use unsigned types for RX and TX byte counts Jon Hunter
2015-05-05 14:17   ` [PATCH 6/8] serial: tegra: Fix cookie used by TX channel Jon Hunter
2015-05-05 14:17   ` [PATCH 7/8] serial: tegra: Correct shutdown of UARTs Jon Hunter
2015-05-05 14:17   ` [PATCH 8/8] serial: tegra: Correct error handling on DMA setup Jon Hunter
2015-05-12  8:39     ` Alexandre Courbot
     [not found]       ` <CAAVeFuL=z-xbGT1e_L6+_GQ8aZ0BvNBfmoi65u_7qVHv=tpTbA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2015-05-12  9:51         ` Jon Hunter
2015-05-13  4:56           ` Alexandre Courbot
2015-05-13  8:23             ` Jon Hunter
2015-05-20  3:57               ` Alexandre Courbot
     [not found]                 ` <CAAVeFuL8XoQUykpVbzgJiYNkoXA0e7c1k95nvB6Q+wZUHjOjSw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2015-05-20  9:51                   ` Jon Hunter
2015-05-20 12:12                     ` Jon Hunter

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1430835479-6613-5-git-send-email-jonathanh@nvidia.com \
    --to=jonathanh-ddmlm1+adcrqt0dzr+alfa@public.gmane.org \
    --cc=gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org \
    --cc=jslaby-AlSwsSmVLrQ@public.gmane.org \
    --cc=ldewangan-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org \
    --cc=linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=linux-serial-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=linux-tegra-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=smohammed-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).