summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-07-06 17:14:33 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2010-07-06 17:14:33 -0700
commit7491eb9b5f39dbd9faa32a07d76597ab502166a1 (patch)
tree972d05969c3989f553ce72860ef39c42265b1ed0 /arch
parent7263e715c91f3de554ab7d4f20f56e080783d0f5 (diff)
parent55dc9d51a89ba10a1f7b3ed15f1262eb83e87e74 (diff)
Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
* 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus: (22 commits) MIPS: Return after handling coprocessor 2 exception MIPS: BCM47xx: Add NVRAM support devices MIPS: Loongson: Define rtc device on MC146818-equipped systems MIPS: MT: Fix FPU affinity. MIPS: Oprofile: Fixup of loongson2_exit() MIPS: Alchemy: sleepcode without compile-time cputype dependencies MIPS: Tracing: Cleanup of address space checking MIPS: Tracing: Cleanup of function graph tracer MIPS: Tracing: Reduce the overhead of dynamic Function Tracer MIPS: Tracing: Cleanup of instructions used MIPS: Tracing: Fix 32-bit support with -mmcount-ra-address MIPS: Tracing: Fix argument passing of the 32bit support with gcc 4.5 MIPS: Tracing: Cleanup comments MIPS: Tracing: Cleanup the arguments passing of prepare_ftrace_return MIPS: Tracing: Merge adjacent #ifdefs with same condition. MIPS: AR7, BCM63xx: fix gpio_to_irq() return value MIPS: Restore signalling NaN behaviour for abs.[sd] MIPS: Loongson: CS5536: Fix ISA support MIPS: Loongson: Add a missing break statement in CS5536 IDE code MIPS: Loongson: CS5536: Add missing RDMSRs for IDE and USB ...
Diffstat (limited to 'arch')
-rw-r--r--arch/mips/alchemy/common/power.c12
-rw-r--r--arch/mips/alchemy/common/sleeper.S81
-rw-r--r--arch/mips/ar7/platform.c2
-rw-r--r--arch/mips/bcm47xx/Makefile2
-rw-r--r--arch/mips/bcm47xx/nvram.c94
-rw-r--r--arch/mips/bcm47xx/setup.c39
-rw-r--r--arch/mips/include/asm/mach-ar7/ar7.h6
-rw-r--r--arch/mips/include/asm/mach-ar7/gpio.h2
-rw-r--r--arch/mips/include/asm/mach-au1x00/au1000.h3
-rw-r--r--arch/mips/include/asm/mach-bcm47xx/nvram.h36
-rw-r--r--arch/mips/include/asm/mach-bcm63xx/gpio.h2
-rw-r--r--arch/mips/kernel/ftrace.c184
-rw-r--r--arch/mips/kernel/mcount.S55
-rw-r--r--arch/mips/kernel/mips-mt-fpaff.c87
-rw-r--r--arch/mips/kernel/traps.c2
-rw-r--r--arch/mips/loongson/Kconfig6
-rw-r--r--arch/mips/loongson/common/Makefile1
-rw-r--r--arch/mips/loongson/common/cs5536/cs5536_ehci.c2
-rw-r--r--arch/mips/loongson/common/cs5536/cs5536_ide.c15
-rw-r--r--arch/mips/loongson/common/cs5536/cs5536_isa.c4
-rw-r--r--arch/mips/loongson/common/cs5536/cs5536_ohci.c2
-rw-r--r--arch/mips/loongson/common/rtc.c43
-rw-r--r--arch/mips/math-emu/dp_simple.c1
-rw-r--r--arch/mips/math-emu/sp_simple.c1
-rw-r--r--arch/mips/oprofile/op_model_loongson2.c8
25 files changed, 515 insertions, 175 deletions
diff --git a/arch/mips/alchemy/common/power.c b/arch/mips/alchemy/common/power.c
index 14eb8c492da..5ef06a164a8 100644
--- a/arch/mips/alchemy/common/power.c
+++ b/arch/mips/alchemy/common/power.c
@@ -193,9 +193,15 @@ static void restore_core_regs(void)
void au_sleep(void)
{
- save_core_regs();
- au1xxx_save_and_sleep();
- restore_core_regs();
+ int cpuid = alchemy_get_cputype();
+ if (cpuid != ALCHEMY_CPU_UNKNOWN) {
+ save_core_regs();
+ if (cpuid <= ALCHEMY_CPU_AU1500)
+ alchemy_sleep_au1000();
+ else if (cpuid <= ALCHEMY_CPU_AU1200)
+ alchemy_sleep_au1550();
+ restore_core_regs();
+ }
}
#endif /* CONFIG_PM */
diff --git a/arch/mips/alchemy/common/sleeper.S b/arch/mips/alchemy/common/sleeper.S
index 4f4b16741d1..77f3c743b71 100644
--- a/arch/mips/alchemy/common/sleeper.S
+++ b/arch/mips/alchemy/common/sleeper.S
@@ -22,10 +22,9 @@
.set noat
.align 5
-/* Save all of the processor general registers and go to sleep.
- * A wakeup condition will get us back here to restore the registers.
- */
-LEAF(au1xxx_save_and_sleep)
+
+/* preparatory stuff */
+.macro SETUP_SLEEP
subu sp, PT_SIZE
sw $1, PT_R1(sp)
sw $2, PT_R2(sp)
@@ -69,12 +68,32 @@ LEAF(au1xxx_save_and_sleep)
*/
lui t3, 0xb190 /* sys_xxx */
sw sp, 0x0018(t3)
- la k0, 3f /* resume path */
+ la k0, alchemy_sleep_wakeup /* resume path */
sw k0, 0x001c(t3)
+.endm
- /* Put SDRAM into self refresh: Preload instructions into cache,
- * issue a precharge, auto/self refresh, then sleep commands to it.
- */
+.macro DO_SLEEP
+ /* put power supply and processor to sleep */
+ sw zero, 0x0078(t3) /* sys_slppwr */
+ sync
+ sw zero, 0x007c(t3) /* sys_sleep */
+ sync
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+.endm
+
+/* sleep code for Au1000/Au1100/Au1500 memory controller type */
+LEAF(alchemy_sleep_au1000)
+
+ SETUP_SLEEP
+
+ /* cache following instructions, as memory gets put to sleep */
la t0, 1f
.set mips3
cache 0x14, 0(t0)
@@ -84,17 +103,32 @@ LEAF(au1xxx_save_and_sleep)
.set mips0
1: lui a0, 0xb400 /* mem_xxx */
-#if defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1100) || \
- defined(CONFIG_SOC_AU1500)
sw zero, 0x001c(a0) /* Precharge */
sync
sw zero, 0x0020(a0) /* Auto Refresh */
sync
sw zero, 0x0030(a0) /* Sleep */
sync
-#endif
-#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
+ DO_SLEEP
+
+END(alchemy_sleep_au1000)
+
+/* sleep code for Au1550/Au1200 memory controller type */
+LEAF(alchemy_sleep_au1550)
+
+ SETUP_SLEEP
+
+ /* cache following instructions, as memory gets put to sleep */
+ la t0, 1f
+ .set mips3
+ cache 0x14, 0(t0)
+ cache 0x14, 32(t0)
+ cache 0x14, 64(t0)
+ cache 0x14, 96(t0)
+ .set mips0
+
+1: lui a0, 0xb400 /* mem_xxx */
sw zero, 0x08c0(a0) /* Precharge */
sync
sw zero, 0x08d0(a0) /* Self Refresh */
@@ -114,26 +148,17 @@ LEAF(au1xxx_save_and_sleep)
and t1, t0, t1 /* clear CE[1:0] */
sw t1, 0x0840(a0) /* mem_sdconfiga */
sync
-#endif
- /* put power supply and processor to sleep */
- sw zero, 0x0078(t3) /* sys_slppwr */
- sync
- sw zero, 0x007c(t3) /* sys_sleep */
- sync
- nop
- nop
- nop
- nop
- nop
- nop
- nop
- nop
+ DO_SLEEP
+
+END(alchemy_sleep_au1550)
+
/* This is where we return upon wakeup.
* Reload all of the registers and return.
*/
-3: lw k0, 0x20(sp)
+LEAF(alchemy_sleep_wakeup)
+ lw k0, 0x20(sp)
mtc0 k0, CP0_STATUS
lw k0, 0x1c(sp)
mtc0 k0, CP0_CONTEXT
@@ -169,4 +194,4 @@ LEAF(au1xxx_save_and_sleep)
lw $31, PT_R31(sp)
jr ra
addiu sp, PT_SIZE
-END(au1xxx_save_and_sleep)
+END(alchemy_sleep_wakeup)
diff --git a/arch/mips/ar7/platform.c b/arch/mips/ar7/platform.c
index 566f2d7f2ea..8f31d1d5968 100644
--- a/arch/mips/ar7/platform.c
+++ b/arch/mips/ar7/platform.c
@@ -542,7 +542,7 @@ static int __init ar7_register_uarts(void)
if (IS_ERR(bus_clk))
panic("unable to get bus clk\n");
- uart_port.type = PORT_16550A;
+ uart_port.type = PORT_AR7;
uart_port.uartclk = clk_get_rate(bus_clk) / 2;
uart_port.iotype = UPIO_MEM32;
uart_port.regshift = 2;
diff --git a/arch/mips/bcm47xx/Makefile b/arch/mips/bcm47xx/Makefile
index 35294b12d63..7465e8a72d9 100644
--- a/arch/mips/bcm47xx/Makefile
+++ b/arch/mips/bcm47xx/Makefile
@@ -3,4 +3,4 @@
# under Linux.
#
-obj-y := gpio.o irq.o prom.o serial.o setup.o time.o wgt634u.o
+obj-y := gpio.o irq.o nvram.o prom.o serial.o setup.o time.o wgt634u.o
diff --git a/arch/mips/bcm47xx/nvram.c b/arch/mips/bcm47xx/nvram.c
new file mode 100644
index 00000000000..06e03b222f6
--- /dev/null
+++ b/arch/mips/bcm47xx/nvram.c
@@ -0,0 +1,94 @@
+/*
+ * BCM947xx nvram variable access
+ *
+ * Copyright (C) 2005 Broadcom Corporation
+ * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/ssb/ssb.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <asm/addrspace.h>
+#include <asm/mach-bcm47xx/nvram.h>
+#include <asm/mach-bcm47xx/bcm47xx.h>
+
+static char nvram_buf[NVRAM_SPACE];
+
+/* Probe for NVRAM header */
+static void __init early_nvram_init(void)
+{
+ struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore;
+ struct nvram_header *header;
+ int i;
+ u32 base, lim, off;
+ u32 *src, *dst;
+
+ base = mcore->flash_window;
+ lim = mcore->flash_window_size;
+
+ off = FLASH_MIN;
+ while (off <= lim) {
+ /* Windowed flash access */
+ header = (struct nvram_header *)
+ KSEG1ADDR(base + off - NVRAM_SPACE);
+ if (header->magic == NVRAM_HEADER)
+ goto found;
+ off <<= 1;
+ }
+
+ /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */
+ header = (struct nvram_header *) KSEG1ADDR(base + 4096);
+ if (header->magic == NVRAM_HEADER)
+ goto found;
+
+ header = (struct nvram_header *) KSEG1ADDR(base + 1024);
+ if (header->magic == NVRAM_HEADER)
+ goto found;
+
+ return;
+
+found:
+ src = (u32 *) header;
+ dst = (u32 *) nvram_buf;
+ for (i = 0; i < sizeof(struct nvram_header); i += 4)
+ *dst++ = *src++;
+ for (; i < header->len && i < NVRAM_SPACE; i += 4)
+ *dst++ = le32_to_cpu(*src++);
+}
+
+int nvram_getenv(char *name, char *val, size_t val_len)
+{
+ char *var, *value, *end, *eq;
+
+ if (!name)
+ return 1;
+
+ if (!nvram_buf[0])
+ early_nvram_init();
+
+ /* Look for name=value and return value */
+ var = &nvram_buf[sizeof(struct nvram_header)];
+ end = nvram_buf + sizeof(nvram_buf) - 2;
+ end[0] = end[1] = '\0';
+ for (; *var; var = value + strlen(value) + 1) {
+ eq = strchr(var, '=');
+ if (!eq)
+ break;
+ value = eq + 1;
+ if ((eq - var) == strlen(name) &&
+ strncmp(var, name, (eq - var)) == 0) {
+ snprintf(val, val_len, "%s", value);
+ return 0;
+ }
+ }
+ return 1;
+}
+EXPORT_SYMBOL(nvram_getenv);
diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c
index d442e11625f..b1aee33efd1 100644
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
@@ -1,8 +1,8 @@
/*
* Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
- * Copyright (C) 2005 Waldemar Brodkorb <wbx@openwrt.org>
* Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
* Copyright (C) 2006 Michael Buesch <mb@bu3sch.de>
+ * Copyright (C) 2010 Waldemar Brodkorb <wbx@openadk.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -33,6 +33,7 @@
#include <asm/time.h>
#include <bcm47xx.h>
#include <asm/fw/cfe/cfe_api.h>
+#include <asm/mach-bcm47xx/nvram.h>
struct ssb_bus ssb_bcm47xx;
EXPORT_SYMBOL(ssb_bcm47xx);
@@ -81,28 +82,42 @@ static int bcm47xx_get_invariants(struct ssb_bus *bus,
/* Fill boardinfo structure */
memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo));
- if (cfe_getenv("boardvendor", buf, sizeof(buf)) >= 0)
+ if (cfe_getenv("boardvendor", buf, sizeof(buf)) >= 0 ||
+ nvram_getenv("boardvendor", buf, sizeof(buf)) >= 0)
iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
- if (cfe_getenv("boardtype", buf, sizeof(buf)) >= 0)
+ if (cfe_getenv("boardtype", buf, sizeof(buf)) >= 0 ||
+ nvram_getenv("boardtype", buf, sizeof(buf)) >= 0)
iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
- if (cfe_getenv("boardrev", buf, sizeof(buf)) >= 0)
+ if (cfe_getenv("boardrev", buf, sizeof(buf)) >= 0 ||
+ nvram_getenv("boardrev", buf, sizeof(buf)) >= 0)
iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0);
/* Fill sprom structure */
memset(&(iv->sprom), 0, sizeof(struct ssb_sprom));
iv->sprom.revision = 3;
- if (cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0)
+ if (cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0 ||
+ nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0)
str2eaddr(buf, iv->sprom.et0mac);
- if (cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0)
+
+ if (cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0 ||
+ nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0)
str2eaddr(buf, iv->sprom.et1mac);
- if (cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0)
- iv->sprom.et0phyaddr = simple_strtoul(buf, NULL, 10);
- if (cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0)
- iv->sprom.et1phyaddr = simple_strtoul(buf, NULL, 10);
- if (cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0)
+
+ if (cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0 ||
+ nvram_getenv("et0phyaddr", buf, sizeof(buf)) >= 0)
+ iv->sprom.et0phyaddr = simple_strtoul(buf, NULL, 0);
+
+ if (cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0 ||
+ nvram_getenv("et1phyaddr", buf, sizeof(buf)) >= 0)
+ iv->sprom.et1phyaddr = simple_strtoul(buf, NULL, 0);
+
+ if (cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0 ||
+ nvram_getenv("et0mdcport", buf, sizeof(buf)) >= 0)
iv->sprom.et0mdcport = simple_strtoul(buf, NULL, 10);
- if (cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0)
+
+ if (cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0 ||
+ nvram_getenv("et1mdcport", buf, sizeof(buf)) >= 0)
iv->sprom.et1mdcport = simple_strtoul(buf, NULL, 10);
return 0;
diff --git a/arch/mips/include/asm/mach-ar7/ar7.h b/arch/mips/include/asm/mach-ar7/ar7.h
index f1cf3894349..483ffea9ecb 100644
--- a/arch/mips/include/asm/mach-ar7/ar7.h
+++ b/arch/mips/include/asm/mach-ar7/ar7.h
@@ -50,7 +50,7 @@
#define UR8_REGS_WDT (AR7_REGS_BASE + 0x0b00)
#define UR8_REGS_UART1 (AR7_REGS_BASE + 0x0f00)
-#define AR7_RESET_PEREPHERIAL 0x0
+#define AR7_RESET_PERIPHERAL 0x0
#define AR7_RESET_SOFTWARE 0x4
#define AR7_RESET_STATUS 0x8
@@ -128,7 +128,7 @@ static inline int ar7_has_high_cpmac(void)
static inline void ar7_device_enable(u32 bit)
{
void *reset_reg =
- (void *)KSEG1ADDR(AR7_REGS_RESET + AR7_RESET_PEREPHERIAL);
+ (void *)KSEG1ADDR(AR7_REGS_RESET + AR7_RESET_PERIPHERAL);
writel(readl(reset_reg) | (1 << bit), reset_reg);
msleep(20);
}
@@ -136,7 +136,7 @@ static inline void ar7_device_enable(u32 bit)
static inline void ar7_device_disable(u32 bit)
{
void *reset_reg =
- (void *)KSEG1ADDR(AR7_REGS_RESET + AR7_RESET_PEREPHERIAL);
+ (void *)KSEG1ADDR(AR7_REGS_RESET + AR7_RESET_PERIPHERAL);
writel(readl(reset_reg) & ~(1 << bit), reset_reg);
msleep(20);
}
diff --git a/arch/mips/include/asm/mach-ar7/gpio.h b/arch/mips/include/asm/mach-ar7/gpio.h
index 73f9b162c97..abc317c0372 100644
--- a/arch/mips/include/asm/mach-ar7/gpio.h
+++ b/arch/mips/include/asm/mach-ar7/gpio.h
@@ -24,7 +24,7 @@
#define AR7_GPIO_MAX 32
#define NR_BUILTIN_GPIO AR7_GPIO_MAX
-#define gpio_to_irq(gpio) NULL
+#define gpio_to_irq(gpio) -1
#define gpio_get_value __gpio_get_value
#define gpio_set_value __gpio_set_value
diff --git a/arch/mips/include/asm/mach-au1x00/au1000.h b/arch/mips/include/asm/mach-au1x00/au1000.h
index e76941db231..a6976619160 100644
--- a/arch/mips/include/asm/mach-au1x00/au1000.h
+++ b/arch/mips/include/asm/mach-au1x00/au1000.h
@@ -188,7 +188,8 @@ extern unsigned long get_au1x00_uart_baud_base(void);
extern unsigned long au1xxx_calc_clock(void);
/* PM: arch/mips/alchemy/common/sleeper.S, power.c, irq.c */
-void au1xxx_save_and_sleep(void);
+void alchemy_sleep_au1000(void);
+void alchemy_sleep_au1550(void);
void au_sleep(void);
diff --git a/arch/mips/include/asm/mach-bcm47xx/nvram.h b/arch/mips/include/asm/mach-bcm47xx/nvram.h
new file mode 100644
index 00000000000..0d8cc146f7a
--- /dev/null
+++ b/arch/mips/include/asm/mach-bcm47xx/nvram.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2005, Broadcom Corporation
+ * Copyright (C) 2006, Felix Fietkau <nbd@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __NVRAM_H
+#define __NVRAM_H
+
+#include <linux/types.h>
+
+struct nvram_header {
+ u32 magic;
+ u32 len;
+ u32 crc_ver_init; /* 0:7 crc, 8:15 ver, 16:31 sdram_init */
+ u32 config_refresh; /* 0:15 sdram_config, 16:31 sdram_refresh */
+ u32 config_ncdl; /* ncdl values for memc */
+};
+
+#define NVRAM_HEADER 0x48534C46 /* 'FLSH' */
+#define NVRAM_VERSION 1
+#define NVRAM_HEADER_SIZE 20
+#define NVRAM_SPACE 0x8000
+
+#define FLASH_MIN 0x00020000 /* Minimum flash size */
+
+#define NVRAM_MAX_VALUE_LEN 255
+#define NVRAM_MAX_PARAM_LEN 64
+
+extern int nvram_getenv(char *name, char *val, size_t val_len);
+
+#endif
diff --git a/arch/mips/include/asm/mach-bcm63xx/gpio.h b/arch/mips/include/asm/mach-bcm63xx/gpio.h
index 7cda8c0a397..1eb534de8e3 100644
--- a/arch/mips/include/asm/mach-bcm63xx/gpio.h
+++ b/arch/mips/include/asm/mach-bcm63xx/gpio.h
@@ -3,7 +3,7 @@
#include <bcm63xx_gpio.h>
-#define gpio_to_irq(gpio) NULL
+#define gpio_to_irq(gpio) -1
#define gpio_get_value __gpio_get_value
#define gpio_set_value __gpio_set_value
diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c
index e9e64e0ff7a..5a84a1f1123 100644
--- a/arch/mips/kernel/ftrace.c
+++ b/arch/mips/kernel/ftrace.c
@@ -2,7 +2,7 @@
* Code for replacing ftrace calls with jumps.
*
* Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com>
- * Copyright (C) 2009 DSLab, Lanzhou University, China
+ * Copyright (C) 2009, 2010 DSLab, Lanzhou University, China
* Author: Wu Zhangjin <wuzhangjin@gmail.com>
*
* Thanks goes to Steven Rostedt for writing the original x86 version.
@@ -12,18 +12,62 @@
#include <linux/init.h>
#include <linux/ftrace.h>
-#include <asm/cacheflush.h>
#include <asm/asm.h>
#include <asm/asm-offsets.h>
+#include <asm/cacheflush.h>
+#include <asm/uasm.h>
+
+/*
+ * If the Instruction Pointer is in module space (0xc0000000), return true;
+ * otherwise, it is in kernel space (0x80000000), return false.
+ *
+ * FIXME: This will not work when the kernel space and module space are the
+ * same. If they are the same, we need to modify scripts/recordmcount.pl,
+ * ftrace_make_nop/call() and the other related parts to ensure the
+ * enabling/disabling of the calling site to _mcount is right for both kernel
+ * and module.
+ */
+
+static inline int in_module(unsigned long ip)
+{
+ return ip & 0x40000000;
+}
#ifdef CONFIG_DYNAMIC_FTRACE
#define JAL 0x0c000000 /* jump & link: ip --> ra, jump to target */
#define ADDR_MASK 0x03ffffff /* op_code|addr : 31...26|25 ....0 */
-#define jump_insn_encode(op_code, addr) \
- ((unsigned int)((op_code) | (((addr) >> 2) & ADDR_MASK)))
-static unsigned int ftrace_nop = 0x00000000;
+#define INSN_B_1F_4 0x10000004 /* b 1f; offset = 4 */
+#define INSN_B_1F_5 0x10000005 /* b 1f; offset = 5 */
+#define INSN_NOP 0x00000000 /* nop */
+#define INSN_JAL(addr) \
+ ((unsigned int)(JAL | (((addr) >> 2) & ADDR_MASK)))
+
+static unsigned int insn_jal_ftrace_caller __read_mostly;
+static unsigned int insn_lui_v1_hi16_mcount __read_mostly;
+static unsigned int insn_j_ftrace_graph_caller __maybe_unused __read_mostly;
+
+static inline void ftrace_dyn_arch_init_insns(void)
+{
+ u32 *buf;
+ unsigned int v1;
+
+ /* lui v1, hi16_mcount */
+ v1 = 3;
+ buf = (u32 *)&insn_lui_v1_hi16_mcount;
+ UASM_i_LA_mostly(&buf, v1, MCOUNT_ADDR);
+
+ /* jal (ftrace_caller + 8), jump over the first two instruction */
+ buf = (u32 *)&insn_jal_ftrace_caller;
+ uasm_i_jal(&buf, (FTRACE_ADDR + 8));
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+ /* j ftrace_graph_caller */
+ buf = (u32 *)&insn_j_ftrace_graph_caller;
+ uasm_i_j(&buf, (unsigned long)ftrace_graph_caller);
+#endif
+}
static int ftrace_modify_code(unsigned long ip, unsigned int new_code)
{
@@ -40,67 +84,56 @@ static int ftrace_modify_code(unsigned long ip, unsigned int new_code)
return 0;
}
-static int lui_v1;
-static int jal_mcount;
-
int ftrace_make_nop(struct module *mod,
struct dyn_ftrace *rec, unsigned long addr)
{
unsigned int new;
- int faulted;
unsigned long ip = rec->ip;
- /* We have compiled module with -mlong-calls, but compiled the kernel
- * without it, we need to cope with them respectively. */
- if (ip & 0x40000000) {
- /* record it for ftrace_make_call */
- if (lui_v1 == 0) {
- /* lui_v1 = *(unsigned int *)ip; */
- safe_load_code(lui_v1, ip, faulted);
-
- if (unlikely(faulted))
- return -EFAULT;
- }
-
- /* lui v1, hi_16bit_of_mcount --> b 1f (0x10000004)
+ /*
+ * We have compiled module with -mlong-calls, but compiled the kernel
+ * without it, we need to cope with them respectively.
+ */
+ if (in_module(ip)) {
+#if defined(KBUILD_MCOUNT_RA_ADDRESS) && defined(CONFIG_32BIT)
+ /*
+ * lui v1, hi_16bit_of_mcount --> b 1f (0x10000005)
+ * addiu v1, v1, low_16bit_of_mcount
+ * move at, ra
+ * move $12, ra_address
+ * jalr v1
+ * sub sp, sp, 8
+ * 1: offset = 5 instructions
+ */
+ new = INSN_B_1F_5;
+#else
+ /*
+ * lui v1, hi_16bit_of_mcount --> b 1f (0x10000004)
* addiu v1, v1, low_16bit_of_mcount
* move at, ra
* jalr v1
- * nop
- * 1f: (ip + 12)
+ * nop | move $12, ra_address | sub sp, sp, 8
+ * 1: offset = 4 instructions
*/
- new = 0x10000004;
+ new = INSN_B_1F_4;
+#endif
} else {
- /* record/calculate it for ftrace_make_call */
- if (jal_mcount == 0) {
- /* We can record it directly like this:
- * jal_mcount = *(unsigned int *)ip;
- * Herein, jump over the first two nop instructions */
- jal_mcount = jump_insn_encode(JAL, (MCOUNT_ADDR + 8));
- }
-
- /* move at, ra
- * jalr v1 --> nop
+ /*
+ * move at, ra
+ * jal _mcount --> nop
*/
- new = ftrace_nop;
+ new = INSN_NOP;
}
return ftrace_modify_code(ip, new);
}
-static int modified; /* initialized as 0 by default */
-
int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
{
unsigned int new;
unsigned long ip = rec->ip;
- /* We just need to remove the "b ftrace_stub" at the fist time! */
- if (modified == 0) {
- modified = 1;
- ftrace_modify_code(addr, ftrace_nop);
- }
/* ip, module: 0xc0000000, kernel: 0x80000000 */
- new = (ip & 0x40000000) ? lui_v1 : jal_mcount;
+ new = in_module(ip) ? insn_lui_v1_hi16_mcount : insn_jal_ftrace_caller;
return ftrace_modify_code(ip, new);
}
@@ -111,44 +144,48 @@ int ftrace_update_ftrace_func(ftrace_func_t func)
{
unsigned int new;
- new = jump_insn_encode(JAL, (unsigned long)func);
+ new = INSN_JAL((unsigned long)func);
return ftrace_modify_code(FTRACE_CALL_IP, new);
}
int __init ftrace_dyn_arch_init(void *data)
{
+ /* Encode the instructions when booting */
+ ftrace_dyn_arch_init_insns();
+
+ /* Remove "b ftrace_stub" to ensure ftrace_caller() is executed */
+ ftrace_modify_code(MCOUNT_ADDR, INSN_NOP);
+
/* The return code is retured via data */
*(unsigned long *)data = 0;
return 0;
}
-#endif /* CONFIG_DYNAMIC_FTRACE */
+#endif /* CONFIG_DYNAMIC_FTRACE */
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
#ifdef CONFIG_DYNAMIC_FTRACE
extern void ftrace_graph_call(void);
-#define JMP 0x08000000 /* jump to target directly */
-#define CALL_FTRACE_GRAPH_CALLER \
- jump_insn_encode(JMP, (unsigned long)(&ftrace_graph_caller))
#define FTRACE_GRAPH_CALL_IP ((unsigned long)(&ftrace_graph_call))
int ftrace_enable_ftrace_graph_caller(void)
{
return ftrace_modify_code(FTRACE_GRAPH_CALL_IP,
- CALL_FTRACE_GRAPH_CALLER);
+ insn_j_ftrace_graph_caller);
}
int ftrace_disable_ftrace_graph_caller(void)
{
- return ftrace_modify_code(FTRACE_GRAPH_CALL_IP, ftrace_nop);
+ return ftrace_modify_code(FTRACE_GRAPH_CALL_IP, INSN_NOP);
}
-#endif /* !CONFIG_DYNAMIC_FTRACE */
+#endif /* CONFIG_DYNAMIC_FTRACE */
#ifndef KBUILD_MCOUNT_RA_ADDRESS
+
#define S_RA_SP (0xafbf << 16) /* s{d,w} ra, offset(sp) */
#define S_R_SP (0xafb0 << 16) /* s{d,w} R, offset(sp) */
#define OFFSET_MASK 0xffff /* stack offset range: 0 ~ PT_SIZE */
@@ -162,17 +199,17 @@ unsigned long ftrace_get_parent_addr(unsigned long self_addr,
unsigned int code;
int faulted;
- /* in module or kernel? */
- if (self_addr & 0x40000000) {
- /* module: move to the instruction "lui v1, HI_16BIT_OF_MCOUNT" */
- ip = self_addr - 20;
- } else {
- /* kernel: move to the instruction "move ra, at" */
- ip = self_addr - 12;
- }
+ /*
+ * For module, move the ip from calling site of mcount to the
+ * instruction "lui v1, hi_16bit_of_mcount"(offset is 20), but for
+ * kernel, move to the instruction "move ra, at"(offset is 12)
+ */
+ ip = self_addr - (in_module(self_addr) ? 20 : 12);
- /* search the text until finding the non-store instruction or "s{d,w}
- * ra, offset(sp)" instruction */
+ /*
+ * search the text until finding the non-store instruction or "s{d,w}
+ * ra, offset(sp)" instruction
+ */
do {
ip -= 4;
@@ -181,10 +218,11 @@ unsigned long ftrace_get_parent_addr(unsigned long self_addr,
if (unlikely(faulted))
return 0;
-
- /* If we hit the non-store instruction before finding where the
+ /*
+ * If we hit the non-store instruction before finding where the
* ra is stored, then this is a leaf function and it does not
- * store the ra on the stack. */
+ * store the ra on the stack
+ */
if ((code & S_R_SP) != S_R_SP)
return parent_addr;
@@ -202,7 +240,7 @@ unsigned long ftrace_get_parent_addr(unsigned long self_addr,
return 0;
}
-#endif
+#endif /* !KBUILD_MCOUNT_RA_ADDRESS */
/*
* Hook the return address and push it in the stack of return addrs
@@ -220,7 +258,8 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
if (unlikely(atomic_read(&current->tracing_graph_pause)))
return;
- /* "parent" is the stack address saved the return address of the caller
+ /*
+ * "parent" is the stack address saved the return address of the caller
* of _mcount.
*
* if the gcc < 4.5, a leaf function does not save the return address
@@ -242,10 +281,11 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
goto out;
#ifndef KBUILD_MCOUNT_RA_ADDRESS
parent = (unsigned long *)ftrace_get_parent_addr(self_addr, old,
- (unsigned long)parent,
- fp);
- /* If fails when getting the stack address of the non-leaf function's
- * ra, stop function graph tracer and return */
+ (unsigned long)parent, fp);
+ /*
+ * If fails when getting the stack address of the non-leaf function's
+ * ra, stop function graph tracer and return
+ */
if (parent == 0)
goto out;
#endif
@@ -272,4 +312,4 @@ out:
ftrace_graph_stop();
WARN_ON(1);
}
-#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
diff --git a/arch/mips/kernel/mcount.S b/arch/mips/kernel/mcount.S
index 6851fc97a51..6bfcb7a00ec 100644
--- a/arch/mips/kernel/mcount.S
+++ b/arch/mips/kernel/mcount.S
@@ -6,6 +6,7 @@
* more details.
*
* Copyright (C) 2009 Lemote Inc. & DSLab, Lanzhou University, China
+ * Copyright (C) 2010 DSLab, Lanzhou University, China
* Author: Wu Zhangjin <wuzhangjin@gmail.com>
*/
@@ -45,8 +46,6 @@
PTR_L a5, PT_R9(sp)
PTR_L a6, PT_R10(sp)
PTR_L a7, PT_R11(sp)
-#endif
-#ifdef CONFIG_64BIT
PTR_ADDIU sp, PT_SIZE
#else
PTR_ADDIU sp, (PT_SIZE + 8)
@@ -58,6 +57,12 @@
move ra, AT
.endm
+/*
+ * The -mmcount-ra-address option of gcc 4.5 uses register $12 to pass
+ * the location of the parent's return address.
+ */
+#define MCOUNT_RA_ADDRESS_REG $12
+
#ifdef CONFIG_DYNAMIC_FTRACE
NESTED(ftrace_caller, PT_SIZE, ra)
@@ -71,14 +76,14 @@ _mcount:
MCOUNT_SAVE_REGS
#ifdef KBUILD_MCOUNT_RA_ADDRESS
- PTR_S t0, PT_R12(sp) /* t0 saved the location of the return address(at) by -mmcount-ra-address */
+ PTR_S MCOUNT_RA_ADDRESS_REG, PT_R12(sp)
#endif
- move a0, ra /* arg1: next ip, selfaddr */
+ move a0, ra /* arg1: self return address */
.globl ftrace_call
ftrace_call:
nop /* a placeholder for the call to a real tracing function */
- move a1, AT /* arg2: the caller's next ip, parent */
+ move a1, AT /* arg2: parent's return address */
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
.globl ftrace_graph_call
@@ -119,9 +124,9 @@ NESTED(_mcount, PT_SIZE, ra)
static_trace:
MCOUNT_SAVE_REGS
- move a0, ra /* arg1: next ip, selfaddr */
+ move a0, ra /* arg1: self return address */
jalr t2 /* (1) call *ftrace_trace_function */
- move a1, AT /* arg2: the caller's next ip, parent */
+ move a1, AT /* arg2: parent's return address */
MCOUNT_RESTORE_REGS
.globl ftrace_stub
@@ -134,28 +139,34 @@ ftrace_stub:
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
NESTED(ftrace_graph_caller, PT_SIZE, ra)
-#ifdef CONFIG_DYNAMIC_FTRACE
- PTR_L a1, PT_R31(sp) /* load the original ra from the stack */
-#ifdef KBUILD_MCOUNT_RA_ADDRESS
- PTR_L t0, PT_R12(sp) /* load the original t0 from the stack */
-#endif
-#else
+#ifndef CONFIG_DYNAMIC_FTRACE
MCOUNT_SAVE_REGS
- move a1, ra /* arg2: next ip, selfaddr */
#endif
+ /* arg1: Get the location of the parent's return address */
#ifdef KBUILD_MCOUNT_RA_ADDRESS
- bnez t0, 1f /* non-leaf func: t0 saved the location of the return address */
+#ifdef CONFIG_DYNAMIC_FTRACE
+ PTR_L a0, PT_R12(sp)
+#else
+ move a0, MCOUNT_RA_ADDRESS_REG
+#endif
+ bnez a0, 1f /* non-leaf func: stored in MCOUNT_RA_ADDRESS_REG */
nop
- PTR_LA t0, PT_R1(sp) /* leaf func: get the location of at(old ra) from our own stack */
-1: move a0, t0 /* arg1: the location of the return address */
+#endif
+ PTR_LA a0, PT_R1(sp) /* leaf func: the location in current stack */
+1:
+
+ /* arg2: Get self return address */
+#ifdef CONFIG_DYNAMIC_FTRACE
+ PTR_L a1, PT_R31(sp)
#else
- PTR_LA a0, PT_R1(sp) /* arg1: &AT -> a0 */
+ move a1, ra
#endif
- jal prepare_ftrace_return
+
+ /* arg3: Get frame pointer of current stack */
#ifdef CONFIG_FRAME_POINTER
- move a2, fp /* arg3: frame pointer */
-#else
+ move a2, fp
+#else /* ! CONFIG_FRAME_POINTER */
#ifdef CONFIG_64BIT
PTR_LA a2, PT_SIZE(sp)
#else
@@ -163,6 +174,8 @@ NESTED(ftrace_graph_caller, PT_SIZE, ra)
#endif
#endif
+ jal prepare_ftrace_return
+ nop
MCOUNT_RESTORE_REGS
RETURN_BACK
END(ftrace_graph_caller)
diff --git a/arch/mips/kernel/mips-mt-fpaff.c b/arch/mips/kernel/mips-mt-fpaff.c
index f5981c49910..2340f11dc29 100644
--- a/arch/mips/kernel/mips-mt-fpaff.c
+++ b/arch/mips/kernel/mips-mt-fpaff.c
@@ -3,6 +3,7 @@
* Copyright (C) 2005 Mips Technologies, Inc
*/
#include <linux/cpu.h>
+#include <linux/cpuset.h>
#include <linux/cpumask.h>
#include <linux/delay.h>
#include <linux/kernel.h>
@@ -39,6 +40,21 @@ static inline struct task_struct *find_process_by_pid(pid_t pid)
return pid ? find_task_by_vpid(pid) : current;
}
+/*
+ * check the target process has a UID that matches the current process's
+ */
+static bool check_same_owner(struct task_struct *p)
+{
+ const struct cred *cred = current_cred(), *pcred;
+ bool match;
+
+ rcu_read_lock();
+ pcred = __task_cred(p);
+ match = (cred->euid == pcred->euid ||
+ cred->euid == pcred->uid);
+ rcu_read_unlock();
+ return match;
+}
/*
* mipsmt_sys_sched_setaffinity - set the cpu affinity of a process
@@ -46,12 +62,10 @@ static inline struct task_struct *find_process_by_pid(pid_t pid)
asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len,
unsigned long __user *user_mask_ptr)
{
- cpumask_t new_mask;
- cpumask_t effective_mask;
- int retval;
- struct task_struct *p;
+ cpumask_var_t cpus_allowed, new_mask, effective_mask;
struct thread_info *ti;
- uid_t euid;
+ struct task_struct *p;
+ int retval;
if (len < sizeof(new_mask))
return -EINVAL;
@@ -60,53 +74,74 @@ asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len,
return -EFAULT;
get_online_cpus();
- read_lock(&tasklist_lock);
+ rcu_read_lock();
p = find_process_by_pid(pid);
if (!p) {
- read_unlock(&tasklist_lock);
+ rcu_read_unlock();
put_online_cpus();
return -ESRCH;
}
- /*
- * It is not safe to call set_cpus_allowed with the
- * tasklist_lock held. We will bump the task_struct's
- * usage count and drop tasklist_lock before invoking
- * set_cpus_allowed.
- */
+ /* Prevent p going away */
get_task_struct(p);
+ rcu_read_unlock();
- euid = current_euid();
+ if (!alloc_cpumask_var(&cpus_allowed, GFP_KERNEL)) {
+ retval = -ENOMEM;
+ goto out_put_task;
+ }
+ if (!alloc_cpumask_var(&new_mask, GFP_KERNEL)) {
+ retval = -ENOMEM;
+ goto out_free_cpus_allowed;
+ }
+ if (!alloc_cpumask_var(&effective_mask, GFP_KERNEL)) {
+ retval = -ENOMEM;
+ goto out_free_new_mask;
+ }
retval = -EPERM;
- if (euid != p->cred->euid && euid != p->cred->uid &&
- !capable(CAP_SYS_NICE)) {
- read_unlock(&tasklist_lock);
+ if (!check_same_owner(p) && !capable(CAP_SYS_NICE))
goto out_unlock;
- }
retval = security_task_setscheduler(p, 0, NULL);
if (retval)
goto out_unlock;
/* Record new user-specified CPU set for future reference */
- p->thread.user_cpus_allowed = new_mask;
-
- /* Unlock the task list */
- read_unlock(&tasklist_lock);
+ cpumask_copy(&p->thread.user_cpus_allowed, new_mask);
+ again:
/* Compute new global allowed CPU set if necessary */
ti = task_thread_info(p);
if (test_ti_thread_flag(ti, TIF_FPUBOUND) &&
- cpus_intersects(new_mask, mt_fpu_cpumask)) {
- cpus_and(effective_mask, new_mask, mt_fpu_cpumask);
- retval = set_cpus_allowed_ptr(p, &effective_mask);
+ cpus_intersects(*new_mask, mt_fpu_cpumask)) {
+ cpus_and(*effective_mask, *new_mask, mt_fpu_cpumask);
+ retval = set_cpus_allowed_ptr(p, effective_mask);
} else {
+ cpumask_copy(effective_mask, new_mask);
clear_ti_thread_flag(ti, TIF_FPUBOUND);
- retval = set_cpus_allowed_ptr(p, &new_mask);
+ retval = set_cpus_allowed_ptr(p, new_mask);
}
+ if (!retval) {
+ cpuset_cpus_allowed(p, cpus_allowed);
+ if (!cpumask_subset(effective_mask, cpus_allowed)) {
+ /*
+ * We must have raced with a concurrent cpuset
+ * update. Just reset the cpus_allowed to the
+ * cpuset's cpus_allowed
+ */
+ cpumask_copy(new_mask, cpus_allowed);
+ goto again;
+ }
+ }
out_unlock:
+ free_cpumask_var(effective_mask);
+out_free_new_mask:
+ free_cpumask_var(new_mask);
+out_free_cpus_allowed:
+ free_cpumask_var(cpus_allowed);
+out_put_task:
put_task_struct(p);
put_online_cpus();
return retval;
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 8bdd6a663c7..852780868fb 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -976,7 +976,7 @@ asmlinkage void do_cpu(struct pt_regs *regs)
case 2:
raw_notifier_call_chain(&cu2_chain, CU2_EXCEPTION, regs);
- break;
+ return;
case 3:
break;
diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig
index 3df1967dea0..c97ca69b94e 100644
--- a/arch/mips/loongson/Kconfig
+++ b/arch/mips/loongson/Kconfig
@@ -23,6 +23,7 @@ config LEMOTE_FULOONG2E
select GENERIC_HARDIRQS_NO__DO_IRQ
select GENERIC_ISA_DMA_SUPPORT_BROKEN
select CPU_HAS_WB
+ select LOONGSON_MC146818
help
Lemote Fuloong(2e) mini-PC board based on the Chinese Loongson-2E CPU and
an FPGA northbridge
@@ -51,6 +52,7 @@ config LEMOTE_MACH2F
select SYS_SUPPORTS_64BIT_KERNEL
select SYS_SUPPORTS_HIGHMEM
select SYS_SUPPORTS_LITTLE_ENDIAN
+ select LOONGSON_MC146818
help
Lemote Loongson 2F family machines utilize the 2F revision of
Loongson processor and the AMD CS5536 south bridge.
@@ -83,3 +85,7 @@ config LOONGSON_UART_BASE
bool
default y
depends on EARLY_PRINTK || SERIAL_8250
+
+config LOONGSON_MC146818
+ bool
+ default n
diff --git a/arch/mips/loongson/common/Makefile b/arch/mips/loongson/common/Makefile
index cdd2e812ba1..e526488df65 100644
--- a/arch/mips/loongson/common/Makefile
+++ b/arch/mips/loongson/common/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_GENERIC_GPIO) += gpio.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-$(CONFIG_SERIAL_8250) += serial.o
obj-$(CONFIG_LOONGSON_UART_BASE) += uart_base.o
+obj-$(CONFIG_LOONGSON_MC146818) += rtc.o
#
# Enable CS5536 Virtual Support Module(VSM) to virtulize the PCI configure
diff --git a/arch/mips/loongson/common/cs5536/cs5536_ehci.c b/arch/mips/loongson/common/cs5536/cs5536_ehci.c
index eaf8b86e331..5b5cbba699b 100644
--- a/arch/mips/loongson/common/cs5536/cs5536_ehci.c
+++ b/arch/mips/loongson/common/cs5536/cs5536_ehci.c
@@ -49,6 +49,8 @@ void pci_ehci_write_reg(int reg, u32 value)
lo |= SOFT_BAR_EHCI_FLAG;
_wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
} else if ((value & 0x01) == 0x00) {
+ _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo);
+ lo = value;
_wrmsr(USB_MSR_REG(USB_EHCI), hi, lo);
value &= 0xfffffff0;
diff --git a/arch/mips/loongson/common/cs5536/cs5536_ide.c b/arch/mips/loongson/common/cs5536/cs5536_ide.c
index 9a96b5664c7..681d1291a2c 100644
--- a/arch/mips/loongson/common/cs5536/cs5536_ide.c
+++ b/arch/mips/loongson/common/cs5536/cs5536_ide.c
@@ -51,6 +51,7 @@ void pci_ide_write_reg(int reg, u32 value)
lo |= SOFT_BAR_IDE_FLAG;
_wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
} else if (value & 0x01) {
+ _rdmsr(IDE_MSR_REG(IDE_IO_BAR), &hi, &lo);
lo = (value & 0xfffffff0) | 0x1;
_wrmsr(IDE_MSR_REG(IDE_IO_BAR), hi, lo);
@@ -65,19 +66,30 @@ void pci_ide_write_reg(int reg, u32 value)
_rdmsr(DIVIL_MSR_REG(DIVIL_BALL_OPTS), &hi, &lo);
lo |= 0x01;
_wrmsr(DIVIL_MSR_REG(DIVIL_BALL_OPTS), hi, lo);
- } else
+ } else {
+ _rdmsr(IDE_MSR_REG(IDE_CFG), &hi, &lo);
+ lo = value;
_wrmsr(IDE_MSR_REG(IDE_CFG), hi, lo);
+ }
break;
case PCI_IDE_DTC_REG:
+ _rdmsr(IDE_MSR_REG(IDE_DTC), &hi, &lo);
+ lo = value;
_wrmsr(IDE_MSR_REG(IDE_DTC), hi, lo);
break;
case PCI_IDE_CAST_REG:
+ _rdmsr(IDE_MSR_REG(IDE_CAST), &hi, &lo);
+ lo = value;
_wrmsr(IDE_MSR_REG(IDE_CAST), hi, lo);
break;
case PCI_IDE_ETC_REG:
+ _rdmsr(IDE_MSR_REG(IDE_ETC), &hi, &lo);
+ lo = value;
_wrmsr(IDE_MSR_REG(IDE_ETC), hi, lo);
break;
case PCI_IDE_PM_REG:
+ _rdmsr(IDE_MSR_REG(IDE_INTERNAL_PM), &hi, &lo);
+ lo = value;
_wrmsr(IDE_MSR_REG(IDE_INTERNAL_PM), hi, lo);
break;
default:
@@ -167,6 +179,7 @@ u32 pci_ide_read_reg(int reg)
case PCI_IDE_ETC_REG:
_rdmsr(IDE_MSR_REG(IDE_ETC), &hi, &lo);
conf_data = lo;
+ break;
case PCI_IDE_PM_REG:
_rdmsr(IDE_MSR_REG(IDE_INTERNAL_PM), &hi, &lo);
conf_data = lo;
diff --git a/arch/mips/loongson/common/cs5536/cs5536_isa.c b/arch/mips/loongson/common/cs5536/cs5536_isa.c
index f5c0818831b..4d9f65abeaf 100644
--- a/arch/mips/loongson/common/cs5536/cs5536_isa.c
+++ b/arch/mips/loongson/common/cs5536/cs5536_isa.c
@@ -61,7 +61,7 @@ static void divil_lbar_enable(void)
for (offset = DIVIL_LBAR_SMB; offset <= DIVIL_LBAR_PMS; offset++) {
_rdmsr(DIVIL_MSR_REG(offset), &hi, &lo);
hi |= 0x01;
- _wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_SMB), hi, lo);
+ _wrmsr(DIVIL_MSR_REG(offset), hi, lo);
}
}
@@ -76,7 +76,7 @@ static void divil_lbar_disable(void)
for (offset = DIVIL_LBAR_SMB; offset <= DIVIL_LBAR_PMS; offset++) {
_rdmsr(DIVIL_MSR_REG(offset), &hi, &lo);
hi &= ~0x01;
- _wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_SMB), hi, lo);
+ _wrmsr(DIVIL_MSR_REG(offset), hi, lo);
}
}
diff --git a/arch/mips/loongson/common/cs5536/cs5536_ohci.c b/arch/mips/loongson/common/cs5536/cs5536_ohci.c
index db5900aadd6..bdedf512baf 100644
--- a/arch/mips/loongson/common/cs5536/cs5536_ohci.c
+++ b/arch/mips/loongson/common/cs5536/cs5536_ohci.c
@@ -49,6 +49,8 @@ void pci_ohci_write_reg(int reg, u32 value)
lo |= SOFT_BAR_OHCI_FLAG;
_wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
} else if ((value & 0x01) == 0x00) {
+ _rdmsr(USB_MSR_REG(USB_OHCI), &hi, &lo);
+ lo = value;
_wrmsr(USB_MSR_REG(USB_OHCI), hi, lo);
value &= 0xfffffff0;
diff --git a/arch/mips/loongson/common/rtc.c b/arch/mips/loongson/common/rtc.c
new file mode 100644
index 00000000000..a90d87c0155
--- /dev/null
+++ b/arch/mips/loongson/common/rtc.c
@@ -0,0 +1,43 @@
+/*
+ * Lemote Fuloong platform support
+ *
+ * Copyright(c) 2010 Arnaud Patard <apatard@mandriva.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/mc146818rtc.h>
+
+struct resource loongson_rtc_resources[] = {
+ {
+ .start = RTC_PORT(0),
+ .end = RTC_PORT(1),
+ .flags = IORESOURCE_IO,
+ }, {
+ .start = RTC_IRQ,
+ .end = RTC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct platform_device loongson_rtc_device = {
+ .name = "rtc_cmos",
+ .id = -1,
+ .resource = loongson_rtc_resources,
+ .num_resources = ARRAY_SIZE(loongson_rtc_resources),
+};
+
+
+static int __init loongson_rtc_platform_init(void)
+{
+ platform_device_register(&loongson_rtc_device);
+ return 0;
+}
+
+device_initcall(loongson_rtc_platform_init);
diff --git a/arch/mips/math-emu/dp_simple.c b/arch/mips/math-emu/dp_simple.c
index d9ae1dbabda..b90974246e5 100644
--- a/arch/mips/math-emu/dp_simple.c
+++ b/arch/mips/math-emu/dp_simple.c
@@ -78,6 +78,7 @@ ieee754dp ieee754dp_abs(ieee754dp x)
DPSIGN(x) = 0;
if (xc == IEEE754_CLASS_SNAN) {
+ SETCX(IEEE754_INVALID_OPERATION);
return ieee754dp_nanxcpt(ieee754dp_indef(), "abs");
}
diff --git a/arch/mips/math-emu/sp_simple.c b/arch/mips/math-emu/sp_simple.c
index 3175477d36f..2fd53c920e9 100644
--- a/arch/mips/math-emu/sp_simple.c
+++ b/arch/mips/math-emu/sp_simple.c
@@ -78,6 +78,7 @@ ieee754sp ieee754sp_abs(ieee754sp x)
SPSIGN(x) = 0;
if (xc == IEEE754_CLASS_SNAN) {
+ SETCX(IEEE754_INVALID_OPERATION);
return ieee754sp_nanxcpt(ieee754sp_indef(), "abs");
}
diff --git a/arch/mips/oprofile/op_model_loongson2.c b/arch/mips/oprofile/op_model_loongson2.c
index d0d24e04767..60d3ea60211 100644
--- a/arch/mips/oprofile/op_model_loongson2.c
+++ b/arch/mips/oprofile/op_model_loongson2.c
@@ -43,6 +43,12 @@ static struct loongson2_register_config {
static char *oprofid = "LoongsonPerf";
static irqreturn_t loongson2_perfcount_handler(int irq, void *dev_id);
+static void reset_counters(void *arg)
+{
+ write_c0_perfctrl(0);
+ write_c0_perfcnt(0);
+}
+
static void loongson2_reg_setup(struct op_counter_config *cfg)
{
unsigned int ctrl = 0;
@@ -139,7 +145,7 @@ static int __init loongson2_init(void)
static void loongson2_exit(void)
{
- write_c0_perfctrl(0);
+ reset_counters(NULL);
free_irq(LOONGSON2_PERFCNT_IRQ, oprofid);
}