X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-kernel.git;a=blobdiff_plain;f=arch%2Fpowerpc%2Fplatforms%2Fcell%2Finterrupt.c;h=2d5bb22d6c092419cd4582bdbdd8f364135db833;hp=151fd8b82d63b2e0878a7ee48118b3cda0ca0576;hb=9063974cdbc5463528cb6aa60c91bc0267af7bbb;hpb=4fa435018d740cb83d74c92306aa1f796da91ddd diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c index 151fd8b82d63..2d5bb22d6c09 100644 --- a/arch/powerpc/platforms/cell/interrupt.c +++ b/arch/powerpc/platforms/cell/interrupt.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -158,6 +159,18 @@ static unsigned int iic_get_irq(void) return virq; } +void iic_setup_cpu(void) +{ + out_be64(&__get_cpu_var(iic).regs->prio, 0xff); +} + +u8 iic_get_target_id(int cpu) +{ + return per_cpu(iic, cpu).target_id; +} + +EXPORT_SYMBOL_GPL(iic_get_target_id); + #ifdef CONFIG_SMP /* Use the highest interrupt priorities for IPI */ @@ -166,29 +179,17 @@ static inline int iic_ipi_to_irq(int ipi) return IIC_IRQ_TYPE_IPI + 0xf - ipi; } -void iic_setup_cpu(void) -{ - out_be64(&__get_cpu_var(iic).regs->prio, 0xff); -} - void iic_cause_IPI(int cpu, int mesg) { out_be64(&per_cpu(iic, cpu).regs->generate, (0xf - mesg) << 4); } -u8 iic_get_target_id(int cpu) -{ - return per_cpu(iic, cpu).target_id; -} -EXPORT_SYMBOL_GPL(iic_get_target_id); - struct irq_host *iic_get_irq_host(int node) { return iic_host; } EXPORT_SYMBOL_GPL(iic_get_irq_host); - static irqreturn_t iic_ipi_action(int irq, void *dev_id) { int ipi = (int)(long)dev_id; @@ -217,6 +218,7 @@ void iic_request_IPIs(void) { iic_request_ipi(PPC_MSG_CALL_FUNCTION, "IPI-call"); iic_request_ipi(PPC_MSG_RESCHEDULE, "IPI-resched"); + iic_request_ipi(PPC_MSG_CALL_FUNC_SINGLE, "IPI-call-single"); #ifdef CONFIG_DEBUGGER iic_request_ipi(PPC_MSG_DEBUGGER_BREAK, "IPI-debug"); #endif /* CONFIG_DEBUGGER */ @@ -231,6 +233,54 @@ static int iic_host_match(struct irq_host *h, struct device_node *node) "IBM,CBEA-Internal-Interrupt-Controller"); } +extern int noirqdebug; + +static void handle_iic_irq(unsigned int irq, struct irq_desc *desc) +{ + const unsigned int cpu = smp_processor_id(); + + spin_lock(&desc->lock); + + desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); + + /* + * If we're currently running this IRQ, or its disabled, + * we shouldn't process the IRQ. Mark it pending, handle + * the necessary masking and go out + */ + if (unlikely((desc->status & (IRQ_INPROGRESS | IRQ_DISABLED)) || + !desc->action)) { + desc->status |= IRQ_PENDING; + goto out_eoi; + } + + kstat_cpu(cpu).irqs[irq]++; + + /* Mark the IRQ currently in progress.*/ + desc->status |= IRQ_INPROGRESS; + + do { + struct irqaction *action = desc->action; + irqreturn_t action_ret; + + if (unlikely(!action)) + goto out_eoi; + + desc->status &= ~IRQ_PENDING; + spin_unlock(&desc->lock); + action_ret = handle_IRQ_event(irq, action); + if (!noirqdebug) + note_interrupt(irq, desc, action_ret); + spin_lock(&desc->lock); + + } while ((desc->status & (IRQ_PENDING | IRQ_DISABLED)) == IRQ_PENDING); + + desc->status &= ~IRQ_INPROGRESS; +out_eoi: + desc->chip->eoi(irq); + spin_unlock(&desc->lock); +} + static int iic_host_map(struct irq_host *h, unsigned int virq, irq_hw_number_t hw) { @@ -240,10 +290,10 @@ static int iic_host_map(struct irq_host *h, unsigned int virq, break; case IIC_IRQ_TYPE_IOEXC: set_irq_chip_and_handler(virq, &iic_ioexc_chip, - handle_fasteoi_irq); + handle_iic_irq); break; default: - set_irq_chip_and_handler(virq, &iic_chip, handle_fasteoi_irq); + set_irq_chip_and_handler(virq, &iic_chip, handle_iic_irq); } return 0; }