Blame view

kernel/irq/chip.c 18 KB
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
1
2
3
4
5
6
7
8
9
10
11
12
13
  /*
   * linux/kernel/irq/chip.c
   *
   * Copyright (C) 1992, 1998-2006 Linus Torvalds, Ingo Molnar
   * Copyright (C) 2005-2006, Thomas Gleixner, Russell King
   *
   * This file contains the core interrupt handling code, for irq-chip
   * based architectures.
   *
   * Detailed information is available in Documentation/DocBook/genericirq
   */
  
  #include <linux/irq.h>
7fe3730de   Michael Ellerman   MSI: arch must co...
14
  #include <linux/msi.h>
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
15
16
17
18
19
  #include <linux/module.h>
  #include <linux/interrupt.h>
  #include <linux/kernel_stat.h>
  
  #include "internals.h"
3a16d7136   Eric W. Biederman   [PATCH] genirq: i...
20
  /**
a0cd9ca2b   Thomas Gleixner   genirq: Namespace...
21
   *	irq_set_chip - set the irq chip for an irq
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
22
23
24
   *	@irq:	irq number
   *	@chip:	pointer to irq chip description structure
   */
a0cd9ca2b   Thomas Gleixner   genirq: Namespace...
25
  int irq_set_chip(unsigned int irq, struct irq_chip *chip)
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
26
  {
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
27
  	unsigned long flags;
31d9d9b6d   Marc Zyngier   genirq: Add suppo...
28
  	struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
29

02725e747   Thomas Gleixner   genirq: Use irq_g...
30
  	if (!desc)
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
31
  		return -EINVAL;
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
32
33
34
  
  	if (!chip)
  		chip = &no_irq_chip;
6b8ff3120   Thomas Gleixner   genirq: Convert c...
35
  	desc->irq_data.chip = chip;
02725e747   Thomas Gleixner   genirq: Use irq_g...
36
  	irq_put_desc_unlock(desc, flags);
d72274e58   David Daney   genirq: Reserve t...
37
38
39
40
41
42
  	/*
  	 * For !CONFIG_SPARSE_IRQ make the irq show up in
  	 * allocated_irqs. For the CONFIG_SPARSE_IRQ case, it is
  	 * already marked, and this call is harmless.
  	 */
  	irq_reserve_irq(irq);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
43
44
  	return 0;
  }
a0cd9ca2b   Thomas Gleixner   genirq: Namespace...
45
  EXPORT_SYMBOL(irq_set_chip);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
46
47
  
  /**
a0cd9ca2b   Thomas Gleixner   genirq: Namespace...
48
   *	irq_set_type - set the irq trigger type for an irq
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
49
   *	@irq:	irq number
0c5d1eb77   David Brownell   genirq: record tr...
50
   *	@type:	IRQ_TYPE_{LEVEL,EDGE}_* value - see include/linux/irq.h
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
51
   */
a0cd9ca2b   Thomas Gleixner   genirq: Namespace...
52
  int irq_set_irq_type(unsigned int irq, unsigned int type)
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
53
  {
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
54
  	unsigned long flags;
31d9d9b6d   Marc Zyngier   genirq: Add suppo...
55
  	struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL);
02725e747   Thomas Gleixner   genirq: Use irq_g...
56
  	int ret = 0;
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
57

02725e747   Thomas Gleixner   genirq: Use irq_g...
58
59
  	if (!desc)
  		return -EINVAL;
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
60

f2b662da8   David Brownell   genirq: record IR...
61
  	type &= IRQ_TYPE_SENSE_MASK;
02725e747   Thomas Gleixner   genirq: Use irq_g...
62
63
64
  	if (type != IRQ_TYPE_NONE)
  		ret = __irq_set_trigger(desc, irq, type);
  	irq_put_desc_busunlock(desc, flags);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
65
66
  	return ret;
  }
a0cd9ca2b   Thomas Gleixner   genirq: Namespace...
67
  EXPORT_SYMBOL(irq_set_irq_type);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
68
69
  
  /**
a0cd9ca2b   Thomas Gleixner   genirq: Namespace...
70
   *	irq_set_handler_data - set irq handler data for an irq
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
71
72
73
74
75
   *	@irq:	Interrupt number
   *	@data:	Pointer to interrupt specific data
   *
   *	Set the hardware irq controller data for an irq
   */
a0cd9ca2b   Thomas Gleixner   genirq: Namespace...
76
  int irq_set_handler_data(unsigned int irq, void *data)
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
77
  {
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
78
  	unsigned long flags;
31d9d9b6d   Marc Zyngier   genirq: Add suppo...
79
  	struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
80

02725e747   Thomas Gleixner   genirq: Use irq_g...
81
  	if (!desc)
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
82
  		return -EINVAL;
6b8ff3120   Thomas Gleixner   genirq: Convert c...
83
  	desc->irq_data.handler_data = data;
02725e747   Thomas Gleixner   genirq: Use irq_g...
84
  	irq_put_desc_unlock(desc, flags);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
85
86
  	return 0;
  }
a0cd9ca2b   Thomas Gleixner   genirq: Namespace...
87
  EXPORT_SYMBOL(irq_set_handler_data);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
88
89
  
  /**
a0cd9ca2b   Thomas Gleixner   genirq: Namespace...
90
   *	irq_set_msi_desc - set MSI descriptor data for an irq
5b912c108   Eric W. Biederman   msi: Kill the msi...
91
   *	@irq:	Interrupt number
472900b8b   Randy Dunlap   [PATCH] IRQ kerne...
92
   *	@entry:	Pointer to MSI descriptor data
5b912c108   Eric W. Biederman   msi: Kill the msi...
93
   *
24b26d421   Liuweni   irq: Fix docbook ...
94
   *	Set the MSI descriptor entry for an irq
5b912c108   Eric W. Biederman   msi: Kill the msi...
95
   */
