aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/Kconfig1
-rw-r--r--arch/powerpc/boot/dts/canyonlands.dts18
-rw-r--r--arch/powerpc/boot/dts/katmai.dts18
-rw-r--r--arch/powerpc/boot/dts/kilauea.dts28
-rw-r--r--arch/powerpc/boot/dts/redwood.dts20
-rw-r--r--arch/powerpc/include/asm/ftrace.h14
-rw-r--r--arch/powerpc/include/asm/hvcall.h2
-rw-r--r--arch/powerpc/include/asm/smp.h2
-rw-r--r--arch/powerpc/include/asm/syscall.h5
-rw-r--r--arch/powerpc/include/asm/thread_info.h7
-rw-r--r--arch/powerpc/kernel/Makefile1
-rw-r--r--arch/powerpc/kernel/ftrace.c8
-rw-r--r--arch/powerpc/kernel/irq.c46
-rw-r--r--arch/powerpc/kernel/ptrace.c10
-rw-r--r--arch/powerpc/kernel/smp.c2
-rw-r--r--arch/powerpc/oprofile/op_model_power4.c24
-rw-r--r--arch/powerpc/platforms/40x/Kconfig2
-rw-r--r--arch/powerpc/platforms/44x/Kconfig6
-rw-r--r--arch/powerpc/platforms/cell/interrupt.c55
-rw-r--r--arch/powerpc/platforms/cell/interrupt.h2
-rw-r--r--arch/powerpc/platforms/cell/smp.c2
-rw-r--r--arch/powerpc/sysdev/Kconfig7
-rw-r--r--arch/powerpc/sysdev/Makefile1
-rw-r--r--arch/powerpc/sysdev/ppc4xx_msi.c276
-rw-r--r--include/linux/smp.h10
25 files changed, 491 insertions, 76 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 423145a6f7ba..2f6a22e8e935 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -141,6 +141,7 @@ config PPC
141 select GENERIC_IRQ_SHOW 141 select GENERIC_IRQ_SHOW
142 select GENERIC_IRQ_SHOW_LEVEL 142 select GENERIC_IRQ_SHOW_LEVEL
143 select HAVE_RCU_TABLE_FREE if SMP 143 select HAVE_RCU_TABLE_FREE if SMP
144 select HAVE_SYSCALL_TRACEPOINTS
144 145
145config EARLY_PRINTK 146config EARLY_PRINTK
146 bool 147 bool
diff --git a/arch/powerpc/boot/dts/canyonlands.dts b/arch/powerpc/boot/dts/canyonlands.dts
index 2779f08313a5..22dd6ae84da0 100644
--- a/arch/powerpc/boot/dts/canyonlands.dts
+++ b/arch/powerpc/boot/dts/canyonlands.dts
@@ -530,5 +530,23 @@
530 0x0 0x0 0x0 0x3 &UIC3 0x12 0x4 /* swizzled int C */ 530 0x0 0x0 0x0 0x3 &UIC3 0x12 0x4 /* swizzled int C */
531 0x0 0x0 0x0 0x4 &UIC3 0x13 0x4 /* swizzled int D */>; 531 0x0 0x0 0x0 0x4 &UIC3 0x13 0x4 /* swizzled int D */>;
532 }; 532 };
533
534 MSI: ppc4xx-msi@C10000000 {
535 compatible = "amcc,ppc4xx-msi", "ppc4xx-msi";
536 reg = < 0xC 0x10000000 0x100>;
537 sdr-base = <0x36C>;
538 msi-data = <0x00000000>;
539 msi-mask = <0x44440000>;
540 interrupt-count = <3>;
541 interrupts = <0 1 2 3>;
542 interrupt-parent = <&UIC3>;
543 #interrupt-cells = <1>;
544 #address-cells = <0>;
545 #size-cells = <0>;
546 interrupt-map = <0 &UIC3 0x18 1
547 1 &UIC3 0x19 1
548 2 &UIC3 0x1A 1
549 3 &UIC3 0x1B 1>;
550 };
533 }; 551 };
534}; 552};
diff --git a/arch/powerpc/boot/dts/katmai.dts b/arch/powerpc/boot/dts/katmai.dts
index 7c3be5e45748..f913dbe25d35 100644
--- a/arch/powerpc/boot/dts/katmai.dts
+++ b/arch/powerpc/boot/dts/katmai.dts
@@ -442,6 +442,24 @@
442 0x0 0x0 0x0 0x4 &UIC3 0xb 0x4 /* swizzled int D */>; 442 0x0 0x0 0x0 0x4 &UIC3 0xb 0x4 /* swizzled int D */>;
443 }; 443 };
444 444
445 MSI: ppc4xx-msi@400300000 {
446 compatible = "amcc,ppc4xx-msi", "ppc4xx-msi";
447 reg = < 0x4 0x00300000 0x100>;
448 sdr-base = <0x3B0>;
449 msi-data = <0x00000000>;
450 msi-mask = <0x44440000>;
451 interrupt-count = <3>;
452 interrupts =<0 1 2 3>;
453 interrupt-parent = <&UIC0>;
454 #interrupt-cells = <1>;
455 #address-cells = <0>;
456 #size-cells = <0>;
457 interrupt-map = <0 &UIC0 0xC 1
458 1 &UIC0 0x0D 1
459 2 &UIC0 0x0E 1
460 3 &UIC0 0x0F 1>;
461 };
462
445 I2O: i2o@400100000 { 463 I2O: i2o@400100000 {
446 compatible = "ibm,i2o-440spe"; 464 compatible = "ibm,i2o-440spe";
447 reg = <0x00000004 0x00100000 0x100>; 465 reg = <0x00000004 0x00100000 0x100>;
diff --git a/arch/powerpc/boot/dts/kilauea.dts b/arch/powerpc/boot/dts/kilauea.dts
index 89edb16649c3..1613d6e4049e 100644
--- a/arch/powerpc/boot/dts/kilauea.dts
+++ b/arch/powerpc/boot/dts/kilauea.dts
@@ -403,5 +403,33 @@
403 0x0 0x0 0x0 0x3 &UIC2 0xd 0x4 /* swizzled int C */ 403 0x0 0x0 0x0 0x3 &UIC2 0xd 0x4 /* swizzled int C */
404 0x0 0x0 0x0 0x4 &UIC2 0xe 0x4 /* swizzled int D */>; 404 0x0 0x0 0x0 0x4 &UIC2 0xe 0x4 /* swizzled int D */>;
405 }; 405 };
406
407 MSI: ppc4xx-msi@C10000000 {
408 compatible = "amcc,ppc4xx-msi", "ppc4xx-msi";
409 reg = < 0x0 0xEF620000 0x100>;
410 sdr-base = <0x4B0>;
411 msi-data = <0x00000000>;
412 msi-mask = <0x44440000>;
413 interrupt-count = <12>;
414 interrupts = <0 1 2 3 4 5 6 7 8 9 0xA 0xB 0xC 0xD>;
415 interrupt-parent = <&UIC2>;
416 #interrupt-cells = <1>;
417 #address-cells = <0>;
418 #size-cells = <0>;
419 interrupt-map = <0 &UIC2 0x10 1
420 1 &UIC2 0x11 1
421 2 &UIC2 0x12 1
422 2 &UIC2 0x13 1
423 2 &UIC2 0x14 1
424 2 &UIC2 0x15 1
425 2 &UIC2 0x16 1
426 2 &UIC2 0x17 1
427 2 &UIC2 0x18 1
428 2 &UIC2 0x19 1
429 2 &UIC2 0x1A 1
430 2 &UIC2 0x1B 1
431 2 &UIC2 0x1C 1
432 3 &UIC2 0x1D 1>;
433 };
406 }; 434 };
407}; 435};
diff --git a/arch/powerpc/boot/dts/redwood.dts b/arch/powerpc/boot/dts/redwood.dts
index 81636c01d906..d86a3a498118 100644
--- a/arch/powerpc/boot/dts/redwood.dts
+++ b/arch/powerpc/boot/dts/redwood.dts
@@ -358,8 +358,28 @@
358 0x0 0x0 0x0 0x4 &UIC3 0xb 0x4 /* swizzled int D */>; 358 0x0 0x0 0x0 0x4 &UIC3 0xb 0x4 /* swizzled int D */>;
359 }; 359 };
360 360
361 MSI: ppc4xx-msi@400300000 {
362 compatible = "amcc,ppc4xx-msi", "ppc4xx-msi";
363 reg = < 0x4 0x00300000 0x100
364 0x4 0x00300000 0x100>;
365 sdr-base = <0x3B0>;
366 msi-data = <0x00000000>;
367 msi-mask = <0x44440000>;
368 interrupt-count = <3>;
369 interrupts =<0 1 2 3>;
370 interrupt-parent = <&UIC0>;
371 #interrupt-cells = <1>;
372 #address-cells = <0>;
373 #size-cells = <0>;
374 interrupt-map = <0 &UIC0 0xC 1
375 1 &UIC0 0x0D 1
376 2 &UIC0 0x0E 1
377 3 &UIC0 0x0F 1>;
378 };
379
361 }; 380 };
362 381
382
363 chosen { 383 chosen {
364 linux,stdout-path = "/plb/opb/serial@ef600200"; 384 linux,stdout-path = "/plb/opb/serial@ef600200";
365 }; 385 };
diff --git a/arch/powerpc/include/asm/ftrace.h b/arch/powerpc/include/asm/ftrace.h
index dde1296b8b41..169d039ed402 100644
--- a/arch/powerpc/include/asm/ftrace.h
+++ b/arch/powerpc/include/asm/ftrace.h
@@ -60,4 +60,18 @@ struct dyn_arch_ftrace {
60 60
61#endif 61#endif
62 62
63#if defined(CONFIG_FTRACE_SYSCALLS) && defined(CONFIG_PPC64) && !defined(__ASSEMBLY__)
64#define ARCH_HAS_SYSCALL_MATCH_SYM_NAME
65static inline bool arch_syscall_match_sym_name(const char *sym, const char *name)
66{
67 /*
68 * Compare the symbol name with the system call name. Skip the .sys or .SyS
69 * prefix from the symbol name and the sys prefix from the system call name and
70 * just match the rest. This is only needed on ppc64 since symbol names on
71 * 32bit do not start with a period so the generic function will work.
72 */
73 return !strcmp(sym + 4, name + 3);
74}
75#endif /* CONFIG_FTRACE_SYSCALLS && CONFIG_PPC64 && !__ASSEMBLY__ */
76
63#endif /* _ASM_POWERPC_FTRACE */ 77#endif /* _ASM_POWERPC_FTRACE */
diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h
index 852b8c1c09db..fd8201dddd4b 100644
--- a/arch/powerpc/include/asm/hvcall.h
+++ b/arch/powerpc/include/asm/hvcall.h
@@ -236,7 +236,7 @@
236#define H_HOME_NODE_ASSOCIATIVITY 0x2EC 236#define H_HOME_NODE_ASSOCIATIVITY 0x2EC
237#define H_BEST_ENERGY 0x2F4 237#define H_BEST_ENERGY 0x2F4
238#define H_GET_MPP_X 0x314 238#define H_GET_MPP_X 0x314
239#define MAX_HCALL_OPCODE H_BEST_ENERGY 239#define MAX_HCALL_OPCODE H_GET_MPP_X
240 240
241#ifndef __ASSEMBLY__ 241#ifndef __ASSEMBLY__
242 242
diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h
index 880b8c1e6e53..11eb404b5606 100644
--- a/arch/powerpc/include/asm/smp.h
+++ b/arch/powerpc/include/asm/smp.h
@@ -191,8 +191,6 @@ extern unsigned long __secondary_hold_spinloop;
191extern unsigned long __secondary_hold_acknowledge; 191extern unsigned long __secondary_hold_acknowledge;
192extern char __secondary_hold; 192extern char __secondary_hold;
193 193
194extern irqreturn_t debug_ipi_action(int irq, void *data);
195
196#endif /* __ASSEMBLY__ */ 194#endif /* __ASSEMBLY__ */
197 195
198#endif /* __KERNEL__ */ 196#endif /* __KERNEL__ */
diff --git a/arch/powerpc/include/asm/syscall.h b/arch/powerpc/include/asm/syscall.h
index 23913e902fc3..b54b2add07be 100644
--- a/arch/powerpc/include/asm/syscall.h
+++ b/arch/powerpc/include/asm/syscall.h
@@ -15,6 +15,11 @@
15 15
16#include <linux/sched.h> 16#include <linux/sched.h>
17 17
18/* ftrace syscalls requires exporting the sys_call_table */
19#ifdef CONFIG_FTRACE_SYSCALLS
20extern const unsigned long *sys_call_table;
21#endif /* CONFIG_FTRACE_SYSCALLS */
22
18static inline long syscall_get_nr(struct task_struct *task, 23static inline long syscall_get_nr(struct task_struct *task,
19 struct pt_regs *regs) 24 struct pt_regs *regs)
20{ 25{
diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h
index 37c353e8af7c..836f231ec1f0 100644
--- a/arch/powerpc/include/asm/thread_info.h
+++ b/arch/powerpc/include/asm/thread_info.h
@@ -110,7 +110,8 @@ static inline struct thread_info *current_thread_info(void)
110#define TIF_NOERROR 12 /* Force successful syscall return */ 110#define TIF_NOERROR 12 /* Force successful syscall return */
111#define TIF_NOTIFY_RESUME 13 /* callback before returning to user */ 111#define TIF_NOTIFY_RESUME 13 /* callback before returning to user */
112#define TIF_FREEZE 14 /* Freezing for suspend */ 112#define TIF_FREEZE 14 /* Freezing for suspend */
113#define TIF_RUNLATCH 15 /* Is the runlatch enabled? */ 113#define TIF_SYSCALL_TRACEPOINT 15 /* syscall tracepoint instrumentation */
114#define TIF_RUNLATCH 16 /* Is the runlatch enabled? */
114 115
115/* as above, but as bit values */ 116/* as above, but as bit values */
116#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) 117#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
@@ -127,8 +128,10 @@ static inline struct thread_info *current_thread_info(void)
127#define _TIF_NOERROR (1<<TIF_NOERROR) 128#define _TIF_NOERROR (1<<TIF_NOERROR)
128#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME) 129#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
129#define _TIF_FREEZE (1<<TIF_FREEZE) 130#define _TIF_FREEZE (1<<TIF_FREEZE)
131#define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT)
130#define _TIF_RUNLATCH (1<<TIF_RUNLATCH) 132#define _TIF_RUNLATCH (1<<TIF_RUNLATCH)
131#define _TIF_SYSCALL_T_OR_A (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP) 133#define _TIF_SYSCALL_T_OR_A (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
134 _TIF_SECCOMP | _TIF_SYSCALL_TRACEPOINT)
132 135
133#define _TIF_USER_WORK_MASK (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \ 136#define _TIF_USER_WORK_MASK (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
134 _TIF_NOTIFY_RESUME) 137 _TIF_NOTIFY_RESUME)
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 9aab36312572..e8b981897d44 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -109,6 +109,7 @@ obj-$(CONFIG_PPC_IO_WORKAROUNDS) += io-workarounds.o
109 109
110obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o 110obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
111obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o 111obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
112obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o
112obj-$(CONFIG_PERF_EVENTS) += perf_callchain.o 113obj-$(CONFIG_PERF_EVENTS) += perf_callchain.o
113 114
114obj-$(CONFIG_PPC_PERF_CTRS) += perf_event.o 115obj-$(CONFIG_PPC_PERF_CTRS) += perf_event.o
diff --git a/arch/powerpc/kernel/ftrace.c b/arch/powerpc/kernel/ftrace.c
index ce1f3e44c24f..bf99cfa6bbfe 100644
--- a/arch/powerpc/kernel/ftrace.c
+++ b/arch/powerpc/kernel/ftrace.c
@@ -22,6 +22,7 @@
22#include <asm/cacheflush.h> 22#include <asm/cacheflush.h>
23#include <asm/code-patching.h> 23#include <asm/code-patching.h>
24#include <asm/ftrace.h> 24#include <asm/ftrace.h>
25#include <asm/syscall.h>
25 26
26 27
27#ifdef CONFIG_DYNAMIC_FTRACE 28#ifdef CONFIG_DYNAMIC_FTRACE
@@ -600,3 +601,10 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
600 } 601 }
601} 602}
602#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 603#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
604
605#if defined(CONFIG_FTRACE_SYSCALLS) && defined(CONFIG_PPC64)
606unsigned long __init arch_syscall_addr(int nr)
607{
608 return sys_call_table[nr*2];
609}
610#endif /* CONFIG_FTRACE_SYSCALLS && CONFIG_PPC64 */
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index a24d37d4cf51..5b428e308666 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -295,17 +295,20 @@ static inline void handle_one_irq(unsigned int irq)
295 unsigned long saved_sp_limit; 295 unsigned long saved_sp_limit;
296 struct irq_desc *desc; 296 struct irq_desc *desc;
297 297
298 desc = irq_to_desc(irq);
299 if (!desc)
300 return;
301
298 /* Switch to the irq stack to handle this */ 302 /* Switch to the irq stack to handle this */
299 curtp = current_thread_info(); 303 curtp = current_thread_info();
300 irqtp = hardirq_ctx[smp_processor_id()]; 304 irqtp = hardirq_ctx[smp_processor_id()];
301 305
302 if (curtp == irqtp) { 306 if (curtp == irqtp) {
303 /* We're already on the irq stack, just handle it */ 307 /* We're already on the irq stack, just handle it */
304 generic_handle_irq(irq); 308 desc->handle_irq(irq, desc);
305 return; 309 return;
306 } 310 }
307 311
308 desc = irq_to_desc(irq);
309 saved_sp_limit = current->thread.ksp_limit; 312 saved_sp_limit = current->thread.ksp_limit;
310 313
311 irqtp->task = curtp->task; 314 irqtp->task = curtp->task;
@@ -557,15 +560,8 @@ struct irq_host *irq_alloc_host(struct device_node *of_node,
557 if (revmap_type == IRQ_HOST_MAP_LEGACY) { 560 if (revmap_type == IRQ_HOST_MAP_LEGACY) {
558 if (irq_map[0].host != NULL) { 561 if (irq_map[0].host != NULL) {
559 raw_spin_unlock_irqrestore(&irq_big_lock, flags); 562 raw_spin_unlock_irqrestore(&irq_big_lock, flags);
560 /* If we are early boot, we can't free the structure, 563 of_node_put(host->of_node);
561 * too bad... 564 kfree(host);
562 * this will be fixed once slab is made available early
563 * instead of the current cruft
564 */
565 if (mem_init_done) {
566 of_node_put(host->of_node);
567 kfree(host);
568 }
569 return NULL; 565 return NULL;
570 } 566 }
571 irq_map[0].host = host; 567 irq_map[0].host = host;
@@ -727,9 +723,7 @@ unsigned int irq_create_mapping(struct irq_host *host,
727 } 723 }
728 pr_debug("irq: -> using host @%p\n", host); 724 pr_debug("irq: -> using host @%p\n", host);
729 725
730 /* Check if mapping already exist, if it does, call 726 /* Check if mapping already exists */
731 * host->ops->map() to update the flags
732 */
733 virq = irq_find_mapping(host, hwirq); 727 virq = irq_find_mapping(host, hwirq);
734 if (virq != NO_IRQ) { 728 if (virq != NO_IRQ) {
735 pr_debug("irq: -> existing mapping on virq %d\n", virq); 729 pr_debug("irq: -> existing mapping on virq %d\n", virq);
@@ -899,10 +893,13 @@ unsigned int irq_radix_revmap_lookup(struct irq_host *host,
899 return irq_find_mapping(host, hwirq); 893 return irq_find_mapping(host, hwirq);
900 894
901 /* 895 /*
902 * No rcu_read_lock(ing) needed, the ptr returned can't go under us 896 * The ptr returned references the static global irq_map.
903 * as it's referencing an entry in the static irq_map table. 897 * but freeing an irq can delete nodes along the path to
898 * do the lookup via call_rcu.
904 */ 899 */
900 rcu_read_lock();
905 ptr = radix_tree_lookup(&host->revmap_data.tree, hwirq); 901 ptr = radix_tree_lookup(&host->revmap_data.tree, hwirq);
902 rcu_read_unlock();
906 903
907 /* 904 /*
908 * If found in radix tree, then fine. 905 * If found in radix tree, then fine.
@@ -1010,14 +1007,23 @@ void irq_free_virt(unsigned int virq, unsigned int count)
1010 WARN_ON (virq < NUM_ISA_INTERRUPTS); 1007 WARN_ON (virq < NUM_ISA_INTERRUPTS);
1011 WARN_ON (count == 0 || (virq + count) > irq_virq_count); 1008 WARN_ON (count == 0 || (virq + count) > irq_virq_count);
1012 1009
1010 if (virq < NUM_ISA_INTERRUPTS) {
1011 if (virq + count < NUM_ISA_INTERRUPTS)
1012 return;
1013 count =- NUM_ISA_INTERRUPTS - virq;
1014 virq = NUM_ISA_INTERRUPTS;
1015 }
1016
1017 if (count > irq_virq_count || virq > irq_virq_count - count) {
1018 if (virq > irq_virq_count)
1019 return;
1020 count = irq_virq_count - virq;
1021 }
1022
1013 raw_spin_lock_irqsave(&irq_big_lock, flags); 1023 raw_spin_lock_irqsave(&irq_big_lock, flags);
1014 for (i = virq; i < (virq + count); i++) { 1024 for (i = virq; i < (virq + count); i++) {
1015 struct irq_host *host; 1025 struct irq_host *host;
1016 1026
1017 if (i < NUM_ISA_INTERRUPTS ||
1018 (virq + count) > irq_virq_count)
1019 continue;
1020
1021 host = irq_map[i].host; 1027 host = irq_map[i].host;
1022 irq_map[i].hwirq = host->inval_irq; 1028 irq_map[i].hwirq = host->inval_irq;
1023 smp_wmb(); 1029 smp_wmb();
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index a6ae1cfad86c..cb22024f2b42 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -29,6 +29,7 @@
29#include <linux/signal.h> 29#include <linux/signal.h>
30#include <linux/seccomp.h> 30#include <linux/seccomp.h>
31#include <linux/audit.h> 31#include <linux/audit.h>
32#include <trace/syscall.h>
32#ifdef CONFIG_PPC32 33#ifdef CONFIG_PPC32
33#include <linux/module.h> 34#include <linux/module.h>
34#endif 35#endif
@@ -40,6 +41,9 @@
40#include <asm/pgtable.h> 41#include <asm/pgtable.h>
41#include <asm/system.h> 42#include <asm/system.h>
42 43
44#define CREATE_TRACE_POINTS
45#include <trace/events/syscalls.h>
46
43/* 47/*
44 * The parameter save area on the stack is used to store arguments being passed 48 * The parameter save area on the stack is used to store arguments being passed
45 * to callee function and is located at fixed offset from stack pointer. 49 * to callee function and is located at fixed offset from stack pointer.
@@ -1710,6 +1714,9 @@ long do_syscall_trace_enter(struct pt_regs *regs)
1710 */ 1714 */
1711 ret = -1L; 1715 ret = -1L;
1712 1716
1717 if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
1718 trace_sys_enter(regs, regs->gpr[0]);
1719
1713 if (unlikely(current->audit_context)) { 1720 if (unlikely(current->audit_context)) {
1714#ifdef CONFIG_PPC64 1721#ifdef CONFIG_PPC64
1715 if (!is_32bit_task()) 1722 if (!is_32bit_task())
@@ -1738,6 +1745,9 @@ void do_syscall_trace_leave(struct pt_regs *regs)
1738 audit_syscall_exit((regs->ccr&0x10000000)?AUDITSC_FAILURE:AUDITSC_SUCCESS, 1745 audit_syscall_exit((regs->ccr&0x10000000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
1739 regs->result); 1746 regs->result);
1740 1747
1748 if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
1749 trace_sys_exit(regs, regs->result);
1750
1741 step = test_thread_flag(TIF_SINGLESTEP); 1751 step = test_thread_flag(TIF_SINGLESTEP);
1742 if (step || test_thread_flag(TIF_SYSCALL_TRACE)) 1752 if (step || test_thread_flag(TIF_SYSCALL_TRACE))
1743 tracehook_report_syscall_exit(regs, step); 1753 tracehook_report_syscall_exit(regs, step);
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 4a6f2ec7e761..8ebc6700b98d 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -129,7 +129,7 @@ static irqreturn_t call_function_single_action(int irq, void *data)
129 return IRQ_HANDLED; 129 return IRQ_HANDLED;
130} 130}
131 131
132irqreturn_t debug_ipi_action(int irq, void *data) 132static irqreturn_t debug_ipi_action(int irq, void *data)
133{ 133{
134 if (crash_ipi_function_ptr) { 134 if (crash_ipi_function_ptr) {
135 crash_ipi_function_ptr(get_irq_regs()); 135 crash_ipi_function_ptr(get_irq_regs());
diff --git a/arch/powerpc/oprofile/op_model_power4.c b/arch/powerpc/oprofile/op_model_power4.c
index 8ee51a252cf1..e6bec74be131 100644
--- a/arch/powerpc/oprofile/op_model_power4.c
+++ b/arch/powerpc/oprofile/op_model_power4.c
@@ -261,6 +261,28 @@ static int get_kernel(unsigned long pc, unsigned long mmcra)
261 return is_kernel; 261 return is_kernel;
262} 262}
263 263
264static bool pmc_overflow(unsigned long val)
265{
266 if ((int)val < 0)
267 return true;
268
269 /*
270 * Events on POWER7 can roll back if a speculative event doesn't
271 * eventually complete. Unfortunately in some rare cases they will
272 * raise a performance monitor exception. We need to catch this to
273 * ensure we reset the PMC. In all cases the PMC will be 256 or less
274 * cycles from overflow.
275 *
276 * We only do this if the first pass fails to find any overflowing
277 * PMCs because a user might set a period of less than 256 and we
278 * don't want to mistakenly reset them.
279 */
280 if (__is_processor(PV_POWER7) && ((0x80000000 - val) <= 256))
281 return true;
282
283 return false;
284}
285
264static void power4_handle_interrupt(struct pt_regs *regs, 286static void power4_handle_interrupt(struct pt_regs *regs,
265 struct op_counter_config *ctr) 287 struct op_counter_config *ctr)
266{ 288{
@@ -281,7 +303,7 @@ static void power4_handle_interrupt(struct pt_regs *regs,
281 303
282 for (i = 0; i < cur_cpu_spec->num_pmcs; ++i) { 304 for (i = 0; i < cur_cpu_spec->num_pmcs; ++i) {
283 val = classic_ctr_read(i); 305 val = classic_ctr_read(i);
284 if (val < 0) { 306 if (pmc_overflow(val)) {
285 if (oprofile_running && ctr[i].enabled) { 307 if (oprofile_running && ctr[i].enabled) {
286 oprofile_add_ext_sample(pc, regs, i, is_kernel); 308 oprofile_add_ext_sample(pc, regs, i, is_kernel);
287 classic_ctr_write(i, reset_value[i]); 309 classic_ctr_write(i, reset_value[i]);
diff --git a/arch/powerpc/platforms/40x/Kconfig b/arch/powerpc/platforms/40x/Kconfig
index b72176434ebe..d733d7ca939c 100644
--- a/arch/powerpc/platforms/40x/Kconfig
+++ b/arch/powerpc/platforms/40x/Kconfig
@@ -57,6 +57,8 @@ config KILAUEA
57 select 405EX 57 select 405EX
58 select PPC40x_SIMPLE 58 select PPC40x_SIMPLE
59 select PPC4xx_PCI_EXPRESS 59 select PPC4xx_PCI_EXPRESS
60 select PCI_MSI
61 select PPC4xx_MSI
60 help 62 help
61 This option enables support for the AMCC PPC405EX evaluation board. 63 This option enables support for the AMCC PPC405EX evaluation board.
62 64
diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig
index f485fc5f6d5e..e958b6f48ec2 100644
--- a/arch/powerpc/platforms/44x/Kconfig
+++ b/arch/powerpc/platforms/44x/Kconfig
@@ -74,6 +74,8 @@ config KATMAI
74 select 440SPe 74 select 440SPe
75 select PCI 75 select PCI
76 select PPC4xx_PCI_EXPRESS 76 select PPC4xx_PCI_EXPRESS
77 select PCI_MSI
78 select PCC4xx_MSI
77 help 79 help
78 This option enables support for the AMCC PPC440SPe evaluation board. 80 This option enables support for the AMCC PPC440SPe evaluation board.
79 81
@@ -118,6 +120,8 @@ config CANYONLANDS
118 select 460EX 120 select 460EX
119 select PCI 121 select PCI
120 select PPC4xx_PCI_EXPRESS 122 select PPC4xx_PCI_EXPRESS
123 select PCI_MSI
124 select PPC4xx_MSI
121 select IBM_NEW_EMAC_RGMII 125 select IBM_NEW_EMAC_RGMII
122 select IBM_NEW_EMAC_ZMII 126 select IBM_NEW_EMAC_ZMII
123 help 127 help
@@ -144,6 +148,8 @@ config REDWOOD
144 select 460SX 148 select 460SX
145 select PCI 149 select PCI
146 select PPC4xx_PCI_EXPRESS 150 select PPC4xx_PCI_EXPRESS
151 select PCI_MSI
152 select PPC4xx_MSI
147 help 153 help
148 This option enables support for the AMCC PPC460SX Redwood board. 154 This option enables support for the AMCC PPC460SX Redwood board.
149 155
diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c
index 449c08c15862..3e4eba603e6b 100644
--- a/arch/powerpc/platforms/cell/interrupt.c
+++ b/arch/powerpc/platforms/cell/interrupt.c
@@ -176,14 +176,14 @@ EXPORT_SYMBOL_GPL(iic_get_target_id);
176#ifdef CONFIG_SMP 176#ifdef CONFIG_SMP
177 177
178/* Use the highest interrupt priorities for IPI */ 178/* Use the highest interrupt priorities for IPI */
179static inline int iic_ipi_to_irq(int ipi) 179static inline int iic_msg_to_irq(int msg)
180{ 180{
181 return IIC_IRQ_TYPE_IPI + 0xf - ipi; 181 return IIC_IRQ_TYPE_IPI + 0xf - msg;
182} 182}
183 183
184void iic_cause_IPI(int cpu, int mesg) 184void iic_message_pass(int cpu, int msg)
185{ 185{
186 out_be64(&per_cpu(cpu_iic, cpu).regs->generate, (0xf - mesg) << 4); 186 out_be64(&per_cpu(cpu_iic, cpu).regs->generate, (0xf - msg) << 4);
187} 187}
188 188
189struct irq_host *iic_get_irq_host(int node) 189struct irq_host *iic_get_irq_host(int node)
@@ -192,50 +192,31 @@ struct irq_host *iic_get_irq_host(int node)
192} 192}
193EXPORT_SYMBOL_GPL(iic_get_irq_host); 193EXPORT_SYMBOL_GPL(iic_get_irq_host);
194 194
195static irqreturn_t iic_ipi_action(int irq, void *dev_id) 195static void iic_request_ipi(int msg)
196{
197 int ipi = (int)(long)dev_id;
198
199 switch(ipi) {
200 case PPC_MSG_CALL_FUNCTION:
201 generic_smp_call_function_interrupt();
202 break;
203 case PPC_MSG_RESCHEDULE:
204 scheduler_ipi();
205 break;
206 case PPC_MSG_CALL_FUNC_SINGLE:
207 generic_smp_call_function_single_interrupt();
208 break;
209 case PPC_MSG_DEBUGGER_BREAK:
210 debug_ipi_action(0, NULL);
211 break;
212 }
213 return IRQ_HANDLED;
214}
215static void iic_request_ipi(int ipi, const char *name)
216{ 196{
217 int virq; 197 int virq;
218 198
219 virq = irq_create_mapping(iic_host, iic_ipi_to_irq(ipi)); 199 virq = irq_create_mapping(iic_host, iic_msg_to_irq(msg));
220 if (virq == NO_IRQ) { 200 if (virq == NO_IRQ) {
221 printk(KERN_ERR 201 printk(KERN_ERR
222 "iic: failed to map IPI %s\n", name); 202 "iic: failed to map IPI %s\n", smp_ipi_name[msg]);
223 return; 203 return;
224 } 204 }
225 if (request_irq(virq, iic_ipi_action, IRQF_DISABLED, name, 205
226 (void *)(long)ipi)) 206 /*
227 printk(KERN_ERR 207 * If smp_request_message_ipi encounters an error it will notify
228 "iic: failed to request IPI %s\n", name); 208 * the error. If a message is not needed it will return non-zero.
209 */
210 if (smp_request_message_ipi(virq, msg))
211 irq_dispose_mapping(virq);
229} 212}
230 213
231void iic_request_IPIs(void) 214void iic_request_IPIs(void)
232{ 215{
233 iic_request_ipi(PPC_MSG_CALL_FUNCTION, "IPI-call"); 216 iic_request_ipi(PPC_MSG_CALL_FUNCTION);
234 iic_request_ipi(PPC_MSG_RESCHEDULE, "IPI-resched"); 217 iic_request_ipi(PPC_MSG_RESCHEDULE);
235 iic_request_ipi(PPC_MSG_CALL_FUNC_SINGLE, "IPI-call-single"); 218 iic_request_ipi(PPC_MSG_CALL_FUNC_SINGLE);
236#ifdef CONFIG_DEBUGGER 219 iic_request_ipi(PPC_MSG_DEBUGGER_BREAK);
237 iic_request_ipi(PPC_MSG_DEBUGGER_BREAK, "IPI-debug");
238#endif /* CONFIG_DEBUGGER */
239} 220}
240 221
241#endif /* CONFIG_SMP */ 222#endif /* CONFIG_SMP */
diff --git a/arch/powerpc/platforms/cell/interrupt.h b/arch/powerpc/platforms/cell/interrupt.h
index 942dc39d6045..4f60ae6ca358 100644
--- a/arch/powerpc/platforms/cell/interrupt.h
+++ b/arch/powerpc/platforms/cell/interrupt.h
@@ -75,7 +75,7 @@ enum {
75}; 75};
76 76
77extern void iic_init_IRQ(void); 77extern void iic_init_IRQ(void);
78extern void iic_cause_IPI(int cpu, int mesg); 78extern void iic_message_pass(int cpu, int msg);
79extern void iic_request_IPIs(void); 79extern void iic_request_IPIs(void);
80extern void iic_setup_cpu(void); 80extern void iic_setup_cpu(void);
81 81
diff --git a/arch/powerpc/platforms/cell/smp.c b/arch/powerpc/platforms/cell/smp.c
index d176e6148e3f..dbb641ea90dd 100644
--- a/arch/powerpc/platforms/cell/smp.c
+++ b/arch/powerpc/platforms/cell/smp.c
@@ -152,7 +152,7 @@ static int smp_cell_cpu_bootable(unsigned int nr)
152 return 1; 152 return 1;
153} 153}
154static struct smp_ops_t bpa_iic_smp_ops = { 154static struct smp_ops_t bpa_iic_smp_ops = {
155 .message_pass = iic_cause_IPI, 155 .message_pass = iic_message_pass,
156 .probe = smp_iic_probe, 156 .probe = smp_iic_probe,
157 .kick_cpu = smp_cell_kick_cpu, 157 .kick_cpu = smp_cell_kick_cpu,
158 .setup_cpu = smp_cell_setup_cpu, 158 .setup_cpu = smp_cell_setup_cpu,
diff --git a/arch/powerpc/sysdev/Kconfig b/arch/powerpc/sysdev/Kconfig
index d775fd148d13..7b4df37ac381 100644
--- a/arch/powerpc/sysdev/Kconfig
+++ b/arch/powerpc/sysdev/Kconfig
@@ -7,11 +7,18 @@ config PPC4xx_PCI_EXPRESS
7 depends on PCI && 4xx 7 depends on PCI && 4xx
8 default n 8 default n
9 9
10config PPC4xx_MSI
11 bool
12 depends on PCI_MSI
13 depends on PCI && 4xx
14 default n
15
10config PPC_MSI_BITMAP 16config PPC_MSI_BITMAP
11 bool 17 bool
12 depends on PCI_MSI 18 depends on PCI_MSI
13 default y if MPIC 19 default y if MPIC
14 default y if FSL_PCI 20 default y if FSL_PCI
21 default y if PPC4xx_MSI
15 22
16source "arch/powerpc/sysdev/xics/Kconfig" 23source "arch/powerpc/sysdev/xics/Kconfig"
17 24
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 6076e0074a87..0efa990e3344 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -41,6 +41,7 @@ obj-$(CONFIG_OF_RTC) += of_rtc.o
41ifeq ($(CONFIG_PCI),y) 41ifeq ($(CONFIG_PCI),y)
42obj-$(CONFIG_4xx) += ppc4xx_pci.o 42obj-$(CONFIG_4xx) += ppc4xx_pci.o
43endif 43endif
44obj-$(CONFIG_PPC4xx_MSI) += ppc4xx_msi.o
44obj-$(CONFIG_PPC4xx_CPM) += ppc4xx_cpm.o 45obj-$(CONFIG_PPC4xx_CPM) += ppc4xx_cpm.o
45obj-$(CONFIG_PPC4xx_GPIO) += ppc4xx_gpio.o 46obj-$(CONFIG_PPC4xx_GPIO) += ppc4xx_gpio.o
46 47
diff --git a/arch/powerpc/sysdev/ppc4xx_msi.c b/arch/powerpc/sysdev/ppc4xx_msi.c
new file mode 100644
index 000000000000..367af0241851
--- /dev/null
+++ b/arch/powerpc/sysdev/ppc4xx_msi.c
@@ -0,0 +1,276 @@
1/*
2 * Adding PCI-E MSI support for PPC4XX SoCs.
3 *
4 * Copyright (c) 2010, Applied Micro Circuits Corporation
5 * Authors: Tirumala R Marri <tmarri@apm.com>
6 * Feng Kan <fkan@apm.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 * MA 02111-1307 USA
22 */
23
24#include <linux/irq.h>
25#include <linux/bootmem.h>
26#include <linux/pci.h>
27#include <linux/msi.h>
28#include <linux/of_platform.h>
29#include <linux/interrupt.h>
30#include <asm/prom.h>
31#include <asm/hw_irq.h>
32#include <asm/ppc-pci.h>
33#include <boot/dcr.h>
34#include <asm/dcr-regs.h>
35#include <asm/msi_bitmap.h>
36
37#define PEIH_TERMADH 0x00
38#define PEIH_TERMADL 0x08
39#define PEIH_MSIED 0x10
40#define PEIH_MSIMK 0x18
41#define PEIH_MSIASS 0x20
42#define PEIH_FLUSH0 0x30
43#define PEIH_FLUSH1 0x38
44#define PEIH_CNTRST 0x48
45#define NR_MSI_IRQS 4
46
47struct ppc4xx_msi {
48 u32 msi_addr_lo;
49 u32 msi_addr_hi;
50 void __iomem *msi_regs;
51 int msi_virqs[NR_MSI_IRQS];
52 struct msi_bitmap bitmap;
53 struct device_node *msi_dev;
54};
55
56static struct ppc4xx_msi ppc4xx_msi;
57
58static int ppc4xx_msi_init_allocator(struct platform_device *dev,
59 struct ppc4xx_msi *msi_data)
60{
61 int err;
62
63 err = msi_bitmap_alloc(&msi_data->bitmap, NR_MSI_IRQS,
64 dev->dev.of_node);
65 if (err)
66 return err;
67
68 err = msi_bitmap_reserve_dt_hwirqs(&msi_data->bitmap);
69 if (err < 0) {
70 msi_bitmap_free(&msi_data->bitmap);
71 return err;
72 }
73
74 return 0;
75}
76
77static int ppc4xx_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
78{
79 int int_no = -ENOMEM;
80 unsigned int virq;
81 struct msi_msg msg;
82 struct msi_desc *entry;
83 struct ppc4xx_msi *msi_data = &ppc4xx_msi;
84
85 list_for_each_entry(entry, &dev->msi_list, list) {
86 int_no = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1);
87 if (int_no >= 0)
88 break;
89 if (int_no < 0) {
90 pr_debug("%s: fail allocating msi interrupt\n",
91 __func__);
92 }
93 virq = irq_of_parse_and_map(msi_data->msi_dev, int_no);
94 if (virq == NO_IRQ) {
95 dev_err(&dev->dev, "%s: fail mapping irq\n", __func__);
96 msi_bitmap_free_hwirqs(&msi_data->bitmap, int_no, 1);
97 return -ENOSPC;
98 }
99 dev_dbg(&dev->dev, "%s: virq = %d\n", __func__, virq);
100
101 /* Setup msi address space */
102 msg.address_hi = msi_data->msi_addr_hi;
103 msg.address_lo = msi_data->msi_addr_lo;
104
105 irq_set_msi_desc(virq, entry);
106 msg.data = int_no;
107 write_msi_msg(virq, &msg);
108 }
109 return 0;
110}
111
112void ppc4xx_teardown_msi_irqs(struct pci_dev *dev)
113{
114 struct msi_desc *entry;
115 struct ppc4xx_msi *msi_data = &ppc4xx_msi;
116
117 dev_dbg(&dev->dev, "PCIE-MSI: tearing down msi irqs\n");
118
119 list_for_each_entry(entry, &dev->msi_list, list) {
120 if (entry->irq == NO_IRQ)
121 continue;
122 irq_set_msi_desc(entry->irq, NULL);
123 msi_bitmap_free_hwirqs(&msi_data->bitmap,
124 virq_to_hw(entry->irq), 1);
125 irq_dispose_mapping(entry->irq);
126 }
127}
128
129static int ppc4xx_msi_check_device(struct pci_dev *pdev, int nvec, int type)
130{
131 dev_dbg(&pdev->dev, "PCIE-MSI:%s called. vec %x type %d\n",
132 __func__, nvec, type);
133 if (type == PCI_CAP_ID_MSIX)
134 pr_debug("ppc4xx msi: MSI-X untested, trying anyway.\n");
135
136 return 0;
137}
138
139static int ppc4xx_setup_pcieh_hw(struct platform_device *dev,
140 struct resource res, struct ppc4xx_msi *msi)
141{
142 const u32 *msi_data;
143 const u32 *msi_mask;
144 const u32 *sdr_addr;
145 dma_addr_t msi_phys;
146 void *msi_virt;
147
148 sdr_addr = of_get_property(dev->dev.of_node, "sdr-base", NULL);
149 if (!sdr_addr)
150 return -1;
151
152 SDR0_WRITE(sdr_addr, (u64)res.start >> 32); /*HIGH addr */
153 SDR0_WRITE(sdr_addr + 1, res.start & 0xFFFFFFFF); /* Low addr */
154
155
156 msi->msi_dev = of_find_node_by_name(NULL, "ppc4xx-msi");
157 if (msi->msi_dev)
158 return -ENODEV;
159
160 msi->msi_regs = of_iomap(msi->msi_dev, 0);
161 if (!msi->msi_regs) {
162 dev_err(&dev->dev, "of_iomap problem failed\n");
163 return -ENOMEM;
164 }
165 dev_dbg(&dev->dev, "PCIE-MSI: msi register mapped 0x%x 0x%x\n",
166 (u32) (msi->msi_regs + PEIH_TERMADH), (u32) (msi->msi_regs));
167
168 msi_virt = dma_alloc_coherent(&dev->dev, 64, &msi_phys, GFP_KERNEL);
169 msi->msi_addr_hi = 0x0;
170 msi->msi_addr_lo = (u32) msi_phys;
171 dev_dbg(&dev->dev, "PCIE-MSI: msi address 0x%x\n", msi->msi_addr_lo);
172
173 /* Progam the Interrupt handler Termination addr registers */
174 out_be32(msi->msi_regs + PEIH_TERMADH, msi->msi_addr_hi);
175 out_be32(msi->msi_regs + PEIH_TERMADL, msi->msi_addr_lo);
176
177 msi_data = of_get_property(dev->dev.of_node, "msi-data", NULL);
178 if (!msi_data)
179 return -1;
180 msi_mask = of_get_property(dev->dev.of_node, "msi-mask", NULL);
181 if (!msi_mask)
182 return -1;
183 /* Program MSI Expected data and Mask bits */
184 out_be32(msi->msi_regs + PEIH_MSIED, *msi_data);
185 out_be32(msi->msi_regs + PEIH_MSIMK, *msi_mask);
186
187 return 0;
188}
189
190static int ppc4xx_of_msi_remove(struct platform_device *dev)
191{
192 struct ppc4xx_msi *msi = dev->dev.platform_data;
193 int i;
194 int virq;
195
196 for (i = 0; i < NR_MSI_IRQS; i++) {
197 virq = msi->msi_virqs[i];
198 if (virq != NO_IRQ)
199 irq_dispose_mapping(virq);
200 }
201
202 if (msi->bitmap.bitmap)
203 msi_bitmap_free(&msi->bitmap);
204 iounmap(msi->msi_regs);
205 of_node_put(msi->msi_dev);
206 kfree(msi);
207
208 return 0;
209}
210
211static int __devinit ppc4xx_msi_probe(struct platform_device *dev)
212{
213 struct ppc4xx_msi *msi;
214 struct resource res;
215 int err = 0;
216
217 msi = &ppc4xx_msi;/*keep the msi data for further use*/
218
219 dev_dbg(&dev->dev, "PCIE-MSI: Setting up MSI support...\n");
220
221 msi = kzalloc(sizeof(struct ppc4xx_msi), GFP_KERNEL);
222 if (!msi) {
223 dev_err(&dev->dev, "No memory for MSI structure\n");
224 return -ENOMEM;
225 }
226 dev->dev.platform_data = msi;
227
228 /* Get MSI ranges */
229 err = of_address_to_resource(dev->dev.of_node, 0, &res);
230 if (err) {
231 dev_err(&dev->dev, "%s resource error!\n",
232 dev->dev.of_node->full_name);
233 goto error_out;
234 }
235
236 if (ppc4xx_setup_pcieh_hw(dev, res, msi))
237 goto error_out;
238
239 err = ppc4xx_msi_init_allocator(dev, msi);
240 if (err) {
241 dev_err(&dev->dev, "Error allocating MSI bitmap\n");
242 goto error_out;
243 }
244
245 ppc_md.setup_msi_irqs = ppc4xx_setup_msi_irqs;
246 ppc_md.teardown_msi_irqs = ppc4xx_teardown_msi_irqs;
247 ppc_md.msi_check_device = ppc4xx_msi_check_device;
248 return err;
249
250error_out:
251 ppc4xx_of_msi_remove(dev);
252 return err;
253}
254static const struct of_device_id ppc4xx_msi_ids[] = {
255 {
256 .compatible = "amcc,ppc4xx-msi",
257 },
258 {}
259};
260static struct platform_driver ppc4xx_msi_driver = {
261 .probe = ppc4xx_msi_probe,
262 .remove = ppc4xx_of_msi_remove,
263 .driver = {
264 .name = "ppc4xx-msi",
265 .owner = THIS_MODULE,
266 .of_match_table = ppc4xx_msi_ids,
267 },
268
269};
270
271static __init int ppc4xx_msi_init(void)
272{
273 return platform_driver_register(&ppc4xx_msi_driver);
274}
275
276subsys_initcall(ppc4xx_msi_init);
diff --git a/include/linux/smp.h b/include/linux/smp.h
index 74243c86ba39..7ad824d510a2 100644
--- a/include/linux/smp.h
+++ b/include/linux/smp.h
@@ -98,16 +98,6 @@ void ipi_call_unlock_irq(void);
98 */ 98 */
99int on_each_cpu(smp_call_func_t func, void *info, int wait); 99int on_each_cpu(smp_call_func_t func, void *info, int wait);
100 100
101#define MSG_ALL_BUT_SELF 0x8000 /* Assume <32768 CPU's */
102#define MSG_ALL 0x8001
103
104#define MSG_INVALIDATE_TLB 0x0001 /* Remote processor TLB invalidate */
105#define MSG_STOP_CPU 0x0002 /* Sent to shut down slave CPU's
106 * when rebooting
107 */
108#define MSG_RESCHEDULE 0x0003 /* Reschedule request from master CPU*/
109#define MSG_CALL_FUNCTION 0x0004 /* Call function on all other CPUs */
110
111/* 101/*
112 * Mark the boot cpu "online" so that it can call console drivers in 102 * Mark the boot cpu "online" so that it can call console drivers in
113 * printk() and can access its per-cpu storage. 103 * printk() and can access its per-cpu storage.