Merge branch 'urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/brodo/pcmcia-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 7 Jul 2010 00:14:53 +0000 (17:14 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 7 Jul 2010 00:14:53 +0000 (17:14 -0700)
* 'urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/brodo/pcmcia-2.6:
  pcmcia: do not initialize the present flag too late.

26 files changed:
Makefile
arch/mips/alchemy/common/power.c
arch/mips/alchemy/common/sleeper.S
arch/mips/ar7/platform.c
arch/mips/bcm47xx/Makefile
arch/mips/bcm47xx/nvram.c [new file with mode: 0644]
arch/mips/bcm47xx/setup.c
arch/mips/include/asm/mach-ar7/ar7.h
arch/mips/include/asm/mach-ar7/gpio.h
arch/mips/include/asm/mach-au1x00/au1000.h
arch/mips/include/asm/mach-bcm47xx/nvram.h [new file with mode: 0644]
arch/mips/include/asm/mach-bcm63xx/gpio.h
arch/mips/kernel/ftrace.c
arch/mips/kernel/mcount.S
arch/mips/kernel/mips-mt-fpaff.c
arch/mips/kernel/traps.c
arch/mips/loongson/Kconfig
arch/mips/loongson/common/Makefile
arch/mips/loongson/common/cs5536/cs5536_ehci.c
arch/mips/loongson/common/cs5536/cs5536_ide.c
arch/mips/loongson/common/cs5536/cs5536_isa.c
arch/mips/loongson/common/cs5536/cs5536_ohci.c
arch/mips/loongson/common/rtc.c [new file with mode: 0644]
arch/mips/math-emu/dp_simple.c
arch/mips/math-emu/sp_simple.c
arch/mips/oprofile/op_model_loongson2.c

index 914e5f5..f9835c8 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -886,7 +886,7 @@ $(vmlinux-dirs): prepare scripts
 # Store (new) KERNELRELASE string in include/config/kernel.release
 include/config/kernel.release: include/config/auto.conf FORCE
        $(Q)rm -f $@
-       $(Q)echo "$(KERNELVERSION)$$($(CONFIG_SHELL) scripts/setlocalversion $(srctree))" > $@
+       $(Q)echo "$(KERNELVERSION)$$($(CONFIG_SHELL) $(srctree)/scripts/setlocalversion $(srctree))" > $@
 
 
 # Things we need to do before we recursively start building the kernel
index 14eb8c4..5ef06a1 100644 (file)
@@ -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 */
index 4f4b167..77f3c74 100644 (file)
        .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)
index 566f2d7..8f31d1d 100644 (file)
@@ -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;
index 35294b1..7465e8a 100644 (file)
@@ -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 (file)
index 0000000..06e03b2
--- /dev/null
@@ -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);
index d442e11..b1aee33 100644 (file)
@@ -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;
index f1cf389..483ffea 100644 (file)
@@ -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);
 }
index 73f9b16..abc317c 100644 (file)
@@ -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
index e76941d..a697661 100644 (file)
@@ -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 (file)
index 0000000..0d8cc14
--- /dev/null
@@ -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
index 7cda8c0..1eb534d 100644 (file)
@@ -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
index e9e64e0..5a84a1f 100644 (file)
@@ -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.
 #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 */
index 6851fc9..6bfcb7a 100644 (file)
@@ -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)
         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)
index f5981c4..2340f11 100644 (file)
@@ -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;
index 8bdd6a6..8527808 100644 (file)
@@ -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;
index 3df1967..c97ca69 100644 (file)
@@ -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
index cdd2e81..e526488 100644 (file)
@@ -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
index eaf8b86..5b5cbba 100644 (file)
@@ -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;
index 9a96b56..681d129 100644 (file)
@@ -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;
index f5c0818..4d9f65a 100644 (file)
@@ -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);
        }
 }
 
index db5900a..bdedf51 100644 (file)
@@ -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 (file)
index 0000000..a90d87c
--- /dev/null
@@ -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);
index d9ae1db..b909742 100644 (file)
@@ -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");
        }
 
index 3175477..2fd53c9 100644 (file)
@@ -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");
        }
 
index d0d24e0..60d3ea6 100644 (file)
@@ -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);
 }