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) |