a0cd9ca2b   Thomas Gleixner   genirq: Namespace...
96
  int irq_set_msi_desc(unsigned int irq, struct msi_desc *entry)
5b912c108   Eric W. Biederman   msi: Kill the msi...
97
  {
5b912c108   Eric W. Biederman   msi: Kill the msi...
98
  	unsigned long flags;
31d9d9b6d   Marc Zyngier   genirq: Add suppo...
99
  	struct irq_desc *desc = irq_get_desc_lock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL);
5b912c108   Eric W. Biederman   msi: Kill the msi...
100

02725e747   Thomas Gleixner   genirq: Use irq_g...
101
  	if (!desc)
5b912c108   Eric W. Biederman   msi: Kill the msi...
102
  		return -EINVAL;
6b8ff3120   Thomas Gleixner   genirq: Convert c...
103
  	desc->irq_data.msi_desc = entry;
7fe3730de   Michael Ellerman   MSI: arch must co...
104
105
  	if (entry)
  		entry->irq = irq;
02725e747   Thomas Gleixner   genirq: Use irq_g...
106
  	irq_put_desc_unlock(desc, flags);
5b912c108   Eric W. Biederman   msi: Kill the msi...
107
108
109
110
  	return 0;
  }
  
  /**
a0cd9ca2b   Thomas Gleixner   genirq: Namespace...
111
   *	irq_set_chip_data - set irq chip data for an irq
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
112
113
114
115
116
   *	@irq:	Interrupt number
   *	@data:	Pointer to chip specific data
   *
   *	Set the hardware irq chip data for an irq
   */
a0cd9ca2b   Thomas Gleixner   genirq: Namespace...
117
  int irq_set_chip_data(unsigned int irq, void *data)
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
118
  {
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
119
  	unsigned long flags;
31d9d9b6d   Marc Zyngier   genirq: Add suppo...
120
  	struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
121

02725e747   Thomas Gleixner   genirq: Use irq_g...
122
  	if (!desc)
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
123
  		return -EINVAL;
6b8ff3120   Thomas Gleixner   genirq: Convert c...
124
  	desc->irq_data.chip_data = data;
02725e747   Thomas Gleixner   genirq: Use irq_g...
125
  	irq_put_desc_unlock(desc, flags);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
126
127
  	return 0;
  }
a0cd9ca2b   Thomas Gleixner   genirq: Namespace...
128
  EXPORT_SYMBOL(irq_set_chip_data);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
129

f303a6dd1   Thomas Gleixner   genirq: Sanitize ...
130
131
132
133
134
135
136
  struct irq_data *irq_get_irq_data(unsigned int irq)
  {
  	struct irq_desc *desc = irq_to_desc(irq);
  
  	return desc ? &desc->irq_data : NULL;
  }
  EXPORT_SYMBOL_GPL(irq_get_irq_data);
c1594b77e   Thomas Gleixner   genirq: Move IRQ_...
137
138
  static void irq_state_clr_disabled(struct irq_desc *desc)
  {
801a0e9ae   Thomas Gleixner   genirq: Add irq d...
139
  	irqd_clear(&desc->irq_data, IRQD_IRQ_DISABLED);
c1594b77e   Thomas Gleixner   genirq: Move IRQ_...
140
141
142
143
  }
  
  static void irq_state_set_disabled(struct irq_desc *desc)
  {
801a0e9ae   Thomas Gleixner   genirq: Add irq d...
144
  	irqd_set(&desc->irq_data, IRQD_IRQ_DISABLED);
c1594b77e   Thomas Gleixner   genirq: Move IRQ_...
145
  }
6e40262ea   Thomas Gleixner   genirq: Move IRQ_...
146
147
  static void irq_state_clr_masked(struct irq_desc *desc)
  {
32f4125eb   Thomas Gleixner   genirq: Move INPR...
148
  	irqd_clear(&desc->irq_data, IRQD_IRQ_MASKED);
6e40262ea   Thomas Gleixner   genirq: Move IRQ_...
149
150
151
152
  }
  
  static void irq_state_set_masked(struct irq_desc *desc)
  {
32f4125eb   Thomas Gleixner   genirq: Move INPR...
153
  	irqd_set(&desc->irq_data, IRQD_IRQ_MASKED);
6e40262ea   Thomas Gleixner   genirq: Move IRQ_...
154
  }
