diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2011-02-07 15:48:49 -0500 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2011-02-19 06:58:16 -0500 |
commit | 009b4c3b8ad584b3462734127a5bec680d5d6af4 (patch) | |
tree | f7cb860dde86ba96afcc085ec7a75ca2a41e49b6 | |
parent | 6954b75b488dd740950573f244ddd66fd28620aa (diff) |
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>
-rw-r--r-- | include/linux/irq.h | 6 | ||||
-rw-r--r-- | kernel/irq/Kconfig | 3 | ||||
-rw-r--r-- | kernel/irq/chip.c | 16 | ||||
-rw-r--r-- | kernel/irq/compat.h | 17 | ||||
-rw-r--r-- | kernel/irq/handle.c | 6 | ||||
-rw-r--r-- | kernel/irq/internals.h | 5 | ||||
-rw-r--r-- | kernel/irq/manage.c | 17 | ||||
-rw-r--r-- | kernel/irq/settings.h | 3 | ||||
-rw-r--r-- | kernel/irq/spurious.c | 6 |
9 files changed, 57 insertions, 22 deletions
diff --git a/include/linux/irq.h b/include/linux/irq.h index 047a695511df..274590fc55a3 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h | |||
@@ -50,7 +50,11 @@ typedef void (*irq_flow_handler_t)(unsigned int irq, | |||
50 | #define IRQ_TYPE_PROBE 0x00000010 /* Probing in progress */ | 50 | #define IRQ_TYPE_PROBE 0x00000010 /* Probing in progress */ |
51 | 51 | ||
52 | /* Internal flags */ | 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 | #define IRQ_DISABLED 0x00000200 /* IRQ disabled - do not enter! */ | 58 | #define IRQ_DISABLED 0x00000200 /* IRQ disabled - do not enter! */ |
55 | #define IRQ_PENDING 0x00000400 /* IRQ pending - replay on enable */ | 59 | #define IRQ_PENDING 0x00000400 /* IRQ pending - replay on enable */ |
56 | #define IRQ_REPLAY 0x00000800 /* IRQ has been replayed but not acked yet */ | 60 | #define IRQ_REPLAY 0x00000800 /* IRQ has been replayed but not acked yet */ |
diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig index 4cd5d7135e0f..9e2256de1d1a 100644 --- a/kernel/irq/Kconfig +++ b/kernel/irq/Kconfig | |||
@@ -13,6 +13,9 @@ config GENERIC_HARDIRQS | |||
13 | config GENERIC_HARDIRQS_NO_DEPRECATED | 13 | config GENERIC_HARDIRQS_NO_DEPRECATED |
14 | def_bool n | 14 | def_bool n |
15 | 15 | ||
16 | config GENERIC_HARDIRQS_NO_COMPAT | ||
17 | def_bool n | ||
18 | |||
16 | # Options selectable by the architecture code | 19 | # Options selectable by the architecture code |
17 | config HAVE_SPARSE_IRQ | 20 | config HAVE_SPARSE_IRQ |
18 | def_bool n | 21 | def_bool n |
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 34245e7d1213..075385549dcd 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c | |||
@@ -383,7 +383,8 @@ void handle_nested_irq(unsigned int irq) | |||
383 | if (unlikely(!action || (desc->status & IRQ_DISABLED))) | 383 | if (unlikely(!action || (desc->status & IRQ_DISABLED))) |
384 | goto out_unlock; | 384 | goto out_unlock; |
385 | 385 | ||
386 | desc->status |= IRQ_INPROGRESS; | 386 | irq_compat_set_progress(desc); |
387 | desc->istate |= IRQS_INPROGRESS; | ||
387 | raw_spin_unlock_irq(&desc->lock); | 388 | raw_spin_unlock_irq(&desc->lock); |
388 | 389 | ||
389 | action_ret = action->thread_fn(action->irq, action->dev_id); | 390 | action_ret = action->thread_fn(action->irq, action->dev_id); |
@@ -391,7 +392,8 @@ void handle_nested_irq(unsigned int irq) | |||
391 | note_interrupt(irq, desc, action_ret); | 392 | note_interrupt(irq, desc, action_ret); |
392 | 393 | ||
393 | raw_spin_lock_irq(&desc->lock); | 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 | out_unlock: | 398 | out_unlock: |
397 | raw_spin_unlock_irq(&desc->lock); | 399 | raw_spin_unlock_irq(&desc->lock); |
@@ -422,7 +424,7 @@ handle_simple_irq(unsigned int irq, struct irq_desc *desc) | |||
422 | { | 424 | { |
423 | raw_spin_lock(&desc->lock); | 425 | raw_spin_lock(&desc->lock); |
424 | 426 | ||
425 | if (unlikely(desc->status & IRQ_INPROGRESS)) | 427 | if (unlikely(desc->istate & IRQS_INPROGRESS)) |
426 | if (!irq_check_poll(desc)) | 428 | if (!irq_check_poll(desc)) |
427 | goto out_unlock; | 429 | goto out_unlock; |
428 | 430 | ||
@@ -454,7 +456,7 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc) | |||
454 | raw_spin_lock(&desc->lock); | 456 | raw_spin_lock(&desc->lock); |
455 | mask_ack_irq(desc); | 457 | mask_ack_irq(desc); |
456 | 458 | ||
457 | if (unlikely(desc->status & IRQ_INPROGRESS)) | 459 | if (unlikely(desc->istate & IRQS_INPROGRESS)) |
458 | if (!irq_check_poll(desc)) | 460 | if (!irq_check_poll(desc)) |
459 | goto out_unlock; | 461 | goto out_unlock; |
460 | 462 | ||
@@ -492,7 +494,7 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc) | |||
492 | { | 494 | { |
493 | raw_spin_lock(&desc->lock); | 495 | raw_spin_lock(&desc->lock); |
494 | 496 | ||
495 | if (unlikely(desc->status & IRQ_INPROGRESS)) | 497 | if (unlikely(desc->istate & IRQS_INPROGRESS)) |
496 | if (!irq_check_poll(desc)) | 498 | if (!irq_check_poll(desc)) |
497 | goto out; | 499 | goto out; |
498 | 500 | ||
@@ -542,8 +544,8 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc) | |||
542 | * we shouldn't process the IRQ. Mark it pending, handle | 544 | * we shouldn't process the IRQ. Mark it pending, handle |
543 | * the necessary masking and go out | 545 | * the necessary masking and go out |
544 | */ | 546 | */ |
545 | if (unlikely((desc->status & (IRQ_INPROGRESS | IRQ_DISABLED)) || | 547 | if (unlikely((desc->istate & (IRQS_INPROGRESS) || |
546 | !desc->action)) { | 548 | (desc->status & IRQ_DISABLED) || !desc->action))) { |
547 | if (!irq_check_poll(desc)) { | 549 | if (!irq_check_poll(desc)) { |
548 | desc->status |= IRQ_PENDING; | 550 | desc->status |= IRQ_PENDING; |
549 | mask_ack_irq(desc); | 551 | mask_ack_irq(desc); |
diff --git a/kernel/irq/compat.h b/kernel/irq/compat.h new file mode 100644 index 000000000000..aac6e400e608 --- /dev/null +++ b/kernel/irq/compat.h | |||
@@ -0,0 +1,17 @@ | |||
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 | ||
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index ff40e0f5e2e2..d4ae0b1ccc00 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c | |||
@@ -123,13 +123,15 @@ irqreturn_t handle_irq_event(struct irq_desc *desc) | |||
123 | irqreturn_t ret; | 123 | irqreturn_t ret; |
124 | 124 | ||
125 | desc->status &= ~IRQ_PENDING; | 125 | desc->status &= ~IRQ_PENDING; |
126 | desc->status |= IRQ_INPROGRESS; | 126 | irq_compat_set_progress(desc); |
127 | desc->istate |= IRQS_INPROGRESS; | ||
127 | raw_spin_unlock(&desc->lock); | 128 | raw_spin_unlock(&desc->lock); |
128 | 129 | ||
129 | ret = handle_irq_event_percpu(desc, action); | 130 | ret = handle_irq_event_percpu(desc, action); |
130 | 131 | ||
131 | raw_spin_lock(&desc->lock); | 132 | raw_spin_lock(&desc->lock); |
132 | desc->status &= ~IRQ_INPROGRESS; | 133 | desc->istate &= ~IRQS_INPROGRESS; |
134 | irq_compat_clr_progress(desc); | ||
133 | return ret; | 135 | return ret; |
134 | } | 136 | } |
135 | 137 | ||
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h index f5d28e1e1eda..d1cb1f8df6fe 100644 --- a/kernel/irq/internals.h +++ b/kernel/irq/internals.h | |||
@@ -13,6 +13,7 @@ | |||
13 | # define IRQ_BITMAP_BITS NR_IRQS | 13 | # define IRQ_BITMAP_BITS NR_IRQS |
14 | #endif | 14 | #endif |
15 | 15 | ||
16 | #include "compat.h" | ||
16 | #include "settings.h" | 17 | #include "settings.h" |
17 | 18 | ||
18 | #define istate core_internal_state__do_not_mess_with_it | 19 | #define istate core_internal_state__do_not_mess_with_it |
@@ -40,11 +41,13 @@ enum { | |||
40 | * IRQS_SPURIOUS_DISABLED - was disabled due to spurious interrupt | 41 | * IRQS_SPURIOUS_DISABLED - was disabled due to spurious interrupt |
41 | * detection | 42 | * detection |
42 | * IRQS_POLL_INPROGRESS - polling in progress | 43 | * IRQS_POLL_INPROGRESS - polling in progress |
44 | * IRQS_INPROGRESS - Interrupt in progress | ||
43 | */ | 45 | */ |
44 | enum { | 46 | enum { |
45 | IRQS_AUTODETECT = 0x00000001, | 47 | IRQS_AUTODETECT = 0x00000001, |
46 | IRQS_SPURIOUS_DISABLED = 0x00000002, | 48 | IRQS_SPURIOUS_DISABLED = 0x00000002, |
47 | IRQS_POLL_INPROGRESS = 0x00000008, | 49 | IRQS_POLL_INPROGRESS = 0x00000008, |
50 | IRQS_INPROGRESS = 0x00000010, | ||
48 | }; | 51 | }; |
49 | 52 | ||
50 | #define irq_data_to_desc(data) container_of(data, struct irq_desc, irq_data) | 53 | #define irq_data_to_desc(data) container_of(data, struct irq_desc, irq_data) |
@@ -128,7 +131,6 @@ static inline void print_irq_desc(unsigned int irq, struct irq_desc *desc) | |||
128 | print_symbol("%s\n", (unsigned long)desc->action->handler); | 131 | print_symbol("%s\n", (unsigned long)desc->action->handler); |
129 | } | 132 | } |
130 | 133 | ||
131 | P(IRQ_INPROGRESS); | ||
132 | P(IRQ_DISABLED); | 134 | P(IRQ_DISABLED); |
133 | P(IRQ_PENDING); | 135 | P(IRQ_PENDING); |
134 | P(IRQ_REPLAY); | 136 | P(IRQ_REPLAY); |
@@ -143,6 +145,7 @@ static inline void print_irq_desc(unsigned int irq, struct irq_desc *desc) | |||
143 | P(IRQ_NOAUTOEN); | 145 | P(IRQ_NOAUTOEN); |
144 | 146 | ||
145 | PS(IRQS_AUTODETECT); | 147 | PS(IRQS_AUTODETECT); |
148 | PS(IRQS_INPROGRESS); | ||
146 | } | 149 | } |
147 | 150 | ||
148 | #undef P | 151 | #undef P |
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 5b918ffa46af..7e5a50825088 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
@@ -30,7 +30,7 @@ | |||
30 | void synchronize_irq(unsigned int irq) | 30 | void synchronize_irq(unsigned int irq) |
31 | { | 31 | { |
32 | struct irq_desc *desc = irq_to_desc(irq); | 32 | struct irq_desc *desc = irq_to_desc(irq); |
33 | unsigned int status; | 33 | unsigned int state; |
34 | 34 | ||
35 | if (!desc) | 35 | if (!desc) |
36 | return; | 36 | return; |
@@ -42,16 +42,16 @@ void synchronize_irq(unsigned int irq) | |||
42 | * Wait until we're out of the critical section. This might | 42 | * Wait until we're out of the critical section. This might |
43 | * give the wrong answer due to the lack of memory barriers. | 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 | cpu_relax(); | 46 | cpu_relax(); |
47 | 47 | ||
48 | /* Ok, that indicated we're done: double-check carefully. */ | 48 | /* Ok, that indicated we're done: double-check carefully. */ |
49 | raw_spin_lock_irqsave(&desc->lock, flags); | 49 | raw_spin_lock_irqsave(&desc->lock, flags); |
50 | status = desc->status; | 50 | state = desc->istate; |
51 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 51 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
52 | 52 | ||
53 | /* Oops, that failed? */ | 53 | /* Oops, that failed? */ |
54 | } while (status & IRQ_INPROGRESS); | 54 | } while (state & IRQS_INPROGRESS); |
55 | 55 | ||
56 | /* | 56 | /* |
57 | * We made sure that no hardirq handler is running. Now verify | 57 | * We made sure that no hardirq handler is running. Now verify |
@@ -637,9 +637,9 @@ again: | |||
637 | * The thread is faster done than the hard interrupt handler | 637 | * The thread is faster done than the hard interrupt handler |
638 | * on the other CPU. If we unmask the irq line then the | 638 | * on the other CPU. If we unmask the irq line then the |
639 | * interrupt can come in again and masks the line, leaves due | 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 | raw_spin_unlock_irq(&desc->lock); | 643 | raw_spin_unlock_irq(&desc->lock); |
644 | chip_bus_sync_unlock(desc); | 644 | chip_bus_sync_unlock(desc); |
645 | cpu_relax(); | 645 | cpu_relax(); |
@@ -897,8 +897,9 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) | |||
897 | desc->status |= IRQ_PER_CPU; | 897 | desc->status |= IRQ_PER_CPU; |
898 | #endif | 898 | #endif |
899 | 899 | ||
900 | desc->status &= ~(IRQ_WAITING | IRQ_ONESHOT | IRQ_INPROGRESS); | 900 | desc->status &= ~(IRQ_WAITING | IRQ_ONESHOT); |
901 | desc->istate &= ~(IRQS_AUTODETECT | IRQS_SPURIOUS_DISABLED); | 901 | desc->istate &= ~(IRQS_AUTODETECT | IRQS_SPURIOUS_DISABLED | \ |
902 | IRQS_INPROGRESS); | ||
902 | 903 | ||
903 | if (new->flags & IRQF_ONESHOT) | 904 | if (new->flags & IRQF_ONESHOT) |
904 | desc->status |= IRQ_ONESHOT; | 905 | desc->status |= IRQ_ONESHOT; |
diff --git a/kernel/irq/settings.h b/kernel/irq/settings.h index 610f55597ce7..a96140eea409 100644 --- a/kernel/irq/settings.h +++ b/kernel/irq/settings.h | |||
@@ -5,3 +5,6 @@ | |||
5 | enum { | 5 | enum { |
6 | _IRQ_DEFAULT_INIT_FLAGS = IRQ_DEFAULT_INIT_FLAGS, | 6 | _IRQ_DEFAULT_INIT_FLAGS = IRQ_DEFAULT_INIT_FLAGS, |
7 | }; | 7 | }; |
8 | |||
9 | #undef IRQ_INPROGRESS | ||
10 | #define IRQ_INPROGRESS GOT_YOU_MORON | ||
diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c index 21c46178b1a6..51504837d8cc 100644 --- a/kernel/irq/spurious.c +++ b/kernel/irq/spurious.c | |||
@@ -45,10 +45,10 @@ bool irq_wait_for_poll(struct irq_desc *desc) | |||
45 | #ifdef CONFIG_SMP | 45 | #ifdef CONFIG_SMP |
46 | do { | 46 | do { |
47 | raw_spin_unlock(&desc->lock); | 47 | raw_spin_unlock(&desc->lock); |
48 | while (desc->status & IRQ_INPROGRESS) | 48 | while (desc->istate & IRQS_INPROGRESS) |
49 | cpu_relax(); | 49 | cpu_relax(); |
50 | raw_spin_lock(&desc->lock); | 50 | raw_spin_lock(&desc->lock); |
51 | } while (desc->status & IRQ_INPROGRESS); | 51 | } while (desc->istate & IRQS_INPROGRESS); |
52 | /* Might have been disabled in meantime */ | 52 | /* Might have been disabled in meantime */ |
53 | return !(desc->status & IRQ_DISABLED) && desc->action; | 53 | return !(desc->status & IRQ_DISABLED) && desc->action; |
54 | #else | 54 | #else |
@@ -88,7 +88,7 @@ static int try_one_irq(int irq, struct irq_desc *desc, bool force) | |||
88 | goto out; | 88 | goto out; |
89 | 89 | ||
90 | /* Already running on another processor */ | 90 | /* Already running on another processor */ |
91 | if (desc->status & IRQ_INPROGRESS) { | 91 | if (desc->istate & IRQS_INPROGRESS) { |
92 | /* | 92 | /* |
93 | * Already running: If it is shared get the other | 93 | * Already running: If it is shared get the other |
94 | * CPU to go looking for our mystery interrupt too | 94 | * CPU to go looking for our mystery interrupt too |