aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2008-11-13 03:46:06 -0500
committerPaul Mundt <lethal@linux-sh.org>2008-11-13 03:46:06 -0500
commit272966c070237c8cb540fe67e06df51bc6ea9cc2 (patch)
tree2937aa90cd6c972b13f0173f60e76c186111ffaf
parent5d52013cbb3d39bde9f5a6023193058eeb112e98 (diff)
serial: sh-sci: Reorder the SCxTDR write after the TDxE clear.
Under qemu there is a race between the TDxE read-and-clear and the SCxTDR write. While on hardware it can be gauranteed that the read-and-clear will happen prior to the character being written out, no such assumption can be made under emulation. As this path happens with IRQs off and the hardware itself doesn't care about the ordering, move the SCxTDR write until after the read-and-clear. Signed-off-by: Vladimir Prus <vladimir@codesourcery.com> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-rw-r--r--arch/sh/kernel/early_printk.c2
-rw-r--r--drivers/serial/sh-sci.c2
2 files changed, 2 insertions, 2 deletions
diff --git a/arch/sh/kernel/early_printk.c b/arch/sh/kernel/early_printk.c
index 98a29a782301..a952dcf9999d 100644
--- a/arch/sh/kernel/early_printk.c
+++ b/arch/sh/kernel/early_printk.c
@@ -85,9 +85,9 @@ static void scif_sercon_putc(int c)
85 while (((sci_in(&scif_port, SCFDR) & EPK_FIFO_BITS) >= EPK_FIFO_SIZE)) 85 while (((sci_in(&scif_port, SCFDR) & EPK_FIFO_BITS) >= EPK_FIFO_SIZE))
86 ; 86 ;
87 87
88 sci_out(&scif_port, SCxTDR, c);
89 sci_in(&scif_port, SCxSR); 88 sci_in(&scif_port, SCxSR);
90 sci_out(&scif_port, SCxSR, 0xf3 & ~(0x20 | 0x40)); 89 sci_out(&scif_port, SCxSR, 0xf3 & ~(0x20 | 0x40));
90 sci_out(&scif_port, SCxTDR, c);
91 91
92 while ((sci_in(&scif_port, SCxSR) & 0x40) == 0) 92 while ((sci_in(&scif_port, SCxSR) & 0x40) == 0)
93 ; 93 ;
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
index 518c0321e4d3..165fc010978c 100644
--- a/drivers/serial/sh-sci.c
+++ b/drivers/serial/sh-sci.c
@@ -144,9 +144,9 @@ static void put_char(struct uart_port *port, char c)
144 status = sci_in(port, SCxSR); 144 status = sci_in(port, SCxSR);
145 } while (!(status & SCxSR_TDxE(port))); 145 } while (!(status & SCxSR_TDxE(port)));
146 146
147 sci_out(port, SCxTDR, c);
148 sci_in(port, SCxSR); /* Dummy read */ 147 sci_in(port, SCxSR); /* Dummy read */
149 sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port)); 148 sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port));
149 sci_out(port, SCxTDR, c);
150 150
151 spin_unlock_irqrestore(&port->lock, flags); 151 spin_unlock_irqrestore(&port->lock, flags);
152} 152}