diff options
| author | Stephen Rothwell <sfr@canb.auug.org.au> | 2005-09-27 13:07:14 -0400 |
|---|---|---|
| committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2005-09-27 13:07:14 -0400 |
| commit | b6b8681843f9eaee12f8c30ffac399f7b2601ab3 (patch) | |
| tree | 378e366e0d85c8d6ffc8da520efe7f96fc8b85ee /arch/powerpc | |
| parent | ed7f2c05de956da72baf066701ac642f7215dbf5 (diff) | |
powerpc: Move iSeries_smp.c to powerpc/platforms/iseries
And rename it to smp.c.
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
Diffstat (limited to 'arch/powerpc')
| -rw-r--r-- | arch/powerpc/platforms/iseries/Makefile | 1 | ||||
| -rw-r--r-- | arch/powerpc/platforms/iseries/smp.c | 121 |
2 files changed, 122 insertions, 0 deletions
diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile index 3a1ed16963a4..202f17419df5 100644 --- a/arch/powerpc/platforms/iseries/Makefile +++ b/arch/powerpc/platforms/iseries/Makefile | |||
| @@ -2,3 +2,4 @@ obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o mf.o lpevents.o \ | |||
| 2 | hvcall.o proc.o htab.o iommu.o | 2 | hvcall.o proc.o htab.o iommu.o |
| 3 | obj-$(CONFIG_PCI) += pci.o irq.o vpdinfo.o | 3 | obj-$(CONFIG_PCI) += pci.o irq.o vpdinfo.o |
| 4 | obj-$(CONFIG_IBMVIO) += vio.o | 4 | obj-$(CONFIG_IBMVIO) += vio.o |
| 5 | obj-$(CONFIG_SMP) += smp.o | ||
diff --git a/arch/powerpc/platforms/iseries/smp.c b/arch/powerpc/platforms/iseries/smp.c new file mode 100644 index 000000000000..f720916682f6 --- /dev/null +++ b/arch/powerpc/platforms/iseries/smp.c | |||
| @@ -0,0 +1,121 @@ | |||
| 1 | /* | ||
| 2 | * SMP support for iSeries machines. | ||
| 3 | * | ||
| 4 | * Dave Engebretsen, Peter Bergner, and | ||
| 5 | * Mike Corrigan {engebret|bergner|mikec}@us.ibm.com | ||
| 6 | * | ||
| 7 | * Plus various changes from other IBM teams... | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or | ||
| 10 | * modify it under the terms of the GNU General Public License | ||
| 11 | * as published by the Free Software Foundation; either version | ||
| 12 | * 2 of the License, or (at your option) any later version. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #undef DEBUG | ||
| 16 | |||
| 17 | #include <linux/config.h> | ||
| 18 | #include <linux/kernel.h> | ||
| 19 | #include <linux/module.h> | ||
| 20 | #include <linux/sched.h> | ||
| 21 | #include <linux/smp.h> | ||
| 22 | #include <linux/smp_lock.h> | ||
| 23 | #include <linux/interrupt.h> | ||
| 24 | #include <linux/kernel_stat.h> | ||
| 25 | #include <linux/delay.h> | ||
| 26 | #include <linux/init.h> | ||
| 27 | #include <linux/spinlock.h> | ||
| 28 | #include <linux/cache.h> | ||
| 29 | #include <linux/err.h> | ||
| 30 | #include <linux/sysdev.h> | ||
| 31 | #include <linux/cpu.h> | ||
| 32 | |||
| 33 | #include <asm/ptrace.h> | ||
| 34 | #include <asm/atomic.h> | ||
| 35 | #include <asm/irq.h> | ||
| 36 | #include <asm/page.h> | ||
| 37 | #include <asm/pgtable.h> | ||
| 38 | #include <asm/io.h> | ||
| 39 | #include <asm/smp.h> | ||
| 40 | #include <asm/paca.h> | ||
| 41 | #include <asm/iSeries/HvCall.h> | ||
| 42 | #include <asm/time.h> | ||
| 43 | #include <asm/ppcdebug.h> | ||
| 44 | #include <asm/machdep.h> | ||
| 45 | #include <asm/cputable.h> | ||
| 46 | #include <asm/system.h> | ||
| 47 | |||
| 48 | static unsigned long iSeries_smp_message[NR_CPUS]; | ||
| 49 | |||
| 50 | void iSeries_smp_message_recv(struct pt_regs *regs) | ||
| 51 | { | ||
| 52 | int cpu = smp_processor_id(); | ||
| 53 | int msg; | ||
| 54 | |||
| 55 | if (num_online_cpus() < 2) | ||
| 56 | return; | ||
| 57 | |||
| 58 | for (msg = 0; msg < 4; msg++) | ||
| 59 | if (test_and_clear_bit(msg, &iSeries_smp_message[cpu])) | ||
| 60 | smp_message_recv(msg, regs); | ||
| 61 | } | ||
| 62 | |||
| 63 | static inline void smp_iSeries_do_message(int cpu, int msg) | ||
| 64 | { | ||
| 65 | set_bit(msg, &iSeries_smp_message[cpu]); | ||
| 66 | HvCall_sendIPI(&(paca[cpu])); | ||
| 67 | } | ||
| 68 | |||
| 69 | static void smp_iSeries_message_pass(int target, int msg) | ||
| 70 | { | ||
| 71 | int i; | ||
| 72 | |||
| 73 | if (target < NR_CPUS) | ||
| 74 | smp_iSeries_do_message(target, msg); | ||
| 75 | else { | ||
| 76 | for_each_online_cpu(i) { | ||
| 77 | if ((target == MSG_ALL_BUT_SELF) && | ||
| 78 | (i == smp_processor_id())) | ||
| 79 | continue; | ||
| 80 | smp_iSeries_do_message(i, msg); | ||
| 81 | } | ||
| 82 | } | ||
| 83 | } | ||
| 84 | |||
| 85 | static int smp_iSeries_probe(void) | ||
| 86 | { | ||
| 87 | return cpus_weight(cpu_possible_map); | ||
| 88 | } | ||
| 89 | |||
| 90 | static void smp_iSeries_kick_cpu(int nr) | ||
| 91 | { | ||
| 92 | BUG_ON((nr < 0) || (nr >= NR_CPUS)); | ||
| 93 | |||
| 94 | /* Verify that our partition has a processor nr */ | ||
| 95 | if (paca[nr].lppaca.dyn_proc_status >= 2) | ||
| 96 | return; | ||
| 97 | |||
| 98 | /* The processor is currently spinning, waiting | ||
| 99 | * for the cpu_start field to become non-zero | ||
| 100 | * After we set cpu_start, the processor will | ||
| 101 | * continue on to secondary_start in iSeries_head.S | ||
| 102 | */ | ||
| 103 | paca[nr].cpu_start = 1; | ||
| 104 | } | ||
| 105 | |||
| 106 | static void __devinit smp_iSeries_setup_cpu(int nr) | ||
| 107 | { | ||
| 108 | } | ||
| 109 | |||
| 110 | static struct smp_ops_t iSeries_smp_ops = { | ||
| 111 | .message_pass = smp_iSeries_message_pass, | ||
| 112 | .probe = smp_iSeries_probe, | ||
| 113 | .kick_cpu = smp_iSeries_kick_cpu, | ||
| 114 | .setup_cpu = smp_iSeries_setup_cpu, | ||
| 115 | }; | ||
| 116 | |||
| 117 | /* This is called very early. */ | ||
| 118 | void __init smp_init_iSeries(void) | ||
| 119 | { | ||
| 120 | smp_ops = &iSeries_smp_ops; | ||
| 121 | } | ||
