Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 247908
b: refs/heads/master
c: 55dd23e
h: refs/heads/master
v: v3
  • Loading branch information
Daniel Hellstrom authored and David S. Miller committed May 16, 2011
1 parent 6c970e1 commit 3c0e609
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: ecbc42b70acbc6327adefe9635db93fcf62bf59d
refs/heads/master: 55dd23eca666876e6028aa35d5e391cfced54871
6 changes: 6 additions & 0 deletions trunk/arch/sparc/kernel/irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,10 @@ BTFIXUPDEF_CALL(void, set_irq_udt, int)
#define set_cpu_int(cpu,level) BTFIXUP_CALL(set_cpu_int)(cpu,level)
#define clear_cpu_int(cpu,level) BTFIXUP_CALL(clear_cpu_int)(cpu,level)
#define set_irq_udt(cpu) BTFIXUP_CALL(set_irq_udt)(cpu)

/* All SUN4D IPIs are sent on this IRQ, may be shared with hard IRQs */
#define SUN4D_IPI_IRQ 14

extern void sun4d_ipi_interrupt(void);

#endif
9 changes: 9 additions & 0 deletions trunk/arch/sparc/kernel/sun4d_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,15 @@ void sun4d_handler_irq(int pil, struct pt_regs *regs)

cc_set_iclr(1 << pil);

#ifdef CONFIG_SMP
/*
* Check IPI data structures after IRQ has been cleared. Hard and Soft
* IRQ can happen at the same time, so both cases are always handled.
*/
if (pil == SUN4D_IPI_IRQ)
sun4d_ipi_interrupt();
#endif

old_regs = set_irq_regs(regs);
irq_enter();
if (sbusl == 0) {
Expand Down
79 changes: 79 additions & 0 deletions trunk/arch/sparc/kernel/sun4d_smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ static inline unsigned long sun4d_swap(volatile unsigned long *ptr, unsigned lon
return val;
}

static void smp4d_ipi_init(void);
static void smp_setup_percpu_timer(void);

static unsigned char cpu_leds[32];
Expand Down Expand Up @@ -118,6 +119,7 @@ void __cpuinit smp4d_callin(void)
*/
void __init smp4d_boot_cpus(void)
{
smp4d_ipi_init();
if (boot_cpu_id)
current_set[0] = NULL;
smp_setup_percpu_timer();
Expand Down Expand Up @@ -189,6 +191,80 @@ void __init smp4d_smp_done(void)
sun4d_distribute_irqs();
}

/* Memory structure giving interrupt handler information about IPI generated */
struct sun4d_ipi_work {
int single;
int msk;
int resched;
};

static DEFINE_PER_CPU_SHARED_ALIGNED(struct sun4d_ipi_work, sun4d_ipi_work);

/* Initialize IPIs on the SUN4D SMP machine */
static void __init smp4d_ipi_init(void)
{
int cpu;
struct sun4d_ipi_work *work;

printk(KERN_INFO "smp4d: setup IPI at IRQ %d\n", SUN4D_IPI_IRQ);

for_each_possible_cpu(cpu) {
work = &per_cpu(sun4d_ipi_work, cpu);
work->single = work->msk = work->resched = 0;
}
}

void sun4d_ipi_interrupt(void)
{
struct sun4d_ipi_work *work = &__get_cpu_var(sun4d_ipi_work);

if (work->single) {
work->single = 0;
smp_call_function_single_interrupt();
}
if (work->msk) {
work->msk = 0;
smp_call_function_interrupt();
}
if (work->resched) {
work->resched = 0;
smp_resched_interrupt();
}
}

static void smp4d_ipi_single(int cpu)
{
struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu);

/* Mark work */
work->single = 1;

/* Generate IRQ on the CPU */
sun4d_send_ipi(cpu, SUN4D_IPI_IRQ);
}

static void smp4d_ipi_mask_one(int cpu)
{
struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu);

/* Mark work */
work->msk = 1;

/* Generate IRQ on the CPU */
sun4d_send_ipi(cpu, SUN4D_IPI_IRQ);
}

static void smp4d_ipi_resched(int cpu)
{
struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu);

/* Mark work */
work->resched = 1;

/* Generate IRQ on the CPU (any IRQ will cause resched) */
sun4d_send_ipi(cpu, SUN4D_IPI_IRQ);
}

static struct smp_funcall {
smpfunc_t func;
unsigned long arg1;
Expand Down Expand Up @@ -354,6 +430,9 @@ void __init sun4d_init_smp(void)
BTFIXUPSET_BLACKBOX(load_current, smp4d_blackbox_current);
BTFIXUPSET_CALL(smp_cross_call, smp4d_cross_call, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4d_processor_id, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(smp_ipi_resched, smp4d_ipi_resched, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(smp_ipi_single, smp4d_ipi_single, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(smp_ipi_mask_one, smp4d_ipi_mask_one, BTFIXUPCALL_NORM);

for (i = 0; i < NR_CPUS; i++) {
ccall_info.processors_in[i] = 1;
Expand Down

0 comments on commit 3c0e609

Please sign in to comment.