Commit 009b4c3b8ad584b3462734127a5bec680d5d6af4
1 parent
6954b75b48
Exists in
master
and in
20 other branches
genirq: Add IRQ_INPROGRESS to core
We need to maintain the flag for now in both fields status and istate. Add a CONFIG_GENERIC_HARDIRQS_NO_COMPAT switch to allow testing w/o the status one. Wrap the access to status IRQ_INPROGRESS in a inline which can be turned of with CONFIG_GENERIC_HARDIRQS_NO_COMPAT along with the define. There is no reason that anything outside of core looks at this. That needs some modifications, but we'll get there. Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Showing 9 changed files with 57 additions and 22 deletions Side-by-side Diff
include/linux/irq.h
... | ... | @@ -50,7 +50,11 @@ |
50 | 50 | #define IRQ_TYPE_PROBE 0x00000010 /* Probing in progress */ |
51 | 51 | |
52 | 52 | /* Internal flags */ |
53 | -#define IRQ_INPROGRESS 0x00000100 /* IRQ handler active - do not enter! */ | |
53 | + | |
54 | +#ifndef CONFIG_GENERIC_HARDIRQS_NO_COMPAT | |
55 | +#define IRQ_INPROGRESS 0x00000100 /* DEPRECATED */ | |
56 | +#endif | |
57 | + | |
54 | 58 | #define IRQ_DISABLED 0x00000200 /* IRQ disabled - do not enter! */ |
55 | 59 | #define IRQ_PENDING 0x00000400 /* IRQ pending - replay on enable */ |
56 | 60 | #define IRQ_REPLAY 0x00000800 /* IRQ has been replayed but not acked yet */ |
kernel/irq/Kconfig
kernel/irq/chip.c
... | ... | @@ -383,7 +383,8 @@ |
383 | 383 | if (unlikely(!action || (desc->status & IRQ_DISABLED))) |
384 | 384 | goto out_unlock; |
385 | 385 | |
386 | - desc->status |= IRQ_INPROGRESS; | |
386 | + irq_compat_set_progress(desc); | |
387 | + desc->istate |= IRQS_INPROGRESS; | |
387 | 388 | raw_spin_unlock_irq(&desc->lock); |
388 | 389 | |
389 | 390 | action_ret = action->thread_fn(action->irq, action->dev_id); |
... | ... | @@ -391,7 +392,8 @@ |
391 | 392 | note_interrupt(irq, desc, action_ret); |
392 | 393 | |
393 | 394 | raw_spin_lock_irq(&desc->lock); |
394 | - desc->status &= ~IRQ_INPROGRESS; | |
395 | + desc->istate &= ~IRQS_INPROGRESS; | |
396 | + irq_compat_clr_progress(desc); | |
395 | 397 | |
396 | 398 | out_unlock: |
397 | 399 | raw_spin_unlock_irq(&desc->lock); |
... | ... | @@ -422,7 +424,7 @@ |
422 | 424 | { |
423 | 425 | raw_spin_lock(&desc->lock); |
424 | 426 | |
425 | - if (unlikely(desc->status & IRQ_INPROGRESS)) | |
427 | + if (unlikely(desc->istate & IRQS_INPROGRESS)) | |
426 | 428 | if (!irq_check_poll(desc)) |
427 | 429 | goto out_unlock; |
428 | 430 | |
... | ... | @@ -454,7 +456,7 @@ |
454 | 456 | raw_spin_lock(&desc->lock); |
455 | 457 | mask_ack_irq(desc); |
456 | 458 | |
457 | - if (unlikely(desc->status & IRQ_INPROGRESS)) | |
459 | + if (unlikely(desc->istate & IRQS_INPROGRESS)) | |
458 | 460 | if (!irq_check_poll(desc)) |
459 | 461 | goto out_unlock; |
460 | 462 | |
... | ... | @@ -492,7 +494,7 @@ |
492 | 494 | { |
493 | 495 | raw_spin_lock(&desc->lock); |
494 | 496 | |
495 | - if (unlikely(desc->status & IRQ_INPROGRESS)) | |
497 | + if (unlikely(desc->istate & IRQS_INPROGRESS)) | |
496 | 498 | if (!irq_check_poll(desc)) |
497 | 499 | goto out; |
498 | 500 | |
... | ... | @@ -542,8 +544,8 @@ |
542 | 544 | * we shouldn't process the IRQ. Mark it pending, handle |
543 | 545 | * the necessary masking and go out |
544 | 546 | */ |
545 | - if (unlikely((desc->status & (IRQ_INPROGRESS | IRQ_DISABLED)) || | |
546 | - !desc->action)) { | |
547 | + if (unlikely((desc->istate & (IRQS_INPROGRESS) || | |
548 | + (desc->status & IRQ_DISABLED) || !desc->action))) { | |
547 | 549 | if (!irq_check_poll(desc)) { |
548 | 550 | desc->status |= IRQ_PENDING; |
549 | 551 | mask_ack_irq(desc); |
kernel/irq/compat.h
1 | +/* | |
2 | + * Compat layer for transition period | |
3 | + */ | |
4 | +#ifndef CONFIG_GENERIC_HARDIRQS_NO_COMPAT | |
5 | +static inline void irq_compat_set_progress(struct irq_desc *desc) | |
6 | +{ | |
7 | + desc->status |= IRQ_INPROGRESS; | |
8 | +} | |
9 | + | |
10 | +static inline void irq_compat_clr_progress(struct irq_desc *desc) | |
11 | +{ | |
12 | + desc->status &= ~IRQ_INPROGRESS; | |
13 | +} | |
14 | +#else | |
15 | +static inline void irq_compat_set_progress(struct irq_desc *desc) { } | |
16 | +static inline void irq_compat_clr_progress(struct irq_desc *desc) { } | |
17 | +#endif |
kernel/irq/handle.c
... | ... | @@ -123,13 +123,15 @@ |
123 | 123 | irqreturn_t ret; |
124 | 124 | |
125 | 125 | desc->status &= ~IRQ_PENDING; |
126 | - desc->status |= IRQ_INPROGRESS; | |
126 | + irq_compat_set_progress(desc); | |
127 | + desc->istate |= IRQS_INPROGRESS; | |
127 | 128 | raw_spin_unlock(&desc->lock); |
128 | 129 | |
129 | 130 | ret = handle_irq_event_percpu(desc, action); |
130 | 131 | |
131 | 132 | raw_spin_lock(&desc->lock); |
132 | - desc->status &= ~IRQ_INPROGRESS; | |
133 | + desc->istate &= ~IRQS_INPROGRESS; | |
134 | + irq_compat_clr_progress(desc); | |
133 | 135 | return ret; |
134 | 136 | } |
135 | 137 |
kernel/irq/internals.h
... | ... | @@ -13,6 +13,7 @@ |
13 | 13 | # define IRQ_BITMAP_BITS NR_IRQS |
14 | 14 | #endif |
15 | 15 | |
16 | +#include "compat.h" | |
16 | 17 | #include "settings.h" |
17 | 18 | |
18 | 19 | #define istate core_internal_state__do_not_mess_with_it |
19 | 20 | |
... | ... | @@ -40,11 +41,13 @@ |
40 | 41 | * IRQS_SPURIOUS_DISABLED - was disabled due to spurious interrupt |
41 | 42 | * detection |
42 | 43 | * IRQS_POLL_INPROGRESS - polling in progress |
44 | + * IRQS_INPROGRESS - Interrupt in progress | |
43 | 45 | */ |
44 | 46 | enum { |
45 | 47 | IRQS_AUTODETECT = 0x00000001, |
46 | 48 | IRQS_SPURIOUS_DISABLED = 0x00000002, |
47 | 49 | IRQS_POLL_INPROGRESS = 0x00000008, |
50 | + IRQS_INPROGRESS = 0x00000010, | |
48 | 51 | }; |
49 | 52 | |
50 | 53 | #define irq_data_to_desc(data) container_of(data, struct irq_desc, irq_data) |
... | ... | @@ -128,7 +131,6 @@ |
128 | 131 | print_symbol("%s\n", (unsigned long)desc->action->handler); |
129 | 132 | } |
130 | 133 | |
131 | - P(IRQ_INPROGRESS); | |
132 | 134 | P(IRQ_DISABLED); |
133 | 135 | P(IRQ_PENDING); |
134 | 136 | P(IRQ_REPLAY); |
... | ... | @@ -143,6 +145,7 @@ |
143 | 145 | P(IRQ_NOAUTOEN); |
144 | 146 | |
145 | 147 | PS(IRQS_AUTODETECT); |
148 | + PS(IRQS_INPROGRESS); | |
146 | 149 | } |
147 | 150 | |
148 | 151 | #undef P |
kernel/irq/manage.c
... | ... | @@ -30,7 +30,7 @@ |
30 | 30 | void synchronize_irq(unsigned int irq) |
31 | 31 | { |
32 | 32 | struct irq_desc *desc = irq_to_desc(irq); |
33 | - unsigned int status; | |
33 | + unsigned int state; | |
34 | 34 | |
35 | 35 | if (!desc) |
36 | 36 | return; |
37 | 37 | |
38 | 38 | |
... | ... | @@ -42,16 +42,16 @@ |
42 | 42 | * Wait until we're out of the critical section. This might |
43 | 43 | * give the wrong answer due to the lack of memory barriers. |
44 | 44 | */ |
45 | - while (desc->status & IRQ_INPROGRESS) | |
45 | + while (desc->istate & IRQS_INPROGRESS) | |
46 | 46 | cpu_relax(); |
47 | 47 | |
48 | 48 | /* Ok, that indicated we're done: double-check carefully. */ |
49 | 49 | raw_spin_lock_irqsave(&desc->lock, flags); |
50 | - status = desc->status; | |
50 | + state = desc->istate; | |
51 | 51 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
52 | 52 | |
53 | 53 | /* Oops, that failed? */ |
54 | - } while (status & IRQ_INPROGRESS); | |
54 | + } while (state & IRQS_INPROGRESS); | |
55 | 55 | |
56 | 56 | /* |
57 | 57 | * We made sure that no hardirq handler is running. Now verify |
58 | 58 | |
... | ... | @@ -637,9 +637,9 @@ |
637 | 637 | * The thread is faster done than the hard interrupt handler |
638 | 638 | * on the other CPU. If we unmask the irq line then the |
639 | 639 | * interrupt can come in again and masks the line, leaves due |
640 | - * to IRQ_INPROGRESS and the irq line is masked forever. | |
640 | + * to IRQS_INPROGRESS and the irq line is masked forever. | |
641 | 641 | */ |
642 | - if (unlikely(desc->status & IRQ_INPROGRESS)) { | |
642 | + if (unlikely(desc->istate & IRQS_INPROGRESS)) { | |
643 | 643 | raw_spin_unlock_irq(&desc->lock); |
644 | 644 | chip_bus_sync_unlock(desc); |
645 | 645 | cpu_relax(); |
... | ... | @@ -897,8 +897,9 @@ |
897 | 897 | desc->status |= IRQ_PER_CPU; |
898 | 898 | #endif |
899 | 899 | |
900 | - desc->status &= ~(IRQ_WAITING | IRQ_ONESHOT | IRQ_INPROGRESS); | |
901 | - desc->istate &= ~(IRQS_AUTODETECT | IRQS_SPURIOUS_DISABLED); | |
900 | + desc->status &= ~(IRQ_WAITING | IRQ_ONESHOT); | |
901 | + desc->istate &= ~(IRQS_AUTODETECT | IRQS_SPURIOUS_DISABLED | \ | |
902 | + IRQS_INPROGRESS); | |
902 | 903 | |
903 | 904 | if (new->flags & IRQF_ONESHOT) |
904 | 905 | desc->status |= IRQ_ONESHOT; |
kernel/irq/settings.h
kernel/irq/spurious.c
... | ... | @@ -45,10 +45,10 @@ |
45 | 45 | #ifdef CONFIG_SMP |
46 | 46 | do { |
47 | 47 | raw_spin_unlock(&desc->lock); |
48 | - while (desc->status & IRQ_INPROGRESS) | |
48 | + while (desc->istate & IRQS_INPROGRESS) | |
49 | 49 | cpu_relax(); |
50 | 50 | raw_spin_lock(&desc->lock); |
51 | - } while (desc->status & IRQ_INPROGRESS); | |
51 | + } while (desc->istate & IRQS_INPROGRESS); | |
52 | 52 | /* Might have been disabled in meantime */ |
53 | 53 | return !(desc->status & IRQ_DISABLED) && desc->action; |
54 | 54 | #else |
... | ... | @@ -88,7 +88,7 @@ |
88 | 88 | goto out; |
89 | 89 | |
90 | 90 | /* Already running on another processor */ |
91 | - if (desc->status & IRQ_INPROGRESS) { | |
91 | + if (desc->istate & IRQS_INPROGRESS) { | |
92 | 92 | /* |
93 | 93 | * Already running: If it is shared get the other |
94 | 94 | * CPU to go looking for our mystery interrupt too |