summaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2010-03-01 04:23:06 +0100
committerDavid S. Miller <davem@davemloft.net>2010-03-01 04:23:06 +0100
commit47871889c601d8199c51a4086f77eebd77c29b0b (patch)
tree40cdcac3bff0ee40cc33dcca61d0577cdf965f77 /arch/mips/kernel
parentbnx2x: Tx barriers and locks (diff)
parentMerge branch 'x86-uv-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/... (diff)
downloadlinux-47871889c601d8199c51a4086f77eebd77c29b0b.tar.xz
linux-47871889c601d8199c51a4086f77eebd77c29b0b.zip
Merge branch 'master' of /home/davem/src/GIT/linux-2.6/
Conflicts: drivers/firmware/iscsi_ibft.c
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r--arch/mips/kernel/Makefile1
-rw-r--r--arch/mips/kernel/asm-offsets.c4
-rw-r--r--arch/mips/kernel/cevt-gt641xx.c10
-rw-r--r--arch/mips/kernel/cpu-probe.c30
-rw-r--r--arch/mips/kernel/ftrace.c2
-rw-r--r--arch/mips/kernel/i8259.c22
-rw-r--r--arch/mips/kernel/irq-gt641xx.c18
-rw-r--r--arch/mips/kernel/linux32.c1
-rw-r--r--arch/mips/kernel/mcount.S2
-rw-r--r--arch/mips/kernel/octeon_switch.S1
-rw-r--r--arch/mips/kernel/rtlx.c1
-rw-r--r--arch/mips/kernel/spinlock_test.c141
-rw-r--r--arch/mips/kernel/traps.c23
-rw-r--r--arch/mips/kernel/vpe.c1
14 files changed, 212 insertions, 45 deletions
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 9326af5186fe..ef20957ca14b 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -93,6 +93,7 @@ obj-$(CONFIG_GPIO_TXX9) += gpio_txx9.o
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+obj-$(CONFIG_SPINLOCK_TEST) += spinlock_test.o
CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(KBUILD_CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi)
diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
index 2c1e1d02338b..ca6c83218caa 100644
--- a/arch/mips/kernel/asm-offsets.c
+++ b/arch/mips/kernel/asm-offsets.c
@@ -188,11 +188,15 @@ void output_mm_defines(void)
DEFINE(_PTE_T_SIZE, sizeof(pte_t));
BLANK();
DEFINE(_PGD_T_LOG2, PGD_T_LOG2);
+#ifndef __PAGETABLE_PMD_FOLDED
DEFINE(_PMD_T_LOG2, PMD_T_LOG2);
+#endif
DEFINE(_PTE_T_LOG2, PTE_T_LOG2);
BLANK();
DEFINE(_PGD_ORDER, PGD_ORDER);
+#ifndef __PAGETABLE_PMD_FOLDED
DEFINE(_PMD_ORDER, PMD_ORDER);
+#endif
DEFINE(_PTE_ORDER, PTE_ORDER);
BLANK();
DEFINE(_PMD_SHIFT, PMD_SHIFT);
diff --git a/arch/mips/kernel/cevt-gt641xx.c b/arch/mips/kernel/cevt-gt641xx.c
index f5d265eb6eae..392ef3756c56 100644
--- a/arch/mips/kernel/cevt-gt641xx.c
+++ b/arch/mips/kernel/cevt-gt641xx.c
@@ -25,7 +25,7 @@
#include <asm/gt64120.h>
#include <asm/time.h>
-static DEFINE_SPINLOCK(gt641xx_timer_lock);
+static DEFINE_RAW_SPINLOCK(gt641xx_timer_lock);
static unsigned int gt641xx_base_clock;
void gt641xx_set_base_clock(unsigned int clock)
@@ -49,7 +49,7 @@ static int gt641xx_timer0_set_next_event(unsigned long delta,
{
u32 ctrl;
- spin_lock(&gt641xx_timer_lock);
+ raw_spin_lock(&gt641xx_timer_lock);
ctrl = GT_READ(GT_TC_CONTROL_OFS);
ctrl &= ~(GT_TC_CONTROL_ENTC0_MSK | GT_TC_CONTROL_SELTC0_MSK);
@@ -58,7 +58,7 @@ static int gt641xx_timer0_set_next_event(unsigned long delta,
GT_WRITE(GT_TC0_OFS, delta);
GT_WRITE(GT_TC_CONTROL_OFS, ctrl);
- spin_unlock(&gt641xx_timer_lock);
+ raw_spin_unlock(&gt641xx_timer_lock);
return 0;
}
@@ -68,7 +68,7 @@ static void gt641xx_timer0_set_mode(enum clock_event_mode mode,
{
u32 ctrl;
- spin_lock(&gt641xx_timer_lock);
+ raw_spin_lock(&gt641xx_timer_lock);
ctrl = GT_READ(GT_TC_CONTROL_OFS);
ctrl &= ~(GT_TC_CONTROL_ENTC0_MSK | GT_TC_CONTROL_SELTC0_MSK);
@@ -86,7 +86,7 @@ static void gt641xx_timer0_set_mode(enum clock_event_mode mode,
GT_WRITE(GT_TC_CONTROL_OFS, ctrl);
- spin_unlock(&gt641xx_timer_lock);
+ raw_spin_unlock(&gt641xx_timer_lock);
}
static void gt641xx_timer0_event_handler(struct clock_event_device *dev)
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 758ad426c57f..be5bb16be4e0 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -162,6 +162,7 @@ void __init check_wait(void)
case CPU_BCM6348:
case CPU_BCM6358:
case CPU_CAVIUM_OCTEON:
+ case CPU_CAVIUM_OCTEON_PLUS:
cpu_wait = r4k_wait;
break;
@@ -700,6 +701,19 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c)
return config3 & MIPS_CONF_M;
}
+static inline unsigned int decode_config4(struct cpuinfo_mips *c)
+{
+ unsigned int config4;
+
+ config4 = read_c0_config4();
+
+ if ((config4 & MIPS_CONF4_MMUEXTDEF) == MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT
+ && cpu_has_tlb)
+ c->tlbsize += (config4 & MIPS_CONF4_MMUSIZEEXT) * 0x40;
+
+ return config4 & MIPS_CONF_M;
+}
+
static void __cpuinit decode_configs(struct cpuinfo_mips *c)
{
int ok;
@@ -718,6 +732,8 @@ static void __cpuinit decode_configs(struct cpuinfo_mips *c)
ok = decode_config2(c);
if (ok)
ok = decode_config3(c);
+ if (ok)
+ ok = decode_config4(c);
mips_probe_watch_registers(c);
}
@@ -731,9 +747,6 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
__cpu_name[cpu] = "MIPS 4Kc";
break;
case PRID_IMP_4KEC:
- c->cputype = CPU_4KEC;
- __cpu_name[cpu] = "MIPS 4KEc";
- break;
case PRID_IMP_4KECR2:
c->cputype = CPU_4KEC;
__cpu_name[cpu] = "MIPS 4KEc";
@@ -899,12 +912,18 @@ static inline void cpu_probe_cavium(struct cpuinfo_mips *c, unsigned int cpu)
case PRID_IMP_CAVIUM_CN38XX:
case PRID_IMP_CAVIUM_CN31XX:
case PRID_IMP_CAVIUM_CN30XX:
+ c->cputype = CPU_CAVIUM_OCTEON;
+ __cpu_name[cpu] = "Cavium Octeon";
+ goto platform;
case PRID_IMP_CAVIUM_CN58XX:
case PRID_IMP_CAVIUM_CN56XX:
case PRID_IMP_CAVIUM_CN50XX:
case PRID_IMP_CAVIUM_CN52XX:
- c->cputype = CPU_CAVIUM_OCTEON;
- __cpu_name[cpu] = "Cavium Octeon";
+ c->cputype = CPU_CAVIUM_OCTEON_PLUS;
+ __cpu_name[cpu] = "Cavium Octeon+";
+platform:
+ if (cpu == 0)
+ __elf_platform = "octeon";
break;
default:
printk(KERN_INFO "Unknown Octeon chip!\n");
@@ -914,6 +933,7 @@ static inline void cpu_probe_cavium(struct cpuinfo_mips *c, unsigned int cpu)
}
const char *__cpu_name[NR_CPUS];
+const char *__elf_platform;
__cpuinit void cpu_probe(void)
{
diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c
index 68b067040d8b..e9e64e0ff7aa 100644
--- a/arch/mips/kernel/ftrace.c
+++ b/arch/mips/kernel/ftrace.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com>
* Copyright (C) 2009 DSLab, Lanzhou University, China
- * Author: Wu Zhangjin <wuzj@lemote.com>
+ * Author: Wu Zhangjin <wuzhangjin@gmail.com>
*
* Thanks goes to Steven Rostedt for writing the original x86 version.
*/
diff --git a/arch/mips/kernel/i8259.c b/arch/mips/kernel/i8259.c
index 01c0885a8061..27799113332c 100644
--- a/arch/mips/kernel/i8259.c
+++ b/arch/mips/kernel/i8259.c
@@ -29,7 +29,7 @@
*/
static int i8259A_auto_eoi = -1;
-DEFINE_SPINLOCK(i8259A_lock);
+DEFINE_RAW_SPINLOCK(i8259A_lock);
static void disable_8259A_irq(unsigned int irq);
static void enable_8259A_irq(unsigned int irq);
static void mask_and_ack_8259A(unsigned int irq);
@@ -65,13 +65,13 @@ static void disable_8259A_irq(unsigned int irq)
irq -= I8259A_IRQ_BASE;
mask = 1 << irq;
- spin_lock_irqsave(&i8259A_lock, flags);
+ raw_spin_lock_irqsave(&i8259A_lock, flags);
cached_irq_mask |= mask;
if (irq & 8)
outb(cached_slave_mask, PIC_SLAVE_IMR);
else
outb(cached_master_mask, PIC_MASTER_IMR);
- spin_unlock_irqrestore(&i8259A_lock, flags);
+ raw_spin_unlock_irqrestore(&i8259A_lock, flags);
}
static void enable_8259A_irq(unsigned int irq)
@@ -81,13 +81,13 @@ static void enable_8259A_irq(unsigned int irq)
irq -= I8259A_IRQ_BASE;
mask = ~(1 << irq);
- spin_lock_irqsave(&i8259A_lock, flags);
+ raw_spin_lock_irqsave(&i8259A_lock, flags);
cached_irq_mask &= mask;
if (irq & 8)
outb(cached_slave_mask, PIC_SLAVE_IMR);
else
outb(cached_master_mask, PIC_MASTER_IMR);
- spin_unlock_irqrestore(&i8259A_lock, flags);
+ raw_spin_unlock_irqrestore(&i8259A_lock, flags);
}
int i8259A_irq_pending(unsigned int irq)
@@ -98,12 +98,12 @@ int i8259A_irq_pending(unsigned int irq)
irq -= I8259A_IRQ_BASE;
mask = 1 << irq;
- spin_lock_irqsave(&i8259A_lock, flags);
+ raw_spin_lock_irqsave(&i8259A_lock, flags);
if (irq < 8)
ret = inb(PIC_MASTER_CMD) & mask;
else
ret = inb(PIC_SLAVE_CMD) & (mask >> 8);
- spin_unlock_irqrestore(&i8259A_lock, flags);
+ raw_spin_unlock_irqrestore(&i8259A_lock, flags);
return ret;
}
@@ -151,7 +151,7 @@ static void mask_and_ack_8259A(unsigned int irq)
irq -= I8259A_IRQ_BASE;
irqmask = 1 << irq;
- spin_lock_irqsave(&i8259A_lock, flags);
+ raw_spin_lock_irqsave(&i8259A_lock, flags);
/*
* Lightweight spurious IRQ detection. We do not want
* to overdo spurious IRQ handling - it's usually a sign
@@ -183,7 +183,7 @@ handle_real_irq:
outb(0x60+irq, PIC_MASTER_CMD); /* 'Specific EOI to master */
}
smtc_im_ack_irq(irq);
- spin_unlock_irqrestore(&i8259A_lock, flags);
+ raw_spin_unlock_irqrestore(&i8259A_lock, flags);
return;
spurious_8259A_irq:
@@ -264,7 +264,7 @@ static void init_8259A(int auto_eoi)
i8259A_auto_eoi = auto_eoi;
- spin_lock_irqsave(&i8259A_lock, flags);
+ raw_spin_lock_irqsave(&i8259A_lock, flags);
outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */
outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-2 */
@@ -298,7 +298,7 @@ static void init_8259A(int auto_eoi)
outb(cached_master_mask, PIC_MASTER_IMR); /* restore master IRQ mask */
outb(cached_slave_mask, PIC_SLAVE_IMR); /* restore slave IRQ mask */
- spin_unlock_irqrestore(&i8259A_lock, flags);
+ raw_spin_unlock_irqrestore(&i8259A_lock, flags);
}
/*
diff --git a/arch/mips/kernel/irq-gt641xx.c b/arch/mips/kernel/irq-gt641xx.c
index ebcc5f7ad9c2..42ef81461bfc 100644
--- a/arch/mips/kernel/irq-gt641xx.c
+++ b/arch/mips/kernel/irq-gt641xx.c
@@ -27,18 +27,18 @@
#define GT641XX_IRQ_TO_BIT(irq) (1U << (irq - GT641XX_IRQ_BASE))
-static DEFINE_SPINLOCK(gt641xx_irq_lock);
+static DEFINE_RAW_SPINLOCK(gt641xx_irq_lock);
static void ack_gt641xx_irq(unsigned int irq)
{
unsigned long flags;
u32 cause;
- spin_lock_irqsave(&gt641xx_irq_lock, flags);
+ raw_spin_lock_irqsave(&gt641xx_irq_lock, flags);
cause = GT_READ(GT_INTRCAUSE_OFS);
cause &= ~GT641XX_IRQ_TO_BIT(irq);
GT_WRITE(GT_INTRCAUSE_OFS, cause);
- spin_unlock_irqrestore(&gt641xx_irq_lock, flags);
+ raw_spin_unlock_irqrestore(&gt641xx_irq_lock, flags);
}
static void mask_gt641xx_irq(unsigned int irq)
@@ -46,11 +46,11 @@ static void mask_gt641xx_irq(unsigned int irq)
unsigned long flags;
u32 mask;
- spin_lock_irqsave(&gt641xx_irq_lock, flags);
+ raw_spin_lock_irqsave(&gt641xx_irq_lock, flags);
mask = GT_READ(GT_INTRMASK_OFS);
mask &= ~GT641XX_IRQ_TO_BIT(irq);
GT_WRITE(GT_INTRMASK_OFS, mask);
- spin_unlock_irqrestore(&gt641xx_irq_lock, flags);
+ raw_spin_unlock_irqrestore(&gt641xx_irq_lock, flags);
}
static void mask_ack_gt641xx_irq(unsigned int irq)
@@ -58,7 +58,7 @@ static void mask_ack_gt641xx_irq(unsigned int irq)
unsigned long flags;
u32 cause, mask;
- spin_lock_irqsave(&gt641xx_irq_lock, flags);
+ raw_spin_lock_irqsave(&gt641xx_irq_lock, flags);
mask = GT_READ(GT_INTRMASK_OFS);
mask &= ~GT641XX_IRQ_TO_BIT(irq);
GT_WRITE(GT_INTRMASK_OFS, mask);
@@ -66,7 +66,7 @@ static void mask_ack_gt641xx_irq(unsigned int irq)
cause = GT_READ(GT_INTRCAUSE_OFS);
cause &= ~GT641XX_IRQ_TO_BIT(irq);
GT_WRITE(GT_INTRCAUSE_OFS, cause);
- spin_unlock_irqrestore(&gt641xx_irq_lock, flags);
+ raw_spin_unlock_irqrestore(&gt641xx_irq_lock, flags);
}
static void unmask_gt641xx_irq(unsigned int irq)
@@ -74,11 +74,11 @@ static void unmask_gt641xx_irq(unsigned int irq)
unsigned long flags;
u32 mask;
- spin_lock_irqsave(&gt641xx_irq_lock, flags);
+ raw_spin_lock_irqsave(&gt641xx_irq_lock, flags);
mask = GT_READ(GT_INTRMASK_OFS);
mask |= GT641XX_IRQ_TO_BIT(irq);
GT_WRITE(GT_INTRMASK_OFS, mask);
- spin_unlock_irqrestore(&gt641xx_irq_lock, flags);
+ raw_spin_unlock_irqrestore(&gt641xx_irq_lock, flags);
}
static struct irq_chip gt641xx_irq_chip = {
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index f042563c924f..bde79ef602e6 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -9,7 +9,6 @@
#include <linux/mm.h>
#include <linux/errno.h>
#include <linux/file.h>
-#include <linux/smp_lock.h>
#include <linux/highuid.h>
#include <linux/resource.h>
#include <linux/highmem.h>
diff --git a/arch/mips/kernel/mcount.S b/arch/mips/kernel/mcount.S
index 0a9cfdb271dd..6851fc97a511 100644
--- a/arch/mips/kernel/mcount.S
+++ b/arch/mips/kernel/mcount.S
@@ -6,7 +6,7 @@
* more details.
*
* Copyright (C) 2009 Lemote Inc. & DSLab, Lanzhou University, China
- * Author: Wu Zhangjin <wuzj@lemote.com>
+ * Author: Wu Zhangjin <wuzhangjin@gmail.com>
*/
#include <asm/regdef.h>
diff --git a/arch/mips/kernel/octeon_switch.S b/arch/mips/kernel/octeon_switch.S
index 3952b8323efa..dd18b26a358a 100644
--- a/arch/mips/kernel/octeon_switch.S
+++ b/arch/mips/kernel/octeon_switch.S
@@ -500,4 +500,3 @@ done_restore:
nop
END(octeon_mult_restore)
.set pop
-
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c
index 364f066cb497..dcaed1bbbfe5 100644
--- a/arch/mips/kernel/rtlx.c
+++ b/arch/mips/kernel/rtlx.c
@@ -28,7 +28,6 @@
#include <linux/vmalloc.h>
#include <linux/elf.h>
#include <linux/seq_file.h>
-#include <linux/smp_lock.h>
#include <linux/syscalls.h>
#include <linux/moduleloader.h>
#include <linux/interrupt.h>
diff --git a/arch/mips/kernel/spinlock_test.c b/arch/mips/kernel/spinlock_test.c
new file mode 100644
index 000000000000..da61134dfc53
--- /dev/null
+++ b/arch/mips/kernel/spinlock_test.c
@@ -0,0 +1,141 @@
+#include <linux/init.h>
+#include <linux/kthread.h>
+#include <linux/hrtimer.h>
+#include <linux/fs.h>
+#include <linux/debugfs.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+
+
+static int ss_get(void *data, u64 *val)
+{
+ ktime_t start, finish;
+ int loops;
+ int cont;
+ DEFINE_RAW_SPINLOCK(ss_spin);
+
+ loops = 1000000;
+ cont = 1;
+
+ start = ktime_get();
+
+ while (cont) {
+ raw_spin_lock(&ss_spin);
+ loops--;
+ if (loops == 0)
+ cont = 0;
+ raw_spin_unlock(&ss_spin);
+ }
+
+ finish = ktime_get();
+
+ *val = ktime_us_delta(finish, start);
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(fops_ss, ss_get, NULL, "%llu\n");
+
+
+
+struct spin_multi_state {
+ raw_spinlock_t lock;
+ atomic_t start_wait;
+ atomic_t enter_wait;
+ atomic_t exit_wait;
+ int loops;
+};
+
+struct spin_multi_per_thread {
+ struct spin_multi_state *state;
+ ktime_t start;
+};
+
+static int multi_other(void *data)
+{
+ int loops;
+ int cont;
+ struct spin_multi_per_thread *pt = data;
+ struct spin_multi_state *s = pt->state;
+
+ loops = s->loops;
+ cont = 1;
+
+ atomic_dec(&s->enter_wait);
+
+ while (atomic_read(&s->enter_wait))
+ ; /* spin */
+
+ pt->start = ktime_get();
+
+ atomic_dec(&s->start_wait);
+
+ while (atomic_read(&s->start_wait))
+ ; /* spin */
+
+ while (cont) {
+ raw_spin_lock(&s->lock);
+ loops--;
+ if (loops == 0)
+ cont = 0;
+ raw_spin_unlock(&s->lock);
+ }
+
+ atomic_dec(&s->exit_wait);
+ while (atomic_read(&s->exit_wait))
+ ; /* spin */
+ return 0;
+}
+
+static int multi_get(void *data, u64 *val)
+{
+ ktime_t finish;
+ struct spin_multi_state ms;
+ struct spin_multi_per_thread t1, t2;
+
+ ms.lock = __RAW_SPIN_LOCK_UNLOCKED("multi_get");
+ ms.loops = 1000000;
+
+ atomic_set(&ms.start_wait, 2);
+ atomic_set(&ms.enter_wait, 2);
+ atomic_set(&ms.exit_wait, 2);
+ t1.state = &ms;
+ t2.state = &ms;
+
+ kthread_run(multi_other, &t2, "multi_get");
+
+ multi_other(&t1);
+
+ finish = ktime_get();
+
+ *val = ktime_us_delta(finish, t1.start);
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(fops_multi, multi_get, NULL, "%llu\n");
+
+
+extern struct dentry *mips_debugfs_dir;
+static int __init spinlock_test(void)
+{
+ struct dentry *d;
+
+ if (!mips_debugfs_dir)
+ return -ENODEV;
+
+ d = debugfs_create_file("spin_single", S_IRUGO,
+ mips_debugfs_dir, NULL,
+ &fops_ss);
+ if (!d)
+ return -ENOMEM;
+
+ d = debugfs_create_file("spin_multi", S_IRUGO,
+ mips_debugfs_dir, NULL,
+ &fops_multi);
+ if (!d)
+ return -ENOMEM;
+
+ return 0;
+}
+device_initcall(spinlock_test);
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 31b204b26ba0..4e00f9bc23ee 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -50,6 +50,7 @@
#include <asm/types.h>
#include <asm/stacktrace.h>
#include <asm/irq.h>
+#include <asm/uasm.h>
extern void check_wait(void);
extern asmlinkage void r4k_wait(void);
@@ -1271,21 +1272,25 @@ unsigned long ebase;
unsigned long exception_handlers[32];
unsigned long vi_handlers[64];
-/*
- * As a side effect of the way this is implemented we're limited
- * to interrupt handlers in the address range from
- * KSEG0 <= x < KSEG0 + 256mb on the Nevada. Oh well ...
- */
-void *set_except_vector(int n, void *addr)
+void __init *set_except_vector(int n, void *addr)
{
unsigned long handler = (unsigned long) addr;
unsigned long old_handler = exception_handlers[n];
exception_handlers[n] = handler;
if (n == 0 && cpu_has_divec) {
- *(u32 *)(ebase + 0x200) = 0x08000000 |
- (0x03ffffff & (handler >> 2));
- local_flush_icache_range(ebase + 0x200, ebase + 0x204);
+ unsigned long jump_mask = ~((1 << 28) - 1);
+ u32 *buf = (u32 *)(ebase + 0x200);
+ unsigned int k0 = 26;
+ if ((handler & jump_mask) == ((ebase + 0x200) & jump_mask)) {
+ uasm_i_j(&buf, handler & ~jump_mask);
+ uasm_i_nop(&buf);
+ } else {
+ UASM_i_LA(&buf, k0, handler);
+ uasm_i_jr(&buf, k0);
+ uasm_i_nop(&buf);
+ }
+ local_flush_icache_range(ebase + 0x200, (unsigned long)buf);
}
return (void *)old_handler;
}
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
index 60477529362e..2bd2151c586a 100644
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -38,7 +38,6 @@
#include <linux/vmalloc.h>
#include <linux/elf.h>
#include <linux/seq_file.h>
-#include <linux/smp_lock.h>
#include <linux/syscalls.h>
#include <linux/moduleloader.h>
#include <linux/interrupt.h>