469992386   Thomas Gleixner   genirq: Consolida...
155
156
  int irq_startup(struct irq_desc *desc)
  {
c1594b77e   Thomas Gleixner   genirq: Move IRQ_...
157
  	irq_state_clr_disabled(desc);
469992386   Thomas Gleixner   genirq: Consolida...
158
  	desc->depth = 0;
3aae994fb   Thomas Gleixner   genirq: Consolida...
159
160
  	if (desc->irq_data.chip->irq_startup) {
  		int ret = desc->irq_data.chip->irq_startup(&desc->irq_data);
6e40262ea   Thomas Gleixner   genirq: Move IRQ_...
161
  		irq_state_clr_masked(desc);
3aae994fb   Thomas Gleixner   genirq: Consolida...
162
163
  		return ret;
  	}
469992386   Thomas Gleixner   genirq: Consolida...
164

87923470c   Thomas Gleixner   genirq: Consolida...
165
  	irq_enable(desc);
469992386   Thomas Gleixner   genirq: Consolida...
166
167
168
169
170
  	return 0;
  }
  
  void irq_shutdown(struct irq_desc *desc)
  {
c1594b77e   Thomas Gleixner   genirq: Move IRQ_...
171
  	irq_state_set_disabled(desc);
469992386   Thomas Gleixner   genirq: Consolida...
172
  	desc->depth = 1;
50f7c0327   Thomas Gleixner   genirq: Remove de...
173
174
  	if (desc->irq_data.chip->irq_shutdown)
  		desc->irq_data.chip->irq_shutdown(&desc->irq_data);
ed585a651   Geert Uytterhoeven   genirq: Make irq_...
175
  	else if (desc->irq_data.chip->irq_disable)
50f7c0327   Thomas Gleixner   genirq: Remove de...
176
177
178
  		desc->irq_data.chip->irq_disable(&desc->irq_data);
  	else
  		desc->irq_data.chip->irq_mask(&desc->irq_data);
6e40262ea   Thomas Gleixner   genirq: Move IRQ_...
179
  	irq_state_set_masked(desc);
469992386   Thomas Gleixner   genirq: Consolida...
180
  }
87923470c   Thomas Gleixner   genirq: Consolida...
181
182
  void irq_enable(struct irq_desc *desc)
  {
c1594b77e   Thomas Gleixner   genirq: Move IRQ_...
183
  	irq_state_clr_disabled(desc);
50f7c0327   Thomas Gleixner   genirq: Remove de...
184
185
186
187
  	if (desc->irq_data.chip->irq_enable)
  		desc->irq_data.chip->irq_enable(&desc->irq_data);
  	else
  		desc->irq_data.chip->irq_unmask(&desc->irq_data);
6e40262ea   Thomas Gleixner   genirq: Move IRQ_...
188
  	irq_state_clr_masked(desc);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
189
  }
50f7c0327   Thomas Gleixner   genirq: Remove de...
190
  void irq_disable(struct irq_desc *desc)
89d694b9d   Thomas Gleixner   genirq: do not le...
191
  {
c1594b77e   Thomas Gleixner   genirq: Move IRQ_...
192
  	irq_state_set_disabled(desc);
50f7c0327   Thomas Gleixner   genirq: Remove de...
193
194
  	if (desc->irq_data.chip->irq_disable) {
  		desc->irq_data.chip->irq_disable(&desc->irq_data);
a61d82580   Thomas Gleixner   genirq: Fix mispl...
195
  		irq_state_set_masked(desc);
50f7c0327   Thomas Gleixner   genirq: Remove de...
196
  	}
89d694b9d   Thomas Gleixner   genirq: do not le...
197
  }
31d9d9b6d   Marc Zyngier   genirq: Add suppo...
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
  void irq_percpu_enable(struct irq_desc *desc, unsigned int cpu)
  {
  	if (desc->irq_data.chip->irq_enable)
  		desc->irq_data.chip->irq_enable(&desc->irq_data);
  	else
  		desc->irq_data.chip->irq_unmask(&desc->irq_data);
  	cpumask_set_cpu(cpu, desc->percpu_enabled);
  }
  
  void irq_percpu_disable(struct irq_desc *desc, unsigned int cpu)
  {
  	if (desc->irq_data.chip->irq_disable)
  		desc->irq_data.chip->irq_disable(&desc->irq_data);
  	else
  		desc->irq_data.chip->irq_mask(&desc->irq_data);
  	cpumask_clear_cpu(cpu, desc->percpu_enabled);
  }
9205e31d1   Thomas Gleixner   genirq: Provide c...
215
  static inline void mask_ack_irq(struct irq_desc *desc)
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
216
  {
9205e31d1   Thomas Gleixner   genirq: Provide c...
217
218
  	if (desc->irq_data.chip->irq_mask_ack)
  		desc->irq_data.chip->irq_mask_ack(&desc->irq_data);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
219
  	else {
e2c0f8ff0   Thomas Gleixner   genirq: Provide c...
220
  		desc->irq_data.chip->irq_mask(&desc->irq_data);
22a49163e   Thomas Gleixner   genirq: Provide c...
221
222
  		if (desc->irq_data.chip->irq_ack)
  			desc->irq_data.chip->irq_ack(&desc->irq_data);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
223
  	}
6e40262ea   Thomas Gleixner   genirq: Move IRQ_...
224
  	irq_state_set_masked(desc);
0b1adaa03   Thomas Gleixner   genirq: Prevent o...
225
  }
d4d5e0896   Thomas Gleixner   genirq: Add IRQCH...
226
  void mask_irq(struct irq_desc *desc)
0b1adaa03   Thomas Gleixner   genirq: Prevent o...
227
  {
e2c0f8ff0   Thomas Gleixner   genirq: Provide c...
228
229
  	if (desc->irq_data.chip->irq_mask) {
  		desc->irq_data.chip->irq_mask(&desc->irq_data);
6e40262ea   Thomas Gleixner   genirq: Move IRQ_...
230
  		irq_state_set_masked(desc);
0b1adaa03   Thomas Gleixner   genirq: Prevent o...
231
232
  	}
  }
d4d5e0896   Thomas Gleixner   genirq: Add IRQCH...
233
  void unmask_irq(struct irq_desc *desc)
0b1adaa03   Thomas Gleixner   genirq: Prevent o...
234
  {
0eda58b7f   Thomas Gleixner   genirq: Provide c...
235
236
  	if (desc->irq_data.chip->irq_unmask) {
  		desc->irq_data.chip->irq_unmask(&desc->irq_data);
6e40262ea   Thomas Gleixner   genirq: Move IRQ_...
237
  		irq_state_clr_masked(desc);
0b1adaa03   Thomas Gleixner   genirq: Prevent o...
238
  	}
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
239
  }
