2008-06-26 13:21:34 +04:00
/*
* Generic helpers for smp ipi calls
*
* ( C ) Jens Axboe < jens . axboe @ oracle . com > 2008
*
*/
# include <linux/init.h>
# include <linux/module.h>
# include <linux/percpu.h>
# include <linux/rcupdate.h>
2008-07-16 01:02:33 +04:00
# include <linux/rculist.h>
2008-06-26 13:21:34 +04:00
# include <linux/smp.h>
static DEFINE_PER_CPU ( struct call_single_queue , call_single_queue ) ;
static LIST_HEAD ( call_function_queue ) ;
__cacheline_aligned_in_smp DEFINE_SPINLOCK ( call_function_lock ) ;
enum {
CSD_FLAG_WAIT = 0x01 ,
CSD_FLAG_ALLOC = 0x02 ,
2009-01-29 18:08:01 +03:00
CSD_FLAG_LOCK = 0x04 ,
2008-06-26 13:21:34 +04:00
} ;
struct call_function_data {
struct call_single_data csd ;
spinlock_t lock ;
unsigned int refs ;
struct rcu_head rcu_head ;
2008-12-30 01:35:16 +03:00
unsigned long cpumask_bits [ ] ;
2008-06-26 13:21:34 +04:00
} ;
struct call_single_queue {
struct list_head list ;
spinlock_t lock ;
} ;
2008-07-26 06:45:11 +04:00
static int __cpuinit init_call_single_data ( void )
2008-06-26 13:21:34 +04:00
{
int i ;
for_each_possible_cpu ( i ) {
struct call_single_queue * q = & per_cpu ( call_single_queue , i ) ;
spin_lock_init ( & q - > lock ) ;
INIT_LIST_HEAD ( & q - > list ) ;
}
2008-07-26 06:45:11 +04:00
return 0 ;
2008-06-26 13:21:34 +04:00
}
2008-07-26 06:45:11 +04:00
early_initcall ( init_call_single_data ) ;
2008-06-26 13:21:34 +04:00
static void csd_flag_wait ( struct call_single_data * data )
{
/* Wait for response */
do {
if ( ! ( data - > flags & CSD_FLAG_WAIT ) )
break ;
cpu_relax ( ) ;
} while ( 1 ) ;
}
/*
* Insert a previously allocated call_single_data element for execution
* on the given CPU . data must already have - > func , - > info , and - > flags set .
*/
static void generic_exec_single ( int cpu , struct call_single_data * data )
{
struct call_single_queue * dst = & per_cpu ( call_single_queue , cpu ) ;
int wait = data - > flags & CSD_FLAG_WAIT , ipi ;
unsigned long flags ;
spin_lock_irqsave ( & dst - > lock , flags ) ;
ipi = list_empty ( & dst - > list ) ;
list_add_tail ( & data - > list , & dst - > list ) ;
spin_unlock_irqrestore ( & dst - > lock , flags ) ;
2008-10-30 20:28:41 +03:00
/*
* Make the list addition visible before sending the ipi .
*/
smp_mb ( ) ;
2008-06-26 13:21:34 +04:00
if ( ipi )
arch_send_call_function_single_ipi ( cpu ) ;
if ( wait )
csd_flag_wait ( data ) ;
}
static void rcu_free_call_data ( struct rcu_head * head )
{
struct call_function_data * data ;
data = container_of ( head , struct call_function_data , rcu_head ) ;
kfree ( data ) ;
}
/*
* Invoked by arch to handle an IPI for call function . Must be called with
* interrupts disabled .
*/
void generic_smp_call_function_interrupt ( void )
{
struct call_function_data * data ;
int cpu = get_cpu ( ) ;
/*
* It ' s ok to use list_for_each_rcu ( ) here even though we may delete
* ' pos ' , since list_del_rcu ( ) doesn ' t clear - > next
*/
rcu_read_lock ( ) ;
list_for_each_entry_rcu ( data , & call_function_queue , csd . list ) {
int refs ;
2008-12-30 01:35:16 +03:00
if ( ! cpumask_test_cpu ( cpu , to_cpumask ( data - > cpumask_bits ) ) )
2008-06-26 13:21:34 +04:00
continue ;
data - > csd . func ( data - > csd . info ) ;
spin_lock ( & data - > lock ) ;
2008-12-30 01:35:16 +03:00
cpumask_clear_cpu ( cpu , to_cpumask ( data - > cpumask_bits ) ) ;
2008-06-26 13:21:34 +04:00
WARN_ON ( data - > refs = = 0 ) ;
data - > refs - - ;
refs = data - > refs ;
spin_unlock ( & data - > lock ) ;
if ( refs )
continue ;
spin_lock ( & call_function_lock ) ;
list_del_rcu ( & data - > csd . list ) ;
spin_unlock ( & call_function_lock ) ;
if ( data - > csd . flags & CSD_FLAG_WAIT ) {
/*
* serialize stores to data with the flag clear
* and wakeup
*/
smp_wmb ( ) ;
data - > csd . flags & = ~ CSD_FLAG_WAIT ;
2008-08-12 12:05:13 +04:00
}
if ( data - > csd . flags & CSD_FLAG_ALLOC )
2008-06-26 13:21:34 +04:00
call_rcu ( & data - > rcu_head , rcu_free_call_data ) ;
}
rcu_read_unlock ( ) ;
put_cpu ( ) ;
}
/*
* Invoked by arch to handle an IPI for call function single . Must be called
* from the arch with interrupts disabled .
*/
void generic_smp_call_function_single_interrupt ( void )
{
struct call_single_queue * q = & __get_cpu_var ( call_single_queue ) ;
LIST_HEAD ( list ) ;
/*
* Need to see other stores to list head for checking whether
* list is empty without holding q - > lock
*/
2008-10-30 20:28:41 +03:00
smp_read_barrier_depends ( ) ;
2008-06-26 13:21:34 +04:00
while ( ! list_empty ( & q - > list ) ) {
unsigned int data_flags ;
spin_lock ( & q - > lock ) ;
list_replace_init ( & q - > list , & list ) ;
spin_unlock ( & q - > lock ) ;
while ( ! list_empty ( & list ) ) {
struct call_single_data * data ;
data = list_entry ( list . next , struct call_single_data ,
list ) ;
list_del ( & data - > list ) ;
/*
* ' data ' can be invalid after this call if
* flags = = 0 ( when called through
* generic_exec_single ( ) , so save them away before
* making the call .
*/
data_flags = data - > flags ;
data - > func ( data - > info ) ;
if ( data_flags & CSD_FLAG_WAIT ) {
smp_wmb ( ) ;
data - > flags & = ~ CSD_FLAG_WAIT ;
2009-01-29 18:08:01 +03:00
} else if ( data_flags & CSD_FLAG_LOCK ) {
smp_wmb ( ) ;
data - > flags & = ~ CSD_FLAG_LOCK ;
2008-06-26 13:21:34 +04:00
} else if ( data_flags & CSD_FLAG_ALLOC )
kfree ( data ) ;
}
/*
* See comment on outer loop
*/
2008-10-30 20:28:41 +03:00
smp_read_barrier_depends ( ) ;
2008-06-26 13:21:34 +04:00
}
}
2009-01-29 18:08:01 +03:00
static DEFINE_PER_CPU ( struct call_single_data , csd_data ) ;
2008-06-26 13:21:34 +04:00
/*
* smp_call_function_single - Run a function on a specific CPU
* @ func : The function to run . This must be fast and non - blocking .
* @ info : An arbitrary pointer to pass to the function .
* @ wait : If true , wait until function has completed on other CPUs .
*
* Returns 0 on success , else a negative status code . Note that @ wait
* will be implicitly turned on in case of allocation failures , since
* we fall back to on - stack allocation .
*/
int smp_call_function_single ( int cpu , void ( * func ) ( void * info ) , void * info ,
2008-06-06 13:18:06 +04:00
int wait )
2008-06-26 13:21:34 +04:00
{
struct call_single_data d ;
unsigned long flags ;
2008-08-26 04:07:14 +04:00
/* prevent preemption and reschedule on another processor,
as well as CPU removal */
2008-06-26 13:21:34 +04:00
int me = get_cpu ( ) ;
2008-08-26 04:07:14 +04:00
int err = 0 ;
2008-06-26 13:21:34 +04:00
/* Can deadlock when called with interrupts disabled */
WARN_ON ( irqs_disabled ( ) ) ;
if ( cpu = = me ) {
local_irq_save ( flags ) ;
func ( info ) ;
local_irq_restore ( flags ) ;
2009-01-01 02:42:15 +03:00
} else if ( ( unsigned ) cpu < nr_cpu_ids & & cpu_online ( cpu ) ) {
2009-01-29 18:08:01 +03:00
struct call_single_data * data ;
2008-06-26 13:21:34 +04:00
if ( ! wait ) {
2009-01-29 18:08:01 +03:00
/*
* We are calling a function on a single CPU
* and we are not going to wait for it to finish .
* We first try to allocate the data , but if we
* fail , we fall back to use a per cpu data to pass
* the information to that CPU . Since all callers
* of this code will use the same data , we must
* synchronize the callers to prevent a new caller
* from corrupting the data before the callee
* can access it .
*
* The CSD_FLAG_LOCK is used to let us know when
* the IPI handler is done with the data .
* The first caller will set it , and the callee
* will clear it . The next caller must wait for
* it to clear before we set it again . This
* will make sure the callee is done with the
* data before a new caller will use it .
*/
2008-06-26 13:21:34 +04:00
data = kmalloc ( sizeof ( * data ) , GFP_ATOMIC ) ;
if ( data )
data - > flags = CSD_FLAG_ALLOC ;
2009-01-29 18:08:01 +03:00
else {
data = & per_cpu ( csd_data , me ) ;
while ( data - > flags & CSD_FLAG_LOCK )
cpu_relax ( ) ;
data - > flags = CSD_FLAG_LOCK ;
}
} else {
2008-06-26 13:21:34 +04:00
data = & d ;
data - > flags = CSD_FLAG_WAIT ;
}
data - > func = func ;
data - > info = info ;
generic_exec_single ( cpu , data ) ;
2008-08-26 04:07:14 +04:00
} else {
err = - ENXIO ; /* CPU not online */
2008-06-26 13:21:34 +04:00
}
put_cpu ( ) ;
2008-08-26 04:07:14 +04:00
return err ;
2008-06-26 13:21:34 +04:00
}
EXPORT_SYMBOL ( smp_call_function_single ) ;
/**
* __smp_call_function_single ( ) : Run a function on another CPU
* @ cpu : The CPU to run on .
* @ data : Pre - allocated and setup data structure
*
* Like smp_call_function_single ( ) , but allow caller to pass in a pre - allocated
* data structure . Useful for embedding @ data inside other structures , for
* instance .
*
*/
void __smp_call_function_single ( int cpu , struct call_single_data * data )
{
/* Can deadlock when called with interrupts disabled */
WARN_ON ( ( data - > flags & CSD_FLAG_WAIT ) & & irqs_disabled ( ) ) ;
generic_exec_single ( cpu , data ) ;
}
2008-12-30 01:35:17 +03:00
/* FIXME: Shim for archs using old arch_send_call_function_ipi API. */
# ifndef arch_send_call_function_ipi_mask
# define arch_send_call_function_ipi_mask(maskp) \
arch_send_call_function_ipi ( * ( maskp ) )
# endif
2008-06-26 13:21:34 +04:00
/**
2008-12-30 01:35:16 +03:00
* smp_call_function_many ( ) : Run a function on a set of other CPUs .
* @ mask : The set of cpus to run on ( only runs on online subset ) .
2008-06-26 13:21:34 +04:00
* @ func : The function to run . This must be fast and non - blocking .
* @ info : An arbitrary pointer to pass to the function .
* @ wait : If true , wait ( atomically ) until function has completed on other CPUs .
*
* If @ wait is true , then returns once @ func has returned . Note that @ wait
* will be implicitly turned on in case of allocation failures , since
* we fall back to on - stack allocation .
*
* You must not call this function with disabled interrupts or from a
* hardware interrupt handler or from a bottom half handler . Preemption
* must be disabled when calling this function .
*/
2008-12-30 01:35:16 +03:00
void smp_call_function_many ( const struct cpumask * mask ,
void ( * func ) ( void * ) , void * info ,
bool wait )
2008-06-26 13:21:34 +04:00
{
2008-12-30 01:35:16 +03:00
struct call_function_data * data ;
2008-06-26 13:21:34 +04:00
unsigned long flags ;
2008-12-30 01:35:16 +03:00
int cpu , next_cpu ;
2008-06-26 13:21:34 +04:00
/* Can deadlock when called with interrupts disabled */
WARN_ON ( irqs_disabled ( ) ) ;
2008-12-30 01:35:16 +03:00
/* So, what's a CPU they want? Ignoring this one. */
cpu = cpumask_first_and ( mask , cpu_online_mask ) ;
if ( cpu = = smp_processor_id ( ) )
cpu = cpumask_next_and ( cpu , mask , cpu_online_mask ) ;
/* No online cpus? We're done. */
if ( cpu > = nr_cpu_ids )
return ;
/* Do we have another CPU which isn't us? */
next_cpu = cpumask_next_and ( cpu , mask , cpu_online_mask ) ;
if ( next_cpu = = smp_processor_id ( ) )
next_cpu = cpumask_next_and ( next_cpu , mask , cpu_online_mask ) ;
/* Fastpath: do that cpu by itself. */
if ( next_cpu > = nr_cpu_ids ) {
smp_call_function_single ( cpu , func , info , wait ) ;
return ;
2008-06-26 13:21:34 +04:00
}
2008-12-30 01:35:16 +03:00
data = kmalloc ( sizeof ( * data ) + cpumask_size ( ) , GFP_ATOMIC ) ;
if ( unlikely ( ! data ) ) {
/* Slow path. */
for_each_online_cpu ( cpu ) {
if ( cpu = = smp_processor_id ( ) )
continue ;
if ( cpumask_test_cpu ( cpu , mask ) )
smp_call_function_single ( cpu , func , info , wait ) ;
}
return ;
2008-06-26 13:21:34 +04:00
}
spin_lock_init ( & data - > lock ) ;
2008-12-30 01:35:16 +03:00
data - > csd . flags = CSD_FLAG_ALLOC ;
if ( wait )
data - > csd . flags | = CSD_FLAG_WAIT ;
2008-06-26 13:21:34 +04:00
data - > csd . func = func ;
data - > csd . info = info ;
2008-12-30 01:35:16 +03:00
cpumask_and ( to_cpumask ( data - > cpumask_bits ) , mask , cpu_online_mask ) ;
cpumask_clear_cpu ( smp_processor_id ( ) , to_cpumask ( data - > cpumask_bits ) ) ;
data - > refs = cpumask_weight ( to_cpumask ( data - > cpumask_bits ) ) ;
2008-06-26 13:21:34 +04:00
spin_lock_irqsave ( & call_function_lock , flags ) ;
list_add_tail_rcu ( & data - > csd . list , & call_function_queue ) ;
spin_unlock_irqrestore ( & call_function_lock , flags ) ;
2008-10-30 20:28:41 +03:00
/*
* Make the list addition visible before sending the ipi .
*/
smp_mb ( ) ;
2008-06-26 13:21:34 +04:00
/* Send a message to all CPUs in the map */
2008-12-30 01:35:17 +03:00
arch_send_call_function_ipi_mask ( to_cpumask ( data - > cpumask_bits ) ) ;
2008-06-26 13:21:34 +04:00
/* optionally wait for the CPUs to complete */
2008-12-30 01:35:16 +03:00
if ( wait )
2008-06-26 13:21:34 +04:00
csd_flag_wait ( & data - > csd ) ;
}
2008-12-30 01:35:16 +03:00
EXPORT_SYMBOL ( smp_call_function_many ) ;
2008-06-26 13:21:34 +04:00
/**
* smp_call_function ( ) : Run a function on all other CPUs .
* @ func : The function to run . This must be fast and non - blocking .
* @ info : An arbitrary pointer to pass to the function .
* @ wait : If true , wait ( atomically ) until function has completed on other CPUs .
*
2008-12-30 01:35:16 +03:00
* Returns 0.
2008-06-26 13:21:34 +04:00
*
* If @ wait is true , then returns once @ func has returned ; otherwise
* it returns just before the target cpu calls @ func . In case of allocation
* failure , @ wait will be implicitly turned on .
*
* You must not call this function with disabled interrupts or from a
* hardware interrupt handler or from a bottom half handler .
*/
2008-06-06 13:18:06 +04:00
int smp_call_function ( void ( * func ) ( void * ) , void * info , int wait )
2008-06-26 13:21:34 +04:00
{
preempt_disable ( ) ;
2008-12-30 01:35:16 +03:00
smp_call_function_many ( cpu_online_mask , func , info , wait ) ;
2008-06-26 13:21:34 +04:00
preempt_enable ( ) ;
2008-12-30 01:35:16 +03:00
return 0 ;
2008-06-26 13:21:34 +04:00
}
EXPORT_SYMBOL ( smp_call_function ) ;
void ipi_call_lock ( void )
{
spin_lock ( & call_function_lock ) ;
}
void ipi_call_unlock ( void )
{
spin_unlock ( & call_function_lock ) ;
}
void ipi_call_lock_irq ( void )
{
spin_lock_irq ( & call_function_lock ) ;
}
void ipi_call_unlock_irq ( void )
{
spin_unlock_irq ( & call_function_lock ) ;
}