diff options
-rw-r--r-- | include/linux/irq.h | 16 | ||||
-rw-r--r-- | kernel/irq/chip.c | 15 | ||||
-rw-r--r-- | kernel/irq/internals.h | 11 | ||||
-rw-r--r-- | kernel/irq/manage.c | 16 | ||||
-rw-r--r-- | kernel/irq/migration.c | 2 | ||||
-rw-r--r-- | kernel/irq/settings.h | 36 | ||||
-rw-r--r-- | kernel/irq/spurious.c | 3 |
7 files changed, 84 insertions, 15 deletions
diff --git a/include/linux/irq.h b/include/linux/irq.h index 3f607ad94220..d5312e6fe1aa 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h | |||
@@ -132,10 +132,14 @@ struct irq_data { | |||
132 | * Bit masks for irq_data.state | 132 | * Bit masks for irq_data.state |
133 | * | 133 | * |
134 | * IRQD_SETAFFINITY_PENDING - Affinity setting is pending | 134 | * IRQD_SETAFFINITY_PENDING - Affinity setting is pending |
135 | * IRQD_NO_BALANCING - Balancing disabled for this IRQ | ||
136 | * IRQD_PER_CPU - Interrupt is per cpu | ||
135 | */ | 137 | */ |
136 | enum { | 138 | enum { |
137 | /* Bit 0 - 7 reserved for TYPE will use later */ | 139 | /* Bit 0 - 7 reserved for TYPE will use later */ |
138 | IRQD_SETAFFINITY_PENDING = (1 << 8), | 140 | IRQD_SETAFFINITY_PENDING = (1 << 8), |
141 | IRQD_NO_BALANCING = (1 << 10), | ||
142 | IRQD_PER_CPU = (1 << 11), | ||
139 | }; | 143 | }; |
140 | 144 | ||
141 | static inline bool irqd_is_setaffinity_pending(struct irq_data *d) | 145 | static inline bool irqd_is_setaffinity_pending(struct irq_data *d) |
@@ -143,6 +147,16 @@ static inline bool irqd_is_setaffinity_pending(struct irq_data *d) | |||
143 | return d->state_use_accessors & IRQD_SETAFFINITY_PENDING; | 147 | return d->state_use_accessors & IRQD_SETAFFINITY_PENDING; |
144 | } | 148 | } |
145 | 149 | ||
150 | static inline bool irqd_is_per_cpu(struct irq_data *d) | ||
151 | { | ||
152 | return d->state_use_accessors & IRQD_PER_CPU; | ||
153 | } | ||
154 | |||
155 | static inline bool irqd_can_balance(struct irq_data *d) | ||
156 | { | ||
157 | return !(d->state_use_accessors & (IRQD_PER_CPU | IRQD_NO_BALANCING)); | ||
158 | } | ||
159 | |||
146 | /** | 160 | /** |
147 | * struct irq_chip - hardware interrupt chip descriptor | 161 | * struct irq_chip - hardware interrupt chip descriptor |
148 | * | 162 | * |
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 73b2e7e00934..b8aa3dfe8301 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c | |||
@@ -706,12 +706,15 @@ void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set) | |||
706 | if (!desc) | 706 | if (!desc) |
707 | return; | 707 | return; |
708 | 708 | ||
709 | /* Sanitize flags */ | ||
710 | set &= IRQF_MODIFY_MASK; | ||
711 | clr &= IRQF_MODIFY_MASK; | ||
712 | |||
713 | raw_spin_lock_irqsave(&desc->lock, flags); | 709 | raw_spin_lock_irqsave(&desc->lock, flags); |
714 | desc->status &= ~clr; | 710 | |
715 | desc->status |= set; | 711 | irq_settings_clr_and_set(desc, clr, set); |
712 | |||
713 | irqd_clear(&desc->irq_data, IRQD_NO_BALANCING | IRQD_PER_CPU); | ||
714 | if (irq_settings_has_no_balance_set(desc)) | ||
715 | irqd_set(&desc->irq_data, IRQD_NO_BALANCING); | ||
716 | if (irq_settings_is_per_cpu(desc)) | ||
717 | irqd_set(&desc->irq_data, IRQD_PER_CPU); | ||
718 | |||
716 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 719 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
717 | } | 720 | } |
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h index b2ba59e73f21..a80b44d2735e 100644 --- a/kernel/irq/internals.h +++ b/kernel/irq/internals.h | |||
@@ -139,3 +139,14 @@ static inline void irqd_clr_move_pending(struct irq_data *d) | |||
139 | d->state_use_accessors &= ~IRQD_SETAFFINITY_PENDING; | 139 | d->state_use_accessors &= ~IRQD_SETAFFINITY_PENDING; |
140 | irq_compat_clr_move_pending(irq_data_to_desc(d)); | 140 | irq_compat_clr_move_pending(irq_data_to_desc(d)); |
141 | } | 141 | } |
142 | |||
143 | static inline void irqd_clear(struct irq_data *d, unsigned int mask) | ||
144 | { | ||
145 | d->state_use_accessors &= ~mask; | ||
146 | } | ||
147 | |||
148 | static inline void irqd_set(struct irq_data *d, unsigned int mask) | ||
149 | { | ||
150 | d->state_use_accessors |= mask; | ||
151 | } | ||
152 | |||
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index f1cfa271ba70..84a0a9c22226 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
@@ -73,8 +73,8 @@ int irq_can_set_affinity(unsigned int irq) | |||
73 | { | 73 | { |
74 | struct irq_desc *desc = irq_to_desc(irq); | 74 | struct irq_desc *desc = irq_to_desc(irq); |
75 | 75 | ||
76 | if ((desc->status & (IRQ_PER_CPU | IRQ_NO_BALANCING)) || | 76 | if (!irqd_can_balance(&desc->irq_data) || !desc->irq_data.chip || |
77 | !desc->irq_data.chip || !desc->irq_data.chip->irq_set_affinity) | 77 | !desc->irq_data.chip->irq_set_affinity) |
78 | return 0; | 78 | return 0; |
79 | 79 | ||
80 | return 1; | 80 | return 1; |
@@ -897,8 +897,10 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) | |||
897 | IRQS_INPROGRESS | IRQS_ONESHOT | \ | 897 | IRQS_INPROGRESS | IRQS_ONESHOT | \ |
898 | IRQS_WAITING); | 898 | IRQS_WAITING); |
899 | 899 | ||
900 | if (new->flags & IRQF_PERCPU) | 900 | if (new->flags & IRQF_PERCPU) { |
901 | desc->status |= IRQ_PER_CPU; | 901 | irqd_set(&desc->irq_data, IRQD_PER_CPU); |
902 | irq_settings_set_per_cpu(desc); | ||
903 | } | ||
902 | 904 | ||
903 | if (new->flags & IRQF_ONESHOT) | 905 | if (new->flags & IRQF_ONESHOT) |
904 | desc->istate |= IRQS_ONESHOT; | 906 | desc->istate |= IRQS_ONESHOT; |
@@ -910,8 +912,10 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) | |||
910 | desc->depth = 1; | 912 | desc->depth = 1; |
911 | 913 | ||
912 | /* Exclude IRQ from balancing if requested */ | 914 | /* Exclude IRQ from balancing if requested */ |
913 | if (new->flags & IRQF_NOBALANCING) | 915 | if (new->flags & IRQF_NOBALANCING) { |
914 | desc->status |= IRQ_NO_BALANCING; | 916 | irq_settings_set_no_balancing(desc); |
917 | irqd_set(&desc->irq_data, IRQD_NO_BALANCING); | ||
918 | } | ||
915 | 919 | ||
916 | /* Set default affinity mask once everything is setup */ | 920 | /* Set default affinity mask once everything is setup */ |
917 | setup_affinity(irq, desc, mask); | 921 | setup_affinity(irq, desc, mask); |
diff --git a/kernel/irq/migration.c b/kernel/irq/migration.c index 24f53caddf47..7a93c6b88b25 100644 --- a/kernel/irq/migration.c +++ b/kernel/irq/migration.c | |||
@@ -15,7 +15,7 @@ void move_masked_irq(int irq) | |||
15 | /* | 15 | /* |
16 | * Paranoia: cpu-local interrupts shouldn't be calling in here anyway. | 16 | * Paranoia: cpu-local interrupts shouldn't be calling in here anyway. |
17 | */ | 17 | */ |
18 | if (desc->status & (IRQ_PER_CPU | IRQ_NO_BALANCING)) { | 18 | if (!irqd_can_balance(&desc->irq_data)) { |
19 | WARN_ON(1); | 19 | WARN_ON(1); |
20 | return; | 20 | return; |
21 | } | 21 | } |
diff --git a/kernel/irq/settings.h b/kernel/irq/settings.h index bb104a2dce73..ba0fffe410ad 100644 --- a/kernel/irq/settings.h +++ b/kernel/irq/settings.h | |||
@@ -4,6 +4,9 @@ | |||
4 | */ | 4 | */ |
5 | enum { | 5 | enum { |
6 | _IRQ_DEFAULT_INIT_FLAGS = IRQ_DEFAULT_INIT_FLAGS, | 6 | _IRQ_DEFAULT_INIT_FLAGS = IRQ_DEFAULT_INIT_FLAGS, |
7 | _IRQ_PER_CPU = IRQ_PER_CPU, | ||
8 | _IRQ_NO_BALANCING = IRQ_NO_BALANCING, | ||
9 | _IRQF_MODIFY_MASK = IRQF_MODIFY_MASK, | ||
7 | }; | 10 | }; |
8 | 11 | ||
9 | #undef IRQ_INPROGRESS | 12 | #undef IRQ_INPROGRESS |
@@ -22,3 +25,36 @@ enum { | |||
22 | #define IRQ_WAKEUP GOT_YOU_MORON | 25 | #define IRQ_WAKEUP GOT_YOU_MORON |
23 | #undef IRQ_MOVE_PENDING | 26 | #undef IRQ_MOVE_PENDING |
24 | #define IRQ_MOVE_PENDING GOT_YOU_MORON | 27 | #define IRQ_MOVE_PENDING GOT_YOU_MORON |
28 | #undef IRQ_PER_CPU | ||
29 | #define IRQ_PER_CPU GOT_YOU_MORON | ||
30 | #undef IRQ_NO_BALANCING | ||
31 | #define IRQ_NO_BALANCING GOT_YOU_MORON | ||
32 | #undef IRQF_MODIFY_MASK | ||
33 | #define IRQF_MODIFY_MASK GOT_YOU_MORON | ||
34 | |||
35 | static inline void | ||
36 | irq_settings_clr_and_set(struct irq_desc *desc, u32 clr, u32 set) | ||
37 | { | ||
38 | desc->status &= ~(clr & _IRQF_MODIFY_MASK); | ||
39 | desc->status |= (set & _IRQF_MODIFY_MASK); | ||
40 | } | ||
41 | |||
42 | static inline bool irq_settings_is_per_cpu(struct irq_desc *desc) | ||
43 | { | ||
44 | return desc->status & _IRQ_PER_CPU; | ||
45 | } | ||
46 | |||
47 | static inline void irq_settings_set_per_cpu(struct irq_desc *desc) | ||
48 | { | ||
49 | desc->status |= _IRQ_PER_CPU; | ||
50 | } | ||
51 | |||
52 | static inline void irq_settings_set_no_balancing(struct irq_desc *desc) | ||
53 | { | ||
54 | desc->status |= _IRQ_NO_BALANCING; | ||
55 | } | ||
56 | |||
57 | static inline bool irq_settings_has_no_balance_set(struct irq_desc *desc) | ||
58 | { | ||
59 | return desc->status & _IRQ_NO_BALANCING; | ||
60 | } | ||
diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c index 692ce2bae302..226ed7d26a84 100644 --- a/kernel/irq/spurious.c +++ b/kernel/irq/spurious.c | |||
@@ -68,7 +68,8 @@ static int try_one_irq(int irq, struct irq_desc *desc, bool force) | |||
68 | raw_spin_lock(&desc->lock); | 68 | raw_spin_lock(&desc->lock); |
69 | 69 | ||
70 | /* PER_CPU and nested thread interrupts are never polled */ | 70 | /* PER_CPU and nested thread interrupts are never polled */ |
71 | if (desc->status & (IRQ_PER_CPU | IRQ_NESTED_THREAD)) | 71 | if (irq_settings_is_per_cpu(desc) || |
72 | (desc->status & IRQ_NESTED_THREAD)) | ||
72 | goto out; | 73 | goto out; |
73 | 74 | ||
74 | /* | 75 | /* |