Browse Source

serial: sh-sci: Fix deadlock caused by serial output request

While spin is already locked, serial output request causes the deadlock,
because serial output process also tries to lock the spin.
This patch removes serial output with spin locked.

Signed-off-by: Takatoshi Akiyama <takatoshi.akiyama.kj@ps.hitachi-solutions.com>
Signed-off-by: Takeshi Kihara <takeshi.kihara.df@renesas.com>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Acked-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Takatoshi Akiyama 8 years ago
parent
commit
6fc5a52042
1 changed files with 5 additions and 15 deletions
  1. 5 15
      drivers/tty/serial/sh-sci.c

+ 5 - 15
drivers/tty/serial/sh-sci.c

@@ -1142,11 +1142,8 @@ static int sci_dma_rx_push(struct sci_port *s, void *buf, size_t count)
 	int copied;
 	int copied;
 
 
 	copied = tty_insert_flip_string(tport, buf, count);
 	copied = tty_insert_flip_string(tport, buf, count);
-	if (copied < count) {
-		dev_warn(port->dev, "Rx overrun: dropping %zu bytes\n",
-			 count - copied);
+	if (copied < count)
 		port->icount.buf_overrun++;
 		port->icount.buf_overrun++;
-	}
 
 
 	port->icount.rx += copied;
 	port->icount.rx += copied;
 
 
@@ -1161,8 +1158,6 @@ static int sci_dma_rx_find_active(struct sci_port *s)
 		if (s->active_rx == s->cookie_rx[i])
 		if (s->active_rx == s->cookie_rx[i])
 			return i;
 			return i;
 
 
-	dev_err(s->port.dev, "%s: Rx cookie %d not found!\n", __func__,
-		s->active_rx);
 	return -1;
 	return -1;
 }
 }
 
 
@@ -1223,9 +1218,9 @@ static void sci_dma_rx_complete(void *arg)
 
 
 	dma_async_issue_pending(chan);
 	dma_async_issue_pending(chan);
 
 
+	spin_unlock_irqrestore(&port->lock, flags);
 	dev_dbg(port->dev, "%s: cookie %d #%d, new active cookie %d\n",
 	dev_dbg(port->dev, "%s: cookie %d #%d, new active cookie %d\n",
 		__func__, s->cookie_rx[active], active, s->active_rx);
 		__func__, s->cookie_rx[active], active, s->active_rx);
-	spin_unlock_irqrestore(&port->lock, flags);
 	return;
 	return;
 
 
 fail:
 fail:
@@ -1273,8 +1268,6 @@ static void sci_submit_rx(struct sci_port *s)
 		if (dma_submit_error(s->cookie_rx[i]))
 		if (dma_submit_error(s->cookie_rx[i]))
 			goto fail;
 			goto fail;
 
 
-		dev_dbg(s->port.dev, "%s(): cookie %d to #%d\n", __func__,
-			s->cookie_rx[i], i);
 	}
 	}
 
 
 	s->active_rx = s->cookie_rx[0];
 	s->active_rx = s->cookie_rx[0];
@@ -1288,7 +1281,6 @@ fail:
 	for (i = 0; i < 2; i++)
 	for (i = 0; i < 2; i++)
 		s->cookie_rx[i] = -EINVAL;
 		s->cookie_rx[i] = -EINVAL;
 	s->active_rx = -EINVAL;
 	s->active_rx = -EINVAL;
-	dev_warn(s->port.dev, "Failed to re-start Rx DMA, using PIO\n");
 	sci_rx_dma_release(s, true);
 	sci_rx_dma_release(s, true);
 }
 }
 
 
@@ -1358,10 +1350,10 @@ static void rx_timer_fn(unsigned long arg)
 	int active, count;
 	int active, count;
 	u16 scr;
 	u16 scr;
 
 
-	spin_lock_irqsave(&port->lock, flags);
-
 	dev_dbg(port->dev, "DMA Rx timed out\n");
 	dev_dbg(port->dev, "DMA Rx timed out\n");
 
 
+	spin_lock_irqsave(&port->lock, flags);
+
 	active = sci_dma_rx_find_active(s);
 	active = sci_dma_rx_find_active(s);
 	if (active < 0) {
 	if (active < 0) {
 		spin_unlock_irqrestore(&port->lock, flags);
 		spin_unlock_irqrestore(&port->lock, flags);
@@ -1370,9 +1362,9 @@ static void rx_timer_fn(unsigned long arg)
 
 
 	status = dmaengine_tx_status(s->chan_rx, s->active_rx, &state);
 	status = dmaengine_tx_status(s->chan_rx, s->active_rx, &state);
 	if (status == DMA_COMPLETE) {
 	if (status == DMA_COMPLETE) {
+		spin_unlock_irqrestore(&port->lock, flags);
 		dev_dbg(port->dev, "Cookie %d #%d has already completed\n",
 		dev_dbg(port->dev, "Cookie %d #%d has already completed\n",
 			s->active_rx, active);
 			s->active_rx, active);
-		spin_unlock_irqrestore(&port->lock, flags);
 
 
 		/* Let packet complete handler take care of the packet */
 		/* Let packet complete handler take care of the packet */
 		return;
 		return;
@@ -1396,8 +1388,6 @@ static void rx_timer_fn(unsigned long arg)
 	/* Handle incomplete DMA receive */
 	/* Handle incomplete DMA receive */
 	dmaengine_terminate_all(s->chan_rx);
 	dmaengine_terminate_all(s->chan_rx);
 	read = sg_dma_len(&s->sg_rx[active]) - state.residue;
 	read = sg_dma_len(&s->sg_rx[active]) - state.residue;
-	dev_dbg(port->dev, "Read %u bytes with cookie %d\n", read,
-		s->active_rx);
 
 
 	if (read) {
 	if (read) {
 		count = sci_dma_rx_push(s, s->rx_buf[active], read);
 		count = sci_dma_rx_push(s, s->rx_buf[active], read);