From bb68660943fc0dc2a5fa634243f3c6b7fb715626 Mon Sep 17 00:00:00 2001 From: Hideo Saito Date: Mon, 12 Mar 2007 14:50:49 +0900 Subject: sh: Fix PCI BAR address-space wraparound. When a SH7751R system includes a card that has wide range space like a graphics card, the pci-pci bridge controller can't set the correct address range. For example, when *lower_limit is 0xfd000000 and bar_size is 0x4000000, in the following code at arch/sh/drivers/pci/pci-auto.c, 0x0 is set in bar_value. pciauto_setup_bars() { ... bar_value = ((*lower_limit - 1) & ~(bar_size - 1)) + bar_size; ... *lower_limit = bar_value + bar_size; } As a result, 0x4000000 is set in *lower_limit, but this value is wrong. The following patch avoids this problem by checking the range of the value and refusing to update the BAR if the calculated value ends up being bogus. Signed-off-by: Hideo Saito Signed-off-by: Paul Mundt --- arch/sh/drivers/pci/pci-auto.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'arch') diff --git a/arch/sh/drivers/pci/pci-auto.c b/arch/sh/drivers/pci/pci-auto.c index ecf16344f94..224e007736f 100644 --- a/arch/sh/drivers/pci/pci-auto.c +++ b/arch/sh/drivers/pci/pci-auto.c @@ -214,6 +214,12 @@ retry: continue; } + if (bar_value < *lower_limit || (bar_value + bar_size) >= *upper_limit) { + DBG(" unavailable -- skipping, value %x size %x\n", + bar_value, bar_size); + continue; + } + #ifdef CONFIG_PCI_AUTO_UPDATE_RESOURCES /* Write it out and update our limit */ early_write_config_dword(hose, top_bus, current_bus, pci_devfn, -- cgit v1.2.3 From ffe1b4e9f436fd7bb784f3bf7ee963c149fbca5f Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 12 Mar 2007 16:15:22 +0900 Subject: sh: Fix SH-3 cache entry_mask and way_size calculation. The code for performing the calculation was only in the SH-4 probe path, move it out to the common path so the other parts get this right too. Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/init.c | 20 +++++++++++++++++--- arch/sh/kernel/cpu/sh4/probe.c | 13 ------------- 2 files changed, 17 insertions(+), 16 deletions(-) (limited to 'arch') diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c index 4b339a640b1..726acfcb9b7 100644 --- a/arch/sh/kernel/cpu/init.c +++ b/arch/sh/kernel/cpu/init.c @@ -3,7 +3,7 @@ * * CPU init code * - * Copyright (C) 2002 - 2006 Paul Mundt + * Copyright (C) 2002 - 2007 Paul Mundt * Copyright (C) 2003 Richard Curnow * * This file is subject to the terms and conditions of the GNU General Public @@ -48,8 +48,19 @@ static void __init cache_init(void) { unsigned long ccr, flags; - if (current_cpu_data.type == CPU_SH_NONE) - panic("Unknown CPU"); + /* First setup the rest of the I-cache info */ + current_cpu_data.icache.entry_mask = current_cpu_data.icache.way_incr - + current_cpu_data.icache.linesz; + + current_cpu_data.icache.way_size = current_cpu_data.icache.sets * + current_cpu_data.icache.linesz; + + /* And the D-cache too */ + current_cpu_data.dcache.entry_mask = current_cpu_data.dcache.way_incr - + current_cpu_data.dcache.linesz; + + current_cpu_data.dcache.way_size = current_cpu_data.dcache.sets * + current_cpu_data.dcache.linesz; jump_to_P2(); ccr = ctrl_inl(CCR); @@ -200,6 +211,9 @@ asmlinkage void __init sh_cpu_init(void) /* First, probe the CPU */ detect_cpu_and_cache_system(); + if (current_cpu_data.type == CPU_SH_NONE) + panic("Unknown CPU"); + /* Init the cache */ cache_init(); diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c index 9d28c88d2f9..58950de2696 100644 --- a/arch/sh/kernel/cpu/sh4/probe.c +++ b/arch/sh/kernel/cpu/sh4/probe.c @@ -195,13 +195,6 @@ int __init detect_cpu_and_cache_system(void) } - /* Setup the rest of the I-cache info */ - current_cpu_data.icache.entry_mask = current_cpu_data.icache.way_incr - - current_cpu_data.icache.linesz; - - current_cpu_data.icache.way_size = current_cpu_data.icache.sets * - current_cpu_data.icache.linesz; - /* And the rest of the D-cache */ if (current_cpu_data.dcache.ways > 1) { size = sizes[(cvr >> 16) & 0xf]; @@ -209,12 +202,6 @@ int __init detect_cpu_and_cache_system(void) current_cpu_data.dcache.sets = (size >> 6); } - current_cpu_data.dcache.entry_mask = current_cpu_data.dcache.way_incr - - current_cpu_data.dcache.linesz; - - current_cpu_data.dcache.way_size = current_cpu_data.dcache.sets * - current_cpu_data.dcache.linesz; - /* * Setup the L2 cache desc * -- cgit v1.2.3 From 3afb209a43a4216ad4f1411922d47a44252926c6 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 14 Mar 2007 13:03:35 +0900 Subject: sh: Fix bogus regs pointer in do_IRQ(). SH-3 and SH-4 were trampling the register, and SH-2 wasn't even setting it in the first place. This ended up with some rather broken behaviour in the sysrq show_regs(). Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh2/entry.S | 1 + arch/sh/kernel/cpu/sh3/entry.S | 5 ++++- arch/sh/kernel/irq.c | 15 ++------------- 3 files changed, 7 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/sh/kernel/cpu/sh2/entry.S b/arch/sh/kernel/cpu/sh2/entry.S index 7f7d292f36e..c16dc8fec48 100644 --- a/arch/sh/kernel/cpu/sh2/entry.S +++ b/arch/sh/kernel/cpu/sh2/entry.S @@ -165,6 +165,7 @@ ENTRY(exception_handler) interrupt_entry: mov r9,r4 + mov r15,r5 mov.l 6f,r9 mov.l 7f,r8 jmp @r8 diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S index c19205b0f2c..f3e827f29a4 100644 --- a/arch/sh/kernel/cpu/sh3/entry.S +++ b/arch/sh/kernel/cpu/sh3/entry.S @@ -514,13 +514,16 @@ skip_save: interrupt_exception: mov.l 1f, r9 + mov.l 2f, r4 + mov.l @r4, r4 jmp @r9 - nop + mov r15, r5 rts nop .align 2 1: .long do_IRQ +2: .long INTEVT .align 2 ENTRY(exception_none) diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c index 67be2b6e8cd..9bdd8a00cd4 100644 --- a/arch/sh/kernel/irq.c +++ b/arch/sh/kernel/irq.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -82,13 +81,9 @@ static union irq_ctx *hardirq_ctx[NR_CPUS] __read_mostly; static union irq_ctx *softirq_ctx[NR_CPUS] __read_mostly; #endif -asmlinkage int do_IRQ(unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, - struct pt_regs __regs) +asmlinkage int do_IRQ(unsigned int irq, struct pt_regs *regs) { - struct pt_regs *regs = RELOC_HIDE(&__regs, 0); struct pt_regs *old_regs = set_irq_regs(regs); - int irq; #ifdef CONFIG_4KSTACKS union irq_ctx *curctx, *irqctx; #endif @@ -111,13 +106,7 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5, } #endif -#ifdef CONFIG_CPU_HAS_INTEVT - irq = evt2irq(ctrl_inl(INTEVT)); -#else - irq = r4; -#endif - - irq = irq_demux(irq); + irq = irq_demux(evt2irq(irq)); #ifdef CONFIG_4KSTACKS curctx = (union irq_ctx *)current_thread_info(); -- cgit v1.2.3