Commit 407e24a0 authored by Geoff Levand's avatar Geoff Levand Committed by Paul Mackerras

[POWERPC] ps3: smp interrupt fixes

PS3 fixups for interrups on SMP.

Fixes the alignment of the interrupt status bitmap, changes the hypervisor
interrupt calls to the '_ext' versions that take an explicit processor
thread ID.
Signed-off-by: default avatarGeoff Levand <geoffrey.levand@am.sony.com>
Acked-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent 9633ac8d
...@@ -317,22 +317,23 @@ struct ps3_bmp { ...@@ -317,22 +317,23 @@ struct ps3_bmp {
unsigned long unused_1[3]; unsigned long unused_1[3];
unsigned long mask; unsigned long mask;
unsigned long unused_2[3]; unsigned long unused_2[3];
} __attribute__ ((packed)); } __attribute__ ((aligned (64)));
spinlock_t lock; spinlock_t lock;
unsigned long ipi_debug_brk_mask; unsigned long ipi_debug_brk_mask;
}; };
/** /**
* struct ps3_private - a per cpu data structure * struct ps3_private - a per cpu data structure
* @node: HV node id * @bmp: ps3_bmp structure
* @cpu: HV thread id * @node: HV logical_ppe_id
* @bmp: an HV ps3_bmp structure * @cpu: HV thread_id
*/ */
struct ps3_private { struct ps3_private {
struct ps3_bmp bmp;
unsigned long node; unsigned long node;
unsigned int cpu; unsigned int cpu;
struct ps3_bmp bmp;
}; };
#if defined(DEBUG) #if defined(DEBUG)
...@@ -389,9 +390,8 @@ static void ps3_chip_mask(unsigned int virq) ...@@ -389,9 +390,8 @@ static void ps3_chip_mask(unsigned int virq)
spin_lock_irqsave(&pd->bmp.lock, flags); spin_lock_irqsave(&pd->bmp.lock, flags);
pd->bmp.mask &= ~(0x8000000000000000UL >> virq); pd->bmp.mask &= ~(0x8000000000000000UL >> virq);
spin_unlock_irqrestore(&pd->bmp.lock, flags);
lv1_did_update_interrupt_mask(pd->node, pd->cpu); lv1_did_update_interrupt_mask(pd->node, pd->cpu);
spin_unlock_irqrestore(&pd->bmp.lock, flags);
} }
static void ps3_chip_unmask(unsigned int virq) static void ps3_chip_unmask(unsigned int virq)
...@@ -406,14 +406,14 @@ static void ps3_chip_unmask(unsigned int virq) ...@@ -406,14 +406,14 @@ static void ps3_chip_unmask(unsigned int virq)
spin_lock_irqsave(&pd->bmp.lock, flags); spin_lock_irqsave(&pd->bmp.lock, flags);
pd->bmp.mask |= (0x8000000000000000UL >> virq); pd->bmp.mask |= (0x8000000000000000UL >> virq);
spin_unlock_irqrestore(&pd->bmp.lock, flags);
lv1_did_update_interrupt_mask(pd->node, pd->cpu); lv1_did_update_interrupt_mask(pd->node, pd->cpu);
spin_unlock_irqrestore(&pd->bmp.lock, flags);
} }
static void ps3_chip_eoi(unsigned int virq) static void ps3_chip_eoi(unsigned int virq)
{ {
lv1_end_of_interrupt(virq); const struct ps3_private *pd = get_irq_chip_data(virq);
lv1_end_of_interrupt_ext(pd->node, pd->cpu, virq);
} }
static struct irq_chip irq_chip = { static struct irq_chip irq_chip = {
...@@ -426,10 +426,12 @@ static struct irq_chip irq_chip = { ...@@ -426,10 +426,12 @@ static struct irq_chip irq_chip = {
static void ps3_host_unmap(struct irq_host *h, unsigned int virq) static void ps3_host_unmap(struct irq_host *h, unsigned int virq)
{ {
int result; int result;
const struct ps3_private *pd = get_irq_chip_data(virq);
pr_debug("%s:%d: virq %d\n", __func__, __LINE__, virq); pr_debug("%s:%d: node %lu, cpu %d, virq %u\n", __func__, __LINE__,
pd->node, pd->cpu, virq);
lv1_disconnect_irq_plug(virq); lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, virq);
result = set_irq_chip_data(virq, NULL); result = set_irq_chip_data(virq, NULL);
BUG_ON(result); BUG_ON(result);
...@@ -441,31 +443,26 @@ static int ps3_host_map(struct irq_host *h, unsigned int virq, ...@@ -441,31 +443,26 @@ static int ps3_host_map(struct irq_host *h, unsigned int virq,
irq_hw_number_t hwirq) irq_hw_number_t hwirq)
{ {
int result; int result;
unsigned int cpu; struct ps3_private *pd = &__get_cpu_var(ps3_private);
pr_debug(" -> %s:%d\n", __func__, __LINE__); pr_debug("%s:%d: node %lu, cpu %d, hwirq %lu => virq %u\n", __func__,
pr_debug("%s:%d: hwirq %lu => virq %u\n", __func__, __LINE__, hwirq, __LINE__, pd->node, pd->cpu, hwirq, virq);
virq);
/* bind this virq to a cpu */ /* Binds this virq to pd->cpu (current cpu) */
preempt_disable(); result = lv1_connect_irq_plug_ext(pd->node, pd->cpu, virq, hwirq, 0);
cpu = smp_processor_id();
result = lv1_connect_irq_plug(virq, hwirq);
preempt_enable();
if (result) { if (result) {
pr_info("%s:%d: lv1_connect_irq_plug failed:" pr_info("%s:%d: lv1_connect_irq_plug_ext failed:"
" %s\n", __func__, __LINE__, ps3_result(result)); " %s\n", __func__, __LINE__, ps3_result(result));
return -EPERM; return -EPERM;
} }
result = set_irq_chip_data(virq, &per_cpu(ps3_private, cpu)); result = set_irq_chip_data(virq, pd);
BUG_ON(result); BUG_ON(result);
set_irq_chip_and_handler(virq, &irq_chip, handle_fasteoi_irq); set_irq_chip_and_handler(virq, &irq_chip, handle_fasteoi_irq);
pr_debug(" <- %s:%d\n", __func__, __LINE__);
return result; return result;
} }
...@@ -544,12 +541,9 @@ unsigned int ps3_get_irq(void) ...@@ -544,12 +541,9 @@ unsigned int ps3_get_irq(void)
void __init ps3_init_IRQ(void) void __init ps3_init_IRQ(void)
{ {
int result; int result;
unsigned long node;
unsigned cpu; unsigned cpu;
struct irq_host *host; struct irq_host *host;
lv1_get_logical_ppe_id(&node);
host = irq_alloc_host(IRQ_HOST_MAP_NOMAP, 0, &ps3_host_ops, host = irq_alloc_host(IRQ_HOST_MAP_NOMAP, 0, &ps3_host_ops,
PS3_INVALID_OUTLET); PS3_INVALID_OUTLET);
irq_set_default_host(host); irq_set_default_host(host);
...@@ -558,12 +552,16 @@ void __init ps3_init_IRQ(void) ...@@ -558,12 +552,16 @@ void __init ps3_init_IRQ(void)
for_each_possible_cpu(cpu) { for_each_possible_cpu(cpu) {
struct ps3_private *pd = &per_cpu(ps3_private, cpu); struct ps3_private *pd = &per_cpu(ps3_private, cpu);
pd->node = node; lv1_get_logical_ppe_id(&pd->node);
pd->cpu = cpu; pd->cpu = get_hard_smp_processor_id(cpu);
spin_lock_init(&pd->bmp.lock); spin_lock_init(&pd->bmp.lock);
result = lv1_configure_irq_state_bitmap(node, cpu, pr_debug("%s:%d: node %lu, cpu %d, bmp %lxh\n", __func__,
ps3_mm_phys_to_lpar(__pa(&pd->bmp.status))); __LINE__, pd->node, pd->cpu,
ps3_mm_phys_to_lpar(__pa(&pd->bmp)));
result = lv1_configure_irq_state_bitmap(pd->node, pd->cpu,
ps3_mm_phys_to_lpar(__pa(&pd->bmp)));
if (result) if (result)
pr_debug("%s:%d: lv1_configure_irq_state_bitmap failed:" pr_debug("%s:%d: lv1_configure_irq_state_bitmap failed:"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment