diff options
Diffstat (limited to 'arch/ppc')
44 files changed, 218 insertions, 183 deletions
diff --git a/arch/ppc/8xx_io/cs4218_tdm.c b/arch/ppc/8xx_io/cs4218_tdm.c index 89fe0ceeaa4..2ca9ec7ec3a 100644 --- a/arch/ppc/8xx_io/cs4218_tdm.c +++ b/arch/ppc/8xx_io/cs4218_tdm.c @@ -1380,7 +1380,7 @@ static void cs_nosound(unsigned long xx) spin_unlock_irqrestore(&cs4218_lock, flags); } -static struct timer_list beep_timer = TIMER_INITIALIZER(cs_nosound, 0, 0); +static DEFINE_TIMER(beep_timer, cs_nosound, 0, 0); }; static void cs_mksound(unsigned int hz, unsigned int ticks) diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig index 6ab7e5ea5fc..347ea284140 100644 --- a/arch/ppc/Kconfig +++ b/arch/ppc/Kconfig @@ -265,6 +265,15 @@ config PPC601_SYNC_FIX If in doubt, say Y here. +config HOTPLUG_CPU + bool "Support for enabling/disabling CPUs" + depends on SMP && HOTPLUG && EXPERIMENTAL && PPC_PMAC + ---help--- + Say Y here to be able to disable and re-enable individual + CPUs at runtime on SMP machines. + + Say N if you are unsure. + source arch/ppc/platforms/4xx/Kconfig source arch/ppc/platforms/85xx/Kconfig @@ -499,11 +508,6 @@ config WINCEPT MPC821 PowerPC, introduced in 1998 and designed to be used in thin-client machines. Say Y to support it directly. - Be aware that PCI buses can only function when SYS board is plugged - into the PIB (Platform IO Board) board from Freescale which provide - 3 PCI slots. The PIBs PCI initialization is the bootloader's - responsiblilty. - endchoice choice @@ -680,6 +684,11 @@ config MPC834x_SYS help This option enables support for the MPC 834x SYS evaluation board. + Be aware that PCI buses can only function when SYS board is plugged + into the PIB (Platform IO Board) board from Freescale which provide + 3 PCI slots. The PIBs PCI initialization is the bootloader's + responsiblilty. + config EV64360 bool "Marvell-EV64360BP" help diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile index d1b6e6dcb50..16e2675f327 100644 --- a/arch/ppc/Makefile +++ b/arch/ppc/Makefile @@ -21,13 +21,14 @@ CC := $(CC) -m32 endif LDFLAGS_vmlinux := -Ttext $(KERNELLOAD) -Bstatic -CPPFLAGS += -Iarch/$(ARCH) -Iinclude3 +# The -Iarch/$(ARCH)/include is temporary while we are merging +CPPFLAGS += -Iarch/$(ARCH) -Iarch/$(ARCH)/include AFLAGS += -Iarch/$(ARCH) CFLAGS += -Iarch/$(ARCH) -msoft-float -pipe \ -ffixed-r2 -mmultiple CPP = $(CC) -E $(CFLAGS) # Temporary hack until we have migrated to asm-powerpc -LINUXINCLUDE += -Iinclude3 +LINUXINCLUDE += -Iarch/$(ARCH)/include CHECKFLAGS += -D__powerpc__ @@ -103,21 +104,16 @@ endef archclean: $(Q)$(MAKE) $(clean)=arch/ppc/boot - $(Q)rm -rf include3 + # Temporary hack until we have migrated to asm-powerpc + $(Q)rm -rf arch/$(ARCH)/include -prepare: include/asm-$(ARCH)/offsets.h checkbin - -arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \ - include/config/MARKER - -include/asm-$(ARCH)/offsets.h: arch/$(ARCH)/kernel/asm-offsets.s - $(call filechk,gen-asm-offsets) +archprepare: checkbin # Temporary hack until we have migrated to asm-powerpc -include/asm: include3/asm -include3/asm: - $(Q)if [ ! -d include3 ]; then mkdir -p include3; fi - $(Q)ln -fsn $(srctree)/include/asm-powerpc include3/asm +include/asm: arch/$(ARCH)/include/asm +arch/$(ARCH)/include/asm: + $(Q)if [ ! -d arch/$(ARCH)/include ]; then mkdir -p arch/$(ARCH)/include; fi + $(Q)ln -fsn $(srctree)/include/asm-powerpc arch/$(ARCH)/include/asm # Use the file '.tmp_gas_check' for binutils tests, as gas won't output # to stdout and these checks are run even on install targets. @@ -143,7 +139,5 @@ checkbin: false ; \ fi -CLEAN_FILES += include/asm-$(ARCH)/offsets.h \ - arch/$(ARCH)/kernel/asm-offsets.s \ - $(TOUT) +CLEAN_FILES += $(TOUT) diff --git a/arch/ppc/boot/common/ns16550.c b/arch/ppc/boot/common/ns16550.c index 9017c547a6f..26818bbb6cf 100644 --- a/arch/ppc/boot/common/ns16550.c +++ b/arch/ppc/boot/common/ns16550.c @@ -23,7 +23,7 @@ static int shift; unsigned long serial_init(int chan, void *ignored) { - unsigned long com_port; + unsigned long com_port, base_baud; unsigned char lcr, dlm; /* We need to find out which type io we're expecting. If it's @@ -43,6 +43,8 @@ unsigned long serial_init(int chan, void *ignored) /* How far apart the registers are. */ shift = rs_table[chan].iomem_reg_shift; + /* Base baud.. */ + base_baud = rs_table[chan].baud_base; /* save the LCR */ lcr = inb(com_port + (UART_LCR << shift)); @@ -62,9 +64,9 @@ unsigned long serial_init(int chan, void *ignored) else { /* Input clock. */ outb(com_port + (UART_DLL << shift), - (BASE_BAUD / SERIAL_BAUD) & 0xFF); + (base_baud / SERIAL_BAUD) & 0xFF); outb(com_port + (UART_DLM << shift), - (BASE_BAUD / SERIAL_BAUD) >> 8); + (base_baud / SERIAL_BAUD) >> 8); /* 8 data, 1 stop, no parity */ outb(com_port + (UART_LCR << shift), 0x03); /* RTS/DTR */ diff --git a/arch/ppc/boot/common/util.S b/arch/ppc/boot/common/util.S index 47e641455bc..c96c9f80521 100644 --- a/arch/ppc/boot/common/util.S +++ b/arch/ppc/boot/common/util.S @@ -252,7 +252,7 @@ _GLOBAL(flush_instruction_cache) 1: dcbf r0,r3 # Flush the data cache icbi r0,r3 # Invalidate the instruction cache addi r3,r3,0x10 # Increment by one cache line - cmplwi cr0,r3,r4 # Are we at the end yet? + cmplw cr0,r3,r4 # Are we at the end yet? blt 1b # No, keep flushing and invalidating #else /* Enable, invalidate and then disable the L1 icache/dcache. */ diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile index b1457a8a9c0..1fb92f16acd 100644 --- a/arch/ppc/kernel/Makefile +++ b/arch/ppc/kernel/Makefile @@ -15,8 +15,9 @@ extra-y += vmlinux.lds obj-y := entry.o traps.o irq.o idle.o time.o misc.o \ process.o signal.o ptrace.o align.o \ semaphore.o syscalls.o setup.o \ - cputable.o ppc_htab.o perfmon.o + cputable.o ppc_htab.o obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o +obj-$(CONFIG_E500) += perfmon.o obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o obj-$(CONFIG_POWER4) += cpu_setup_power4.o obj-$(CONFIG_MODULES) += module.o ppc_ksyms.o diff --git a/arch/ppc/kernel/cpu_setup_6xx.S b/arch/ppc/kernel/cpu_setup_6xx.S index bd037caa405..ba396438ede 100644 --- a/arch/ppc/kernel/cpu_setup_6xx.S +++ b/arch/ppc/kernel/cpu_setup_6xx.S @@ -12,10 +12,9 @@ #include <linux/config.h> #include <asm/processor.h> #include <asm/page.h> -#include <asm/ppc_asm.h> #include <asm/cputable.h> #include <asm/ppc_asm.h> -#include <asm/offsets.h> +#include <asm/asm-offsets.h> #include <asm/cache.h> _GLOBAL(__setup_cpu_601) diff --git a/arch/ppc/kernel/cpu_setup_power4.S b/arch/ppc/kernel/cpu_setup_power4.S index f2ea1a990f1..7e4fbb65372 100644 --- a/arch/ppc/kernel/cpu_setup_power4.S +++ b/arch/ppc/kernel/cpu_setup_power4.S @@ -14,8 +14,7 @@ #include <asm/page.h> #include <asm/ppc_asm.h> #include <asm/cputable.h> -#include <asm/ppc_asm.h> -#include <asm/offsets.h> +#include <asm/asm-offsets.h> #include <asm/cache.h> _GLOBAL(__970_cpu_preinit) diff --git a/arch/ppc/kernel/dma-mapping.c b/arch/ppc/kernel/dma-mapping.c index e0c631cf96b..b566d982806 100644 --- a/arch/ppc/kernel/dma-mapping.c +++ b/arch/ppc/kernel/dma-mapping.c @@ -393,7 +393,7 @@ EXPORT_SYMBOL(__dma_sync); * __dma_sync_page() implementation for systems using highmem. * In this case, each page of a buffer must be kmapped/kunmapped * in order to have a virtual address for __dma_sync(). This must - * not sleep so kmap_atmomic()/kunmap_atomic() are used. + * not sleep so kmap_atomic()/kunmap_atomic() are used. * * Note: yes, it is possible and correct to have a buffer extend * beyond the first page. diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S index cb83045e2ed..03d4886869f 100644 --- a/arch/ppc/kernel/entry.S +++ b/arch/ppc/kernel/entry.S @@ -29,7 +29,7 @@ #include <asm/cputable.h> #include <asm/thread_info.h> #include <asm/ppc_asm.h> -#include <asm/offsets.h> +#include <asm/asm-offsets.h> #include <asm/unistd.h> #undef SHOW_SYSCALLS diff --git a/arch/ppc/kernel/fpu.S b/arch/ppc/kernel/fpu.S index 6189b26f640..665d7d34304 100644 --- a/arch/ppc/kernel/fpu.S +++ b/arch/ppc/kernel/fpu.S @@ -18,7 +18,7 @@ #include <asm/cache.h> #include <asm/thread_info.h> #include <asm/ppc_asm.h> -#include <asm/offsets.h> +#include <asm/asm-offsets.h> /* * This task wants to use the FPU now. diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S index a931d773715..1960fb8c259 100644 --- a/arch/ppc/kernel/head.S +++ b/arch/ppc/kernel/head.S @@ -31,7 +31,7 @@ #include <asm/cache.h> #include <asm/thread_info.h> #include <asm/ppc_asm.h> -#include <asm/offsets.h> +#include <asm/asm-offsets.h> #ifdef CONFIG_APUS #include <asm/amigappc.h> @@ -1023,23 +1023,21 @@ __secondary_start_gemini: andc r4,r4,r3 mtspr SPRN_HID0,r4 sync - bl gemini_prom_init b __secondary_start #endif /* CONFIG_GEMINI */ - .globl __secondary_start_psurge -__secondary_start_psurge: - li r24,1 /* cpu # */ - b __secondary_start_psurge99 - .globl __secondary_start_psurge2 -__secondary_start_psurge2: - li r24,2 /* cpu # */ - b __secondary_start_psurge99 - .globl __secondary_start_psurge3 -__secondary_start_psurge3: - li r24,3 /* cpu # */ - b __secondary_start_psurge99 -__secondary_start_psurge99: - /* we come in here with IR=0 and DR=1, and DBAT 0 + + .globl __secondary_start_pmac_0 +__secondary_start_pmac_0: + /* NB the entries for cpus 0, 1, 2 must each occupy 8 bytes. */ + li r24,0 + b 1f + li r24,1 + b 1f + li r24,2 + b 1f + li r24,3 +1: + /* on powersurge, we come in here with IR=0 and DR=1, and DBAT 0 set to map the 0xf0000000 - 0xffffffff region */ mfmsr r0 rlwinm r0,r0,0,28,26 /* clear DR (0x10) */ diff --git a/arch/ppc/kernel/head_44x.S b/arch/ppc/kernel/head_44x.S index 9e68e32edb6..599245b0407 100644 --- a/arch/ppc/kernel/head_44x.S +++ b/arch/ppc/kernel/head_44x.S @@ -40,7 +40,7 @@ #include <asm/cputable.h> #include <asm/thread_info.h> #include <asm/ppc_asm.h> -#include <asm/offsets.h> +#include <asm/asm-offsets.h> #include "head_booke.h" diff --git a/arch/ppc/kernel/head_4xx.S b/arch/ppc/kernel/head_4xx.S index 0a5e723d3be..8562b807b37 100644 --- a/arch/ppc/kernel/head_4xx.S +++ b/arch/ppc/kernel/head_4xx.S @@ -40,7 +40,7 @@ #include <asm/cputable.h> #include <asm/thread_info.h> #include <asm/ppc_asm.h> -#include <asm/offsets.h> +#include <asm/asm-offsets.h> /* As with the other PowerPC ports, it is expected that when code * execution begins here, the following registers contain valid, yet @@ -453,6 +453,7 @@ label: #else CRITICAL_EXCEPTION(0x1020, WDTException, UnknownException) #endif +#endif /* 0x1100 - Data TLB Miss Exception * As the name implies, translation is not in the MMU, so search the diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S index eb18cadb375..cb1a3a54a02 100644 --- a/arch/ppc/kernel/head_8xx.S +++ b/arch/ppc/kernel/head_8xx.S @@ -30,7 +30,7 @@ #include <asm/cputable.h> #include <asm/thread_info.h> #include <asm/ppc_asm.h> -#include <asm/offsets.h> +#include <asm/asm-offsets.h> /* Macro to make the code more readable. */ #ifdef CONFIG_8xx_CPU6 diff --git a/arch/ppc/kernel/head_fsl_booke.S b/arch/ppc/kernel/head_fsl_booke.S index 4028f4c7d97..8e52e840831 100644 --- a/arch/ppc/kernel/head_fsl_booke.S +++ b/arch/ppc/kernel/head_fsl_booke.S @@ -41,7 +41,7 @@ #include <asm/cputable.h> #include <asm/thread_info.h> #include <asm/ppc_asm.h> -#include <asm/offsets.h> +#include <asm/asm-offsets.h> #include "head_booke.h" /* As with the other PowerPC ports, it is expected that when code diff --git a/arch/ppc/kernel/idle.c b/arch/ppc/kernel/idle.c index 53547b6de45..fba29c876b6 100644 --- a/arch/ppc/kernel/idle.c +++ b/arch/ppc/kernel/idle.c @@ -22,6 +22,7 @@ #include <linux/ptrace.h> #include <linux/slab.h> #include <linux/sysctl.h> +#include <linux/cpu.h> #include <asm/pgtable.h> #include <asm/uaccess.h> @@ -35,6 +36,7 @@ void default_idle(void) { void (*powersave)(void); + int cpu = smp_processor_id(); powersave = ppc_md.power_save; @@ -44,7 +46,7 @@ void default_idle(void) #ifdef CONFIG_SMP else { set_thread_flag(TIF_POLLING_NRFLAG); - while (!need_resched()) + while (!need_resched() && !cpu_is_offline(cpu)) barrier(); clear_thread_flag(TIF_POLLING_NRFLAG); } @@ -52,6 +54,8 @@ void default_idle(void) } if (need_resched()) schedule(); + if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING) + cpu_die(); } /* diff --git a/arch/ppc/kernel/idle_6xx.S b/arch/ppc/kernel/idle_6xx.S index 25d009c75f7..1a2194cf682 100644 --- a/arch/ppc/kernel/idle_6xx.S +++ b/arch/ppc/kernel/idle_6xx.S @@ -20,7 +20,7 @@ #include <asm/cputable.h> #include <asm/thread_info.h> #include <asm/ppc_asm.h> -#include <asm/offsets.h> +#include <asm/asm-offsets.h> #undef DEBUG diff --git a/arch/ppc/kernel/idle_power4.S b/arch/ppc/kernel/idle_power4.S index 73a58ff0390..cc0d535365c 100644 --- a/arch/ppc/kernel/idle_power4.S +++ b/arch/ppc/kernel/idle_power4.S @@ -20,7 +20,7 @@ #include <asm/cputable.h> #include <asm/thread_info.h> #include <asm/ppc_asm.h> -#include <asm/offsets.h> +#include <asm/asm-offsets.h> #undef DEBUG diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S index ce71b4a0158..90d917d2e85 100644 --- a/arch/ppc/kernel/misc.S +++ b/arch/ppc/kernel/misc.S @@ -23,7 +23,7 @@ #include <asm/mmu.h> #include <asm/ppc_asm.h> #include <asm/thread_info.h> -#include <asm/offsets.h> +#include <asm/asm-offsets.h> .text diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c index 7b3586a3bf3..854e45beb38 100644 --- a/arch/ppc/kernel/pci.c +++ b/arch/ppc/kernel/pci.c @@ -80,7 +80,6 @@ fixup_broken_pcnet32(struct pci_dev* dev) if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) { dev->vendor = PCI_VENDOR_ID_AMD; pci_write_config_word(dev, PCI_VENDOR_ID, PCI_VENDOR_ID_AMD); - pci_name_device(dev); } } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID, fixup_broken_pcnet32); diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c index e70b587b9e5..726fe7ce174 100644 --- a/arch/ppc/kernel/smp.c +++ b/arch/ppc/kernel/smp.c @@ -45,6 +45,7 @@ cpumask_t cpu_online_map; cpumask_t cpu_possible_map; int smp_hw_index[NR_CPUS]; struct thread_info *secondary_ti; +static struct task_struct *idle_tasks[NR_CPUS]; EXPORT_SYMBOL(cpu_online_map); EXPORT_SYMBOL(cpu_possible_map); @@ -286,7 +287,8 @@ static void __devinit smp_store_cpu_info(int id) void __init smp_prepare_cpus(unsigned int max_cpus) { - int num_cpus, i; + int num_cpus, i, cpu; + struct task_struct *p; /* Fixup boot cpu */ smp_store_cpu_info(smp_processor_id()); @@ -308,6 +310,17 @@ void __init smp_prepare_cpus(unsigned int max_cpus) if (smp_ops->space_timers) smp_ops->space_timers(num_cpus); + + for_each_cpu(cpu) { + if (cpu == smp_processor_id()) + continue; + /* create a process for the processor */ + p = fork_idle(cpu); + if (IS_ERR(p)) + panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p)); + p->thread_info->cpu = cpu; + idle_tasks[cpu] = p; + } } void __devinit smp_prepare_boot_cpu(void) @@ -334,12 +347,17 @@ int __devinit start_secondary(void *unused) set_dec(tb_ticks_per_jiffy); cpu_callin_map[cpu] = 1; - printk("CPU %i done callin...\n", cpu); + printk("CPU %d done callin...\n", cpu); smp_ops->setup_cpu(cpu); - printk("CPU %i done setup...\n", cpu); - local_irq_enable(); + printk("CPU %d done setup...\n", cpu); smp_ops->take_timebase(); - printk("CPU %i done timebase take...\n", cpu); + printk("CPU %d done timebase take...\n", cpu); + + spin_lock(&call_lock); + cpu_set(cpu, cpu_online_map); + spin_unlock(&call_lock); + + local_irq_enable(); cpu_idle(); return 0; @@ -347,17 +365,11 @@ int __devinit start_secondary(void *unused) int __cpu_up(unsigned int cpu) { - struct task_struct *p; char buf[32]; int c; - /* create a process for the processor */ - /* only regs.msr is actually used, and 0 is OK for it */ - p = fork_idle(cpu); - if (IS_ERR(p)) - panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p)); - secondary_ti = p->thread_info; - p->thread_info->cpu = cpu; + secondary_ti = idle_tasks[cpu]->thread_info; + mb(); /* * There was a cache flush loop here to flush the cache @@ -389,7 +401,11 @@ int __cpu_up(unsigned int cpu) printk("Processor %d found.\n", cpu); smp_ops->give_timebase(); - cpu_set(cpu, cpu_online_map); + + /* Wait until cpu puts itself in the online map */ + while (!cpu_online(cpu)) + cpu_relax(); + return 0; } diff --git a/arch/ppc/kernel/swsusp.S b/arch/ppc/kernel/swsusp.S index 55148bb88d3..69773cc1a85 100644 --- a/arch/ppc/kernel/swsusp.S +++ b/arch/ppc/kernel/swsusp.S @@ -5,7 +5,7 @@ #include <asm/cputable.h> #include <asm/thread_info.h> #include <asm/ppc_asm.h> -#include <asm/offsets.h> +#include <asm/asm-offsets.h> /* diff --git a/arch/ppc/kernel/syscalls.c b/arch/ppc/kernel/syscalls.c index 124313ce3c0..127f040de9d 100644 --- a/arch/ppc/kernel/syscalls.c +++ b/arch/ppc/kernel/syscalls.c @@ -41,10 +41,6 @@ #include <asm/ipc.h> #include <asm/semaphore.h> -void -check_bugs(void) -{ -} /* * sys_ipc() is the de-multiplexer for the SysV IPC calls.. diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c index d87423d1003..961ede87be7 100644 --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c @@ -118,6 +118,28 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) info.si_code = code; info.si_addr = (void __user *) addr; force_sig_info(signr, &info, current); + + /* + * Init gets no signals that it doesn't have a handler for. + * That's all very well, but if it has caused a synchronous + * exception and we ignore the resulting signal, it will just + * generate the same exception over and over again and we get + * nowhere. Better to kill it and let the kernel panic. + */ + if (current->pid == 1) { + __sighandler_t handler; + + spin_lock_irq(¤t->sighand->siglock); + handler = current->sighand->action[signr-1].sa.sa_handler; + spin_unlock_irq(¤t->sighand->siglock); + if (handler == SIG_DFL) { + /* init has generated a synchronous exception + and it doesn't have a handler for the signal */ + printk(KERN_CRIT "init has generated signal %d " + "but has no handler for it\n", signr); + do_exit(signr); + } + } } /* @@ -849,10 +871,12 @@ void AltivecAssistException(struct pt_regs *regs) } #endif /* CONFIG_ALTIVEC */ +#ifdef CONFIG_E500 void PerformanceMonitorException(struct pt_regs *regs) { perf_irq(regs); } +#endif #ifdef CONFIG_FSL_BOOKE void CacheLockingException(struct pt_regs *regs, unsigned long address, diff --git a/arch/ppc/lib/Makefile b/arch/ppc/lib/Makefile index 1c380e67d43..f1e1fb4144f 100644 --- a/arch/ppc/lib/Makefile +++ b/arch/ppc/lib/Makefile @@ -4,6 +4,5 @@ obj-y := checksum.o string.o strcase.o dec_and_lock.o div64.o -obj-$(CONFIG_SMP) += locks.o obj-$(CONFIG_8xx) += rheap.o obj-$(CONFIG_CPM2) += rheap.o diff --git a/arch/ppc/lib/dec_and_lock.c b/arch/ppc/lib/dec_and_lock.c index 4ee888070d9..b18f0d9a00f 100644 --- a/arch/ppc/lib/dec_and_lock.c +++ b/arch/ppc/lib/dec_and_lock.c @@ -11,14 +11,7 @@ * has a cmpxchg, and where atomic->value is an int holding * the value of the atomic (i.e. the high bits aren't used * for a lock or anything like that). - * - * N.B. ATOMIC_DEC_AND_LOCK gets defined in include/linux/spinlock.h - * if spinlocks are empty and thus atomic_dec_and_lock is defined - * to be atomic_dec_and_test - in that case we don't need it - * defined here as well. */ - -#ifndef ATOMIC_DEC_AND_LOCK int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) { int counter; @@ -43,4 +36,3 @@ int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) } EXPORT_SYMBOL(_atomic_dec_and_lock); -#endif /* ATOMIC_DEC_AND_LOCK */ diff --git a/arch/ppc/mm/fault.c b/arch/ppc/mm/fault.c index 57d9930843a..ee5e9f25baf 100644 --- a/arch/ppc/mm/fault.c +++ b/arch/ppc/mm/fault.c @@ -278,11 +278,7 @@ bad_area: /* User mode accesses cause a SIGSEGV */ if (user_mode(regs)) { - info.si_signo = SIGSEGV; - info.si_errno = 0; - info.si_code = code; - info.si_addr = (void __user *) address; - force_sig_info(SIGSEGV, &info, current); + _exception(SIGSEGV, regs, code, address); return 0; } diff --git a/arch/ppc/mm/hashtable.S b/arch/ppc/mm/hashtable.S index ab83132a7ed..3ec87c91343 100644 --- a/arch/ppc/mm/hashtable.S +++ b/arch/ppc/mm/hashtable.S @@ -30,7 +30,7 @@ #include <asm/cputable.h> #include <asm/ppc_asm.h> #include <asm/thread_info.h> -#include <asm/offsets.h> +#include <asm/asm-offsets.h> #ifdef CONFIG_SMP .comm mmu_hash_lock,4 diff --git a/arch/ppc/platforms/4xx/ebony.c b/arch/ppc/platforms/4xx/ebony.c index 0fd3442f513..d6b2b1965dc 100644 --- a/arch/ppc/platforms/4xx/ebony.c +++ b/arch/ppc/platforms/4xx/ebony.c @@ -91,15 +91,10 @@ ebony_calibrate_decr(void) * on Rev. C silicon then errata forces us to * use the internal clock. */ - switch (PVR_REV(mfspr(SPRN_PVR))) { - case PVR_REV(PVR_440GP_RB): - freq = EBONY_440GP_RB_SYSCLK; - break; - case PVR_REV(PVR_440GP_RC1): - default: - freq = EBONY_440GP_RC_SYSCLK; - break; - } + if (strcmp(cur_cpu_spec[0]->cpu_name, "440GP Rev. B") == 0) + freq = EBONY_440GP_RB_SYSCLK; + else + freq = EBONY_440GP_RC_SYSCLK; ibm44x_calibrate_decr(freq); } diff --git a/arch/ppc/platforms/hdpu.c b/arch/ppc/platforms/hdpu.c index b659d7b3d74..ff379686012 100644 --- a/arch/ppc/platforms/hdpu.c +++ b/arch/ppc/platforms/hdpu.c @@ -58,7 +58,7 @@ static void parse_bootinfo(unsigned long r3, static void hdpu_set_l1pe(void); static void hdpu_cpustate_set(unsigned char new_state); #ifdef CONFIG_SMP -static spinlock_t timebase_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(timebase_lock); static unsigned int timebase_upper = 0, timebase_lower = 0; extern int smp_tb_synchronized; diff --git a/arch/ppc/platforms/pmac_sleep.S b/arch/ppc/platforms/pmac_sleep.S index 016a7464915..88419c77ac4 100644 --- a/arch/ppc/platforms/pmac_sleep.S +++ b/arch/ppc/platforms/pmac_sleep.S @@ -17,7 +17,7 @@ #include <asm/cputable.h> #include <asm/cache.h> #include <asm/thread_info.h> -#include <asm/offsets.h> +#include <asm/asm-offsets.h> #define MAGIC 0x4c617273 /* 'Lars' */ @@ -161,6 +161,8 @@ _GLOBAL(low_sleep_handler) addi r3,r3,sleep_storage@l stw r5,0(r3) + .globl low_cpu_die +low_cpu_die: /* Flush & disable all caches */ bl flush_disable_caches diff --git a/arch/ppc/platforms/pmac_smp.c b/arch/ppc/platforms/pmac_smp.c index 8e049dab4e6..794a23994b8 100644 --- a/arch/ppc/platforms/pmac_smp.c +++ b/arch/ppc/platforms/pmac_smp.c @@ -33,6 +33,7 @@ #include <linux/spinlock.h> #include <linux/errno.h> #include <linux/hardirq.h> +#include <linux/cpu.h> #include <asm/ptrace.h> #include <asm/atomic.h> @@ -55,9 +56,7 @@ * Powersurge (old powermac SMP) support. */ -extern void __secondary_start_psurge(void); -extern void __secondary_start_psurge2(void); /* Temporary horrible hack */ -extern void __secondary_start_psurge3(void); /* Temporary horrible hack */ +extern void __secondary_start_pmac_0(void); /* Addresses for powersurge registers */ #define HAMMERHEAD_BASE 0xf8000000 @@ -119,7 +118,7 @@ static volatile int sec_tb_reset = 0; static unsigned int pri_tb_hi, pri_tb_lo; static unsigned int pri_tb_stamp; -static void __init core99_init_caches(int cpu) +static void __devinit core99_init_caches(int cpu) { if (!cpu_has_feature(CPU_FTR_L2CR)) return; @@ -346,7 +345,7 @@ static int __init smp_psurge_probe(void) static void __init smp_psurge_kick_cpu(int nr) { - void (*start)(void) = __secondary_start_psurge; + unsigned long start = __pa(__secondary_start_pmac_0) + nr * 8; unsigned long a; /* may need to flush here if secondary bats aren't setup */ @@ -356,17 +355,7 @@ static void __init smp_psurge_kick_cpu(int nr) if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu", 0x353); - /* setup entry point of secondary processor */ - switch (nr) { - case 2: - start = __secondary_start_psurge2; - break; - case 3: - start = __secondary_start_psurge3; - break; - } - - out_be32(psurge_start, __pa(start)); + out_be32(psurge_start, start); mb(); psurge_set_ipi(nr); @@ -500,14 +489,14 @@ static int __init smp_core99_probe(void) return ncpus; } -static void __init smp_core99_kick_cpu(int nr) +static void __devinit smp_core99_kick_cpu(int nr) { unsigned long save_vector, new_vector; unsigned long flags; volatile unsigned long *vector = ((volatile unsigned long *)(KERNELBASE+0x100)); - if (nr < 1 || nr > 3) + if (nr < 0 || nr > 3) return; if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu", 0x346); @@ -518,19 +507,9 @@ static void __init smp_core99_kick_cpu(int nr) save_vector = *vector; /* Setup fake reset vector that does - * b __secondary_start_psurge - KERNELBASE + * b __secondary_start_pmac_0 + nr*8 - KERNELBASE */ - switch(nr) { - case 1: - new_vector = (unsigned long)__secondary_start_psurge; - break; - case 2: - new_vector = (unsigned long)__secondary_start_psurge2; - break; - case 3: - new_vector = (unsigned long)__secondary_start_psurge3; - break; - } + new_vector = (unsigned long) __secondary_start_pmac_0 + nr * 8; *vector = 0x48000002 + new_vector - KERNELBASE; /* flush data cache and inval instruction cache */ @@ -554,7 +533,7 @@ static void __init smp_core99_kick_cpu(int nr) if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu done", 0x347); } -static void __init smp_core99_setup_cpu(int cpu_nr) +static void __devinit smp_core99_setup_cpu(int cpu_nr) { /* Setup L2/L3 */ if (cpu_nr != 0) @@ -668,3 +647,47 @@ struct smp_ops_t core99_smp_ops __pmacdata = { .give_timebase = smp_core99_give_timebase, .take_timebase = smp_core99_take_timebase, }; + +#ifdef CONFIG_HOTPLUG_CPU + +int __cpu_disable(void) +{ + cpu_clear(smp_processor_id(), cpu_online_map); + + /* XXX reset cpu affinity here */ + openpic_set_priority(0xf); + asm volatile("mtdec %0" : : "r" (0x7fffffff)); + mb(); + udelay(20); + asm volatile("mtdec %0" : : "r" (0x7fffffff)); + return 0; +} + +extern void low_cpu_die(void) __attribute__((noreturn)); /* in pmac_sleep.S */ +static int cpu_dead[NR_CPUS]; + +void cpu_die(void) +{ + local_irq_disable(); + cpu_dead[smp_processor_id()] = 1; + mb(); + low_cpu_die(); +} + +void __cpu_die(unsigned int cpu) +{ + int timeout; + + timeout = 1000; + while (!cpu_dead[cpu]) { + if (--timeout == 0) { + printk("CPU %u refused to die!\n", cpu); + break; + } + msleep(1); + } + cpu_callin_map[cpu] = 0; + cpu_dead[cpu] = 0; +} + +#endif diff --git a/arch/ppc/syslib/cpc700_pic.c b/arch/ppc/syslib/cpc700_pic.c index 77470980753..75fe8eb1069 100644 --- a/arch/ppc/syslib/cpc700_pic.c +++ b/arch/ppc/syslib/cpc700_pic.c @@ -90,14 +90,10 @@ cpc700_mask_and_ack_irq(unsigned int irq) } static struct hw_interrupt_type cpc700_pic = { - "CPC700 PIC", - NULL, - NULL, - cpc700_unmask_irq, - cpc700_mask_irq, - cpc700_mask_and_ack_irq, - NULL, - NULL + .typename = "CPC700 PIC", + .enable = cpc700_unmask_irq, + .disable = cpc700_mask_irq, + .ack = cpc700_mask_and_ack_irq, }; __init static void diff --git a/arch/ppc/syslib/i8259.c b/arch/ppc/syslib/i8259.c index b9391e65014..5c7908c20e4 100644 --- a/arch/ppc/syslib/i8259.c +++ b/arch/ppc/syslib/i8259.c @@ -129,14 +129,11 @@ static void i8259_end_irq(unsigned int irq) } struct hw_interrupt_type i8259_pic = { - " i8259 ", - NULL, - NULL, - i8259_unmask_irq, - i8259_mask_irq, - i8259_mask_and_ack_irq, - i8259_end_irq, - NULL + .typename = " i8259 ", + .enable = i8259_unmask_irq, + .disable = i8259_mask_irq, + .ack = i8259_mask_and_ack_irq, + .end = i8259_end_irq, }; static struct resource pic1_iores = { diff --git a/arch/ppc/syslib/ibm440gx_common.c b/arch/ppc/syslib/ibm440gx_common.c index d4776af6a3c..0bb919859b8 100644 --- a/arch/ppc/syslib/ibm440gx_common.c +++ b/arch/ppc/syslib/ibm440gx_common.c @@ -236,9 +236,10 @@ void __init ibm440gx_l2c_setup(struct ibm44x_clocks* p) /* Disable L2C on rev.A, rev.B and 800MHz version of rev.C, enable it on all other revisions */ - u32 pvr = mfspr(SPRN_PVR); - if (pvr == PVR_440GX_RA || pvr == PVR_440GX_RB || - (pvr == PVR_440GX_RC && p->cpu > 667000000)) + if (strcmp(cur_cpu_spec[0]->cpu_name, "440GX Rev. A") == 0 || + strcmp(cur_cpu_spec[0]->cpu_name, "440GX Rev. B") == 0 + || (strcmp(cur_cpu_spec[0]->cpu_name, "440GX Rev. C") + == 0 && p->cpu > 667000000)) ibm440gx_l2c_disable(); else ibm440gx_l2c_enable(); diff --git a/arch/ppc/syslib/mpc10x_common.c b/arch/ppc/syslib/mpc10x_common.c index 87065e2e4c5..3e039706bdb 100644 --- a/arch/ppc/syslib/mpc10x_common.c +++ b/arch/ppc/syslib/mpc10x_common.c @@ -140,12 +140,12 @@ struct platform_device ppc_sys_platform_devices[] = { }, [MPC10X_UART0] = { .name = "serial8250", - .id = 0, + .id = PLAT8250_DEV_PLATFORM, .dev.platform_data = serial_plat_uart0, }, [MPC10X_UART1] = { .name = "serial8250", - .id = 1, + .id = PLAT8250_DEV_PLATFORM1, .dev.platform_data = serial_plat_uart1, }, diff --git a/arch/ppc/syslib/mpc83xx_devices.c b/arch/ppc/syslib/mpc83xx_devices.c index 5aaf0e58e1f..95b3b8a7f0b 100644 --- a/arch/ppc/syslib/mpc83xx_devices.c +++ b/arch/ppc/syslib/mpc83xx_devices.c @@ -165,7 +165,7 @@ struct platform_device ppc_sys_platform_devices[] = { }, [MPC83xx_DUART] = { .name = "serial8250", - .id = 0, + .id = PLAT8250_DEV_PLATFORM, .dev.platform_data = serial_platform_data, }, [MPC83xx_SEC2] = { diff --git a/arch/ppc/syslib/mpc85xx_devices.c b/arch/ppc/syslib/mpc85xx_devices.c index 8af322dd476..bbc5ac0de87 100644 --- a/arch/ppc/syslib/mpc85xx_devices.c +++ b/arch/ppc/syslib/mpc85xx_devices.c @@ -282,7 +282,7 @@ struct platform_device ppc_sys_platform_devices[] = { }, [MPC85xx_DUART] = { .name = "serial8250", - .id = 0, + .id = PLAT8250_DEV_PLATFORM, .dev.platform_data = serial_platform_data, }, [MPC85xx_PERFMON] = { diff --git a/arch/ppc/syslib/mv64x60.c b/arch/ppc/syslib/mv64x60.c index 6262b11f366..839f8872826 100644 --- a/arch/ppc/syslib/mv64x60.c +++ b/arch/ppc/syslib/mv64x60.c @@ -31,7 +31,7 @@ u8 mv64x60_pci_exclude_bridge = 1; -spinlock_t mv64x60_lock = SPIN_LOCK_UNLOCKED; +DEFINE_SPINLOCK(mv64x60_lock); static phys_addr_t mv64x60_bridge_pbase; static void *mv64x60_bridge_vbase; diff --git a/arch/ppc/syslib/open_pic2.c b/arch/ppc/syslib/open_pic2.c index 7e272c51a49..2e0ea92144f 100644 --- a/arch/ppc/syslib/open_pic2.c +++ b/arch/ppc/syslib/open_pic2.c @@ -82,13 +82,11 @@ static void openpic2_end_irq(unsigned int irq_nr); static void openpic2_ack_irq(unsigned int irq_nr); struct hw_interrupt_type open_pic2 = { - " OpenPIC2 ", - NULL, - NULL, - openpic2_enable_irq, - openpic2_disable_irq, - openpic2_ack_irq, - openpic2_end_irq, + .typename = " OpenPIC2 ", + .enable = openpic2_enable_irq, + .disable = openpic2_disable_irq, + .ack = openpic2_ack_irq, + .end = openpic2_end_irq, }; /* diff --git a/arch/ppc/syslib/ppc403_pic.c b/arch/ppc/syslib/ppc403_pic.c index 06cb0af2a58..ce4d1deb86e 100644 --- a/arch/ppc/syslib/ppc403_pic.c +++ b/arch/ppc/syslib/ppc403_pic.c @@ -34,13 +34,10 @@ static void ppc403_aic_disable(unsigned int irq); static void ppc403_aic_disable_and_ack(unsigned int irq); static struct hw_interrupt_type ppc403_aic = { - "403GC AIC", - NULL, - NULL, - ppc403_aic_enable, - ppc403_aic_disable, - ppc403_aic_disable_and_ack, - 0 + .typename = "403GC AIC", + .enable = ppc403_aic_enable, + .disable = ppc403_aic_disable, + .ack = ppc403_aic_disable_and_ack, }; int diff --git a/arch/ppc/syslib/qspan_pci.c b/arch/ppc/syslib/qspan_pci.c index 57f4ed5e5ae..0970b5d3039 100644 --- a/arch/ppc/syslib/qspan_pci.c +++ b/arch/ppc/syslib/qspan_pci.c @@ -94,7 +94,7 @@ #define mk_config_type1(bus, dev, offset) \ mk_config_addr(bus, dev, offset) | 1; -static spinlock_t pcibios_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(pcibios_lock); int qspan_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned char *val) diff --git a/arch/ppc/syslib/xilinx_pic.c b/arch/ppc/syslib/xilinx_pic.c index e0bd66f0847..2cbcad278ce 100644 --- a/arch/ppc/syslib/xilinx_pic.c +++ b/arch/ppc/syslib/xilinx_pic.c @@ -79,14 +79,11 @@ xilinx_intc_end(unsigned int irq) } static struct hw_interrupt_type xilinx_intc = { - "Xilinx Interrupt Controller", - NULL, - NULL, - xilinx_intc_enable, - xilinx_intc_disable, - xilinx_intc_disable_and_ack, - xilinx_intc_end, - 0 + .typename = "Xilinx Interrupt Controller", + .enable = xilinx_intc_enable, + .disable = xilinx_intc_disable, + .ack = xilinx_intc_disable_and_ack, + .end = xilinx_intc_end, }; int |