399b5da29   Thomas Gleixner   genirq: Support n...
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
  /*
   *	handle_nested_irq - Handle a nested irq from a irq thread
   *	@irq:	the interrupt number
   *
   *	Handle interrupts which are nested into a threaded interrupt
   *	handler. The handler function is called inside the calling
   *	threads context.
   */
  void handle_nested_irq(unsigned int irq)
  {
  	struct irq_desc *desc = irq_to_desc(irq);
  	struct irqaction *action;
  	irqreturn_t action_ret;
  
  	might_sleep();
239007b84   Thomas Gleixner   genirq: Convert i...
255
  	raw_spin_lock_irq(&desc->lock);
399b5da29   Thomas Gleixner   genirq: Support n...
256
257
258
259
  
  	kstat_incr_irqs_this_cpu(irq, desc);
  
  	action = desc->action;
32f4125eb   Thomas Gleixner   genirq: Move INPR...
260
  	if (unlikely(!action || irqd_irq_disabled(&desc->irq_data)))
399b5da29   Thomas Gleixner   genirq: Support n...
261
  		goto out_unlock;
32f4125eb   Thomas Gleixner   genirq: Move INPR...
262
  	irqd_set(&desc->irq_data, IRQD_IRQ_INPROGRESS);
239007b84   Thomas Gleixner   genirq: Convert i...
263
  	raw_spin_unlock_irq(&desc->lock);
399b5da29   Thomas Gleixner   genirq: Support n...
264
265
266
267
  
  	action_ret = action->thread_fn(action->irq, action->dev_id);
  	if (!noirqdebug)
  		note_interrupt(irq, desc, action_ret);
239007b84   Thomas Gleixner   genirq: Convert i...
268
  	raw_spin_lock_irq(&desc->lock);
32f4125eb   Thomas Gleixner   genirq: Move INPR...
269
  	irqd_clear(&desc->irq_data, IRQD_IRQ_INPROGRESS);
399b5da29   Thomas Gleixner   genirq: Support n...
270
271
  
  out_unlock:
239007b84   Thomas Gleixner   genirq: Convert i...
272
  	raw_spin_unlock_irq(&desc->lock);
399b5da29   Thomas Gleixner   genirq: Support n...
273
274
  }
  EXPORT_SYMBOL_GPL(handle_nested_irq);
fe200ae48   Thomas Gleixner   genirq: Mark poll...
275
276
  static bool irq_check_poll(struct irq_desc *desc)
  {
6954b75b4   Thomas Gleixner   genirq: Move IRQ_...
277
  	if (!(desc->istate & IRQS_POLL_INPROGRESS))
fe200ae48   Thomas Gleixner   genirq: Mark poll...
278
279
280
  		return false;
  	return irq_wait_for_poll(desc);
  }
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
281
282
283
284
  /**
   *	handle_simple_irq - Simple and software-decoded IRQs.
   *	@irq:	the interrupt number
   *	@desc:	the interrupt description structure for this irq
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
285
286
287
288
289
290
291
292
   *
   *	Simple interrupts are either sent from a demultiplexing interrupt
   *	handler or come from hardware, where no interrupt hardware control
   *	is necessary.
   *
   *	Note: The caller is expected to handle the ack, clear, mask and
   *	unmask issues if necessary.
   */
7ad5b3a50   Harvey Harrison   kernel: remove fa...
293
  void
7d12e780e   David Howells   IRQ: Maintain reg...
294
  handle_simple_irq(unsigned int irq, struct irq_desc *desc)
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
295
  {
239007b84   Thomas Gleixner   genirq: Convert i...
296
  	raw_spin_lock(&desc->lock);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
297

32f4125eb   Thomas Gleixner   genirq: Move INPR...
298
  	if (unlikely(irqd_irq_inprogress(&desc->irq_data)))
fe200ae48   Thomas Gleixner   genirq: Mark poll...
299
300
  		if (!irq_check_poll(desc))
  			goto out_unlock;
163ef3091   Thomas Gleixner   genirq: Move IRQ_...
301
  	desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
d6c88a507   Thomas Gleixner   genirq: revert dy...
302
  	kstat_incr_irqs_this_cpu(irq, desc);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
303

32f4125eb   Thomas Gleixner   genirq: Move INPR...
304
  	if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data)))
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
305
  		goto out_unlock;
107781e72   Thomas Gleixner   genirq: Use handl...
306
  	handle_irq_event(desc);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
307

dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
308
  out_unlock:
239007b84   Thomas Gleixner   genirq: Convert i...
309
  	raw_spin_unlock(&desc->lock);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
310
  }
edf76f830   Jonathan Cameron   irq: Export funct...
311
  EXPORT_SYMBOL_GPL(handle_simple_irq);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
312
313
314
315
316
  
  /**
   *	handle_level_irq - Level type irq handler
   *	@irq:	the interrupt number
   *	@desc:	the interrupt description structure for this irq
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
317
318
319
320
321
322
   *
   *	Level type interrupts are active as long as the hardware line has
   *	the active level. This may require to mask the interrupt and unmask
   *	it after the associated handler has acknowledged the device, so the
   *	interrupt line is back to inactive.
   */
7ad5b3a50   Harvey Harrison   kernel: remove fa...
323
  void
