diff options
author | Paul Mackerras <paulus@samba.org> | 2007-02-07 14:05:13 +1100 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2007-02-07 14:05:13 +1100 |
commit | 8423200553113cc031caa9b147f6150a8e26545c (patch) | |
tree | 752c93a200c9ba056c7469c96f7e27d02c99291d /arch | |
parent | f03e64f2ca6ee3d0b7824536b1940497701fe766 (diff) | |
parent | 62d0cfcb27cf755cebdc93ca95dabc83608007cd (diff) | |
download | linux-3.10-8423200553113cc031caa9b147f6150a8e26545c.tar.gz linux-3.10-8423200553113cc031caa9b147f6150a8e26545c.tar.bz2 linux-3.10-8423200553113cc031caa9b147f6150a8e26545c.zip |
Merge branch 'linux-2.6'
Diffstat (limited to 'arch')
58 files changed, 442 insertions, 252 deletions
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index 3370e6faeae..c1518639069 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c @@ -47,6 +47,7 @@ * Power off function, if any */ void (*pm_power_off)(void) = machine_power_off; +EXPORT_SYMBOL(pm_power_off); void cpu_idle(void) diff --git a/arch/arm/configs/at91sam9260ek_defconfig b/arch/arm/configs/at91sam9260ek_defconfig index 79049206dfa..46b0c734aeb 100644 --- a/arch/arm/configs/at91sam9260ek_defconfig +++ b/arch/arm/configs/at91sam9260ek_defconfig @@ -923,7 +923,6 @@ CONFIG_FORCED_INLINING=y # CONFIG_HEADERS_CHECK is not set # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set # CONFIG_DEBUG_ERRORS is not set CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/arch/arm/configs/at91sam9261ek_defconfig b/arch/arm/configs/at91sam9261ek_defconfig index 784ad7c0186..fcd8fa091e9 100644 --- a/arch/arm/configs/at91sam9261ek_defconfig +++ b/arch/arm/configs/at91sam9261ek_defconfig @@ -1079,7 +1079,6 @@ CONFIG_FORCED_INLINING=y # CONFIG_HEADERS_CHECK is not set # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set # CONFIG_DEBUG_ERRORS is not set CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index d994561816a..cf495a3084b 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -22,6 +22,10 @@ #include <asm/thread_info.h> #include <asm/system.h> +#if (PHYS_OFFSET & 0x001fffff) +#error "PHYS_OFFSET must be at an even 2MiB boundary!" +#endif + #define KERNEL_RAM_VADDR (PAGE_OFFSET + TEXT_OFFSET) #define KERNEL_RAM_PADDR (PHYS_OFFSET + TEXT_OFFSET) @@ -251,7 +255,8 @@ __create_page_tables: * Then map first 1MB of ram in case it contains our boot params. */ add r0, r4, #PAGE_OFFSET >> 18 - orr r6, r7, #PHYS_OFFSET + orr r6, r7, #(PHYS_OFFSET & 0xff000000) + orr r6, r6, #(PHYS_OFFSET & 0x00e00000) str r6, [r0] #ifdef CONFIG_XIP_KERNEL diff --git a/arch/arm/mach-at91rm9200/at91rm9200_devices.c b/arch/arm/mach-at91rm9200/at91rm9200_devices.c index 4641b99db0e..57fac7203fe 100644 --- a/arch/arm/mach-at91rm9200/at91rm9200_devices.c +++ b/arch/arm/mach-at91rm9200/at91rm9200_devices.c @@ -272,7 +272,7 @@ void __init at91_add_device_cf(struct at91_cf_data *data) at91_set_A_periph(AT91_PIN_PC12, 0); /* NCS6/CFCE2 */ /* nWAIT is _not_ a default setting */ - at91_set_A_periph(AT91_PIN_PC6, 1); /* nWAIT */ + at91_set_A_periph(AT91_PIN_PC6, 1); /* nWAIT */ cf_data = *data; platform_device_register(&at91rm9200_cf_device); diff --git a/arch/arm/mach-at91rm9200/at91sam9260.c b/arch/arm/mach-at91rm9200/at91sam9260.c index 203f073a53e..b14871adc30 100644 --- a/arch/arm/mach-at91rm9200/at91sam9260.c +++ b/arch/arm/mach-at91rm9200/at91sam9260.c @@ -16,6 +16,7 @@ #include <asm/mach/map.h> #include <asm/arch/at91sam9260.h> #include <asm/arch/at91_pmc.h> +#include <asm/arch/at91_rstc.h> #include "generic.h" #include "clock.h" @@ -212,7 +213,7 @@ static struct at91_gpio_bank at91sam9260_gpio[] = { static void at91sam9260_reset(void) { -#warning "Implement CPU reset" + at91_sys_write(AT91_RSTC_CR, (0xA5 << 24) | AT91_RSTC_PROCRST | AT91_RSTC_PERRST); } diff --git a/arch/arm/mach-at91rm9200/at91sam9261.c b/arch/arm/mach-at91rm9200/at91sam9261.c index 5a82f35da2e..d242bb885c6 100644 --- a/arch/arm/mach-at91rm9200/at91sam9261.c +++ b/arch/arm/mach-at91rm9200/at91sam9261.c @@ -16,6 +16,7 @@ #include <asm/mach/map.h> #include <asm/arch/at91sam9261.h> #include <asm/arch/at91_pmc.h> +#include <asm/arch/at91_rstc.h> #include "generic.h" #include "clock.h" @@ -207,7 +208,7 @@ static struct at91_gpio_bank at91sam9261_gpio[] = { static void at91sam9261_reset(void) { -#warning "Implement CPU reset" + at91_sys_write(AT91_RSTC_CR, (0xA5 << 24) | AT91_RSTC_PROCRST | AT91_RSTC_PERRST); } diff --git a/arch/arm/mach-at91rm9200/gpio.c b/arch/arm/mach-at91rm9200/gpio.c index 3f188508c39..af22659c8a2 100644 --- a/arch/arm/mach-at91rm9200/gpio.c +++ b/arch/arm/mach-at91rm9200/gpio.c @@ -20,7 +20,6 @@ #include <asm/io.h> #include <asm/hardware.h> #include <asm/arch/at91_pio.h> -#include <asm/arch/at91_pmc.h> #include <asm/arch/gpio.h> #include "generic.h" @@ -224,17 +223,17 @@ static u32 backups[MAX_GPIO_BANKS]; static int gpio_irq_set_wake(unsigned pin, unsigned state) { unsigned mask = pin_to_mask(pin); + unsigned bank = (pin - PIN_BASE) / 32; - pin -= PIN_BASE; - pin /= 32; - - if (unlikely(pin >= MAX_GPIO_BANKS)) + if (unlikely(bank >= MAX_GPIO_BANKS)) return -EINVAL; if (state) - wakeups[pin] |= mask; + wakeups[bank] |= mask; else - wakeups[pin] &= ~mask; + wakeups[bank] &= ~mask; + + set_irq_wake(gpio[bank].id, state); return 0; } @@ -246,29 +245,15 @@ void at91_gpio_suspend(void) for (i = 0; i < gpio_banks; i++) { u32 pio = gpio[i].offset; - /* - * Note: drivers should have disabled GPIO interrupts that - * aren't supposed to be wakeup sources. - * But that is not much good on ARM..... disable_irq() does - * not update the hardware immediately, so the hardware mask - * (IMR) has the wrong value (not current, too much is - * permitted). - * - * Our workaround is to disable all non-wakeup IRQs ... - * which is exactly what correct drivers asked for in the - * first place! - */ backups[i] = at91_sys_read(pio + PIO_IMR); at91_sys_write(pio + PIO_IDR, backups[i]); at91_sys_write(pio + PIO_IER, wakeups[i]); - if (!wakeups[i]) { - disable_irq_wake(gpio[i].id); - at91_sys_write(AT91_PMC_PCDR, 1 << gpio[i].id); - } else { - enable_irq_wake(gpio[i].id); + if (!wakeups[i]) + clk_disable(gpio[i].clock); + else { #ifdef CONFIG_PM_DEBUG - printk(KERN_DEBUG "GPIO-%c may wake for %08x\n", "ABCD"[i], wakeups[i]); + printk(KERN_DEBUG "GPIO-%c may wake for %08x\n", 'A'+i, wakeups[i]); #endif } } @@ -281,9 +266,11 @@ void at91_gpio_resume(void) for (i = 0; i < gpio_banks; i++) { u32 pio = gpio[i].offset; + if (!wakeups[i]) + clk_enable(gpio[i].clock); + at91_sys_write(pio + PIO_IDR, wakeups[i]); at91_sys_write(pio + PIO_IER, backups[i]); - at91_sys_write(AT91_PMC_PCER, 1 << gpio[i].id); } } diff --git a/arch/arm/mach-imx/cpufreq.c b/arch/arm/mach-imx/cpufreq.c index ac5f9989566..4f66e90db74 100644 --- a/arch/arm/mach-imx/cpufreq.c +++ b/arch/arm/mach-imx/cpufreq.c @@ -184,6 +184,17 @@ static int imx_set_target(struct cpufreq_policy *policy, long sysclk; unsigned int bclk_div = 1; + /* + * Some governors do not respects CPU and policy lower limits + * which leads to bad things (division by zero etc), ensure + * that such things do not happen. + */ + if(target_freq < policy->cpuinfo.min_freq) + target_freq = policy->cpuinfo.min_freq; + + if(target_freq < policy->min) + target_freq = policy->min; + freq = target_freq * 1000; pr_debug(KERN_DEBUG "imx: requested frequency %ld Hz, mpctl0 at boot 0x%08x\n", @@ -258,7 +269,8 @@ static int __init imx_cpufreq_driver_init(struct cpufreq_policy *policy) policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.min_freq = 8000; policy->cpuinfo.max_freq = 200000; - policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; + /* Manual states, that PLL stabilizes in two CLK32 periods */ + policy->cpuinfo.transition_latency = 4 * 1000000000LL / CLK32; return 0; } diff --git a/arch/arm/mach-s3c2410/gpio.c b/arch/arm/mach-s3c2410/gpio.c index ba346546150..f6fb215bb48 100644 --- a/arch/arm/mach-s3c2410/gpio.c +++ b/arch/arm/mach-s3c2410/gpio.c @@ -57,6 +57,7 @@ void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function) case S3C2410_GPIO_SFN2: case S3C2410_GPIO_SFN3: if (pin < S3C2410_GPIO_BANKB) { + function -= 1; function &= 1; function <<= S3C2410_GPIO_OFFSET(pin); } else { @@ -83,15 +84,18 @@ EXPORT_SYMBOL(s3c2410_gpio_cfgpin); unsigned int s3c2410_gpio_getcfg(unsigned int pin) { void __iomem *base = S3C24XX_GPIO_BASE(pin); - unsigned long mask; + unsigned long val = __raw_readl(base); if (pin < S3C2410_GPIO_BANKB) { - mask = 1 << S3C2410_GPIO_OFFSET(pin); + val >>= S3C2410_GPIO_OFFSET(pin); + val &= 1; + val += 1; } else { - mask = 3 << S3C2410_GPIO_OFFSET(pin)*2; + val >>= S3C2410_GPIO_OFFSET(pin)*2; + val &= 3; } - return __raw_readl(base) & mask; + return val | S3C2410_GPIO_INPUT; } EXPORT_SYMBOL(s3c2410_gpio_getcfg); diff --git a/arch/arm/mach-s3c2410/pm.c b/arch/arm/mach-s3c2410/pm.c index 00834097eb8..ebf294dd31d 100644 --- a/arch/arm/mach-s3c2410/pm.c +++ b/arch/arm/mach-s3c2410/pm.c @@ -451,15 +451,14 @@ static void s3c2410_pm_check_resume_pin(unsigned int pin, unsigned int irqoffs) irqstate = s3c_irqwake_eintmask & (1L<<irqoffs); pinstate = s3c2410_gpio_getcfg(pin); - pinstate >>= S3C2410_GPIO_OFFSET(pin)*2; if (!irqstate) { - if (pinstate == 0x02) + if (pinstate == S3C2410_GPIO_IRQ) DBG("Leaving IRQ %d (pin %d) enabled\n", irq, pin); } else { - if (pinstate == 0x02) { + if (pinstate == S3C2410_GPIO_IRQ) { DBG("Disabling IRQ %d (pin %d)\n", irq, pin); - s3c2410_gpio_cfgpin(pin, 0x00); + s3c2410_gpio_cfgpin(pin, S3C2410_GPIO_INPUT); } } } diff --git a/arch/arm/mach-s3c2410/s3c2412-dma.c b/arch/arm/mach-s3c2410/s3c2412-dma.c index fe71a8fdb87..138f726ac6b 100644 --- a/arch/arm/mach-s3c2410/s3c2412-dma.c +++ b/arch/arm/mach-s3c2410/s3c2412-dma.c @@ -133,8 +133,8 @@ static struct s3c24xx_dma_map __initdata s3c2412_dma_mappings[] = { static void s3c2412_dma_select(struct s3c2410_dma_chan *chan, struct s3c24xx_dma_map *map) { - writel(chan->regs + S3C2412_DMA_DMAREQSEL, - map->channels[0] | S3C2412_DMAREQSEL_HW); + writel(map->channels[0] | S3C2412_DMAREQSEL_HW, + chan->regs + S3C2412_DMA_DMAREQSEL); } static struct s3c24xx_dma_selection __initdata s3c2412_dma_sel = { diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index b5814b4b6f3..7760193e74c 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -52,15 +52,18 @@ void show_mem(void) printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); for_each_online_node(node) { + pg_data_t *n = NODE_DATA(node); + struct page *map = n->node_mem_map - n->node_start_pfn; + for_each_nodebank (i,mi,node) { unsigned int pfn1, pfn2; struct page *page, *end; - pfn1 = mi->bank[i].start >> PAGE_SHIFT; - pfn2 = (mi->bank[i].size + mi->bank[i].start) >> PAGE_SHIFT; + pfn1 = __phys_to_pfn(mi->bank[i].start); + pfn2 = __phys_to_pfn(mi->bank[i].size + mi->bank[i].start); - page = NODE_MEM_MAP(node) + pfn1; - end = NODE_MEM_MAP(node) + pfn2; + page = map + pfn1; + end = map + pfn2; do { total++; diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c index 251685fe73a..0ac615c0f79 100644 --- a/arch/arm/mm/ioremap.c +++ b/arch/arm/mm/ioremap.c @@ -300,7 +300,8 @@ __ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size, addr = (unsigned long)area->addr; #ifndef CONFIG_SMP - if ((((cpu_architecture() >= CPU_ARCH_ARMv6) && (get_cr() & CR_XP)) || + if (DOMAIN_IO == 0 && + (((cpu_architecture() >= CPU_ARCH_ARMv6) && (get_cr() & CR_XP)) || cpu_is_xsc3()) && !((__pfn_to_phys(pfn) | size | addr) & ~SUPERSECTION_MASK)) { area->flags |= VM_ARM_SECTION_MAPPING; diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S index 490e11b3423..d29fe927ee9 100644 --- a/arch/arm/mm/proc-xscale.S +++ b/arch/arm/mm/proc-xscale.S @@ -708,7 +708,7 @@ __8032x_proc_info: .type __8033x_proc_info,#object __8033x_proc_info: .long 0x69054010 - .long 0xffffff30 + .long 0xfffffd30 .long PMD_TYPE_SECT | \ PMD_SECT_BUFFERABLE | \ PMD_SECT_CACHEABLE | \ diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types index 8bcb838e544..bd78058b717 100644 --- a/arch/arm/tools/mach-types +++ b/arch/arm/tools/mach-types @@ -12,7 +12,7 @@ # # http://www.arm.linux.org.uk/developer/machines/?action=new # -# Last update: Thu Dec 7 17:19:20 2006 +# Last update: Tue Jan 16 16:52:56 2007 # # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # @@ -1219,3 +1219,26 @@ zevio_1020 MACH_ZEVIO_1020 ZEVIO_1020 1207 hitrack MACH_HITRACK HITRACK 1208 syme1 MACH_SYME1 SYME1 1209 syhl1 MACH_SYHL1 SYHL1 1210 +empca400 MACH_EMPCA400 EMPCA400 1211 +em7210 MACH_EM7210 EM7210 1212 +htchermes MACH_HTCHERMES HTCHERMES 1213 +eti_c1 MACH_ETI_C1 ETI_C1 1214 +mach_dep2410 MACH_MACH_DEP2410 MACH_DEP2410 1215 +ac100 MACH_AC100 AC100 1216 +sneetch MACH_SNEETCH SNEETCH 1217 +studentmate MACH_STUDENTMATE STUDENTMATE 1218 +zir2410 MACH_ZIR2410 ZIR2410 1219 +zir2413 MACH_ZIR2413 ZIR2413 1220 +dlonip3 MACH_DLONIP3 DLONIP3 1221 +instream MACH_INSTREAM INSTREAM 1222 +ambarella MACH_AMBARELLA AMBARELLA 1223 +nevis MACH_NEVIS NEVIS 1224 +htc_trinity MACH_HTC_TRINITY HTC_TRINITY 1225 +ql202b MACH_QL202B QL202B 1226 +vpac270 MACH_VPAC270 VPAC270 1227 +rd129 MACH_RD129 RD129 1228 +htcwizard MACH_HTCWIZARD HTCWIZARD 1229 +xscale_treo680 MACH_XSCALE_TREO680 XSCALE_TREO680 1230 +tecon_tmezon MACH_TECON_TMEZON TECON_TMEZON 1231 +zylonite MACH_ZYLONITE ZYLONITE 1233 +gene1270 MACH_GENE1270 GENE1270 1234 diff --git a/arch/arm/vfp/entry.S b/arch/arm/vfp/entry.S index 7b595547c1c..ca2a5ad19ea 100644 --- a/arch/arm/vfp/entry.S +++ b/arch/arm/vfp/entry.S @@ -25,6 +25,7 @@ do_vfp: enable_irq ldr r4, .LCvfp + ldr r11, [r10, #TI_CPU] @ CPU number add r10, r10, #TI_VFPSTATE @ r10 = workspace ldr pc, [r4] @ call VFP entry point diff --git a/arch/arm/vfp/vfp.h b/arch/arm/vfp/vfp.h index f2797896e6d..54a2ad6d9ca 100644 --- a/arch/arm/vfp/vfp.h +++ b/arch/arm/vfp/vfp.h @@ -370,3 +370,7 @@ struct op { u32 (* const fn)(int dd, int dn, int dm, u32 fpscr); u32 flags; }; + +#ifdef CONFIG_SMP +extern void vfp_save_state(void *location, u32 fpexc); +#endif diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S index e51e6679c40..d4b7b229631 100644 --- a/arch/arm/vfp/vfphw.S +++ b/arch/arm/vfp/vfphw.S @@ -65,6 +65,7 @@ @ r2 = faulted PC+4 @ r9 = successful return @ r10 = vfp_state union +@ r11 = CPU number @ lr = failure return .globl vfp_support_entry @@ -79,7 +80,7 @@ vfp_support_entry: DBGSTR1 "enable %x", r10 ldr r3, last_VFP_context_address orr r1, r1, #FPEXC_ENABLE @ user FPEXC has the enable bit set - ldr r4, [r3] @ last_VFP_context pointer + ldr r4, [r3, r11, lsl #2] @ last_VFP_context pointer bic r5, r1, #FPEXC_EXCEPTION @ make sure exceptions are disabled cmp r4, r10 beq check_for_exception @ we are returning to the same @@ -91,7 +92,9 @@ vfp_support_entry: @ exceptions, so we can get at the @ rest of it +#ifndef CONFIG_SMP @ Save out the current registers to the old thread state + @ No need for SMP since this is not done lazily DBGSTR1 "save old state %p", r4 cmp r4, #0 @@ -105,10 +108,11 @@ vfp_support_entry: stmia r4, {r1, r5, r6, r8} @ save FPEXC, FPSCR, FPINST, FPINST2 @ and point r4 at the word at the @ start of the register dump +#endif no_old_VFP_process: DBGSTR1 "load state %p", r10 - str r10, [r3] @ update the last_VFP_context pointer + str r10, [r3, r11, lsl #2] @ update the last_VFP_context pointer @ Load the saved state back into the VFP VFPFLDMIA r10 @ reload the working registers while @ FPEXC is in a safe state @@ -162,6 +166,24 @@ process_exception: @ required. If not, the user code will @ retry the faulted instruction +#ifdef CONFIG_SMP + .globl vfp_save_state + .type vfp_save_state, %function +vfp_save_state: + @ Save the current VFP state + @ r0 - save location + @ r1 - FPEXC + DBGSTR1 "save VFP state %p", r0 + VFPFMRX r2, FPSCR @ current status + VFPFMRX r3, FPINST @ FPINST (always there, rev0 onwards) + tst r1, #FPEXC_FPV2 @ is there an FPINST2 to read? + VFPFMRX r12, FPINST2, NE @ FPINST2 if needed - avoids reading + @ nonexistant reg on rev0 + VFPFSTMIA r0 @ save the working registers + stmia r0, {r1, r2, r3, r12} @ save FPEXC, FPSCR, FPINST, FPINST2 + mov pc, lr +#endif + last_VFP_context_address: .word last_VFP_context diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index 490d9d18a7d..f1e5951dc72 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c @@ -28,7 +28,7 @@ void vfp_testing_entry(void); void vfp_support_entry(void); void (*vfp_vector)(void) = vfp_testing_entry; -union vfp_state *last_VFP_context; +union vfp_state *last_VFP_context[NR_CPUS]; /* * Dual-use variable. @@ -41,13 +41,35 @@ static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v) { struct thread_info *thread = v; union vfp_state *vfp; + __u32 cpu = thread->cpu; if (likely(cmd == THREAD_NOTIFY_SWITCH)) { + u32 fpexc = fmrx(FPEXC); + +#ifdef CONFIG_SMP + /* + * On SMP, if VFP is enabled, save the old state in + * case the thread migrates to a different CPU. The + * restoring is done lazily. + */ + if ((fpexc & FPEXC_ENABLE) && last_VFP_context[cpu]) { + vfp_save_state(last_VFP_context[cpu], fpexc); + last_VFP_context[cpu]->hard.cpu = cpu; + } + /* + * Thread migration, just force the reloading of the + * state on the new CPU in case the VFP registers + * contain stale data. + */ + if (thread->vfpstate.hard.cpu != cpu) + last_VFP_context[cpu] = NULL; +#endif + /* * Always disable VFP so we can lazily save/restore the * old state. */ - fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_ENABLE); + fmxr(FPEXC, fpexc & ~FPEXC_ENABLE); return NOTIFY_DONE; } @@ -68,8 +90,8 @@ static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v) } /* flush and release case: Per-thread VFP cleanup. */ - if (last_VFP_context == vfp) - last_VFP_context = NULL; + if (last_VFP_context[cpu] == vfp) + last_VFP_context[cpu] = NULL; return NOTIFY_DONE; } diff --git a/arch/avr32/configs/atstk1002_defconfig b/arch/avr32/configs/atstk1002_defconfig index ae92a14ef9a..77dace9d54b 100644 --- a/arch/avr32/configs/atstk1002_defconfig +++ b/arch/avr32/configs/atstk1002_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.19-rc2 -# Fri Oct 20 11:52:37 2006 +# Linux kernel version: 2.6.20-rc6 +# Fri Jan 26 13:12:59 2007 # CONFIG_AVR32=y CONFIG_GENERIC_HARDIRQS=y @@ -9,6 +9,8 @@ CONFIG_HARDIRQS_SW_RESEND=y CONFIG_GENERIC_IRQ_PROBE=y CONFIG_RWSEM_GENERIC_SPINLOCK=y CONFIG_GENERIC_TIME=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" @@ -36,6 +38,7 @@ CONFIG_TASK_DELAY_ACCT=y # CONFIG_UTS_NS is not set CONFIG_AUDIT=y # CONFIG_IKCONFIG is not set +CONFIG_SYSFS_DEPRECATED=y CONFIG_RELAY=y CONFIG_INITRAMFS_SOURCE="" CONFIG_CC_OPTIMIZE_FOR_SIZE=y @@ -75,7 +78,9 @@ CONFIG_MODULE_UNLOAD=y # Block layer # CONFIG_BLOCK=y +# CONFIG_LBD is not set # CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set # # IO Schedulers @@ -125,6 +130,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_OWNERSHIP_TRACE is not set # CONFIG_HZ_100 is not set CONFIG_HZ_250=y +# CONFIG_HZ_300 is not set # CONFIG_HZ_1000 is not set CONFIG_HZ=250 CONFIG_CMDLINE="" @@ -182,6 +188,7 @@ CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_CUBIC=y CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set # CONFIG_IPV6 is not set # CONFIG_INET6_XFRM_TUNNEL is not set # CONFIG_INET6_TUNNEL is not set @@ -260,6 +267,7 @@ CONFIG_MTD_CMDLINE_PARTS=y # User Modules And Translation Layers # CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y CONFIG_MTD_BLOCK=y # CONFIG_FTL is not set # CONFIG_NFTL is not set @@ -355,7 +363,6 @@ CONFIG_BLK_DEV_INITRD=y # # Misc devices # -# CONFIG_SGI_IOC4 is not set # CONFIG_TIFM_CORE is not set # @@ -405,11 +412,14 @@ CONFIG_TUN=m # # PHY device support # +# CONFIG_PHYLIB is not set # # Ethernet (10 or 100Mbit) # -# CONFIG_NET_ETHERNET is not set +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_MACB=y # # Ethernet (1000 Mbit) @@ -505,10 +515,6 @@ CONFIG_UNIX98_PTYS=y # CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set - -# -# Ftape, the floppy tape device driver -# # CONFIG_RAW_DRIVER is not set # @@ -621,6 +627,10 @@ CONFIG_UNIX98_PTYS=y # # +# Virtualization +# + +# # File systems # CONFIG_EXT2_FS=m @@ -683,7 +693,6 @@ CONFIG_CONFIGFS_FS=m # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set CONFIG_JFFS2_FS=y CONFIG_JFFS2_FS_DEBUG=0 CONFIG_JFFS2_FS_WRITEBUFFER=y @@ -763,6 +772,11 @@ CONFIG_NLS_ISO8859_1=m CONFIG_NLS_UTF8=m # +# Distributed Lock Manager +# +# CONFIG_DLM is not set + +# # Kernel hacking # CONFIG_TRACE_IRQFLAGS_SUPPORT=y @@ -770,6 +784,8 @@ CONFIG_TRACE_IRQFLAGS_SUPPORT=y CONFIG_ENABLE_MUST_CHECK=y CONFIG_MAGIC_SYSRQ=y # CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set CONFIG_DEBUG_KERNEL=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_DETECT_SOFTLOCKUP=y @@ -785,13 +801,10 @@ CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_DEBUG_KOBJECT is not set CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_INFO is not set -CONFIG_DEBUG_FS=y # CONFIG_DEBUG_VM is not set # CONFIG_DEBUG_LIST is not set CONFIG_FRAME_POINTER=y -# CONFIG_UNWIND_INFO is not set CONFIG_FORCED_INLINING=y -# CONFIG_HEADERS_CHECK is not set # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_KPROBES is not set @@ -809,6 +822,7 @@ CONFIG_FORCED_INLINING=y # # Library routines # +CONFIG_BITREVERSE=y CONFIG_CRC_CCITT=m # CONFIG_CRC16 is not set CONFIG_CRC32=y @@ -817,3 +831,4 @@ CONFIG_AUDIT_GENERIC=y CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=y CONFIG_PLIST=y +CONFIG_IOMAP_COPY=y diff --git a/arch/avr32/kernel/avr32_ksyms.c b/arch/avr32/kernel/avr32_ksyms.c index 7c4c76114bb..80f55f8dbf1 100644 --- a/arch/avr32/kernel/avr32_ksyms.c +++ b/arch/avr32/kernel/avr32_ksyms.c @@ -29,6 +29,7 @@ EXPORT_SYMBOL(__avr32_asr64); */ EXPORT_SYMBOL(memset); EXPORT_SYMBOL(memcpy); +EXPORT_SYMBOL(clear_page); /* * Userspace access stuff. diff --git a/arch/i386/boot/compressed/relocs.c b/arch/i386/boot/compressed/relocs.c index 468da89153c..881951ca03e 100644 --- a/arch/i386/boot/compressed/relocs.c +++ b/arch/i386/boot/compressed/relocs.c @@ -43,6 +43,8 @@ static int is_safe_abs_reloc(const char* sym_name) /* Match found */ return 1; } + if (strncmp(sym_name, "__crc_", 6) == 0) + return 1; return 0; } diff --git a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c index bec50170b75..4786fedca6e 100644 --- a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c +++ b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c @@ -51,7 +51,6 @@ enum { static int has_N44_O17_errata[NR_CPUS]; -static int has_N60_errata[NR_CPUS]; static unsigned int stock_freq; static struct cpufreq_driver p4clockmod_driver; static unsigned int cpufreq_p4_get(unsigned int cpu); @@ -224,12 +223,6 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy) case 0x0f12: has_N44_O17_errata[policy->cpu] = 1; dprintk("has errata -- disabling low frequencies\n"); - break; - - case 0x0f29: - has_N60_errata[policy->cpu] = 1; - dprintk("has errata -- disabling frequencies lower than 2ghz\n"); - break; } /* get max frequency */ @@ -241,8 +234,6 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy) for (i=1; (p4clockmod_table[i].frequency != CPUFREQ_TABLE_END); i++) { if ((i<2) && (has_N44_O17_errata[policy->cpu])) p4clockmod_table[i].frequency = CPUFREQ_ENTRY_INVALID; - else if (has_N60_errata[policy->cpu] && ((stock_freq * i)/8) < 2000000) - p4clockmod_table[i].frequency = CPUFREQ_ENTRY_INVALID; else p4clockmod_table[i].frequency = (stock_freq * i)/8; } diff --git a/arch/i386/kernel/cpu/cyrix.c b/arch/i386/kernel/cpu/cyrix.c index abcff92f994..c0c3b59de32 100644 --- a/arch/i386/kernel/cpu/cyrix.c +++ b/arch/i386/kernel/cpu/cyrix.c @@ -173,7 +173,7 @@ static void __cpuinit geode_configure(void) ccr4 = getCx86(CX86_CCR4); ccr4 |= 0x38; /* FPU fast, DTE cache, Mem bypass */ - setCx86(CX86_CCR4, ccr4); + setCx86(CX86_CCR3, ccr3); set_cx86_memwb(); set_cx86_reorder(); diff --git a/arch/i386/kernel/efi.c b/arch/i386/kernel/efi.c index b92c7f0a358..8f9c624ace6 100644 --- a/arch/i386/kernel/efi.c +++ b/arch/i386/kernel/efi.c @@ -473,6 +473,70 @@ static inline void __init check_range_for_systab(efi_memory_desc_t *md) } /* + * Wrap all the virtual calls in a way that forces the parameters on the stack. + */ + +#define efi_call_virt(f, args...) \ + ((efi_##f##_t __attribute__((regparm(0)))*)efi.systab->runtime->f)(args) + +static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc) +{ + return efi_call_virt(get_time, tm, tc); +} + +static efi_status_t virt_efi_set_time (efi_time_t *tm) +{ + return efi_call_virt(set_time, tm); +} + +static efi_status_t virt_efi_get_wakeup_time (efi_bool_t *enabled, + efi_bool_t *pending, + efi_time_t *tm) +{ + return efi_call_virt(get_wakeup_time, enabled, pending, tm); +} + +static efi_status_t virt_efi_set_wakeup_time (efi_bool_t enabled, + efi_time_t *tm) +{ + return efi_call_virt(set_wakeup_time, enabled, tm); +} + +static efi_status_t virt_efi_get_variable (efi_char16_t *name, + efi_guid_t *vendor, u32 *attr, + unsigned long *data_size, void *data) +{ + return efi_call_virt(get_variable, name, vendor, attr, data_size, data); +} + +static efi_status_t virt_efi_get_next_variable (unsigned long *name_size, + efi_char16_t *name, + efi_guid_t *vendor) +{ + return efi_call_virt(get_next_variable, name_size, name, vendor); +} + +static efi_status_t virt_efi_set_variable (efi_char16_t *name, + efi_guid_t *vendor, + unsigned long attr, + unsigned long data_size, void *data) +{ + return efi_call_virt(set_variable, name, vendor, attr, data_size, data); +} + +static efi_status_t virt_efi_get_next_high_mono_count (u32 *count) +{ + return efi_call_virt(get_next_high_mono_count, count); +} + +static void virt_efi_reset_system (int reset_type, efi_status_t status, + unsigned long data_size, + efi_char16_t *data) +{ + efi_call_virt(reset_system, reset_type, status, data_size, data); +} + +/* * This function will switch the EFI runtime services to virtual mode. * Essentially, look through the EFI memmap and map every region that * has the runtime attribute bit set in its memory descriptor and update @@ -525,22 +589,15 @@ void __init efi_enter_virtual_mode(void) * pointers in the runtime service table to the new virtual addresses. */ - efi.get_time = (efi_get_time_t *) efi.systab->runtime->get_time; - efi.set_time = (efi_set_time_t *) efi.systab->runtime->set_time; - efi.get_wakeup_time = (efi_get_wakeup_time_t *) - efi.systab->runtime->get_wakeup_time; - efi.set_wakeup_time = (efi_set_wakeup_time_t *) - efi.systab->runtime->set_wakeup_time; - efi.get_variable = (efi_get_variable_t *) - efi.systab->runtime->get_variable; - efi.get_next_variable = (efi_get_next_variable_t *) - efi.systab->runtime->get_next_variable; - efi.set_variable = (efi_set_variable_t *) - efi.systab->runtime->set_variable; - efi.get_next_high_mono_count = (efi_get_next_high_mono_count_t *) - efi.systab->runtime->get_next_high_mono_count; - efi.reset_system = (efi_reset_system_t *) - efi.systab->runtime->reset_system; + efi.get_time = virt_efi_get_time; + efi.set_time = virt_efi_set_time; + efi.get_wakeup_time = virt_efi_get_wakeup_time; + efi.set_wakeup_time = virt_efi_set_wakeup_time; + efi.get_variable = virt_efi_get_variable; + efi.get_next_variable = virt_efi_get_next_variable; + efi.set_variable = virt_efi_set_variable; + efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count; + efi.reset_system = virt_efi_reset_system; } void __init diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S index 06461b8b715..5e47683fc63 100644 --- a/arch/i386/kernel/entry.S +++ b/arch/i386/kernel/entry.S @@ -302,12 +302,16 @@ sysenter_past_esp: pushl $(__USER_CS) CFI_ADJUST_CFA_OFFSET 4 /*CFI_REL_OFFSET cs, 0*/ +#ifndef CONFIG_COMPAT_VDSO /* * Push current_thread_info()->sysenter_return to the stack. * A tiny bit of offset fixup is necessary - 4*4 means the 4 words * pushed above; +8 corresponds to copy_thread's esp0 setting. */ pushl (TI_sysenter_return-THREAD_SIZE+8+4*4)(%esp) +#else + pushl $SYSENTER_RETURN +#endif CFI_ADJUST_CFA_OFFSET 4 CFI_REL_OFFSET eip, 0 diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index 2424cc9c7b3..6a3875f81a0 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c @@ -1227,26 +1227,32 @@ static u8 irq_vector[NR_IRQ_VECTORS] __read_mostly = { FIRST_DEVICE_VECTOR , 0 } static int __assign_irq_vector(int irq) { - static int current_vector = FIRST_DEVICE_VECTOR, offset = 0; - int vector; + static int current_vector = FIRST_DEVICE_VECTOR, current_offset = 0; + int vector, offset, i; BUG_ON((unsigned)irq >= NR_IRQ_VECTORS); if (irq_vector[irq] > 0) return irq_vector[irq]; - current_vector += 8; - if (current_vector == SYSCALL_VECTOR) - current_vector += 8; - - if (current_vector >= FIRST_SYSTEM_VECTOR) { - offset++; - if (!(offset % 8)) - return -ENOSPC; - current_vector = FIRST_DEVICE_VECTOR + offset; - } - vector = current_vector; + offset = current_offset; +next: + vector += 8; + if (vector >= FIRST_SYSTEM_VECTOR) { + offset = (offset + 1) % 8; + vector = FIRST_DEVICE_VECTOR + offset; + } + if (vector == current_vector) + return -ENOSPC; + if (vector == SYSCALL_VECTOR) + goto next; + for (i = 0; i < NR_IRQ_VECTORS; i++) + if (irq_vector[i] == vector) + goto next; + + current_vector = vector; + current_offset = offset; irq_vector[irq] = vector; return vector; diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c index a5e34d65596..1a6f8bb8881 100644 --- a/arch/i386/kernel/nmi.c +++ b/arch/i386/kernel/nmi.c @@ -310,13 +310,7 @@ static int __init setup_nmi_watchdog(char *str) if ((nmi >= NMI_INVALID) || (nmi < NMI_NONE)) return 0; - /* - * If any other x86 CPU has a local APIC, then - * please test the NMI stuff there and send me the - * missing bits. Right now Intel P6/P4 and AMD K7 only. - */ - if ((nmi == NMI_LOCAL_APIC) && (nmi_known_cpu() == 0)) - return 0; /* no lapic support */ + nmi_watchdog = nmi; return 1; } diff --git a/arch/i386/kernel/paravirt.c b/arch/i386/kernel/paravirt.c index 3dceab5828f..e55fd05da0f 100644 --- a/arch/i386/kernel/paravirt.c +++ b/arch/i386/kernel/paravirt.c @@ -566,4 +566,11 @@ struct paravirt_ops paravirt_ops = { .irq_enable_sysexit = native_irq_enable_sysexit, .iret = native_iret, }; -EXPORT_SYMBOL(paravirt_ops); + +/* + * NOTE: CONFIG_PARAVIRT is experimental and the paravirt_ops + * semantics are subject to change. Hence we only do this + * internal-only export of this, until it gets sorted out and + * all lowlevel CPU ops used by modules are separately exported. + */ +EXPORT_SYMBOL_GPL(paravirt_ops); diff --git a/arch/i386/kernel/sysenter.c b/arch/i386/kernel/sysenter.c index 7de9117b5a3..5da744204d1 100644 --- a/arch/i386/kernel/sysenter.c +++ b/arch/i386/kernel/sysenter.c @@ -79,11 +79,6 @@ int __init sysenter_setup(void) #ifdef CONFIG_COMPAT_VDSO __set_fixmap(FIX_VDSO, __pa(syscall_page), PAGE_READONLY); printk("Compat vDSO mapped to %08lx.\n", __fix_to_virt(FIX_VDSO)); -#else - /* - * In the non-compat case the ELF coredumping code needs the fixmap: - */ - __set_fixmap(FIX_VDSO, __pa(syscall_page), PAGE_KERNEL_RO); #endif if (!boot_cpu_has(X86_FEATURE_SEP)) { @@ -100,6 +95,7 @@ int __init sysenter_setup(void) return 0; } +#ifndef CONFIG_COMPAT_VDSO static struct page *syscall_nopage(struct vm_area_struct *vma, unsigned long adr, int *type) { @@ -146,6 +142,13 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int exstack) vma->vm_end = addr + PAGE_SIZE; /* MAYWRITE to allow gdb to COW and set breakpoints */ vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYEXEC|VM_MAYWRITE; + /* + * Make sure the vDSO gets into every core dump. + * Dumping its contents makes post-mortem fully interpretable later + * without matching up the same kernel and hardware config to see + * what PC values meant. + */ + vma->vm_flags |= VM_ALWAYSDUMP; vma->vm_flags |= mm->def_flags; vma->vm_page_prot = protection_map[vma->vm_flags & 7]; vma->vm_ops = &syscall_vm_ops; @@ -187,3 +190,4 @@ int in_gate_area_no_task(unsigned long addr) { return 0; } +#endif diff --git a/arch/i386/mach-default/setup.c b/arch/i386/mach-default/setup.c index c511705c386..cc2f519b2f7 100644 --- a/arch/i386/mach-default/setup.c +++ b/arch/i386/mach-default/setup.c @@ -102,7 +102,7 @@ void __init time_init_hook(void) * along the MCA bus. Use this to hook into that chain if you will need * it. **/ -void __init mca_nmi_hook(void) +void mca_nmi_hook(void) { /* If I recall correctly, there's a whole bunch of other things that * we can do to check for NMI problems, but that's all I know about diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index ef2fe474f10..29f05d4b68c 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -609,6 +609,9 @@ EXPORT_SYMBOL(acpi_register_gsi); void acpi_unregister_gsi(u32 gsi) { + if (acpi_irq_model == ACPI_IRQ_MODEL_PLATFORM) + return; + iosapic_unregister_intr(gsi); } diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c index 54d55e4d64f..ce49c85c928 100644 --- a/arch/ia64/kernel/irq.c +++ b/arch/ia64/kernel/irq.c @@ -122,6 +122,9 @@ static void migrate_irqs(void) for (irq=0; irq < NR_IRQS; irq++) { desc = irq_desc + irq; + if (desc->status == IRQ_DISABLED) + continue; + /* * No handling for now. * TBD: Implement a disable function so we can now diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index fd2ff0698a8..bbd386f572d 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1568,6 +1568,20 @@ config MIPS_MT_FPAFF depends on MIPS_MT default y +config MIPS_MT_SMTC_INSTANT_REPLAY + bool "Low-latency Dispatch of Deferred SMTC IPIs" + depends on MIPS_MT_SMTC + default y + help + SMTC pseudo-interrupts between TCs are deferred and queued + if the target TC is interrupt-inhibited (IXMT). In the first + SMTC prototypes, these queued IPIs were serviced on return + to user mode, or on entry into the kernel idle loop. The + INSTANT_REPLAY option dispatches them as part of local_irq_restore() + processing, which adds runtime overhead (hence the option to turn + it off), but ensures that IPIs are handled promptly even under + heavy I/O interrupt load. + config MIPS_VPE_LOADER_TOM bool "Load VPE program into memory hidden from linux" depends on MIPS_VPE_LOADER diff --git a/arch/mips/Makefile b/arch/mips/Makefile index d1b026a0337..c68b5d3e5d1 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -623,7 +623,7 @@ LDFLAGS += -m $(ld-emul) ifdef CONFIG_MIPS CHECKFLAGS += $(shell $(CC) $(CFLAGS) -dM -E -xc /dev/null | \ - egrep -vw '__GNUC_(MAJOR|MINOR|PATCHLEVEL)__' | \ + egrep -vw '__GNUC_(|MINOR_|PATCHLEVEL_)_' | \ sed -e 's/^\#define /-D/' -e "s/ /='/" -e "s/$$/'/") ifdef CONFIG_64BIT CHECKFLAGS += -m64 diff --git a/arch/mips/dec/prom/memory.c b/arch/mips/dec/prom/memory.c index 3027ce78279..3aa01d268f2 100644 --- a/arch/mips/dec/prom/memory.c +++ b/arch/mips/dec/prom/memory.c @@ -122,7 +122,7 @@ unsigned long __init prom_free_prom_memory(void) addr += PAGE_SIZE; } - printk("Freeing unused PROM memory: %ldk freed\n", + printk("Freeing unused PROM memory: %ldkb freed\n", (end - PAGE_SIZE) >> 10); return end - PAGE_SIZE; diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index a8b387197d5..6a857bf030b 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c @@ -4,6 +4,7 @@ #include <linux/sched.h> #include <linux/cpumask.h> #include <linux/interrupt.h> +#include <linux/module.h> #include <asm/cpu.h> #include <asm/processor.h> @@ -270,9 +271,12 @@ void smtc_configure_tlb(void) * of their initialization in smtc_cpu_setup(). */ - tlbsiz = tlbsiz & 0x3f; /* MIPS32 limits TLB indices to 64 */ - cpu_data[0].tlbsize = tlbsiz; + /* MIPS32 limits TLB indices to 64 */ + if (tlbsiz > 64) + tlbsiz = 64; + cpu_data[0].tlbsize = current_cpu_data.tlbsize = tlbsiz; smtc_status |= SMTC_TLB_SHARED; + local_flush_tlb_all(); printk("TLB of %d entry pairs shared by %d VPEs\n", tlbsiz, vpes); @@ -1017,6 +1021,35 @@ void setup_cross_vpe_interrupts(void) * SMTC-specific hacks invoked from elsewhere in the kernel. */ +void smtc_ipi_replay(void) +{ + /* + * To the extent that we've ever turned interrupts off, + * we may have accumulated deferred IPIs. This is subtle. + * If we use the smtc_ipi_qdepth() macro, we'll get an + * exact number - but we'll also disable interrupts + * and create a window of failure where a new IPI gets + * queued after we test the depth but before we re-enable + * interrupts. So long as IXMT never gets set, however, + * we should be OK: If we pick up something and dispatch + * it here, that's great. If we see nothing, but concurrent + * with this operation, another TC sends us an IPI, IXMT + * is clear, and we'll handle it as a real pseudo-interrupt + * and not a pseudo-pseudo interrupt. + */ + if (IPIQ[smp_processor_id()].depth > 0) { + struct smtc_ipi *pipi; + extern void self_ipi(struct smtc_ipi *); + + while ((pipi = smtc_ipi_dq(&IPIQ[smp_processor_id()]))) { + self_ipi(pipi); + smtc_cpu_stats[smp_processor_id()].selfipis++; + } + } +} + +EXPORT_SYMBOL(smtc_ipi_replay); + void smtc_idle_loop_hook(void) { #ifdef SMTC_IDLE_HOOK_DEBUG @@ -1113,29 +1146,14 @@ void smtc_idle_loop_hook(void) if (pdb_msg != &id_ho_db_msg[0]) printk("CPU%d: %s", smp_processor_id(), id_ho_db_msg); #endif /* SMTC_IDLE_HOOK_DEBUG */ + /* - * To the extent that we've ever turned interrupts off, - * we may have accumulated deferred IPIs. This is subtle. - * If we use the smtc_ipi_qdepth() macro, we'll get an - * exact number - but we'll also disable interrupts - * and create a window of failure where a new IPI gets - * queued after we test the depth but before we re-enable - * interrupts. So long as IXMT never gets set, however, - * we should be OK: If we pick up something and dispatch - * it here, that's great. If we see nothing, but concurrent - * with this operation, another TC sends us an IPI, IXMT - * is clear, and we'll handle it as a real pseudo-interrupt - * and not a pseudo-pseudo interrupt. + * Replay any accumulated deferred IPIs. If "Instant Replay" + * is in use, there should never be any. */ - if (IPIQ[smp_processor_id()].depth > 0) { - struct smtc_ipi *pipi; - extern void self_ipi(struct smtc_ipi *); - - if ((pipi = smtc_ipi_dq(&IPIQ[smp_processor_id()])) != NULL) { - self_ipi(pipi); - smtc_cpu_stats[smp_processor_id()].selfipis++; - } - } +#ifndef CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY + smtc_ipi_replay(); +#endif /* CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY */ } void smtc_soft_dump(void) diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c index 666bef484dc..458fccf87c5 100644 --- a/arch/mips/kernel/vpe.c +++ b/arch/mips/kernel/vpe.c @@ -139,13 +139,16 @@ struct tc { struct list_head list; }; -struct vpecontrol_ { +struct { /* Virtual processing elements */ struct list_head vpe_list; /* Thread contexts */ struct list_head tc_list; -} vpecontrol; +} vpecontrol = { + .vpe_list = LIST_HEAD_INIT(vpecontrol.vpe_list), + .tc_list = LIST_HEAD_INIT(vpecontrol.tc_list) +}; static void release_progmem(void *ptr); /* static __attribute_used__ void dump_vpe(struct vpe * v); */ @@ -1388,8 +1391,6 @@ static int __init vpe_module_init(void) /* dump_mtregs(); */ - INIT_LIST_HEAD(&vpecontrol.vpe_list); - INIT_LIST_HEAD(&vpecontrol.tc_list); val = read_c0_mvpconf0(); for (i = 0; i < ((val & MVPCONF0_PTC) + 1); i++) { diff --git a/arch/mips/mips-boards/malta/Makefile b/arch/mips/mips-boards/malta/Makefile index b662c75fb28..cb7f349b051 100644 --- a/arch/mips/mips-boards/malta/Makefile +++ b/arch/mips/mips-boards/malta/Makefile @@ -19,5 +19,6 @@ # under Linux. # -obj-y := malta_int.o malta_mtd.o malta_setup.o +obj-y := malta_int.o malta_setup.o +obj-$(CONFIG_MTD) += malta_mtd.o obj-$(CONFIG_SMP) += malta_smp.o diff --git a/arch/mips/mips-boards/sim/sim_setup.c b/arch/mips/mips-boards/sim/sim_setup.c index 2659c1c3b78..ea2066c3a1f 100644 --- a/arch/mips/mips-boards/sim/sim_setup.c +++ b/arch/mips/mips-boards/sim/sim_setup.c @@ -57,7 +57,7 @@ void __init plat_mem_setup(void) board_time_init = sim_time_init; prom_printf("Linux started...\n"); -#ifdef CONFIG_MT_SMP +#ifdef CONFIG_MIPS_MT_SMP sanitize_tlb_entries(); #endif } diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 30245c09d02..49065c133eb 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -501,7 +501,8 @@ void free_initmem(void) freed = prom_free_prom_memory(); if (freed) - printk(KERN_INFO "Freeing firmware memory: %ldk freed\n",freed); + printk(KERN_INFO "Freeing firmware memory: %ldkb freed\n", + freed >> 10); free_init_pages("unused kernel memory", __pa_symbol(&__init_begin), diff --git a/arch/mips/momentum/ocelot_g/prom.c b/arch/mips/momentum/ocelot_g/prom.c index 6509a9c9863..2f75c6b91ec 100644 --- a/arch/mips/momentum/ocelot_g/prom.c +++ b/arch/mips/momentum/ocelot_g/prom.c @@ -28,7 +28,7 @@ struct callvectors* debug_vectors; extern unsigned long marvell_base; extern unsigned long bus_clock; -#ifdef CONFIG_GALILLEO_GT64240_ETH +#ifdef CONFIG_GALILEO_GT64240_ETH extern unsigned char prom_mac_addr_base[6]; #endif @@ -61,7 +61,7 @@ void __init prom_init(void) mips_machgroup = MACH_GROUP_MOMENCO; mips_machtype = MACH_MOMENCO_OCELOT_G; -#ifdef CONFIG_GALILLEO_GT64240_ETH +#ifdef CONFIG_GALILEO_GT64240_ETH /* get the base MAC address for on-board ethernet ports */ memcpy(prom_mac_addr_base, (void*)0xfc807cf2, 6); #endif diff --git a/arch/mips/momentum/ocelot_g/setup.c b/arch/mips/momentum/ocelot_g/setup.c index d288f7b0184..9db638a7982 100644 --- a/arch/mips/momentum/ocelot_g/setup.c +++ b/arch/mips/momentum/ocelot_g/setup.c @@ -64,7 +64,7 @@ #include "ocelot_pld.h" -#ifdef CONFIG_GALILLEO_GT64240_ETH +#ifdef CONFIG_GALILEO_GT64240_ETH extern unsigned char prom_mac_addr_base[6]; #endif @@ -185,7 +185,7 @@ void __init plat_mem_setup(void) /* do handoff reconfiguration */ PMON_v2_setup(); -#ifdef CONFIG_GALILLEO_GT64240_ETH +#ifdef CONFIG_GALILEO_GT64240_ETH /* get the mac addr */ memcpy(prom_mac_addr_base, (void*)0xfc807cf2, 6); #endif diff --git a/arch/mips/vr41xx/common/irq.c b/arch/mips/vr41xx/common/irq.c index 397ba94cd7e..16decf4ac2f 100644 --- a/arch/mips/vr41xx/common/irq.c +++ b/arch/mips/vr41xx/common/irq.c @@ -1,7 +1,7 @@ /* * Interrupt handing routines for NEC VR4100 series. * - * Copyright (C) 2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2005-2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> * * 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 @@ -73,13 +73,19 @@ static void irq_dispatch(unsigned int irq) if (cascade->get_irq != NULL) { unsigned int source_irq = irq; desc = irq_desc + source_irq; - desc->chip->ack(source_irq); + if (desc->chip->mask_ack) + desc->chip->mask_ack(source_irq); + else { + desc->chip->mask(source_irq); + desc->chip->ack(source_irq); + } irq = cascade->get_irq(irq); if (irq < 0) atomic_inc(&irq_err_count); else irq_dispatch(irq); - desc->chip->end(source_irq); + if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask) + desc->chip->unmask(source_irq); } else do_IRQ(irq); } diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 5f80f0b828f..aeb53096acf 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -492,6 +492,7 @@ config PPC_MAPLE select PPC_NATIVE select PPC_RTAS select MMIO_NVRAM + select ATA_NONSTANDARD if ATA default n help This option enables support for the Maple 970FX Evaluation Board. @@ -533,12 +534,15 @@ config PPC_IBM_CELL_BLADE select UDBG_RTAS_CONSOLE config PPC_PS3 - bool "Sony PS3" + bool "Sony PS3 (incomplete)" depends on PPC_MULTIPLATFORM && PPC64 select PPC_CELL help This option enables support for the Sony PS3 game console and other platforms using the PS3 hypervisor. + Support for this platform is not yet complete, so + enabling this will not result in a bootable kernel on a + PS3 system. config PPC_CELLEB bool "Toshiba's Cell Reference Set 'Celleb' Architecture" diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index b6d08738180..6828df4afd9 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -1429,7 +1429,7 @@ long sys_pciconfig_iobase(long which, unsigned long in_bus, for (ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) { bus = pci_bus_b(ln); - if (in_bus >= bus->number && in_bus < (bus->number + bus->subordinate)) + if (in_bus >= bus->number && in_bus <= bus->subordinate) break; bus = NULL; } diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index a4b28c73bba..ae0ede19879 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c @@ -284,6 +284,13 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, * pages though */ vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC; + /* + * Make sure the vDSO gets into every core dump. + * Dumping its contents makes post-mortem fully interpretable later + * without matching up the same kernel and hardware config to see + * what PC values meant. + */ + vma->vm_flags |= VM_ALWAYSDUMP; vma->vm_flags |= mm->def_flags; vma->vm_page_prot = protection_map[vma->vm_flags & 0x7]; vma->vm_ops = &vdso_vmops; diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c index 89a28cc018c..113bd48a89b 100644 --- a/arch/sparc/kernel/process.c +++ b/arch/sparc/kernel/process.c @@ -54,6 +54,7 @@ void (*pm_idle)(void); * handler when auxio is not present-- unused for now... */ void (*pm_power_off)(void) = machine_power_off; +EXPORT_SYMBOL(pm_power_off); /* * sysctl - toggle power-off restriction for serial console diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c index 276f22881d0..6b5f26b0fb7 100644 --- a/arch/sparc/kernel/smp.c +++ b/arch/sparc/kernel/smp.c @@ -292,8 +292,8 @@ int setup_profiling_timer(unsigned int multiplier) void __init smp_prepare_cpus(unsigned int max_cpus) { - extern void smp4m_boot_cpus(void); - extern void smp4d_boot_cpus(void); + extern void __init smp4m_boot_cpus(void); + extern void __init smp4d_boot_cpus(void); int i, cpuid, extra; printk("Entering SMP Mode...\n"); @@ -375,8 +375,8 @@ void __init smp_prepare_boot_cpu(void) int __cpuinit __cpu_up(unsigned int cpu) { - extern int smp4m_boot_one_cpu(int); - extern int smp4d_boot_one_cpu(int); + extern int __cpuinit smp4m_boot_one_cpu(int); + extern int __cpuinit smp4d_boot_one_cpu(int); int ret=0; switch(sparc_cpu_model) { diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c index c80ea61e8ba..c69de5d4863 100644 --- a/arch/sparc/kernel/sun4d_smp.c +++ b/arch/sparc/kernel/sun4d_smp.c @@ -164,7 +164,7 @@ void __init smp4d_boot_cpus(void) local_flush_cache_all(); } -int smp4d_boot_one_cpu(int i) +int __cpuinit smp4d_boot_one_cpu(int i) { extern unsigned long sun4d_cpu_startup; unsigned long *entry = &sun4d_cpu_startup; diff --git a/arch/sparc64/kernel/sun4v_tlb_miss.S b/arch/sparc64/kernel/sun4v_tlb_miss.S index b731881224e..9871dbb1ab4 100644 --- a/arch/sparc64/kernel/sun4v_tlb_miss.S +++ b/arch/sparc64/kernel/sun4v_tlb_miss.S @@ -142,9 +142,9 @@ sun4v_dtlb_prot: rdpr %tl, %g1 cmp %g1, 1 bgu,pn %xcc, winfix_trampoline - nop - ba,pt %xcc, sparc64_realfault_common mov FAULT_CODE_DTLB | FAULT_CODE_WRITE, %g4 + ba,pt %xcc, sparc64_realfault_common + nop /* Called from trap table: * %g4: vaddr diff --git a/arch/um/Kconfig.i386 b/arch/um/Kconfig.i386 index f191a550a07..d6cffb27fff 100644 --- a/arch/um/Kconfig.i386 +++ b/arch/um/Kconfig.i386 @@ -19,31 +19,31 @@ config SEMAPHORE_SLEEPERS choice prompt "Host memory split" default HOST_VMSPLIT_3G - ---help--- - This is needed when the host kernel on which you run has a non-default - (like 2G/2G) memory split, instead of the customary 3G/1G. If you did - not recompile your own kernel but use the default distro's one, you can - safely accept the "Default split" option. - - It can be enabled on recent (>=2.6.16-rc2) vanilla kernels via - CONFIG_VM_SPLIT_*, or on previous kernels with special patches (-ck - patchset by Con Kolivas, or other ones) - option names match closely the - host CONFIG_VM_SPLIT_* ones. - - A lower setting (where 1G/3G is lowest and 3G/1G is higher) will - tolerate even more "normal" host kernels, but an higher setting will be - stricter. - - So, if you do not know what to do here, say 'Default split'. - - config HOST_VMSPLIT_3G - bool "Default split (3G/1G user/kernel host split)" - config HOST_VMSPLIT_3G_OPT - bool "3G/1G user/kernel host split (for full 1G low memory)" - config HOST_VMSPLIT_2G - bool "2G/2G user/kernel host split" - config HOST_VMSPLIT_1G - bool "1G/3G user/kernel host split" + help + This is needed when the host kernel on which you run has a non-default + (like 2G/2G) memory split, instead of the customary 3G/1G. If you did + not recompile your own kernel but use the default distro's one, you can + safely accept the "Default split" option. + + It can be enabled on recent (>=2.6.16-rc2) vanilla kernels via + CONFIG_VM_SPLIT_*, or on previous kernels with special patches (-ck + patchset by Con Kolivas, or other ones) - option names match closely the + host CONFIG_VM_SPLIT_* ones. + + A lower setting (where 1G/3G is lowest and 3G/1G is higher) will + tolerate even more "normal" host kernels, but an higher setting will be + stricter. + + So, if you do not know what to do here, say 'Default split'. + +config HOST_VMSPLIT_3G + bool "Default split (3G/1G user/kernel host split)" +config HOST_VMSPLIT_3G_OPT + bool "3G/1G user/kernel host split (for full 1G low memory)" +config HOST_VMSPLIT_2G + bool "2G/2G user/kernel host split" +config HOST_VMSPLIT_1G + bool "1G/3G user/kernel host split" endchoice config TOP_ADDR @@ -67,13 +67,13 @@ config 3_LEVEL_PGTABLES config STUB_CODE hex - default 0xbfffe000 if !HOST_2G_2G - default 0x7fffe000 if HOST_2G_2G + default 0xbfffe000 if !HOST_VMSPLIT_2G + default 0x7fffe000 if HOST_VMSPLIT_2G config STUB_DATA hex - default 0xbffff000 if !HOST_2G_2G - default 0x7ffff000 if HOST_2G_2G + default 0xbffff000 if !HOST_VMSPLIT_2G + default 0x7ffff000 if HOST_VMSPLIT_2G config STUB_START hex diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c index 0709fc6670c..3f6acd66771 100644 --- a/arch/um/sys-i386/signal.c +++ b/arch/um/sys-i386/signal.c @@ -219,7 +219,8 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig, unsigned long save_sp = PT_REGS_SP(regs); int err = 0; - stack_top &= -8UL; + /* This is the same calculation as i386 - ((sp + 4) & 15) == 0 */ + stack_top = ((stack_top + 4) & -16UL) - 4; frame = (struct sigframe __user *) stack_top - 1; if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) return 1; diff --git a/arch/um/sys-x86_64/signal.c b/arch/um/sys-x86_64/signal.c index 9edf114faf7..af2f017617b 100644 --- a/arch/um/sys-x86_64/signal.c +++ b/arch/um/sys-x86_64/signal.c @@ -191,8 +191,9 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, struct task_struct *me = current; frame = (struct rt_sigframe __user *) - round_down(stack_top - sizeof(struct rt_sigframe), 16) - 8; - frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128); + round_down(stack_top - sizeof(struct rt_sigframe), 16); + /* Subtract 128 for a red zone and 8 for proper alignment */ + frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128 - 8); if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate))) goto out; diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c index 543ef4f405e..5ce0bd486bb 100644 --- a/arch/x86_64/ia32/ia32_binfmt.c +++ b/arch/x86_64/ia32/ia32_binfmt.c @@ -64,55 +64,6 @@ typedef unsigned int elf_greg_t; #define ELF_NGREG (sizeof (struct user_regs_struct32) / sizeof(elf_greg_t)) typedef elf_greg_t elf_gregset_t[ELF_NGREG]; -/* - * These macros parameterize elf_core_dump in fs/binfmt_elf.c to write out - * extra segments containing the vsyscall DSO contents. Dumping its - * contents makes post-mortem fully interpretable later without matching up - * the same kernel and hardware config to see what PC values meant. - * Dumping its extra ELF program headers includes all the other information - * a debugger needs to easily find how the vsyscall DSO was being used. - */ -#define ELF_CORE_EXTRA_PHDRS (find_vma(current->mm, VSYSCALL32_BASE) ? \ - (VSYSCALL32_EHDR->e_phnum) : 0) -#define ELF_CORE_WRITE_EXTRA_PHDRS \ -do { \ - if (find_vma(current->mm, VSYSCALL32_BASE)) { \ - const struct elf32_phdr *const vsyscall_phdrs = \ - (const struct elf32_phdr *) (VSYSCALL32_BASE \ - + VSYSCALL32_EHDR->e_phoff);\ - int i; \ - Elf32_Off ofs = 0; \ - for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \ - struct elf32_phdr phdr = vsyscall_phdrs[i]; \ - if (phdr.p_type == PT_LOAD) { \ - BUG_ON(ofs != 0); \ - ofs = phdr.p_offset = offset; \ - phdr.p_memsz = PAGE_ALIGN(phdr.p_memsz); \ - phdr.p_filesz = phdr.p_memsz; \ - offset += phdr.p_filesz; \ - } \ - else \ - phdr.p_offset += ofs; \ - phdr.p_paddr = 0; /* match other core phdrs */ \ - DUMP_WRITE(&phdr, sizeof(phdr)); \ - } \ - } \ -} while (0) -#define ELF_CORE_WRITE_EXTRA_DATA \ -do { \ - if (find_vma(current->mm, VSYSCALL32_BASE)) { \ - const struct elf32_phdr *const vsyscall_phdrs = \ - (const struct elf32_phdr *) (VSYSCALL32_BASE \ - + VSYSCALL32_EHDR->e_phoff); \ - int i; \ - for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \ - if (vsyscall_phdrs[i].p_type == PT_LOAD) \ - DUMP_WRITE((void *) (u64) vsyscall_phdrs[i].p_vaddr,\ - PAGE_ALIGN(vsyscall_phdrs[i].p_memsz)); \ - } \ - } \ -} while (0) - struct elf_siginfo { int si_signo; /* signal number */ diff --git a/arch/x86_64/ia32/syscall32.c b/arch/x86_64/ia32/syscall32.c index 3e5ed20cba4..59f1fa15591 100644 --- a/arch/x86_64/ia32/syscall32.c +++ b/arch/x86_64/ia32/syscall32.c @@ -59,6 +59,13 @@ int syscall32_setup_pages(struct linux_binprm *bprm, int exstack) vma->vm_end = VSYSCALL32_END; /* MAYWRITE to allow gdb to COW and set breakpoints */ vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYEXEC|VM_MAYWRITE; + /* + * Make sure the vDSO gets into every core dump. + * Dumping its contents makes post-mortem fully interpretable later + * without matching up the same kernel and hardware config to see + * what PC values meant. + */ + vma->vm_flags |= VM_ALWAYSDUMP; vma->vm_flags |= mm->def_flags; vma->vm_page_prot = protection_map[vma->vm_flags & 7]; vma->vm_ops = &syscall32_vm_ops; @@ -75,6 +82,14 @@ int syscall32_setup_pages(struct linux_binprm *bprm, int exstack) return 0; } +const char *arch_vma_name(struct vm_area_struct *vma) +{ + if (vma->vm_start == VSYSCALL32_BASE && + vma->vm_mm && vma->vm_mm->task_size == IA32_PAGE_OFFSET) + return "[vdso]"; + return NULL; +} + static int __init init_syscall32(void) { syscall32_page = (void *)get_zeroed_page(GFP_KERNEL); diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c index 186aebbae32..9cb42ecb7f8 100644 --- a/arch/x86_64/kernel/nmi.c +++ b/arch/x86_64/kernel/nmi.c @@ -302,8 +302,6 @@ int __init setup_nmi_watchdog(char *str) if ((nmi >= NMI_INVALID) || (nmi < NMI_NONE)) return 0; - if ((nmi == NMI_LOCAL_APIC) && (nmi_known_cpu() == 0)) - return 0; /* no lapic support */ nmi_watchdog = nmi; return 1; } |