Submitted By: Jim Gifford (patches at jg555 dot com) Date: 2006-11-20 Initial Package Version: 2.6.18.3 Origin: Linux-MIPS Upstream Status: http://www.linux-mips.org/pub/linux/mips/kernel/v2.6/ diff -Naur linux-2.6.18.3/Documentation/mips/time.README linux-mips-2.6.18.3/Documentation/mips/time.README --- linux-2.6.18.3/Documentation/mips/time.README 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/Documentation/mips/time.README 2006-11-20 10:09:08.000000000 -0800 @@ -63,7 +63,7 @@ a) board_time_init - a function pointer. Invoked at the beginnig of time_init(). It is optional. 1. (optional) set up RTC routines - 2. (optional) calibrate and set the mips_counter_frequency + 2. (optional) calibrate and set the mips_hpt_frequency b) plat_timer_setup - a function pointer. Invoked at the end of time_init() 1. (optional) over-ride any decisions made in time_init() @@ -72,7 +72,7 @@ c) (optional) board-specific RTC routines. - d) (optional) mips_counter_frequency - It must be definied if the board + d) (optional) mips_hpt_frequency - It must be definied if the board is using CPU counter for timer interrupt or it is using fixed rate gettimeoffset(). @@ -104,7 +104,7 @@ or use an exnternal timer? In order to use CPU counter register as the timer interrupt source, you - must know the counter speed (mips_counter_frequency). It is usually the + must know the counter speed (mips_hpt_frequency). It is usually the same as the CPU speed or an integral divisor of it. d) decide on whether you want to use high-level or low-level timer @@ -122,7 +122,7 @@ board_time_init() - a) (optional) set up RTC routines, - b) (optional) calibrate and set the mips_counter_frequency + b) (optional) calibrate and set the mips_hpt_frequency (only needed if you intended to use fixed_rate_gettimeoffset or use cpu counter as timer interrupt source) diff -Naur linux-2.6.18.3/Makefile linux-mips-2.6.18.3/Makefile --- linux-2.6.18.3/Makefile 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/Makefile 2006-11-20 10:09:08.000000000 -0800 @@ -149,10 +149,7 @@ # then ARCH is assigned, getting whatever value it gets normally, and # SUBARCH is subsequently ignored. -SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ - -e s/arm.*/arm/ -e s/sa110/arm/ \ - -e s/s390x/s390/ -e s/parisc64/parisc/ \ - -e s/ppc.*/powerpc/ -e s/mips.*/mips/ ) +SUBARCH := mips # Cross compiling and selecting different set of gcc/bin-utils # --------------------------------------------------------------------------- diff -Naur linux-2.6.18.3/arch/mips/Kconfig linux-mips-2.6.18.3/arch/mips/Kconfig --- linux-2.6.18.3/arch/mips/Kconfig 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/Kconfig 2006-11-20 10:09:08.000000000 -0800 @@ -126,7 +126,6 @@ select IRQ_CPU select IRQ_CPU_RM7K select IRQ_CPU_RM9K - select SERIAL_RM9000 select SYS_HAS_CPU_RM9000 select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_64BIT_KERNEL @@ -478,9 +477,8 @@ select SWAP_IO_SPACE select SYS_HAS_CPU_RM7000 select SYS_SUPPORTS_32BIT_KERNEL - select SYS_SUPPORTS_64BIT_KERNEL + select SYS_SUPPORTS_64BIT_KERNEL if BROKEN select SYS_SUPPORTS_BIG_ENDIAN - select ARCH_SPARSEMEM_ENABLE help The Ocelot is a MIPS-based Single Board Computer (SBC) made by Momentum Computer . @@ -524,8 +522,6 @@ config MACH_VR41XX bool "NEC VR41XX-based machines" select SYS_HAS_CPU_VR41XX - select SYS_SUPPORTS_32BIT_KERNEL - select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL config PMC_YOSEMITE bool "PMC-Sierra Yosemite eval board" @@ -614,6 +610,7 @@ select SYS_SUPPORTS_64BIT_KERNEL select SYS_SUPPORTS_BIG_ENDIAN select SYS_SUPPORTS_NUMA + select SYS_SUPPORTS_SMP help This are the SGI Origin 200, Origin 2000 and Onyx 2 Graphics workstations. To compile a Linux kernel that runs on these, say Y @@ -1200,7 +1197,7 @@ select CPU_SUPPORTS_32BIT_KERNEL select CPU_SUPPORTS_64BIT_KERNEL help - The options selects support for the NEC VR4100 series of processors. + The options selects support for the NEC VR41xx series of processors. Only choose this option if you have one of these processors as a kernel built with this option will not run on any other type of processor or vice versa. @@ -1527,6 +1524,7 @@ select CPU_MIPSR2_SRS select MIPS_MT select SMP + select SYS_SUPPORTS_SMP help This is a kernel model which is known a SMTC or lately has been marketesed into SMVP. @@ -1538,6 +1536,7 @@ select CPU_MIPSR2_SRS select MIPS_MT select SMP + select SYS_SUPPORTS_SMP help This is a kernel model which is also known a VSMP or lately has been marketesed into SMVP. @@ -1649,9 +1648,7 @@ default y config IRQ_PER_CPU - depends on SMP bool - default y # # - Highmem only makes sense for the 32-bit kernel. @@ -1691,9 +1688,6 @@ config ARCH_SPARSEMEM_ENABLE bool - -config ARCH_SPARSEMEM_ENABLE - bool select SPARSEMEM_STATIC config NUMA @@ -1719,6 +1713,7 @@ config SMP bool "Multi-Processing support" depends on SYS_SUPPORTS_SMP + select IRQ_PER_CPU help This enables support for systems with more than one CPU. If you have a system with only one CPU, like most personal computers, say N. If @@ -1973,6 +1968,11 @@ depends on MIPS32_COMPAT default y +config SYSVIPC_COMPAT + bool + depends on COMPAT && SYSVIPC + default y + config MIPS32_O32 bool "Kernel support for o32 binaries" depends on MIPS32_COMPAT diff -Naur linux-2.6.18.3/arch/mips/Makefile linux-mips-2.6.18.3/arch/mips/Makefile --- linux-2.6.18.3/arch/mips/Makefile 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/Makefile 2006-11-20 10:09:08.000000000 -0800 @@ -63,7 +63,9 @@ ifdef CONFIG_BUILD_ELF64 cflags-y += $(call cc-option,-mno-explicit-relocs) else -cflags-y += $(call cc-option,-msym32) +# -msym32 can not be used for modules since they are loaded into XKSEG +CFLAGS_MODULE += $(call cc-option,-mno-explicit-relocs) +CFLAGS_KERNEL += $(call cc-option,-msym32) endif endif @@ -91,8 +93,17 @@ # carefully avoid to add it redundantly because gcc 3.3/3.4 complains # when fed the toolchain default! # -cflags-$(CONFIG_CPU_BIG_ENDIAN) += $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' && echo -EB -D__MIPSEB__) -cflags-$(CONFIG_CPU_LITTLE_ENDIAN) += $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' || echo -EL -D__MIPSEL__) +# Certain gcc versions upto gcc 4.1.1 (probably 4.2-subversion as of +# 2006-10-10 don't properly change the the predefined symbols if -EB / -EL +# are used, so we kludge that here. A bug has been filed at +# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29413. +# +undef-all += -UMIPSEB -U_MIPSEB -U__MIPSEB -U__MIPSEB__ +undef-all += -UMIPSEL -U_MIPSEL -U__MIPSEL -U__MIPSEL__ +predef-be += -DMIPSEB -D_MIPSEB -D__MIPSEB -D__MIPSEB__ +predef-le += -DMIPSEL -D_MIPSEL -D__MIPSEL -D__MIPSEL__ +cflags-$(CONFIG_CPU_BIG_ENDIAN) += $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' && echo -EB $(undef-all) $(predef-be)) +cflags-$(CONFIG_CPU_LITTLE_ENDIAN) += $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' || echo -EL $(undef-all) $(predef-le)) cflags-$(CONFIG_SB1XXX_CORELIS) += $(call cc-option,-mno-sched-prolog) \ -fno-omit-frame-pointer @@ -330,6 +341,7 @@ # MIPS SEAD board # core-$(CONFIG_MIPS_SEAD) += arch/mips/mips-boards/sead/ +cflags-$(CONFIG_MIPS_SEAD) += -Iinclude/asm-mips/mach-mips load-$(CONFIG_MIPS_SEAD) += 0xffffffff80100000 # diff -Naur linux-2.6.18.3/arch/mips/au1000/common/pci.c linux-mips-2.6.18.3/arch/mips/au1000/common/pci.c --- linux-2.6.18.3/arch/mips/au1000/common/pci.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/au1000/common/pci.c 2006-11-20 10:09:08.000000000 -0800 @@ -76,13 +76,17 @@ } #ifdef CONFIG_DMA_NONCOHERENT - /* - * Set the NC bit in controller for Au1500 pre-AC silicon - */ - u32 prid = read_c0_prid(); - if ( (prid & 0xFF000000) == 0x01000000 && prid < 0x01030202) { - au_writel( 1<<16 | au_readl(Au1500_PCI_CFG), Au1500_PCI_CFG); - printk("Non-coherent PCI accesses enabled\n"); + { + /* + * Set the NC bit in controller for Au1500 pre-AC silicon + */ + u32 prid = read_c0_prid(); + + if ((prid & 0xFF000000) == 0x01000000 && prid < 0x01030202) { + au_writel((1 << 16) | au_readl(Au1500_PCI_CFG), + Au1500_PCI_CFG); + printk("Non-coherent PCI accesses enabled\n"); + } } #endif diff -Naur linux-2.6.18.3/arch/mips/au1000/common/setup.c linux-mips-2.6.18.3/arch/mips/au1000/common/setup.c --- linux-2.6.18.3/arch/mips/au1000/common/setup.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/au1000/common/setup.c 2006-11-20 10:09:08.000000000 -0800 @@ -141,17 +141,20 @@ /* This routine should be valid for all Au1x based boards */ phys_t __fixup_bigphys_addr(phys_t phys_addr, phys_t size) { - u32 start, end; - /* Don't fixup 36 bit addresses */ - if ((phys_addr >> 32) != 0) return phys_addr; + if ((phys_addr >> 32) != 0) + return phys_addr; #ifdef CONFIG_PCI - start = (u32)Au1500_PCI_MEM_START; - end = (u32)Au1500_PCI_MEM_END; - /* check for pci memory window */ - if ((phys_addr >= start) && ((phys_addr + size) < end)) { - return (phys_t)((phys_addr - start) + Au1500_PCI_MEM_START); + { + u32 start, end; + + start = (u32)Au1500_PCI_MEM_START; + end = (u32)Au1500_PCI_MEM_END; + /* check for pci memory window */ + if ((phys_addr >= start) && ((phys_addr + size) < end)) + return (phys_t) + ((phys_addr - start) + Au1500_PCI_MEM_START); } #endif diff -Naur linux-2.6.18.3/arch/mips/au1000/db1x00/Makefile linux-mips-2.6.18.3/arch/mips/au1000/db1x00/Makefile --- linux-2.6.18.3/arch/mips/au1000/db1x00/Makefile 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/au1000/db1x00/Makefile 2006-11-20 10:09:08.000000000 -0800 @@ -6,4 +6,3 @@ # Makefile for the Alchemy Semiconductor Db1x00 board. lib-y := init.o board_setup.o irqmap.o -obj-$(CONFIG_WM97XX_COMODULE) += mirage_ts.o diff -Naur linux-2.6.18.3/arch/mips/au1000/db1x00/mirage_ts.c linux-mips-2.6.18.3/arch/mips/au1000/db1x00/mirage_ts.c --- linux-2.6.18.3/arch/mips/au1000/db1x00/mirage_ts.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/au1000/db1x00/mirage_ts.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,260 +0,0 @@ -/* - * linux/arch/mips/au1000/db1x00/mirage_ts.c - * - * BRIEF MODULE DESCRIPTION - * Glue between Mirage board-specific touchscreen pieces - * and generic Wolfson Codec touchscreen support. - * - * Based on pb1100_ts.c used in Hydrogen II. - * - * Copyright (c) 2003 Embedded Edge, LLC - * dan@embeddededge.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. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/* - * Imported interface to Wolfson Codec driver. - */ -extern void *wm97xx_ts_get_handle(int which); -extern int wm97xx_ts_ready(void* ts_handle); -extern void wm97xx_ts_set_cal(void* ts_handle, int xscale, int xtrans, int yscale, int ytrans); -extern u16 wm97xx_ts_get_ac97(void* ts_handle, u8 reg); -extern void wm97xx_ts_set_ac97(void* ts_handle, u8 reg, u16 val); -extern int wm97xx_ts_read_data(void* ts_handle, long* x, long* y, long* pressure); -extern void wm97xx_ts_send_data(void* ts_handle, long x, long y, long z); - -int wm97xx_comodule_present = 1; - - -#define TS_NAME "mirage_ts" - -#define err(format, arg...) printk(KERN_ERR TS_NAME ": " format "\n" , ## arg) -#define info(format, arg...) printk(KERN_INFO TS_NAME ": " format "\n" , ## arg) -#define warn(format, arg...) printk(KERN_WARNING TS_NAME ": " format "\n" , ## arg) -#define DPRINTK(format, arg...) printk("%s: " format "\n", __FUNCTION__ , ## arg) - - -#define PEN_DOWN_IRQ AU1000_GPIO_7 - -static struct task_struct *ts_task = 0; -static DECLARE_COMPLETION(ts_complete); -static DECLARE_WAIT_QUEUE_HEAD(pendown_wait); - -#ifdef CONFIG_WM97XX_FIVEWIRETS -static int release_pressure = 1; -#else -static int release_pressure = 50; -#endif - -typedef struct { - long x; - long y; -} DOWN_EVENT; - -#define SAMPLE_RATE 50 /* samples per second */ -#define PEN_DEBOUNCE 5 /* samples for settling - fn of SAMPLE_RATE */ -#define PEN_UP_TIMEOUT 10 /* in seconds */ -#define PEN_UP_SETTLE 5 /* samples per second */ - -static struct { - int xscale; - int xtrans; - int yscale; - int ytrans; -} mirage_ts_cal = -{ -#if 0 - .xscale = 84, - .xtrans = -157, - .yscale = 66, - .ytrans = -150, -#else - .xscale = 84, - .xtrans = -150, - .yscale = 66, - .ytrans = -146, -#endif -}; - - -static void pendown_irq(int irqnr, void *devid, struct pt_regs *regs) -{ -//DPRINTK("got one 0x%x", au_readl(SYS_PINSTATERD)); - wake_up(&pendown_wait); -} - -static int ts_thread(void *id) -{ - static int pen_was_down = 0; - static DOWN_EVENT pen_xy; - long x, y, z; - void *ts; /* handle */ - struct task_struct *tsk = current; - int timeout = HZ / SAMPLE_RATE; - - ts_task = tsk; - - daemonize(); - tsk->tty = NULL; - tsk->policy = SCHED_FIFO; - tsk->rt_priority = 1; - strcpy(tsk->comm, "touchscreen"); - - /* only want to receive SIGKILL */ - spin_lock_irq(&tsk->sigmask_lock); - siginitsetinv(&tsk->blocked, sigmask(SIGKILL)); - recalc_sigpending(tsk); - spin_unlock_irq(&tsk->sigmask_lock); - - /* get handle for codec */ - ts = wm97xx_ts_get_handle(0); - - /* proceed only after everybody is ready */ - wait_event_timeout(pendown_wait, wm97xx_ts_ready(ts), HZ/4); - - /* board-specific calibration */ - wm97xx_ts_set_cal(ts, - mirage_ts_cal.xscale, - mirage_ts_cal.xtrans, - mirage_ts_cal.yscale, - mirage_ts_cal.ytrans); - - /* route Wolfson pendown interrupts to our GPIO */ - au_sync(); - wm97xx_ts_set_ac97(ts, 0x4c, wm97xx_ts_get_ac97(ts, 0x4c) & ~0x0008); - au_sync(); - wm97xx_ts_set_ac97(ts, 0x56, wm97xx_ts_get_ac97(ts, 0x56) & ~0x0008); - au_sync(); - wm97xx_ts_set_ac97(ts, 0x52, wm97xx_ts_get_ac97(ts, 0x52) | 0x2008); - au_sync(); - - for (;;) { - interruptible_sleep_on_timeout(&pendown_wait, timeout); - disable_irq(PEN_DOWN_IRQ); - if (signal_pending(tsk)) { - break; - } - - /* read codec */ - if (!wm97xx_ts_read_data(ts, &x, &y, &z)) - z = 0; /* treat no-data and pen-up the same */ - - if (signal_pending(tsk)) { - break; - } - - if (z >= release_pressure) { - y = ~y; /* top to bottom */ - if (pen_was_down > 1 /*&& pen_was_down < PEN_DEBOUNCE*/) {//THXXX - /* bounce ? */ - x = pen_xy.x; - y = pen_xy.y; - --pen_was_down; - } else if (pen_was_down <= 1) { - pen_xy.x = x; - pen_xy.y = y; - if (pen_was_down) - wm97xx_ts_send_data(ts, x, y, z); - pen_was_down = PEN_DEBOUNCE; - } - //wm97xx_ts_send_data(ts, x, y, z); - timeout = HZ / SAMPLE_RATE; - } else { - if (pen_was_down) { - if (--pen_was_down) - z = release_pressure; - else //THXXX - wm97xx_ts_send_data(ts, pen_xy.x, pen_xy.y, z); - } - /* The pendown signal takes some time to settle after - * reading the pen pressure so wait a little - * before enabling the pen. - */ - if (! pen_was_down) { -// interruptible_sleep_on_timeout(&pendown_wait, HZ / PEN_UP_SETTLE); - timeout = HZ * PEN_UP_TIMEOUT; - } - } - enable_irq(PEN_DOWN_IRQ); - } - enable_irq(PEN_DOWN_IRQ); - ts_task = NULL; - complete(&ts_complete); - return 0; -} - -static int __init ts_mirage_init(void) -{ - int ret; - - /* pen down signal is connected to GPIO 7 */ - - ret = request_irq(PEN_DOWN_IRQ, pendown_irq, 0, "ts-pendown", NULL); - if (ret) { - err("unable to get pendown irq%d: [%d]", PEN_DOWN_IRQ, ret); - return ret; - } - - lock_kernel(); - ret = kernel_thread(ts_thread, NULL, CLONE_FS | CLONE_FILES); - if (ret < 0) { - unlock_kernel(); - return ret; - } - unlock_kernel(); - - info("Mirage touchscreen IRQ initialized."); - - return 0; -} - -static void __exit ts_mirage_exit(void) -{ - if (ts_task) { - send_sig(SIGKILL, ts_task, 1); - wait_for_completion(&ts_complete); - } - - free_irq(PEN_DOWN_IRQ, NULL); -} - -module_init(ts_mirage_init); -module_exit(ts_mirage_exit); - diff -Naur linux-2.6.18.3/arch/mips/au1000/pb1100/board_setup.c linux-mips-2.6.18.3/arch/mips/au1000/pb1100/board_setup.c --- linux-2.6.18.3/arch/mips/au1000/pb1100/board_setup.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/au1000/pb1100/board_setup.c 2006-11-20 10:09:08.000000000 -0800 @@ -47,8 +47,7 @@ void __init board_setup(void) { - u32 pin_func; - u32 sys_freqctrl, sys_clksrc; + volatile void __iomem * base = (volatile void __iomem *) 0xac000000UL; // set AUX clock to 12MHz * 8 = 96 MHz au_writel(8, SYS_AUXPLL); @@ -56,60 +55,64 @@ udelay(100); #if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE) - // configure pins GPIO[14:9] as GPIO - pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x80); + { + u32 pin_func, sys_freqctrl, sys_clksrc; - /* zero and disable FREQ2 */ - sys_freqctrl = au_readl(SYS_FREQCTRL0); - sys_freqctrl &= ~0xFFF00000; - au_writel(sys_freqctrl, SYS_FREQCTRL0); - - /* zero and disable USBH/USBD/IrDA clock */ - sys_clksrc = au_readl(SYS_CLKSRC); - sys_clksrc &= ~0x0000001F; - au_writel(sys_clksrc, SYS_CLKSRC); - - sys_freqctrl = au_readl(SYS_FREQCTRL0); - sys_freqctrl &= ~0xFFF00000; - - sys_clksrc = au_readl(SYS_CLKSRC); - sys_clksrc &= ~0x0000001F; - - // FREQ2 = aux/2 = 48 MHz - sys_freqctrl |= ((0<<22) | (1<<21) | (1<<20)); - au_writel(sys_freqctrl, SYS_FREQCTRL0); - - /* - * Route 48MHz FREQ2 into USBH/USBD/IrDA - */ - sys_clksrc |= ((4<<2) | (0<<1) | 0 ); - au_writel(sys_clksrc, SYS_CLKSRC); - - /* setup the static bus controller */ - au_writel(0x00000002, MEM_STCFG3); /* type = PCMCIA */ - au_writel(0x280E3D07, MEM_STTIME3); /* 250ns cycle time */ - au_writel(0x10000000, MEM_STADDR3); /* any PCMCIA select */ + // configure pins GPIO[14:9] as GPIO + pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x80); - // get USB Functionality pin state (device vs host drive pins) - pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000); + /* zero and disable FREQ2 */ + sys_freqctrl = au_readl(SYS_FREQCTRL0); + sys_freqctrl &= ~0xFFF00000; + au_writel(sys_freqctrl, SYS_FREQCTRL0); + + /* zero and disable USBH/USBD/IrDA clock */ + sys_clksrc = au_readl(SYS_CLKSRC); + sys_clksrc &= ~0x0000001F; + au_writel(sys_clksrc, SYS_CLKSRC); + + sys_freqctrl = au_readl(SYS_FREQCTRL0); + sys_freqctrl &= ~0xFFF00000; + + sys_clksrc = au_readl(SYS_CLKSRC); + sys_clksrc &= ~0x0000001F; + + // FREQ2 = aux/2 = 48 MHz + sys_freqctrl |= ((0<<22) | (1<<21) | (1<<20)); + au_writel(sys_freqctrl, SYS_FREQCTRL0); + + /* + * Route 48MHz FREQ2 into USBH/USBD/IrDA + */ + sys_clksrc |= ((4<<2) | (0<<1) | 0 ); + au_writel(sys_clksrc, SYS_CLKSRC); + + /* setup the static bus controller */ + au_writel(0x00000002, MEM_STCFG3); /* type = PCMCIA */ + au_writel(0x280E3D07, MEM_STTIME3); /* 250ns cycle time */ + au_writel(0x10000000, MEM_STADDR3); /* any PCMCIA select */ + + // get USB Functionality pin state (device vs host drive pins) + pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000); #ifndef CONFIG_AU1X00_USB_DEVICE - // 2nd USB port is USB host - pin_func |= 0x8000; + // 2nd USB port is USB host + pin_func |= 0x8000; #endif - au_writel(pin_func, SYS_PINFUNC); + au_writel(pin_func, SYS_PINFUNC); + } #endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE) /* Enable sys bus clock divider when IDLE state or no bus activity. */ au_writel(au_readl(SYS_POWERCTRL) | (0x3 << 5), SYS_POWERCTRL); // Enable the RTC if not already enabled - if (!(readb(0xac000028) & 0x20)) { - writeb(readb(0xac000028) | 0x20, 0xac000028); + if (!(readb(base + 0x28) & 0x20)) { + writeb(readb(base + 0x28) | 0x20, base + 0x28); au_sync(); } // Put the clock in BCD mode - if (readb(0xac00002C) & 0x4) { /* reg B */ - writeb(readb(0xac00002c) & ~0x4, 0xac00002c); + if (readb(base + 0x2C) & 0x4) { /* reg B */ + writeb(readb(base + 0x2c) & ~0x4, base + 0x2c); au_sync(); } } diff -Naur linux-2.6.18.3/arch/mips/cobalt/setup.c linux-mips-2.6.18.3/arch/mips/cobalt/setup.c --- linux-2.6.18.3/arch/mips/cobalt/setup.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/cobalt/setup.c 2006-11-20 10:09:08.000000000 -0800 @@ -51,8 +51,8 @@ void __init plat_timer_setup(struct irqaction *irq) { - /* Load timer value for 1KHz (TCLK is 50MHz) */ - GALILEO_OUTL(50*1000*1000 / 1000, GT_TC0_OFS); + /* Load timer value for HZ (TCLK is 50MHz) */ + GALILEO_OUTL(50*1000*1000 / HZ, GT_TC0_OFS); /* Enable timer */ GALILEO_OUTL(GALILEO_ENTC0 | GALILEO_SELTC0, GT_TC_CONTROL_OFS); diff -Naur linux-2.6.18.3/arch/mips/configs/e55_defconfig linux-mips-2.6.18.3/arch/mips/configs/e55_defconfig --- linux-2.6.18.3/arch/mips/configs/e55_defconfig 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/configs/e55_defconfig 2006-11-20 10:09:08.000000000 -0800 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.18-rc1 -# Thu Jul 6 10:04:02 2006 +# Linux kernel version: 2.6.18-rc2 +# Tue Jul 25 23:15:03 2006 # CONFIG_MIPS=y @@ -227,7 +227,6 @@ # # PCCARD (PCMCIA/CardBus) support # -# CONFIG_PCCARD is not set # # PCI Hotplug Support @@ -254,7 +253,6 @@ # CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y -# CONFIG_FW_LOADER is not set # CONFIG_SYS_HYPERVISOR is not set # @@ -284,6 +282,7 @@ CONFIG_BLK_DEV_RAM=m CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 # CONFIG_BLK_DEV_INITRD is not set # CONFIG_CDROM_PKTCDVD is not set @@ -643,6 +642,7 @@ # # Kernel hacking # +CONFIG_TRACE_IRQFLAGS_SUPPORT=y # CONFIG_PRINTK_TIME is not set # CONFIG_MAGIC_SYSRQ is not set # CONFIG_UNUSED_SYMBOLS is not set @@ -650,7 +650,7 @@ CONFIG_LOG_BUF_SHIFT=14 # CONFIG_DEBUG_FS is not set CONFIG_CROSSCOMPILE=y -CONFIG_CMDLINE="console=ttyVR0,19200 mem=8M" +CONFIG_CMDLINE="console=ttyVR0,19200 ide0=0x1f0,0x3f6,40 mem=8M" # # Security options diff -Naur linux-2.6.18.3/arch/mips/configs/mpc30x_defconfig linux-mips-2.6.18.3/arch/mips/configs/mpc30x_defconfig --- linux-2.6.18.3/arch/mips/configs/mpc30x_defconfig 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/configs/mpc30x_defconfig 2006-11-20 10:09:08.000000000 -0800 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.18-rc1 -# Thu Jul 6 10:04:15 2006 +# Linux kernel version: 2.6.18-rc2 +# Tue Jul 25 23:16:46 2006 # CONFIG_MIPS=y @@ -71,7 +71,6 @@ CONFIG_VICTOR_MPC30X=y # CONFIG_ZAO_CAPCELLA is not set CONFIG_PCI_VR41XX=y -CONFIG_VRC4173=y CONFIG_RWSEM_GENERIC_SPINLOCK=y CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y @@ -168,6 +167,7 @@ CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set CONFIG_SYSCTL=y # CONFIG_AUDIT is not set # CONFIG_IKCONFIG is not set @@ -841,7 +841,7 @@ # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set # CONFIG_USB_LED is not set -# CONFIG_USB_CY7C63 is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set # CONFIG_USB_PHIDGETKIT is not set # CONFIG_USB_PHIDGETSERVO is not set @@ -982,7 +982,6 @@ # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set -# CONFIG_CIFS_DEBUG2 is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set @@ -1007,6 +1006,7 @@ # # Kernel hacking # +CONFIG_TRACE_IRQFLAGS_SUPPORT=y # CONFIG_PRINTK_TIME is not set # CONFIG_MAGIC_SYSRQ is not set # CONFIG_UNUSED_SYMBOLS is not set @@ -1014,7 +1014,7 @@ CONFIG_LOG_BUF_SHIFT=14 # CONFIG_DEBUG_FS is not set CONFIG_CROSSCOMPILE=y -CONFIG_CMDLINE="mem=32M console=ttyVR0,19200" +CONFIG_CMDLINE="mem=32M console=ttyVR0,19200 ide0=0x170,0x376,73" # # Security options diff -Naur linux-2.6.18.3/arch/mips/configs/workpad_defconfig linux-mips-2.6.18.3/arch/mips/configs/workpad_defconfig --- linux-2.6.18.3/arch/mips/configs/workpad_defconfig 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/configs/workpad_defconfig 2006-11-20 10:09:08.000000000 -0800 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.18-rc1 -# Thu Jul 6 10:04:21 2006 +# Linux kernel version: 2.6.18-rc2 +# Tue Jul 25 23:13:04 2006 # CONFIG_MIPS=y @@ -166,6 +166,7 @@ CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set CONFIG_SYSCTL=y # CONFIG_AUDIT is not set # CONFIG_IKCONFIG is not set @@ -379,6 +380,7 @@ CONFIG_BLK_DEV_RAM=m CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 # CONFIG_BLK_DEV_INITRD is not set # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set @@ -855,7 +857,6 @@ # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set -# CONFIG_CIFS_DEBUG2 is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set @@ -880,6 +881,7 @@ # # Kernel hacking # +CONFIG_TRACE_IRQFLAGS_SUPPORT=y # CONFIG_PRINTK_TIME is not set # CONFIG_MAGIC_SYSRQ is not set # CONFIG_UNUSED_SYMBOLS is not set @@ -887,7 +889,7 @@ CONFIG_LOG_BUF_SHIFT=14 # CONFIG_DEBUG_FS is not set CONFIG_CROSSCOMPILE=y -CONFIG_CMDLINE="console=ttyVR0,19200 mem=16M" +CONFIG_CMDLINE="console=ttyVR0,19200 ide0=0x170,0x376,49 mem=16M" # # Security options diff -Naur linux-2.6.18.3/arch/mips/gt64120/common/time.c linux-mips-2.6.18.3/arch/mips/gt64120/common/time.c --- linux-2.6.18.3/arch/mips/gt64120/common/time.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/gt64120/common/time.c 2006-11-20 10:09:08.000000000 -0800 @@ -62,14 +62,14 @@ * as *irq (=irq0 in ../kernel/time.c). We will do our own timer interrupt * handling. */ -void gt64120_time_init(void) +void __init plat_timer_setup(struct irqaction *irq) { static struct irqaction timer; /* Disable timer first */ GT_WRITE(GT_TC_CONTROL_OFS, 0); /* Load timer value for 100 Hz */ - GT_WRITE(GT_TC3_OFS, Sys_clock / 100); + GT_WRITE(GT_TC3_OFS, Sys_clock / HZ); /* * Create the IRQ structure entry for the timer. Since we're too early diff -Naur linux-2.6.18.3/arch/mips/gt64120/ev64120/setup.c linux-mips-2.6.18.3/arch/mips/gt64120/ev64120/setup.c --- linux-2.6.18.3/arch/mips/gt64120/ev64120/setup.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/gt64120/ev64120/setup.c 2006-11-20 10:09:08.000000000 -0800 @@ -69,7 +69,6 @@ * Initializes basic routines and structures pointers, memory size (as * given by the bios and saves the command line. */ -extern void gt64120_time_init(void); void __init plat_mem_setup(void) { @@ -77,7 +76,6 @@ _machine_halt = galileo_machine_halt; pm_power_off = galileo_machine_power_off; - board_time_init = gt64120_time_init; set_io_port_base(KSEG1); } diff -Naur linux-2.6.18.3/arch/mips/gt64120/momenco_ocelot/setup.c linux-mips-2.6.18.3/arch/mips/gt64120/momenco_ocelot/setup.c --- linux-2.6.18.3/arch/mips/gt64120/momenco_ocelot/setup.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/gt64120/momenco_ocelot/setup.c 2006-11-20 10:09:08.000000000 -0800 @@ -71,7 +71,6 @@ extern void momenco_ocelot_halt(void); extern void momenco_ocelot_power_off(void); -extern void gt64120_time_init(void); extern void momenco_ocelot_irq_setup(void); static char reset_reason; @@ -157,8 +156,6 @@ void (*l3func)(unsigned long)=KSEG1ADDR(&setup_l3cache); unsigned int tmpword; - board_time_init = gt64120_time_init; - _machine_restart = momenco_ocelot_restart; _machine_halt = momenco_ocelot_halt; pm_power_off = momenco_ocelot_power_off; diff -Naur linux-2.6.18.3/arch/mips/kernel/asm-offsets.c linux-mips-2.6.18.3/arch/mips/kernel/asm-offsets.c --- linux-2.6.18.3/arch/mips/kernel/asm-offsets.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/kernel/asm-offsets.c 2006-11-20 10:09:08.000000000 -0800 @@ -22,7 +22,7 @@ #define offset(string, ptr, member) \ __asm__("\n@@@" string "%0" : : "i" (_offset(ptr, member))) #define constant(string, member) \ - __asm__("\n@@@" string "%x0" : : "ri" (member)) + __asm__("\n@@@" string "%X0" : : "ri" (member)) #define size(string, size) \ __asm__("\n@@@" string "%0" : : "i" (sizeof(size))) #define linefeed text("") diff -Naur linux-2.6.18.3/arch/mips/kernel/cpu-probe.c linux-mips-2.6.18.3/arch/mips/kernel/cpu-probe.c --- linux-2.6.18.3/arch/mips/kernel/cpu-probe.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/kernel/cpu-probe.c 2006-11-20 10:09:08.000000000 -0800 @@ -38,15 +38,40 @@ static void r39xx_wait(void) { - unsigned long cfg = read_c0_conf(); - write_c0_conf(cfg | TX39_CONF_HALT); + local_irq_disable(); + if (!need_resched()) + write_c0_conf(read_c0_conf() | TX39_CONF_HALT); + local_irq_enable(); } +/* + * There is a race when WAIT instruction executed with interrupt + * enabled. + * But it is implementation-dependent wheter the pipelie restarts when + * a non-enabled interrupt is requested. + */ static void r4k_wait(void) { - __asm__(".set\tmips3\n\t" - "wait\n\t" - ".set\tmips0"); + __asm__(" .set mips3 \n" + " wait \n" + " .set mips0 \n"); +} + +/* + * This variant is preferable as it allows testing need_resched and going to + * sleep depending on the outcome atomically. Unfortunately the "It is + * implementation-dependent whether the pipeline restarts when a non-enabled + * interrupt is requested" restriction in the MIPS32/MIPS64 architecture makes + * using this version a gamble. + */ +static void r4k_wait_irqoff(void) +{ + local_irq_disable(); + if (!need_resched()) + __asm__(" .set mips3 \n" + " wait \n" + " .set mips0 \n"); + local_irq_enable(); } /* The Au1xxx wait is available only if using 32khz counter or @@ -56,17 +81,17 @@ static void au1k_wait(void) { /* using the wait instruction makes CP0 counter unusable */ - __asm__(".set mips3\n\t" - "cache 0x14, 0(%0)\n\t" - "cache 0x14, 32(%0)\n\t" - "sync\n\t" - "nop\n\t" - "wait\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - ".set mips0\n\t" + __asm__(" .set mips3 \n" + " cache 0x14, 0(%0) \n" + " cache 0x14, 32(%0) \n" + " sync \n" + " nop \n" + " wait \n" + " nop \n" + " nop \n" + " nop \n" + " nop \n" + " .set mips0 \n" : : "r" (au1k_wait)); } @@ -110,8 +135,6 @@ case CPU_R5000: case CPU_NEVADA: case CPU_RM7000: - case CPU_RM9000: - case CPU_TX49XX: case CPU_4KC: case CPU_4KEC: case CPU_4KSC: @@ -125,6 +148,10 @@ cpu_wait = r4k_wait; printk(" available.\n"); break; + case CPU_TX49XX: + cpu_wait = r4k_wait_irqoff; + printk(" available.\n"); + break; case CPU_AU1000: case CPU_AU1100: case CPU_AU1500: @@ -136,6 +163,14 @@ } else printk(" unavailable.\n"); break; + case CPU_RM9000: + if ((c->processor_id & 0x00ff) >= 0x40) { + cpu_wait = r4k_wait; + printk(" available.\n"); + } else { + printk(" unavailable.\n"); + } + break; default: printk(" unavailable.\n"); break; diff -Naur linux-2.6.18.3/arch/mips/kernel/head.S linux-mips-2.6.18.3/arch/mips/kernel/head.S --- linux-2.6.18.3/arch/mips/kernel/head.S 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/kernel/head.S 2006-11-20 10:09:08.000000000 -0800 @@ -189,7 +189,8 @@ MTC0 zero, CP0_CONTEXT # clear context register PTR_LA $28, init_thread_union - PTR_ADDIU sp, $28, _THREAD_SIZE - 32 + PTR_LI sp, _THREAD_SIZE - 32 + PTR_ADDU sp, $28 set_saved_sp sp, t0, t1 PTR_SUBU sp, 4 * SZREG # init stack pointer diff -Naur linux-2.6.18.3/arch/mips/kernel/irixsig.c linux-mips-2.6.18.3/arch/mips/kernel/irixsig.c --- linux-2.6.18.3/arch/mips/kernel/irixsig.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/kernel/irixsig.c 2006-11-20 10:09:08.000000000 -0800 @@ -17,6 +17,7 @@ #include #include +#include #undef DEBUG_SIG @@ -172,11 +173,12 @@ return ret; } -asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs) +void do_irix_signal(struct pt_regs *regs) { struct k_sigaction ka; siginfo_t info; int signr; + sigset_t *oldset; /* * We want the common case to go fast, which is why we may in certain @@ -184,19 +186,28 @@ * if so. */ if (!user_mode(regs)) - return 1; + return; - if (try_to_freeze()) - goto no_signal; - - if (!oldset) + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else oldset = ¤t->blocked; signr = get_signal_to_deliver(&info, &ka, regs, NULL); - if (signr > 0) - return handle_signal(signr, &info, &ka, oldset, regs); + if (signr > 0) { + /* Whee! Actually deliver the signal. */ + if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { + /* a signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TIF_RESTORE_SIGMASK flag */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + } + + return; + } -no_signal: /* * Who's code doesn't conform to the restartable syscall convention * dies here!!! The li instruction, a single machine instruction, @@ -208,8 +219,22 @@ regs->regs[2] == ERESTARTNOINTR) { regs->cp0_epc -= 8; } + if (regs->regs[2] == ERESTART_RESTARTBLOCK) { + regs->regs[2] = __NR_restart_syscall; + regs->regs[7] = regs->regs[26]; + regs->cp0_epc -= 4; + } + regs->regs[0] = 0; /* Don't deal with this again. */ + } + + /* + * If there's no signal to deliver, we just put the saved sigmask + * back + */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); } - return 0; } asmlinkage void @@ -413,7 +438,7 @@ asmlinkage int irix_sigsuspend(struct pt_regs *regs) { - sigset_t saveset, newset; + sigset_t newset; sigset_t __user *uset; uset = (sigset_t __user *) regs->regs[4]; @@ -422,18 +447,15 @@ sigdelsetmask(&newset, ~_BLOCKABLE); spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; + current->saved_sigmask = current->blocked; current->blocked = newset; recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - regs->regs[2] = -EINTR; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (do_irix_signal(&saveset, regs)) - return -EINTR; - } + current->state = TASK_INTERRUPTIBLE; + schedule(); + set_thread_flag(TIF_RESTORE_SIGMASK); + return -ERESTARTNOHAND; } /* hate hate hate... */ diff -Naur linux-2.6.18.3/arch/mips/kernel/irq.c linux-mips-2.6.18.3/arch/mips/kernel/irq.c --- linux-2.6.18.3/arch/mips/kernel/irq.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/kernel/irq.c 2006-11-20 10:09:08.000000000 -0800 @@ -26,6 +26,48 @@ #include #include +static unsigned long irq_map[NR_IRQS / BITS_PER_LONG]; + +int __devinit allocate_irqno(void) +{ + int irq; + +again: + irq = find_first_zero_bit(irq_map, NR_IRQS); + + if (irq >= NR_IRQS) + return -ENOSPC; + + if (test_and_set_bit(irq, irq_map)) + goto again; + + return irq; +} + +EXPORT_SYMBOL_GPL(allocate_irqno); + +/* + * Allocate the 16 legacy interrupts for i8259 devices. This happens early + * in the kernel initialization so treating allocation failure as BUG() is + * ok. + */ +void __init alloc_legacy_irqno(void) +{ + int i; + + for (i = 0; i <= 16; i++) + BUG_ON(test_and_set_bit(i, irq_map)); +} + +void __devinit free_irqno(unsigned int irq) +{ + smp_mb__before_clear_bit(); + clear_bit(irq, irq_map); + smp_mb__after_clear_bit(); +} + +EXPORT_SYMBOL_GPL(free_irqno); + /* * 'what should we do if we get a hw irq event on an illegal vector'. * each architecture has to answer this themselves. diff -Naur linux-2.6.18.3/arch/mips/kernel/linux32.c linux-mips-2.6.18.3/arch/mips/kernel/linux32.c --- linux-2.6.18.3/arch/mips/kernel/linux32.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/kernel/linux32.c 2006-11-20 10:09:08.000000000 -0800 @@ -380,531 +380,6 @@ return ret; } -struct msgbuf32 { s32 mtype; char mtext[1]; }; - -struct ipc_perm32 -{ - key_t key; - __compat_uid_t uid; - __compat_gid_t gid; - __compat_uid_t cuid; - __compat_gid_t cgid; - compat_mode_t mode; - unsigned short seq; -}; - -struct ipc64_perm32 { - key_t key; - __compat_uid_t uid; - __compat_gid_t gid; - __compat_uid_t cuid; - __compat_gid_t cgid; - compat_mode_t mode; - unsigned short seq; - unsigned short __pad1; - unsigned int __unused1; - unsigned int __unused2; -}; - -struct semid_ds32 { - struct ipc_perm32 sem_perm; /* permissions .. see ipc.h */ - compat_time_t sem_otime; /* last semop time */ - compat_time_t sem_ctime; /* last change time */ - u32 sem_base; /* ptr to first semaphore in array */ - u32 sem_pending; /* pending operations to be processed */ - u32 sem_pending_last; /* last pending operation */ - u32 undo; /* undo requests on this array */ - unsigned short sem_nsems; /* no. of semaphores in array */ -}; - -struct semid64_ds32 { - struct ipc64_perm32 sem_perm; - compat_time_t sem_otime; - compat_time_t sem_ctime; - unsigned int sem_nsems; - unsigned int __unused1; - unsigned int __unused2; -}; - -struct msqid_ds32 -{ - struct ipc_perm32 msg_perm; - u32 msg_first; - u32 msg_last; - compat_time_t msg_stime; - compat_time_t msg_rtime; - compat_time_t msg_ctime; - u32 wwait; - u32 rwait; - unsigned short msg_cbytes; - unsigned short msg_qnum; - unsigned short msg_qbytes; - compat_ipc_pid_t msg_lspid; - compat_ipc_pid_t msg_lrpid; -}; - -struct msqid64_ds32 { - struct ipc64_perm32 msg_perm; - compat_time_t msg_stime; - unsigned int __unused1; - compat_time_t msg_rtime; - unsigned int __unused2; - compat_time_t msg_ctime; - unsigned int __unused3; - unsigned int msg_cbytes; - unsigned int msg_qnum; - unsigned int msg_qbytes; - compat_pid_t msg_lspid; - compat_pid_t msg_lrpid; - unsigned int __unused4; - unsigned int __unused5; -}; - -struct shmid_ds32 { - struct ipc_perm32 shm_perm; - int shm_segsz; - compat_time_t shm_atime; - compat_time_t shm_dtime; - compat_time_t shm_ctime; - compat_ipc_pid_t shm_cpid; - compat_ipc_pid_t shm_lpid; - unsigned short shm_nattch; -}; - -struct shmid64_ds32 { - struct ipc64_perm32 shm_perm; - compat_size_t shm_segsz; - compat_time_t shm_atime; - compat_time_t shm_dtime; - compat_time_t shm_ctime; - compat_pid_t shm_cpid; - compat_pid_t shm_lpid; - unsigned int shm_nattch; - unsigned int __unused1; - unsigned int __unused2; -}; - -struct ipc_kludge32 { - u32 msgp; - s32 msgtyp; -}; - -static int -do_sys32_semctl(int first, int second, int third, void __user *uptr) -{ - union semun fourth; - u32 pad; - int err, err2; - struct semid64_ds s; - mm_segment_t old_fs; - - if (!uptr) - return -EINVAL; - err = -EFAULT; - if (get_user (pad, (u32 __user *)uptr)) - return err; - if ((third & ~IPC_64) == SETVAL) - fourth.val = (int)pad; - else - fourth.__pad = (void __user *)A(pad); - switch (third & ~IPC_64) { - case IPC_INFO: - case IPC_RMID: - case IPC_SET: - case SEM_INFO: - case GETVAL: - case GETPID: - case GETNCNT: - case GETZCNT: - case GETALL: - case SETVAL: - case SETALL: - err = sys_semctl (first, second, third, fourth); - break; - - case IPC_STAT: - case SEM_STAT: - fourth.__pad = (struct semid64_ds __user *)&s; - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_semctl(first, second, third | IPC_64, fourth); - set_fs(old_fs); - - if (third & IPC_64) { - struct semid64_ds32 __user *usp64 = (struct semid64_ds32 __user *) A(pad); - - if (!access_ok(VERIFY_WRITE, usp64, sizeof(*usp64))) { - err = -EFAULT; - break; - } - err2 = __put_user(s.sem_perm.key, &usp64->sem_perm.key); - err2 |= __put_user(s.sem_perm.uid, &usp64->sem_perm.uid); - err2 |= __put_user(s.sem_perm.gid, &usp64->sem_perm.gid); - err2 |= __put_user(s.sem_perm.cuid, &usp64->sem_perm.cuid); - err2 |= __put_user(s.sem_perm.cgid, &usp64->sem_perm.cgid); - err2 |= __put_user(s.sem_perm.mode, &usp64->sem_perm.mode); - err2 |= __put_user(s.sem_perm.seq, &usp64->sem_perm.seq); - err2 |= __put_user(s.sem_otime, &usp64->sem_otime); - err2 |= __put_user(s.sem_ctime, &usp64->sem_ctime); - err2 |= __put_user(s.sem_nsems, &usp64->sem_nsems); - } else { - struct semid_ds32 __user *usp32 = (struct semid_ds32 __user *) A(pad); - - if (!access_ok(VERIFY_WRITE, usp32, sizeof(*usp32))) { - err = -EFAULT; - break; - } - err2 = __put_user(s.sem_perm.key, &usp32->sem_perm.key); - err2 |= __put_user(s.sem_perm.uid, &usp32->sem_perm.uid); - err2 |= __put_user(s.sem_perm.gid, &usp32->sem_perm.gid); - err2 |= __put_user(s.sem_perm.cuid, &usp32->sem_perm.cuid); - err2 |= __put_user(s.sem_perm.cgid, &usp32->sem_perm.cgid); - err2 |= __put_user(s.sem_perm.mode, &usp32->sem_perm.mode); - err2 |= __put_user(s.sem_perm.seq, &usp32->sem_perm.seq); - err2 |= __put_user(s.sem_otime, &usp32->sem_otime); - err2 |= __put_user(s.sem_ctime, &usp32->sem_ctime); - err2 |= __put_user(s.sem_nsems, &usp32->sem_nsems); - } - if (err2) - err = -EFAULT; - break; - - default: - err = - EINVAL; - break; - } - - return err; -} - -static int -do_sys32_msgsnd (int first, int second, int third, void __user *uptr) -{ - struct msgbuf32 __user *up = (struct msgbuf32 __user *)uptr; - struct msgbuf *p; - mm_segment_t old_fs; - int err; - - if (second < 0) - return -EINVAL; - p = kmalloc (second + sizeof (struct msgbuf) - + 4, GFP_USER); - if (!p) - return -ENOMEM; - err = get_user (p->mtype, &up->mtype); - if (err) - goto out; - err |= __copy_from_user (p->mtext, &up->mtext, second); - if (err) - goto out; - old_fs = get_fs (); - set_fs (KERNEL_DS); - err = sys_msgsnd (first, (struct msgbuf __user *)p, second, third); - set_fs (old_fs); -out: - kfree (p); - - return err; -} - -static int -do_sys32_msgrcv (int first, int second, int msgtyp, int third, - int version, void __user *uptr) -{ - struct msgbuf32 __user *up; - struct msgbuf *p; - mm_segment_t old_fs; - int err; - - if (!version) { - struct ipc_kludge32 __user *uipck = (struct ipc_kludge32 __user *)uptr; - struct ipc_kludge32 ipck; - - err = -EINVAL; - if (!uptr) - goto out; - err = -EFAULT; - if (copy_from_user (&ipck, uipck, sizeof (struct ipc_kludge32))) - goto out; - uptr = (void __user *)AA(ipck.msgp); - msgtyp = ipck.msgtyp; - } - - if (second < 0) - return -EINVAL; - err = -ENOMEM; - p = kmalloc (second + sizeof (struct msgbuf) + 4, GFP_USER); - if (!p) - goto out; - old_fs = get_fs (); - set_fs (KERNEL_DS); - err = sys_msgrcv (first, (struct msgbuf __user *)p, second + 4, msgtyp, third); - set_fs (old_fs); - if (err < 0) - goto free_then_out; - up = (struct msgbuf32 __user *)uptr; - if (put_user (p->mtype, &up->mtype) || - __copy_to_user (&up->mtext, p->mtext, err)) - err = -EFAULT; -free_then_out: - kfree (p); -out: - return err; -} - -static int -do_sys32_msgctl (int first, int second, void __user *uptr) -{ - int err = -EINVAL, err2; - struct msqid64_ds m; - struct msqid_ds32 __user *up32 = (struct msqid_ds32 __user *)uptr; - struct msqid64_ds32 __user *up64 = (struct msqid64_ds32 __user *)uptr; - mm_segment_t old_fs; - - switch (second & ~IPC_64) { - case IPC_INFO: - case IPC_RMID: - case MSG_INFO: - err = sys_msgctl (first, second, (struct msqid_ds __user *)uptr); - break; - - case IPC_SET: - if (second & IPC_64) { - if (!access_ok(VERIFY_READ, up64, sizeof(*up64))) { - err = -EFAULT; - break; - } - err = __get_user(m.msg_perm.uid, &up64->msg_perm.uid); - err |= __get_user(m.msg_perm.gid, &up64->msg_perm.gid); - err |= __get_user(m.msg_perm.mode, &up64->msg_perm.mode); - err |= __get_user(m.msg_qbytes, &up64->msg_qbytes); - } else { - if (!access_ok(VERIFY_READ, up32, sizeof(*up32))) { - err = -EFAULT; - break; - } - err = __get_user(m.msg_perm.uid, &up32->msg_perm.uid); - err |= __get_user(m.msg_perm.gid, &up32->msg_perm.gid); - err |= __get_user(m.msg_perm.mode, &up32->msg_perm.mode); - err |= __get_user(m.msg_qbytes, &up32->msg_qbytes); - } - if (err) - break; - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_msgctl(first, second | IPC_64, (struct msqid_ds __user *)&m); - set_fs(old_fs); - break; - - case IPC_STAT: - case MSG_STAT: - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_msgctl(first, second | IPC_64, (struct msqid_ds __user *)&m); - set_fs(old_fs); - if (second & IPC_64) { - if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) { - err = -EFAULT; - break; - } - err2 = __put_user(m.msg_perm.key, &up64->msg_perm.key); - err2 |= __put_user(m.msg_perm.uid, &up64->msg_perm.uid); - err2 |= __put_user(m.msg_perm.gid, &up64->msg_perm.gid); - err2 |= __put_user(m.msg_perm.cuid, &up64->msg_perm.cuid); - err2 |= __put_user(m.msg_perm.cgid, &up64->msg_perm.cgid); - err2 |= __put_user(m.msg_perm.mode, &up64->msg_perm.mode); - err2 |= __put_user(m.msg_perm.seq, &up64->msg_perm.seq); - err2 |= __put_user(m.msg_stime, &up64->msg_stime); - err2 |= __put_user(m.msg_rtime, &up64->msg_rtime); - err2 |= __put_user(m.msg_ctime, &up64->msg_ctime); - err2 |= __put_user(m.msg_cbytes, &up64->msg_cbytes); - err2 |= __put_user(m.msg_qnum, &up64->msg_qnum); - err2 |= __put_user(m.msg_qbytes, &up64->msg_qbytes); - err2 |= __put_user(m.msg_lspid, &up64->msg_lspid); - err2 |= __put_user(m.msg_lrpid, &up64->msg_lrpid); - if (err2) - err = -EFAULT; - } else { - if (!access_ok(VERIFY_WRITE, up32, sizeof(*up32))) { - err = -EFAULT; - break; - } - err2 = __put_user(m.msg_perm.key, &up32->msg_perm.key); - err2 |= __put_user(m.msg_perm.uid, &up32->msg_perm.uid); - err2 |= __put_user(m.msg_perm.gid, &up32->msg_perm.gid); - err2 |= __put_user(m.msg_perm.cuid, &up32->msg_perm.cuid); - err2 |= __put_user(m.msg_perm.cgid, &up32->msg_perm.cgid); - err2 |= __put_user(m.msg_perm.mode, &up32->msg_perm.mode); - err2 |= __put_user(m.msg_perm.seq, &up32->msg_perm.seq); - err2 |= __put_user(m.msg_stime, &up32->msg_stime); - err2 |= __put_user(m.msg_rtime, &up32->msg_rtime); - err2 |= __put_user(m.msg_ctime, &up32->msg_ctime); - err2 |= __put_user(m.msg_cbytes, &up32->msg_cbytes); - err2 |= __put_user(m.msg_qnum, &up32->msg_qnum); - err2 |= __put_user(m.msg_qbytes, &up32->msg_qbytes); - err2 |= __put_user(m.msg_lspid, &up32->msg_lspid); - err2 |= __put_user(m.msg_lrpid, &up32->msg_lrpid); - if (err2) - err = -EFAULT; - } - break; - } - - return err; -} - -static int -do_sys32_shmat (int first, int second, int third, int version, void __user *uptr) -{ - unsigned long raddr; - u32 __user *uaddr = (u32 __user *)A((u32)third); - int err = -EINVAL; - - if (version == 1) - return err; - err = do_shmat (first, uptr, second, &raddr); - if (err) - return err; - err = put_user (raddr, uaddr); - return err; -} - -struct shm_info32 { - int used_ids; - u32 shm_tot, shm_rss, shm_swp; - u32 swap_attempts, swap_successes; -}; - -static int -do_sys32_shmctl (int first, int second, void __user *uptr) -{ - struct shmid64_ds32 __user *up64 = (struct shmid64_ds32 __user *)uptr; - struct shmid_ds32 __user *up32 = (struct shmid_ds32 __user *)uptr; - struct shm_info32 __user *uip = (struct shm_info32 __user *)uptr; - int err = -EFAULT, err2; - struct shmid64_ds s64; - mm_segment_t old_fs; - struct shm_info si; - struct shmid_ds s; - - switch (second & ~IPC_64) { - case IPC_INFO: - second = IPC_INFO; /* So that we don't have to translate it */ - case IPC_RMID: - case SHM_LOCK: - case SHM_UNLOCK: - err = sys_shmctl(first, second, (struct shmid_ds __user *)uptr); - break; - case IPC_SET: - if (second & IPC_64) { - err = get_user(s.shm_perm.uid, &up64->shm_perm.uid); - err |= get_user(s.shm_perm.gid, &up64->shm_perm.gid); - err |= get_user(s.shm_perm.mode, &up64->shm_perm.mode); - } else { - err = get_user(s.shm_perm.uid, &up32->shm_perm.uid); - err |= get_user(s.shm_perm.gid, &up32->shm_perm.gid); - err |= get_user(s.shm_perm.mode, &up32->shm_perm.mode); - } - if (err) - break; - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_shmctl(first, second & ~IPC_64, (struct shmid_ds __user *)&s); - set_fs(old_fs); - break; - - case IPC_STAT: - case SHM_STAT: - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_shmctl(first, second | IPC_64, (void __user *) &s64); - set_fs(old_fs); - if (err < 0) - break; - if (second & IPC_64) { - if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) { - err = -EFAULT; - break; - } - err2 = __put_user(s64.shm_perm.key, &up64->shm_perm.key); - err2 |= __put_user(s64.shm_perm.uid, &up64->shm_perm.uid); - err2 |= __put_user(s64.shm_perm.gid, &up64->shm_perm.gid); - err2 |= __put_user(s64.shm_perm.cuid, &up64->shm_perm.cuid); - err2 |= __put_user(s64.shm_perm.cgid, &up64->shm_perm.cgid); - err2 |= __put_user(s64.shm_perm.mode, &up64->shm_perm.mode); - err2 |= __put_user(s64.shm_perm.seq, &up64->shm_perm.seq); - err2 |= __put_user(s64.shm_atime, &up64->shm_atime); - err2 |= __put_user(s64.shm_dtime, &up64->shm_dtime); - err2 |= __put_user(s64.shm_ctime, &up64->shm_ctime); - err2 |= __put_user(s64.shm_segsz, &up64->shm_segsz); - err2 |= __put_user(s64.shm_nattch, &up64->shm_nattch); - err2 |= __put_user(s64.shm_cpid, &up64->shm_cpid); - err2 |= __put_user(s64.shm_lpid, &up64->shm_lpid); - } else { - if (!access_ok(VERIFY_WRITE, up32, sizeof(*up32))) { - err = -EFAULT; - break; - } - err2 = __put_user(s64.shm_perm.key, &up32->shm_perm.key); - err2 |= __put_user(s64.shm_perm.uid, &up32->shm_perm.uid); - err2 |= __put_user(s64.shm_perm.gid, &up32->shm_perm.gid); - err2 |= __put_user(s64.shm_perm.cuid, &up32->shm_perm.cuid); - err2 |= __put_user(s64.shm_perm.cgid, &up32->shm_perm.cgid); - err2 |= __put_user(s64.shm_perm.mode, &up32->shm_perm.mode); - err2 |= __put_user(s64.shm_perm.seq, &up32->shm_perm.seq); - err2 |= __put_user(s64.shm_atime, &up32->shm_atime); - err2 |= __put_user(s64.shm_dtime, &up32->shm_dtime); - err2 |= __put_user(s64.shm_ctime, &up32->shm_ctime); - err2 |= __put_user(s64.shm_segsz, &up32->shm_segsz); - err2 |= __put_user(s64.shm_nattch, &up32->shm_nattch); - err2 |= __put_user(s64.shm_cpid, &up32->shm_cpid); - err2 |= __put_user(s64.shm_lpid, &up32->shm_lpid); - } - if (err2) - err = -EFAULT; - break; - - case SHM_INFO: - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_shmctl(first, second, (void __user *)&si); - set_fs(old_fs); - if (err < 0) - break; - err2 = put_user(si.used_ids, &uip->used_ids); - err2 |= __put_user(si.shm_tot, &uip->shm_tot); - err2 |= __put_user(si.shm_rss, &uip->shm_rss); - err2 |= __put_user(si.shm_swp, &uip->shm_swp); - err2 |= __put_user(si.swap_attempts, &uip->swap_attempts); - err2 |= __put_user (si.swap_successes, &uip->swap_successes); - if (err2) - err = -EFAULT; - break; - - default: - err = -EINVAL; - break; - } - - return err; -} - -static int sys32_semtimedop(int semid, struct sembuf __user *tsems, int nsems, - const struct compat_timespec __user *timeout32) -{ - struct compat_timespec t32; - struct timespec __user *t64 = compat_alloc_user_space(sizeof(*t64)); - - if (copy_from_user(&t32, timeout32, sizeof(t32))) - return -EFAULT; - - if (put_user(t32.tv_sec, &t64->tv_sec) || - put_user(t32.tv_nsec, &t64->tv_nsec)) - return -EFAULT; - - return sys_semtimedop(semid, tsems, nsems, t64); -} - asmlinkage long sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth) { @@ -916,48 +391,43 @@ switch (call) { case SEMOP: /* struct sembuf is the same on 32 and 64bit :)) */ - err = sys_semtimedop (first, (struct sembuf __user *)AA(ptr), second, - NULL); + err = sys_semtimedop(first, compat_ptr(ptr), second, NULL); break; case SEMTIMEDOP: - err = sys32_semtimedop (first, (struct sembuf __user *)AA(ptr), second, - (const struct compat_timespec __user *)AA(fifth)); + err = compat_sys_semtimedop(first, compat_ptr(ptr), second, + compat_ptr(fifth)); break; case SEMGET: - err = sys_semget (first, second, third); + err = sys_semget(first, second, third); break; case SEMCTL: - err = do_sys32_semctl (first, second, third, - (void __user *)AA(ptr)); + err = compat_sys_semctl(first, second, third, compat_ptr(ptr)); break; - case MSGSND: - err = do_sys32_msgsnd (first, second, third, - (void __user *)AA(ptr)); + err = compat_sys_msgsnd(first, second, third, compat_ptr(ptr)); break; case MSGRCV: - err = do_sys32_msgrcv (first, second, fifth, third, - version, (void __user *)AA(ptr)); + err = compat_sys_msgrcv(first, second, fifth, third, + version, compat_ptr(ptr)); break; case MSGGET: - err = sys_msgget ((key_t) first, second); + err = sys_msgget((key_t) first, second); break; case MSGCTL: - err = do_sys32_msgctl (first, second, (void __user *)AA(ptr)); + err = compat_sys_msgctl(first, second, compat_ptr(ptr)); break; - case SHMAT: - err = do_sys32_shmat (first, second, third, - version, (void __user *)AA(ptr)); + err = compat_sys_shmat(first, second, third, version, + compat_ptr(ptr)); break; case SHMDT: - err = sys_shmdt ((char __user *)A(ptr)); + err = sys_shmdt(compat_ptr(ptr)); break; case SHMGET: - err = sys_shmget (first, (unsigned)second, third); + err = sys_shmget(first, (unsigned)second, third); break; case SHMCTL: - err = do_sys32_shmctl (first, second, (void __user *)AA(ptr)); + err = compat_sys_shmctl(first, second, compat_ptr(ptr)); break; default: err = -EINVAL; @@ -967,18 +437,16 @@ return err; } -asmlinkage long sys32_shmat(int shmid, char __user *shmaddr, - int shmflg, int32_t __user *addr) +#ifdef CONFIG_MIPS32_N32 +asmlinkage long sysn32_semctl(int semid, int semnum, int cmd, union semun arg) { - unsigned long raddr; - int err; - - err = do_shmat(shmid, shmaddr, shmflg, &raddr); - if (err) - return err; - - return put_user(raddr, addr); + /* compat_sys_semctl expects a pointer to union semun */ + u32 __user *uptr = compat_alloc_user_space(sizeof(u32)); + if (put_user(ptr_to_compat(arg.__pad), uptr)) + return -EFAULT; + return compat_sys_semctl(semid, semnum, cmd, uptr); } +#endif struct sysctl_args32 { @@ -1053,7 +521,9 @@ asmlinkage int sys32_personality(unsigned long personality) { int ret; - if (current->personality == PER_LINUX32 && personality == PER_LINUX) + personality &= 0xffffffff; + if (personality(current->personality) == PER_LINUX32 && + personality == PER_LINUX) personality = PER_LINUX32; ret = sys_personality(personality); if (ret == PER_LINUX32) @@ -1296,9 +766,3 @@ return do_fork(clone_flags, newsp, ®s, 0, parent_tidptr, child_tidptr); } - -extern asmlinkage void sys_set_thread_area(u32 addr); -asmlinkage void sys32_set_thread_area(u32 addr) -{ - sys_set_thread_area(AA(addr)); -} diff -Naur linux-2.6.18.3/arch/mips/kernel/mips-mt.c linux-mips-2.6.18.3/arch/mips/kernel/mips-mt.c --- linux-2.6.18.3/arch/mips/kernel/mips-mt.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/kernel/mips-mt.c 2006-11-20 10:09:08.000000000 -0800 @@ -96,6 +96,10 @@ 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; @@ -141,8 +145,9 @@ p = find_process_by_pid(pid); if (!p) goto out_unlock; - - retval = 0; + retval = security_task_getscheduler(p); + if (retval) + goto out_unlock; cpus_and(mask, p->thread.user_cpus_allowed, cpu_possible_map); diff -Naur linux-2.6.18.3/arch/mips/kernel/proc.c linux-mips-2.6.18.3/arch/mips/kernel/proc.c --- linux-2.6.18.3/arch/mips/kernel/proc.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/kernel/proc.c 2006-11-20 10:09:08.000000000 -0800 @@ -89,9 +89,9 @@ static int show_cpuinfo(struct seq_file *m, void *v) { - unsigned int version = current_cpu_data.processor_id; - unsigned int fp_vers = current_cpu_data.fpu_id; unsigned long n = (unsigned long) v - 1; + unsigned int version = cpu_data[n].processor_id; + unsigned int fp_vers = cpu_data[n].fpu_id; char fmt [64]; #ifdef CONFIG_SMP @@ -107,9 +107,9 @@ seq_printf(m, "processor\t\t: %ld\n", n); sprintf(fmt, "cpu model\t\t: %%s V%%d.%%d%s\n", - cpu_has_fpu ? " FPU V%d.%d" : ""); - seq_printf(m, fmt, cpu_name[current_cpu_data.cputype <= CPU_LAST ? - current_cpu_data.cputype : CPU_UNKNOWN], + cpu_data[n].options & MIPS_CPU_FPU ? " FPU V%d.%d" : ""); + seq_printf(m, fmt, cpu_name[cpu_data[n].cputype <= CPU_LAST ? + cpu_data[n].cputype : CPU_UNKNOWN], (version >> 4) & 0x0f, version & 0x0f, (fp_vers >> 4) & 0x0f, fp_vers & 0x0f); seq_printf(m, "BogoMIPS\t\t: %lu.%02lu\n", @@ -118,7 +118,7 @@ seq_printf(m, "wait instruction\t: %s\n", cpu_wait ? "yes" : "no"); seq_printf(m, "microsecond timers\t: %s\n", cpu_has_counter ? "yes" : "no"); - seq_printf(m, "tlb_entries\t\t: %d\n", current_cpu_data.tlbsize); + seq_printf(m, "tlb_entries\t\t: %d\n", cpu_data[n].tlbsize); seq_printf(m, "extra interrupt vector\t: %s\n", cpu_has_divec ? "yes" : "no"); seq_printf(m, "hardware watchpoint\t: %s\n", diff -Naur linux-2.6.18.3/arch/mips/kernel/process.c linux-mips-2.6.18.3/arch/mips/kernel/process.c --- linux-2.6.18.3/arch/mips/kernel/process.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/kernel/process.c 2006-11-20 10:09:08.000000000 -0800 @@ -114,7 +114,7 @@ status |= KU_USER; regs->cp0_status = status; clear_used_math(); - lose_fpu(); + clear_fpu_owner(); if (cpu_has_dsp) __init_dsp(); regs->cp0_epc = pc; @@ -281,62 +281,63 @@ } *schedule_frame, mfinfo[64]; static int mfinfo_num; -static int __init get_frame_info(struct mips_frame_info *info) +static inline int is_ra_save_ins(union mips_instruction *ip) { - int i; - void *func = info->func; - union mips_instruction *ip = (union mips_instruction *)func; + /* sw / sd $ra, offset($sp) */ + return (ip->i_format.opcode == sw_op || ip->i_format.opcode == sd_op) && + ip->i_format.rs == 29 && + ip->i_format.rt == 31; +} + +static inline int is_jal_jalr_jr_ins(union mips_instruction *ip) +{ + if (ip->j_format.opcode == jal_op) + return 1; + if (ip->r_format.opcode != spec_op) + return 0; + return ip->r_format.func == jalr_op || ip->r_format.func == jr_op; +} + +static inline int is_sp_move_ins(union mips_instruction *ip) +{ + /* addiu/daddiu sp,sp,-imm */ + if (ip->i_format.rs != 29 || ip->i_format.rt != 29) + return 0; + if (ip->i_format.opcode == addiu_op || ip->i_format.opcode == daddiu_op) + return 1; + return 0; +} + +static int get_frame_info(struct mips_frame_info *info) +{ + union mips_instruction *ip = info->func; + int i, max_insns = + min(128UL, info->func_size / sizeof(union mips_instruction)); + info->pc_offset = -1; info->frame_size = 0; - for (i = 0; i < 128; i++, ip++) { - /* if jal, jalr, jr, stop. */ - if (ip->j_format.opcode == jal_op || - (ip->r_format.opcode == spec_op && - (ip->r_format.func == jalr_op || - ip->r_format.func == jr_op))) - break; - if (info->func_size && i >= info->func_size / 4) + for (i = 0; i < max_insns; i++, ip++) { + + if (is_jal_jalr_jr_ins(ip)) break; - if ( -#ifdef CONFIG_32BIT - ip->i_format.opcode == addiu_op && -#endif -#ifdef CONFIG_64BIT - ip->i_format.opcode == daddiu_op && -#endif - ip->i_format.rs == 29 && - ip->i_format.rt == 29) { - /* addiu/daddiu sp,sp,-imm */ - if (info->frame_size) - continue; - info->frame_size = - ip->i_format.simmediate; + if (!info->frame_size) { + if (is_sp_move_ins(ip)) + info->frame_size = - ip->i_format.simmediate; + continue; } - - if ( -#ifdef CONFIG_32BIT - ip->i_format.opcode == sw_op && -#endif -#ifdef CONFIG_64BIT - ip->i_format.opcode == sd_op && -#endif - ip->i_format.rs == 29 && - ip->i_format.rt == 31) { - /* sw / sd $ra, offset($sp) */ - if (info->pc_offset != -1) - continue; + if (info->pc_offset == -1 && is_ra_save_ins(ip)) { info->pc_offset = ip->i_format.simmediate / sizeof(long); + break; } } - if (info->pc_offset == -1 || info->frame_size == 0) { - if (func == schedule) - printk("Can't analyze prologue code at %p\n", func); - info->pc_offset = -1; - info->frame_size = 0; - } - - return 0; + if (info->frame_size && info->pc_offset >= 0) /* nested */ + return 0; + if (info->pc_offset < 0) /* leaf */ + return 1; + /* prologue seems boggus... */ + return -1; } static int __init frame_info_init(void) @@ -368,7 +369,14 @@ schedule_frame = &mfinfo[0]; #endif for (i = 0; i < ARRAY_SIZE(mfinfo) && mfinfo[i].func; i++) - get_frame_info(&mfinfo[i]); + get_frame_info(mfinfo + i); + + /* + * Without schedule() frame info, result given by + * thread_saved_pc() and get_wchan() are not reliable. + */ + if (schedule_frame->pc_offset < 0) + printk("Can't analyze schedule() prologue at %p\n", schedule); mfinfo_num = i; return 0; @@ -427,6 +435,8 @@ if (i < 0) break; + if (mfinfo[i].pc_offset < 0) + break; pc = ((unsigned long *)frame)[mfinfo[i].pc_offset]; if (!mfinfo[i].frame_size) break; @@ -437,3 +447,49 @@ return pc; } +#ifdef CONFIG_KALLSYMS +/* used by show_backtrace() */ +unsigned long unwind_stack(struct task_struct *task, unsigned long *sp, + unsigned long pc, unsigned long ra) +{ + unsigned long stack_page; + struct mips_frame_info info; + char *modname; + char namebuf[KSYM_NAME_LEN + 1]; + unsigned long size, ofs; + int leaf; + + stack_page = (unsigned long)task_stack_page(task); + if (!stack_page) + return 0; + + if (!kallsyms_lookup(pc, &size, &ofs, &modname, namebuf)) + return 0; + if (ofs == 0) + return 0; + + info.func = (void *)(pc - ofs); + info.func_size = ofs; /* analyze from start to ofs */ + leaf = get_frame_info(&info); + if (leaf < 0) + return 0; + + if (*sp < stack_page || + *sp + info.frame_size > stack_page + THREAD_SIZE - 32) + return 0; + + if (leaf) + /* + * For some extreme cases, get_frame_info() can + * consider wrongly a nested function as a leaf + * one. In that cases avoid to return always the + * same value. + */ + pc = pc != ra ? ra : 0; + else + pc = ((unsigned long *)(*sp))[info.pc_offset]; + + *sp += info.frame_size; + return __kernel_text_address(pc) ? pc : 0; +} +#endif diff -Naur linux-2.6.18.3/arch/mips/kernel/ptrace.c linux-mips-2.6.18.3/arch/mips/kernel/ptrace.c --- linux-2.6.18.3/arch/mips/kernel/ptrace.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/kernel/ptrace.c 2006-11-20 10:09:08.000000000 -0800 @@ -20,12 +20,12 @@ #include #include #include -#include #include #include #include #include -#include +#include +#include #include #include @@ -106,6 +106,7 @@ int ptrace_getfpregs (struct task_struct *child, __u32 __user *data) { int i; + unsigned int tmp; if (!access_ok(VERIFY_WRITE, data, 33 * 8)) return -EIO; @@ -121,10 +122,10 @@ __put_user (child->thread.fpu.fcr31, data + 64); + preempt_disable(); if (cpu_has_fpu) { - unsigned int flags, tmp; + unsigned int flags; - preempt_disable(); if (cpu_has_mipsmt) { unsigned int vpflags = dvpe(); flags = read_c0_status(); @@ -138,11 +139,11 @@ __asm__ __volatile__("cfc1\t%0,$0" : "=r" (tmp)); write_c0_status(flags); } - preempt_enable(); - __put_user (tmp, data + 65); } else { - __put_user ((__u32) 0, data + 65); + tmp = 0; } + preempt_enable(); + __put_user (tmp, data + 65); return 0; } @@ -245,16 +246,17 @@ unsigned int mtflags; #endif /* CONFIG_MIPS_MT_SMTC */ - if (!cpu_has_fpu) + preempt_disable(); + if (!cpu_has_fpu) { + preempt_enable(); break; + } #ifdef CONFIG_MIPS_MT_SMTC /* Read-modify-write of Status must be atomic */ local_irq_save(irqflags); mtflags = dmt(); #endif /* CONFIG_MIPS_MT_SMTC */ - - preempt_disable(); if (cpu_has_mipsmt) { unsigned int vpflags = dvpe(); flags = read_c0_status(); @@ -471,12 +473,16 @@ */ asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit) { + /* do the secure computing check first */ + secure_computing(regs->orig_eax); + if (unlikely(current->audit_context) && entryexit) audit_syscall_exit(AUDITSC_RESULT(regs->regs[2]), regs->regs[2]); if (!(current->ptrace & PT_PTRACED)) goto out; + if (!test_thread_flag(TIF_SYSCALL_TRACE)) goto out; @@ -494,9 +500,14 @@ send_sig(current->exit_code, current, 1); current->exit_code = 0; } - out: + +out: + /* There is no ->orig_eax and that's quite intensional for now making + this work will require some work in various other place before it's + more than a placebo. */ + if (unlikely(current->audit_context) && !entryexit) - audit_syscall_entry(audit_arch(), regs->regs[2], - regs->regs[4], regs->regs[5], - regs->regs[6], regs->regs[7]); + audit_syscall_entry(audit_arch(), regs->orig_eax, + regs->regs[4], regs->regs[5], + regs->regs[6], regs->regs[7]); } diff -Naur linux-2.6.18.3/arch/mips/kernel/ptrace32.c linux-mips-2.6.18.3/arch/mips/kernel/ptrace32.c --- linux-2.6.18.3/arch/mips/kernel/ptrace32.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/kernel/ptrace32.c 2006-11-20 10:09:08.000000000 -0800 @@ -175,7 +175,9 @@ unsigned int mtflags; #endif /* CONFIG_MIPS_MT_SMTC */ + preempt_disable(); if (!cpu_has_fpu) { + preempt_enable(); tmp = 0; break; } @@ -186,7 +188,6 @@ mtflags = dmt(); #endif /* CONFIG_MIPS_MT_SMTC */ - preempt_disable(); if (cpu_has_mipsmt) { unsigned int vpflags = dvpe(); flags = read_c0_status(); diff -Naur linux-2.6.18.3/arch/mips/kernel/r4k_switch.S linux-mips-2.6.18.3/arch/mips/kernel/r4k_switch.S --- linux-2.6.18.3/arch/mips/kernel/r4k_switch.S 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/kernel/r4k_switch.S 2006-11-20 10:09:08.000000000 -0800 @@ -85,7 +85,12 @@ move $28, a2 cpu_restore_nonscratch a1 +#if (_THREAD_SIZE - 32) < 0x10000 PTR_ADDIU t0, $28, _THREAD_SIZE - 32 +#else + PTR_LI t0, _THREAD_SIZE - 32 + PTR_ADDU t0, $28 +#endif set_saved_sp t0, t1, t2 #ifdef CONFIG_MIPS_MT_SMTC /* Read-modify-writes of Status must be atomic on a VPE */ diff -Naur linux-2.6.18.3/arch/mips/kernel/scall32-o32.S linux-mips-2.6.18.3/arch/mips/kernel/scall32-o32.S --- linux-2.6.18.3/arch/mips/kernel/scall32-o32.S 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/kernel/scall32-o32.S 2006-11-20 10:09:08.000000000 -0800 @@ -662,6 +662,8 @@ sys sys_tee 4 sys sys_vmsplice 4 sys sys_move_pages 6 + sys sys_set_robust_list 2 + sys sys_get_robust_list 3 .endm /* We pre-compute the number of _instruction_ bytes needed to diff -Naur linux-2.6.18.3/arch/mips/kernel/scall64-64.S linux-mips-2.6.18.3/arch/mips/kernel/scall64-64.S --- linux-2.6.18.3/arch/mips/kernel/scall64-64.S 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/kernel/scall64-64.S 2006-11-20 10:09:08.000000000 -0800 @@ -466,3 +466,5 @@ PTR sys_tee /* 5265 */ PTR sys_vmsplice PTR sys_move_pages + PTR sys_set_robust_list + PTR sys_get_robust_list diff -Naur linux-2.6.18.3/arch/mips/kernel/scall64-n32.S linux-mips-2.6.18.3/arch/mips/kernel/scall64-n32.S --- linux-2.6.18.3/arch/mips/kernel/scall64-n32.S 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/kernel/scall64-n32.S 2006-11-20 10:09:08.000000000 -0800 @@ -149,8 +149,8 @@ PTR sys_mincore PTR sys_madvise PTR sys_shmget - PTR sys32_shmat - PTR sys_shmctl /* 6030 */ + PTR sys_shmat + PTR compat_sys_shmctl /* 6030 */ PTR sys_dup PTR sys_dup2 PTR sys_pause @@ -184,12 +184,12 @@ PTR sys32_newuname PTR sys_semget PTR sys_semop - PTR sys_semctl + PTR sysn32_semctl PTR sys_shmdt /* 6065 */ PTR sys_msgget - PTR sys_msgsnd - PTR sys_msgrcv - PTR sys_msgctl + PTR compat_sys_msgsnd + PTR compat_sys_msgrcv + PTR compat_sys_msgctl PTR compat_sys_fcntl /* 6070 */ PTR sys_flock PTR sys_fsync @@ -247,7 +247,7 @@ PTR sys_capset PTR sys32_rt_sigpending /* 6125 */ PTR compat_sys_rt_sigtimedwait - PTR sys_rt_sigqueueinfo + PTR sys32_rt_sigqueueinfo PTR sysn32_rt_sigsuspend PTR sys32_sigaltstack PTR compat_sys_utime /* 6130 */ @@ -280,7 +280,7 @@ PTR sys_sync PTR sys_acct PTR sys32_settimeofday - PTR sys_mount /* 6160 */ + PTR compat_sys_mount /* 6160 */ PTR sys_umount PTR sys_swapon PTR sys_swapoff @@ -335,7 +335,7 @@ PTR compat_sys_fcntl64 PTR sys_set_tid_address PTR sys_restart_syscall - PTR sys_semtimedop /* 6215 */ + PTR compat_sys_semtimedop /* 6215 */ PTR sys_fadvise64_64 PTR compat_sys_statfs64 PTR compat_sys_fstatfs64 @@ -390,5 +390,7 @@ PTR sys_splice PTR sys_sync_file_range PTR sys_tee - PTR sys_vmsplice /* 6271 */ + PTR sys_vmsplice /* 6270 */ PTR sys_move_pages + PTR compat_sys_set_robust_list + PTR compat_sys_get_robust_list diff -Naur linux-2.6.18.3/arch/mips/kernel/scall64-o32.S linux-mips-2.6.18.3/arch/mips/kernel/scall64-o32.S --- linux-2.6.18.3/arch/mips/kernel/scall64-o32.S 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/kernel/scall64-o32.S 2006-11-20 10:09:08.000000000 -0800 @@ -226,7 +226,7 @@ PTR sys_ni_syscall /* was sys_stat */ PTR sys_lseek PTR sys_getpid /* 4020 */ - PTR sys_mount + PTR compat_sys_mount PTR sys_oldumount PTR sys_setuid PTR sys_getuid @@ -498,7 +498,7 @@ PTR sys_mknodat /* 4290 */ PTR sys_fchownat PTR compat_sys_futimesat - PTR compat_sys_newfstatat + PTR sys_newfstatat PTR sys_unlinkat PTR sys_renameat /* 4295 */ PTR sys_linkat @@ -514,4 +514,6 @@ PTR sys_tee PTR sys_vmsplice PTR compat_sys_move_pages + PTR compat_sys_set_robust_list + PTR compat_sys_get_robust_list /* 4310 */ .size sys_call_table,.-sys_call_table diff -Naur linux-2.6.18.3/arch/mips/kernel/signal.c linux-mips-2.6.18.3/arch/mips/kernel/signal.c --- linux-2.6.18.3/arch/mips/kernel/signal.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/kernel/signal.c 2006-11-20 10:09:08.000000000 -0800 @@ -424,15 +424,11 @@ if (!user_mode(regs)) return; - if (try_to_freeze()) - goto no_signal; - if (test_thread_flag(TIF_RESTORE_SIGMASK)) oldset = ¤t->saved_sigmask; else oldset = ¤t->blocked; - signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { /* Whee! Actually deliver the signal. */ @@ -446,9 +442,10 @@ if (test_thread_flag(TIF_RESTORE_SIGMASK)) clear_thread_flag(TIF_RESTORE_SIGMASK); } + + return; } -no_signal: /* * Who's code doesn't conform to the restartable syscall convention * dies here!!! The li instruction, a single machine instruction, @@ -466,6 +463,7 @@ regs->regs[7] = regs->regs[26]; regs->cp0_epc -= 4; } + regs->regs[0] = 0; /* Don't deal with this again. */ } /* diff -Naur linux-2.6.18.3/arch/mips/kernel/signal32.c linux-mips-2.6.18.3/arch/mips/kernel/signal32.c --- linux-2.6.18.3/arch/mips/kernel/signal32.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/kernel/signal32.c 2006-11-20 10:09:08.000000000 -0800 @@ -815,9 +815,6 @@ if (!user_mode(regs)) return; - if (try_to_freeze()) - goto no_signal; - if (test_thread_flag(TIF_RESTORE_SIGMASK)) oldset = ¤t->saved_sigmask; else @@ -836,9 +833,10 @@ if (test_thread_flag(TIF_RESTORE_SIGMASK)) clear_thread_flag(TIF_RESTORE_SIGMASK); } + + return; } -no_signal: /* * Who's code doesn't conform to the restartable syscall convention * dies here!!! The li instruction, a single machine instruction, @@ -856,6 +854,7 @@ regs->regs[7] = regs->regs[26]; regs->cp0_epc -= 4; } + regs->regs[0] = 0; /* Don't deal with this again. */ } /* diff -Naur linux-2.6.18.3/arch/mips/kernel/smp-mt.c linux-mips-2.6.18.3/arch/mips/kernel/smp-mt.c --- linux-2.6.18.3/arch/mips/kernel/smp-mt.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/kernel/smp-mt.c 2006-11-20 10:09:08.000000000 -0800 @@ -203,7 +203,7 @@ write_vpe_c0_config( read_c0_config()); /* make sure there are no software interrupts pending */ - write_vpe_c0_cause(read_vpe_c0_cause() & ~(C_SW1|C_SW0)); + write_vpe_c0_cause(0); /* Propagate Config7 */ write_vpe_c0_config7(read_c0_config7()); diff -Naur linux-2.6.18.3/arch/mips/kernel/smp.c linux-mips-2.6.18.3/arch/mips/kernel/smp.c --- linux-2.6.18.3/arch/mips/kernel/smp.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/kernel/smp.c 2006-11-20 10:09:08.000000000 -0800 @@ -467,14 +467,18 @@ static int __init topology_init(void) { - int cpu; - int ret; + int i, ret; - for_each_present_cpu(cpu) { - ret = register_cpu(&per_cpu(cpu_devices, cpu), cpu); +#ifdef CONFIG_NUMA + for_each_online_node(i) + register_one_node(i); +#endif /* CONFIG_NUMA */ + + for_each_present_cpu(i) { + ret = register_cpu(&per_cpu(cpu_devices, i), i); if (ret) printk(KERN_WARNING "topology_init: register_cpu %d " - "failed (%d)\n", cpu, ret); + "failed (%d)\n", i, ret); } return 0; diff -Naur linux-2.6.18.3/arch/mips/kernel/smtc-asm.S linux-mips-2.6.18.3/arch/mips/kernel/smtc-asm.S --- linux-2.6.18.3/arch/mips/kernel/smtc-asm.S 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/kernel/smtc-asm.S 2006-11-20 10:09:08.000000000 -0800 @@ -8,7 +8,7 @@ #include #include #include -#include +#include /* * "Software Interrupt" linkage. diff -Naur linux-2.6.18.3/arch/mips/kernel/syscall.c linux-mips-2.6.18.3/arch/mips/kernel/syscall.c --- linux-2.6.18.3/arch/mips/kernel/syscall.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/kernel/syscall.c 2006-11-20 10:09:08.000000000 -0800 @@ -263,7 +263,7 @@ return error; } -void sys_set_thread_area(unsigned long addr) +asmlinkage int sys_set_thread_area(unsigned long addr) { struct thread_info *ti = task_thread_info(current); @@ -271,6 +271,8 @@ /* If some future MIPS implementation has this register in hardware, * we will need to update it here (and in context switches). */ + + return 0; } asmlinkage int _sys_sysmips(int cmd, long arg1, int arg2, int arg3) diff -Naur linux-2.6.18.3/arch/mips/kernel/traps.c linux-mips-2.6.18.3/arch/mips/kernel/traps.c --- linux-2.6.18.3/arch/mips/kernel/traps.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/kernel/traps.c 2006-11-20 10:09:08.000000000 -0800 @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -64,7 +65,7 @@ extern asmlinkage void handle_reserved(void); extern int fpu_emulator_cop1Handler(struct pt_regs *xcp, - struct mips_fpu_struct *ctx); + struct mips_fpu_struct *ctx, int has_fpu); void (*board_be_init)(void); int (*board_be_handler)(struct pt_regs *regs, int is_fixup); @@ -72,28 +73,68 @@ void (*board_ejtag_handler_setup)(void); void (*board_bind_eic_interrupt)(int irq, int regset); -/* - * These constant is for searching for possible module text segments. - * MODULE_RANGE is a guess of how much space is likely to be vmalloced. - */ -#define MODULE_RANGE (8*1024*1024) + +static void show_raw_backtrace(unsigned long reg29) +{ + unsigned long *sp = (unsigned long *)reg29; + unsigned long addr; + + printk("Call Trace:"); +#ifdef CONFIG_KALLSYMS + printk("\n"); +#endif + while (!kstack_end(sp)) { + addr = *sp++; + if (__kernel_text_address(addr)) + print_ip_sym(addr); + } + printk("\n"); +} + +#ifdef CONFIG_KALLSYMS +static int raw_show_trace; +static int __init set_raw_show_trace(char *str) +{ + raw_show_trace = 1; + return 1; +} +__setup("raw_show_trace", set_raw_show_trace); + +extern unsigned long unwind_stack(struct task_struct *task, unsigned long *sp, + unsigned long pc, unsigned long ra); + +static void show_backtrace(struct task_struct *task, struct pt_regs *regs) +{ + unsigned long sp = regs->regs[29]; + unsigned long ra = regs->regs[31]; + unsigned long pc = regs->cp0_epc; + + if (raw_show_trace || !__kernel_text_address(pc)) { + show_raw_backtrace(sp); + return; + } + printk("Call Trace:\n"); + do { + print_ip_sym(pc); + pc = unwind_stack(task, &sp, pc, ra); + ra = 0; + } while (pc); + printk("\n"); +} +#else +#define show_backtrace(task, r) show_raw_backtrace((r)->regs[29]); +#endif /* * This routine abuses get_user()/put_user() to reference pointers * with at least a bit of error checking ... */ -void show_stack(struct task_struct *task, unsigned long *sp) +static void show_stacktrace(struct task_struct *task, struct pt_regs *regs) { const int field = 2 * sizeof(unsigned long); long stackdata; int i; - - if (!sp) { - if (task && task != current) - sp = (unsigned long *) task->thread.reg29; - else - sp = (unsigned long *) &sp; - } + unsigned long *sp = (unsigned long *)regs->regs[29]; printk("Stack :"); i = 0; @@ -114,32 +155,48 @@ i++; } printk("\n"); + show_backtrace(task, regs); } -void show_trace(struct task_struct *task, unsigned long *stack) +static __always_inline void prepare_frametrace(struct pt_regs *regs) { - const int field = 2 * sizeof(unsigned long); - unsigned long addr; - - if (!stack) { - if (task && task != current) - stack = (unsigned long *) task->thread.reg29; - else - stack = (unsigned long *) &stack; - } - - printk("Call Trace:"); -#ifdef CONFIG_KALLSYMS - printk("\n"); + __asm__ __volatile__( + ".set push\n\t" + ".set noat\n\t" +#ifdef CONFIG_64BIT + "1: dla $1, 1b\n\t" + "sd $1, %0\n\t" + "sd $29, %1\n\t" + "sd $31, %2\n\t" +#else + "1: la $1, 1b\n\t" + "sw $1, %0\n\t" + "sw $29, %1\n\t" + "sw $31, %2\n\t" #endif - while (!kstack_end(stack)) { - addr = *stack++; - if (__kernel_text_address(addr)) { - printk(" [<%0*lx>] ", field, addr); - print_symbol("%s\n", addr); + ".set pop\n\t" + : "=m" (regs->cp0_epc), + "=m" (regs->regs[29]), "=m" (regs->regs[31]) + : : "memory"); +} + +void show_stack(struct task_struct *task, unsigned long *sp) +{ + struct pt_regs regs; + if (sp) { + regs.regs[29] = (unsigned long)sp; + regs.regs[31] = 0; + regs.cp0_epc = 0; + } else { + if (task && task != current) { + regs.regs[29] = task->thread.reg29; + regs.regs[31] = 0; + regs.cp0_epc = task->thread.reg31; + } else { + prepare_frametrace(®s); } } - printk("\n"); + show_stacktrace(task, ®s); } /* @@ -147,9 +204,15 @@ */ void dump_stack(void) { - unsigned long stack; + struct pt_regs regs; - show_trace(current, &stack); + /* + * Remove any garbage that may be in regs (specially func + * addresses) to avoid show_raw_backtrace() to report them + */ + memset(®s, 0, sizeof(regs)); + prepare_frametrace(®s); + show_backtrace(current, ®s); } EXPORT_SYMBOL(dump_stack); @@ -268,8 +331,7 @@ print_modules(); printk("Process %s (pid: %d, threadinfo=%p, task=%p)\n", current->comm, current->pid, current_thread_info(), current); - show_stack(current, (long *) regs->regs[29]); - show_trace(current, (long *) regs->regs[29]); + show_stacktrace(current, regs); show_code((unsigned int *) regs->cp0_epc); printk("\n"); } @@ -292,6 +354,16 @@ printk("%s[#%d]:\n", str, ++die_counter); show_registers(regs); spin_unlock_irq(&die_lock); + + if (in_interrupt()) + panic("Fatal exception in interrupt"); + + if (panic_on_oops) { + printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n"); + ssleep(5); + panic("Fatal exception"); + } + do_exit(SIGSEGV); } @@ -601,7 +673,7 @@ preempt_enable(); /* Run the emulator */ - sig = fpu_emulator_cop1Handler (regs, ¤t->thread.fpu); + sig = fpu_emulator_cop1Handler (regs, ¤t->thread.fpu, 1); preempt_disable(); @@ -751,11 +823,13 @@ set_used_math(); } - preempt_enable(); - - if (!cpu_has_fpu) { - int sig = fpu_emulator_cop1Handler(regs, - ¤t->thread.fpu); + if (cpu_has_fpu) { + preempt_enable(); + } else { + int sig; + preempt_enable(); + sig = fpu_emulator_cop1Handler(regs, + ¤t->thread.fpu, 0); if (sig) force_sig(sig, current); #ifdef CONFIG_MIPS_MT_FPAFF diff -Naur linux-2.6.18.3/arch/mips/kernel/vmlinux.lds.S linux-mips-2.6.18.3/arch/mips/kernel/vmlinux.lds.S --- linux-2.6.18.3/arch/mips/kernel/vmlinux.lds.S 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/kernel/vmlinux.lds.S 2006-11-20 10:09:08.000000000 -0800 @@ -50,6 +50,16 @@ /* writeable */ .data : { /* Data */ . = . + DATAOFFSET; /* for CONFIG_MAPPED_KERNEL */ + /* + * This ALIGN is needed as a workaround for a bug a gcc bug upto 4.1 which + * limits the maximum alignment to at most 32kB and results in the following + * warning: + * + * CC arch/mips/kernel/init_task.o + * arch/mips/kernel/init_task.c:30: warning: alignment of ‘init_thread_union’ + * is greater than maximum object file alignment. Using 32768 + */ + . = ALIGN(_PAGE_SIZE); *(.data.init_task) *(.data) diff -Naur linux-2.6.18.3/arch/mips/kernel/vpe.c linux-mips-2.6.18.3/arch/mips/kernel/vpe.c --- linux-2.6.18.3/arch/mips/kernel/vpe.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/kernel/vpe.c 2006-11-20 10:09:08.000000000 -0800 @@ -768,10 +768,16 @@ */ write_tc_c0_tcbind((read_tc_c0_tcbind() & ~TCBIND_CURVPE) | v->minor); + write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() & ~(VPECONF0_VPA)); + + back_to_back_c0_hazard(); + /* Set up the XTC bit in vpeconf0 to point at our tc */ write_vpe_c0_vpeconf0( (read_vpe_c0_vpeconf0() & ~(VPECONF0_XTC)) | (t->index << VPECONF0_XTC_SHIFT)); + back_to_back_c0_hazard(); + /* enable this VPE */ write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA); diff -Naur linux-2.6.18.3/arch/mips/lib/Makefile linux-mips-2.6.18.3/arch/mips/lib/Makefile --- linux-2.6.18.3/arch/mips/lib/Makefile 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/lib/Makefile 2006-11-20 10:09:08.000000000 -0800 @@ -5,8 +5,6 @@ lib-y += csum_partial_copy.o memcpy.o promlib.o strlen_user.o strncpy_user.o \ strnlen_user.o uncached.o -obj-y += iomap.o - # libgcc-style stuff needed in the kernel lib-y += ashldi3.o ashrdi3.o lshrdi3.o diff -Naur linux-2.6.18.3/arch/mips/lib/iomap.c linux-mips-2.6.18.3/arch/mips/lib/iomap.c --- linux-2.6.18.3/arch/mips/lib/iomap.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/lib/iomap.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,78 +0,0 @@ -/* - * iomap.c, Memory Mapped I/O routines for MIPS architecture. - * - * This code is based on lib/iomap.c, by Linus Torvalds. - * - * Copyright (C) 2004-2005 Yoichi Yuasa - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include -#include -#include - -#include - -void __iomem *ioport_map(unsigned long port, unsigned int nr) -{ - unsigned long end; - - end = port + nr - 1UL; - if (ioport_resource.start > port || - ioport_resource.end < end || port > end) - return NULL; - - return (void __iomem *)(mips_io_port_base + port); -} - -void ioport_unmap(void __iomem *addr) -{ -} -EXPORT_SYMBOL(ioport_map); -EXPORT_SYMBOL(ioport_unmap); - -void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) -{ - unsigned long start, len, flags; - - if (dev == NULL) - return NULL; - - start = pci_resource_start(dev, bar); - len = pci_resource_len(dev, bar); - if (!start || !len) - return NULL; - - if (maxlen != 0 && len > maxlen) - len = maxlen; - - flags = pci_resource_flags(dev, bar); - if (flags & IORESOURCE_IO) - return ioport_map(start, len); - if (flags & IORESOURCE_MEM) { - if (flags & IORESOURCE_CACHEABLE) - return ioremap_cachable(start, len); - return ioremap_nocache(start, len); - } - - return NULL; -} - -void pci_iounmap(struct pci_dev *dev, void __iomem *addr) -{ - iounmap(addr); -} -EXPORT_SYMBOL(pci_iomap); -EXPORT_SYMBOL(pci_iounmap); diff -Naur linux-2.6.18.3/arch/mips/lib-32/dump_tlb.c linux-mips-2.6.18.3/arch/mips/lib-32/dump_tlb.c --- linux-2.6.18.3/arch/mips/lib-32/dump_tlb.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/lib-32/dump_tlb.c 2006-11-20 10:09:08.000000000 -0800 @@ -40,8 +40,6 @@ return "256Mb"; #endif } - - return "unknown"; } #define BARRIER() \ diff -Naur linux-2.6.18.3/arch/mips/lib-64/dump_tlb.c linux-mips-2.6.18.3/arch/mips/lib-64/dump_tlb.c --- linux-2.6.18.3/arch/mips/lib-64/dump_tlb.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/lib-64/dump_tlb.c 2006-11-20 10:09:08.000000000 -0800 @@ -31,8 +31,6 @@ case PM_256M: return "256Mb"; #endif } - - return "unknown"; } #define BARRIER() \ @@ -149,7 +147,7 @@ printk("Addr == %08lx\n", addr); printk("tasks->mm.pgd == %08lx\n", (unsigned long) t->mm->pgd); - page_dir = pgd_offset(t->mm, 0); + page_dir = pgd_offset(t->mm, 0UL); printk("page_dir == %016lx\n", (unsigned long) page_dir); pgd = pgd_offset(t->mm, addr); @@ -184,13 +182,13 @@ dump_list_process(current, address); } -unsigned int vtop(void *address) +unsigned long vtop(void *address) { pgd_t *pgd; pud_t *pud; pmd_t *pmd; pte_t *pte; - unsigned int addr, paddr; + unsigned long addr, paddr; addr = (unsigned long) address; pgd = pgd_offset(current->mm, addr); diff -Naur linux-2.6.18.3/arch/mips/math-emu/cp1emu.c linux-mips-2.6.18.3/arch/mips/math-emu/cp1emu.c --- linux-2.6.18.3/arch/mips/math-emu/cp1emu.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/math-emu/cp1emu.c 2006-11-20 10:09:08.000000000 -0800 @@ -38,8 +38,6 @@ #include #include -#include -#include #include #include #include @@ -1233,7 +1231,8 @@ return 0; } -int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx) +int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx, + int has_fpu) { unsigned long oldepc, prevepc; mips_instruction insn; @@ -1263,7 +1262,7 @@ ieee754_csr.rm = mips_rm[ieee754_csr.rm]; } - if (cpu_has_fpu) + if (has_fpu) break; if (sig) break; diff -Naur linux-2.6.18.3/arch/mips/mips-boards/atlas/atlas_int.c linux-mips-2.6.18.3/arch/mips/mips-boards/atlas/atlas_int.c --- linux-2.6.18.3/arch/mips/mips-boards/atlas/atlas_int.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/mips-boards/atlas/atlas_int.c 2006-11-20 10:09:08.000000000 -0800 @@ -1,6 +1,8 @@ /* - * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. + * Copyright (C) 1999, 2000, 2006 MIPS Technologies, Inc. + * All rights reserved. + * Authors: Carsten Langgaard + * Maciej W. Rozycki * * ######################################################################## * @@ -25,17 +27,20 @@ */ #include #include +#include #include #include #include #include -#include +#include #include +#include +#include + #include #include -#include - +#include static struct atlas_ictrl_regs *atlas_hw0_icregs; @@ -47,13 +52,13 @@ void disable_atlas_irq(unsigned int irq_nr) { - atlas_hw0_icregs->intrsten = (1 << (irq_nr-ATLASINT_BASE)); + atlas_hw0_icregs->intrsten = 1 << (irq_nr - ATLAS_INT_BASE); iob(); } void enable_atlas_irq(unsigned int irq_nr) { - atlas_hw0_icregs->intseten = (1 << (irq_nr-ATLASINT_BASE)); + atlas_hw0_icregs->intseten = 1 << (irq_nr - ATLAS_INT_BASE); iob(); } @@ -107,7 +112,7 @@ if (unlikely(int_status == 0)) return; - irq = ATLASINT_BASE + ls1bit32(int_status); + irq = ATLAS_INT_BASE + ls1bit32(int_status); DEBUG_INT("atlas_hw0_irqdispatch: irq=%d\n", irq); @@ -161,15 +166,14 @@ } /* - * IRQs on the Atlas board look basically (barring software IRQs which we - * don't use at all and all external interrupt sources are combined together - * on hardware interrupt 0 (MIPS IRQ 2)) like: + * IRQs on the Atlas board look basically like (all external interrupt + * sources are combined together on hardware interrupt 0 (MIPS IRQ 2)): * - * MIPS IRQ Source + * MIPS IRQ Source * -------- ------ - * 0 Software (ignored) - * 1 Software (ignored) - * 2 Combined hardware interrupt (hw0) + * 0 Software 0 (reschedule IPI on MT) + * 1 Software 1 (remote call IPI on MT) + * 2 Combined Atlas hardware interrupt (hw0) * 3 Hardware (ignored) * 4 Hardware (ignored) * 5 Hardware (ignored) @@ -179,7 +183,7 @@ * We handle the IRQ according to _our_ priority which is: * * Highest ---- R4k Timer - * Lowest ---- Combined hardware interrupt + * Lowest ---- Software 0 * * then we just return, if multiple IRQs are pending then we will just take * another exception, big deal. @@ -193,17 +197,19 @@ if (irq == MIPSCPU_INT_ATLAS) atlas_hw0_irqdispatch(regs); - else if (irq > 0) + else if (irq >= 0) do_IRQ(MIPSCPU_INT_BASE + irq, regs); else spurious_interrupt(regs); } -void __init arch_init_irq(void) +static inline void init_atlas_irqs (int base) { int i; - atlas_hw0_icregs = (struct atlas_ictrl_regs *)ioremap (ATLAS_ICTRL_REGS_BASE, sizeof(struct atlas_ictrl_regs *)); + atlas_hw0_icregs = (struct atlas_ictrl_regs *) + ioremap(ATLAS_ICTRL_REGS_BASE, + sizeof(struct atlas_ictrl_regs *)); /* * Mask out all interrupt by writing "1" to all bit position in @@ -211,7 +217,7 @@ */ atlas_hw0_icregs->intrsten = 0xffffffff; - for (i = ATLASINT_BASE; i <= ATLASINT_END; i++) { + for (i = ATLAS_INT_BASE; i <= ATLAS_INT_END; i++) { irq_desc[i].status = IRQ_DISABLED; irq_desc[i].action = 0; irq_desc[i].depth = 1; @@ -219,3 +225,62 @@ spin_lock_init(&irq_desc[i].lock); } } + +static struct irqaction atlasirq = { + .handler = no_action, + .name = "Atlas cascade" +}; + +msc_irqmap_t __initdata msc_irqmap[] = { + {MSC01C_INT_TMR, MSC01_IRQ_EDGE, 0}, + {MSC01C_INT_PCI, MSC01_IRQ_LEVEL, 0}, +}; +int __initdata msc_nr_irqs = sizeof(msc_irqmap) / sizeof(*msc_irqmap); + +msc_irqmap_t __initdata msc_eicirqmap[] = { + {MSC01E_INT_SW0, MSC01_IRQ_LEVEL, 0}, + {MSC01E_INT_SW1, MSC01_IRQ_LEVEL, 0}, + {MSC01E_INT_ATLAS, MSC01_IRQ_LEVEL, 0}, + {MSC01E_INT_TMR, MSC01_IRQ_EDGE, 0}, + {MSC01E_INT_PCI, MSC01_IRQ_LEVEL, 0}, + {MSC01E_INT_PERFCTR, MSC01_IRQ_LEVEL, 0}, + {MSC01E_INT_CPUCTR, MSC01_IRQ_LEVEL, 0} +}; +int __initdata msc_nr_eicirqs = sizeof(msc_eicirqmap) / sizeof(*msc_eicirqmap); + +void __init arch_init_irq(void) +{ + init_atlas_irqs(ATLAS_INT_BASE); + + if (!cpu_has_veic) + mips_cpu_irq_init(MIPSCPU_INT_BASE); + + switch(mips_revision_corid) { + case MIPS_REVISION_CORID_CORE_MSC: + case MIPS_REVISION_CORID_CORE_FPGA2: + case MIPS_REVISION_CORID_CORE_FPGA3: + case MIPS_REVISION_CORID_CORE_24K: + case MIPS_REVISION_CORID_CORE_EMUL_MSC: + if (cpu_has_veic) + init_msc_irqs (MSC01E_INT_BASE, + msc_eicirqmap, msc_nr_eicirqs); + else + init_msc_irqs (MSC01C_INT_BASE, + msc_irqmap, msc_nr_irqs); + } + + + if (cpu_has_veic) { + set_vi_handler (MSC01E_INT_ATLAS, atlas_hw0_irqdispatch); + setup_irq (MSC01E_INT_BASE + MSC01E_INT_ATLAS, &atlasirq); + } else if (cpu_has_vint) { + set_vi_handler (MIPSCPU_INT_ATLAS, atlas_hw0_irqdispatch); +#ifdef CONFIG_MIPS_MT_SMTC + setup_irq_smtc (MIPSCPU_INT_BASE + MIPSCPU_INT_ATLAS, + &atlasirq, (0x100 << MIPSCPU_INT_ATLAS)); +#else /* Not SMTC */ + setup_irq(MIPSCPU_INT_BASE + MIPSCPU_INT_ATLAS, &atlasirq); +#endif /* CONFIG_MIPS_MT_SMTC */ + } else + setup_irq(MIPSCPU_INT_BASE + MIPSCPU_INT_ATLAS, &atlasirq); +} diff -Naur linux-2.6.18.3/arch/mips/mips-boards/atlas/atlas_setup.c linux-mips-2.6.18.3/arch/mips/mips-boards/atlas/atlas_setup.c --- linux-2.6.18.3/arch/mips/mips-boards/atlas/atlas_setup.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/mips-boards/atlas/atlas_setup.c 2006-11-20 10:09:08.000000000 -0800 @@ -77,7 +77,7 @@ #else s.iobase = ATLAS_UART_REGS_BASE+3; #endif - s.irq = ATLASINT_UART; + s.irq = ATLAS_INT_UART; s.uartclk = ATLAS_BASE_BAUD * 16; s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_AUTO_IRQ; s.iotype = UPIO_PORT; diff -Naur linux-2.6.18.3/arch/mips/mips-boards/generic/memory.c linux-mips-2.6.18.3/arch/mips/mips-boards/generic/memory.c --- linux-2.6.18.3/arch/mips/mips-boards/generic/memory.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/mips-boards/generic/memory.c 2006-11-20 10:09:08.000000000 -0800 @@ -176,7 +176,7 @@ if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA) continue; - addr = boot_mem_map.map[i].addr; + addr = PAGE_ALIGN(boot_mem_map.map[i].addr); while (addr < boot_mem_map.map[i].addr + boot_mem_map.map[i].size) { ClearPageReserved(virt_to_page(__va(addr))); diff -Naur linux-2.6.18.3/arch/mips/mips-boards/generic/time.c linux-mips-2.6.18.3/arch/mips/mips-boards/generic/time.c --- linux-2.6.18.3/arch/mips/mips-boards/generic/time.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/mips-boards/generic/time.c 2006-11-20 10:09:08.000000000 -0800 @@ -41,8 +41,13 @@ #include #include + +#ifdef CONFIG_MIPS_ATLAS +#include +#endif +#ifdef CONFIG_MIPS_MALTA #include -#include +#endif unsigned long cpu_khz; @@ -92,10 +97,9 @@ irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { int cpu = smp_processor_id(); - int r2 = cpu_has_mips_r2; #ifdef CONFIG_MIPS_MT_SMTC - /* + /* * In an SMTC system, one Count/Compare set exists per VPE. * Which TC within a VPE gets the interrupt is essentially * random - we only know that it shouldn't be one with @@ -108,29 +112,46 @@ * the general MIPS timer_interrupt routine. */ + int vpflags; + /* - * DVPE is necessary so long as cross-VPE interrupts - * are done via read-modify-write of Cause register. + * We could be here due to timer interrupt, + * perf counter overflow, or both. */ - int vpflags = dvpe(); - write_c0_compare (read_c0_count() - 1); - clear_c0_cause(CPUCTR_IMASKBIT); - evpe(vpflags); - - if (cpu_data[cpu].vpe_id == 0) { - timer_interrupt(irq, dev_id, regs); - scroll_display_message(); - } else - write_c0_compare (read_c0_count() + ( mips_hpt_frequency/HZ)); - smtc_timer_broadcast(cpu_data[cpu].vpe_id); + if (read_c0_cause() & (1 << 26)) + perf_irq(regs); - if (cpu != 0) + if (read_c0_cause() & (1 << 30)) { + /* If timer interrupt, make it de-assert */ + write_c0_compare (read_c0_count() - 1); /* - * Other CPUs should do profiling and process accounting + * DVPE is necessary so long as cross-VPE interrupts + * are done via read-modify-write of Cause register. */ - local_timer_interrupt(irq, dev_id, regs); - + vpflags = dvpe(); + clear_c0_cause(CPUCTR_IMASKBIT); + evpe(vpflags); + /* + * There are things we only want to do once per tick + * in an "MP" system. One TC of each VPE will take + * the actual timer interrupt. The others will get + * timer broadcast IPIs. We use whoever it is that takes + * the tick on VPE 0 to run the full timer_interrupt(). + */ + if (cpu_data[cpu].vpe_id == 0) { + timer_interrupt(irq, NULL, regs); + smtc_timer_broadcast(cpu_data[cpu].vpe_id); + scroll_display_message(); + } else { + write_c0_compare(read_c0_count() + + (mips_hpt_frequency/HZ)); + local_timer_interrupt(irq, dev_id, regs); + smtc_timer_broadcast(cpu_data[cpu].vpe_id); + } + } #else /* CONFIG_MIPS_MT_SMTC */ + int r2 = cpu_has_mips_r2; + if (cpu == 0) { /* * CPU 0 handles the global timer interrupt job and process @@ -161,14 +182,13 @@ */ local_timer_interrupt(irq, dev_id, regs); } -#endif /* CONFIG_MIPS_MT_SMTC */ - out: +#endif /* CONFIG_MIPS_MT_SMTC */ return IRQ_HANDLED; } /* - * Estimate CPU frequency. Sets mips_counter_frequency as a side-effect + * Estimate CPU frequency. Sets mips_hpt_frequency as a side-effect */ static unsigned int __init estimate_cpu_frequency(void) { diff -Naur linux-2.6.18.3/arch/mips/mips-boards/malta/malta_int.c linux-mips-2.6.18.3/arch/mips/mips-boards/malta/malta_int.c --- linux-2.6.18.3/arch/mips/mips-boards/malta/malta_int.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/mips-boards/malta/malta_int.c 2006-11-20 10:09:08.000000000 -0800 @@ -208,23 +208,23 @@ unsigned int a0 = 7; unsigned int t0; - t0 = s0 & 0xf000; + t0 = pending & 0xf000; t0 = t0 < 1; t0 = t0 << 2; a0 = a0 - t0; - s0 = s0 << t0; + pending = pending << t0; - t0 = s0 & 0xc000; + t0 = pending & 0xc000; t0 = t0 < 1; t0 = t0 << 1; a0 = a0 - t0; - s0 = s0 << t0; + pending = pending << t0; - t0 = s0 & 0x8000; + t0 = pending & 0x8000; t0 = t0 < 1; //t0 = t0 << 2; a0 = a0 - t0; - //s0 = s0 << t0; + //pending = pending << t0; return a0; #endif diff -Naur linux-2.6.18.3/arch/mips/mips-boards/sim/sim_time.c linux-mips-2.6.18.3/arch/mips/mips-boards/sim/sim_time.c --- linux-2.6.18.3/arch/mips/mips-boards/sim/sim_time.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/mips-boards/sim/sim_time.c 2006-11-20 10:09:08.000000000 -0800 @@ -103,7 +103,7 @@ /* - * Estimate CPU frequency. Sets mips_counter_frequency as a side-effect + * Estimate CPU frequency. Sets mips_hpt_frequency as a side-effect */ static unsigned int __init estimate_cpu_frequency(void) { diff -Naur linux-2.6.18.3/arch/mips/mm/c-r3k.c linux-mips-2.6.18.3/arch/mips/mm/c-r3k.c --- linux-2.6.18.3/arch/mips/mm/c-r3k.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/mm/c-r3k.c 2006-11-20 10:09:08.000000000 -0800 @@ -335,7 +335,7 @@ flush_cache_mm = r3k_flush_cache_mm; flush_cache_range = r3k_flush_cache_range; flush_cache_page = r3k_flush_cache_page; - flush_icache_page = r3k_flush_icache_page; + __flush_icache_page = r3k_flush_icache_page; flush_icache_range = r3k_flush_icache_range; flush_cache_sigtramp = r3k_flush_cache_sigtramp; diff -Naur linux-2.6.18.3/arch/mips/mm/c-r4k.c linux-mips-2.6.18.3/arch/mips/mm/c-r4k.c --- linux-2.6.18.3/arch/mips/mm/c-r4k.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/mm/c-r4k.c 2006-11-20 10:09:08.000000000 -0800 @@ -475,7 +475,7 @@ } } if (exec) { - if (cpu_has_vtag_icache) { + if (cpu_has_vtag_icache && mm == current->active_mm) { int cpu = smp_processor_id(); if (cpu_context(cpu, mm) != 0) @@ -599,7 +599,7 @@ * We're not sure of the virtual address(es) involved here, so * we have to flush the entire I-cache. */ - if (cpu_has_vtag_icache) { + if (cpu_has_vtag_icache && vma->vm_mm == current->active_mm) { int cpu = smp_processor_id(); if (cpu_context(cpu, vma->vm_mm) != 0) @@ -1242,7 +1242,7 @@ clear_c0_config(CONF_CU); break; /* - * We need to catch the ealry Alchemy SOCs with + * We need to catch the early Alchemy SOCs with * the write-only co_config.od bit and set it back to one... */ case CPU_AU1000: /* rev. DA, HA, HB */ @@ -1291,7 +1291,7 @@ __flush_cache_all = r4k___flush_cache_all; flush_cache_mm = r4k_flush_cache_mm; flush_cache_page = r4k_flush_cache_page; - flush_icache_page = r4k_flush_icache_page; + __flush_icache_page = r4k_flush_icache_page; flush_cache_range = r4k_flush_cache_range; flush_cache_sigtramp = r4k_flush_cache_sigtramp; diff -Naur linux-2.6.18.3/arch/mips/mm/c-sb1.c linux-mips-2.6.18.3/arch/mips/mm/c-sb1.c --- linux-2.6.18.3/arch/mips/mm/c-sb1.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/mm/c-sb1.c 2006-11-20 10:09:08.000000000 -0800 @@ -19,6 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include +#include #include #include @@ -155,6 +156,26 @@ } /* + * Invalidate a range of the icache. The addresses are virtual, and + * the cache is virtually indexed and tagged. However, we don't + * necessarily have the right ASID context, so use index ops instead + * of hit ops. + */ +static inline void __sb1_flush_icache_range(unsigned long start, + unsigned long end) +{ + start &= ~(icache_line_size - 1); + end = (end + icache_line_size - 1) & ~(icache_line_size - 1); + + while (start != end) { + cache_set_op(Index_Invalidate_I, start & icache_index_mask); + start += icache_line_size; + } + mispredict(); + sync(); +} + +/* * Flush the icache for a given physical page. Need to writeback the * dcache first, then invalidate the icache. If the page isn't * executable, nothing is required. @@ -173,8 +194,11 @@ /* * Bumping the ASID is probably cheaper than the flush ... */ - if (cpu_context(cpu, vma->vm_mm) != 0) - drop_mmu_context(vma->vm_mm, cpu); + if (vma->vm_mm == current->active_mm) { + if (cpu_context(cpu, vma->vm_mm) != 0) + drop_mmu_context(vma->vm_mm, cpu); + } else + __sb1_flush_icache_range(addr, addr + PAGE_SIZE); } #ifdef CONFIG_SMP @@ -210,26 +234,25 @@ __attribute__((alias("local_sb1_flush_cache_page"))); #endif -/* - * Invalidate a range of the icache. The addresses are virtual, and - * the cache is virtually indexed and tagged. However, we don't - * necessarily have the right ASID context, so use index ops instead - * of hit ops. - */ -static inline void __sb1_flush_icache_range(unsigned long start, - unsigned long end) +#ifdef CONFIG_SMP +static void sb1_flush_cache_data_page_ipi(void *info) { - start &= ~(icache_line_size - 1); - end = (end + icache_line_size - 1) & ~(icache_line_size - 1); + unsigned long start = (unsigned long)info; - while (start != end) { - cache_set_op(Index_Invalidate_I, start & icache_index_mask); - start += icache_line_size; - } - mispredict(); - sync(); + __sb1_writeback_inv_dcache_range(start, start + PAGE_SIZE); } +static void sb1_flush_cache_data_page(unsigned long addr) +{ + if (in_atomic()) + __sb1_writeback_inv_dcache_range(addr, addr + PAGE_SIZE); + else + on_each_cpu(sb1_flush_cache_data_page_ipi, (void *) addr, 1, 1); +} +#else +void sb1_flush_cache_data_page(unsigned long) + __attribute__((alias("local_sb1_flush_cache_data_page"))); +#endif /* * Invalidate all caches on this CPU @@ -326,9 +349,12 @@ * If there's a context, bump the ASID (cheaper than a flush, * since we don't know VAs!) */ - if (cpu_context(cpu, vma->vm_mm) != 0) { - drop_mmu_context(vma->vm_mm, cpu); - } + if (vma->vm_mm == current->active_mm) { + if (cpu_context(cpu, vma->vm_mm) != 0) + drop_mmu_context(vma->vm_mm, cpu); + } else + __sb1_flush_icache_range(start, start + PAGE_SIZE); + } #ifdef CONFIG_SMP @@ -520,7 +546,7 @@ /* These routines are for Icache coherence with the Dcache */ flush_icache_range = sb1_flush_icache_range; - flush_icache_page = sb1_flush_icache_page; + __flush_icache_page = sb1_flush_icache_page; flush_icache_all = __sb1_flush_icache_all; /* local only */ /* This implies an Icache flush too, so can't be nop'ed */ @@ -528,7 +554,7 @@ flush_cache_sigtramp = sb1_flush_cache_sigtramp; local_flush_data_cache_page = (void *) sb1_nop; - flush_data_cache_page = (void *) sb1_nop; + flush_data_cache_page = sb1_flush_cache_data_page; /* Full flush */ __flush_cache_all = sb1___flush_cache_all; @@ -552,5 +578,5 @@ : : "memory"); - flush_cache_all(); + local_sb1___flush_cache_all(); } diff -Naur linux-2.6.18.3/arch/mips/mm/c-tx39.c linux-mips-2.6.18.3/arch/mips/mm/c-tx39.c --- linux-2.6.18.3/arch/mips/mm/c-tx39.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/mm/c-tx39.c 2006-11-20 10:09:08.000000000 -0800 @@ -382,7 +382,7 @@ flush_cache_mm = (void *) tx39h_flush_icache_all; flush_cache_range = (void *) tx39h_flush_icache_all; flush_cache_page = (void *) tx39h_flush_icache_all; - flush_icache_page = (void *) tx39h_flush_icache_all; + __flush_icache_page = (void *) tx39h_flush_icache_all; flush_icache_range = (void *) tx39h_flush_icache_all; flush_cache_sigtramp = (void *) tx39h_flush_icache_all; @@ -408,7 +408,7 @@ flush_cache_mm = tx39_flush_cache_mm; flush_cache_range = tx39_flush_cache_range; flush_cache_page = tx39_flush_cache_page; - flush_icache_page = tx39_flush_icache_page; + __flush_icache_page = tx39_flush_icache_page; flush_icache_range = tx39_flush_icache_range; flush_cache_sigtramp = tx39_flush_cache_sigtramp; diff -Naur linux-2.6.18.3/arch/mips/mm/cache.c linux-mips-2.6.18.3/arch/mips/mm/cache.c --- linux-2.6.18.3/arch/mips/mm/cache.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/mm/cache.c 2006-11-20 10:09:08.000000000 -0800 @@ -25,7 +25,7 @@ void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, unsigned long pfn); void (*flush_icache_range)(unsigned long start, unsigned long end); -void (*flush_icache_page)(struct vm_area_struct *vma, struct page *page); +void (*__flush_icache_page)(struct vm_area_struct *vma, struct page *page); /* MIPS specific cache operations */ void (*flush_cache_sigtramp)(unsigned long addr); @@ -70,6 +70,8 @@ struct address_space *mapping = page_mapping(page); unsigned long addr; + if (PageHighMem(page)) + return; if (mapping && !mapping_mapped(mapping)) { SetPageDcacheDirty(page); return; @@ -91,16 +93,16 @@ { struct page *page; unsigned long pfn, addr; + int exec = (vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc; pfn = pte_pfn(pte); - if (pfn_valid(pfn) && (page = pfn_to_page(pfn), page_mapping(page)) && - Page_dcache_dirty(page)) { - if (pages_do_alias((unsigned long)page_address(page), - address & PAGE_MASK)) { - addr = (unsigned long) page_address(page); + if (unlikely(!pfn_valid(pfn))) + return; + page = pfn_to_page(pfn); + if (page_mapping(page) && Page_dcache_dirty(page)) { + addr = (unsigned long) page_address(page); + if (exec || pages_do_alias(addr, address & PAGE_MASK)) flush_data_cache_page(addr); - } - ClearPageDcacheDirty(page); } } diff -Naur linux-2.6.18.3/arch/mips/mm/fault.c linux-mips-2.6.18.3/arch/mips/mm/fault.c --- linux-2.6.18.3/arch/mips/mm/fault.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/mm/fault.c 2006-11-20 10:09:08.000000000 -0800 @@ -89,7 +89,7 @@ if (!(vma->vm_flags & VM_WRITE)) goto bad_area; } else { - if (!(vma->vm_flags & (VM_READ | VM_EXEC))) + if (!(vma->vm_flags & (VM_READ | VM_WRITE | VM_EXEC))) goto bad_area; } diff -Naur linux-2.6.18.3/arch/mips/mm/init.c linux-mips-2.6.18.3/arch/mips/mm/init.c --- linux-2.6.18.3/arch/mips/mm/init.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/mm/init.c 2006-11-20 10:09:08.000000000 -0800 @@ -30,11 +30,39 @@ #include #include #include +#include #include #include #include #include #include +#include + +/* CP0 hazard avoidance. */ +#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \ + "nop; nop; nop; nop; nop; nop;\n\t" \ + ".set reorder\n\t") + +/* Atomicity and interruptability */ +#ifdef CONFIG_MIPS_MT_SMTC + +#include + +#define ENTER_CRITICAL(flags) \ + { \ + unsigned int mvpflags; \ + local_irq_save(flags);\ + mvpflags = dvpe() +#define EXIT_CRITICAL(flags) \ + evpe(mvpflags); \ + local_irq_restore(flags); \ + } +#else + +#define ENTER_CRITICAL(flags) local_irq_save(flags) +#define EXIT_CRITICAL(flags) local_irq_restore(flags) + +#endif /* CONFIG_MIPS_MT_SMTC */ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); @@ -80,13 +108,184 @@ return 1UL << order; } -#ifdef CONFIG_HIGHMEM -pte_t *kmap_pte; -pgprot_t kmap_prot; +/* + * These are almost like kmap_atomic / kunmap_atmic except they take an + * additional address argument as the hint. + */ #define kmap_get_fixmap_pte(vaddr) \ pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)), (vaddr)) +#ifdef CONFIG_MIPS_MT_SMTC +static pte_t *kmap_coherent_pte; +static void __init kmap_coherent_init(void) +{ + unsigned long vaddr; + + /* cache the first coherent kmap pte */ + vaddr = __fix_to_virt(FIX_CMAP_BEGIN); + kmap_coherent_pte = kmap_get_fixmap_pte(vaddr); +} +#else +static inline void kmap_coherent_init(void) {} +#endif + +static inline void *kmap_coherent(struct page *page, unsigned long addr) +{ + enum fixed_addresses idx; + unsigned long vaddr, flags, entrylo; + unsigned long old_ctx; + pte_t pte; + int tlbidx; + + inc_preempt_count(); + idx = (addr >> PAGE_SHIFT) & (FIX_N_COLOURS - 1); +#ifdef CONFIG_MIPS_MT_SMTC + idx += FIX_N_COLOURS * smp_processor_id(); +#endif + vaddr = __fix_to_virt(FIX_CMAP_END - idx); + pte = mk_pte(page, PAGE_KERNEL); +#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32_R1) + entrylo = pte.pte_high; +#else + entrylo = pte_val(pte) >> 6; +#endif + + ENTER_CRITICAL(flags); + old_ctx = read_c0_entryhi(); + write_c0_entryhi(vaddr & (PAGE_MASK << 1)); + write_c0_entrylo0(entrylo); + write_c0_entrylo1(entrylo); +#ifdef CONFIG_MIPS_MT_SMTC + set_pte(kmap_coherent_pte - (FIX_CMAP_END - idx), pte); + /* preload TLB instead of local_flush_tlb_one() */ + mtc0_tlbw_hazard(); + tlb_probe(); + BARRIER; + tlbidx = read_c0_index(); + mtc0_tlbw_hazard(); + if (tlbidx < 0) + tlb_write_random(); + else + tlb_write_indexed(); +#else + tlbidx = read_c0_wired(); + write_c0_wired(tlbidx + 1); + write_c0_index(tlbidx); + mtc0_tlbw_hazard(); + tlb_write_indexed(); +#endif + tlbw_use_hazard(); + write_c0_entryhi(old_ctx); + EXIT_CRITICAL(flags); + + return (void*) vaddr; +} + +#define UNIQUE_ENTRYHI(idx) (CKSEG0 + ((idx) << (PAGE_SHIFT + 1))) + +static inline void kunmap_coherent(struct page *page) +{ +#ifndef CONFIG_MIPS_MT_SMTC + unsigned int wired; + unsigned long flags, old_ctx; + + ENTER_CRITICAL(flags); + old_ctx = read_c0_entryhi(); + wired = read_c0_wired() - 1; + write_c0_wired(wired); + write_c0_index(wired); + write_c0_entryhi(UNIQUE_ENTRYHI(wired)); + write_c0_entrylo0(0); + write_c0_entrylo1(0); + mtc0_tlbw_hazard(); + tlb_write_indexed(); + tlbw_use_hazard(); + write_c0_entryhi(old_ctx); + EXIT_CRITICAL(flags); +#endif + dec_preempt_count(); + preempt_check_resched(); +} + +void copy_user_highpage(struct page *to, struct page *from, + unsigned long vaddr, struct vm_area_struct *vma) +{ + void *vfrom, *vto; + + vto = kmap_atomic(to, KM_USER1); + if (cpu_has_dc_aliases) { + vfrom = kmap_coherent(from, vaddr); + copy_page(vto, vfrom); + kunmap_coherent(from); + } else { + vfrom = kmap_atomic(from, KM_USER0); + copy_page(vto, vfrom); + kunmap_atomic(vfrom, KM_USER0); + } + if (((vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc) || + pages_do_alias((unsigned long)vto, vaddr & PAGE_MASK)) + flush_data_cache_page((unsigned long)vto); + kunmap_atomic(vto, KM_USER1); + /* Make sure this page is cleared on other CPU's too before using it */ + smp_wmb(); +} + +EXPORT_SYMBOL(copy_user_highpage); + +void copy_user_page(void *vto, void *vfrom, unsigned long vaddr, + struct page *to) +{ + if (cpu_has_dc_aliases) { + struct page *from = virt_to_page(vfrom); + vfrom = kmap_coherent(from, vaddr); + copy_page(vto, vfrom); + kunmap_coherent(from); + } else + copy_page(vto, vfrom); + if (!cpu_has_ic_fills_f_dc || + pages_do_alias((unsigned long)vto, vaddr & PAGE_MASK)) + flush_data_cache_page((unsigned long)vto); +} + +EXPORT_SYMBOL(copy_user_page); + +void copy_to_user_page(struct vm_area_struct *vma, + struct page *page, unsigned long vaddr, void *dst, const void *src, + unsigned long len) +{ + if (cpu_has_dc_aliases) { + void *vto = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK); + memcpy(vto, src, len); + kunmap_coherent(page); + } else + memcpy(dst, src, len); + if ((vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc) + flush_cache_page(vma, vaddr, page_to_pfn(page)); +} + +EXPORT_SYMBOL(copy_to_user_page); + +void copy_from_user_page(struct vm_area_struct *vma, + struct page *page, unsigned long vaddr, void *dst, const void *src, + unsigned long len) +{ + if (cpu_has_dc_aliases) { + void *vfrom = + kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK); + memcpy(dst, vfrom, len); + kunmap_coherent(page); + } else + memcpy(dst, src, len); +} + +EXPORT_SYMBOL(copy_from_user_page); + + +#ifdef CONFIG_HIGHMEM +pte_t *kmap_pte; +pgprot_t kmap_prot; + static void __init kmap_init(void) { unsigned long kmap_vstart; @@ -97,11 +296,12 @@ kmap_prot = PAGE_KERNEL; } +#endif /* CONFIG_HIGHMEM */ -#ifdef CONFIG_32BIT void __init fixrange_init(unsigned long start, unsigned long end, pgd_t *pgd_base) { +#if defined(CONFIG_HIGHMEM) || defined(CONFIG_MIPS_MT_SMTC) pgd_t *pgd; pud_t *pud; pmd_t *pmd; @@ -122,7 +322,7 @@ for (; (k < PTRS_PER_PMD) && (vaddr != end); pmd++, k++) { if (pmd_none(*pmd)) { pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); - set_pmd(pmd, __pmd(pte)); + set_pmd(pmd, __pmd((unsigned long)pte)); if (pte != pte_offset_kernel(pmd, 0)) BUG(); } @@ -132,9 +332,8 @@ } j = 0; } +#endif } -#endif /* CONFIG_32BIT */ -#endif /* CONFIG_HIGHMEM */ #ifndef CONFIG_NEED_MULTIPLE_NODES extern void pagetable_init(void); @@ -175,6 +374,7 @@ #ifdef CONFIG_HIGHMEM kmap_init(); #endif + kmap_coherent_init(); max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT; low = max_low_pfn; diff -Naur linux-2.6.18.3/arch/mips/mm/ioremap.c linux-mips-2.6.18.3/arch/mips/mm/ioremap.c --- linux-2.6.18.3/arch/mips/mm/ioremap.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/mm/ioremap.c 2006-11-20 10:09:08.000000000 -0800 @@ -176,7 +176,7 @@ #define IS_KSEG1(addr) (((unsigned long)(addr) & ~0x1fffffffUL) == CKSEG1) -void __iounmap(volatile void __iomem *addr) +void __iounmap(const volatile void __iomem *addr) { struct vm_struct *p; diff -Naur linux-2.6.18.3/arch/mips/mm/pg-r4k.c linux-mips-2.6.18.3/arch/mips/mm/pg-r4k.c --- linux-2.6.18.3/arch/mips/mm/pg-r4k.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/mm/pg-r4k.c 2006-11-20 10:09:08.000000000 -0800 @@ -270,6 +270,20 @@ emit_instruction(mi); } +static inline void build_addiu_a2(unsigned long offset) +{ + union mips_instruction mi; + + BUG_ON(offset > 0x7fff); + + mi.i_format.opcode = cpu_has_64bit_gp_regs ? daddiu_op : addiu_op; + mi.i_format.rs = 6; /* $a2 */ + mi.i_format.rt = 6; /* $a2 */ + mi.i_format.simmediate = offset; + + emit_instruction(mi); +} + static inline void build_addiu_a1(unsigned long offset) { union mips_instruction mi; @@ -333,6 +347,7 @@ void __init build_clear_page(void) { unsigned int loop_start; + unsigned long off; epc = (unsigned int *) &clear_page_array; instruction_pending = 0; @@ -369,7 +384,12 @@ } } - build_addiu_a2_a0(PAGE_SIZE - (cpu_has_prefetch ? pref_offset_clear : 0)); + off = PAGE_SIZE - (cpu_has_prefetch ? pref_offset_clear : 0); + if (off > 0x7fff) { + build_addiu_a2_a0(off >> 1); + build_addiu_a2(off >> 1); + } else + build_addiu_a2_a0(off); if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x()) build_insn_word(0x3c01a000); /* lui $at, 0xa000 */ @@ -420,12 +440,18 @@ void __init build_copy_page(void) { unsigned int loop_start; + unsigned long off; epc = (unsigned int *) ©_page_array; store_offset = load_offset = 0; instruction_pending = 0; - build_addiu_a2_a0(PAGE_SIZE - (cpu_has_prefetch ? pref_offset_copy : 0)); + off = PAGE_SIZE - (cpu_has_prefetch ? pref_offset_copy : 0); + if (off > 0x7fff) { + build_addiu_a2_a0(off >> 1); + build_addiu_a2(off >> 1); + } else + build_addiu_a2_a0(off); if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x()) build_insn_word(0x3c01a000); /* lui $at, 0xa000 */ diff -Naur linux-2.6.18.3/arch/mips/mm/pgtable-32.c linux-mips-2.6.18.3/arch/mips/mm/pgtable-32.c --- linux-2.6.18.3/arch/mips/mm/pgtable-32.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/mm/pgtable-32.c 2006-11-20 10:09:08.000000000 -0800 @@ -31,9 +31,10 @@ void __init pagetable_init(void) { -#ifdef CONFIG_HIGHMEM unsigned long vaddr; - pgd_t *pgd, *pgd_base; + pgd_t *pgd_base; +#ifdef CONFIG_HIGHMEM + pgd_t *pgd; pud_t *pud; pmd_t *pmd; pte_t *pte; @@ -44,7 +45,6 @@ pgd_init((unsigned long)swapper_pg_dir + sizeof(pgd_t) * USER_PTRS_PER_PGD); -#ifdef CONFIG_HIGHMEM pgd_base = swapper_pg_dir; /* @@ -53,6 +53,7 @@ vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK; fixrange_init(vaddr, 0, pgd_base); +#ifdef CONFIG_HIGHMEM /* * Permanent kmaps: */ diff -Naur linux-2.6.18.3/arch/mips/mm/pgtable-64.c linux-mips-2.6.18.3/arch/mips/mm/pgtable-64.c --- linux-2.6.18.3/arch/mips/mm/pgtable-64.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/mm/pgtable-64.c 2006-11-20 10:09:08.000000000 -0800 @@ -8,6 +8,7 @@ */ #include #include +#include #include void pgd_init(unsigned long page) @@ -52,7 +53,17 @@ void __init pagetable_init(void) { + unsigned long vaddr; + pgd_t *pgd_base; + /* Initialize the entire pgd. */ pgd_init((unsigned long)swapper_pg_dir); pmd_init((unsigned long)invalid_pmd_table, (unsigned long)invalid_pte_table); + + pgd_base = swapper_pg_dir; + /* + * Fixed mappings: + */ + vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK; + fixrange_init(vaddr, 0, pgd_base); } diff -Naur linux-2.6.18.3/arch/mips/mm/tlbex.c linux-mips-2.6.18.3/arch/mips/mm/tlbex.c --- linux-2.6.18.3/arch/mips/mm/tlbex.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/mm/tlbex.c 2006-11-20 10:09:08.000000000 -0800 @@ -102,7 +102,7 @@ insn_addu, insn_addiu, insn_and, insn_andi, insn_beq, insn_beql, insn_bgez, insn_bgezl, insn_bltz, insn_bltzl, insn_bne, insn_daddu, insn_daddiu, insn_dmfc0, insn_dmtc0, - insn_dsll, insn_dsll32, insn_dsra, insn_dsrl, + insn_dsll, insn_dsll32, insn_dsra, insn_dsrl, insn_dsrl32, insn_dsubu, insn_eret, insn_j, insn_jal, insn_jr, insn_ld, insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0, insn_mtc0, insn_ori, insn_rfe, insn_sc, insn_scd, insn_sd, insn_sll, @@ -145,6 +145,7 @@ { insn_dsll32, M(spec_op,0,0,0,0,dsll32_op), RT | RD | RE }, { insn_dsra, M(spec_op,0,0,0,0,dsra_op), RT | RD | RE }, { insn_dsrl, M(spec_op,0,0,0,0,dsrl_op), RT | RD | RE }, + { insn_dsrl32, M(spec_op,0,0,0,0,dsrl32_op), RT | RD | RE }, { insn_dsubu, M(spec_op,0,0,0,0,dsubu_op), RS | RT | RD }, { insn_eret, M(cop0_op,cop_op,0,0,0,eret_op), 0 }, { insn_j, M(j_op,0,0,0,0,0), JIMM }, @@ -385,6 +386,7 @@ I_u2u1u3(_dsll32); I_u2u1u3(_dsra); I_u2u1u3(_dsrl); +I_u2u1u3(_dsrl32); I_u3u1u2(_dsubu); I_0(_eret); I_u1(_j); @@ -996,7 +998,12 @@ #endif l_vmalloc_done(l, *p); - i_dsrl(p, tmp, tmp, PGDIR_SHIFT-3); /* get pgd offset in bytes */ + + if (PGDIR_SHIFT - 3 < 32) /* get pgd offset in bytes */ + i_dsrl(p, tmp, tmp, PGDIR_SHIFT-3); + else + i_dsrl32(p, tmp, tmp, PGDIR_SHIFT - 3 - 32); + i_andi(p, tmp, tmp, (PTRS_PER_PGD - 1)<<3); i_daddu(p, ptr, ptr, tmp); /* add in pgd offset */ i_dmfc0(p, tmp, C0_BADVADDR); /* get faulting address */ @@ -1073,7 +1080,7 @@ static __init void build_adjust_context(u32 **p, unsigned int ctx) { - unsigned int shift = 4 - (PTE_T_LOG2 + 1); + unsigned int shift = 4 - (PTE_T_LOG2 + 1) + PAGE_SHIFT - 12; unsigned int mask = (PTRS_PER_PTE / 2 - 1) << (PTE_T_LOG2 + 1); switch (current_cpu_data.cputype) { diff -Naur linux-2.6.18.3/arch/mips/momentum/jaguar_atx/Makefile linux-mips-2.6.18.3/arch/mips/momentum/jaguar_atx/Makefile --- linux-2.6.18.3/arch/mips/momentum/jaguar_atx/Makefile 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/momentum/jaguar_atx/Makefile 2006-11-20 10:09:08.000000000 -0800 @@ -6,7 +6,7 @@ # unless it's something special (ie not a .c file). # -obj-y += irq.o prom.o reset.o setup.o +obj-y += irq.o platform.o prom.o reset.o setup.o obj-$(CONFIG_SERIAL_8250_CONSOLE) += ja-console.o obj-$(CONFIG_REMOTE_DEBUG) += dbg_io.o diff -Naur linux-2.6.18.3/arch/mips/momentum/jaguar_atx/jaguar_atx_fpga.h linux-mips-2.6.18.3/arch/mips/momentum/jaguar_atx/jaguar_atx_fpga.h --- linux-2.6.18.3/arch/mips/momentum/jaguar_atx/jaguar_atx_fpga.h 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/momentum/jaguar_atx/jaguar_atx_fpga.h 2006-11-20 10:09:08.000000000 -0800 @@ -46,7 +46,9 @@ extern unsigned long ja_fpga_base; -#define JAGUAR_FPGA_WRITE(x,y) writeb(x, ja_fpga_base + JAGUAR_ATX_REG_##y) -#define JAGUAR_FPGA_READ(x) readb(ja_fpga_base + JAGUAR_ATX_REG_##x) +#define __FPGA_REG_TO_ADDR(reg) \ + ((void *) ja_fpga_base + JAGUAR_ATX_REG_##reg) +#define JAGUAR_FPGA_WRITE(x, reg) writeb(x, __FPGA_REG_TO_ADDR(reg)) +#define JAGUAR_FPGA_READ(reg) readb(__FPGA_REG_TO_ADDR(reg)) #endif diff -Naur linux-2.6.18.3/arch/mips/momentum/jaguar_atx/platform.c linux-mips-2.6.18.3/arch/mips/momentum/jaguar_atx/platform.c --- linux-2.6.18.3/arch/mips/momentum/jaguar_atx/platform.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/momentum/jaguar_atx/platform.c 2006-11-20 10:09:08.000000000 -0800 @@ -0,0 +1,235 @@ +#include +#include +#include +#include +#include + +#include "jaguar_atx_fpga.h" + +#if defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) + +static struct resource mv643xx_eth_shared_resources[] = { + [0] = { + .name = "ethernet shared base", + .start = 0xf1000000 + MV643XX_ETH_SHARED_REGS, + .end = 0xf1000000 + MV643XX_ETH_SHARED_REGS + + MV643XX_ETH_SHARED_REGS_SIZE - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device mv643xx_eth_shared_device = { + .name = MV643XX_ETH_SHARED_NAME, + .id = 0, + .num_resources = ARRAY_SIZE(mv643xx_eth_shared_resources), + .resource = mv643xx_eth_shared_resources, +}; + +#define MV_SRAM_BASE 0xfe000000UL +#define MV_SRAM_SIZE (256 * 1024) + +#define MV_SRAM_RXRING_SIZE (MV_SRAM_SIZE / 4) +#define MV_SRAM_TXRING_SIZE (MV_SRAM_SIZE / 4) + +#define MV_SRAM_BASE_ETH0 MV_SRAM_BASE +#define MV_SRAM_BASE_ETH1 (MV_SRAM_BASE + (MV_SRAM_SIZE / 2)) + +#define MV64x60_IRQ_ETH_0 48 +#define MV64x60_IRQ_ETH_1 49 +#define MV64x60_IRQ_ETH_2 50 + +#ifdef CONFIG_MV643XX_ETH_0 + +static struct resource mv64x60_eth0_resources[] = { + [0] = { + .name = "eth0 irq", + .start = MV64x60_IRQ_ETH_0, + .end = MV64x60_IRQ_ETH_0, + .flags = IORESOURCE_IRQ, + }, +}; + +static char eth0_mac_addr[ETH_ALEN]; + +static struct mv643xx_eth_platform_data eth0_pd = { + .mac_addr = eth0_mac_addr, + + .tx_sram_addr = MV_SRAM_BASE_ETH0, + .tx_sram_size = MV_SRAM_TXRING_SIZE, + .tx_queue_size = MV_SRAM_TXRING_SIZE / 16, + + .rx_sram_addr = MV_SRAM_BASE_ETH0 + MV_SRAM_TXRING_SIZE, + .rx_sram_size = MV_SRAM_RXRING_SIZE, + .rx_queue_size = MV_SRAM_RXRING_SIZE / 16, +}; + +static struct platform_device eth0_device = { + .name = MV643XX_ETH_NAME, + .id = 0, + .num_resources = ARRAY_SIZE(mv64x60_eth0_resources), + .resource = mv64x60_eth0_resources, + .dev = { + .platform_data = ð0_pd, + }, +}; +#endif /* CONFIG_MV643XX_ETH_0 */ + +#ifdef CONFIG_MV643XX_ETH_1 + +static struct resource mv64x60_eth1_resources[] = { + [0] = { + .name = "eth1 irq", + .start = MV64x60_IRQ_ETH_1, + .end = MV64x60_IRQ_ETH_1, + .flags = IORESOURCE_IRQ, + }, +}; + +static char eth1_mac_addr[ETH_ALEN]; + +static struct mv643xx_eth_platform_data eth1_pd = { + .mac_addr = eth1_mac_addr, + + .tx_sram_addr = MV_SRAM_BASE_ETH1, + .tx_sram_size = MV_SRAM_TXRING_SIZE, + .tx_queue_size = MV_SRAM_TXRING_SIZE / 16, + + .rx_sram_addr = MV_SRAM_BASE_ETH1 + MV_SRAM_TXRING_SIZE, + .rx_sram_size = MV_SRAM_RXRING_SIZE, + .rx_queue_size = MV_SRAM_RXRING_SIZE / 16, +}; + +static struct platform_device eth1_device = { + .name = MV643XX_ETH_NAME, + .id = 1, + .num_resources = ARRAY_SIZE(mv64x60_eth1_resources), + .resource = mv64x60_eth1_resources, + .dev = { + .platform_data = ð1_pd, + }, +}; +#endif /* CONFIG_MV643XX_ETH_1 */ + +#ifdef CONFIG_MV643XX_ETH_2 + +static struct resource mv64x60_eth2_resources[] = { + [0] = { + .name = "eth2 irq", + .start = MV64x60_IRQ_ETH_2, + .end = MV64x60_IRQ_ETH_2, + .flags = IORESOURCE_IRQ, + }, +}; + +static char eth2_mac_addr[ETH_ALEN]; + +static struct mv643xx_eth_platform_data eth2_pd = { + .mac_addr = eth2_mac_addr, +}; + +static struct platform_device eth2_device = { + .name = MV643XX_ETH_NAME, + .id = 1, + .num_resources = ARRAY_SIZE(mv64x60_eth2_resources), + .resource = mv64x60_eth2_resources, + .dev = { + .platform_data = ð2_pd, + }, +}; +#endif /* CONFIG_MV643XX_ETH_2 */ + +static struct platform_device *mv643xx_eth_pd_devs[] __initdata = { + &mv643xx_eth_shared_device, +#ifdef CONFIG_MV643XX_ETH_0 + ð0_device, +#endif +#ifdef CONFIG_MV643XX_ETH_1 + ð1_device, +#endif +#ifdef CONFIG_MV643XX_ETH_2 + ð2_device, +#endif +}; + +static u8 __init exchange_bit(u8 val, u8 cs) +{ + /* place the data */ + JAGUAR_FPGA_WRITE((val << 2) | cs, EEPROM_MODE); + udelay(1); + + /* turn the clock on */ + JAGUAR_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE); + udelay(1); + + /* turn the clock off and read-strobe */ + JAGUAR_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE); + + /* return the data */ + return (JAGUAR_FPGA_READ(EEPROM_MODE) >> 3) & 0x1; +} + +static void __init get_mac(char dest[6]) +{ + u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + int i,j; + + for (i = 0; i < 12; i++) + exchange_bit(read_opcode[i], 1); + + for (j = 0; j < 6; j++) { + dest[j] = 0; + for (i = 0; i < 8; i++) { + dest[j] <<= 1; + dest[j] |= exchange_bit(0, 1); + } + } + + /* turn off CS */ + exchange_bit(0,0); +} + +/* + * Copy and increment ethernet MAC address by a small value. + * + * This is useful for systems where the only one MAC address is stored in + * non-volatile memory for multiple ports. + */ +static inline void eth_mac_add(unsigned char *dst, unsigned char *src, + unsigned int add) +{ + int i; + + BUG_ON(add >= 256); + + for (i = ETH_ALEN; i >= 0; i--) { + dst[i] = src[i] + add; + add = dst[i] < src[i]; /* compute carry */ + } + + WARN_ON(add); +} + +static int __init mv643xx_eth_add_pds(void) +{ + unsigned char mac[ETH_ALEN]; + int ret; + + get_mac(mac); +#ifdef CONFIG_MV643XX_ETH_0 + eth_mac_add(eth1_mac_addr, mac, 0); +#endif +#ifdef CONFIG_MV643XX_ETH_1 + eth_mac_add(eth1_mac_addr, mac, 1); +#endif +#ifdef CONFIG_MV643XX_ETH_2 + eth_mac_add(eth2_mac_addr, mac, 2); +#endif + ret = platform_add_devices(mv643xx_eth_pd_devs, + ARRAY_SIZE(mv643xx_eth_pd_devs)); + + return ret; +} + +device_initcall(mv643xx_eth_add_pds); + +#endif /* defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) */ diff -Naur linux-2.6.18.3/arch/mips/momentum/jaguar_atx/prom.c linux-mips-2.6.18.3/arch/mips/momentum/jaguar_atx/prom.c --- linux-2.6.18.3/arch/mips/momentum/jaguar_atx/prom.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/momentum/jaguar_atx/prom.c 2006-11-20 10:09:08.000000000 -0800 @@ -39,56 +39,6 @@ return "Momentum Jaguar-ATX"; } -#ifdef CONFIG_MV643XX_ETH -extern unsigned char prom_mac_addr_base[6]; - -static void burn_clocks(void) -{ - int i; - - /* this loop should burn at least 1us -- this should be plenty */ - for (i = 0; i < 0x10000; i++) - ; -} - -static u8 exchange_bit(u8 val, u8 cs) -{ - /* place the data */ - JAGUAR_FPGA_WRITE((val << 2) | cs, EEPROM_MODE); - burn_clocks(); - - /* turn the clock on */ - JAGUAR_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE); - burn_clocks(); - - /* turn the clock off and read-strobe */ - JAGUAR_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE); - - /* return the data */ - return ((JAGUAR_FPGA_READ(EEPROM_MODE) >> 3) & 0x1); -} - -void get_mac(char dest[6]) -{ - u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - int i,j; - - for (i = 0; i < 12; i++) - exchange_bit(read_opcode[i], 1); - - for (j = 0; j < 6; j++) { - dest[j] = 0; - for (i = 0; i < 8; i++) { - dest[j] <<= 1; - dest[j] |= exchange_bit(0, 1); - } - } - - /* turn off CS */ - exchange_bit(0,0); -} -#endif - #ifdef CONFIG_64BIT unsigned long signext(unsigned long addr) @@ -228,11 +178,6 @@ #endif /* CONFIG_64BIT */ mips_machgroup = MACH_GROUP_MOMENCO; mips_machtype = MACH_MOMENCO_JAGUAR_ATX; - -#ifdef CONFIG_MV643XX_ETH - /* get the base MAC address for on-board ethernet ports */ - get_mac(prom_mac_addr_base); -#endif } unsigned long __init prom_free_prom_memory(void) diff -Naur linux-2.6.18.3/arch/mips/momentum/ocelot_3/Makefile linux-mips-2.6.18.3/arch/mips/momentum/ocelot_3/Makefile --- linux-2.6.18.3/arch/mips/momentum/ocelot_3/Makefile 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/momentum/ocelot_3/Makefile 2006-11-20 10:09:08.000000000 -0800 @@ -5,4 +5,4 @@ # removes any old dependencies. DON'T put your own dependencies here # unless it's something special (ie not a .c file). # -obj-y += irq.o prom.o reset.o setup.o +obj-y += irq.o platform.o prom.o reset.o setup.o diff -Naur linux-2.6.18.3/arch/mips/momentum/ocelot_3/ocelot_3_fpga.h linux-mips-2.6.18.3/arch/mips/momentum/ocelot_3/ocelot_3_fpga.h --- linux-2.6.18.3/arch/mips/momentum/ocelot_3/ocelot_3_fpga.h 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/momentum/ocelot_3/ocelot_3_fpga.h 2006-11-20 10:09:08.000000000 -0800 @@ -51,7 +51,9 @@ extern unsigned long ocelot_fpga_base; -#define OCELOT_FPGA_WRITE(x, y) writeb(x, ocelot_fpga_base + OCELOT_3_REG_##y) -#define OCELOT_FPGA_READ(x) readb(ocelot_fpga_base + OCELOT_3_REG_##x) +#define __FPGA_REG_TO_ADDR(reg) \ + ((void *) ocelot_fpga_base + OCELOT_3_REG_##reg) +#define OCELOT_FPGA_WRITE(x, reg) writeb(x, __FPGA_REG_TO_ADDR(reg)) +#define OCELOT_FPGA_READ(reg) readb(__FPGA_REG_TO_ADDR(reg)) #endif diff -Naur linux-2.6.18.3/arch/mips/momentum/ocelot_3/platform.c linux-mips-2.6.18.3/arch/mips/momentum/ocelot_3/platform.c --- linux-2.6.18.3/arch/mips/momentum/ocelot_3/platform.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/momentum/ocelot_3/platform.c 2006-11-20 10:09:08.000000000 -0800 @@ -0,0 +1,235 @@ +#include +#include +#include +#include +#include + +#include "ocelot_3_fpga.h" + +#if defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) + +static struct resource mv643xx_eth_shared_resources[] = { + [0] = { + .name = "ethernet shared base", + .start = 0xf1000000 + MV643XX_ETH_SHARED_REGS, + .end = 0xf1000000 + MV643XX_ETH_SHARED_REGS + + MV643XX_ETH_SHARED_REGS_SIZE - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device mv643xx_eth_shared_device = { + .name = MV643XX_ETH_SHARED_NAME, + .id = 0, + .num_resources = ARRAY_SIZE(mv643xx_eth_shared_resources), + .resource = mv643xx_eth_shared_resources, +}; + +#define MV_SRAM_BASE 0xfe000000UL +#define MV_SRAM_SIZE (256 * 1024) + +#define MV_SRAM_RXRING_SIZE (MV_SRAM_SIZE / 4) +#define MV_SRAM_TXRING_SIZE (MV_SRAM_SIZE / 4) + +#define MV_SRAM_BASE_ETH0 MV_SRAM_BASE +#define MV_SRAM_BASE_ETH1 (MV_SRAM_BASE + (MV_SRAM_SIZE / 2)) + +#define MV64x60_IRQ_ETH_0 48 +#define MV64x60_IRQ_ETH_1 49 +#define MV64x60_IRQ_ETH_2 50 + +#ifdef CONFIG_MV643XX_ETH_0 + +static struct resource mv64x60_eth0_resources[] = { + [0] = { + .name = "eth0 irq", + .start = MV64x60_IRQ_ETH_0, + .end = MV64x60_IRQ_ETH_0, + .flags = IORESOURCE_IRQ, + }, +}; + +static char eth0_mac_addr[ETH_ALEN]; + +static struct mv643xx_eth_platform_data eth0_pd = { + .mac_addr = eth0_mac_addr, + + .tx_sram_addr = MV_SRAM_BASE_ETH0, + .tx_sram_size = MV_SRAM_TXRING_SIZE, + .tx_queue_size = MV_SRAM_TXRING_SIZE / 16, + + .rx_sram_addr = MV_SRAM_BASE_ETH0 + MV_SRAM_TXRING_SIZE, + .rx_sram_size = MV_SRAM_RXRING_SIZE, + .rx_queue_size = MV_SRAM_RXRING_SIZE / 16, +}; + +static struct platform_device eth0_device = { + .name = MV643XX_ETH_NAME, + .id = 0, + .num_resources = ARRAY_SIZE(mv64x60_eth0_resources), + .resource = mv64x60_eth0_resources, + .dev = { + .platform_data = ð0_pd, + }, +}; +#endif /* CONFIG_MV643XX_ETH_0 */ + +#ifdef CONFIG_MV643XX_ETH_1 + +static struct resource mv64x60_eth1_resources[] = { + [0] = { + .name = "eth1 irq", + .start = MV64x60_IRQ_ETH_1, + .end = MV64x60_IRQ_ETH_1, + .flags = IORESOURCE_IRQ, + }, +}; + +static char eth1_mac_addr[ETH_ALEN]; + +static struct mv643xx_eth_platform_data eth1_pd = { + .mac_addr = eth1_mac_addr, + + .tx_sram_addr = MV_SRAM_BASE_ETH1, + .tx_sram_size = MV_SRAM_TXRING_SIZE, + .tx_queue_size = MV_SRAM_TXRING_SIZE / 16, + + .rx_sram_addr = MV_SRAM_BASE_ETH1 + MV_SRAM_TXRING_SIZE, + .rx_sram_size = MV_SRAM_RXRING_SIZE, + .rx_queue_size = MV_SRAM_RXRING_SIZE / 16, +}; + +static struct platform_device eth1_device = { + .name = MV643XX_ETH_NAME, + .id = 1, + .num_resources = ARRAY_SIZE(mv64x60_eth1_resources), + .resource = mv64x60_eth1_resources, + .dev = { + .platform_data = ð1_pd, + }, +}; +#endif /* CONFIG_MV643XX_ETH_1 */ + +#ifdef CONFIG_MV643XX_ETH_2 + +static struct resource mv64x60_eth2_resources[] = { + [0] = { + .name = "eth2 irq", + .start = MV64x60_IRQ_ETH_2, + .end = MV64x60_IRQ_ETH_2, + .flags = IORESOURCE_IRQ, + }, +}; + +static char eth2_mac_addr[ETH_ALEN]; + +static struct mv643xx_eth_platform_data eth2_pd = { + .mac_addr = eth2_mac_addr, +}; + +static struct platform_device eth2_device = { + .name = MV643XX_ETH_NAME, + .id = 1, + .num_resources = ARRAY_SIZE(mv64x60_eth2_resources), + .resource = mv64x60_eth2_resources, + .dev = { + .platform_data = ð2_pd, + }, +}; +#endif /* CONFIG_MV643XX_ETH_2 */ + +static struct platform_device *mv643xx_eth_pd_devs[] __initdata = { + &mv643xx_eth_shared_device, +#ifdef CONFIG_MV643XX_ETH_0 + ð0_device, +#endif +#ifdef CONFIG_MV643XX_ETH_1 + ð1_device, +#endif +#ifdef CONFIG_MV643XX_ETH_2 + ð2_device, +#endif +}; + +static u8 __init exchange_bit(u8 val, u8 cs) +{ + /* place the data */ + OCELOT_FPGA_WRITE((val << 2) | cs, EEPROM_MODE); + udelay(1); + + /* turn the clock on */ + OCELOT_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE); + udelay(1); + + /* turn the clock off and read-strobe */ + OCELOT_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE); + + /* return the data */ + return (OCELOT_FPGA_READ(EEPROM_MODE) >> 3) & 0x1; +} + +static void __init get_mac(char dest[6]) +{ + u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + int i,j; + + for (i = 0; i < 12; i++) + exchange_bit(read_opcode[i], 1); + + for (j = 0; j < 6; j++) { + dest[j] = 0; + for (i = 0; i < 8; i++) { + dest[j] <<= 1; + dest[j] |= exchange_bit(0, 1); + } + } + + /* turn off CS */ + exchange_bit(0,0); +} + +/* + * Copy and increment ethernet MAC address by a small value. + * + * This is useful for systems where the only one MAC address is stored in + * non-volatile memory for multiple ports. + */ +static inline void eth_mac_add(unsigned char *dst, unsigned char *src, + unsigned int add) +{ + int i; + + BUG_ON(add >= 256); + + for (i = ETH_ALEN; i >= 0; i--) { + dst[i] = src[i] + add; + add = dst[i] < src[i]; /* compute carry */ + } + + WARN_ON(add); +} + +static int __init mv643xx_eth_add_pds(void) +{ + unsigned char mac[ETH_ALEN]; + int ret; + + get_mac(mac); +#ifdef CONFIG_MV643XX_ETH_0 + eth_mac_add(eth1_mac_addr, mac, 0); +#endif +#ifdef CONFIG_MV643XX_ETH_1 + eth_mac_add(eth1_mac_addr, mac, 1); +#endif +#ifdef CONFIG_MV643XX_ETH_2 + eth_mac_add(eth2_mac_addr, mac, 2); +#endif + ret = platform_add_devices(mv643xx_eth_pd_devs, + ARRAY_SIZE(mv643xx_eth_pd_devs)); + + return ret; +} + +device_initcall(mv643xx_eth_add_pds); + +#endif /* defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) */ diff -Naur linux-2.6.18.3/arch/mips/momentum/ocelot_3/prom.c linux-mips-2.6.18.3/arch/mips/momentum/ocelot_3/prom.c --- linux-2.6.18.3/arch/mips/momentum/ocelot_3/prom.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/momentum/ocelot_3/prom.c 2006-11-20 10:09:08.000000000 -0800 @@ -34,64 +34,11 @@ extern unsigned long marvell_base; extern unsigned long cpu_clock; -#ifdef CONFIG_MV643XX_ETH -extern unsigned char prom_mac_addr_base[6]; -#endif - const char *get_system_type(void) { return "Momentum Ocelot-3"; } -#ifdef CONFIG_MV643XX_ETH -void burn_clocks(void) -{ - int i; - - /* this loop should burn at least 1us -- this should be plenty */ - for (i = 0; i < 0x10000; i++) - ; -} - -u8 exchange_bit(u8 val, u8 cs) -{ - /* place the data */ - OCELOT_FPGA_WRITE((val << 2) | cs, EEPROM_MODE); - burn_clocks(); - - /* turn the clock on */ - OCELOT_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE); - burn_clocks(); - - /* turn the clock off and read-strobe */ - OCELOT_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE); - - /* return the data */ - return ((OCELOT_FPGA_READ(EEPROM_MODE) >> 3) & 0x1); -} - -void get_mac(char dest[6]) -{ - u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - int i,j; - - for (i = 0; i < 12; i++) - exchange_bit(read_opcode[i], 1); - - for (j = 0; j < 6; j++) { - dest[j] = 0; - for (i = 0; i < 8; i++) { - dest[j] <<= 1; - dest[j] |= exchange_bit(0, 1); - } - } - - /* turn off CS */ - exchange_bit(0,0); -} -#endif - - #ifdef CONFIG_64BIT unsigned long signext(unsigned long addr) @@ -228,11 +175,6 @@ mips_machgroup = MACH_GROUP_MOMENCO; mips_machtype = MACH_MOMENCO_OCELOT_3; -#ifdef CONFIG_MV643XX_ETH - /* get the base MAC address for on-board ethernet ports */ - get_mac(prom_mac_addr_base); -#endif - #ifndef CONFIG_64BIT debug_vectors->printf("Booting Linux kernel...\n"); #endif diff -Naur linux-2.6.18.3/arch/mips/momentum/ocelot_3/setup.c linux-mips-2.6.18.3/arch/mips/momentum/ocelot_3/setup.c --- linux-2.6.18.3/arch/mips/momentum/ocelot_3/setup.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/momentum/ocelot_3/setup.c 2006-11-20 10:09:08.000000000 -0800 @@ -4,7 +4,7 @@ * BRIEF MODULE DESCRIPTION * Momentum Computer Ocelot-3 board dependent boot routines * - * Copyright (C) 1996, 1997, 01, 05 Ralf Baechle + * Copyright (C) 1996, 1997, 01, 05 - 06 Ralf Baechle * Copyright (C) 2000 RidgeRun, Inc. * Copyright (C) 2001 Red Hat, Inc. * Copyright (C) 2002 Momentum Computer diff -Naur linux-2.6.18.3/arch/mips/momentum/ocelot_c/Makefile linux-mips-2.6.18.3/arch/mips/momentum/ocelot_c/Makefile --- linux-2.6.18.3/arch/mips/momentum/ocelot_c/Makefile 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/momentum/ocelot_c/Makefile 2006-11-20 10:09:08.000000000 -0800 @@ -2,7 +2,7 @@ # Makefile for Momentum Computer's Ocelot-C and -CS boards. # -obj-y += cpci-irq.o irq.o prom.o reset.o \ +obj-y += cpci-irq.o irq.o platform.o prom.o reset.o \ setup.o uart-irq.o obj-$(CONFIG_KGDB) += dbg_io.o diff -Naur linux-2.6.18.3/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h linux-mips-2.6.18.3/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h --- linux-2.6.18.3/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h 2006-11-20 10:09:08.000000000 -0800 @@ -53,7 +53,9 @@ #define OCELOT_C_REG_INTSET 0xe #define OCELOT_C_REG_INTCLR 0xf -#define OCELOT_FPGA_WRITE(x, y) writeb(x, OCELOT_C_CS0_ADDR + OCELOT_C_REG_##y) -#define OCELOT_FPGA_READ(x) readb(OCELOT_C_CS0_ADDR + OCELOT_C_REG_##x) +#define __FPGA_REG_TO_ADDR(reg) \ + ((void *) OCELOT_C_CS0_ADDR + OCELOT_C_REG_##reg) +#define OCELOT_FPGA_WRITE(x, reg) writeb(x, __FPGA_REG_TO_ADDR(reg)) +#define OCELOT_FPGA_READ(reg) readb(__FPGA_REG_TO_ADDR(reg)) #endif diff -Naur linux-2.6.18.3/arch/mips/momentum/ocelot_c/platform.c linux-mips-2.6.18.3/arch/mips/momentum/ocelot_c/platform.c --- linux-2.6.18.3/arch/mips/momentum/ocelot_c/platform.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/momentum/ocelot_c/platform.c 2006-11-20 10:09:08.000000000 -0800 @@ -0,0 +1,201 @@ +#include +#include +#include +#include +#include + +#include "ocelot_c_fpga.h" + +#if defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) + +static struct resource mv643xx_eth_shared_resources[] = { + [0] = { + .name = "ethernet shared base", + .start = 0xf1000000 + MV643XX_ETH_SHARED_REGS, + .end = 0xf1000000 + MV643XX_ETH_SHARED_REGS + + MV643XX_ETH_SHARED_REGS_SIZE - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device mv643xx_eth_shared_device = { + .name = MV643XX_ETH_SHARED_NAME, + .id = 0, + .num_resources = ARRAY_SIZE(mv643xx_eth_shared_resources), + .resource = mv643xx_eth_shared_resources, +}; + +#define MV_SRAM_BASE 0xfe000000UL +#define MV_SRAM_SIZE (256 * 1024) + +#define MV_SRAM_RXRING_SIZE (MV_SRAM_SIZE / 4) +#define MV_SRAM_TXRING_SIZE (MV_SRAM_SIZE / 4) + +#define MV_SRAM_BASE_ETH0 MV_SRAM_BASE +#define MV_SRAM_BASE_ETH1 (MV_SRAM_BASE + (MV_SRAM_SIZE / 2)) + +#define MV64x60_IRQ_ETH_0 48 +#define MV64x60_IRQ_ETH_1 49 + +#ifdef CONFIG_MV643XX_ETH_0 + +static struct resource mv64x60_eth0_resources[] = { + [0] = { + .name = "eth0 irq", + .start = MV64x60_IRQ_ETH_0, + .end = MV64x60_IRQ_ETH_0, + .flags = IORESOURCE_IRQ, + }, +}; + +static char eth0_mac_addr[ETH_ALEN]; + +static struct mv643xx_eth_platform_data eth0_pd = { + .mac_addr = eth0_mac_addr, + + .tx_sram_addr = MV_SRAM_BASE_ETH0, + .tx_sram_size = MV_SRAM_TXRING_SIZE, + .tx_queue_size = MV_SRAM_TXRING_SIZE / 16, + + .rx_sram_addr = MV_SRAM_BASE_ETH0 + MV_SRAM_TXRING_SIZE, + .rx_sram_size = MV_SRAM_RXRING_SIZE, + .rx_queue_size = MV_SRAM_RXRING_SIZE / 16, +}; + +static struct platform_device eth0_device = { + .name = MV643XX_ETH_NAME, + .id = 0, + .num_resources = ARRAY_SIZE(mv64x60_eth0_resources), + .resource = mv64x60_eth0_resources, + .dev = { + .platform_data = ð0_pd, + }, +}; +#endif /* CONFIG_MV643XX_ETH_0 */ + +#ifdef CONFIG_MV643XX_ETH_1 + +static struct resource mv64x60_eth1_resources[] = { + [0] = { + .name = "eth1 irq", + .start = MV64x60_IRQ_ETH_1, + .end = MV64x60_IRQ_ETH_1, + .flags = IORESOURCE_IRQ, + }, +}; + +static char eth1_mac_addr[ETH_ALEN]; + +static struct mv643xx_eth_platform_data eth1_pd = { + .mac_addr = eth1_mac_addr, + + .tx_sram_addr = MV_SRAM_BASE_ETH1, + .tx_sram_size = MV_SRAM_TXRING_SIZE, + .tx_queue_size = MV_SRAM_TXRING_SIZE / 16, + + .rx_sram_addr = MV_SRAM_BASE_ETH1 + MV_SRAM_TXRING_SIZE, + .rx_sram_size = MV_SRAM_RXRING_SIZE, + .rx_queue_size = MV_SRAM_RXRING_SIZE / 16, +}; + +static struct platform_device eth1_device = { + .name = MV643XX_ETH_NAME, + .id = 1, + .num_resources = ARRAY_SIZE(mv64x60_eth1_resources), + .resource = mv64x60_eth1_resources, + .dev = { + .platform_data = ð1_pd, + }, +}; +#endif /* CONFIG_MV643XX_ETH_1 */ + +static struct platform_device *mv643xx_eth_pd_devs[] __initdata = { + &mv643xx_eth_shared_device, +#ifdef CONFIG_MV643XX_ETH_0 + ð0_device, +#endif +#ifdef CONFIG_MV643XX_ETH_1 + ð1_device, +#endif + /* The third port is not wired up on the Ocelot C */ +}; + +static u8 __init exchange_bit(u8 val, u8 cs) +{ + /* place the data */ + OCELOT_FPGA_WRITE((val << 2) | cs, EEPROM_MODE); + udelay(1); + + /* turn the clock on */ + OCELOT_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE); + udelay(1); + + /* turn the clock off and read-strobe */ + OCELOT_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE); + + /* return the data */ + return (OCELOT_FPGA_READ(EEPROM_MODE) >> 3) & 0x1; +} + +static void __init get_mac(char dest[6]) +{ + u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + int i,j; + + for (i = 0; i < 12; i++) + exchange_bit(read_opcode[i], 1); + + for (j = 0; j < 6; j++) { + dest[j] = 0; + for (i = 0; i < 8; i++) { + dest[j] <<= 1; + dest[j] |= exchange_bit(0, 1); + } + } + + /* turn off CS */ + exchange_bit(0,0); +} + +/* + * Copy and increment ethernet MAC address by a small value. + * + * This is useful for systems where the only one MAC address is stored in + * non-volatile memory for multiple ports. + */ +static inline void eth_mac_add(unsigned char *dst, unsigned char *src, + unsigned int add) +{ + int i; + + BUG_ON(add >= 256); + + for (i = ETH_ALEN; i >= 0; i--) { + dst[i] = src[i] + add; + add = dst[i] < src[i]; /* compute carry */ + } + + WARN_ON(add); +} + +static int __init mv643xx_eth_add_pds(void) +{ + unsigned char mac[ETH_ALEN]; + int ret; + + get_mac(mac); +#ifdef CONFIG_MV643XX_ETH_0 + eth_mac_add(eth1_mac_addr, mac, 0); +#endif +#ifdef CONFIG_MV643XX_ETH_1 + eth_mac_add(eth1_mac_addr, mac, 1); +#endif + ret = platform_add_devices(mv643xx_eth_pd_devs, + ARRAY_SIZE(mv643xx_eth_pd_devs)); + + return ret; +} + +device_initcall(mv643xx_eth_add_pds); + +#endif /* defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) */ diff -Naur linux-2.6.18.3/arch/mips/momentum/ocelot_c/prom.c linux-mips-2.6.18.3/arch/mips/momentum/ocelot_c/prom.c --- linux-2.6.18.3/arch/mips/momentum/ocelot_c/prom.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/momentum/ocelot_c/prom.c 2006-11-20 10:09:08.000000000 -0800 @@ -29,11 +29,7 @@ struct callvectors* debug_vectors; extern unsigned long marvell_base; -extern unsigned long cpu_clock; - -#ifdef CONFIG_MV643XX_ETH -extern unsigned char prom_mac_addr_base[6]; -#endif +extern unsigned int cpu_clock; const char *get_system_type(void) { @@ -44,55 +40,6 @@ #endif } -#ifdef CONFIG_MV643XX_ETH -static void burn_clocks(void) -{ - int i; - - /* this loop should burn at least 1us -- this should be plenty */ - for (i = 0; i < 0x10000; i++) - ; -} - -static u8 exchange_bit(u8 val, u8 cs) -{ - /* place the data */ - OCELOT_FPGA_WRITE((val << 2) | cs, EEPROM_MODE); - burn_clocks(); - - /* turn the clock on */ - OCELOT_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE); - burn_clocks(); - - /* turn the clock off and read-strobe */ - OCELOT_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE); - - /* return the data */ - return ((OCELOT_FPGA_READ(EEPROM_MODE) >> 3) & 0x1); -} - -void get_mac(char dest[6]) -{ - u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - int i,j; - - for (i = 0; i < 12; i++) - exchange_bit(read_opcode[i], 1); - - for (j = 0; j < 6; j++) { - dest[j] = 0; - for (i = 0; i < 8; i++) { - dest[j] <<= 1; - dest[j] |= exchange_bit(0, 1); - } - } - - /* turn off CS */ - exchange_bit(0,0); -} -#endif - - #ifdef CONFIG_64BIT unsigned long signext(unsigned long addr) @@ -226,11 +173,6 @@ mips_machgroup = MACH_GROUP_MOMENCO; mips_machtype = MACH_MOMENCO_OCELOT_C; -#ifdef CONFIG_MV643XX_ETH - /* get the base MAC address for on-board ethernet ports */ - get_mac(prom_mac_addr_base); -#endif - #ifndef CONFIG_64BIT debug_vectors->printf("Booting Linux kernel...\n"); #endif diff -Naur linux-2.6.18.3/arch/mips/momentum/ocelot_c/setup.c linux-mips-2.6.18.3/arch/mips/momentum/ocelot_c/setup.c --- linux-2.6.18.3/arch/mips/momentum/ocelot_c/setup.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/momentum/ocelot_c/setup.c 2006-11-20 10:09:08.000000000 -0800 @@ -70,8 +70,7 @@ #include "ocelot_c_fpga.h" unsigned long marvell_base; -extern unsigned long mv64340_sram_base; -unsigned long cpu_clock; +unsigned int cpu_clock; /* These functions are used for rebooting or halting the machine*/ extern void momenco_ocelot_restart(char *command); @@ -120,7 +119,6 @@ add_wired_entry(ENTRYLO(0xfe000000), ENTRYLO(0xff000000), 0xfffffffffe000000, PM_16M); marvell_base = 0xfffffffff4000000; - mv64340_sram_base = 0xfffffffffe000000; #else /* marvell and extra space */ add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000), 0xf4000000, PM_64K); @@ -130,7 +128,6 @@ add_wired_entry(ENTRYLO(0xfe000000), ENTRYLO(0xff000000), 0xfe000000, PM_16M); marvell_base = 0xf4000000; - mv64340_sram_base = 0xfe000000; #endif } @@ -347,22 +344,20 @@ } } -#ifndef CONFIG_64BIT -/* This needs to be one of the first initcalls, because no I/O port access - can work before this */ +/* + * This needs to be one of the first initcalls, because no I/O port access + * can work before this + */ static int io_base_ioremap(void) { - /* we're mapping PCI accesses from 0xc0000000 to 0xf0000000 */ - void *io_remap_range = ioremap(0xc0000000, 0x30000000); + void __iomem * io_remap_range = ioremap(0xc0000000UL, 0x10000); - if (!io_remap_range) { + if (!io_remap_range) panic("Could not ioremap I/O port range"); - } - printk("io_remap_range set at 0x%08x\n", (uint32_t)io_remap_range); - set_io_port_base(io_remap_range - 0xc0000000); + + set_io_port_base((unsigned long) io_remap_range); return 0; } module_init(io_base_ioremap); -#endif diff -Naur linux-2.6.18.3/arch/mips/momentum/ocelot_g/gt-irq.c linux-mips-2.6.18.3/arch/mips/momentum/ocelot_g/gt-irq.c --- linux-2.6.18.3/arch/mips/momentum/ocelot_g/gt-irq.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/momentum/ocelot_g/gt-irq.c 2006-11-20 10:09:08.000000000 -0800 @@ -28,7 +28,7 @@ * be handled and ack'ed differently than other MIPS interrupts. */ -#if CURRENTLY_UNUSED +#if 0 struct tq_struct irq_handlers[MAX_CAUSE_REGS][MAX_CAUSE_REG_WIDTH]; void hook_irq_handler(int int_cause, int bit_num, void *isr_ptr); @@ -96,7 +96,7 @@ return 0; return 1; } -#endif /* UNUSED */ +#endif /* 0 */ /* * Interrupt handler for interrupts coming from the Galileo chip via P0_INT#. @@ -197,7 +197,7 @@ void gt64240_irq_init(void) { -#if CURRENTLY_UNUSED +#if 0 int i, j; /* Reset irq handlers pointers to NULL */ @@ -209,5 +209,5 @@ irq_handlers[i][j].data = NULL; } } -#endif +#endif /* 0 */ } diff -Naur linux-2.6.18.3/arch/mips/momentum/ocelot_g/ocelot_pld.h linux-mips-2.6.18.3/arch/mips/momentum/ocelot_g/ocelot_pld.h --- linux-2.6.18.3/arch/mips/momentum/ocelot_g/ocelot_pld.h 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/momentum/ocelot_g/ocelot_pld.h 2006-11-20 10:09:08.000000000 -0800 @@ -23,8 +23,8 @@ #define OCELOT_REG_INTSET (12) #define OCELOT_REG_INTCLR (13) -#define OCELOT_PLD_WRITE(x, y) writeb(x, OCELOT_CS0_ADDR + OCELOT_REG_##y) -#define OCELOT_PLD_READ(x) readb(OCELOT_CS0_ADDR + OCELOT_REG_##x) - +#define __PLD_REG_TO_ADDR(reg) ((void *) OCELOT_CS0_ADDR + OCELOT_REG_##reg) +#define OCELOT_PLD_WRITE(x, reg) writeb(x, __PLD_REG_TO_ADDR(reg)) +#define OCELOT_PLD_READ(reg) readb(__PLD_REG_TO_ADDR(reg)) #endif /* __MOMENCO_OCELOT_PLD_H__ */ diff -Naur linux-2.6.18.3/arch/mips/momentum/ocelot_g/setup.c linux-mips-2.6.18.3/arch/mips/momentum/ocelot_g/setup.c --- linux-2.6.18.3/arch/mips/momentum/ocelot_g/setup.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/momentum/ocelot_g/setup.c 2006-11-20 10:09:08.000000000 -0800 @@ -57,6 +57,7 @@ #include #include #include +#include #include #include #include @@ -161,6 +162,10 @@ printk("Done\n"); } +void __init plat_timer_setup(struct irqaction *irq) +{ +} + void __init plat_mem_setup(void) { void (*l3func)(unsigned long) = (void *) KSEG1ADDR(setup_l3cache); diff -Naur linux-2.6.18.3/arch/mips/oprofile/op_model_mipsxx.c linux-mips-2.6.18.3/arch/mips/oprofile/op_model_mipsxx.c --- linux-2.6.18.3/arch/mips/oprofile/op_model_mipsxx.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/oprofile/op_model_mipsxx.c 2006-11-20 10:09:08.000000000 -0800 @@ -30,16 +30,18 @@ #define M_COUNTER_OVERFLOW (1UL << 31) #ifdef CONFIG_MIPS_MT_SMP -#define WHAT (M_TC_EN_VPE | M_PERFCTL_VPEID(smp_processor_id())) +#define WHAT (M_TC_EN_VPE | M_PERFCTL_VPEID(smp_processor_id())) +#define vpe_id() smp_processor_id() #else -#define WHAT 0 +#define WHAT 0 +#define vpe_id() smp_processor_id() #endif #define __define_perf_accessors(r, n, np) \ \ static inline unsigned int r_c0_ ## r ## n(void) \ { \ - unsigned int cpu = smp_processor_id(); \ + unsigned int cpu = vpe_id(); \ \ switch (cpu) { \ case 0: \ @@ -54,7 +56,7 @@ \ static inline void w_c0_ ## r ## n(unsigned int value) \ { \ - unsigned int cpu = smp_processor_id(); \ + unsigned int cpu = vpe_id(); \ \ switch (cpu) { \ case 0: \ @@ -217,7 +219,7 @@ { int counters = __n_counters(); -#ifndef CONFIG_SMP +#ifdef CONFIG_MIPS_MT_SMP if (current_cpu_data.cputype == CPU_34K) return counters >> 1; #endif diff -Naur linux-2.6.18.3/arch/mips/pci/Makefile linux-mips-2.6.18.3/arch/mips/pci/Makefile --- linux-2.6.18.3/arch/mips/pci/Makefile 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/pci/Makefile 2006-11-20 10:09:08.000000000 -0800 @@ -28,7 +28,7 @@ obj-$(CONFIG_LASAT) += pci-lasat.o obj-$(CONFIG_MIPS_ATLAS) += fixup-atlas.o obj-$(CONFIG_MIPS_COBALT) += fixup-cobalt.o -obj-$(CONFIG_MIPS_EV96100) += fixup-ev64120.o +obj-$(CONFIG_MIPS_EV64120) += pci-ev64120.o obj-$(CONFIG_MIPS_EV96100) += fixup-ev96100.o pci-ev96100.o obj-$(CONFIG_MIPS_ITE8172) += fixup-ite8172g.o obj-$(CONFIG_MIPS_IVR) += fixup-ivr.o diff -Naur linux-2.6.18.3/arch/mips/pci/fixup-atlas.c linux-mips-2.6.18.3/arch/mips/pci/fixup-atlas.c --- linux-2.6.18.3/arch/mips/pci/fixup-atlas.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/pci/fixup-atlas.c 2006-11-20 10:09:08.000000000 -0800 @@ -21,16 +21,16 @@ #include -#define PCIA ATLASINT_PCIA -#define PCIB ATLASINT_PCIB -#define PCIC ATLASINT_PCIC -#define PCID ATLASINT_PCID -#define INTA ATLASINT_INTA -#define INTB ATLASINT_INTB -#define ETH ATLASINT_ETH -#define INTC ATLASINT_INTC -#define SCSI ATLASINT_SCSI -#define INTD ATLASINT_INTD +#define PCIA ATLAS_INT_PCIA +#define PCIB ATLAS_INT_PCIB +#define PCIC ATLAS_INT_PCIC +#define PCID ATLAS_INT_PCID +#define INTA ATLAS_INT_INTA +#define INTB ATLAS_INT_INTB +#define ETH ATLAS_INT_ETH +#define INTC ATLAS_INT_INTC +#define SCSI ATLAS_INT_SCSI +#define INTD ATLAS_INT_INTD static char irq_tab[][5] __initdata = { /* INTA INTB INTC INTD */ diff -Naur linux-2.6.18.3/arch/mips/pci/fixup-ev64120.c linux-mips-2.6.18.3/arch/mips/pci/fixup-ev64120.c --- linux-2.6.18.3/arch/mips/pci/fixup-ev64120.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/pci/fixup-ev64120.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,34 +0,0 @@ -#include -#include - -int pci_range_ck(unsigned char bus, unsigned char dev) -{ - if (((bus == 0) || (bus == 1)) && (dev >= 6) && (dev <= 8)) - return 0; - - return -1; -} - -/* - * After detecting all agents over the PCI , this function is called - * in order to give an interrupt number for each PCI device starting - * from IRQ 20. It does also enables master for each device. - */ -void __devinit pcibios_fixup_bus(struct pci_bus *bus) -{ - unsigned int irq = 20; - struct pci_bus *current_bus = bus; - struct pci_dev *dev; - struct list_head *devices_link; - - list_for_each(devices_link, &(current_bus->devices)) { - dev = pci_dev_b(devices_link); - if (dev != NULL) { - dev->irq = irq++; - - /* Assign an interrupt number for the device */ - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); - pcibios_set_master(dev); - } - } -} diff -Naur linux-2.6.18.3/arch/mips/pci/fixup-tb0219.c linux-mips-2.6.18.3/arch/mips/pci/fixup-tb0219.c --- linux-2.6.18.3/arch/mips/pci/fixup-tb0219.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/pci/fixup-tb0219.c 2006-11-20 10:09:08.000000000 -0800 @@ -2,7 +2,7 @@ * fixup-tb0219.c, The TANBAC TB0219 specific PCI fixups. * * Copyright (C) 2003 Megasolution Inc. - * Copyright (C) 2004 Yoichi Yuasa + * Copyright (C) 2004-2005 Yoichi Yuasa * * 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 diff -Naur linux-2.6.18.3/arch/mips/pci/ops-au1000.c linux-mips-2.6.18.3/arch/mips/pci/ops-au1000.c --- linux-2.6.18.3/arch/mips/pci/ops-au1000.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/pci/ops-au1000.c 2006-11-20 10:09:08.000000000 -0800 @@ -110,7 +110,7 @@ if (first_cfg) { /* reserve a wired entry for pci config accesses */ first_cfg = 0; - pci_cfg_vm = get_vm_area(0x2000, 0); + pci_cfg_vm = get_vm_area(0x2000, VM_IOREMAP); if (!pci_cfg_vm) panic (KERN_ERR "PCI unable to get vm area\n"); pci_cfg_wired_entry = read_c0_wired(); diff -Naur linux-2.6.18.3/arch/mips/pci/pci-ev64120.c linux-mips-2.6.18.3/arch/mips/pci/pci-ev64120.c --- linux-2.6.18.3/arch/mips/pci/pci-ev64120.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/pci/pci-ev64120.c 2006-11-20 10:09:08.000000000 -0800 @@ -0,0 +1,21 @@ +#include + +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + int irq; + + if (!pin) + return 0; + + irq = allocate_irqno(); + if (irq < 0) + return 0; + + return irq; +} + +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} diff -Naur linux-2.6.18.3/arch/mips/qemu/Makefile linux-mips-2.6.18.3/arch/mips/qemu/Makefile --- linux-2.6.18.3/arch/mips/qemu/Makefile 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/qemu/Makefile 2006-11-20 10:09:08.000000000 -0800 @@ -4,4 +4,5 @@ obj-y = q-firmware.o q-irq.o q-mem.o q-setup.o q-reset.o +obj-$(CONFIG_VT) += q-vga.o obj-$(CONFIG_SMP) += q-smp.o diff -Naur linux-2.6.18.3/arch/mips/qemu/q-setup.c linux-mips-2.6.18.3/arch/mips/qemu/q-setup.c --- linux-2.6.18.3/arch/mips/qemu/q-setup.c 2006-11-18 19:28:22.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/qemu/q-setup.c 2006-11-20 10:09:08.000000000 -0800 @@ -2,6 +2,7 @@ #include #include +extern void qvga_init(void); extern void qemu_reboot_setup(void); #define QEMU_PORT_BASE 0xb4000000 @@ -23,5 +24,9 @@ void __init plat_mem_setup(void) { set_io_port_base(QEMU_PORT_BASE); +#ifdef CONFIG_VT + qvga_init(); +#endif + qemu_reboot_setup(); } diff -Naur linux-2.6.18.3/arch/mips/qemu/q-vga.c linux-mips-2.6.18.3/arch/mips/qemu/q-vga.c --- linux-2.6.18.3/arch/mips/qemu/q-vga.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-mips-2.6.18.3/arch/mips/qemu/q-vga.c 2006-11-20 10:09:08.000000000 -0800 @@ -0,0 +1,189 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2005 by Ralf Baechle (ralf@linux-mips.org) + * + * This will eventually go into the qemu firmware. + */ +#include +#include +#include +#include +#include