7d12e780e   David Howells   IRQ: Maintain reg...
324
  handle_level_irq(unsigned int irq, struct irq_desc *desc)
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
325
  {
239007b84   Thomas Gleixner   genirq: Convert i...
326
  	raw_spin_lock(&desc->lock);
9205e31d1   Thomas Gleixner   genirq: Provide c...
327
  	mask_ack_irq(desc);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
328

32f4125eb   Thomas Gleixner   genirq: Move INPR...
329
  	if (unlikely(irqd_irq_inprogress(&desc->irq_data)))
fe200ae48   Thomas Gleixner   genirq: Mark poll...
330
331
  		if (!irq_check_poll(desc))
  			goto out_unlock;
163ef3091   Thomas Gleixner   genirq: Move IRQ_...
332
  	desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
d6c88a507   Thomas Gleixner   genirq: revert dy...
333
  	kstat_incr_irqs_this_cpu(irq, desc);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
334
335
336
337
338
  
  	/*
  	 * If its disabled or no action available
  	 * keep it masked and get out of here
  	 */
32f4125eb   Thomas Gleixner   genirq: Move INPR...
339
  	if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data)))
86998aa65   Ingo Molnar   [PATCH] genirq co...
340
  		goto out_unlock;
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
341

1529866c6   Thomas Gleixner   genirq: Use handl...
342
  	handle_irq_event(desc);
b25c340c1   Thomas Gleixner   genirq: Add onesh...
343

32f4125eb   Thomas Gleixner   genirq: Move INPR...
344
  	if (!irqd_irq_disabled(&desc->irq_data) && !(desc->istate & IRQS_ONESHOT))
0eda58b7f   Thomas Gleixner   genirq: Provide c...
345
  		unmask_irq(desc);
86998aa65   Ingo Molnar   [PATCH] genirq co...
346
  out_unlock:
239007b84   Thomas Gleixner   genirq: Convert i...
347
  	raw_spin_unlock(&desc->lock);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
348
  }
14819ea1e   Ingo Molnar   irq: export __set...
349
  EXPORT_SYMBOL_GPL(handle_level_irq);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
350

781295762   Thomas Gleixner   genirq: Add prefl...
351
352
353
354
355
356
357
358
359
  #ifdef CONFIG_IRQ_PREFLOW_FASTEOI
  static inline void preflow_handler(struct irq_desc *desc)
  {
  	if (desc->preflow_handler)
  		desc->preflow_handler(&desc->irq_data);
  }
  #else
  static inline void preflow_handler(struct irq_desc *desc) { }
  #endif
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
360
  /**
47c2a3aa4   Ingo Molnar   [PATCH] genirq: a...
361
   *	handle_fasteoi_irq - irq handler for transparent controllers
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
362
363
   *	@irq:	the interrupt number
   *	@desc:	the interrupt description structure for this irq
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
364
   *
47c2a3aa4   Ingo Molnar   [PATCH] genirq: a...
365
   *	Only a single callback will be issued to the chip: an ->eoi()
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
366
367
368
369
   *	call when the interrupt has been serviced. This enables support
   *	for modern forms of interrupt handlers, which handle the flow
   *	details in hardware, transparently.
   */
7ad5b3a50   Harvey Harrison   kernel: remove fa...
370
  void
7d12e780e   David Howells   IRQ: Maintain reg...
371
  handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
372
  {
239007b84   Thomas Gleixner   genirq: Convert i...
373
  	raw_spin_lock(&desc->lock);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
374

32f4125eb   Thomas Gleixner   genirq: Move INPR...
375
  	if (unlikely(irqd_irq_inprogress(&desc->irq_data)))
fe200ae48   Thomas Gleixner   genirq: Mark poll...
376
377
  		if (!irq_check_poll(desc))
  			goto out;
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
378

163ef3091   Thomas Gleixner   genirq: Move IRQ_...
379
  	desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
d6c88a507   Thomas Gleixner   genirq: revert dy...
380
  	kstat_incr_irqs_this_cpu(irq, desc);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
381
382
383
  
  	/*
  	 * If its disabled or no action available
76d216014   Ingo Molnar   [PATCH] genirq: d...
384
  	 * then mask it and get out of here:
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
385
  	 */
32f4125eb   Thomas Gleixner   genirq: Move INPR...
386
  	if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) {
2a0d6fb33   Thomas Gleixner   genirq: Move IRQ_...
387
  		desc->istate |= IRQS_PENDING;
e2c0f8ff0   Thomas Gleixner   genirq: Provide c...
388
  		mask_irq(desc);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
389
  		goto out;
98bb244b6   Benjamin Herrenschmidt   [PATCH] genirq: f...
390
  	}
c69e3758f   Thomas Gleixner   genirq: Fixup fas...
391
392
393
  
  	if (desc->istate & IRQS_ONESHOT)
  		mask_irq(desc);
781295762   Thomas Gleixner   genirq: Add prefl...
394
  	preflow_handler(desc);
a7ae4de5c   Thomas Gleixner   genirq: Use handl...
395
  	handle_irq_event(desc);
77694b408   Thomas Gleixner   genirq; Add faste...
396
397
  
  out_eoi:
0c5c15572   Thomas Gleixner   genirq: Provide c...
398
  	desc->irq_data.chip->irq_eoi(&desc->irq_data);
77694b408   Thomas Gleixner   genirq; Add faste...
399
  out_unlock:
239007b84   Thomas Gleixner   genirq: Convert i...
400
  	raw_spin_unlock(&desc->lock);
