aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2010-09-27 08:44:25 -0400
committerThomas Gleixner <tglx@linutronix.de>2010-10-04 06:27:16 -0400
commitff7dcd44dd446db2c3e13bdedf2d52b8e0127f16 (patch)
treeca03e829ea08aa536124a7777d99233dbbd89984
parent3bb9808e99bcc36eecb8e082bf70efb2a0bcdcb7 (diff)
genirq: Create irq_data
Low level chip functions need access to irq_desc->handler_data, irq_desc->chip_data and irq_desc->msi_desc. We hand down the irq number to the low level functions, so they need to lookup irq_desc. With sparse irq this means a radix tree lookup. We could hand down irq_desc itself, but low level chip functions have no need to fiddle with it directly and we want to restrict access to irq_desc further. Preparatory patch for new chip functions. Note, that the ugly anon union/struct is there to avoid a full tree wide clean up for now. This is not going to last 3 years like __do_IRQ() Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: Peter Zijlstra <peterz@infradead.org> LKML-Reference: <20100927121841.645542300@linutronix.de> Reviewed-by: H. Peter Anvin <hpa@zytor.com> Reviewed-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--include/linux/irq.h90
-rw-r--r--kernel/irq/handle.c39
2 files changed, 82 insertions, 47 deletions
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 06273a2a17e7..363c76ff82c8 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -84,6 +84,37 @@ struct proc_dir_entry;
84struct msi_desc; 84struct msi_desc;
85 85
86/** 86/**
87 * struct irq_data - per irq and irq chip data passed down to chip functions
88 * @irq: interrupt number
89 * @node: node index useful for balancing
90 * @chip: low level interrupt hardware access
91 * @handler_data: per-IRQ data for the irq_chip methods
92 * @chip_data: platform-specific per-chip private data for the chip
93 * methods, to allow shared chip implementations
94 * @msi_desc: MSI descriptor
95 * @affinity: IRQ affinity on SMP
96 * @irq_2_iommu: iommu with this irq
97 *
98 * The fields here need to overlay the ones in irq_desc until we
99 * cleaned up the direct references and switched everything over to
100 * irq_data.
101 */
102struct irq_data {
103 unsigned int irq;
104 unsigned int node;
105 struct irq_chip *chip;
106 void *handler_data;
107 void *chip_data;
108 struct msi_desc *msi_desc;
109#ifdef CONFIG_SMP
110 cpumask_var_t affinity;
111#endif
112#ifdef CONFIG_INTR_REMAP
113 struct irq_2_iommu *irq_2_iommu;
114#endif
115};
116
117/**
87 * struct irq_chip - hardware interrupt chip descriptor 118 * struct irq_chip - hardware interrupt chip descriptor
88 * 119 *
89 * @name: name for /proc/interrupts 120 * @name: name for /proc/interrupts
@@ -140,16 +171,10 @@ struct timer_rand_state;
140struct irq_2_iommu; 171struct irq_2_iommu;
141/** 172/**
142 * struct irq_desc - interrupt descriptor 173 * struct irq_desc - interrupt descriptor
143 * @irq: interrupt number for this descriptor 174 * @irq_data: per irq and chip data passed down to chip functions
144 * @timer_rand_state: pointer to timer rand state struct 175 * @timer_rand_state: pointer to timer rand state struct
145 * @kstat_irqs: irq stats per cpu 176 * @kstat_irqs: irq stats per cpu
146 * @irq_2_iommu: iommu with this irq
147 * @handle_irq: highlevel irq-events handler [if NULL, __do_IRQ()] 177 * @handle_irq: highlevel irq-events handler [if NULL, __do_IRQ()]
148 * @chip: low level interrupt hardware access
149 * @msi_desc: MSI descriptor
150 * @handler_data: per-IRQ data for the irq_chip methods
151 * @chip_data: platform-specific per-chip private data for the chip
152 * methods, to allow shared chip implementations
153 * @action: the irq action chain 178 * @action: the irq action chain
154 * @status: status information 179 * @status: status information
155 * @depth: disable-depth, for nested irq_disable() calls 180 * @depth: disable-depth, for nested irq_disable() calls
@@ -158,8 +183,6 @@ struct irq_2_iommu;
158 * @last_unhandled: aging timer for unhandled count 183 * @last_unhandled: aging timer for unhandled count
159 * @irqs_unhandled: stats field for spurious unhandled interrupts 184 * @irqs_unhandled: stats field for spurious unhandled interrupts
160 * @lock: locking for SMP 185 * @lock: locking for SMP
161 * @affinity: IRQ affinity on SMP
162 * @node: node index useful for balancing
163 * @pending_mask: pending rebalanced interrupts 186 * @pending_mask: pending rebalanced interrupts
164 * @threads_active: number of irqaction threads currently running 187 * @threads_active: number of irqaction threads currently running
165 * @wait_for_threads: wait queue for sync_irq to wait for threaded handlers 188 * @wait_for_threads: wait queue for sync_irq to wait for threaded handlers
@@ -167,17 +190,32 @@ struct irq_2_iommu;
167 * @name: flow handler name for /proc/interrupts output 190 * @name: flow handler name for /proc/interrupts output
168 */ 191 */
169struct irq_desc { 192struct irq_desc {
170 unsigned int irq; 193
171 struct timer_rand_state *timer_rand_state; 194 /*
172 unsigned int *kstat_irqs; 195 * This union will go away, once we fixed the direct access to
196 * irq_desc all over the place. The direct fields are a 1:1
197 * overlay of irq_data.
198 */
199 union {
200 struct irq_data irq_data;
201 struct {
202 unsigned int irq;
203 unsigned int node;
204 struct irq_chip *chip;
205 void *handler_data;
206 void *chip_data;
207 struct msi_desc *msi_desc;
208#ifdef CONFIG_SMP
209 cpumask_var_t affinity;
210#endif
173#ifdef CONFIG_INTR_REMAP 211#ifdef CONFIG_INTR_REMAP
174 struct irq_2_iommu *irq_2_iommu; 212 struct irq_2_iommu *irq_2_iommu;
175#endif 213#endif
214 };
215 };
216 struct timer_rand_state *timer_rand_state;
217 unsigned int *kstat_irqs;
176 irq_flow_handler_t handle_irq; 218 irq_flow_handler_t handle_irq;
177 struct irq_chip *chip;
178 struct msi_desc *msi_desc;
179 void *handler_data;
180 void *chip_data;
181 struct irqaction *action; /* IRQ action list */ 219 struct irqaction *action; /* IRQ action list */
182 unsigned int status; /* IRQ status */ 220 unsigned int status; /* IRQ status */
183 221
@@ -188,9 +226,7 @@ struct irq_desc {
188 unsigned int irqs_unhandled; 226 unsigned int irqs_unhandled;
189 raw_spinlock_t lock; 227 raw_spinlock_t lock;
190#ifdef CONFIG_SMP 228#ifdef CONFIG_SMP
191 cpumask_var_t affinity;
192 const struct cpumask *affinity_hint; 229 const struct cpumask *affinity_hint;
193 unsigned int node;
194#ifdef CONFIG_GENERIC_PENDING_IRQ 230#ifdef CONFIG_GENERIC_PENDING_IRQ
195 cpumask_var_t pending_mask; 231 cpumask_var_t pending_mask;
196#endif 232#endif
@@ -406,15 +442,15 @@ extern int set_irq_chip_data(unsigned int irq, void *data);
406extern int set_irq_type(unsigned int irq, unsigned int type); 442extern int set_irq_type(unsigned int irq, unsigned int type);
407extern int set_irq_msi(unsigned int irq, struct msi_desc *entry); 443extern int set_irq_msi(unsigned int irq, struct msi_desc *entry);
408 444
409#define get_irq_chip(irq) (irq_to_desc(irq)->chip) 445#define get_irq_chip(irq) (irq_to_desc(irq)->irq_data.chip)
410#define get_irq_chip_data(irq) (irq_to_desc(irq)->chip_data) 446#define get_irq_chip_data(irq) (irq_to_desc(irq)->irq_data.chip_data)
411#define get_irq_data(irq) (irq_to_desc(irq)->handler_data) 447#define get_irq_data(irq) (irq_to_desc(irq)->irq_data.handler_data)
412#define get_irq_msi(irq) (irq_to_desc(irq)->msi_desc) 448#define get_irq_msi(irq) (irq_to_desc(irq)->irq_data.msi_desc)
413 449
414#define get_irq_desc_chip(desc) ((desc)->chip) 450#define get_irq_desc_chip(desc) ((desc)->irq_data.chip)
415#define get_irq_desc_chip_data(desc) ((desc)->chip_data) 451#define get_irq_desc_chip_data(desc) ((desc)->irq_data.chip_data)
416#define get_irq_desc_data(desc) ((desc)->handler_data) 452#define get_irq_desc_data(desc) ((desc)->irq_data.handler_data)
417#define get_irq_desc_msi(desc) ((desc)->msi_desc) 453#define get_irq_desc_msi(desc) ((desc)->irq_data.msi_desc)
418 454
419#endif /* CONFIG_GENERIC_HARDIRQS */ 455#endif /* CONFIG_GENERIC_HARDIRQS */
420 456
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index 27e5c6911223..099d4fc368c3 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -75,12 +75,10 @@ EXPORT_SYMBOL_GPL(nr_irqs);
75#ifdef CONFIG_SPARSE_IRQ 75#ifdef CONFIG_SPARSE_IRQ
76 76
77static struct irq_desc irq_desc_init = { 77static struct irq_desc irq_desc_init = {
78 .irq = -1, 78 .status = IRQ_DISABLED,
79 .status = IRQ_DISABLED, 79 .handle_irq = handle_bad_irq,
80 .chip = &no_irq_chip, 80 .depth = 1,
81 .handle_irq = handle_bad_irq, 81 .lock = __RAW_SPIN_LOCK_UNLOCKED(irq_desc_init.lock),
82 .depth = 1,
83 .lock = __RAW_SPIN_LOCK_UNLOCKED(irq_desc_init.lock),
84}; 82};
85 83
86void __ref init_kstat_irqs(struct irq_desc *desc, int node, int nr) 84void __ref init_kstat_irqs(struct irq_desc *desc, int node, int nr)
@@ -105,7 +103,7 @@ static void init_one_irq_desc(int irq, struct irq_desc *desc, int node)
105 memcpy(desc, &irq_desc_init, sizeof(struct irq_desc)); 103 memcpy(desc, &irq_desc_init, sizeof(struct irq_desc));
106 104
107 raw_spin_lock_init(&desc->lock); 105 raw_spin_lock_init(&desc->lock);
108 desc->irq = irq; 106 desc->irq_data.irq = irq;
109#ifdef CONFIG_SMP 107#ifdef CONFIG_SMP
110 desc->node = node; 108 desc->node = node;
111#endif 109#endif
@@ -151,12 +149,10 @@ void replace_irq_desc(unsigned int irq, struct irq_desc *desc)
151 149
152static struct irq_desc irq_desc_legacy[NR_IRQS_LEGACY] __cacheline_aligned_in_smp = { 150static struct irq_desc irq_desc_legacy[NR_IRQS_LEGACY] __cacheline_aligned_in_smp = {
153 [0 ... NR_IRQS_LEGACY-1] = { 151 [0 ... NR_IRQS_LEGACY-1] = {
154 .irq = -1, 152 .status = IRQ_DISABLED,
155 .status = IRQ_DISABLED, 153 .handle_irq = handle_bad_irq,
156 .chip = &no_irq_chip, 154 .depth = 1,
157 .handle_irq = handle_bad_irq, 155 .lock = __RAW_SPIN_LOCK_UNLOCKED(irq_desc_init.lock),
158 .depth = 1,
159 .lock = __RAW_SPIN_LOCK_UNLOCKED(irq_desc_init.lock),
160 } 156 }
161}; 157};
162 158
@@ -183,8 +179,11 @@ int __init early_irq_init(void)
183 kstat_irqs_legacy = kzalloc_node(NR_IRQS_LEGACY * nr_cpu_ids * 179 kstat_irqs_legacy = kzalloc_node(NR_IRQS_LEGACY * nr_cpu_ids *
184 sizeof(int), GFP_NOWAIT, node); 180 sizeof(int), GFP_NOWAIT, node);
185 181
182 irq_desc_init.irq_data.chip = &no_irq_chip;
183
186 for (i = 0; i < legacy_count; i++) { 184 for (i = 0; i < legacy_count; i++) {
187 desc[i].irq = i; 185 desc[i].irq_data.irq = i;
186 desc[i].irq_data.chip = &no_irq_chip;
188#ifdef CONFIG_SMP 187#ifdef CONFIG_SMP
189 desc[i].node = node; 188 desc[i].node = node;
190#endif 189#endif
@@ -241,11 +240,10 @@ out_unlock:
241 240
242struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { 241struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {
243 [0 ... NR_IRQS-1] = { 242 [0 ... NR_IRQS-1] = {
244 .status = IRQ_DISABLED, 243 .status = IRQ_DISABLED,
245 .chip = &no_irq_chip, 244 .handle_irq = handle_bad_irq,
246 .handle_irq = handle_bad_irq, 245 .depth = 1,
247 .depth = 1, 246 .lock = __RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock),
248 .lock = __RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock),
249 } 247 }
250}; 248};
251 249
@@ -264,7 +262,8 @@ int __init early_irq_init(void)
264 count = ARRAY_SIZE(irq_desc); 262 count = ARRAY_SIZE(irq_desc);
265 263
266 for (i = 0; i < count; i++) { 264 for (i = 0; i < count; i++) {
267 desc[i].irq = i; 265 desc[i].irq_data.irq = i;
266 desc[i].irq_data.chip = &no_irq_chip;
268 alloc_desc_masks(&desc[i], 0, true); 267 alloc_desc_masks(&desc[i], 0, true);
269 init_desc_masks(&desc[i]); 268 init_desc_masks(&desc[i]);
270 desc[i].kstat_irqs = kstat_irqs_all[i]; 269 desc[i].kstat_irqs = kstat_irqs_all[i];