All of lore.kernel.org
 help / color / mirror / Atom feed
From: fabrizio.castro@bp.renesas.com (Fabrizio Castro)
To: cip-dev@lists.cip-project.org
Subject: [cip-dev] [PATCH 4.19.y 19/60] serial: sh-sci: Fix TX DMA buffer flushing and workqueue races
Date: Wed, 28 Aug 2019 12:02:50 +0100	[thread overview]
Message-ID: <1566990211-24785-20-git-send-email-fabrizio.castro@bp.renesas.com> (raw)
In-Reply-To: <1566990211-24785-1-git-send-email-fabrizio.castro@bp.renesas.com>

From: Geert Uytterhoeven <geert+renesas@glider.be>

commit 8493eab02608b0e82f67b892aa72882e510c31d0 upstream.

When uart_flush_buffer() is called, the .flush_buffer() callback zeroes
the tx_dma_len field.  This may race with the work queue function
handling transmit DMA requests:

  1. If the buffer is flushed before the first DMA API call,
     dmaengine_prep_slave_single() may be called with a zero length,
     causing the DMA request to never complete, leading to messages
     like:

        rcar-dmac e7300000.dma-controller: Channel Address Error happen

     and, with debug enabled:

	sh-sci e6e88000.serial: sci_dma_tx_work_fn: ffff800639b55000: 0...0, cookie 126

     and DMA timeouts.

  2. If the buffer is flushed after the first DMA API call, but before
     the second, dma_sync_single_for_device() may be called with a zero
     length, causing the transmit data not to be flushed to RAM, and
     leading to stale data being output.

Fix this by:
  1. Letting sci_dma_tx_work_fn() return immediately if the transmit
     buffer is empty,
  2. Extending the critical section to cover all DMA preparational work,
     so tx_dma_len stays consistent for all of it,
  3. Using local copies of circ_buf.head and circ_buf.tail, to make sure
     they match the actual operation above.

Reported-by: Eugeniu Rosca <erosca@de.adit-jv.com>
Suggested-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Reviewed-by: Eugeniu Rosca <erosca@de.adit-jv.com>
Tested-by: Eugeniu Rosca <erosca@de.adit-jv.com>
Link: https://lore.kernel.org/r/20190624123540.20629-2-geert+renesas at glider.be
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Fabrizio Castro <fabrizio.castro@bp.renesas.com>
---
 drivers/tty/serial/sh-sci.c | 22 +++++++++++++++-------
 1 file changed, 15 insertions(+), 7 deletions(-)

diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 040832635..60f3672 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -1376,6 +1376,7 @@ static void work_fn_tx(struct work_struct *work)
 	struct circ_buf *xmit = &port->state->xmit;
 	unsigned long flags;
 	dma_addr_t buf;
+	int head, tail;
 
 	/*
 	 * DMA is idle now.
@@ -1385,16 +1386,23 @@ static void work_fn_tx(struct work_struct *work)
 	 * consistent xmit buffer state.
 	 */
 	spin_lock_irq(&port->lock);
-	buf = s->tx_dma_addr + (xmit->tail & (UART_XMIT_SIZE - 1));
+	head = xmit->head;
+	tail = xmit->tail;
+	buf = s->tx_dma_addr + (tail & (UART_XMIT_SIZE - 1));
 	s->tx_dma_len = min_t(unsigned int,
-		CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE),
-		CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE));
-	spin_unlock_irq(&port->lock);
+		CIRC_CNT(head, tail, UART_XMIT_SIZE),
+		CIRC_CNT_TO_END(head, tail, UART_XMIT_SIZE));
+	if (!s->tx_dma_len) {
+		/* Transmit buffer has been flushed */
+		spin_unlock_irq(&port->lock);
+		return;
+	}
 
 	desc = dmaengine_prep_slave_single(chan, buf, s->tx_dma_len,
 					   DMA_MEM_TO_DEV,
 					   DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 	if (!desc) {
+		spin_unlock_irq(&port->lock);
 		dev_warn(port->dev, "Failed preparing Tx DMA descriptor\n");
 		goto switch_to_pio;
 	}
@@ -1402,18 +1410,18 @@ static void work_fn_tx(struct work_struct *work)
 	dma_sync_single_for_device(chan->device->dev, buf, s->tx_dma_len,
 				   DMA_TO_DEVICE);
 
-	spin_lock_irq(&port->lock);
 	desc->callback = sci_dma_tx_complete;
 	desc->callback_param = s;
-	spin_unlock_irq(&port->lock);
 	s->cookie_tx = dmaengine_submit(desc);
 	if (dma_submit_error(s->cookie_tx)) {
+		spin_unlock_irq(&port->lock);
 		dev_warn(port->dev, "Failed submitting Tx DMA descriptor\n");
 		goto switch_to_pio;
 	}
 
+	spin_unlock_irq(&port->lock);
 	dev_dbg(port->dev, "%s: %p: %d...%d, cookie %d\n",
-		__func__, xmit->buf, xmit->tail, xmit->head, s->cookie_tx);
+		__func__, xmit->buf, tail, head, s->cookie_tx);
 
 	dma_async_issue_pending(chan);
 	return;
-- 
2.7.4

  parent reply	other threads:[~2019-08-28 11:02 UTC|newest]

Thread overview: 62+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-08-28 11:02 [cip-dev] [PATCH 4.19.y 00/60] Add basic RZ/G2M SoC support Fabrizio Castro
2019-08-28 11:02 ` [cip-dev] [PATCH 4.19.y 01/60] dt-bindings: can: rcar_can: Add r8a774a1 support Fabrizio Castro
2019-08-28 11:02 ` [cip-dev] [PATCH 4.19.y 02/60] dt-bindings: can: rcar_can: Fix RZ/G2 CAN clocks Fabrizio Castro
2019-08-28 11:02 ` [cip-dev] [PATCH 4.19.y 03/60] dt-bindings: can: rcar_can: Add r8a774c0 support Fabrizio Castro
2019-08-28 11:02 ` [cip-dev] [PATCH 4.19.y 04/60] dt-bindings: rcar-gen3-phy-usb3: Add r8a774a1 support Fabrizio Castro
2019-08-28 11:02 ` [cip-dev] [PATCH 4.19.y 05/60] dt-bindings: usb-xhci: " Fabrizio Castro
2019-08-28 11:02 ` [cip-dev] [PATCH 4.19.y 06/60] dt-bindings: usb-xhci: Add r8a774c0 support Fabrizio Castro
2019-08-28 11:02 ` [cip-dev] [PATCH 4.19.y 07/60] dt-bindings: usb: renesas_usbhs: Add r8a774a1 support Fabrizio Castro
2019-08-28 11:02 ` [cip-dev] [PATCH 4.19.y 08/60] dt-bindings: thermal: rcar-gen3-thermal: " Fabrizio Castro
2019-08-28 11:02 ` [cip-dev] [PATCH 4.19.y 09/60] dt-bindings: dmaengine: usb-dmac: Add binding for r8a774a1 Fabrizio Castro
2019-08-28 11:02 ` [cip-dev] [PATCH 4.19.y 10/60] thermal: rcar_gen3_thermal: Add r8a774a1 support Fabrizio Castro
2019-08-28 11:02 ` [cip-dev] [PATCH 4.19.y 11/60] gpio: rcar: reference device instead of platform device Fabrizio Castro
2019-08-28 11:02 ` [cip-dev] [PATCH 4.19.y 12/60] gpio: rcar: select General Output Register to set output states Fabrizio Castro
2019-08-28 11:02 ` [cip-dev] [PATCH 4.19.y 13/60] gpio: rcar: Pedantic formatting Fabrizio Castro
2019-08-28 11:02 ` [cip-dev] [PATCH 4.19.y 14/60] clk: renesas: cpg-mssr: Use genpd of_node instead of local copy Fabrizio Castro
2019-08-28 11:02 ` [cip-dev] [PATCH 4.19.y 15/60] clk: renesas: cpg-mssr: Remove error messages on out-of-memory conditions Fabrizio Castro
2019-08-28 11:02 ` [cip-dev] [PATCH 4.19.y 16/60] soc: renesas: rcar-sysc: Remove rcar_sysc_power_{down, up}() helpers Fabrizio Castro
2019-08-28 11:02 ` [cip-dev] [PATCH 4.19.y 17/60] soc: renesas: rcar-sysc: Merge PM Domain registration and linking Fabrizio Castro
2019-08-28 11:02 ` [cip-dev] [PATCH 4.19.y 18/60] soc: renesas: rcar-sysc: Fix power domain control after system resume Fabrizio Castro
2019-08-28 11:02 ` Fabrizio Castro [this message]
2019-08-28 11:02 ` [cip-dev] [PATCH 4.19.y 20/60] serial: sh-sci: Terminate TX DMA during buffer flushing Fabrizio Castro
2019-08-28 11:02 ` [cip-dev] [PATCH 4.19.y 21/60] serial: sh-sci: Fix crash in rx_timer_fn() on PIO fallback Fabrizio Castro
2019-08-28 11:02 ` [cip-dev] [PATCH 4.19.y 22/60] serial: sh-sci: Extract sci_dma_rx_chan_invalidate() Fabrizio Castro
2019-08-28 11:02 ` [cip-dev] [PATCH 4.19.y 23/60] serial: sh-sci: Extract sci_dma_rx_reenable_irq() Fabrizio Castro
2019-08-28 11:02 ` [cip-dev] [PATCH 4.19.y 24/60] serial: sh-sci: Fix fallback to PIO in sci_dma_rx_complete() Fabrizio Castro
2019-08-28 11:02 ` [cip-dev] [PATCH 4.19.y 25/60] dmaengine: rcar-dmac: set scatter/gather max segment size Fabrizio Castro
2019-08-28 11:02 ` [cip-dev] [PATCH 4.19.y 26/60] dmaengine: rcar-dmac: Update copyright information Fabrizio Castro
2019-08-28 11:02 ` [cip-dev] [PATCH 4.19.y 27/60] dmaengine: rcar-dmac: Reject zero-length slave DMA requests Fabrizio Castro
2019-08-28 11:02 ` [cip-dev] [PATCH 4.19.y 28/60] spi: sh-msiof: fix deferred probing Fabrizio Castro
2019-08-28 11:03 ` [cip-dev] [PATCH 4.19.y 29/60] ravb: remove tx buffer addr 4byte alilgnment restriction for R-Car Gen3 Fabrizio Castro
2019-08-28 11:03 ` [cip-dev] [PATCH 4.19.y 30/60] ravb: Avoid unsupported internal delay mode for R-Car E3/D3 Fabrizio Castro
2019-08-28 11:03 ` [cip-dev] [PATCH 4.19.y 31/60] mmc: renesas_sdhi_internal_dmac: set scatter/gather max segment size Fabrizio Castro
2019-08-28 11:03 ` [cip-dev] [PATCH 4.19.y 32/60] arm64: dts: renesas: Initial r8a774a1 SoC device tree Fabrizio Castro
2019-08-28 11:03 ` [cip-dev] [PATCH 4.19.y 33/60] arm64: dts: renesas: r8a774a1: Add SYS-DMAC controller nodes Fabrizio Castro
2019-08-28 11:03 ` [cip-dev] [PATCH 4.19.y 34/60] arm64: dts: renesas: r8a774a1: Add SCIF and HSCIF nodes Fabrizio Castro
2019-08-28 11:03 ` [cip-dev] [PATCH 4.19.y 35/60] arm64: dts: renesas: r8a774a1: Add INTC-EX device node Fabrizio Castro
2019-08-28 11:03 ` [cip-dev] [PATCH 4.19.y 36/60] arm64: dts: renesas: r8a774a1: Add Ethernet AVB node Fabrizio Castro
2019-08-28 11:03 ` [cip-dev] [PATCH 4.19.y 37/60] arm64: dts: renesas: r8a774a1: Add RWDT node Fabrizio Castro
2019-08-28 11:03 ` [cip-dev] [PATCH 4.19.y 38/60] arm64: dts: renesas: r8a774a1: Add pinctrl device node Fabrizio Castro
2019-08-28 11:03 ` [cip-dev] [PATCH 4.19.y 39/60] arm64: dts: renesas: r8a774a1: Add GPIO device nodes Fabrizio Castro
2019-08-28 11:03 ` [cip-dev] [PATCH 4.19.y 40/60] arm64: dts: renesas: r8a774a1: Add SDHI nodes Fabrizio Castro
2019-08-28 11:03 ` [cip-dev] [PATCH 4.19.y 41/60] arm64: dts: renesas: r8a774a1: Add I2C and IIC-DVFS support Fabrizio Castro
2019-08-28 11:03 ` [cip-dev] [PATCH 4.19.y 42/60] arm64: dts: renesas: r8a774a1: Add RZ/G2M thermal support Fabrizio Castro
2019-08-28 11:03 ` [cip-dev] [PATCH 4.19.y 43/60] arm64: dts: renesas: r8a774a1: Add IPMMU device nodes Fabrizio Castro
2019-08-28 11:03 ` [cip-dev] [PATCH 4.19.y 44/60] arm64: dts: renesas: r8a774a1: Add all MSIOF nodes Fabrizio Castro
2019-08-28 11:03 ` [cip-dev] [PATCH 4.19.y 45/60] arm64: dts: renesas: r8a774a1: Add Cortex-A53 CPU cores Fabrizio Castro
2019-08-28 11:03 ` [cip-dev] [PATCH 4.19.y 46/60] arm64: dts: renesas: r8a774a1: Add PWM device nodes Fabrizio Castro
2019-08-28 11:03 ` [cip-dev] [PATCH 4.19.y 47/60] arm64: dts: renesas: r8a774a1: Add audio support Fabrizio Castro
2019-08-28 11:03 ` [cip-dev] [PATCH 4.19.y 48/60] arm64: dts: renesas: r8a774a1: Add FCPF and FCPV instances Fabrizio Castro
2019-08-28 11:03 ` [cip-dev] [PATCH 4.19.y 49/60] arm64: dts: renesas: r8a774a1: Add USB2.0 phy and host(EHCI/OHCI) device nodes Fabrizio Castro
2019-08-28 11:03 ` [cip-dev] [PATCH 4.19.y 50/60] arm64: dts: renesas: r8a774a1: Add USB-DMAC and HSUSB " Fabrizio Castro
2019-08-28 11:03 ` [cip-dev] [PATCH 4.19.y 51/60] arm64: dts: renesas: r8a774a1: Add USB3.0 " Fabrizio Castro
2019-08-28 11:03 ` [cip-dev] [PATCH 4.19.y 52/60] arm64: dts: renesas: Fix whitespace around assignments Fabrizio Castro
2019-08-28 11:03 ` [cip-dev] [PATCH 4.19.y 53/60] arm64: dts: renesas: Remove unneeded status from thermal nodes Fabrizio Castro
2019-08-28 11:03 ` [cip-dev] [PATCH 4.19.y 54/60] arm64: dts: renesas: r8a774a1: Add CAN nodes Fabrizio Castro
2019-08-28 11:03 ` [cip-dev] [PATCH 4.19.y 55/60] arm64: dts: renesas: r8a774a1: Replace power magic numbers Fabrizio Castro
2019-08-28 11:03 ` [cip-dev] [PATCH 4.19.y 56/60] arm64: dts: renesas: r8a774a1: Replace clock " Fabrizio Castro
2019-08-28 11:03 ` [cip-dev] [PATCH 4.19.y 57/60] arm64: dts: renesas: r8a774a1: Enable DMA for SCIF2 Fabrizio Castro
2019-08-28 11:03 ` [cip-dev] [PATCH 4.19.y 58/60] arm64: dts: renesas: r8a774a1: Fix hsusb reg size Fabrizio Castro
2019-08-28 11:03 ` [cip-dev] [PATCH 4.19.y 59/60] arm64: dts: Remove inconsistent use of 'arm, armv8' compatible string Fabrizio Castro
2019-08-28 11:03 ` [cip-dev] [PATCH 4.19.y 60/60] arm64: dts: renesas: r8a774a1: Add clkp2 clock to CAN nodes Fabrizio Castro
2019-08-28 13:29 ` [cip-dev] [PATCH 4.19.y 00/60] Add basic RZ/G2M SoC support Fabrizio Castro

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=1566990211-24785-20-git-send-email-fabrizio.castro@bp.renesas.com \
    --to=fabrizio.castro@bp.renesas.com \
    --cc=cip-dev@lists.cip-project.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.