77694b408   Thomas Gleixner   genirq; Add faste...
401
402
403
404
405
  	return;
  out:
  	if (!(desc->irq_data.chip->flags & IRQCHIP_EOI_IF_HANDLED))
  		goto out_eoi;
  	goto out_unlock;
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
406
407
408
409
410
411
  }
  
  /**
   *	handle_edge_irq - edge type IRQ handler
   *	@irq:	the interrupt number
   *	@desc:	the interrupt description structure for this irq
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
412
413
   *
   *	Interrupt occures on the falling and/or rising edge of a hardware
25985edce   Lucas De Marchi   Fix common misspe...
414
   *	signal. The occurrence is latched into the irq controller hardware
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
415
416
   *	and must be acked in order to be reenabled. After the ack another
   *	interrupt can happen on the same source even before the first one
dfff0615d   Uwe Kleine-König   tree-wide: fix ty...
417
   *	is handled by the associated event handler. If this happens it
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
418
419
420
421
422
423
   *	might be necessary to disable (mask) the interrupt depending on the
   *	controller hardware. This requires to reenable the interrupt inside
   *	of the loop which handles the interrupts which have arrived while
   *	the handler was running. If all pending interrupts are handled, the
   *	loop is left.
   */
7ad5b3a50   Harvey Harrison   kernel: remove fa...
424
  void
7d12e780e   David Howells   IRQ: Maintain reg...
425
  handle_edge_irq(unsigned int irq, struct irq_desc *desc)
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
426
  {
239007b84   Thomas Gleixner   genirq: Convert i...
427
  	raw_spin_lock(&desc->lock);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
428

163ef3091   Thomas Gleixner   genirq: Move IRQ_...
429
  	desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
430
431
432
433
434
  	/*
  	 * If we're currently running this IRQ, or its disabled,
  	 * we shouldn't process the IRQ. Mark it pending, handle
  	 * the necessary masking and go out
  	 */
32f4125eb   Thomas Gleixner   genirq: Move INPR...
435
436
  	if (unlikely(irqd_irq_disabled(&desc->irq_data) ||
  		     irqd_irq_inprogress(&desc->irq_data) || !desc->action)) {
fe200ae48   Thomas Gleixner   genirq: Mark poll...
437
  		if (!irq_check_poll(desc)) {
2a0d6fb33   Thomas Gleixner   genirq: Move IRQ_...
438
  			desc->istate |= IRQS_PENDING;
fe200ae48   Thomas Gleixner   genirq: Mark poll...
439
440
441
  			mask_ack_irq(desc);
  			goto out_unlock;
  		}
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
442
  	}
d6c88a507   Thomas Gleixner   genirq: revert dy...
443
  	kstat_incr_irqs_this_cpu(irq, desc);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
444
445
  
  	/* Start handling the irq */
22a49163e   Thomas Gleixner   genirq: Provide c...
446
  	desc->irq_data.chip->irq_ack(&desc->irq_data);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
447

dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
448
  	do {
a60a5dc2d   Thomas Gleixner   genirq: Use handl...
449
  		if (unlikely(!desc->action)) {
e2c0f8ff0   Thomas Gleixner   genirq: Provide c...
450
  			mask_irq(desc);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
451
452
453
454
455
456
457
458
  			goto out_unlock;
  		}
  
  		/*
  		 * When another irq arrived while we were handling
  		 * one, we could have masked the irq.
  		 * Renable it, if it was not disabled in meantime.
  		 */
2a0d6fb33   Thomas Gleixner   genirq: Move IRQ_...
459
  		if (unlikely(desc->istate & IRQS_PENDING)) {
32f4125eb   Thomas Gleixner   genirq: Move INPR...
460
461
  			if (!irqd_irq_disabled(&desc->irq_data) &&
  			    irqd_irq_masked(&desc->irq_data))
c1594b77e   Thomas Gleixner   genirq: Move IRQ_...
462
  				unmask_irq(desc);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
463
  		}
a60a5dc2d   Thomas Gleixner   genirq: Use handl...
464
  		handle_irq_event(desc);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
465

2a0d6fb33   Thomas Gleixner   genirq: Move IRQ_...
466
  	} while ((desc->istate & IRQS_PENDING) &&
32f4125eb   Thomas Gleixner   genirq: Move INPR...
467
  		 !irqd_irq_disabled(&desc->irq_data));
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
468

dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
469
  out_unlock:
239007b84   Thomas Gleixner   genirq: Convert i...
470
  	raw_spin_unlock(&desc->lock);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
471
  }
0521c8fbb   Thomas Gleixner   genirq: Provide e...
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
  #ifdef CONFIG_IRQ_EDGE_EOI_HANDLER
  /**
   *	handle_edge_eoi_irq - edge eoi type IRQ handler
   *	@irq:	the interrupt number
   *	@desc:	the interrupt description structure for this irq
   *
   * Similar as the above handle_edge_irq, but using eoi and w/o the
   * mask/unmask logic.
   */
  void handle_edge_eoi_irq(unsigned int irq, struct irq_desc *desc)
  {
  	struct irq_chip *chip = irq_desc_get_chip(desc);
  
  	raw_spin_lock(&desc->lock);
  
  	desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
  	/*
  	 * If we're currently running this IRQ, or its disabled,
  	 * we shouldn't process the IRQ. Mark it pending, handle
  	 * the necessary masking and go out
  	 */
  	if (unlikely(irqd_irq_disabled(&desc->irq_data) ||
  		     irqd_irq_inprogress(&desc->irq_data) || !desc->action)) {
  		if (!irq_check_poll(desc)) {
  			desc->istate |= IRQS_PENDING;
  			goto out_eoi;
  		}
  	}
  	kstat_incr_irqs_this_cpu(irq, desc);
  
  	do {
  		if (unlikely(!desc->action))
  			goto out_eoi;
  
  		handle_irq_event(desc);
  
  	} while ((desc->istate & IRQS_PENDING) &&
  		 !irqd_irq_disabled(&desc->irq_data));
ac0e0447b   Stephen Rothwell   genirq: fix CONFI...
510
  out_eoi:
0521c8fbb   Thomas Gleixner   genirq: Provide e...
511
512
513
514
  	chip->irq_eoi(&desc->irq_data);
  	raw_spin_unlock(&desc->lock);
  }
  #endif
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
515
  /**
24b26d421   Liuweni   irq: Fix docbook ...
516
   *	handle_percpu_irq - Per CPU local irq handler
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
517
518
   *	@irq:	the interrupt number
   *	@desc:	the interrupt description structure for this irq
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
519
520
521
   *
   *	Per CPU interrupts on SMP machines without locking requirements
   */
