diff options
Diffstat (limited to 'kernel/irq/spurious.c')
| -rw-r--r-- | kernel/irq/spurious.c | 37 |
1 files changed, 21 insertions, 16 deletions
diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c index b2fb3c18d06b..417e98092cf2 100644 --- a/kernel/irq/spurious.c +++ b/kernel/irq/spurious.c | |||
| @@ -16,39 +16,39 @@ static int irqfixup __read_mostly; | |||
| 16 | /* | 16 | /* |
| 17 | * Recovery handler for misrouted interrupts. | 17 | * Recovery handler for misrouted interrupts. |
| 18 | */ | 18 | */ |
| 19 | |||
| 20 | static int misrouted_irq(int irq, struct pt_regs *regs) | 19 | static int misrouted_irq(int irq, struct pt_regs *regs) |
| 21 | { | 20 | { |
| 22 | int i; | 21 | int i; |
| 23 | irq_desc_t *desc; | ||
| 24 | int ok = 0; | 22 | int ok = 0; |
| 25 | int work = 0; /* Did we do work for a real IRQ */ | 23 | int work = 0; /* Did we do work for a real IRQ */ |
| 26 | 24 | ||
| 27 | for(i = 1; i < NR_IRQS; i++) { | 25 | for (i = 1; i < NR_IRQS; i++) { |
| 26 | struct irq_desc *desc = irq_desc + i; | ||
| 28 | struct irqaction *action; | 27 | struct irqaction *action; |
| 29 | 28 | ||
| 30 | if (i == irq) /* Already tried */ | 29 | if (i == irq) /* Already tried */ |
| 31 | continue; | 30 | continue; |
| 32 | desc = &irq_desc[i]; | 31 | |
| 33 | spin_lock(&desc->lock); | 32 | spin_lock(&desc->lock); |
| 34 | action = desc->action; | ||
| 35 | /* Already running on another processor */ | 33 | /* Already running on another processor */ |
| 36 | if (desc->status & IRQ_INPROGRESS) { | 34 | if (desc->status & IRQ_INPROGRESS) { |
| 37 | /* | 35 | /* |
| 38 | * Already running: If it is shared get the other | 36 | * Already running: If it is shared get the other |
| 39 | * CPU to go looking for our mystery interrupt too | 37 | * CPU to go looking for our mystery interrupt too |
| 40 | */ | 38 | */ |
| 41 | if (desc->action && (desc->action->flags & SA_SHIRQ)) | 39 | if (desc->action && (desc->action->flags & IRQF_SHARED)) |
| 42 | desc->status |= IRQ_PENDING; | 40 | desc->status |= IRQ_PENDING; |
| 43 | spin_unlock(&desc->lock); | 41 | spin_unlock(&desc->lock); |
| 44 | continue; | 42 | continue; |
| 45 | } | 43 | } |
| 46 | /* Honour the normal IRQ locking */ | 44 | /* Honour the normal IRQ locking */ |
| 47 | desc->status |= IRQ_INPROGRESS; | 45 | desc->status |= IRQ_INPROGRESS; |
| 46 | action = desc->action; | ||
| 48 | spin_unlock(&desc->lock); | 47 | spin_unlock(&desc->lock); |
| 48 | |||
| 49 | while (action) { | 49 | while (action) { |
| 50 | /* Only shared IRQ handlers are safe to call */ | 50 | /* Only shared IRQ handlers are safe to call */ |
| 51 | if (action->flags & SA_SHIRQ) { | 51 | if (action->flags & IRQF_SHARED) { |
| 52 | if (action->handler(i, action->dev_id, regs) == | 52 | if (action->handler(i, action->dev_id, regs) == |
| 53 | IRQ_HANDLED) | 53 | IRQ_HANDLED) |
| 54 | ok = 1; | 54 | ok = 1; |
| @@ -62,9 +62,8 @@ static int misrouted_irq(int irq, struct pt_regs *regs) | |||
| 62 | 62 | ||
| 63 | /* | 63 | /* |
| 64 | * While we were looking for a fixup someone queued a real | 64 | * While we were looking for a fixup someone queued a real |
| 65 | * IRQ clashing with our walk | 65 | * IRQ clashing with our walk: |
| 66 | */ | 66 | */ |
| 67 | |||
| 68 | while ((desc->status & IRQ_PENDING) && action) { | 67 | while ((desc->status & IRQ_PENDING) && action) { |
| 69 | /* | 68 | /* |
| 70 | * Perform real IRQ processing for the IRQ we deferred | 69 | * Perform real IRQ processing for the IRQ we deferred |
| @@ -80,8 +79,8 @@ static int misrouted_irq(int irq, struct pt_regs *regs) | |||
| 80 | * If we did actual work for the real IRQ line we must let the | 79 | * If we did actual work for the real IRQ line we must let the |
| 81 | * IRQ controller clean up too | 80 | * IRQ controller clean up too |
| 82 | */ | 81 | */ |
| 83 | if(work) | 82 | if (work && desc->chip && desc->chip->end) |
| 84 | desc->handler->end(i); | 83 | desc->chip->end(i); |
| 85 | spin_unlock(&desc->lock); | 84 | spin_unlock(&desc->lock); |
| 86 | } | 85 | } |
| 87 | /* So the caller can adjust the irq error counts */ | 86 | /* So the caller can adjust the irq error counts */ |
| @@ -100,7 +99,8 @@ static int misrouted_irq(int irq, struct pt_regs *regs) | |||
| 100 | */ | 99 | */ |
| 101 | 100 | ||
| 102 | static void | 101 | static void |
| 103 | __report_bad_irq(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret) | 102 | __report_bad_irq(unsigned int irq, struct irq_desc *desc, |
| 103 | irqreturn_t action_ret) | ||
| 104 | { | 104 | { |
| 105 | struct irqaction *action; | 105 | struct irqaction *action; |
| 106 | 106 | ||
| @@ -113,6 +113,7 @@ __report_bad_irq(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret) | |||
| 113 | } | 113 | } |
| 114 | dump_stack(); | 114 | dump_stack(); |
| 115 | printk(KERN_ERR "handlers:\n"); | 115 | printk(KERN_ERR "handlers:\n"); |
| 116 | |||
| 116 | action = desc->action; | 117 | action = desc->action; |
| 117 | while (action) { | 118 | while (action) { |
| 118 | printk(KERN_ERR "[<%p>]", action->handler); | 119 | printk(KERN_ERR "[<%p>]", action->handler); |
| @@ -123,7 +124,8 @@ __report_bad_irq(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret) | |||
| 123 | } | 124 | } |
| 124 | } | 125 | } |
| 125 | 126 | ||
| 126 | static void report_bad_irq(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret) | 127 | static void |
| 128 | report_bad_irq(unsigned int irq, struct irq_desc *desc, irqreturn_t action_ret) | ||
| 127 | { | 129 | { |
| 128 | static int count = 100; | 130 | static int count = 100; |
| 129 | 131 | ||
| @@ -133,8 +135,8 @@ static void report_bad_irq(unsigned int irq, irq_desc_t *desc, irqreturn_t actio | |||
| 133 | } | 135 | } |
| 134 | } | 136 | } |
| 135 | 137 | ||
| 136 | void note_interrupt(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret, | 138 | void note_interrupt(unsigned int irq, struct irq_desc *desc, |
| 137 | struct pt_regs *regs) | 139 | irqreturn_t action_ret, struct pt_regs *regs) |
| 138 | { | 140 | { |
| 139 | if (unlikely(action_ret != IRQ_HANDLED)) { | 141 | if (unlikely(action_ret != IRQ_HANDLED)) { |
| 140 | desc->irqs_unhandled++; | 142 | desc->irqs_unhandled++; |
| @@ -166,7 +168,8 @@ void note_interrupt(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret, | |||
| 166 | */ | 168 | */ |
| 167 | printk(KERN_EMERG "Disabling IRQ #%d\n", irq); | 169 | printk(KERN_EMERG "Disabling IRQ #%d\n", irq); |
| 168 | desc->status |= IRQ_DISABLED; | 170 | desc->status |= IRQ_DISABLED; |
| 169 | desc->handler->disable(irq); | 171 | desc->depth = 1; |
| 172 | desc->chip->disable(irq); | ||
| 170 | } | 173 | } |
| 171 | desc->irqs_unhandled = 0; | 174 | desc->irqs_unhandled = 0; |
| 172 | } | 175 | } |
| @@ -177,6 +180,7 @@ int __init noirqdebug_setup(char *str) | |||
| 177 | { | 180 | { |
| 178 | noirqdebug = 1; | 181 | noirqdebug = 1; |
| 179 | printk(KERN_INFO "IRQ lockup detection disabled\n"); | 182 | printk(KERN_INFO "IRQ lockup detection disabled\n"); |
| 183 | |||
| 180 | return 1; | 184 | return 1; |
| 181 | } | 185 | } |
| 182 | 186 | ||
| @@ -187,6 +191,7 @@ static int __init irqfixup_setup(char *str) | |||
| 187 | irqfixup = 1; | 191 | irqfixup = 1; |
| 188 | printk(KERN_WARNING "Misrouted IRQ fixup support enabled.\n"); | 192 | printk(KERN_WARNING "Misrouted IRQ fixup support enabled.\n"); |
| 189 | printk(KERN_WARNING "This may impact system performance.\n"); | 193 | printk(KERN_WARNING "This may impact system performance.\n"); |
| 194 | |||
| 190 | return 1; | 195 | return 1; |
| 191 | } | 196 | } |
| 192 | 197 | ||
