From c98c406eb2c518c7c5bc922fafa1f9fdcb7b76f4 Mon Sep 17 00:00:00 2001
From: David Howells <dhowells@redhat.com>
Date: Wed, 12 Dec 2012 15:36:37 +0000
Subject: [PATCH] MN10300: ttySM: Use memory barriers correctly in circular
 buffer logic

Use memory barriers correctly in the circular buffer logic used in the driver,
as documented in Documentation/circular-buffers.txt.

Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Mark Salter <msalter@redhat.com>
---
 arch/mn10300/kernel/mn10300-serial.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/arch/mn10300/kernel/mn10300-serial.c b/arch/mn10300/kernel/mn10300-serial.c
index 339cef4c8256..131b81f9d6c8 100644
--- a/arch/mn10300/kernel/mn10300-serial.c
+++ b/arch/mn10300/kernel/mn10300-serial.c
@@ -487,16 +487,17 @@ static void mn10300_serial_receive_interrupt(struct mn10300_serial_port *port)
 
 try_again:
 	/* pull chars out of the hat */
-	ix = port->rx_outp;
-	if (ix == port->rx_inp) {
+	ix = ACCESS_ONCE(port->rx_outp);
+	if (CIRC_CNT(port->rx_inp, ix, MNSC_BUFFER_SIZE) == 0) {
 		if (push && !tty->low_latency)
 			tty_flip_buffer_push(tty);
 		return;
 	}
 
+	smp_read_barrier_depends();
 	ch = port->rx_buffer[ix++];
 	st = port->rx_buffer[ix++];
-	smp_rmb();
+	smp_mb();
 	port->rx_outp = ix & (MNSC_BUFFER_SIZE - 1);
 	port->uart.icount.rx++;
 
@@ -1657,13 +1658,14 @@ static int mn10300_serial_poll_get_char(struct uart_port *_port)
 
 	do {
 		/* pull chars out of the hat */
-		ix = port->rx_outp;
-		if (ix == port->rx_inp)
+		ix = ACCESS_ONCE(port->rx_outp);
+		if (CIRC_CNT(port->rx_inp, ix, MNSC_BUFFER_SIZE) == 0)
 			return NO_POLL_CHAR;
 
+		smp_read_barrier_depends();
 		ch = port->rx_buffer[ix++];
 		st = port->rx_buffer[ix++];
-		smp_rmb();
+		smp_mb();
 		port->rx_outp = ix & (MNSC_BUFFER_SIZE - 1);
 
 	} while (st & (SC01STR_FEF | SC01STR_PEF | SC01STR_OEF));
-- 
2.30.2