7ad5b3a50   Harvey Harrison   kernel: remove fa...
522
  void
7d12e780e   David Howells   IRQ: Maintain reg...
523
  handle_percpu_irq(unsigned int irq, struct irq_desc *desc)
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
524
  {
35e857cbe   Thomas Gleixner   genirq: Fixup cor...
525
  	struct irq_chip *chip = irq_desc_get_chip(desc);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
526

d6c88a507   Thomas Gleixner   genirq: revert dy...
527
  	kstat_incr_irqs_this_cpu(irq, desc);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
528

849f061c2   Thomas Gleixner   genirq: Use handl...
529
530
  	if (chip->irq_ack)
  		chip->irq_ack(&desc->irq_data);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
531

849f061c2   Thomas Gleixner   genirq: Use handl...
532
  	handle_irq_event_percpu(desc, desc->action);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
533

849f061c2   Thomas Gleixner   genirq: Use handl...
534
535
  	if (chip->irq_eoi)
  		chip->irq_eoi(&desc->irq_data);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
536
  }
31d9d9b6d   Marc Zyngier   genirq: Add suppo...
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
  /**
   * handle_percpu_devid_irq - Per CPU local irq handler with per cpu dev ids
   * @irq:	the interrupt number
   * @desc:	the interrupt description structure for this irq
   *
   * Per CPU interrupts on SMP machines without locking requirements. Same as
   * handle_percpu_irq() above but with the following extras:
   *
   * action->percpu_dev_id is a pointer to percpu variables which
   * contain the real device id for the cpu on which this handler is
   * called
   */
  void handle_percpu_devid_irq(unsigned int irq, struct irq_desc *desc)
  {
  	struct irq_chip *chip = irq_desc_get_chip(desc);
  	struct irqaction *action = desc->action;
  	void *dev_id = __this_cpu_ptr(action->percpu_dev_id);
  	irqreturn_t res;
  
  	kstat_incr_irqs_this_cpu(irq, desc);
  
  	if (chip->irq_ack)
  		chip->irq_ack(&desc->irq_data);
  
  	trace_irq_handler_entry(irq, action);
  	res = action->handler(irq, dev_id);
  	trace_irq_handler_exit(irq, action, res);
  
  	if (chip->irq_eoi)
  		chip->irq_eoi(&desc->irq_data);
  }
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
568
  void
3836ca08a   Thomas Gleixner   genirq: Consolida...
569
  __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
a460e745e   Ingo Molnar   [PATCH] genirq: c...
570
  		  const char *name)
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
571
  {
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
572
  	unsigned long flags;
31d9d9b6d   Marc Zyngier   genirq: Add suppo...
573
  	struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, 0);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
574

02725e747   Thomas Gleixner   genirq: Use irq_g...
575
  	if (!desc)
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
576
  		return;
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
577

091738a26   Thomas Gleixner   genirq: Remove re...
578
  	if (!handle) {
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
579
  		handle = handle_bad_irq;
091738a26   Thomas Gleixner   genirq: Remove re...
580
581
  	} else {
  		if (WARN_ON(desc->irq_data.chip == &no_irq_chip))
02725e747   Thomas Gleixner   genirq: Use irq_g...
582
  			goto out;
f8b5473fc   Thomas Gleixner   [ARM] 3690/1: gen...
583
  	}
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
584

dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
585
586
  	/* Uninstall? */
  	if (handle == handle_bad_irq) {
6b8ff3120   Thomas Gleixner   genirq: Convert c...
587
  		if (desc->irq_data.chip != &no_irq_chip)
9205e31d1   Thomas Gleixner   genirq: Provide c...
588
  			mask_ack_irq(desc);
801a0e9ae   Thomas Gleixner   genirq: Add irq d...
589
  		irq_state_set_disabled(desc);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
590
591
592
  		desc->depth = 1;
  	}
  	desc->handle_irq = handle;
a460e745e   Ingo Molnar   [PATCH] genirq: c...
593
  	desc->name = name;
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
594
595
  
  	if (handle != handle_bad_irq && is_chained) {
1ccb4e612   Thomas Gleixner   genirq: Wrap the ...
596
597
  		irq_settings_set_noprobe(desc);
  		irq_settings_set_norequest(desc);
7f1b1244e   Paul Mundt   genirq: Support p...
598
  		irq_settings_set_nothread(desc);
469992386   Thomas Gleixner   genirq: Consolida...
599
  		irq_startup(desc);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
600
  	}
02725e747   Thomas Gleixner   genirq: Use irq_g...
601
602
  out:
  	irq_put_desc_busunlock(desc, flags);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
603
  }
3836ca08a   Thomas Gleixner   genirq: Consolida...
604
  EXPORT_SYMBOL_GPL(__irq_set_handler);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
605
606
  
  void
