Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 204710
b: refs/heads/master
c: b9f1cd7
h: refs/heads/master
v: v3
  • Loading branch information
Benjamin Herrenschmidt committed Jul 9, 2010
1 parent 96dd727 commit 1091f87
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 19 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: e3145b387a02d4bf8b8033b1354d413fc0864494
refs/heads/master: b9f1cd71dbf21a91fb7e2336a1d1ff18b97771e5
7 changes: 3 additions & 4 deletions trunk/arch/powerpc/include/asm/dbell.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,9 @@ enum ppc_dbell {
PPC_G_DBELL_MC = 4, /* guest mcheck doorbell */
};

#ifdef CONFIG_SMP
extern unsigned long dbell_smp_message[NR_CPUS];
extern void smp_dbell_message_pass(int target, int msg);
#endif
extern void doorbell_message_pass(int target, int msg);
extern void doorbell_exception(struct pt_regs *regs);
extern void doorbell_setup_this_cpu(void);

static inline void ppc_msgsnd(enum ppc_dbell type, u32 flags, u32 tag)
{
Expand Down
47 changes: 34 additions & 13 deletions trunk/arch/powerpc/kernel/dbell.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,45 +13,66 @@
#include <linux/kernel.h>
#include <linux/smp.h>
#include <linux/threads.h>
#include <linux/percpu.h>

#include <asm/dbell.h>

#ifdef CONFIG_SMP
unsigned long dbell_smp_message[NR_CPUS];
struct doorbell_cpu_info {
unsigned long messages; /* current messages bits */
unsigned int tag; /* tag value */
};

void smp_dbell_message_pass(int target, int msg)
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);

info->messages = 0;
info->tag = mfspr(SPRN_PIR) & 0x3fff;
}

void doorbell_message_pass(int target, int msg)
{
struct doorbell_cpu_info *info;
int i;

if(target < NR_CPUS) {
set_bit(msg, &dbell_smp_message[target]);
ppc_msgsnd(PPC_DBELL, 0, target);
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) {
else if (target == MSG_ALL_BUT_SELF) {
for_each_online_cpu(i) {
if (i == smp_processor_id())
continue;
set_bit(msg, &dbell_smp_message[i]);
ppc_msgsnd(PPC_DBELL, 0, i);
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)
set_bit(msg, &dbell_smp_message[i]);
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);
}
}

void doorbell_exception(struct pt_regs *regs)
{
int cpu = smp_processor_id();
struct doorbell_cpu_info *info = &__get_cpu_var(doorbell_cpu_info);
int msg;

if (num_online_cpus() < 2)
/* Warning: regs can be NULL when called from irq enable */

if (!info->messages || (num_online_cpus() < 2))
return;

for (msg = 0; msg < 4; msg++)
if (test_and_clear_bit(msg, &dbell_smp_message[cpu]))
if (test_and_clear_bit(msg, &info->messages))
smp_message_recv(msg);
}

Expand Down
4 changes: 3 additions & 1 deletion trunk/arch/powerpc/platforms/85xx/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ static void __init
smp_85xx_setup_cpu(int cpu_nr)
{
mpic_setup_this_cpu();
if (cpu_has_feature(CPU_FTR_DBELL))
doorbell_setup_this_cpu();
}

struct smp_ops_t smp_85xx_ops = {
Expand All @@ -117,7 +119,7 @@ void __init mpc85xx_smp_init(void)
}

if (cpu_has_feature(CPU_FTR_DBELL))
smp_85xx_ops.message_pass = smp_dbell_message_pass;
smp_85xx_ops.message_pass = doorbell_message_pass;

BUG_ON(!smp_85xx_ops.message_pass);

Expand Down

0 comments on commit 1091f87

Please sign in to comment.