aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2010-07-21 15:43:03 -0400
committerIngo Molnar <mingo@elte.hu>2010-07-21 15:43:06 -0400
commit9dcdbf7a33d9018ac5d45debcf261be648bdd56a (patch)
treebbcc1a018f11ff76cd7ce174ef3ffe2c02da07ee /arch/mips
parentcc5edb0eb9ce892b530e34a5d110382483587942 (diff)
parentcd5b8f8755a89a57fc8c408d284b8b613f090345 (diff)
Merge branch 'linus' into perf/core
Merge reason: Pick up the latest perf fixes. Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/mips')
-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 14eb8c492da2..5ef06a164a82 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)
193 193
194void au_sleep(void) 194void au_sleep(void)
195{ 195{
196 save_core_regs(); 196 int cpuid = alchemy_get_cputype();
197 au1xxx_save_and_sleep(); 197 if (cpuid != ALCHEMY_CPU_UNKNOWN) {
198 restore_core_regs(); 198 save_core_regs();
199 if (cpuid <= ALCHEMY_CPU_AU1500)
200 alchemy_sleep_au1000();
201 else if (cpuid <= ALCHEMY_CPU_AU1200)
202 alchemy_sleep_au1550();
203 restore_core_regs();
204 }
199} 205}
200 206
201#endif /* CONFIG_PM */ 207#endif /* CONFIG_PM */
diff --git a/arch/mips/alchemy/common/sleeper.S b/arch/mips/alchemy/common/sleeper.S
index 4f4b16741d12..77f3c743b716 100644
--- a/arch/mips/alchemy/common/sleeper.S
+++ b/arch/mips/alchemy/common/sleeper.S
@@ -22,10 +22,9 @@
22 .set noat 22 .set noat
23 .align 5 23 .align 5
24 24
25/* Save all of the processor general registers and go to sleep. 25
26 * A wakeup condition will get us back here to restore the registers. 26/* preparatory stuff */
27 */ 27.macro SETUP_SLEEP
28LEAF(au1xxx_save_and_sleep)
29 subu sp, PT_SIZE 28 subu sp, PT_SIZE
30 sw $1, PT_R1(sp) 29 sw $1, PT_R1(sp)
31 sw $2, PT_R2(sp) 30 sw $2, PT_R2(sp)
@@ -69,12 +68,32 @@ LEAF(au1xxx_save_and_sleep)
69 */ 68 */
70 lui t3, 0xb190 /* sys_xxx */ 69 lui t3, 0xb190 /* sys_xxx */
71 sw sp, 0x0018(t3) 70 sw sp, 0x0018(t3)
72 la k0, 3f /* resume path */ 71 la k0, alchemy_sleep_wakeup /* resume path */
73 sw k0, 0x001c(t3) 72 sw k0, 0x001c(t3)
73.endm
74 74
75 /* Put SDRAM into self refresh: Preload instructions into cache, 75.macro DO_SLEEP
76 * issue a precharge, auto/self refresh, then sleep commands to it. 76 /* put power supply and processor to sleep */
77 */ 77 sw zero, 0x0078(t3) /* sys_slppwr */
78 sync
79 sw zero, 0x007c(t3) /* sys_sleep */
80 sync
81 nop
82 nop
83 nop
84 nop
85 nop
86 nop
87 nop
88 nop
89.endm
90
91/* sleep code for Au1000/Au1100/Au1500 memory controller type */
92LEAF(alchemy_sleep_au1000)
93
94 SETUP_SLEEP
95
96 /* cache following instructions, as memory gets put to sleep */
78 la t0, 1f 97 la t0, 1f
79 .set mips3 98 .set mips3
80 cache 0x14, 0(t0) 99 cache 0x14, 0(t0)
@@ -84,17 +103,32 @@ LEAF(au1xxx_save_and_sleep)
84 .set mips0 103 .set mips0
85 104
861: lui a0, 0xb400 /* mem_xxx */ 1051: lui a0, 0xb400 /* mem_xxx */
87#if defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1100) || \
88 defined(CONFIG_SOC_AU1500)
89 sw zero, 0x001c(a0) /* Precharge */ 106 sw zero, 0x001c(a0) /* Precharge */
90 sync 107 sync
91 sw zero, 0x0020(a0) /* Auto Refresh */ 108 sw zero, 0x0020(a0) /* Auto Refresh */
92 sync 109 sync
93 sw zero, 0x0030(a0) /* Sleep */ 110 sw zero, 0x0030(a0) /* Sleep */
94 sync 111 sync
95#endif
96 112
97#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) 113 DO_SLEEP
114
115END(alchemy_sleep_au1000)
116
117/* sleep code for Au1550/Au1200 memory controller type */
118LEAF(alchemy_sleep_au1550)
119
120 SETUP_SLEEP
121
122 /* cache following instructions, as memory gets put to sleep */
123 la t0, 1f
124 .set mips3
125 cache 0x14, 0(t0)
126 cache 0x14, 32(t0)
127 cache 0x14, 64(t0)
128 cache 0x14, 96(t0)
129 .set mips0
130
1311: lui a0, 0xb400 /* mem_xxx */
98 sw zero, 0x08c0(a0) /* Precharge */ 132 sw zero, 0x08c0(a0) /* Precharge */
99 sync 133 sync
100 sw zero, 0x08d0(a0) /* Self Refresh */ 134 sw zero, 0x08d0(a0) /* Self Refresh */
@@ -114,26 +148,17 @@ LEAF(au1xxx_save_and_sleep)
114 and t1, t0, t1 /* clear CE[1:0] */ 148 and t1, t0, t1 /* clear CE[1:0] */
115 sw t1, 0x0840(a0) /* mem_sdconfiga */ 149 sw t1, 0x0840(a0) /* mem_sdconfiga */
116 sync 150 sync
117#endif
118 151
119 /* put power supply and processor to sleep */ 152 DO_SLEEP
120 sw zero, 0x0078(t3) /* sys_slppwr */ 153
121 sync 154END(alchemy_sleep_au1550)
122 sw zero, 0x007c(t3) /* sys_sleep */ 155
123 sync
124 nop
125 nop
126 nop
127 nop
128 nop
129 nop
130 nop
131 nop
132 156
133 /* This is where we return upon wakeup. 157 /* This is where we return upon wakeup.
134 * Reload all of the registers and return. 158 * Reload all of the registers and return.
135 */ 159 */
1363: lw k0, 0x20(sp) 160LEAF(alchemy_sleep_wakeup)
161 lw k0, 0x20(sp)
137 mtc0 k0, CP0_STATUS 162 mtc0 k0, CP0_STATUS
138 lw k0, 0x1c(sp) 163 lw k0, 0x1c(sp)
139 mtc0 k0, CP0_CONTEXT 164 mtc0 k0, CP0_CONTEXT
@@ -169,4 +194,4 @@ LEAF(au1xxx_save_and_sleep)
169 lw $31, PT_R31(sp) 194 lw $31, PT_R31(sp)
170 jr ra 195 jr ra
171 addiu sp, PT_SIZE 196 addiu sp, PT_SIZE
172END(au1xxx_save_and_sleep) 197END(alchemy_sleep_wakeup)
diff --git a/arch/mips/ar7/platform.c b/arch/mips/ar7/platform.c
index 566f2d7f2ea3..8f31d1d59683 100644
--- a/arch/mips/ar7/platform.c
+++ b/arch/mips/ar7/platform.c
@@ -542,7 +542,7 @@ static int __init ar7_register_uarts(void)
542 if (IS_ERR(bus_clk)) 542 if (IS_ERR(bus_clk))
543 panic("unable to get bus clk\n"); 543 panic("unable to get bus clk\n");
544 544
545 uart_port.type = PORT_16550A; 545 uart_port.type = PORT_AR7;
546 uart_port.uartclk = clk_get_rate(bus_clk) / 2; 546 uart_port.uartclk = clk_get_rate(bus_clk) / 2;
547 uart_port.iotype = UPIO_MEM32; 547 uart_port.iotype = UPIO_MEM32;
548 uart_port.regshift = 2; 548 uart_port.regshift = 2;
diff --git a/arch/mips/bcm47xx/Makefile b/arch/mips/bcm47xx/Makefile
index 35294b12d638..7465e8a72d9a 100644
--- a/arch/mips/bcm47xx/Makefile
+++ b/arch/mips/bcm47xx/Makefile
@@ -3,4 +3,4 @@
3# under Linux. 3# under Linux.
4# 4#
5 5
6obj-y := gpio.o irq.o prom.o serial.o setup.o time.o wgt634u.o 6obj-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 000000000000..06e03b222f6d
--- /dev/null
+++ b/arch/mips/bcm47xx/nvram.c
@@ -0,0 +1,94 @@
1/*
2 * BCM947xx nvram variable access
3 *
4 * Copyright (C) 2005 Broadcom Corporation
5 * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13#include <linux/init.h>
14#include <linux/types.h>
15#include <linux/module.h>
16#include <linux/ssb/ssb.h>
17#include <linux/kernel.h>
18#include <linux/string.h>
19#include <asm/addrspace.h>
20#include <asm/mach-bcm47xx/nvram.h>
21#include <asm/mach-bcm47xx/bcm47xx.h>
22
23static char nvram_buf[NVRAM_SPACE];
24
25/* Probe for NVRAM header */
26static void __init early_nvram_init(void)
27{
28 struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore;
29 struct nvram_header *header;
30 int i;
31 u32 base, lim, off;
32 u32 *src, *dst;
33
34 base = mcore->flash_window;
35 lim = mcore->flash_window_size;
36
37 off = FLASH_MIN;
38 while (off <= lim) {
39 /* Windowed flash access */
40 header = (struct nvram_header *)
41 KSEG1ADDR(base + off - NVRAM_SPACE);
42 if (header->magic == NVRAM_HEADER)
43 goto found;
44 off <<= 1;
45 }
46
47 /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */
48 header = (struct nvram_header *) KSEG1ADDR(base + 4096);
49 if (header->magic == NVRAM_HEADER)
50 goto found;
51
52 header = (struct nvram_header *) KSEG1ADDR(base + 1024);
53 if (header->magic == NVRAM_HEADER)
54 goto found;
55
56 return;
57
58found:
59 src = (u32 *) header;
60 dst = (u32 *) nvram_buf;
61 for (i = 0; i < sizeof(struct nvram_header); i += 4)
62 *dst++ = *src++;
63 for (; i < header->len && i < NVRAM_SPACE; i += 4)
64 *dst++ = le32_to_cpu(*src++);
65}
66
67int nvram_getenv(char *name, char *val, size_t val_len)
68{
69 char *var, *value, *end, *eq;
70
71 if (!name)
72 return 1;
73
74 if (!nvram_buf[0])
75 early_nvram_init();
76
77 /* Look for name=value and return value */
78 var = &nvram_buf[sizeof(struct nvram_header)];
79 end = nvram_buf + sizeof(nvram_buf) - 2;
80 end[0] = end[1] = '\0';
81 for (; *var; var = value + strlen(value) + 1) {
82 eq = strchr(var, '=');
83 if (!eq)
84 break;
85 value = eq + 1;
86 if ((eq - var) == strlen(name) &&
87 strncmp(var, name, (eq - var)) == 0) {
88 snprintf(val, val_len, "%s", value);
89 return 0;
90 }
91 }
92 return 1;
93}
94EXPORT_SYMBOL(nvram_getenv);
diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c
index d442e11625fa..b1aee33efd11 100644
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
@@ -1,8 +1,8 @@
1/* 1/*
2 * Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org> 2 * Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
3 * Copyright (C) 2005 Waldemar Brodkorb <wbx@openwrt.org>
4 * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org> 3 * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
5 * Copyright (C) 2006 Michael Buesch <mb@bu3sch.de> 4 * Copyright (C) 2006 Michael Buesch <mb@bu3sch.de>
5 * Copyright (C) 2010 Waldemar Brodkorb <wbx@openadk.org>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify it 7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the 8 * under the terms of the GNU General Public License as published by the
@@ -33,6 +33,7 @@
33#include <asm/time.h> 33#include <asm/time.h>
34#include <bcm47xx.h> 34#include <bcm47xx.h>
35#include <asm/fw/cfe/cfe_api.h> 35#include <asm/fw/cfe/cfe_api.h>
36#include <asm/mach-bcm47xx/nvram.h>
36 37
37struct ssb_bus ssb_bcm47xx; 38struct ssb_bus ssb_bcm47xx;
38EXPORT_SYMBOL(ssb_bcm47xx); 39EXPORT_SYMBOL(ssb_bcm47xx);
@@ -81,28 +82,42 @@ static int bcm47xx_get_invariants(struct ssb_bus *bus,
81 /* Fill boardinfo structure */ 82 /* Fill boardinfo structure */
82 memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo)); 83 memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo));
83 84
84 if (cfe_getenv("boardvendor", buf, sizeof(buf)) >= 0) 85 if (cfe_getenv("boardvendor", buf, sizeof(buf)) >= 0 ||
86 nvram_getenv("boardvendor", buf, sizeof(buf)) >= 0)
85 iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0); 87 iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
86 if (cfe_getenv("boardtype", buf, sizeof(buf)) >= 0) 88 if (cfe_getenv("boardtype", buf, sizeof(buf)) >= 0 ||
89 nvram_getenv("boardtype", buf, sizeof(buf)) >= 0)
87 iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0); 90 iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
88 if (cfe_getenv("boardrev", buf, sizeof(buf)) >= 0) 91 if (cfe_getenv("boardrev", buf, sizeof(buf)) >= 0 ||
92 nvram_getenv("boardrev", buf, sizeof(buf)) >= 0)
89 iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0); 93 iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0);
90 94
91 /* Fill sprom structure */ 95 /* Fill sprom structure */
92 memset(&(iv->sprom), 0, sizeof(struct ssb_sprom)); 96 memset(&(iv->sprom), 0, sizeof(struct ssb_sprom));
93 iv->sprom.revision = 3; 97 iv->sprom.revision = 3;
94 98
95 if (cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0) 99 if (cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0 ||
100 nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0)
96 str2eaddr(buf, iv->sprom.et0mac); 101 str2eaddr(buf, iv->sprom.et0mac);
97 if (cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0) 102
103 if (cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0 ||
104 nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0)
98 str2eaddr(buf, iv->sprom.et1mac); 105 str2eaddr(buf, iv->sprom.et1mac);
99 if (cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0) 106
100 iv->sprom.et0phyaddr = simple_strtoul(buf, NULL, 10); 107 if (cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0 ||
101 if (cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0) 108 nvram_getenv("et0phyaddr", buf, sizeof(buf)) >= 0)
102 iv->sprom.et1phyaddr = simple_strtoul(buf, NULL, 10); 109 iv->sprom.et0phyaddr = simple_strtoul(buf, NULL, 0);
103 if (cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0) 110
111 if (cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0 ||
112 nvram_getenv("et1phyaddr", buf, sizeof(buf)) >= 0)
113 iv->sprom.et1phyaddr = simple_strtoul(buf, NULL, 0);
114
115 if (cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0 ||
116 nvram_getenv("et0mdcport", buf, sizeof(buf)) >= 0)
104 iv->sprom.et0mdcport = simple_strtoul(buf, NULL, 10); 117 iv->sprom.et0mdcport = simple_strtoul(buf, NULL, 10);
105 if (cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0) 118
119 if (cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0 ||
120 nvram_getenv("et1mdcport", buf, sizeof(buf)) >= 0)
106 iv->sprom.et1mdcport = simple_strtoul(buf, NULL, 10); 121 iv->sprom.et1mdcport = simple_strtoul(buf, NULL, 10);
107 122
108 return 0; 123 return 0;
diff --git a/arch/mips/include/asm/mach-ar7/ar7.h b/arch/mips/include/asm/mach-ar7/ar7.h
index f1cf38943497..483ffea9ecb1 100644
--- a/arch/mips/include/asm/mach-ar7/ar7.h
+++ b/arch/mips/include/asm/mach-ar7/ar7.h
@@ -50,7 +50,7 @@
50#define UR8_REGS_WDT (AR7_REGS_BASE + 0x0b00) 50#define UR8_REGS_WDT (AR7_REGS_BASE + 0x0b00)
51#define UR8_REGS_UART1 (AR7_REGS_BASE + 0x0f00) 51#define UR8_REGS_UART1 (AR7_REGS_BASE + 0x0f00)
52 52
53#define AR7_RESET_PEREPHERIAL 0x0 53#define AR7_RESET_PERIPHERAL 0x0
54#define AR7_RESET_SOFTWARE 0x4 54#define AR7_RESET_SOFTWARE 0x4
55#define AR7_RESET_STATUS 0x8 55#define AR7_RESET_STATUS 0x8
56 56
@@ -128,7 +128,7 @@ static inline int ar7_has_high_cpmac(void)
128static inline void ar7_device_enable(u32 bit) 128static inline void ar7_device_enable(u32 bit)
129{ 129{
130 void *reset_reg = 130 void *reset_reg =
131 (void *)KSEG1ADDR(AR7_REGS_RESET + AR7_RESET_PEREPHERIAL); 131 (void *)KSEG1ADDR(AR7_REGS_RESET + AR7_RESET_PERIPHERAL);
132 writel(readl(reset_reg) | (1 << bit), reset_reg); 132 writel(readl(reset_reg) | (1 << bit), reset_reg);
133 msleep(20); 133 msleep(20);
134} 134}
@@ -136,7 +136,7 @@ static inline void ar7_device_enable(u32 bit)
136static inline void ar7_device_disable(u32 bit) 136static inline void ar7_device_disable(u32 bit)
137{ 137{
138 void *reset_reg = 138 void *reset_reg =
139 (void *)KSEG1ADDR(AR7_REGS_RESET + AR7_RESET_PEREPHERIAL); 139 (void *)KSEG1ADDR(AR7_REGS_RESET + AR7_RESET_PERIPHERAL);
140 writel(readl(reset_reg) & ~(1 << bit), reset_reg); 140 writel(readl(reset_reg) & ~(1 << bit), reset_reg);
141 msleep(20); 141 msleep(20);
142} 142}
diff --git a/arch/mips/include/asm/mach-ar7/gpio.h b/arch/mips/include/asm/mach-ar7/gpio.h
index 73f9b162c970..abc317c0372e 100644
--- a/arch/mips/include/asm/mach-ar7/gpio.h
+++ b/arch/mips/include/asm/mach-ar7/gpio.h
@@ -24,7 +24,7 @@
24#define AR7_GPIO_MAX 32 24#define AR7_GPIO_MAX 32
25#define NR_BUILTIN_GPIO AR7_GPIO_MAX 25#define NR_BUILTIN_GPIO AR7_GPIO_MAX
26 26
27#define gpio_to_irq(gpio) NULL 27#define gpio_to_irq(gpio) -1
28 28
29#define gpio_get_value __gpio_get_value 29#define gpio_get_value __gpio_get_value
30#define gpio_set_value __gpio_set_value 30#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 e76941db2312..a6976619160a 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);
188extern unsigned long au1xxx_calc_clock(void); 188extern unsigned long au1xxx_calc_clock(void);
189 189
190/* PM: arch/mips/alchemy/common/sleeper.S, power.c, irq.c */ 190/* PM: arch/mips/alchemy/common/sleeper.S, power.c, irq.c */
191void au1xxx_save_and_sleep(void); 191void alchemy_sleep_au1000(void);
192void alchemy_sleep_au1550(void);
192void au_sleep(void); 193void au_sleep(void);
193 194
194 195
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 000000000000..0d8cc146f7a4
--- /dev/null
+++ b/arch/mips/include/asm/mach-bcm47xx/nvram.h
@@ -0,0 +1,36 @@
1/*
2 * Copyright (C) 2005, Broadcom Corporation
3 * Copyright (C) 2006, Felix Fietkau <nbd@openwrt.org>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 */
10
11#ifndef __NVRAM_H
12#define __NVRAM_H
13
14#include <linux/types.h>
15
16struct nvram_header {
17 u32 magic;
18 u32 len;
19 u32 crc_ver_init; /* 0:7 crc, 8:15 ver, 16:31 sdram_init */
20 u32 config_refresh; /* 0:15 sdram_config, 16:31 sdram_refresh */
21 u32 config_ncdl; /* ncdl values for memc */
22};
23
24#define NVRAM_HEADER 0x48534C46 /* 'FLSH' */
25#define NVRAM_VERSION 1
26#define NVRAM_HEADER_SIZE 20
27#define NVRAM_SPACE 0x8000
28
29#define FLASH_MIN 0x00020000 /* Minimum flash size */
30
31#define NVRAM_MAX_VALUE_LEN 255
32#define NVRAM_MAX_PARAM_LEN 64
33
34extern int nvram_getenv(char *name, char *val, size_t val_len);
35
36#endif
diff --git a/arch/mips/include/asm/mach-bcm63xx/gpio.h b/arch/mips/include/asm/mach-bcm63xx/gpio.h
index 7cda8c0a3979..1eb534de8e3b 100644
--- a/arch/mips/include/asm/mach-bcm63xx/gpio.h
+++ b/arch/mips/include/asm/mach-bcm63xx/gpio.h
@@ -3,7 +3,7 @@
3 3
4#include <bcm63xx_gpio.h> 4#include <bcm63xx_gpio.h>
5 5
6#define gpio_to_irq(gpio) NULL 6#define gpio_to_irq(gpio) -1
7 7
8#define gpio_get_value __gpio_get_value 8#define gpio_get_value __gpio_get_value
9#define gpio_set_value __gpio_set_value 9#define gpio_set_value __gpio_set_value
diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c
index e9e64e0ff7aa..5a84a1f11231 100644
--- a/arch/mips/kernel/ftrace.c
+++ b/arch/mips/kernel/ftrace.c
@@ -2,7 +2,7 @@
2 * Code for replacing ftrace calls with jumps. 2 * Code for replacing ftrace calls with jumps.
3 * 3 *
4 * Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com> 4 * Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com>
5 * Copyright (C) 2009 DSLab, Lanzhou University, China 5 * Copyright (C) 2009, 2010 DSLab, Lanzhou University, China
6 * Author: Wu Zhangjin <wuzhangjin@gmail.com> 6 * Author: Wu Zhangjin <wuzhangjin@gmail.com>
7 * 7 *
8 * Thanks goes to Steven Rostedt for writing the original x86 version. 8 * Thanks goes to Steven Rostedt for writing the original x86 version.
@@ -12,18 +12,62 @@
12#include <linux/init.h> 12#include <linux/init.h>
13#include <linux/ftrace.h> 13#include <linux/ftrace.h>
14 14
15#include <asm/cacheflush.h>
16#include <asm/asm.h> 15#include <asm/asm.h>
17#include <asm/asm-offsets.h> 16#include <asm/asm-offsets.h>
17#include <asm/cacheflush.h>
18#include <asm/uasm.h>
19
20/*
21 * If the Instruction Pointer is in module space (0xc0000000), return true;
22 * otherwise, it is in kernel space (0x80000000), return false.
23 *
24 * FIXME: This will not work when the kernel space and module space are the
25 * same. If they are the same, we need to modify scripts/recordmcount.pl,
26 * ftrace_make_nop/call() and the other related parts to ensure the
27 * enabling/disabling of the calling site to _mcount is right for both kernel
28 * and module.
29 */
30
31static inline int in_module(unsigned long ip)
32{
33 return ip & 0x40000000;
34}
18 35
19#ifdef CONFIG_DYNAMIC_FTRACE 36#ifdef CONFIG_DYNAMIC_FTRACE
20 37
21#define JAL 0x0c000000 /* jump & link: ip --> ra, jump to target */ 38#define JAL 0x0c000000 /* jump & link: ip --> ra, jump to target */
22#define ADDR_MASK 0x03ffffff /* op_code|addr : 31...26|25 ....0 */ 39#define ADDR_MASK 0x03ffffff /* op_code|addr : 31...26|25 ....0 */
23#define jump_insn_encode(op_code, addr) \
24 ((unsigned int)((op_code) | (((addr) >> 2) & ADDR_MASK)))
25 40
26static unsigned int ftrace_nop = 0x00000000; 41#define INSN_B_1F_4 0x10000004 /* b 1f; offset = 4 */
42#define INSN_B_1F_5 0x10000005 /* b 1f; offset = 5 */
43#define INSN_NOP 0x00000000 /* nop */
44#define INSN_JAL(addr) \
45 ((unsigned int)(JAL | (((addr) >> 2) & ADDR_MASK)))
46
47static unsigned int insn_jal_ftrace_caller __read_mostly;
48static unsigned int insn_lui_v1_hi16_mcount __read_mostly;
49static unsigned int insn_j_ftrace_graph_caller __maybe_unused __read_mostly;
50
51static inline void ftrace_dyn_arch_init_insns(void)
52{
53 u32 *buf;
54 unsigned int v1;
55
56 /* lui v1, hi16_mcount */
57 v1 = 3;
58 buf = (u32 *)&insn_lui_v1_hi16_mcount;
59 UASM_i_LA_mostly(&buf, v1, MCOUNT_ADDR);
60
61 /* jal (ftrace_caller + 8), jump over the first two instruction */
62 buf = (u32 *)&insn_jal_ftrace_caller;
63 uasm_i_jal(&buf, (FTRACE_ADDR + 8));
64
65#ifdef CONFIG_FUNCTION_GRAPH_TRACER
66 /* j ftrace_graph_caller */
67 buf = (u32 *)&insn_j_ftrace_graph_caller;
68 uasm_i_j(&buf, (unsigned long)ftrace_graph_caller);
69#endif
70}
27 71
28static int ftrace_modify_code(unsigned long ip, unsigned int new_code) 72static int ftrace_modify_code(unsigned long ip, unsigned int new_code)
29{ 73{
@@ -40,67 +84,56 @@ static int ftrace_modify_code(unsigned long ip, unsigned int new_code)
40 return 0; 84 return 0;
41} 85}
42 86
43static int lui_v1;
44static int jal_mcount;
45
46int ftrace_make_nop(struct module *mod, 87int ftrace_make_nop(struct module *mod,
47 struct dyn_ftrace *rec, unsigned long addr) 88 struct dyn_ftrace *rec, unsigned long addr)
48{ 89{
49 unsigned int new; 90 unsigned int new;
50 int faulted;
51 unsigned long ip = rec->ip; 91 unsigned long ip = rec->ip;
52 92
53 /* We have compiled module with -mlong-calls, but compiled the kernel 93 /*
54 * without it, we need to cope with them respectively. */ 94 * We have compiled module with -mlong-calls, but compiled the kernel
55 if (ip & 0x40000000) { 95 * without it, we need to cope with them respectively.
56 /* record it for ftrace_make_call */ 96 */
57 if (lui_v1 == 0) { 97 if (in_module(ip)) {
58 /* lui_v1 = *(unsigned int *)ip; */ 98#if defined(KBUILD_MCOUNT_RA_ADDRESS) && defined(CONFIG_32BIT)
59 safe_load_code(lui_v1, ip, faulted); 99 /*
60 100 * lui v1, hi_16bit_of_mcount --> b 1f (0x10000005)
61 if (unlikely(faulted)) 101 * addiu v1, v1, low_16bit_of_mcount
62 return -EFAULT; 102 * move at, ra
63 } 103 * move $12, ra_address
64 104 * jalr v1
65 /* lui v1, hi_16bit_of_mcount --> b 1f (0x10000004) 105 * sub sp, sp, 8
106 * 1: offset = 5 instructions
107 */
108 new = INSN_B_1F_5;
109#else
110 /*
111 * lui v1, hi_16bit_of_mcount --> b 1f (0x10000004)
66 * addiu v1, v1, low_16bit_of_mcount 112 * addiu v1, v1, low_16bit_of_mcount
67 * move at, ra 113 * move at, ra
68 * jalr v1 114 * jalr v1
69 * nop 115 * nop | move $12, ra_address | sub sp, sp, 8
70 * 1f: (ip + 12) 116 * 1: offset = 4 instructions
71 */ 117 */
72 new = 0x10000004; 118 new = INSN_B_1F_4;
119#endif
73 } else { 120 } else {
74 /* record/calculate it for ftrace_make_call */ 121 /*
75 if (jal_mcount == 0) { 122 * move at, ra
76 /* We can record it directly like this: 123 * jal _mcount --> nop
77 * jal_mcount = *(unsigned int *)ip;
78 * Herein, jump over the first two nop instructions */
79 jal_mcount = jump_insn_encode(JAL, (MCOUNT_ADDR + 8));
80 }
81
82 /* move at, ra
83 * jalr v1 --> nop
84 */ 124 */
85 new = ftrace_nop; 125 new = INSN_NOP;
86 } 126 }
87 return ftrace_modify_code(ip, new); 127 return ftrace_modify_code(ip, new);
88} 128}
89 129
90static int modified; /* initialized as 0 by default */
91
92int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) 130int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
93{ 131{
94 unsigned int new; 132 unsigned int new;
95 unsigned long ip = rec->ip; 133 unsigned long ip = rec->ip;
96 134
97 /* We just need to remove the "b ftrace_stub" at the fist time! */
98 if (modified == 0) {
99 modified = 1;
100 ftrace_modify_code(addr, ftrace_nop);
101 }
102 /* ip, module: 0xc0000000, kernel: 0x80000000 */ 135 /* ip, module: 0xc0000000, kernel: 0x80000000 */
103 new = (ip & 0x40000000) ? lui_v1 : jal_mcount; 136 new = in_module(ip) ? insn_lui_v1_hi16_mcount : insn_jal_ftrace_caller;
104 137
105 return ftrace_modify_code(ip, new); 138 return ftrace_modify_code(ip, new);
106} 139}
@@ -111,44 +144,48 @@ int ftrace_update_ftrace_func(ftrace_func_t func)
111{ 144{
112 unsigned int new; 145 unsigned int new;
113 146
114 new = jump_insn_encode(JAL, (unsigned long)func); 147 new = INSN_JAL((unsigned long)func);
115 148
116 return ftrace_modify_code(FTRACE_CALL_IP, new); 149 return ftrace_modify_code(FTRACE_CALL_IP, new);
117} 150}
118 151
119int __init ftrace_dyn_arch_init(void *data) 152int __init ftrace_dyn_arch_init(void *data)
120{ 153{
154 /* Encode the instructions when booting */
155 ftrace_dyn_arch_init_insns();
156
157 /* Remove "b ftrace_stub" to ensure ftrace_caller() is executed */
158 ftrace_modify_code(MCOUNT_ADDR, INSN_NOP);
159
121 /* The return code is retured via data */ 160 /* The return code is retured via data */
122 *(unsigned long *)data = 0; 161 *(unsigned long *)data = 0;
123 162
124 return 0; 163 return 0;
125} 164}
126#endif /* CONFIG_DYNAMIC_FTRACE */ 165#endif /* CONFIG_DYNAMIC_FTRACE */
127 166
128#ifdef CONFIG_FUNCTION_GRAPH_TRACER 167#ifdef CONFIG_FUNCTION_GRAPH_TRACER
129 168
130#ifdef CONFIG_DYNAMIC_FTRACE 169#ifdef CONFIG_DYNAMIC_FTRACE
131 170
132extern void ftrace_graph_call(void); 171extern void ftrace_graph_call(void);
133#define JMP 0x08000000 /* jump to target directly */
134#define CALL_FTRACE_GRAPH_CALLER \
135 jump_insn_encode(JMP, (unsigned long)(&ftrace_graph_caller))
136#define FTRACE_GRAPH_CALL_IP ((unsigned long)(&ftrace_graph_call)) 172#define FTRACE_GRAPH_CALL_IP ((unsigned long)(&ftrace_graph_call))
137 173
138int ftrace_enable_ftrace_graph_caller(void) 174int ftrace_enable_ftrace_graph_caller(void)
139{ 175{
140 return ftrace_modify_code(FTRACE_GRAPH_CALL_IP, 176 return ftrace_modify_code(FTRACE_GRAPH_CALL_IP,
141 CALL_FTRACE_GRAPH_CALLER); 177 insn_j_ftrace_graph_caller);
142} 178}
143 179
144int ftrace_disable_ftrace_graph_caller(void) 180int ftrace_disable_ftrace_graph_caller(void)
145{ 181{
146 return ftrace_modify_code(FTRACE_GRAPH_CALL_IP, ftrace_nop); 182 return ftrace_modify_code(FTRACE_GRAPH_CALL_IP, INSN_NOP);
147} 183}
148 184
149#endif /* !CONFIG_DYNAMIC_FTRACE */ 185#endif /* CONFIG_DYNAMIC_FTRACE */
150 186
151#ifndef KBUILD_MCOUNT_RA_ADDRESS 187#ifndef KBUILD_MCOUNT_RA_ADDRESS
188
152#define S_RA_SP (0xafbf << 16) /* s{d,w} ra, offset(sp) */ 189#define S_RA_SP (0xafbf << 16) /* s{d,w} ra, offset(sp) */
153#define S_R_SP (0xafb0 << 16) /* s{d,w} R, offset(sp) */ 190#define S_R_SP (0xafb0 << 16) /* s{d,w} R, offset(sp) */
154#define OFFSET_MASK 0xffff /* stack offset range: 0 ~ PT_SIZE */ 191#define OFFSET_MASK 0xffff /* stack offset range: 0 ~ PT_SIZE */
@@ -162,17 +199,17 @@ unsigned long ftrace_get_parent_addr(unsigned long self_addr,
162 unsigned int code; 199 unsigned int code;
163 int faulted; 200 int faulted;
164 201
165 /* in module or kernel? */ 202 /*
166 if (self_addr & 0x40000000) { 203 * For module, move the ip from calling site of mcount to the
167 /* module: move to the instruction "lui v1, HI_16BIT_OF_MCOUNT" */ 204 * instruction "lui v1, hi_16bit_of_mcount"(offset is 20), but for
168 ip = self_addr - 20; 205 * kernel, move to the instruction "move ra, at"(offset is 12)
169 } else { 206 */
170 /* kernel: move to the instruction "move ra, at" */ 207 ip = self_addr - (in_module(self_addr) ? 20 : 12);
171 ip = self_addr - 12;
172 }
173 208
174 /* search the text until finding the non-store instruction or "s{d,w} 209 /*
175 * ra, offset(sp)" instruction */ 210 * search the text until finding the non-store instruction or "s{d,w}
211 * ra, offset(sp)" instruction
212 */
176 do { 213 do {
177 ip -= 4; 214 ip -= 4;
178 215
@@ -181,10 +218,11 @@ unsigned long ftrace_get_parent_addr(unsigned long self_addr,
181 218
182 if (unlikely(faulted)) 219 if (unlikely(faulted))
183 return 0; 220 return 0;
184 221 /*
185 /* If we hit the non-store instruction before finding where the 222 * If we hit the non-store instruction before finding where the
186 * ra is stored, then this is a leaf function and it does not 223 * ra is stored, then this is a leaf function and it does not
187 * store the ra on the stack. */ 224 * store the ra on the stack
225 */
188 if ((code & S_R_SP) != S_R_SP) 226 if ((code & S_R_SP) != S_R_SP)
189 return parent_addr; 227 return parent_addr;
190 228
@@ -202,7 +240,7 @@ unsigned long ftrace_get_parent_addr(unsigned long self_addr,
202 return 0; 240 return 0;
203} 241}
204 242
205#endif 243#endif /* !KBUILD_MCOUNT_RA_ADDRESS */
206 244
207/* 245/*
208 * Hook the return address and push it in the stack of return addrs 246 * 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,
220 if (unlikely(atomic_read(&current->tracing_graph_pause))) 258 if (unlikely(atomic_read(&current->tracing_graph_pause)))
221 return; 259 return;
222 260
223 /* "parent" is the stack address saved the return address of the caller 261 /*
262 * "parent" is the stack address saved the return address of the caller
224 * of _mcount. 263 * of _mcount.
225 * 264 *
226 * if the gcc < 4.5, a leaf function does not save the return address 265 * 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,
242 goto out; 281 goto out;
243#ifndef KBUILD_MCOUNT_RA_ADDRESS 282#ifndef KBUILD_MCOUNT_RA_ADDRESS
244 parent = (unsigned long *)ftrace_get_parent_addr(self_addr, old, 283 parent = (unsigned long *)ftrace_get_parent_addr(self_addr, old,
245 (unsigned long)parent, 284 (unsigned long)parent, fp);
246 fp); 285 /*
247 /* If fails when getting the stack address of the non-leaf function's 286 * If fails when getting the stack address of the non-leaf function's
248 * ra, stop function graph tracer and return */ 287 * ra, stop function graph tracer and return
288 */
249 if (parent == 0) 289 if (parent == 0)
250 goto out; 290 goto out;
251#endif 291#endif
@@ -272,4 +312,4 @@ out:
272 ftrace_graph_stop(); 312 ftrace_graph_stop();
273 WARN_ON(1); 313 WARN_ON(1);
274} 314}
275#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 315#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
diff --git a/arch/mips/kernel/mcount.S b/arch/mips/kernel/mcount.S
index 6851fc97a511..6bfcb7a00ec6 100644
--- a/arch/mips/kernel/mcount.S
+++ b/arch/mips/kernel/mcount.S
@@ -6,6 +6,7 @@
6 * more details. 6 * more details.
7 * 7 *
8 * Copyright (C) 2009 Lemote Inc. & DSLab, Lanzhou University, China 8 * Copyright (C) 2009 Lemote Inc. & DSLab, Lanzhou University, China
9 * Copyright (C) 2010 DSLab, Lanzhou University, China
9 * Author: Wu Zhangjin <wuzhangjin@gmail.com> 10 * Author: Wu Zhangjin <wuzhangjin@gmail.com>
10 */ 11 */
11 12
@@ -45,8 +46,6 @@
45 PTR_L a5, PT_R9(sp) 46 PTR_L a5, PT_R9(sp)
46 PTR_L a6, PT_R10(sp) 47 PTR_L a6, PT_R10(sp)
47 PTR_L a7, PT_R11(sp) 48 PTR_L a7, PT_R11(sp)
48#endif
49#ifdef CONFIG_64BIT
50 PTR_ADDIU sp, PT_SIZE 49 PTR_ADDIU sp, PT_SIZE
51#else 50#else
52 PTR_ADDIU sp, (PT_SIZE + 8) 51 PTR_ADDIU sp, (PT_SIZE + 8)
@@ -58,6 +57,12 @@
58 move ra, AT 57 move ra, AT
59 .endm 58 .endm
60 59
60/*
61 * The -mmcount-ra-address option of gcc 4.5 uses register $12 to pass
62 * the location of the parent's return address.
63 */
64#define MCOUNT_RA_ADDRESS_REG $12
65
61#ifdef CONFIG_DYNAMIC_FTRACE 66#ifdef CONFIG_DYNAMIC_FTRACE
62 67
63NESTED(ftrace_caller, PT_SIZE, ra) 68NESTED(ftrace_caller, PT_SIZE, ra)
@@ -71,14 +76,14 @@ _mcount:
71 76
72 MCOUNT_SAVE_REGS 77 MCOUNT_SAVE_REGS
73#ifdef KBUILD_MCOUNT_RA_ADDRESS 78#ifdef KBUILD_MCOUNT_RA_ADDRESS
74 PTR_S t0, PT_R12(sp) /* t0 saved the location of the return address(at) by -mmcount-ra-address */ 79 PTR_S MCOUNT_RA_ADDRESS_REG, PT_R12(sp)
75#endif 80#endif
76 81
77 move a0, ra /* arg1: next ip, selfaddr */ 82 move a0, ra /* arg1: self return address */
78 .globl ftrace_call 83 .globl ftrace_call
79ftrace_call: 84ftrace_call:
80 nop /* a placeholder for the call to a real tracing function */ 85 nop /* a placeholder for the call to a real tracing function */
81 move a1, AT /* arg2: the caller's next ip, parent */ 86 move a1, AT /* arg2: parent's return address */
82 87
83#ifdef CONFIG_FUNCTION_GRAPH_TRACER 88#ifdef CONFIG_FUNCTION_GRAPH_TRACER
84 .globl ftrace_graph_call 89 .globl ftrace_graph_call
@@ -119,9 +124,9 @@ NESTED(_mcount, PT_SIZE, ra)
119static_trace: 124static_trace:
120 MCOUNT_SAVE_REGS 125 MCOUNT_SAVE_REGS
121 126
122 move a0, ra /* arg1: next ip, selfaddr */ 127 move a0, ra /* arg1: self return address */
123 jalr t2 /* (1) call *ftrace_trace_function */ 128 jalr t2 /* (1) call *ftrace_trace_function */
124 move a1, AT /* arg2: the caller's next ip, parent */ 129 move a1, AT /* arg2: parent's return address */
125 130
126 MCOUNT_RESTORE_REGS 131 MCOUNT_RESTORE_REGS
127 .globl ftrace_stub 132 .globl ftrace_stub
@@ -134,28 +139,34 @@ ftrace_stub:
134#ifdef CONFIG_FUNCTION_GRAPH_TRACER 139#ifdef CONFIG_FUNCTION_GRAPH_TRACER
135 140
136NESTED(ftrace_graph_caller, PT_SIZE, ra) 141NESTED(ftrace_graph_caller, PT_SIZE, ra)
137#ifdef CONFIG_DYNAMIC_FTRACE 142#ifndef CONFIG_DYNAMIC_FTRACE
138 PTR_L a1, PT_R31(sp) /* load the original ra from the stack */
139#ifdef KBUILD_MCOUNT_RA_ADDRESS
140 PTR_L t0, PT_R12(sp) /* load the original t0 from the stack */
141#endif
142#else
143 MCOUNT_SAVE_REGS 143 MCOUNT_SAVE_REGS
144 move a1, ra /* arg2: next ip, selfaddr */
145#endif 144#endif
146 145
146 /* arg1: Get the location of the parent's return address */
147#ifdef KBUILD_MCOUNT_RA_ADDRESS 147#ifdef KBUILD_MCOUNT_RA_ADDRESS
148 bnez t0, 1f /* non-leaf func: t0 saved the location of the return address */ 148#ifdef CONFIG_DYNAMIC_FTRACE
149 PTR_L a0, PT_R12(sp)
150#else
151 move a0, MCOUNT_RA_ADDRESS_REG
152#endif
153 bnez a0, 1f /* non-leaf func: stored in MCOUNT_RA_ADDRESS_REG */
149 nop 154 nop
150 PTR_LA t0, PT_R1(sp) /* leaf func: get the location of at(old ra) from our own stack */ 155#endif
1511: move a0, t0 /* arg1: the location of the return address */ 156 PTR_LA a0, PT_R1(sp) /* leaf func: the location in current stack */
1571:
158
159 /* arg2: Get self return address */
160#ifdef CONFIG_DYNAMIC_FTRACE
161 PTR_L a1, PT_R31(sp)
152#else 162#else
153 PTR_LA a0, PT_R1(sp) /* arg1: &AT -> a0 */ 163 move a1, ra
154#endif 164#endif
155 jal prepare_ftrace_return 165
166 /* arg3: Get frame pointer of current stack */
156#ifdef CONFIG_FRAME_POINTER 167#ifdef CONFIG_FRAME_POINTER
157 move a2, fp /* arg3: frame pointer */ 168 move a2, fp
158#else 169#else /* ! CONFIG_FRAME_POINTER */
159#ifdef CONFIG_64BIT 170#ifdef CONFIG_64BIT
160 PTR_LA a2, PT_SIZE(sp) 171 PTR_LA a2, PT_SIZE(sp)
161#else 172#else
@@ -163,6 +174,8 @@ NESTED(ftrace_graph_caller, PT_SIZE, ra)
163#endif 174#endif
164#endif 175#endif
165 176
177 jal prepare_ftrace_return
178 nop
166 MCOUNT_RESTORE_REGS 179 MCOUNT_RESTORE_REGS
167 RETURN_BACK 180 RETURN_BACK
168 END(ftrace_graph_caller) 181 END(ftrace_graph_caller)
diff --git a/arch/mips/kernel/mips-mt-fpaff.c b/arch/mips/kernel/mips-mt-fpaff.c
index f5981c499109..2340f11dc29c 100644
--- a/arch/mips/kernel/mips-mt-fpaff.c
+++ b/arch/mips/kernel/mips-mt-fpaff.c
@@ -3,6 +3,7 @@
3 * Copyright (C) 2005 Mips Technologies, Inc 3 * Copyright (C) 2005 Mips Technologies, Inc
4 */ 4 */
5#include <linux/cpu.h> 5#include <linux/cpu.h>
6#include <linux/cpuset.h>
6#include <linux/cpumask.h> 7#include <linux/cpumask.h>
7#include <linux/delay.h> 8#include <linux/delay.h>
8#include <linux/kernel.h> 9#include <linux/kernel.h>
@@ -39,6 +40,21 @@ static inline struct task_struct *find_process_by_pid(pid_t pid)
39 return pid ? find_task_by_vpid(pid) : current; 40 return pid ? find_task_by_vpid(pid) : current;
40} 41}
41 42
43/*
44 * check the target process has a UID that matches the current process's
45 */
46static bool check_same_owner(struct task_struct *p)
47{
48 const struct cred *cred = current_cred(), *pcred;
49 bool match;
50
51 rcu_read_lock();
52 pcred = __task_cred(p);
53 match = (cred->euid == pcred->euid ||
54 cred->euid == pcred->uid);
55 rcu_read_unlock();
56 return match;
57}
42 58
43/* 59/*
44 * mipsmt_sys_sched_setaffinity - set the cpu affinity of a process 60 * 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)
46asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len, 62asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len,
47 unsigned long __user *user_mask_ptr) 63 unsigned long __user *user_mask_ptr)
48{ 64{
49 cpumask_t new_mask; 65 cpumask_var_t cpus_allowed, new_mask, effective_mask;
50 cpumask_t effective_mask;
51 int retval;
52 struct task_struct *p;
53 struct thread_info *ti; 66 struct thread_info *ti;
54 uid_t euid; 67 struct task_struct *p;
68 int retval;
55 69
56 if (len < sizeof(new_mask)) 70 if (len < sizeof(new_mask))
57 return -EINVAL; 71 return -EINVAL;
@@ -60,53 +74,74 @@ asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len,
60 return -EFAULT; 74 return -EFAULT;
61 75
62 get_online_cpus(); 76 get_online_cpus();
63 read_lock(&tasklist_lock); 77 rcu_read_lock();
64 78
65 p = find_process_by_pid(pid); 79 p = find_process_by_pid(pid);
66 if (!p) { 80 if (!p) {
67 read_unlock(&tasklist_lock); 81 rcu_read_unlock();
68 put_online_cpus(); 82 put_online_cpus();
69 return -ESRCH; 83 return -ESRCH;
70 } 84 }
71 85
72 /* 86 /* Prevent p going away */
73 * It is not safe to call set_cpus_allowed with the
74 * tasklist_lock held. We will bump the task_struct's
75 * usage count and drop tasklist_lock before invoking
76 * set_cpus_allowed.
77 */
78 get_task_struct(p); 87 get_task_struct(p);
88 rcu_read_unlock();
79 89
80 euid = current_euid(); 90 if (!alloc_cpumask_var(&cpus_allowed, GFP_KERNEL)) {
91 retval = -ENOMEM;
92 goto out_put_task;
93 }
94 if (!alloc_cpumask_var(&new_mask, GFP_KERNEL)) {
95 retval = -ENOMEM;
96 goto out_free_cpus_allowed;
97 }
98 if (!alloc_cpumask_var(&effective_mask, GFP_KERNEL)) {
99 retval = -ENOMEM;
100 goto out_free_new_mask;
101 }
81 retval = -EPERM; 102 retval = -EPERM;
82 if (euid != p->cred->euid && euid != p->cred->uid && 103 if (!check_same_owner(p) && !capable(CAP_SYS_NICE))
83 !capable(CAP_SYS_NICE)) {
84 read_unlock(&tasklist_lock);
85 goto out_unlock; 104 goto out_unlock;
86 }
87 105
88 retval = security_task_setscheduler(p, 0, NULL); 106 retval = security_task_setscheduler(p, 0, NULL);
89 if (retval) 107 if (retval)
90 goto out_unlock; 108 goto out_unlock;
91 109
92 /* Record new user-specified CPU set for future reference */ 110 /* Record new user-specified CPU set for future reference */
93 p->thread.user_cpus_allowed = new_mask; 111 cpumask_copy(&p->thread.user_cpus_allowed, new_mask);
94
95 /* Unlock the task list */
96 read_unlock(&tasklist_lock);
97 112
113 again:
98 /* Compute new global allowed CPU set if necessary */ 114 /* Compute new global allowed CPU set if necessary */
99 ti = task_thread_info(p); 115 ti = task_thread_info(p);
100 if (test_ti_thread_flag(ti, TIF_FPUBOUND) && 116 if (test_ti_thread_flag(ti, TIF_FPUBOUND) &&
101 cpus_intersects(new_mask, mt_fpu_cpumask)) { 117 cpus_intersects(*new_mask, mt_fpu_cpumask)) {
102 cpus_and(effective_mask, new_mask, mt_fpu_cpumask); 118 cpus_and(*effective_mask, *new_mask, mt_fpu_cpumask);
103 retval = set_cpus_allowed_ptr(p, &effective_mask); 119 retval = set_cpus_allowed_ptr(p, effective_mask);
104 } else { 120 } else {
121 cpumask_copy(effective_mask, new_mask);
105 clear_ti_thread_flag(ti, TIF_FPUBOUND); 122 clear_ti_thread_flag(ti, TIF_FPUBOUND);
106 retval = set_cpus_allowed_ptr(p, &new_mask); 123 retval = set_cpus_allowed_ptr(p, new_mask);
107 } 124 }
108 125
126 if (!retval) {
127 cpuset_cpus_allowed(p, cpus_allowed);
128 if (!cpumask_subset(effective_mask, cpus_allowed)) {
129 /*
130 * We must have raced with a concurrent cpuset
131 * update. Just reset the cpus_allowed to the
132 * cpuset's cpus_allowed
133 */
134 cpumask_copy(new_mask, cpus_allowed);
135 goto again;
136 }
137 }
109out_unlock: 138out_unlock:
139 free_cpumask_var(effective_mask);
140out_free_new_mask:
141 free_cpumask_var(new_mask);
142out_free_cpus_allowed:
143 free_cpumask_var(cpus_allowed);
144out_put_task:
110 put_task_struct(p); 145 put_task_struct(p);
111 put_online_cpus(); 146 put_online_cpus();
112 return retval; 147 return retval;
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 8bdd6a663c7f..852780868fb4 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)
976 976
977 case 2: 977 case 2:
978 raw_notifier_call_chain(&cu2_chain, CU2_EXCEPTION, regs); 978 raw_notifier_call_chain(&cu2_chain, CU2_EXCEPTION, regs);
979 break; 979 return;
980 980
981 case 3: 981 case 3:
982 break; 982 break;
diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig
index 3df1967dea08..c97ca69b94e0 100644
--- a/arch/mips/loongson/Kconfig
+++ b/arch/mips/loongson/Kconfig
@@ -23,6 +23,7 @@ config LEMOTE_FULOONG2E
23 select GENERIC_HARDIRQS_NO__DO_IRQ 23 select GENERIC_HARDIRQS_NO__DO_IRQ
24 select GENERIC_ISA_DMA_SUPPORT_BROKEN 24 select GENERIC_ISA_DMA_SUPPORT_BROKEN
25 select CPU_HAS_WB 25 select CPU_HAS_WB
26 select LOONGSON_MC146818
26 help 27 help
27 Lemote Fuloong(2e) mini-PC board based on the Chinese Loongson-2E CPU and 28 Lemote Fuloong(2e) mini-PC board based on the Chinese Loongson-2E CPU and
28 an FPGA northbridge 29 an FPGA northbridge
@@ -51,6 +52,7 @@ config LEMOTE_MACH2F
51 select SYS_SUPPORTS_64BIT_KERNEL 52 select SYS_SUPPORTS_64BIT_KERNEL
52 select SYS_SUPPORTS_HIGHMEM 53 select SYS_SUPPORTS_HIGHMEM
53 select SYS_SUPPORTS_LITTLE_ENDIAN 54 select SYS_SUPPORTS_LITTLE_ENDIAN
55 select LOONGSON_MC146818
54 help 56 help
55 Lemote Loongson 2F family machines utilize the 2F revision of 57 Lemote Loongson 2F family machines utilize the 2F revision of
56 Loongson processor and the AMD CS5536 south bridge. 58 Loongson processor and the AMD CS5536 south bridge.
@@ -83,3 +85,7 @@ config LOONGSON_UART_BASE
83 bool 85 bool
84 default y 86 default y
85 depends on EARLY_PRINTK || SERIAL_8250 87 depends on EARLY_PRINTK || SERIAL_8250
88
89config LOONGSON_MC146818
90 bool
91 default n
diff --git a/arch/mips/loongson/common/Makefile b/arch/mips/loongson/common/Makefile
index cdd2e812ba1a..e526488df655 100644
--- a/arch/mips/loongson/common/Makefile
+++ b/arch/mips/loongson/common/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_GENERIC_GPIO) += gpio.o
12obj-$(CONFIG_EARLY_PRINTK) += early_printk.o 12obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
13obj-$(CONFIG_SERIAL_8250) += serial.o 13obj-$(CONFIG_SERIAL_8250) += serial.o
14obj-$(CONFIG_LOONGSON_UART_BASE) += uart_base.o 14obj-$(CONFIG_LOONGSON_UART_BASE) += uart_base.o
15obj-$(CONFIG_LOONGSON_MC146818) += rtc.o
15 16
16# 17#
17# Enable CS5536 Virtual Support Module(VSM) to virtulize the PCI configure 18# 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 eaf8b86e3318..5b5cbba699b3 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)
49 lo |= SOFT_BAR_EHCI_FLAG; 49 lo |= SOFT_BAR_EHCI_FLAG;
50 _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); 50 _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
51 } else if ((value & 0x01) == 0x00) { 51 } else if ((value & 0x01) == 0x00) {
52 _rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo);
53 lo = value;
52 _wrmsr(USB_MSR_REG(USB_EHCI), hi, lo); 54 _wrmsr(USB_MSR_REG(USB_EHCI), hi, lo);
53 55
54 value &= 0xfffffff0; 56 value &= 0xfffffff0;
diff --git a/arch/mips/loongson/common/cs5536/cs5536_ide.c b/arch/mips/loongson/common/cs5536/cs5536_ide.c
index 9a96b5664c78..681d1291a2c7 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)
51 lo |= SOFT_BAR_IDE_FLAG; 51 lo |= SOFT_BAR_IDE_FLAG;
52 _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); 52 _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
53 } else if (value & 0x01) { 53 } else if (value & 0x01) {
54 _rdmsr(IDE_MSR_REG(IDE_IO_BAR), &hi, &lo);
54 lo = (value & 0xfffffff0) | 0x1; 55 lo = (value & 0xfffffff0) | 0x1;
55 _wrmsr(IDE_MSR_REG(IDE_IO_BAR), hi, lo); 56 _wrmsr(IDE_MSR_REG(IDE_IO_BAR), hi, lo);
56 57
@@ -65,19 +66,30 @@ void pci_ide_write_reg(int reg, u32 value)
65 _rdmsr(DIVIL_MSR_REG(DIVIL_BALL_OPTS), &hi, &lo); 66 _rdmsr(DIVIL_MSR_REG(DIVIL_BALL_OPTS), &hi, &lo);
66 lo |= 0x01; 67 lo |= 0x01;
67 _wrmsr(DIVIL_MSR_REG(DIVIL_BALL_OPTS), hi, lo); 68 _wrmsr(DIVIL_MSR_REG(DIVIL_BALL_OPTS), hi, lo);
68 } else 69 } else {
70 _rdmsr(IDE_MSR_REG(IDE_CFG), &hi, &lo);
71 lo = value;
69 _wrmsr(IDE_MSR_REG(IDE_CFG), hi, lo); 72 _wrmsr(IDE_MSR_REG(IDE_CFG), hi, lo);
73 }
70 break; 74 break;
71 case PCI_IDE_DTC_REG: 75 case PCI_IDE_DTC_REG:
76 _rdmsr(IDE_MSR_REG(IDE_DTC), &hi, &lo);
77 lo = value;
72 _wrmsr(IDE_MSR_REG(IDE_DTC), hi, lo); 78 _wrmsr(IDE_MSR_REG(IDE_DTC), hi, lo);
73 break; 79 break;
74 case PCI_IDE_CAST_REG: 80 case PCI_IDE_CAST_REG:
81 _rdmsr(IDE_MSR_REG(IDE_CAST), &hi, &lo);
82 lo = value;
75 _wrmsr(IDE_MSR_REG(IDE_CAST), hi, lo); 83 _wrmsr(IDE_MSR_REG(IDE_CAST), hi, lo);
76 break; 84 break;
77 case PCI_IDE_ETC_REG: 85 case PCI_IDE_ETC_REG:
86 _rdmsr(IDE_MSR_REG(IDE_ETC), &hi, &lo);
87 lo = value;
78 _wrmsr(IDE_MSR_REG(IDE_ETC), hi, lo); 88 _wrmsr(IDE_MSR_REG(IDE_ETC), hi, lo);
79 break; 89 break;
80 case PCI_IDE_PM_REG: 90 case PCI_IDE_PM_REG:
91 _rdmsr(IDE_MSR_REG(IDE_INTERNAL_PM), &hi, &lo);
92 lo = value;
81 _wrmsr(IDE_MSR_REG(IDE_INTERNAL_PM), hi, lo); 93 _wrmsr(IDE_MSR_REG(IDE_INTERNAL_PM), hi, lo);
82 break; 94 break;
83 default: 95 default:
@@ -167,6 +179,7 @@ u32 pci_ide_read_reg(int reg)
167 case PCI_IDE_ETC_REG: 179 case PCI_IDE_ETC_REG:
168 _rdmsr(IDE_MSR_REG(IDE_ETC), &hi, &lo); 180 _rdmsr(IDE_MSR_REG(IDE_ETC), &hi, &lo);
169 conf_data = lo; 181 conf_data = lo;
182 break;
170 case PCI_IDE_PM_REG: 183 case PCI_IDE_PM_REG:
171 _rdmsr(IDE_MSR_REG(IDE_INTERNAL_PM), &hi, &lo); 184 _rdmsr(IDE_MSR_REG(IDE_INTERNAL_PM), &hi, &lo);
172 conf_data = lo; 185 conf_data = lo;
diff --git a/arch/mips/loongson/common/cs5536/cs5536_isa.c b/arch/mips/loongson/common/cs5536/cs5536_isa.c
index f5c0818831b2..4d9f65abeaff 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)
61 for (offset = DIVIL_LBAR_SMB; offset <= DIVIL_LBAR_PMS; offset++) { 61 for (offset = DIVIL_LBAR_SMB; offset <= DIVIL_LBAR_PMS; offset++) {
62 _rdmsr(DIVIL_MSR_REG(offset), &hi, &lo); 62 _rdmsr(DIVIL_MSR_REG(offset), &hi, &lo);
63 hi |= 0x01; 63 hi |= 0x01;
64 _wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_SMB), hi, lo); 64 _wrmsr(DIVIL_MSR_REG(offset), hi, lo);
65 } 65 }
66} 66}
67 67
@@ -76,7 +76,7 @@ static void divil_lbar_disable(void)
76 for (offset = DIVIL_LBAR_SMB; offset <= DIVIL_LBAR_PMS; offset++) { 76 for (offset = DIVIL_LBAR_SMB; offset <= DIVIL_LBAR_PMS; offset++) {
77 _rdmsr(DIVIL_MSR_REG(offset), &hi, &lo); 77 _rdmsr(DIVIL_MSR_REG(offset), &hi, &lo);
78 hi &= ~0x01; 78 hi &= ~0x01;
79 _wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_SMB), hi, lo); 79 _wrmsr(DIVIL_MSR_REG(offset), hi, lo);
80 } 80 }
81} 81}
82 82
diff --git a/arch/mips/loongson/common/cs5536/cs5536_ohci.c b/arch/mips/loongson/common/cs5536/cs5536_ohci.c
index db5900aadd6b..bdedf512baf7 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)
49 lo |= SOFT_BAR_OHCI_FLAG; 49 lo |= SOFT_BAR_OHCI_FLAG;
50 _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); 50 _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
51 } else if ((value & 0x01) == 0x00) { 51 } else if ((value & 0x01) == 0x00) {
52 _rdmsr(USB_MSR_REG(USB_OHCI), &hi, &lo);
53 lo = value;
52 _wrmsr(USB_MSR_REG(USB_OHCI), hi, lo); 54 _wrmsr(USB_MSR_REG(USB_OHCI), hi, lo);
53 55
54 value &= 0xfffffff0; 56 value &= 0xfffffff0;
diff --git a/arch/mips/loongson/common/rtc.c b/arch/mips/loongson/common/rtc.c
new file mode 100644
index 000000000000..a90d87c01555
--- /dev/null
+++ b/arch/mips/loongson/common/rtc.c
@@ -0,0 +1,43 @@
1/*
2 * Lemote Fuloong platform support
3 *
4 * Copyright(c) 2010 Arnaud Patard <apatard@mandriva.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#include <linux/init.h>
13#include <linux/kernel.h>
14#include <linux/platform_device.h>
15#include <linux/mc146818rtc.h>
16
17struct resource loongson_rtc_resources[] = {
18 {
19 .start = RTC_PORT(0),
20 .end = RTC_PORT(1),
21 .flags = IORESOURCE_IO,
22 }, {
23 .start = RTC_IRQ,
24 .end = RTC_IRQ,
25 .flags = IORESOURCE_IRQ,
26 }
27};
28
29static struct platform_device loongson_rtc_device = {
30 .name = "rtc_cmos",
31 .id = -1,
32 .resource = loongson_rtc_resources,
33 .num_resources = ARRAY_SIZE(loongson_rtc_resources),
34};
35
36
37static int __init loongson_rtc_platform_init(void)
38{
39 platform_device_register(&loongson_rtc_device);
40 return 0;
41}
42
43device_initcall(loongson_rtc_platform_init);
diff --git a/arch/mips/math-emu/dp_simple.c b/arch/mips/math-emu/dp_simple.c
index d9ae1dbabda7..b90974246e5b 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)
78 DPSIGN(x) = 0; 78 DPSIGN(x) = 0;
79 79
80 if (xc == IEEE754_CLASS_SNAN) { 80 if (xc == IEEE754_CLASS_SNAN) {
81 SETCX(IEEE754_INVALID_OPERATION);
81 return ieee754dp_nanxcpt(ieee754dp_indef(), "abs"); 82 return ieee754dp_nanxcpt(ieee754dp_indef(), "abs");
82 } 83 }
83 84
diff --git a/arch/mips/math-emu/sp_simple.c b/arch/mips/math-emu/sp_simple.c
index 3175477d36f6..2fd53c920e99 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)
78 SPSIGN(x) = 0; 78 SPSIGN(x) = 0;
79 79
80 if (xc == IEEE754_CLASS_SNAN) { 80 if (xc == IEEE754_CLASS_SNAN) {
81 SETCX(IEEE754_INVALID_OPERATION);
81 return ieee754sp_nanxcpt(ieee754sp_indef(), "abs"); 82 return ieee754sp_nanxcpt(ieee754sp_indef(), "abs");
82 } 83 }
83 84
diff --git a/arch/mips/oprofile/op_model_loongson2.c b/arch/mips/oprofile/op_model_loongson2.c
index d0d24e047676..60d3ea602118 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 {
43static char *oprofid = "LoongsonPerf"; 43static char *oprofid = "LoongsonPerf";
44static irqreturn_t loongson2_perfcount_handler(int irq, void *dev_id); 44static irqreturn_t loongson2_perfcount_handler(int irq, void *dev_id);
45 45
46static void reset_counters(void *arg)
47{
48 write_c0_perfctrl(0);
49 write_c0_perfcnt(0);
50}
51
46static void loongson2_reg_setup(struct op_counter_config *cfg) 52static void loongson2_reg_setup(struct op_counter_config *cfg)
47{ 53{
48 unsigned int ctrl = 0; 54 unsigned int ctrl = 0;
@@ -139,7 +145,7 @@ static int __init loongson2_init(void)
139 145
140static void loongson2_exit(void) 146static void loongson2_exit(void)
141{ 147{
142 write_c0_perfctrl(0); 148 reset_counters(NULL);
143 free_irq(LOONGSON2_PERFCNT_IRQ, oprofid); 149 free_irq(LOONGSON2_PERFCNT_IRQ, oprofid);
144} 150}
145 151