forked from Minki/linux
[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: Geoff Levand <geoffrey.levand@am.sony.com> Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
This commit is contained in:
parent
9633ac8d17
commit
407e24a0c7
@ -317,22 +317,23 @@ struct ps3_bmp {
|
||||
unsigned long unused_1[3];
|
||||
unsigned long mask;
|
||||
unsigned long unused_2[3];
|
||||
} __attribute__ ((packed));
|
||||
} __attribute__ ((aligned (64)));
|
||||
|
||||
spinlock_t lock;
|
||||
unsigned long ipi_debug_brk_mask;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ps3_private - a per cpu data structure
|
||||
* @node: HV node id
|
||||
* @cpu: HV thread id
|
||||
* @bmp: an HV ps3_bmp structure
|
||||
* @bmp: ps3_bmp structure
|
||||
* @node: HV logical_ppe_id
|
||||
* @cpu: HV thread_id
|
||||
*/
|
||||
|
||||
struct ps3_private {
|
||||
struct ps3_bmp bmp;
|
||||
unsigned long node;
|
||||
unsigned int cpu;
|
||||
struct ps3_bmp bmp;
|
||||
};
|
||||
|
||||
#if defined(DEBUG)
|
||||
@ -389,9 +390,8 @@ static void ps3_chip_mask(unsigned int virq)
|
||||
|
||||
spin_lock_irqsave(&pd->bmp.lock, flags);
|
||||
pd->bmp.mask &= ~(0x8000000000000000UL >> virq);
|
||||
spin_unlock_irqrestore(&pd->bmp.lock, flags);
|
||||
|
||||
lv1_did_update_interrupt_mask(pd->node, pd->cpu);
|
||||
spin_unlock_irqrestore(&pd->bmp.lock, flags);
|
||||
}
|
||||
|
||||
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);
|
||||
pd->bmp.mask |= (0x8000000000000000UL >> virq);
|
||||
spin_unlock_irqrestore(&pd->bmp.lock, flags);
|
||||
|
||||
lv1_did_update_interrupt_mask(pd->node, pd->cpu);
|
||||
spin_unlock_irqrestore(&pd->bmp.lock, flags);
|
||||
}
|
||||
|
||||
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 = {
|
||||
@ -426,10 +426,12 @@ static struct irq_chip irq_chip = {
|
||||
static void ps3_host_unmap(struct irq_host *h, unsigned int virq)
|
||||
{
|
||||
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);
|
||||
BUG_ON(result);
|
||||
@ -441,31 +443,26 @@ static int ps3_host_map(struct irq_host *h, unsigned int virq,
|
||||
irq_hw_number_t hwirq)
|
||||
{
|
||||
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: hwirq %lu => virq %u\n", __func__, __LINE__, hwirq,
|
||||
virq);
|
||||
pr_debug("%s:%d: node %lu, cpu %d, hwirq %lu => virq %u\n", __func__,
|
||||
__LINE__, pd->node, pd->cpu, hwirq, virq);
|
||||
|
||||
/* bind this virq to a cpu */
|
||||
/* Binds this virq to pd->cpu (current cpu) */
|
||||
|
||||
preempt_disable();
|
||||
cpu = smp_processor_id();
|
||||
result = lv1_connect_irq_plug(virq, hwirq);
|
||||
preempt_enable();
|
||||
result = lv1_connect_irq_plug_ext(pd->node, pd->cpu, virq, hwirq, 0);
|
||||
|
||||
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));
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
result = set_irq_chip_data(virq, &per_cpu(ps3_private, cpu));
|
||||
result = set_irq_chip_data(virq, pd);
|
||||
BUG_ON(result);
|
||||
|
||||
set_irq_chip_and_handler(virq, &irq_chip, handle_fasteoi_irq);
|
||||
|
||||
pr_debug(" <- %s:%d\n", __func__, __LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -544,12 +541,9 @@ unsigned int ps3_get_irq(void)
|
||||
void __init ps3_init_IRQ(void)
|
||||
{
|
||||
int result;
|
||||
unsigned long node;
|
||||
unsigned cpu;
|
||||
struct irq_host *host;
|
||||
|
||||
lv1_get_logical_ppe_id(&node);
|
||||
|
||||
host = irq_alloc_host(IRQ_HOST_MAP_NOMAP, 0, &ps3_host_ops,
|
||||
PS3_INVALID_OUTLET);
|
||||
irq_set_default_host(host);
|
||||
@ -558,12 +552,16 @@ void __init ps3_init_IRQ(void)
|
||||
for_each_possible_cpu(cpu) {
|
||||
struct ps3_private *pd = &per_cpu(ps3_private, cpu);
|
||||
|
||||
pd->node = node;
|
||||
pd->cpu = cpu;
|
||||
lv1_get_logical_ppe_id(&pd->node);
|
||||
pd->cpu = get_hard_smp_processor_id(cpu);
|
||||
spin_lock_init(&pd->bmp.lock);
|
||||
|
||||
result = lv1_configure_irq_state_bitmap(node, cpu,
|
||||
ps3_mm_phys_to_lpar(__pa(&pd->bmp.status)));
|
||||
pr_debug("%s:%d: node %lu, cpu %d, bmp %lxh\n", __func__,
|
||||
__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)
|
||||
pr_debug("%s:%d: lv1_configure_irq_state_bitmap failed:"
|
||||
|
Loading…
Reference in New Issue
Block a user