Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6c1ead5e authored by Carlos Sanchez's avatar Carlos Sanchez Committed by Linus Torvalds
Browse files

serial: MPSC: Remove race between Rx stop & restart



The patch in commit ID f7232056 stops (aborts)
the MPSC's receive engine just before restarting it.  Unfortunately, it
doesn't wait for the abort to complete before restarting it which creates a
race between the abort and the restart.  If the restart occurs first, the
in-progress abort stops it again and the rx engine remains stopped.

Instead, do the abort when the SDMA engine is being stopped.  Make sure to
wait for the abort to complete before continuing.

Signed-off-by: default avatarCarlos Sanchez <carlos.sanchez@gecoinc.com>
Signed-off-by: default avatarMark A. Greer <mgreer@mvista.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 817794e0
Loading
Loading
Loading
Loading
+14 −2
Original line number Diff line number Diff line
@@ -1363,8 +1363,6 @@ mpsc_start_rx(struct mpsc_port_info *pi)
{
	pr_debug("mpsc_start_rx[%d]: Starting...\n", pi->port.line);

	/* Issue a Receive Abort to clear any receive errors */
	writel(MPSC_CHR_2_RA, pi->mpsc_base + MPSC_CHR_2);
	if (pi->rcv_data) {
		mpsc_enter_hunt(pi);
		mpsc_sdma_cmd(pi, SDMA_SDCM_ERD);
@@ -1379,6 +1377,20 @@ mpsc_stop_rx(struct uart_port *port)

	pr_debug("mpsc_stop_rx[%d]: Stopping...\n", port->line);

	if (pi->mirror_regs) {
		writel(pi->MPSC_CHR_2_m | MPSC_CHR_2_RA,
				pi->mpsc_base + MPSC_CHR_2);
		/* Erratum prevents reading CHR_2 so just delay for a while */
		udelay(100);
	}
	else {
		writel(readl(pi->mpsc_base + MPSC_CHR_2) | MPSC_CHR_2_RA,
			pi->mpsc_base + MPSC_CHR_2);

		while (readl(pi->mpsc_base + MPSC_CHR_2) & MPSC_CHR_2_RA)
			udelay(10);
	}

	mpsc_sdma_cmd(pi, SDMA_SDCM_AR);
	return;
}