3836ca08a   Thomas Gleixner   genirq: Consolida...
607
  irq_set_chip_and_handler_name(unsigned int irq, struct irq_chip *chip,
a460e745e   Ingo Molnar   [PATCH] genirq: c...
608
  			      irq_flow_handler_t handle, const char *name)
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
609
  {
35e857cbe   Thomas Gleixner   genirq: Fixup cor...
610
  	irq_set_chip(irq, chip);
3836ca08a   Thomas Gleixner   genirq: Consolida...
611
  	__irq_set_handler(irq, handle, 0, name);
dd87eb3a2   Thomas Gleixner   [PATCH] genirq: a...
612
  }
46f4f8f66   Ralf Baechle   IRQ_NOPROBE helpe...
613

442471848   Thomas Gleixner   genirq: Provide s...
614
  void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set)
46f4f8f66   Ralf Baechle   IRQ_NOPROBE helpe...
615
  {
46f4f8f66   Ralf Baechle   IRQ_NOPROBE helpe...
616
  	unsigned long flags;
31d9d9b6d   Marc Zyngier   genirq: Add suppo...
617
  	struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0);
46f4f8f66   Ralf Baechle   IRQ_NOPROBE helpe...
618

442471848   Thomas Gleixner   genirq: Provide s...
619
  	if (!desc)
46f4f8f66   Ralf Baechle   IRQ_NOPROBE helpe...
620
  		return;
a005677b3   Thomas Gleixner   genirq: Mirror IR...
621
  	irq_settings_clr_and_set(desc, clr, set);
876dbd4cc   Thomas Gleixner   genirq: Mirror ir...
622
  	irqd_clear(&desc->irq_data, IRQD_NO_BALANCING | IRQD_PER_CPU |
e1ef82414   Thomas Gleixner   genirq: Reflect I...
623
  		   IRQD_TRIGGER_MASK | IRQD_LEVEL | IRQD_MOVE_PCNTXT);
a005677b3   Thomas Gleixner   genirq: Mirror IR...
624
625
626
627
  	if (irq_settings_has_no_balance_set(desc))
  		irqd_set(&desc->irq_data, IRQD_NO_BALANCING);
  	if (irq_settings_is_per_cpu(desc))
  		irqd_set(&desc->irq_data, IRQD_PER_CPU);
e1ef82414   Thomas Gleixner   genirq: Reflect I...
628
629
  	if (irq_settings_can_move_pcntxt(desc))
  		irqd_set(&desc->irq_data, IRQD_MOVE_PCNTXT);
0ef5ca1e1   Thomas Gleixner   genirq; Fix clean...
630
631
  	if (irq_settings_is_level(desc))
  		irqd_set(&desc->irq_data, IRQD_LEVEL);
a005677b3   Thomas Gleixner   genirq: Mirror IR...
632

876dbd4cc   Thomas Gleixner   genirq: Mirror ir...
633
  	irqd_set(&desc->irq_data, irq_settings_get_trigger_mask(desc));
02725e747   Thomas Gleixner   genirq: Use irq_g...
634
  	irq_put_desc_unlock(desc, flags);
46f4f8f66   Ralf Baechle   IRQ_NOPROBE helpe...
635
  }
edf76f830   Jonathan Cameron   irq: Export funct...
636
  EXPORT_SYMBOL_GPL(irq_modify_status);
0fdb4b259   David Daney   genirq: Add chip ...
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
  
  /**
   *	irq_cpu_online - Invoke all irq_cpu_online functions.
   *
   *	Iterate through all irqs and invoke the chip.irq_cpu_online()
   *	for each.
   */
  void irq_cpu_online(void)
  {
  	struct irq_desc *desc;
  	struct irq_chip *chip;
  	unsigned long flags;
  	unsigned int irq;
  
  	for_each_active_irq(irq) {
  		desc = irq_to_desc(irq);
  		if (!desc)
  			continue;
  
  		raw_spin_lock_irqsave(&desc->lock, flags);
  
  		chip = irq_data_get_irq_chip(&desc->irq_data);
b3d422329   Thomas Gleixner   genirq: Add chip ...
659
660
  		if (chip && chip->irq_cpu_online &&
  		    (!(chip->flags & IRQCHIP_ONOFFLINE_ENABLED) ||
32f4125eb   Thomas Gleixner   genirq: Move INPR...
661
  		     !irqd_irq_disabled(&desc->irq_data)))
0fdb4b259   David Daney   genirq: Add chip ...
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
  			chip->irq_cpu_online(&desc->irq_data);
  
  		raw_spin_unlock_irqrestore(&desc->lock, flags);
  	}
  }
  
  /**
   *	irq_cpu_offline - Invoke all irq_cpu_offline functions.
   *
   *	Iterate through all irqs and invoke the chip.irq_cpu_offline()
   *	for each.
   */
  void irq_cpu_offline(void)
  {
  	struct irq_desc *desc;
  	struct irq_chip *chip;
  	unsigned long flags;
  	unsigned int irq;
  
  	for_each_active_irq(irq) {
  		desc = irq_to_desc(irq);
  		if (!desc)
  			continue;
  
  		raw_spin_lock_irqsave(&desc->lock, flags);
  
  		chip = irq_data_get_irq_chip(&desc->irq_data);
b3d422329   Thomas Gleixner   genirq: Add chip ...
689
690
  		if (chip && chip->irq_cpu_offline &&
  		    (!(chip->flags & IRQCHIP_ONOFFLINE_ENABLED) ||
32f4125eb   Thomas Gleixner   genirq: Move INPR...
691
  		     !irqd_irq_disabled(&desc->irq_data)))
0fdb4b259   David Daney   genirq: Add chip ...
692
693
694
695
696
  			chip->irq_cpu_offline(&desc->irq_data);
  
  		raw_spin_unlock_irqrestore(&desc->lock, flags);
  	}
  }