diff options
author | Jens Axboe <jens.axboe@oracle.com> | 2008-06-10 14:49:30 -0400 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2008-06-26 05:22:57 -0400 |
commit | 7b7426c8a615cf61df9a77b9df7d5b75d91e3fa0 (patch) | |
tree | e54ae91c30d44d427d0e8d82d04724d66ddae834 | |
parent | f6dd9fa5a75a3dae16c6843e74e56bf75be51c7c (diff) |
m32r: convert to generic helpers for IPI function calls
This converts m32r to use the new helpers for smp_call_function() and
friends, and adds support for smp_call_function_single(). Not tested,
not even compiled.
Cc: Hirokazu Takata <takata@linux-m32r.org>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
-rw-r--r-- | arch/m32r/Kconfig | 1 | ||||
-rw-r--r-- | arch/m32r/kernel/m32r_ksyms.c | 3 | ||||
-rw-r--r-- | arch/m32r/kernel/smp.c | 128 | ||||
-rw-r--r-- | arch/m32r/kernel/traps.c | 3 | ||||
-rw-r--r-- | include/asm-m32r/smp.h | 4 |
5 files changed, 20 insertions, 119 deletions
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig index de153de2ea9f..a5f864c445b2 100644 --- a/arch/m32r/Kconfig +++ b/arch/m32r/Kconfig | |||
@@ -296,6 +296,7 @@ config PREEMPT | |||
296 | 296 | ||
297 | config SMP | 297 | config SMP |
298 | bool "Symmetric multi-processing support" | 298 | bool "Symmetric multi-processing support" |
299 | select USE_GENERIC_SMP_HELPERS | ||
299 | ---help--- | 300 | ---help--- |
300 | This enables support for systems with more than one CPU. If you have | 301 | This enables support for systems with more than one CPU. If you have |
301 | a system with only one CPU, like most personal computers, say N. If | 302 | a system with only one CPU, like most personal computers, say N. If |
diff --git a/arch/m32r/kernel/m32r_ksyms.c b/arch/m32r/kernel/m32r_ksyms.c index e6709fe950ba..16bcb189a383 100644 --- a/arch/m32r/kernel/m32r_ksyms.c +++ b/arch/m32r/kernel/m32r_ksyms.c | |||
@@ -43,9 +43,6 @@ EXPORT_SYMBOL(dcache_dummy); | |||
43 | #endif | 43 | #endif |
44 | EXPORT_SYMBOL(cpu_data); | 44 | EXPORT_SYMBOL(cpu_data); |
45 | 45 | ||
46 | /* Global SMP stuff */ | ||
47 | EXPORT_SYMBOL(smp_call_function); | ||
48 | |||
49 | /* TLB flushing */ | 46 | /* TLB flushing */ |
50 | EXPORT_SYMBOL(smp_flush_tlb_page); | 47 | EXPORT_SYMBOL(smp_flush_tlb_page); |
51 | #endif | 48 | #endif |
diff --git a/arch/m32r/kernel/smp.c b/arch/m32r/kernel/smp.c index c837bc13b015..74eb7bcd5a40 100644 --- a/arch/m32r/kernel/smp.c +++ b/arch/m32r/kernel/smp.c | |||
@@ -35,22 +35,6 @@ | |||
35 | /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ | 35 | /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ |
36 | 36 | ||
37 | /* | 37 | /* |
38 | * Structure and data for smp_call_function(). This is designed to minimise | ||
39 | * static memory requirements. It also looks cleaner. | ||
40 | */ | ||
41 | static DEFINE_SPINLOCK(call_lock); | ||
42 | |||
43 | struct call_data_struct { | ||
44 | void (*func) (void *info); | ||
45 | void *info; | ||
46 | atomic_t started; | ||
47 | atomic_t finished; | ||
48 | int wait; | ||
49 | } __attribute__ ((__aligned__(SMP_CACHE_BYTES))); | ||
50 | |||
51 | static struct call_data_struct *call_data; | ||
52 | |||
53 | /* | ||
54 | * For flush_cache_all() | 38 | * For flush_cache_all() |
55 | */ | 39 | */ |
56 | static DEFINE_SPINLOCK(flushcache_lock); | 40 | static DEFINE_SPINLOCK(flushcache_lock); |
@@ -96,9 +80,6 @@ void smp_invalidate_interrupt(void); | |||
96 | void smp_send_stop(void); | 80 | void smp_send_stop(void); |
97 | static void stop_this_cpu(void *); | 81 | static void stop_this_cpu(void *); |
98 | 82 | ||
99 | int smp_call_function(void (*) (void *), void *, int, int); | ||
100 | void smp_call_function_interrupt(void); | ||
101 | |||
102 | void smp_send_timer(void); | 83 | void smp_send_timer(void); |
103 | void smp_ipi_timer_interrupt(struct pt_regs *); | 84 | void smp_ipi_timer_interrupt(struct pt_regs *); |
104 | void smp_local_timer_interrupt(void); | 85 | void smp_local_timer_interrupt(void); |
@@ -565,86 +546,14 @@ static void stop_this_cpu(void *dummy) | |||
565 | for ( ; ; ); | 546 | for ( ; ; ); |
566 | } | 547 | } |
567 | 548 | ||
568 | /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ | 549 | void arch_send_call_function_ipi(cpumask_t mask) |
569 | /* Call function Routines */ | ||
570 | /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ | ||
571 | |||
572 | /*==========================================================================* | ||
573 | * Name: smp_call_function | ||
574 | * | ||
575 | * Description: This routine sends a 'CALL_FUNCTION_IPI' to all other CPUs | ||
576 | * in the system. | ||
577 | * | ||
578 | * Born on Date: 2002.02.05 | ||
579 | * | ||
580 | * Arguments: *func - The function to run. This must be fast and | ||
581 | * non-blocking. | ||
582 | * *info - An arbitrary pointer to pass to the function. | ||
583 | * nonatomic - currently unused. | ||
584 | * wait - If true, wait (atomically) until function has | ||
585 | * completed on other CPUs. | ||
586 | * | ||
587 | * Returns: 0 on success, else a negative status code. Does not return | ||
588 | * until remote CPUs are nearly ready to execute <<func>> or | ||
589 | * are or have executed. | ||
590 | * | ||
591 | * Cautions: You must not call this function with disabled interrupts or | ||
592 | * from a hardware interrupt handler, you may call it from a | ||
593 | * bottom half handler. | ||
594 | * | ||
595 | * Modification log: | ||
596 | * Date Who Description | ||
597 | * ---------- --- -------------------------------------------------------- | ||
598 | * | ||
599 | *==========================================================================*/ | ||
600 | int smp_call_function(void (*func) (void *info), void *info, int nonatomic, | ||
601 | int wait) | ||
602 | { | 550 | { |
603 | struct call_data_struct data; | 551 | send_IPI_mask(mask, CALL_FUNCTION_IPI, 0); |
604 | int cpus; | 552 | } |
605 | |||
606 | #ifdef DEBUG_SMP | ||
607 | unsigned long flags; | ||
608 | __save_flags(flags); | ||
609 | if (!(flags & 0x0040)) /* Interrupt Disable NONONO */ | ||
610 | BUG(); | ||
611 | #endif /* DEBUG_SMP */ | ||
612 | |||
613 | /* Holding any lock stops cpus from going down. */ | ||
614 | spin_lock(&call_lock); | ||
615 | cpus = num_online_cpus() - 1; | ||
616 | |||
617 | if (!cpus) { | ||
618 | spin_unlock(&call_lock); | ||
619 | return 0; | ||
620 | } | ||
621 | |||
622 | /* Can deadlock when called with interrupts disabled */ | ||
623 | WARN_ON(irqs_disabled()); | ||
624 | |||
625 | data.func = func; | ||
626 | data.info = info; | ||
627 | atomic_set(&data.started, 0); | ||
628 | data.wait = wait; | ||
629 | if (wait) | ||
630 | atomic_set(&data.finished, 0); | ||
631 | |||
632 | call_data = &data; | ||
633 | mb(); | ||
634 | |||
635 | /* Send a message to all other CPUs and wait for them to respond */ | ||
636 | send_IPI_allbutself(CALL_FUNCTION_IPI, 0); | ||
637 | |||
638 | /* Wait for response */ | ||
639 | while (atomic_read(&data.started) != cpus) | ||
640 | barrier(); | ||
641 | |||
642 | if (wait) | ||
643 | while (atomic_read(&data.finished) != cpus) | ||
644 | barrier(); | ||
645 | spin_unlock(&call_lock); | ||
646 | 553 | ||
647 | return 0; | 554 | void arch_send_call_function_single_ipi(int cpu) |
555 | { | ||
556 | send_IPI_mask(cpumask_of_cpu(cpu), CALL_FUNC_SINGLE_IPI, 0); | ||
648 | } | 557 | } |
649 | 558 | ||
650 | /*==========================================================================* | 559 | /*==========================================================================* |
@@ -666,27 +575,16 @@ int smp_call_function(void (*func) (void *info), void *info, int nonatomic, | |||
666 | *==========================================================================*/ | 575 | *==========================================================================*/ |
667 | void smp_call_function_interrupt(void) | 576 | void smp_call_function_interrupt(void) |
668 | { | 577 | { |
669 | void (*func) (void *info) = call_data->func; | ||
670 | void *info = call_data->info; | ||
671 | int wait = call_data->wait; | ||
672 | |||
673 | /* | ||
674 | * Notify initiating CPU that I've grabbed the data and am | ||
675 | * about to execute the function | ||
676 | */ | ||
677 | mb(); | ||
678 | atomic_inc(&call_data->started); | ||
679 | /* | ||
680 | * At this point the info structure may be out of scope unless wait==1 | ||
681 | */ | ||
682 | irq_enter(); | 578 | irq_enter(); |
683 | (*func)(info); | 579 | generic_smp_call_function_interrupt(); |
684 | irq_exit(); | 580 | irq_exit(); |
581 | } | ||
685 | 582 | ||
686 | if (wait) { | 583 | void smp_call_function_single_interrupt(void) |
687 | mb(); | 584 | { |
688 | atomic_inc(&call_data->finished); | 585 | irq_enter(); |
689 | } | 586 | generic_smp_call_function_single_interrupt(); |
587 | irq_exit(); | ||
690 | } | 588 | } |
691 | 589 | ||
692 | /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ | 590 | /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/ |
diff --git a/arch/m32r/kernel/traps.c b/arch/m32r/kernel/traps.c index 89ba4a0b5d51..46159a4e644b 100644 --- a/arch/m32r/kernel/traps.c +++ b/arch/m32r/kernel/traps.c | |||
@@ -40,6 +40,7 @@ extern void smp_invalidate_interrupt(void); | |||
40 | extern void smp_call_function_interrupt(void); | 40 | extern void smp_call_function_interrupt(void); |
41 | extern void smp_ipi_timer_interrupt(void); | 41 | extern void smp_ipi_timer_interrupt(void); |
42 | extern void smp_flush_cache_all_interrupt(void); | 42 | extern void smp_flush_cache_all_interrupt(void); |
43 | extern void smp_call_function_single_interrupt(void); | ||
43 | 44 | ||
44 | /* | 45 | /* |
45 | * for Boot AP function | 46 | * for Boot AP function |
@@ -103,7 +104,7 @@ void set_eit_vector_entries(void) | |||
103 | eit_vector[186] = (unsigned long)smp_call_function_interrupt; | 104 | eit_vector[186] = (unsigned long)smp_call_function_interrupt; |
104 | eit_vector[187] = (unsigned long)smp_ipi_timer_interrupt; | 105 | eit_vector[187] = (unsigned long)smp_ipi_timer_interrupt; |
105 | eit_vector[188] = (unsigned long)smp_flush_cache_all_interrupt; | 106 | eit_vector[188] = (unsigned long)smp_flush_cache_all_interrupt; |
106 | eit_vector[189] = 0; | 107 | eit_vector[189] = (unsigned long)smp_call_function_single_interrupt; |
107 | eit_vector[190] = 0; | 108 | eit_vector[190] = 0; |
108 | eit_vector[191] = 0; | 109 | eit_vector[191] = 0; |
109 | #endif | 110 | #endif |
diff --git a/include/asm-m32r/smp.h b/include/asm-m32r/smp.h index 078e1a51a042..c5dd66916692 100644 --- a/include/asm-m32r/smp.h +++ b/include/asm-m32r/smp.h | |||
@@ -89,6 +89,9 @@ static __inline__ unsigned int num_booting_cpus(void) | |||
89 | extern void smp_send_timer(void); | 89 | extern void smp_send_timer(void); |
90 | extern unsigned long send_IPI_mask_phys(cpumask_t, int, int); | 90 | extern unsigned long send_IPI_mask_phys(cpumask_t, int, int); |
91 | 91 | ||
92 | extern void arch_send_call_function_single_ipi(int cpu); | ||
93 | extern void arch_send_call_function_ipi(cpumask_t mask); | ||
94 | |||
92 | #endif /* not __ASSEMBLY__ */ | 95 | #endif /* not __ASSEMBLY__ */ |
93 | 96 | ||
94 | #define NO_PROC_ID (0xff) /* No processor magic marker */ | 97 | #define NO_PROC_ID (0xff) /* No processor magic marker */ |
@@ -104,6 +107,7 @@ extern unsigned long send_IPI_mask_phys(cpumask_t, int, int); | |||
104 | #define LOCAL_TIMER_IPI (M32R_IRQ_IPI3-M32R_IRQ_IPI0) | 107 | #define LOCAL_TIMER_IPI (M32R_IRQ_IPI3-M32R_IRQ_IPI0) |
105 | #define INVALIDATE_CACHE_IPI (M32R_IRQ_IPI4-M32R_IRQ_IPI0) | 108 | #define INVALIDATE_CACHE_IPI (M32R_IRQ_IPI4-M32R_IRQ_IPI0) |
106 | #define CPU_BOOT_IPI (M32R_IRQ_IPI5-M32R_IRQ_IPI0) | 109 | #define CPU_BOOT_IPI (M32R_IRQ_IPI5-M32R_IRQ_IPI0) |
110 | #define CALL_FUNC_SINGLE_IPI (M32R_IRQ_IPI6-M32R_IRQ_IPI0) | ||
107 | 111 | ||
108 | #define IPI_SHIFT (0) | 112 | #define IPI_SHIFT (0) |
109 | #define NR_IPIS (8) | 113 | #define NR_IPIS (8) |