diff options
| -rw-r--r-- | arch/powerpc/platforms/cell/interrupt.c | 53 |
1 files changed, 51 insertions, 2 deletions
diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c index 04f74f9f9ab6..5bf7df146022 100644 --- a/arch/powerpc/platforms/cell/interrupt.c +++ b/arch/powerpc/platforms/cell/interrupt.c | |||
| @@ -35,6 +35,7 @@ | |||
| 35 | #include <linux/percpu.h> | 35 | #include <linux/percpu.h> |
| 36 | #include <linux/types.h> | 36 | #include <linux/types.h> |
| 37 | #include <linux/ioport.h> | 37 | #include <linux/ioport.h> |
| 38 | #include <linux/kernel_stat.h> | ||
| 38 | 39 | ||
| 39 | #include <asm/io.h> | 40 | #include <asm/io.h> |
| 40 | #include <asm/pgtable.h> | 41 | #include <asm/pgtable.h> |
| @@ -231,6 +232,54 @@ static int iic_host_match(struct irq_host *h, struct device_node *node) | |||
| 231 | "IBM,CBEA-Internal-Interrupt-Controller"); | 232 | "IBM,CBEA-Internal-Interrupt-Controller"); |
| 232 | } | 233 | } |
| 233 | 234 | ||
| 235 | extern int noirqdebug; | ||
| 236 | |||
| 237 | static void handle_iic_irq(unsigned int irq, struct irq_desc *desc) | ||
| 238 | { | ||
| 239 | const unsigned int cpu = smp_processor_id(); | ||
| 240 | |||
| 241 | spin_lock(&desc->lock); | ||
| 242 | |||
| 243 | desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); | ||
| 244 | |||
| 245 | /* | ||
| 246 | * If we're currently running this IRQ, or its disabled, | ||
| 247 | * we shouldn't process the IRQ. Mark it pending, handle | ||
| 248 | * the necessary masking and go out | ||
| 249 | */ | ||
| 250 | if (unlikely((desc->status & (IRQ_INPROGRESS | IRQ_DISABLED)) || | ||
| 251 | !desc->action)) { | ||
| 252 | desc->status |= IRQ_PENDING; | ||
| 253 | goto out_eoi; | ||
| 254 | } | ||
| 255 | |||
| 256 | kstat_cpu(cpu).irqs[irq]++; | ||
| 257 | |||
| 258 | /* Mark the IRQ currently in progress.*/ | ||
| 259 | desc->status |= IRQ_INPROGRESS; | ||
| 260 | |||
| 261 | do { | ||
| 262 | struct irqaction *action = desc->action; | ||
| 263 | irqreturn_t action_ret; | ||
| 264 | |||
| 265 | if (unlikely(!action)) | ||
| 266 | goto out_eoi; | ||
| 267 | |||
| 268 | desc->status &= ~IRQ_PENDING; | ||
| 269 | spin_unlock(&desc->lock); | ||
| 270 | action_ret = handle_IRQ_event(irq, action); | ||
| 271 | if (!noirqdebug) | ||
| 272 | note_interrupt(irq, desc, action_ret); | ||
| 273 | spin_lock(&desc->lock); | ||
| 274 | |||
| 275 | } while ((desc->status & (IRQ_PENDING | IRQ_DISABLED)) == IRQ_PENDING); | ||
| 276 | |||
| 277 | desc->status &= ~IRQ_INPROGRESS; | ||
| 278 | out_eoi: | ||
| 279 | desc->chip->eoi(irq); | ||
| 280 | spin_unlock(&desc->lock); | ||
| 281 | } | ||
| 282 | |||
| 234 | static int iic_host_map(struct irq_host *h, unsigned int virq, | 283 | static int iic_host_map(struct irq_host *h, unsigned int virq, |
| 235 | irq_hw_number_t hw) | 284 | irq_hw_number_t hw) |
| 236 | { | 285 | { |
| @@ -240,10 +289,10 @@ static int iic_host_map(struct irq_host *h, unsigned int virq, | |||
| 240 | break; | 289 | break; |
| 241 | case IIC_IRQ_TYPE_IOEXC: | 290 | case IIC_IRQ_TYPE_IOEXC: |
| 242 | set_irq_chip_and_handler(virq, &iic_ioexc_chip, | 291 | set_irq_chip_and_handler(virq, &iic_ioexc_chip, |
| 243 | handle_fasteoi_irq); | 292 | handle_iic_irq); |
| 244 | break; | 293 | break; |
| 245 | default: | 294 | default: |
| 246 | set_irq_chip_and_handler(virq, &iic_chip, handle_fasteoi_irq); | 295 | set_irq_chip_and_handler(virq, &iic_chip, handle_iic_irq); |
| 247 | } | 296 | } |
| 248 | return 0; | 297 | return 0; |
| 249 | } | 298 | } |
