From acca4f4d9bd657e8bc7e1665ba5077465138f133 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 10 Nov 2008 20:00:45 +0900 Subject: [PATCH 01/11] sh: Handle fixmap TLB eviction more coherently. There was a race in the kmap_coherent() implementation. While we guarded against preemption, there was nothing preventing eviction of the pre-faulted fixmap entry from the UTLB. Under certain workloads this would result in the fixmap entries used for cache colouring being evicted from the UTLB in the midst of a copy_page(). In addition to pre-faulting, we also make sure to preserve the PTEs in the kernel page table and introduce a cached PTE for kmap_coherent() usage. This follows a similar change on MIPS ("[MIPS] Fix aliasing bug in copy_to_user_page / copy_from_user_page"). Reported-by: Hideo Saito Reported-by: CHIKAMA Masaki Tested-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt --- arch/sh/include/asm/pgtable.h | 6 ++++++ arch/sh/mm/init.c | 12 +++++++++--- arch/sh/mm/pg-sh4.c | 17 +++++++++++++++++ 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/arch/sh/include/asm/pgtable.h b/arch/sh/include/asm/pgtable.h index 52220d70a096..b517ae08b9c0 100644 --- a/arch/sh/include/asm/pgtable.h +++ b/arch/sh/include/asm/pgtable.h @@ -148,6 +148,12 @@ extern void paging_init(void); extern void page_table_range_init(unsigned long start, unsigned long end, pgd_t *pgd); +#if !defined(CONFIG_CACHE_OFF) && defined(CONFIG_CPU_SH4) && defined(CONFIG_MMU) +extern void kmap_coherent_init(void); +#else +#define kmap_coherent_init() do { } while (0) +#endif + #include #endif /* __ASM_SH_PGTABLE_H */ diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c index 4abf00031dae..6cbef8caeb56 100644 --- a/arch/sh/mm/init.c +++ b/arch/sh/mm/init.c @@ -137,6 +137,7 @@ void __init page_table_range_init(unsigned long start, unsigned long end, void __init paging_init(void) { unsigned long max_zone_pfns[MAX_NR_ZONES]; + unsigned long vaddr; int nid; /* We don't need to map the kernel through the TLB, as @@ -148,10 +149,15 @@ void __init paging_init(void) * check for a null value. */ set_TTB(swapper_pg_dir); - /* Populate the relevant portions of swapper_pg_dir so that + /* + * Populate the relevant portions of swapper_pg_dir so that * we can use the fixmap entries without calling kmalloc. - * pte's will be filled in by __set_fixmap(). */ - page_table_range_init(FIXADDR_START, FIXADDR_TOP, swapper_pg_dir); + * pte's will be filled in by __set_fixmap(). + */ + vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK; + page_table_range_init(vaddr, 0, swapper_pg_dir); + + kmap_coherent_init(); memset(max_zone_pfns, 0, sizeof(max_zone_pfns)); diff --git a/arch/sh/mm/pg-sh4.c b/arch/sh/mm/pg-sh4.c index 38870e0fc182..2fe14da1f839 100644 --- a/arch/sh/mm/pg-sh4.c +++ b/arch/sh/mm/pg-sh4.c @@ -7,6 +7,7 @@ * Released under the terms of the GNU GPL v2.0. */ #include +#include #include #include #include @@ -16,6 +17,20 @@ #define CACHE_ALIAS (current_cpu_data.dcache.alias_mask) +#define kmap_get_fixmap_pte(vaddr) \ + pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)), (vaddr)) + +static pte_t *kmap_coherent_pte; + +void __init kmap_coherent_init(void) +{ + unsigned long vaddr; + + /* cache the first coherent kmap pte */ + vaddr = __fix_to_virt(FIX_CMAP_BEGIN); + kmap_coherent_pte = kmap_get_fixmap_pte(vaddr); +} + static inline void *kmap_coherent(struct page *page, unsigned long addr) { enum fixed_addresses idx; @@ -34,6 +49,8 @@ static inline void *kmap_coherent(struct page *page, unsigned long addr) update_mmu_cache(NULL, vaddr, pte); + set_pte(kmap_coherent_pte - (FIX_CMAP_END - idx), pte); + return (void *)vaddr; } From 1a22f08dbd0e77c7cf45b5f527f93131d0b591b6 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Tue, 11 Nov 2008 12:19:05 +0900 Subject: [PATCH 02/11] serial: sh-sci: fix cannot work SH7723 SCIFA SH7723 has SCIFA. This module is similer SCI register map, but it has FIFO. So this patch adds new type(PORT_SCIFA) and change some type checking. Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt --- drivers/serial/sh-sci.c | 20 +++++++++++--------- drivers/serial/sh-sci.h | 16 ++++++++-------- include/linux/serial_core.h | 3 +++ 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 5c0f32c7fbf6..518c0321e4d3 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -478,10 +478,10 @@ static void sci_transmit_chars(struct uart_port *port) return; } - if (port->type == PORT_SCIF) - count = scif_txroom(port); - else + if (port->type == PORT_SCI) count = sci_txroom(port); + else + count = scif_txroom(port); do { unsigned char c; @@ -510,7 +510,7 @@ static void sci_transmit_chars(struct uart_port *port) } else { ctrl = sci_in(port, SCSCR); - if (port->type == PORT_SCIF) { + if (port->type != PORT_SCI) { sci_in(port, SCxSR); /* Dummy read */ sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port)); } @@ -536,10 +536,10 @@ static inline void sci_receive_chars(struct uart_port *port) return; while (1) { - if (port->type == PORT_SCIF) - count = scif_rxroom(port); - else + if (port->type == PORT_SCI) count = sci_rxroom(port); + else + count = scif_rxroom(port); /* Don't copy more bytes than there is room for in the buffer */ count = tty_buffer_request_room(tty, count); @@ -714,7 +714,7 @@ static inline int sci_handle_breaks(struct uart_port *port) #if defined(SCIF_ORER) /* XXX: Handle SCIF overrun error */ - if (port->type == PORT_SCIF && (sci_in(port, SCLSR) & SCIF_ORER) != 0) { + if (port->type != PORT_SCI && (sci_in(port, SCLSR) & SCIF_ORER) != 0) { sci_out(port, SCLSR, 0); if (tty_insert_flip_char(tty, 0, TTY_OVERRUN)) { copied++; @@ -1042,7 +1042,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, sci_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */ - if (port->type == PORT_SCIF) + if (port->type != PORT_SCI) sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST); smr_val = sci_in(port, SCSMR) & 3; @@ -1085,6 +1085,7 @@ static const char *sci_type(struct uart_port *port) case PORT_SCI: return "sci"; case PORT_SCIF: return "scif"; case PORT_IRDA: return "irda"; + case PORT_SCIFA: return "scifa"; } return NULL; @@ -1112,6 +1113,7 @@ static void sci_config_port(struct uart_port *port, int flags) s->init_pins = sci_init_pins_sci; break; case PORT_SCIF: + case PORT_SCIFA: s->init_pins = sci_init_pins_scif; break; case PORT_IRDA: diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index 6163a45f968f..9f33b064172e 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h @@ -289,18 +289,18 @@ #define CPU_SCIx_FNS(name, sci_offset, sci_size, scif_offset, scif_size)\ static inline unsigned int sci_##name##_in(struct uart_port *port) \ { \ - if (port->type == PORT_SCI) { \ - SCI_IN(sci_size, sci_offset) \ - } else { \ - SCI_IN(scif_size, scif_offset); \ + if (port->type == PORT_SCIF) { \ + SCI_IN(scif_size, scif_offset) \ + } else { /* PORT_SCI or PORT_SCIFA */ \ + SCI_IN(sci_size, sci_offset); \ } \ } \ static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \ { \ - if (port->type == PORT_SCI) { \ - SCI_OUT(sci_size, sci_offset, value) \ - } else { \ - SCI_OUT(scif_size, scif_offset, value); \ + if (port->type == PORT_SCIF) { \ + SCI_OUT(scif_size, scif_offset, value) \ + } else { /* PORT_SCI or PORT_SCIFA */ \ + SCI_OUT(sci_size, sci_offset, value); \ } \ } diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index e27f216361fc..4e4f1277f3bf 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -155,6 +155,9 @@ #define PORT_SC26XX 82 +/* SH-SCI */ +#define PORT_SCIFA 83 + #ifdef __KERNEL__ #include From 51ee3d92bfb983790b9ed576c22f59d42adff329 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Tue, 11 Nov 2008 12:19:11 +0900 Subject: [PATCH 03/11] fix sci type for SH7723 This patch changes sci type of SH7723 from PORT_SCI to PORT_SCIFA. Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh4a/setup-sh7723.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c index a7412cede534..6d9e6972cfc9 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c @@ -119,17 +119,17 @@ static struct plat_sci_port sci_platform_data[] = { },{ .mapbase = 0xa4e30000, .flags = UPF_BOOT_AUTOCONF, - .type = PORT_SCI, + .type = PORT_SCIFA, .irqs = { 56, 56, 56, 56 }, },{ .mapbase = 0xa4e40000, .flags = UPF_BOOT_AUTOCONF, - .type = PORT_SCI, + .type = PORT_SCIFA, .irqs = { 88, 88, 88, 88 }, },{ .mapbase = 0xa4e50000, .flags = UPF_BOOT_AUTOCONF, - .type = PORT_SCI, + .type = PORT_SCIFA, .irqs = { 109, 109, 109, 109 }, }, { .flags = 0, From ade7a9b4ccd20ab8159c77a0abd20552f2d6b06c Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Tue, 11 Nov 2008 16:47:21 +0900 Subject: [PATCH 04/11] usb: r8a66597-hcd: fix wrong data access in SuperH on-chip USB When I used SuperH on-chip USB, there was the problem that accessed r8a66597_root_hub which was not allocated. Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt --- drivers/usb/host/r8a66597-hcd.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index c18d8790c410..2376f24f3c83 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -1763,11 +1763,12 @@ static void r8a66597_timer(unsigned long _r8a66597) { struct r8a66597 *r8a66597 = (struct r8a66597 *)_r8a66597; unsigned long flags; + int port; spin_lock_irqsave(&r8a66597->lock, flags); - r8a66597_root_hub_control(r8a66597, 0); - r8a66597_root_hub_control(r8a66597, 1); + for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) + r8a66597_root_hub_control(r8a66597, port); spin_unlock_irqrestore(&r8a66597->lock, flags); } From 185aed75570fb4f78ef283dfa26cd9da5fa06a91 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 12 Nov 2008 12:53:48 +0900 Subject: [PATCH 05/11] sh: Provide a sane valid_phys_addr_range() to prevent TLB reset with PMB. With the PMB enabled, only P1SEG and up are covered by the PMB mappings, meaning that situations where out-of-bounds physical addresses are read from will lead to TLB reset after the PMB miss, allowing for use cases like dd if=/dev/mem to reset the TLB. Fix this up to make sure the reference is between __MEMORY_START (phys) and __pa(high_memory). This is coherent across all variants of sh/sh64 with and without MMU, though the PMB bug itself is only applicable to SH-4A parts. Reported-by: Hideo Saito Signed-off-by: Paul Mundt --- arch/sh/include/asm/io.h | 4 ++++ arch/sh/mm/Makefile_32 | 2 +- arch/sh/mm/Makefile_64 | 2 +- arch/sh/mm/mmap.c | 31 +++++++++++++++++++++++++++++++ 4 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 arch/sh/mm/mmap.c diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h index 436c28539577..65eaae34e753 100644 --- a/arch/sh/include/asm/io.h +++ b/arch/sh/include/asm/io.h @@ -293,6 +293,10 @@ __ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags) */ #define xlate_dev_kmem_ptr(p) p +#define ARCH_HAS_VALID_PHYS_ADDR_RANGE +int valid_phys_addr_range(unsigned long addr, size_t size); +int valid_mmap_phys_addr_range(unsigned long pfn, size_t size); + #endif /* __KERNEL__ */ #endif /* __ASM_SH_IO_H */ diff --git a/arch/sh/mm/Makefile_32 b/arch/sh/mm/Makefile_32 index 70e0906023cc..f066e76da204 100644 --- a/arch/sh/mm/Makefile_32 +++ b/arch/sh/mm/Makefile_32 @@ -2,7 +2,7 @@ # Makefile for the Linux SuperH-specific parts of the memory manager. # -obj-y := init.o extable_32.o consistent.o +obj-y := init.o extable_32.o consistent.o mmap.o ifndef CONFIG_CACHE_OFF cache-$(CONFIG_CPU_SH2) := cache-sh2.o diff --git a/arch/sh/mm/Makefile_64 b/arch/sh/mm/Makefile_64 index 0d92a8a3ac9a..9481d0f54efd 100644 --- a/arch/sh/mm/Makefile_64 +++ b/arch/sh/mm/Makefile_64 @@ -2,7 +2,7 @@ # Makefile for the Linux SuperH-specific parts of the memory manager. # -obj-y := init.o consistent.o +obj-y := init.o consistent.o mmap.o mmu-y := tlb-nommu.o pg-nommu.o extable_32.o mmu-$(CONFIG_MMU) := fault_64.o ioremap_64.o tlbflush_64.o tlb-sh5.o \ diff --git a/arch/sh/mm/mmap.c b/arch/sh/mm/mmap.c new file mode 100644 index 000000000000..1f3cc3d92d3d --- /dev/null +++ b/arch/sh/mm/mmap.c @@ -0,0 +1,31 @@ +/* + * arch/sh/mm/mmap.c + * + * Copyright (C) 2008 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include + +/* + * You really shouldn't be using read() or write() on /dev/mem. This + * might go away in the future. + */ +int valid_phys_addr_range(unsigned long addr, size_t count) +{ + if (addr < (PAGE_OFFSET + (PFN_START << PAGE_SHIFT))) + return 0; + if (addr + count > __pa(high_memory)) + return 0; + + return 1; +} + +int valid_mmap_phys_addr_range(unsigned long pfn, size_t size) +{ + return 1; +} From bff4056c8b868a4311d5ebd6cbbf09a2c10f4551 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 13 Nov 2008 15:28:21 +0900 Subject: [PATCH 06/11] i2c: fix i2c-sh_mobile rx underrun Fix receive path underrun in i2c-sh_mobile driver. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/i2c/busses/i2c-sh_mobile.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index 640cbb237328..3384a717fec0 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -318,7 +318,8 @@ static int sh_mobile_i2c_isr_rx(struct sh_mobile_i2c_data *pd) } else data = i2c_op(pd, OP_RX, 0); - pd->msg->buf[real_pos] = data; + if (real_pos >= 0) + pd->msg->buf[real_pos] = data; } while (0); pd->pos++; From bfbedf787c6b77270679429caadb044b2d33c94c Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 13 Nov 2008 15:33:45 +0900 Subject: [PATCH 07/11] sh: early printk port type fix Add PORT_SCIF to unbreak the early printk code. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/kernel/early_printk.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/sh/kernel/early_printk.c b/arch/sh/kernel/early_printk.c index 6b7d166694e2..98a29a782301 100644 --- a/arch/sh/kernel/early_printk.c +++ b/arch/sh/kernel/early_printk.c @@ -75,6 +75,7 @@ static struct console bios_console = { #endif static struct uart_port scif_port = { + .type = PORT_SCIF, .mapbase = CONFIG_EARLY_SCIF_CONSOLE_PORT, .membase = (char __iomem *)CONFIG_EARLY_SCIF_CONSOLE_PORT, }; From 10840f034e2329150ce0e683e636ea13b268d333 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 13 Nov 2008 15:38:02 +0900 Subject: [PATCH 08/11] sh: Don't factor in PAGE_OFFSET for valid_phys_addr_range() check. Signed-off-by: Paul Mundt --- arch/sh/mm/mmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sh/mm/mmap.c b/arch/sh/mm/mmap.c index 1f3cc3d92d3d..8837d511710a 100644 --- a/arch/sh/mm/mmap.c +++ b/arch/sh/mm/mmap.c @@ -17,7 +17,7 @@ */ int valid_phys_addr_range(unsigned long addr, size_t count) { - if (addr < (PAGE_OFFSET + (PFN_START << PAGE_SHIFT))) + if (addr < __MEMORY_START) return 0; if (addr + count > __pa(high_memory)) return 0; From 2cd0ebc83d771220eeddec91fd6d4cfefc2cc46e Mon Sep 17 00:00:00 2001 From: Francesco VIRLINZI Date: Wed, 15 Oct 2008 11:58:24 +0200 Subject: [PATCH 09/11] sh: Fixed the TMU0 reload value on resume This patch fixes the TMU0 interrupt frequency on suspend/resume. During the resume the kernel reprograms the TMU0.ClockEvent mode but if the mode is periodic than the TMU0.TCOR is updated with a random wrong value without taking care latest valid saved value. There was no problem with No_HZ system where TMU0.TCOR isn't used. Signed-off-by: Francesco M. Virlinzi Signed-off-by: Stuart Menefy Signed-off-by: Paul Mundt --- arch/sh/kernel/timers/timer-tmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sh/kernel/timers/timer-tmu.c b/arch/sh/kernel/timers/timer-tmu.c index aaaf90d06b85..3c61ddd4d43e 100644 --- a/arch/sh/kernel/timers/timer-tmu.c +++ b/arch/sh/kernel/timers/timer-tmu.c @@ -120,7 +120,7 @@ static void tmu_set_mode(enum clock_event_mode mode, { switch (mode) { case CLOCK_EVT_MODE_PERIODIC: - ctrl_outl(ctrl_inl(TMU0_TCNT), TMU0_TCOR); + ctrl_outl(tmu_latest_interval[TMU0], TMU0_TCOR); break; case CLOCK_EVT_MODE_ONESHOT: ctrl_outl(0, TMU0_TCOR); From 5d52013cbb3d39bde9f5a6023193058eeb112e98 Mon Sep 17 00:00:00 2001 From: Stuart MENEFY Date: Fri, 10 Oct 2008 19:49:30 +0100 Subject: [PATCH 10/11] sh: __copy_user function can corrupt the stack in case of exception The __copy_user function can corrupt the stack in the case of a non-trivial length of data, and either of the first two move instructions cause an exception. This is because the fixup for these two instructions is mapped to the no_pop case, but these instructions execute after the stack is pushed. This change creates an explicit NO_POP exception mapping macro, and uses it for the two instructions executed in the trivial case where no stack pushes occur. More information at ST Linux bugzilla: https://bugzilla.stlinux.com/show_bug.cgi?id=4824 Signed-off-by: Dylan Reid Signed-off-by: Stuart Menefy Signed-off-by: Paul Mundt --- arch/sh/lib/copy_page.S | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/arch/sh/lib/copy_page.S b/arch/sh/lib/copy_page.S index 5d12e657be34..43de7e8e4e17 100644 --- a/arch/sh/lib/copy_page.S +++ b/arch/sh/lib/copy_page.S @@ -80,6 +80,11 @@ ENTRY(copy_page) .section __ex_table, "a"; \ .long 9999b, 6000f ; \ .previous +#define EX_NO_POP(...) \ + 9999: __VA_ARGS__ ; \ + .section __ex_table, "a"; \ + .long 9999b, 6005f ; \ + .previous ENTRY(__copy_user) ! Check if small number of bytes mov #11,r0 @@ -139,9 +144,9 @@ EX( mov.b r1,@r4 ) bt 1f 2: -EX( mov.b @r5+,r0 ) +EX_NO_POP( mov.b @r5+,r0 ) dt r6 -EX( mov.b r0,@r4 ) +EX_NO_POP( mov.b r0,@r4 ) bf/s 2b add #1,r4 @@ -150,7 +155,7 @@ EX( mov.b r0,@r4 ) # Exception handler: .section .fixup, "ax" -6000: +6005: mov.l 8000f,r1 mov r3,r0 jmp @r1 From 272966c070237c8cb540fe67e06df51bc6ea9cc2 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 13 Nov 2008 17:46:06 +0900 Subject: [PATCH 11/11] 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 Signed-off-by: Paul Mundt --- arch/sh/kernel/early_printk.c | 2 +- drivers/serial/sh-sci.c | 2 +- 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) while (((sci_in(&scif_port, SCFDR) & EPK_FIFO_BITS) >= EPK_FIFO_SIZE)) ; - sci_out(&scif_port, SCxTDR, c); sci_in(&scif_port, SCxSR); sci_out(&scif_port, SCxSR, 0xf3 & ~(0x20 | 0x40)); + sci_out(&scif_port, SCxTDR, c); while ((sci_in(&scif_port, SCxSR) & 0x40) == 0) ; 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) status = sci_in(port, SCxSR); } while (!(status & SCxSR_TDxE(port))); - sci_out(port, SCxTDR, c); sci_in(port, SCxSR); /* Dummy read */ sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port)); + sci_out(port, SCxTDR, c); spin_unlock_irqrestore(&port->lock, flags); }