diff options
Diffstat (limited to 'arch/powerpc/kernel/dbell.c')
| -rw-r--r-- | arch/powerpc/kernel/dbell.c | 69 | 
1 files changed, 13 insertions, 56 deletions
diff --git a/arch/powerpc/kernel/dbell.c b/arch/powerpc/kernel/dbell.c index 3307a52d797..d55c76c571f 100644 --- a/arch/powerpc/kernel/dbell.c +++ b/arch/powerpc/kernel/dbell.c @@ -13,84 +13,41 @@  #include <linux/kernel.h>  #include <linux/smp.h>  #include <linux/threads.h> -#include <linux/percpu.h> +#include <linux/hardirq.h>  #include <asm/dbell.h>  #include <asm/irq_regs.h>  #ifdef CONFIG_SMP -struct doorbell_cpu_info { -	unsigned long	messages;	/* current messages bits */ -	unsigned int	tag;		/* tag value */ -}; - -static DEFINE_PER_CPU(struct doorbell_cpu_info, doorbell_cpu_info); -  void doorbell_setup_this_cpu(void)  { -	struct doorbell_cpu_info *info = &__get_cpu_var(doorbell_cpu_info); +	unsigned long tag = mfspr(SPRN_DOORBELL_CPUTAG) & PPC_DBELL_TAG_MASK; -	info->messages = 0; -	info->tag = mfspr(SPRN_PIR) & 0x3fff; +	smp_muxed_ipi_set_data(smp_processor_id(), tag);  } -void doorbell_message_pass(int target, int msg) +void doorbell_cause_ipi(int cpu, unsigned long data)  { -	struct doorbell_cpu_info *info; -	int i; - -	if (target < NR_CPUS) { -		info = &per_cpu(doorbell_cpu_info, target); -		set_bit(msg, &info->messages); -		ppc_msgsnd(PPC_DBELL, 0, info->tag); -	} -	else if (target == MSG_ALL_BUT_SELF) { -		for_each_online_cpu(i) { -			if (i == smp_processor_id()) -				continue; -			info = &per_cpu(doorbell_cpu_info, i); -			set_bit(msg, &info->messages); -			ppc_msgsnd(PPC_DBELL, 0, info->tag); -		} -	} -	else { /* target == MSG_ALL */ -		for_each_online_cpu(i) { -			info = &per_cpu(doorbell_cpu_info, i); -			set_bit(msg, &info->messages); -		} -		ppc_msgsnd(PPC_DBELL, PPC_DBELL_MSG_BRDCAST, 0); -	} +	/* Order previous accesses vs. msgsnd, which is treated as a store */ +	mb(); +	ppc_msgsnd(PPC_DBELL_MSGTYPE, 0, data);  }  void doorbell_exception(struct pt_regs *regs)  {  	struct pt_regs *old_regs = set_irq_regs(regs); -	struct doorbell_cpu_info *info = &__get_cpu_var(doorbell_cpu_info); -	int msg; - -	/* Warning: regs can be NULL when called from irq enable */ - -	if (!info->messages || (num_online_cpus() < 2)) -		goto out; -	for (msg = 0; msg < 4; msg++) -		if (test_and_clear_bit(msg, &info->messages)) -			smp_message_recv(msg); +	irq_enter(); -out: -	set_irq_regs(old_regs); -} +	may_hard_irq_enable(); -void doorbell_check_self(void) -{ -	struct doorbell_cpu_info *info = &__get_cpu_var(doorbell_cpu_info); +	__get_cpu_var(irq_stat).doorbell_irqs++; -	if (!info->messages) -		return; +	smp_ipi_demux(); -	ppc_msgsnd(PPC_DBELL, 0, info->tag); +	irq_exit(); +	set_irq_regs(old_regs);  } -  #else /* CONFIG_SMP */  void doorbell_exception(struct pt_regs *regs)  {  | 
